summaryrefslogtreecommitdiff
path: root/cras/src/server/cras_server_metrics.c
diff options
context:
space:
mode:
Diffstat (limited to 'cras/src/server/cras_server_metrics.c')
-rw-r--r--cras/src/server/cras_server_metrics.c1326
1 files changed, 0 insertions, 1326 deletions
diff --git a/cras/src/server/cras_server_metrics.c b/cras/src/server/cras_server_metrics.c
deleted file mode 100644
index 7e487107..00000000
--- a/cras/src/server/cras_server_metrics.c
+++ /dev/null
@@ -1,1326 +0,0 @@
-/* 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 <errno.h>
-#include <math.h>
-#include <stdio.h>
-#include <string.h>
-#include <syslog.h>
-
-#ifdef CRAS_DBUS
-#include "cras_bt_io.h"
-#endif
-#include "cras_iodev.h"
-#include "cras_metrics.h"
-#include "cras_main_message.h"
-#include "cras_rstream.h"
-#include "cras_server_metrics.h"
-#include "cras_system_state.h"
-
-#define METRICS_NAME_BUFFER_SIZE 100
-
-const char kBusyloop[] = "Cras.Busyloop";
-const char kBusyloopLength[] = "Cras.BusyloopLength";
-const char kDeviceTypeInput[] = "Cras.DeviceTypeInput";
-const char kDeviceTypeOutput[] = "Cras.DeviceTypeOutput";
-const char kDeviceGain[] = "Cras.DeviceGain";
-const char kDeviceVolume[] = "Cras.DeviceVolume";
-const char kFetchDelayMilliSeconds[] = "Cras.FetchDelayMilliSeconds";
-const char kHighestDeviceDelayInput[] = "Cras.HighestDeviceDelayInput";
-const char kHighestDeviceDelayOutput[] = "Cras.HighestDeviceDelayOutput";
-const char kHighestInputHardwareLevel[] = "Cras.HighestInputHardwareLevel";
-const char kHighestOutputHardwareLevel[] = "Cras.HighestOutputHardwareLevel";
-const char kMissedCallbackFirstTimeInput[] =
- "Cras.MissedCallbackFirstTimeInput";
-const char kMissedCallbackFirstTimeOutput[] =
- "Cras.MissedCallbackFirstTimeOutput";
-const char kMissedCallbackFrequencyInput[] =
- "Cras.MissedCallbackFrequencyInput";
-const char kMissedCallbackFrequencyOutput[] =
- "Cras.MissedCallbackFrequencyOutput";
-const char kMissedCallbackFrequencyAfterReschedulingInput[] =
- "Cras.MissedCallbackFrequencyAfterReschedulingInput";
-const char kMissedCallbackFrequencyAfterReschedulingOutput[] =
- "Cras.MissedCallbackFrequencyAfterReschedulingOutput";
-const char kMissedCallbackSecondTimeInput[] =
- "Cras.MissedCallbackSecondTimeInput";
-const char kMissedCallbackSecondTimeOutput[] =
- "Cras.MissedCallbackSecondTimeOutput";
-const char kNoCodecsFoundMetric[] = "Cras.NoCodecsFoundAtBoot";
-const char kStreamCallbackThreshold[] = "Cras.StreamCallbackThreshold";
-const char kStreamClientTypeInput[] = "Cras.StreamClientTypeInput";
-const char kStreamClientTypeOutput[] = "Cras.StreamClientTypeOutput";
-const char kStreamFlags[] = "Cras.StreamFlags";
-const char kStreamEffects[] = "Cras.StreamEffects";
-const char kStreamRuntime[] = "Cras.StreamRuntime";
-const char kStreamSamplingFormat[] = "Cras.StreamSamplingFormat";
-const char kStreamSamplingRate[] = "Cras.StreamSamplingRate";
-const char kUnderrunsPerDevice[] = "Cras.UnderrunsPerDevice";
-const char kHfpScoConnectionError[] = "Cras.HfpScoConnectionError";
-const char kHfpBatteryIndicatorSupported[] =
- "Cras.HfpBatteryIndicatorSupported";
-const char kHfpBatteryReport[] = "Cras.HfpBatteryReport";
-const char kHfpWidebandSpeechSupported[] = "Cras.HfpWidebandSpeechSupported";
-const char kHfpWidebandSpeechPacketLoss[] = "Cras.HfpWidebandSpeechPacketLoss";
-const char kHfpWidebandSpeechSelectedCodec[] =
- "Cras.kHfpWidebandSpeechSelectedCodec";
-
-/*
- * Records missed callback frequency only when the runtime of stream is larger
- * than the threshold.
- */
-const double MISSED_CB_FREQUENCY_SECONDS_MIN = 10.0;
-
-const time_t CRAS_METRICS_SHORT_PERIOD_THRESHOLD_SECONDS = 600;
-const time_t CRAS_METRICS_LONG_PERIOD_THRESHOLD_SECONDS = 3600;
-
-static const char *get_timespec_period_str(struct timespec ts)
-{
- if (ts.tv_sec < CRAS_METRICS_SHORT_PERIOD_THRESHOLD_SECONDS)
- return "ShortPeriod";
- if (ts.tv_sec < CRAS_METRICS_LONG_PERIOD_THRESHOLD_SECONDS)
- return "MediumPeriod";
- return "LongPeriod";
-}
-
-/* Type of metrics to log. */
-enum CRAS_SERVER_METRICS_TYPE {
- BT_BATTERY_INDICATOR_SUPPORTED,
- BT_BATTERY_REPORT,
- BT_SCO_CONNECTION_ERROR,
- BT_WIDEBAND_PACKET_LOSS,
- BT_WIDEBAND_SUPPORTED,
- BT_WIDEBAND_SELECTED_CODEC,
- BUSYLOOP,
- BUSYLOOP_LENGTH,
- DEVICE_GAIN,
- DEVICE_RUNTIME,
- DEVICE_VOLUME,
- HIGHEST_DEVICE_DELAY_INPUT,
- HIGHEST_DEVICE_DELAY_OUTPUT,
- HIGHEST_INPUT_HW_LEVEL,
- HIGHEST_OUTPUT_HW_LEVEL,
- LONGEST_FETCH_DELAY,
- MISSED_CB_FIRST_TIME_INPUT,
- MISSED_CB_FIRST_TIME_OUTPUT,
- MISSED_CB_FREQUENCY_INPUT,
- MISSED_CB_FREQUENCY_OUTPUT,
- MISSED_CB_FREQUENCY_AFTER_RESCHEDULING_INPUT,
- MISSED_CB_FREQUENCY_AFTER_RESCHEDULING_OUTPUT,
- MISSED_CB_SECOND_TIME_INPUT,
- MISSED_CB_SECOND_TIME_OUTPUT,
- NUM_UNDERRUNS,
- STREAM_CONFIG,
- STREAM_RUNTIME
-};
-
-enum CRAS_METRICS_DEVICE_TYPE {
- /* Output devices. */
- CRAS_METRICS_DEVICE_INTERNAL_SPEAKER,
- CRAS_METRICS_DEVICE_HEADPHONE,
- CRAS_METRICS_DEVICE_HDMI,
- CRAS_METRICS_DEVICE_HAPTIC,
- CRAS_METRICS_DEVICE_LINEOUT,
- /* Input devices. */
- CRAS_METRICS_DEVICE_INTERNAL_MIC,
- CRAS_METRICS_DEVICE_FRONT_MIC,
- CRAS_METRICS_DEVICE_REAR_MIC,
- CRAS_METRICS_DEVICE_KEYBOARD_MIC,
- CRAS_METRICS_DEVICE_MIC,
- CRAS_METRICS_DEVICE_HOTWORD,
- CRAS_METRICS_DEVICE_POST_MIX_LOOPBACK,
- CRAS_METRICS_DEVICE_POST_DSP_LOOPBACK,
- /* Devices supporting input and output function. */
- CRAS_METRICS_DEVICE_USB,
- CRAS_METRICS_DEVICE_A2DP,
- CRAS_METRICS_DEVICE_HFP,
- CRAS_METRICS_DEVICE_HSP,
- CRAS_METRICS_DEVICE_BLUETOOTH,
- CRAS_METRICS_DEVICE_BLUETOOTH_NB_MIC,
- CRAS_METRICS_DEVICE_NO_DEVICE,
- CRAS_METRICS_DEVICE_NORMAL_FALLBACK,
- CRAS_METRICS_DEVICE_ABNORMAL_FALLBACK,
- CRAS_METRICS_DEVICE_SILENT_HOTWORD,
- CRAS_METRICS_DEVICE_UNKNOWN,
- CRAS_METRICS_DEVICE_BLUETOOTH_WB_MIC,
- CRAS_METRICS_DEVICE_ALSA_LOOPBACK,
-};
-
-struct cras_server_metrics_stream_config {
- enum CRAS_STREAM_DIRECTION direction;
- unsigned cb_threshold;
- unsigned flags;
- unsigned effects;
- int format;
- unsigned rate;
- enum CRAS_CLIENT_TYPE client_type;
-};
-
-struct cras_server_metrics_device_data {
- enum CRAS_METRICS_DEVICE_TYPE type;
- enum CRAS_STREAM_DIRECTION direction;
- struct timespec runtime;
- unsigned value;
-};
-
-struct cras_server_metrics_stream_data {
- enum CRAS_CLIENT_TYPE client_type;
- enum CRAS_STREAM_TYPE stream_type;
- enum CRAS_STREAM_DIRECTION direction;
- struct timespec runtime;
-};
-
-struct cras_server_metrics_timespec_data {
- struct timespec runtime;
- unsigned count;
-};
-
-union cras_server_metrics_data {
- unsigned value;
- struct cras_server_metrics_stream_config stream_config;
- struct cras_server_metrics_device_data device_data;
- struct cras_server_metrics_stream_data stream_data;
- struct cras_server_metrics_timespec_data timespec_data;
-};
-
-/*
- * Make sure the size of message in the acceptable range. Otherwise, it may
- * be split into mutiple packets while sending.
- */
-static_assert(sizeof(union cras_server_metrics_data) <= 256,
- "The size is too large.");
-
-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;
-}
-
-static void handle_metrics_message(struct cras_main_message *msg, void *arg);
-
-/* The wrapper function of cras_main_message_send. */
-static int cras_server_metrics_message_send(struct cras_main_message *msg)
-{
- /* If current function is in the main thread, call handler directly. */
- if (cras_system_state_in_main_thread()) {
- handle_metrics_message(msg, NULL);
- return 0;
- }
- return cras_main_message_send(msg);
-}
-
-static inline const char *
-metrics_device_type_str(enum CRAS_METRICS_DEVICE_TYPE device_type)
-{
- switch (device_type) {
- case CRAS_METRICS_DEVICE_INTERNAL_SPEAKER:
- return "InternalSpeaker";
- case CRAS_METRICS_DEVICE_HEADPHONE:
- return "Headphone";
- case CRAS_METRICS_DEVICE_HDMI:
- return "HDMI";
- case CRAS_METRICS_DEVICE_HAPTIC:
- return "Haptic";
- case CRAS_METRICS_DEVICE_LINEOUT:
- return "Lineout";
- /* Input devices. */
- case CRAS_METRICS_DEVICE_INTERNAL_MIC:
- return "InternalMic";
- case CRAS_METRICS_DEVICE_FRONT_MIC:
- return "FrontMic";
- case CRAS_METRICS_DEVICE_REAR_MIC:
- return "RearMic";
- case CRAS_METRICS_DEVICE_KEYBOARD_MIC:
- return "KeyboardMic";
- case CRAS_METRICS_DEVICE_MIC:
- return "Mic";
- case CRAS_METRICS_DEVICE_HOTWORD:
- return "Hotword";
- case CRAS_METRICS_DEVICE_POST_MIX_LOOPBACK:
- return "PostMixLoopback";
- case CRAS_METRICS_DEVICE_POST_DSP_LOOPBACK:
- return "PostDspLoopback";
- /* Devices supporting input and output function. */
- case CRAS_METRICS_DEVICE_USB:
- return "USB";
- case CRAS_METRICS_DEVICE_A2DP:
- return "A2DP";
- case CRAS_METRICS_DEVICE_HFP:
- return "HFP";
- case CRAS_METRICS_DEVICE_HSP:
- return "HSP";
- case CRAS_METRICS_DEVICE_BLUETOOTH:
- return "Bluetooth";
- case CRAS_METRICS_DEVICE_BLUETOOTH_NB_MIC:
- return "BluetoothNarrowBandMic";
- case CRAS_METRICS_DEVICE_BLUETOOTH_WB_MIC:
- return "BluetoothWideBandMic";
- case CRAS_METRICS_DEVICE_NO_DEVICE:
- return "NoDevice";
- case CRAS_METRICS_DEVICE_ALSA_LOOPBACK:
- return "AlsaLoopback";
- /* Other fallback devices. */
- case CRAS_METRICS_DEVICE_NORMAL_FALLBACK:
- return "NormalFallback";
- case CRAS_METRICS_DEVICE_ABNORMAL_FALLBACK:
- return "AbnormalFallback";
- case CRAS_METRICS_DEVICE_SILENT_HOTWORD:
- return "SilentHotword";
- case CRAS_METRICS_DEVICE_UNKNOWN:
- return "Unknown";
- default:
- return "InvalidType";
- }
-}
-
-static inline const char *
-metrics_client_type_str(enum CRAS_CLIENT_TYPE client_type)
-{
- switch (client_type) {
- case CRAS_CLIENT_TYPE_UNKNOWN:
- return "Unknown";
- case CRAS_CLIENT_TYPE_LEGACY:
- return "Legacy";
- case CRAS_CLIENT_TYPE_TEST:
- return "Test";
- case CRAS_CLIENT_TYPE_PCM:
- return "PCM";
- case CRAS_CLIENT_TYPE_CHROME:
- return "Chrome";
- case CRAS_CLIENT_TYPE_ARC:
- return "ARC";
- case CRAS_CLIENT_TYPE_CROSVM:
- return "CrOSVM";
- case CRAS_CLIENT_TYPE_SERVER_STREAM:
- return "ServerStream";
- case CRAS_CLIENT_TYPE_LACROS:
- return "LaCrOS";
- case CRAS_CLIENT_TYPE_PLUGIN:
- return "PluginVM";
- case CRAS_CLIENT_TYPE_ARCVM:
- return "ARCVM";
- default:
- return "InvalidType";
- }
-}
-
-static inline const char *
-metrics_stream_type_str(enum CRAS_STREAM_TYPE stream_type)
-{
- switch (stream_type) {
- case CRAS_STREAM_TYPE_DEFAULT:
- return "Default";
- case CRAS_STREAM_TYPE_MULTIMEDIA:
- return "Multimedia";
- case CRAS_STREAM_TYPE_VOICE_COMMUNICATION:
- return "VoiceCommunication";
- case CRAS_STREAM_TYPE_SPEECH_RECOGNITION:
- return "SpeechRecognition";
- case CRAS_STREAM_TYPE_PRO_AUDIO:
- return "ProAudio";
- case CRAS_STREAM_TYPE_ACCESSIBILITY:
- return "Accessibility";
- default:
- return "InvalidType";
- }
-}
-
-static enum CRAS_METRICS_DEVICE_TYPE
-get_metrics_device_type(struct cras_iodev *iodev)
-{
- /* Check whether it is a special device. */
- if (iodev->info.idx < MAX_SPECIAL_DEVICE_IDX) {
- switch (iodev->info.idx) {
- case NO_DEVICE:
- syslog(LOG_ERR, "The invalid device has been used.");
- return CRAS_METRICS_DEVICE_NO_DEVICE;
- case SILENT_RECORD_DEVICE:
- case SILENT_PLAYBACK_DEVICE:
- if (iodev->active_node->type ==
- CRAS_NODE_TYPE_FALLBACK_NORMAL)
- return CRAS_METRICS_DEVICE_NORMAL_FALLBACK;
- else
- return CRAS_METRICS_DEVICE_ABNORMAL_FALLBACK;
- case SILENT_HOTWORD_DEVICE:
- return CRAS_METRICS_DEVICE_SILENT_HOTWORD;
- }
- }
-
- switch (iodev->active_node->type) {
- case CRAS_NODE_TYPE_INTERNAL_SPEAKER:
- return CRAS_METRICS_DEVICE_INTERNAL_SPEAKER;
- case CRAS_NODE_TYPE_HEADPHONE:
- return CRAS_METRICS_DEVICE_HEADPHONE;
- case CRAS_NODE_TYPE_HDMI:
- return CRAS_METRICS_DEVICE_HDMI;
- case CRAS_NODE_TYPE_HAPTIC:
- return CRAS_METRICS_DEVICE_HAPTIC;
- case CRAS_NODE_TYPE_LINEOUT:
- return CRAS_METRICS_DEVICE_LINEOUT;
- case CRAS_NODE_TYPE_MIC:
- switch (iodev->active_node->position) {
- case NODE_POSITION_INTERNAL:
- return CRAS_METRICS_DEVICE_INTERNAL_MIC;
- case NODE_POSITION_FRONT:
- return CRAS_METRICS_DEVICE_FRONT_MIC;
- case NODE_POSITION_REAR:
- return CRAS_METRICS_DEVICE_REAR_MIC;
- case NODE_POSITION_KEYBOARD:
- return CRAS_METRICS_DEVICE_KEYBOARD_MIC;
- case NODE_POSITION_EXTERNAL:
- default:
- return CRAS_METRICS_DEVICE_MIC;
- }
- case CRAS_NODE_TYPE_HOTWORD:
- return CRAS_METRICS_DEVICE_HOTWORD;
- case CRAS_NODE_TYPE_POST_MIX_PRE_DSP:
- return CRAS_METRICS_DEVICE_POST_MIX_LOOPBACK;
- case CRAS_NODE_TYPE_POST_DSP:
- return CRAS_METRICS_DEVICE_POST_DSP_LOOPBACK;
- case CRAS_NODE_TYPE_USB:
- return CRAS_METRICS_DEVICE_USB;
- case CRAS_NODE_TYPE_BLUETOOTH: {
-#ifdef CRAS_DBUS
- enum cras_bt_device_profile profile =
- cras_bt_io_profile_to_log(iodev);
- switch (profile) {
- case CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE:
- return CRAS_METRICS_DEVICE_A2DP;
- case CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY:
- /* HFP narrow band has its own node type so we know
- * this is wideband mic for sure. */
- return (iodev->direction == CRAS_STREAM_INPUT) ?
- CRAS_METRICS_DEVICE_BLUETOOTH_WB_MIC :
- CRAS_METRICS_DEVICE_HFP;
- case CRAS_BT_DEVICE_PROFILE_HSP_AUDIOGATEWAY:
- return CRAS_METRICS_DEVICE_HSP;
- default:
- break;
- }
-#endif
- return CRAS_METRICS_DEVICE_BLUETOOTH;
- }
- case CRAS_NODE_TYPE_BLUETOOTH_NB_MIC:
- return CRAS_METRICS_DEVICE_BLUETOOTH_NB_MIC;
- case CRAS_NODE_TYPE_ALSA_LOOPBACK:
- return CRAS_METRICS_DEVICE_ALSA_LOOPBACK;
- case CRAS_NODE_TYPE_UNKNOWN:
- default:
- return CRAS_METRICS_DEVICE_UNKNOWN;
- }
-}
-
-/*
- * Logs metrics for each group it belongs to. The UMA does not merge subgroups
- * automatically so we need to log them separately.
- *
- * For example, if we call this function with argument (3, 48000,
- * Cras.StreamSamplingRate, Input, Chrome), it will send 48000 to below
- * metrics:
- * Cras.StreamSamplingRate.Input.Chrome
- * Cras.StreamSamplingRate.Input
- * Cras.StreamSamplingRate
- */
-static void log_sparse_histogram_each_level(int num, int sample, ...)
-{
- char metrics_name[METRICS_NAME_BUFFER_SIZE] = {};
- va_list valist;
- int i, len = 0;
-
- va_start(valist, sample);
-
- for (i = 0; i < num && len < METRICS_NAME_BUFFER_SIZE; i++) {
- int metric_len =
- snprintf(metrics_name + len,
- METRICS_NAME_BUFFER_SIZE - len, "%s%s",
- i ? "." : "", va_arg(valist, char *));
- // Exit early on error or running out of bufferspace. Avoids
- // logging partial or corrupted strings.
- if (metric_len < 0 ||
- metric_len > METRICS_NAME_BUFFER_SIZE - len)
- break;
- len += metric_len;
- cras_metrics_log_sparse_histogram(metrics_name, sample);
- }
-
- va_end(valist);
-}
-
-static void log_histogram_each_level(int num, int sample, int min, int max,
- int nbuckets, ...)
-{
- char metrics_name[METRICS_NAME_BUFFER_SIZE] = {};
- va_list valist;
- int i, len = 0;
-
- va_start(valist, nbuckets);
-
- for (i = 0; i < num && len < METRICS_NAME_BUFFER_SIZE; i++) {
- int metric_len =
- snprintf(metrics_name + len,
- METRICS_NAME_BUFFER_SIZE - len, "%s%s",
- i ? "." : "", va_arg(valist, char *));
- // Exit early on error or running out of bufferspace. Avoids
- // logging partial or corrupted strings.
- if (metric_len < 0 ||
- metric_len > METRICS_NAME_BUFFER_SIZE - len)
- break;
- len += metric_len;
- cras_metrics_log_histogram(metrics_name, sample, min, max,
- nbuckets);
- }
-
- va_end(valist);
-}
-
-int cras_server_metrics_hfp_sco_connection_error(
- enum CRAS_METRICS_BT_SCO_ERROR_TYPE type)
-{
- struct cras_server_metrics_message msg;
- union cras_server_metrics_data data;
- int err;
-
- data.value = type;
- init_server_metrics_msg(&msg, BT_SCO_CONNECTION_ERROR, data);
-
- err = cras_server_metrics_message_send(
- (struct cras_main_message *)&msg);
- if (err < 0) {
- syslog(LOG_ERR, "Failed to send metrics message: "
- "BT_SCO_CONNECTION_ERROR");
- return err;
- }
- return 0;
-}
-
-int cras_server_metrics_hfp_battery_indicator(int battery_indicator_support)
-{
- struct cras_server_metrics_message msg;
- union cras_server_metrics_data data;
- int err;
-
- data.value = battery_indicator_support;
- init_server_metrics_msg(&msg, BT_BATTERY_INDICATOR_SUPPORTED, data);
-
- err = cras_server_metrics_message_send(
- (struct cras_main_message *)&msg);
- if (err < 0) {
- syslog(LOG_ERR, "Failed to send metrics message: "
- "BT_BATTERY_INDICATOR_SUPPORTED");
- return err;
- }
- return 0;
-}
-
-int cras_server_metrics_hfp_battery_report(int battery_report)
-{
- struct cras_server_metrics_message msg;
- union cras_server_metrics_data data;
- int err;
-
- data.value = battery_report;
- init_server_metrics_msg(&msg, BT_BATTERY_REPORT, data);
-
- err = cras_server_metrics_message_send(
- (struct cras_main_message *)&msg);
- if (err < 0) {
- syslog(LOG_ERR, "Failed to send metrics message: "
- "BT_BATTERY_REPORT");
- return err;
- }
- return 0;
-}
-
-int cras_server_metrics_hfp_packet_loss(float packet_loss_ratio)
-{
- struct cras_server_metrics_message msg;
- union cras_server_metrics_data data;
- int err;
-
- /* Percentage is too coarse for packet loss, so we use number of bad
- * packets per thousand packets instead. */
- data.value = (unsigned)(round(packet_loss_ratio * 1000));
- init_server_metrics_msg(&msg, BT_WIDEBAND_PACKET_LOSS, data);
-
- err = cras_server_metrics_message_send(
- (struct cras_main_message *)&msg);
- if (err < 0) {
- syslog(LOG_ERR,
- "Failed to send metrics message: BT_WIDEBAND_PACKET_LOSS");
- return err;
- }
- return 0;
-}
-
-int cras_server_metrics_hfp_wideband_support(bool supported)
-{
- struct cras_server_metrics_message msg;
- union cras_server_metrics_data data;
- int err;
-
- data.value = supported;
- init_server_metrics_msg(&msg, BT_WIDEBAND_SUPPORTED, data);
-
- err = cras_server_metrics_message_send(
- (struct cras_main_message *)&msg);
- if (err < 0) {
- syslog(LOG_ERR,
- "Failed to send metrics message: BT_WIDEBAND_SUPPORTED");
- return err;
- }
- return 0;
-}
-
-int cras_server_metrics_hfp_wideband_selected_codec(int codec)
-{
- struct cras_server_metrics_message msg;
- union cras_server_metrics_data data;
- int err;
-
- data.value = codec;
- init_server_metrics_msg(&msg, BT_WIDEBAND_SELECTED_CODEC, data);
-
- err = cras_server_metrics_message_send(
- (struct cras_main_message *)&msg);
- if (err < 0) {
- syslog(LOG_ERR, "Failed to send metrics message: "
- "BT_WIDEBAND_SELECTED_CODEC");
- return err;
- }
- return 0;
-}
-
-int cras_server_metrics_device_runtime(struct cras_iodev *iodev)
-{
- struct cras_server_metrics_message msg;
- union cras_server_metrics_data data;
- struct timespec now;
- int err;
-
- data.device_data.type = get_metrics_device_type(iodev);
- data.device_data.direction = iodev->direction;
- clock_gettime(CLOCK_MONOTONIC_RAW, &now);
- subtract_timespecs(&now, &iodev->open_ts, &data.device_data.runtime);
-
- init_server_metrics_msg(&msg, DEVICE_RUNTIME, data);
-
- err = cras_server_metrics_message_send(
- (struct cras_main_message *)&msg);
- if (err < 0) {
- syslog(LOG_ERR,
- "Failed to send metrics message: DEVICE_RUNTIME");
- return err;
- }
-
- return 0;
-}
-
-int cras_server_metrics_device_gain(struct cras_iodev *iodev)
-{
- struct cras_server_metrics_message msg;
- union cras_server_metrics_data data;
- int err;
-
- if (iodev->direction == CRAS_STREAM_OUTPUT)
- return 0;
-
- data.device_data.type = get_metrics_device_type(iodev);
- data.device_data.value =
- (unsigned)100 * iodev->active_node->ui_gain_scaler;
-
- init_server_metrics_msg(&msg, DEVICE_GAIN, data);
-
- err = cras_server_metrics_message_send(
- (struct cras_main_message *)&msg);
- if (err < 0) {
- syslog(LOG_ERR, "Failed to send metrics message: DEVICE_GAIN");
- return err;
- }
-
- return 0;
-}
-
-int cras_server_metrics_device_volume(struct cras_iodev *iodev)
-{
- struct cras_server_metrics_message msg;
- union cras_server_metrics_data data;
- int err;
-
- if (iodev->direction == CRAS_STREAM_INPUT)
- return 0;
-
- data.device_data.type = get_metrics_device_type(iodev);
- data.device_data.value = iodev->active_node->volume;
-
- init_server_metrics_msg(&msg, DEVICE_VOLUME, data);
-
- err = cras_server_metrics_message_send(
- (struct cras_main_message *)&msg);
- if (err < 0) {
- syslog(LOG_ERR,
- "Failed to send metrics message: DEVICE_VOLUME");
- return err;
- }
-
- return 0;
-}
-
-int cras_server_metrics_highest_device_delay(
- unsigned int hw_level, unsigned int largest_cb_level,
- enum CRAS_STREAM_DIRECTION direction)
-{
- struct cras_server_metrics_message msg;
- union cras_server_metrics_data data;
- int err;
-
- if (largest_cb_level == 0) {
- syslog(LOG_ERR,
- "Failed to record device delay: devided by zero");
- return -1;
- }
-
- /*
- * Because the latency depends on the callback threshold of streams, it
- * should be calculated as dividing the highest hardware level by largest
- * callback threshold of streams. For output device, this value should fall
- * around 2 because CRAS 's scheduling maintain device buffer level around
- * 1~2 minimum callback level. For input device, this value should be around
- * 1 because the device buffer level is around 0~1 minimum callback level.
- * Besides, UMA cannot record float so this ratio is multiplied by 1000.
- */
- data.value = hw_level * 1000 / largest_cb_level;
-
- switch (direction) {
- case CRAS_STREAM_INPUT:
- init_server_metrics_msg(&msg, HIGHEST_DEVICE_DELAY_INPUT, data);
- break;
- case CRAS_STREAM_OUTPUT:
- init_server_metrics_msg(&msg, HIGHEST_DEVICE_DELAY_OUTPUT,
- data);
- break;
- default:
- return 0;
- }
-
- err = cras_server_metrics_message_send(
- (struct cras_main_message *)&msg);
- if (err < 0) {
- syslog(LOG_ERR,
- "Failed to send metrics message: HIGHEST_DEVICE_DELAY");
- return err;
- }
-
- return 0;
-}
-
-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_server_metrics_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;
-}
-
-/* Logs longest fetch delay of a stream. */
-int cras_server_metrics_longest_fetch_delay(const struct cras_rstream *stream)
-{
- struct cras_server_metrics_message msg;
- union cras_server_metrics_data data;
- int err;
-
- data.stream_data.client_type = stream->client_type;
- data.stream_data.stream_type = stream->stream_type;
- data.stream_data.direction = stream->direction;
-
- /*
- * There is no delay when the sleep_interval_ts larger than the
- * longest_fetch_interval.
- */
- if (!timespec_after(&stream->longest_fetch_interval,
- &stream->sleep_interval_ts)) {
- data.stream_data.runtime.tv_sec = 0;
- data.stream_data.runtime.tv_nsec = 0;
- } else {
- subtract_timespecs(&stream->longest_fetch_interval,
- &stream->sleep_interval_ts,
- &data.stream_data.runtime);
- }
-
- init_server_metrics_msg(&msg, LONGEST_FETCH_DELAY, data);
- err = cras_server_metrics_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_server_metrics_message_send(
- (struct cras_main_message *)&msg);
- if (err < 0) {
- syslog(LOG_ERR,
- "Failed to send metrics message: NUM_UNDERRUNS");
- return err;
- }
-
- return 0;
-}
-
-/* Logs the frequency of missed callback. */
-static int
-cras_server_metrics_missed_cb_frequency(const struct cras_rstream *stream)
-{
- struct cras_server_metrics_message msg;
- union cras_server_metrics_data data;
- struct timespec now, time_since;
- double seconds, frequency;
- int err;
-
- clock_gettime(CLOCK_MONOTONIC_RAW, &now);
- subtract_timespecs(&now, &stream->start_ts, &time_since);
- seconds = (double)time_since.tv_sec + time_since.tv_nsec / 1000000000.0;
-
- /* Ignore streams which do not have enough runtime. */
- if (seconds < MISSED_CB_FREQUENCY_SECONDS_MIN)
- return 0;
-
- /* Compute how many callbacks are missed in a day. */
- frequency = (double)stream->num_missed_cb * 86400.0 / seconds;
- data.value = (unsigned)(round(frequency) + 1e-9);
-
- if (stream->direction == CRAS_STREAM_INPUT)
- init_server_metrics_msg(&msg, MISSED_CB_FREQUENCY_INPUT, data);
- else
- init_server_metrics_msg(&msg, MISSED_CB_FREQUENCY_OUTPUT, data);
-
- err = cras_server_metrics_message_send(
- (struct cras_main_message *)&msg);
- if (err < 0) {
- syslog(LOG_ERR,
- "Failed to send metrics message: MISSED_CB_FREQUENCY");
- return err;
- }
-
- /*
- * If missed callback happened at least once, also record frequncy after
- * rescheduling.
- */
- if (!stream->num_missed_cb)
- return 0;
-
- subtract_timespecs(&now, &stream->first_missed_cb_ts, &time_since);
- seconds = (double)time_since.tv_sec + time_since.tv_nsec / 1000000000.0;
-
- /* Compute how many callbacks are missed in a day. */
- frequency = (double)(stream->num_missed_cb - 1) * 86400.0 / seconds;
- data.value = (unsigned)(round(frequency) + 1e-9);
-
- if (stream->direction == CRAS_STREAM_INPUT) {
- init_server_metrics_msg(
- &msg, MISSED_CB_FREQUENCY_AFTER_RESCHEDULING_INPUT,
- data);
- } else {
- init_server_metrics_msg(
- &msg, MISSED_CB_FREQUENCY_AFTER_RESCHEDULING_OUTPUT,
- data);
- }
-
- err = cras_server_metrics_message_send(
- (struct cras_main_message *)&msg);
- if (err < 0) {
- syslog(LOG_ERR,
- "Failed to send metrics message: MISSED_CB_FREQUENCY");
- return err;
- }
-
- return 0;
-}
-
-/*
- * Logs the duration between stream starting time and the first missed
- * callback.
- */
-static int
-cras_server_metrics_missed_cb_first_time(const struct cras_rstream *stream)
-{
- struct cras_server_metrics_message msg;
- union cras_server_metrics_data data;
- struct timespec time_since;
- int err;
-
- subtract_timespecs(&stream->first_missed_cb_ts, &stream->start_ts,
- &time_since);
- data.value = (unsigned)time_since.tv_sec;
-
- if (stream->direction == CRAS_STREAM_INPUT) {
- init_server_metrics_msg(&msg, MISSED_CB_FIRST_TIME_INPUT, data);
- } else {
- init_server_metrics_msg(&msg, MISSED_CB_FIRST_TIME_OUTPUT,
- data);
- }
- err = cras_server_metrics_message_send(
- (struct cras_main_message *)&msg);
- if (err < 0) {
- syslog(LOG_ERR, "Failed to send metrics message: "
- "MISSED_CB_FIRST_TIME");
- return err;
- }
-
- return 0;
-}
-
-/* Logs the duration between the first and the second missed callback events. */
-static int
-cras_server_metrics_missed_cb_second_time(const struct cras_rstream *stream)
-{
- struct cras_server_metrics_message msg;
- union cras_server_metrics_data data;
- struct timespec now, time_since;
- int err;
-
- clock_gettime(CLOCK_MONOTONIC_RAW, &now);
- subtract_timespecs(&now, &stream->first_missed_cb_ts, &time_since);
- data.value = (unsigned)time_since.tv_sec;
-
- if (stream->direction == CRAS_STREAM_INPUT) {
- init_server_metrics_msg(&msg, MISSED_CB_SECOND_TIME_INPUT,
- data);
- } else {
- init_server_metrics_msg(&msg, MISSED_CB_SECOND_TIME_OUTPUT,
- data);
- }
- err = cras_server_metrics_message_send(
- (struct cras_main_message *)&msg);
- if (err < 0) {
- syslog(LOG_ERR, "Failed to send metrics message: "
- "MISSED_CB_SECOND_TIME");
- return err;
- }
-
- return 0;
-}
-
-int cras_server_metrics_missed_cb_event(struct cras_rstream *stream)
-{
- int rc = 0;
-
- stream->num_missed_cb += 1;
- if (stream->num_missed_cb == 1)
- clock_gettime(CLOCK_MONOTONIC_RAW, &stream->first_missed_cb_ts);
-
- /* Do not record missed cb if the stream has these flags. */
- if (stream->flags & (BULK_AUDIO_OK | USE_DEV_TIMING | TRIGGER_ONLY))
- return 0;
-
- /* Only record the first and the second events. */
- if (stream->num_missed_cb == 1)
- rc = cras_server_metrics_missed_cb_first_time(stream);
- else if (stream->num_missed_cb == 2)
- rc = cras_server_metrics_missed_cb_second_time(stream);
-
- return rc;
-}
-
-/* Logs the stream configurations from clients. */
-static int
-cras_server_metrics_stream_config(const struct cras_rstream_config *config)
-{
- struct cras_server_metrics_message msg;
- union cras_server_metrics_data data;
- int err;
-
- data.stream_config.direction = config->direction;
- data.stream_config.cb_threshold = (unsigned)config->cb_threshold;
- data.stream_config.flags = (unsigned)config->flags;
- data.stream_config.effects = (unsigned)config->effects;
- data.stream_config.format = (int)config->format->format;
- data.stream_config.rate = (unsigned)config->format->frame_rate;
- data.stream_config.client_type = config->client_type;
-
- init_server_metrics_msg(&msg, STREAM_CONFIG, data);
- err = cras_server_metrics_message_send(
- (struct cras_main_message *)&msg);
- if (err < 0) {
- syslog(LOG_ERR,
- "Failed to send metrics message: STREAM_CONFIG");
- return err;
- }
-
- return 0;
-}
-
-/* Logs runtime of a stream. */
-int cras_server_metrics_stream_runtime(const struct cras_rstream *stream)
-{
- struct cras_server_metrics_message msg;
- union cras_server_metrics_data data;
- struct timespec now;
- int err;
-
- data.stream_data.client_type = stream->client_type;
- data.stream_data.stream_type = stream->stream_type;
- data.stream_data.direction = stream->direction;
- clock_gettime(CLOCK_MONOTONIC_RAW, &now);
- subtract_timespecs(&now, &stream->start_ts, &data.stream_data.runtime);
-
- init_server_metrics_msg(&msg, STREAM_RUNTIME, data);
-
- err = cras_server_metrics_message_send(
- (struct cras_main_message *)&msg);
- if (err < 0) {
- syslog(LOG_ERR,
- "Failed to send metrics message: STREAM_RUNTIME");
- return err;
- }
-
- return 0;
-}
-
-int cras_server_metrics_stream_create(const struct cras_rstream_config *config)
-{
- return cras_server_metrics_stream_config(config);
-}
-
-int cras_server_metrics_stream_destroy(const struct cras_rstream *stream)
-{
- int rc;
- rc = cras_server_metrics_missed_cb_frequency(stream);
- if (rc < 0)
- return rc;
- rc = cras_server_metrics_stream_runtime(stream);
- if (rc < 0)
- return rc;
- return cras_server_metrics_longest_fetch_delay(stream);
-}
-
-int cras_server_metrics_busyloop(struct timespec *ts, unsigned count)
-{
- struct cras_server_metrics_message msg;
- union cras_server_metrics_data data;
- int err;
-
- data.timespec_data.runtime = *ts;
- data.timespec_data.count = count;
-
- init_server_metrics_msg(&msg, BUSYLOOP, data);
-
- err = cras_server_metrics_message_send(
- (struct cras_main_message *)&msg);
- if (err < 0) {
- syslog(LOG_ERR, "Failed to send metrics message: BUSYLOOP");
- return err;
- }
- return 0;
-}
-
-int cras_server_metrics_busyloop_length(unsigned length)
-{
- struct cras_server_metrics_message msg;
- union cras_server_metrics_data data;
- int err;
-
- data.value = length;
-
- init_server_metrics_msg(&msg, BUSYLOOP_LENGTH, data);
-
- err = cras_server_metrics_message_send(
- (struct cras_main_message *)&msg);
- if (err < 0) {
- syslog(LOG_ERR,
- "Failed to send metrics message: BUSYLOOP_LENGTH");
- return err;
- }
- return 0;
-}
-
-static void metrics_device_runtime(struct cras_server_metrics_device_data data)
-{
- char metrics_name[METRICS_NAME_BUFFER_SIZE];
-
- snprintf(metrics_name, METRICS_NAME_BUFFER_SIZE,
- "Cras.%sDevice%sRuntime",
- data.direction == CRAS_STREAM_INPUT ? "Input" : "Output",
- metrics_device_type_str(data.type));
- cras_metrics_log_histogram(metrics_name, (unsigned)data.runtime.tv_sec,
- 0, 10000, 20);
-
- /* Logs the usage of each device. */
- if (data.direction == CRAS_STREAM_INPUT)
- cras_metrics_log_sparse_histogram(kDeviceTypeInput, data.type);
- else
- cras_metrics_log_sparse_histogram(kDeviceTypeOutput, data.type);
-}
-
-static void metrics_device_gain(struct cras_server_metrics_device_data data)
-{
- char metrics_name[METRICS_NAME_BUFFER_SIZE];
-
- snprintf(metrics_name, METRICS_NAME_BUFFER_SIZE, "%s.%s", kDeviceGain,
- metrics_device_type_str(data.type));
- cras_metrics_log_histogram(metrics_name, data.value, 0, 2000, 20);
-}
-
-static void metrics_device_volume(struct cras_server_metrics_device_data data)
-{
- char metrics_name[METRICS_NAME_BUFFER_SIZE];
-
- snprintf(metrics_name, METRICS_NAME_BUFFER_SIZE, "%s.%s", kDeviceVolume,
- metrics_device_type_str(data.type));
- cras_metrics_log_histogram(metrics_name, data.value, 0, 100, 20);
-}
-
-static void
-metrics_longest_fetch_delay(struct cras_server_metrics_stream_data data)
-{
- int fetch_delay_msec =
- data.runtime.tv_sec * 1000 + data.runtime.tv_nsec / 1000000;
- log_histogram_each_level(3, fetch_delay_msec, 0, 10000, 20,
- kFetchDelayMilliSeconds,
- metrics_client_type_str(data.client_type),
- metrics_stream_type_str(data.stream_type));
-}
-
-static void metrics_stream_runtime(struct cras_server_metrics_stream_data data)
-{
- log_histogram_each_level(
- 4, (int)data.runtime.tv_sec, 0, 10000, 20, kStreamRuntime,
- data.direction == CRAS_STREAM_INPUT ? "Input" : "Output",
- metrics_client_type_str(data.client_type),
- metrics_stream_type_str(data.stream_type));
-}
-
-static void metrics_busyloop(struct cras_server_metrics_timespec_data data)
-{
- char metrics_name[METRICS_NAME_BUFFER_SIZE];
-
- snprintf(metrics_name, METRICS_NAME_BUFFER_SIZE, "%s.%s", kBusyloop,
- get_timespec_period_str(data.runtime));
-
- cras_metrics_log_histogram(metrics_name, data.count, 0, 1000, 20);
-}
-
-static void
-metrics_stream_config(struct cras_server_metrics_stream_config config)
-{
- const char *direction;
-
- if (config.direction == CRAS_STREAM_INPUT)
- direction = "Input";
- else
- direction = "Output";
-
- /* Logs stream callback threshold. */
- log_sparse_histogram_each_level(
- 3, config.cb_threshold, kStreamCallbackThreshold, direction,
- metrics_client_type_str(config.client_type));
-
- /* Logs stream flags. */
- log_sparse_histogram_each_level(
- 3, config.flags, kStreamFlags, direction,
- metrics_client_type_str(config.client_type));
-
- /* Logs stream effects. */
- log_sparse_histogram_each_level(
- 3, config.effects, kStreamEffects, direction,
- metrics_client_type_str(config.client_type));
-
- /* Logs stream sampling format. */
- log_sparse_histogram_each_level(
- 3, config.format, kStreamSamplingFormat, direction,
- metrics_client_type_str(config.client_type));
-
- /* Logs stream sampling rate. */
- log_sparse_histogram_each_level(
- 3, config.rate, kStreamSamplingRate, direction,
- metrics_client_type_str(config.client_type));
-
- /* Logs stream client type. */
- if (config.direction == CRAS_STREAM_INPUT)
- cras_metrics_log_sparse_histogram(kStreamClientTypeInput,
- config.client_type);
- else
- cras_metrics_log_sparse_histogram(kStreamClientTypeOutput,
- config.client_type);
-}
-
-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 BT_SCO_CONNECTION_ERROR:
- cras_metrics_log_sparse_histogram(kHfpScoConnectionError,
- metrics_msg->data.value);
- break;
- case BT_BATTERY_INDICATOR_SUPPORTED:
- cras_metrics_log_sparse_histogram(kHfpBatteryIndicatorSupported,
- metrics_msg->data.value);
- break;
- case BT_BATTERY_REPORT:
- cras_metrics_log_sparse_histogram(kHfpBatteryReport,
- metrics_msg->data.value);
- break;
- case BT_WIDEBAND_PACKET_LOSS:
- cras_metrics_log_histogram(kHfpWidebandSpeechPacketLoss,
- metrics_msg->data.value, 0, 1000,
- 20);
- break;
- case BT_WIDEBAND_SUPPORTED:
- cras_metrics_log_sparse_histogram(kHfpWidebandSpeechSupported,
- metrics_msg->data.value);
- break;
- case BT_WIDEBAND_SELECTED_CODEC:
- cras_metrics_log_sparse_histogram(
- kHfpWidebandSpeechSelectedCodec,
- metrics_msg->data.value);
- break;
- case DEVICE_GAIN:
- metrics_device_gain(metrics_msg->data.device_data);
- break;
- case DEVICE_RUNTIME:
- metrics_device_runtime(metrics_msg->data.device_data);
- break;
- case DEVICE_VOLUME:
- metrics_device_volume(metrics_msg->data.device_data);
- break;
- case HIGHEST_DEVICE_DELAY_INPUT:
- cras_metrics_log_histogram(kHighestDeviceDelayInput,
- metrics_msg->data.value, 1, 10000,
- 20);
- break;
- case HIGHEST_DEVICE_DELAY_OUTPUT:
- cras_metrics_log_histogram(kHighestDeviceDelayOutput,
- metrics_msg->data.value, 1, 10000,
- 20);
- break;
- 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:
- metrics_longest_fetch_delay(metrics_msg->data.stream_data);
- break;
- case MISSED_CB_FIRST_TIME_INPUT:
- cras_metrics_log_histogram(kMissedCallbackFirstTimeInput,
- metrics_msg->data.value, 0, 90000,
- 20);
- break;
- case MISSED_CB_FIRST_TIME_OUTPUT:
- cras_metrics_log_histogram(kMissedCallbackFirstTimeOutput,
- metrics_msg->data.value, 0, 90000,
- 20);
- break;
- case MISSED_CB_FREQUENCY_INPUT:
- cras_metrics_log_histogram(kMissedCallbackFrequencyInput,
- metrics_msg->data.value, 0, 90000,
- 20);
- break;
- case MISSED_CB_FREQUENCY_OUTPUT:
- cras_metrics_log_histogram(kMissedCallbackFrequencyOutput,
- metrics_msg->data.value, 0, 90000,
- 20);
- break;
- case MISSED_CB_FREQUENCY_AFTER_RESCHEDULING_INPUT:
- cras_metrics_log_histogram(
- kMissedCallbackFrequencyAfterReschedulingInput,
- metrics_msg->data.value, 0, 90000, 20);
- break;
- case MISSED_CB_FREQUENCY_AFTER_RESCHEDULING_OUTPUT:
- cras_metrics_log_histogram(
- kMissedCallbackFrequencyAfterReschedulingOutput,
- metrics_msg->data.value, 0, 90000, 20);
- break;
- case MISSED_CB_SECOND_TIME_INPUT:
- cras_metrics_log_histogram(kMissedCallbackSecondTimeInput,
- metrics_msg->data.value, 0, 90000,
- 20);
- break;
- case MISSED_CB_SECOND_TIME_OUTPUT:
- cras_metrics_log_histogram(kMissedCallbackSecondTimeOutput,
- metrics_msg->data.value, 0, 90000,
- 20);
- 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;
- case STREAM_RUNTIME:
- metrics_stream_runtime(metrics_msg->data.stream_data);
- break;
- case BUSYLOOP:
- metrics_busyloop(metrics_msg->data.timespec_data);
- break;
- case BUSYLOOP_LENGTH:
- cras_metrics_log_histogram(
- kBusyloopLength, metrics_msg->data.value, 0, 1000, 50);
- 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;
-}