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