/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include #include #include #include #include "cras_metrics.h" #include "cras_main_message.h" #include "cras_rstream.h" const char kHighestInputHardwareLevel[] = "Cras.HighestInputHardwareLevel"; const char kHighestOutputHardwareLevel[] = "Cras.HighestOutputHardwareLevel"; const char kNoCodecsFoundMetric[] = "Cras.NoCodecsFoundAtBoot"; const char kStreamTimeoutMilliSeconds[] = "Cras.StreamTimeoutMilliSeconds"; const char kStreamCallbackThreshold[] = "Cras.StreamCallbackThreshold"; const char kStreamFlags[] = "Cras.StreamFlags"; const char kStreamSamplingFormat[] = "Cras.StreamSamplingFormat"; const char kStreamSamplingRate[] = "Cras.StreamSamplingRate"; const char kUnderrunsPerDevice[] = "Cras.UnderrunsPerDevice"; /* Type of metrics to log. */ enum CRAS_SERVER_METRICS_TYPE { HIGHEST_INPUT_HW_LEVEL, HIGHEST_OUTPUT_HW_LEVEL, LONGEST_FETCH_DELAY, NUM_UNDERRUNS, STREAM_CONFIG }; struct cras_server_metrics_stream_config { unsigned cb_threshold; unsigned flags; int format; unsigned rate; }; union cras_server_metrics_data { unsigned value; struct cras_server_metrics_stream_config stream_config; }; struct cras_server_metrics_message { struct cras_main_message header; enum CRAS_SERVER_METRICS_TYPE metrics_type; union cras_server_metrics_data data; }; static void init_server_metrics_msg( struct cras_server_metrics_message *msg, enum CRAS_SERVER_METRICS_TYPE type, union cras_server_metrics_data data) { memset(msg, 0, sizeof(*msg)); msg->header.type = CRAS_MAIN_METRICS; msg->header.length = sizeof(*msg); msg->metrics_type = type; msg->data = data; } int cras_server_metrics_highest_hw_level(unsigned hw_level, enum CRAS_STREAM_DIRECTION direction) { struct cras_server_metrics_message msg; union cras_server_metrics_data data; int err; data.value = hw_level; switch (direction) { case CRAS_STREAM_INPUT: init_server_metrics_msg(&msg, HIGHEST_INPUT_HW_LEVEL, data); break; case CRAS_STREAM_OUTPUT: init_server_metrics_msg(&msg, HIGHEST_OUTPUT_HW_LEVEL, data); break; default: return 0; } err = cras_main_message_send((struct cras_main_message *)&msg); if (err < 0) { syslog(LOG_ERR, "Failed to send metrics message: HIGHEST_HW_LEVEL"); return err; } return 0; } int cras_server_metrics_longest_fetch_delay(unsigned delay_msec) { struct cras_server_metrics_message msg; union cras_server_metrics_data data; int err; data.value = delay_msec; init_server_metrics_msg(&msg, LONGEST_FETCH_DELAY, data); err = cras_main_message_send((struct cras_main_message *)&msg); if (err < 0) { syslog(LOG_ERR, "Failed to send metrics message: LONGEST_FETCH_DELAY"); return err; } return 0; } int cras_server_metrics_num_underruns(unsigned num_underruns) { struct cras_server_metrics_message msg; union cras_server_metrics_data data; int err; data.value = num_underruns; init_server_metrics_msg(&msg, NUM_UNDERRUNS, data); err = cras_main_message_send((struct cras_main_message *)&msg); if (err < 0) { syslog(LOG_ERR, "Failed to send metrics message: NUM_UNDERRUNS"); return err; } return 0; } int cras_server_metrics_stream_config(struct cras_rstream_config *config) { struct cras_server_metrics_message msg; union cras_server_metrics_data data; int err; data.stream_config.cb_threshold = (unsigned)config->cb_threshold; data.stream_config.flags = (unsigned)config->flags; data.stream_config.format = (int)config->format->format; data.stream_config.rate = (unsigned)config->format->frame_rate; init_server_metrics_msg(&msg, STREAM_CONFIG, data); err = cras_main_message_send((struct cras_main_message *)&msg); if (err < 0) { syslog(LOG_ERR, "Failed to send metrics message: STREAM_CONFIG"); return err; } return 0; } static void metrics_stream_config( struct cras_server_metrics_stream_config config) { /* Logs stream callback threshold. */ cras_metrics_log_sparse_histogram(kStreamCallbackThreshold, config.cb_threshold); /* Logs stream flags. */ cras_metrics_log_sparse_histogram(kStreamFlags, config.flags); /* Logs stream sampling format. */ cras_metrics_log_sparse_histogram(kStreamSamplingFormat, config.format); /* Logs stream sampling rate. */ cras_metrics_log_sparse_histogram(kStreamSamplingRate, config.rate); } static void handle_metrics_message(struct cras_main_message *msg, void *arg) { struct cras_server_metrics_message *metrics_msg = (struct cras_server_metrics_message *)msg; switch (metrics_msg->metrics_type) { case HIGHEST_INPUT_HW_LEVEL: cras_metrics_log_histogram(kHighestInputHardwareLevel, metrics_msg->data.value, 1, 10000, 20); break; case HIGHEST_OUTPUT_HW_LEVEL: cras_metrics_log_histogram(kHighestOutputHardwareLevel, metrics_msg->data.value, 1, 10000, 20); break; case LONGEST_FETCH_DELAY: cras_metrics_log_histogram(kStreamTimeoutMilliSeconds, metrics_msg->data.value, 1, 20000, 10); break; case NUM_UNDERRUNS: cras_metrics_log_histogram(kUnderrunsPerDevice, metrics_msg->data.value, 0, 1000, 10); break; case STREAM_CONFIG: metrics_stream_config(metrics_msg->data.stream_config); break; default: syslog(LOG_ERR, "Unknown metrics type %u", metrics_msg->metrics_type); break; } } int cras_server_metrics_init() { cras_main_message_add_handler(CRAS_MAIN_METRICS, handle_metrics_message, NULL); return 0; }