Home | History | Annotate | Download | only in server
      1 /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
      2  * Use of this source code is governed by a BSD-style license that can be
      3  * found in the LICENSE file.
      4  */
      5 
      6 #include <errno.h>
      7 #include <stdio.h>
      8 #include <string.h>
      9 #include <syslog.h>
     10 
     11 #include "cras_metrics.h"
     12 #include "cras_main_message.h"
     13 #include "cras_rstream.h"
     14 
     15 const char kHighestInputHardwareLevel[] = "Cras.HighestInputHardwareLevel";
     16 const char kHighestOutputHardwareLevel[] = "Cras.HighestOutputHardwareLevel";
     17 const char kNoCodecsFoundMetric[] = "Cras.NoCodecsFoundAtBoot";
     18 const char kStreamTimeoutMilliSeconds[] = "Cras.StreamTimeoutMilliSeconds";
     19 const char kStreamCallbackThreshold[] = "Cras.StreamCallbackThreshold";
     20 const char kStreamFlags[] = "Cras.StreamFlags";
     21 const char kStreamSamplingFormat[] = "Cras.StreamSamplingFormat";
     22 const char kStreamSamplingRate[] = "Cras.StreamSamplingRate";
     23 const char kUnderrunsPerDevice[] = "Cras.UnderrunsPerDevice";
     24 
     25 /* Type of metrics to log. */
     26 enum CRAS_SERVER_METRICS_TYPE {
     27 	HIGHEST_INPUT_HW_LEVEL,
     28 	HIGHEST_OUTPUT_HW_LEVEL,
     29 	LONGEST_FETCH_DELAY,
     30 	NUM_UNDERRUNS,
     31 	STREAM_CONFIG
     32 };
     33 
     34 struct cras_server_metrics_stream_config {
     35 	unsigned cb_threshold;
     36 	unsigned flags;
     37 	int format;
     38 	unsigned rate;
     39 };
     40 
     41 union cras_server_metrics_data {
     42 	unsigned value;
     43 	struct cras_server_metrics_stream_config stream_config;
     44 };
     45 
     46 struct cras_server_metrics_message {
     47 	struct cras_main_message header;
     48 	enum CRAS_SERVER_METRICS_TYPE metrics_type;
     49 	union cras_server_metrics_data data;
     50 };
     51 
     52 static void init_server_metrics_msg(
     53 		struct cras_server_metrics_message *msg,
     54 		enum CRAS_SERVER_METRICS_TYPE type,
     55 		union cras_server_metrics_data data)
     56 {
     57 	memset(msg, 0, sizeof(*msg));
     58 	msg->header.type = CRAS_MAIN_METRICS;
     59 	msg->header.length = sizeof(*msg);
     60 	msg->metrics_type = type;
     61 	msg->data = data;
     62 }
     63 
     64 int cras_server_metrics_highest_hw_level(unsigned hw_level,
     65 		enum CRAS_STREAM_DIRECTION direction)
     66 {
     67 	struct cras_server_metrics_message msg;
     68 	union cras_server_metrics_data data;
     69 	int err;
     70 
     71 	data.value = hw_level;
     72 
     73 	switch (direction) {
     74 	case CRAS_STREAM_INPUT:
     75 		init_server_metrics_msg(&msg, HIGHEST_INPUT_HW_LEVEL, data);
     76 		break;
     77 	case CRAS_STREAM_OUTPUT:
     78 		init_server_metrics_msg(&msg, HIGHEST_OUTPUT_HW_LEVEL, data);
     79 		break;
     80 	default:
     81 		return 0;
     82 	}
     83 
     84 	err = cras_main_message_send((struct cras_main_message *)&msg);
     85 	if (err < 0) {
     86 		syslog(LOG_ERR,
     87 		       "Failed to send metrics message: HIGHEST_HW_LEVEL");
     88 		return err;
     89 	}
     90 
     91 	return 0;
     92 }
     93 
     94 int cras_server_metrics_longest_fetch_delay(unsigned delay_msec)
     95 {
     96 	struct cras_server_metrics_message msg;
     97 	union cras_server_metrics_data data;
     98 	int err;
     99 
    100 	data.value = delay_msec;
    101 	init_server_metrics_msg(&msg, LONGEST_FETCH_DELAY, data);
    102 	err = cras_main_message_send((struct cras_main_message *)&msg);
    103 	if (err < 0) {
    104 		syslog(LOG_ERR,
    105 		       "Failed to send metrics message: LONGEST_FETCH_DELAY");
    106 		return err;
    107 	}
    108 
    109 	return 0;
    110 }
    111 
    112 int cras_server_metrics_num_underruns(unsigned num_underruns)
    113 {
    114 	struct cras_server_metrics_message msg;
    115 	union cras_server_metrics_data data;
    116 	int err;
    117 
    118 	data.value = num_underruns;
    119 	init_server_metrics_msg(&msg, NUM_UNDERRUNS, data);
    120 	err = cras_main_message_send((struct cras_main_message *)&msg);
    121 	if (err < 0) {
    122 		syslog(LOG_ERR,
    123 		       "Failed to send metrics message: NUM_UNDERRUNS");
    124 		return err;
    125 	}
    126 
    127 	return 0;
    128 }
    129 
    130 int cras_server_metrics_stream_config(struct cras_rstream_config *config)
    131 {
    132 	struct cras_server_metrics_message msg;
    133 	union cras_server_metrics_data data;
    134 	int err;
    135 
    136 	data.stream_config.cb_threshold = (unsigned)config->cb_threshold;
    137 	data.stream_config.flags = (unsigned)config->flags;
    138 	data.stream_config.format = (int)config->format->format;
    139 	data.stream_config.rate = (unsigned)config->format->frame_rate;
    140 
    141 	init_server_metrics_msg(&msg, STREAM_CONFIG, data);
    142 	err = cras_main_message_send((struct cras_main_message *)&msg);
    143 	if (err < 0) {
    144 		syslog(LOG_ERR,
    145 			"Failed to send metrics message: STREAM_CONFIG");
    146 		return err;
    147 	}
    148 
    149 	return 0;
    150 }
    151 
    152 static void metrics_stream_config(
    153 		struct cras_server_metrics_stream_config config)
    154 {
    155 	/* Logs stream callback threshold. */
    156 	cras_metrics_log_sparse_histogram(kStreamCallbackThreshold,
    157 					  config.cb_threshold);
    158 
    159 	/* Logs stream flags. */
    160 	cras_metrics_log_sparse_histogram(kStreamFlags,
    161 					  config.flags);
    162 
    163 	/* Logs stream sampling format. */
    164 	cras_metrics_log_sparse_histogram(kStreamSamplingFormat,
    165 					  config.format);
    166 
    167 	/* Logs stream sampling rate. */
    168 	cras_metrics_log_sparse_histogram(kStreamSamplingRate,
    169 					  config.rate);
    170 }
    171 
    172 static void handle_metrics_message(struct cras_main_message *msg, void *arg)
    173 {
    174 	struct cras_server_metrics_message *metrics_msg =
    175 			(struct cras_server_metrics_message *)msg;
    176 	switch (metrics_msg->metrics_type) {
    177 	case HIGHEST_INPUT_HW_LEVEL:
    178 		cras_metrics_log_histogram(kHighestInputHardwareLevel,
    179 				metrics_msg->data.value, 1, 10000, 20);
    180 		break;
    181 	case HIGHEST_OUTPUT_HW_LEVEL:
    182 		cras_metrics_log_histogram(kHighestOutputHardwareLevel,
    183 				metrics_msg->data.value, 1, 10000, 20);
    184 		break;
    185 	case LONGEST_FETCH_DELAY:
    186 		cras_metrics_log_histogram(kStreamTimeoutMilliSeconds,
    187 				metrics_msg->data.value, 1, 20000, 10);
    188 		break;
    189 	case NUM_UNDERRUNS:
    190 		cras_metrics_log_histogram(kUnderrunsPerDevice,
    191 				metrics_msg->data.value, 0, 1000, 10);
    192 		break;
    193 	case STREAM_CONFIG:
    194 		metrics_stream_config(metrics_msg->data.stream_config);
    195 		break;
    196 	default:
    197 		syslog(LOG_ERR, "Unknown metrics type %u",
    198 		       metrics_msg->metrics_type);
    199 		break;
    200 	}
    201 
    202 }
    203 
    204 int cras_server_metrics_init() {
    205 	cras_main_message_add_handler(CRAS_MAIN_METRICS,
    206 				      handle_metrics_message, NULL);
    207 	return 0;
    208 }
    209