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
init_server_metrics_msg(struct cras_server_metrics_message * msg,enum CRAS_SERVER_METRICS_TYPE type,union cras_server_metrics_data data)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
cras_server_metrics_highest_hw_level(unsigned hw_level,enum CRAS_STREAM_DIRECTION direction)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
cras_server_metrics_longest_fetch_delay(unsigned delay_msec)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
cras_server_metrics_num_underruns(unsigned num_underruns)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
cras_server_metrics_stream_config(struct cras_rstream_config * config)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
metrics_stream_config(struct cras_server_metrics_stream_config config)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
handle_metrics_message(struct cras_main_message * msg,void * arg)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
cras_server_metrics_init()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