sink.text.details: honor component's initial log level
[babeltrace.git] / src / plugins / text / details / details.c
1 /*
2 * Copyright 2019 Philippe Proulx <pproulx@efficios.com>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23 #define BT_LOG_OUTPUT_LEVEL (details_comp->log_level)
24 #define BT_LOG_TAG "PLUGIN/SINK.TEXT.DETAILS"
25 #include "logging/log.h"
26
27 #include <babeltrace2/babeltrace.h>
28
29 #include "common/common.h"
30 #include "common/assert.h"
31 #include "details.h"
32 #include "write.h"
33
34 #define LOG_WRONG_PARAM_TYPE(_name, _value, _exp_type) \
35 do { \
36 BT_LOGE("Wrong `%s` parameter type: type=%s, " \
37 "expected-type=%s", \
38 (_name), bt_common_value_type_string( \
39 bt_value_get_type(_value)), \
40 bt_common_value_type_string(_exp_type)); \
41 } while (0)
42
43 static
44 const char * const in_port_name = "in";
45
46 static
47 const char * const color_param_name = "color";
48
49 static
50 const char * const with_metadata_param_name = "with-metadata";
51
52 static
53 const char * const with_time_param_name = "with-time";
54
55 static
56 const char * const with_trace_class_name_param_name = "with-trace-class-name";
57
58 static
59 const char * const with_trace_name_param_name = "with-trace-name";
60
61 static
62 const char * const with_stream_class_name_param_name = "with-stream-class-name";
63
64 static
65 const char * const with_stream_name_param_name = "with-stream-name";
66
67 static
68 const char * const with_uuid_param_name = "with-uuid";
69
70 static
71 const char * const compact_param_name = "compact";
72
73 BT_HIDDEN
74 void details_destroy_details_trace_class_meta(
75 struct details_trace_class_meta *details_tc_meta)
76 {
77 if (!details_tc_meta) {
78 goto end;
79 }
80
81 if (details_tc_meta->objects) {
82 g_hash_table_destroy(details_tc_meta->objects);
83 details_tc_meta->objects = NULL;
84 }
85
86 g_free(details_tc_meta);
87
88 end:
89 return;
90 }
91
92 BT_HIDDEN
93 struct details_trace_class_meta *details_create_details_trace_class_meta(void)
94 {
95 struct details_trace_class_meta *details_tc_meta =
96 g_new0(struct details_trace_class_meta, 1);
97
98 if (!details_tc_meta) {
99 goto end;
100 }
101
102 details_tc_meta->objects = g_hash_table_new(
103 g_direct_hash, g_direct_equal);
104 if (!details_tc_meta->objects) {
105 details_destroy_details_trace_class_meta(details_tc_meta);
106 details_tc_meta = NULL;
107 goto end;
108 }
109
110 details_tc_meta->tc_destruction_listener_id = UINT64_C(-1);
111
112 end:
113 return details_tc_meta;
114 }
115
116 static
117 void destroy_details_comp(struct details_comp *details_comp)
118 {
119 GHashTableIter iter;
120 gpointer key, value;
121
122 if (!details_comp) {
123 goto end;
124 }
125
126 if (details_comp->meta) {
127 /*
128 * Remove trace class destruction listeners, because
129 * otherwise, when they are called, `details_comp`
130 * (their user data) won't exist anymore (we're
131 * destroying it here).
132 */
133 g_hash_table_iter_init(&iter, details_comp->meta);
134
135 while (g_hash_table_iter_next(&iter, &key, &value)) {
136 struct details_trace_class_meta *details_tc_meta =
137 value;
138
139 if (details_tc_meta->tc_destruction_listener_id !=
140 UINT64_C(-1)) {
141 bt_trace_class_remove_destruction_listener(
142 (const void *) key,
143 details_tc_meta->tc_destruction_listener_id);
144 }
145 }
146
147 g_hash_table_destroy(details_comp->meta);
148 details_comp->meta = NULL;
149 }
150
151 if (details_comp->traces) {
152 /*
153 * Remove trace destruction listeners, because
154 * otherwise, when they are called, `details_comp` won't
155 * exist anymore (we're destroying it here).
156 */
157 g_hash_table_iter_init(&iter, details_comp->traces);
158
159 while (g_hash_table_iter_next(&iter, &key, &value)) {
160 struct details_trace *details_trace = value;
161
162 bt_trace_remove_destruction_listener(
163 (const void *) key,
164 details_trace->trace_destruction_listener_id);
165 }
166
167 g_hash_table_destroy(details_comp->traces);
168 details_comp->traces = NULL;
169 }
170
171 if (details_comp->str) {
172 g_string_free(details_comp->str, TRUE);
173 details_comp->str = NULL;
174 }
175
176 BT_SELF_COMPONENT_PORT_INPUT_MESSAGE_ITERATOR_PUT_REF_AND_RESET(
177 details_comp->msg_iter);
178 g_free(details_comp);
179
180 end:
181 return;
182 }
183
184 static
185 struct details_comp *create_details_comp(
186 bt_self_component_sink *self_comp_sink)
187 {
188 struct details_comp *details_comp = g_new0(struct details_comp, 1);
189 bt_self_component *self_comp =
190 bt_self_component_sink_as_self_component(self_comp_sink);
191
192 if (!details_comp) {
193 goto error;
194 }
195
196 details_comp->log_level = bt_component_get_logging_level(
197 bt_self_component_as_component(self_comp));
198 details_comp->meta = g_hash_table_new_full(g_direct_hash,
199 g_direct_equal, NULL,
200 (GDestroyNotify) details_destroy_details_trace_class_meta);
201 if (!details_comp->meta) {
202 goto error;
203 }
204
205 details_comp->traces = g_hash_table_new_full(g_direct_hash,
206 g_direct_equal, NULL, g_free);
207 if (!details_comp->traces) {
208 goto error;
209 }
210
211 details_comp->str = g_string_new(NULL);
212 if (!details_comp->str) {
213 goto error;
214 }
215
216 goto end;
217
218 error:
219 destroy_details_comp(details_comp);
220 details_comp = NULL;
221
222 end:
223 return details_comp;
224 }
225
226 BT_HIDDEN
227 void details_finalize(bt_self_component_sink *comp)
228 {
229 struct details_comp *details_comp;
230
231 BT_ASSERT(comp);
232 details_comp = bt_self_component_get_data(
233 bt_self_component_sink_as_self_component(comp));
234 BT_ASSERT(details_comp);
235 destroy_details_comp(details_comp);
236 }
237
238 static
239 int configure_bool_opt(struct details_comp *details_comp,
240 const bt_value *params, const char *param_name,
241 bool default_value, bool *opt_value)
242 {
243 int ret = 0;
244 const bt_value *value;
245
246 *opt_value = default_value;
247 value = bt_value_map_borrow_entry_value_const(params, param_name);
248 if (value) {
249 if (!bt_value_is_bool(value)) {
250 LOG_WRONG_PARAM_TYPE(param_name, value,
251 BT_VALUE_TYPE_BOOL);
252 ret = -1;
253 goto end;
254 }
255
256 *opt_value = (bool) bt_value_bool_get(value);
257 }
258
259 end:
260 return ret;
261 }
262
263 static
264 int configure_details_comp(struct details_comp *details_comp,
265 const bt_value *params)
266 {
267 int ret = 0;
268 const bt_value *value;
269 const char *str;
270
271 /* Colorize output? */
272 details_comp->cfg.with_color = bt_common_colors_supported();
273 value = bt_value_map_borrow_entry_value_const(params, color_param_name);
274 if (value) {
275 if (!bt_value_is_string(value)) {
276 LOG_WRONG_PARAM_TYPE(color_param_name, value,
277 BT_VALUE_TYPE_STRING);
278 goto error;
279 }
280
281 str = bt_value_string_get(value);
282
283 if (strcmp(str, "never") == 0) {
284 details_comp->cfg.with_color = false;
285 } else if (strcmp(str, "auto") == 0) {
286 details_comp->cfg.with_color =
287 bt_common_colors_supported();
288 } else if (strcmp(str, "always") == 0) {
289 details_comp->cfg.with_color = true;
290 } else {
291 BT_LOGE("Invalid `%s` parameter: unknown value "
292 "(expecting `never`, `auto`, or `always`): "
293 "value=\"%s\"", color_param_name, str);
294 goto error;
295 }
296 }
297
298 /* With metadata objects? */
299 ret = configure_bool_opt(details_comp, params, with_metadata_param_name,
300 true, &details_comp->cfg.with_meta);
301 if (ret) {
302 goto error;
303 }
304
305 /* Compact? */
306 ret = configure_bool_opt(details_comp, params, compact_param_name,
307 false, &details_comp->cfg.compact);
308 if (ret) {
309 goto error;
310 }
311
312 /* With time? */
313 ret = configure_bool_opt(details_comp, params, with_time_param_name,
314 true, &details_comp->cfg.with_time);
315 if (ret) {
316 goto error;
317 }
318
319 /* With trace class name? */
320 ret = configure_bool_opt(details_comp, params,
321 with_trace_class_name_param_name,
322 true, &details_comp->cfg.with_trace_class_name);
323 if (ret) {
324 goto error;
325 }
326
327 /* With trace name? */
328 ret = configure_bool_opt(details_comp, params,
329 with_trace_name_param_name,
330 true, &details_comp->cfg.with_trace_name);
331 if (ret) {
332 goto error;
333 }
334
335 /* With stream class name? */
336 ret = configure_bool_opt(details_comp, params,
337 with_stream_class_name_param_name,
338 true, &details_comp->cfg.with_stream_class_name);
339 if (ret) {
340 goto error;
341 }
342
343 /* With stream name? */
344 ret = configure_bool_opt(details_comp, params,
345 with_stream_name_param_name,
346 true, &details_comp->cfg.with_stream_name);
347 if (ret) {
348 goto error;
349 }
350
351 /* With UUID? */
352 ret = configure_bool_opt(details_comp, params,
353 with_uuid_param_name, true, &details_comp->cfg.with_uuid);
354 if (ret) {
355 goto error;
356 }
357
358 goto end;
359
360 error:
361 ret = -1;
362
363 end:
364 return ret;
365 }
366
367 static
368 void log_configuration(bt_self_component_sink *comp,
369 struct details_comp *details_comp)
370 {
371 BT_LOGI("Configuration for `sink.text.details` component `%s`:",
372 bt_component_get_name(bt_self_component_as_component(
373 bt_self_component_sink_as_self_component(comp))));
374 BT_LOGI(" Colorize output: %d", details_comp->cfg.with_color);
375 BT_LOGI(" Compact: %d", details_comp->cfg.compact);
376 BT_LOGI(" With metadata: %d", details_comp->cfg.with_meta);
377 BT_LOGI(" With time: %d", details_comp->cfg.with_time);
378 BT_LOGI(" With trace class name: %d",
379 details_comp->cfg.with_trace_class_name);
380 BT_LOGI(" With trace name: %d", details_comp->cfg.with_trace_name);
381 BT_LOGI(" With stream class name: %d",
382 details_comp->cfg.with_stream_class_name);
383 BT_LOGI(" With stream name: %d", details_comp->cfg.with_stream_name);
384 BT_LOGI(" With UUID: %d", details_comp->cfg.with_uuid);
385 }
386
387 BT_HIDDEN
388 bt_self_component_status details_init(bt_self_component_sink *comp,
389 const bt_value *params,
390 __attribute__((unused)) void *init_method_data)
391 {
392 bt_self_component_status status = BT_SELF_COMPONENT_STATUS_OK;
393 struct details_comp *details_comp = NULL;
394
395 status = bt_self_component_sink_add_input_port(comp, in_port_name,
396 NULL, NULL);
397 if (status != BT_SELF_COMPONENT_STATUS_OK) {
398 goto error;
399 }
400
401 details_comp = create_details_comp(comp);
402 if (!details_comp) {
403 status = BT_SELF_COMPONENT_STATUS_NOMEM;
404 goto error;
405 }
406
407 if (configure_details_comp(details_comp, params)) {
408 BT_LOGE_STR("Failed to configure component.");
409 goto error;
410 }
411
412 log_configuration(comp, details_comp);
413 bt_self_component_set_data(
414 bt_self_component_sink_as_self_component(comp), details_comp);
415 goto end;
416
417 error:
418 if (status == BT_SELF_COMPONENT_STATUS_OK) {
419 status = BT_SELF_COMPONENT_STATUS_ERROR;
420 }
421
422 destroy_details_comp(details_comp);
423
424 end:
425 return status;
426 }
427
428 BT_HIDDEN
429 bt_self_component_status details_graph_is_configured(
430 bt_self_component_sink *comp)
431 {
432 bt_self_component_status status = BT_SELF_COMPONENT_STATUS_OK;
433 bt_self_component_port_input_message_iterator *iterator;
434 struct details_comp *details_comp;
435 bt_self_component_port_input *in_port;
436
437 details_comp = bt_self_component_get_data(
438 bt_self_component_sink_as_self_component(comp));
439 BT_ASSERT(details_comp);
440 in_port = bt_self_component_sink_borrow_input_port_by_name(comp,
441 in_port_name);
442 if (!bt_port_is_connected(bt_port_input_as_port_const(
443 bt_self_component_port_input_as_port_input(in_port)))) {
444 BT_LOGE("Single input port is not connected: "
445 "port-name=\"%s\"", in_port_name);
446 status = BT_SELF_COMPONENT_STATUS_ERROR;
447 goto end;
448 }
449
450 iterator = bt_self_component_port_input_message_iterator_create(
451 bt_self_component_sink_borrow_input_port_by_name(comp,
452 in_port_name));
453 if (!iterator) {
454 status = BT_SELF_COMPONENT_STATUS_NOMEM;
455 goto end;
456 }
457
458 BT_SELF_COMPONENT_PORT_INPUT_MESSAGE_ITERATOR_MOVE_REF(
459 details_comp->msg_iter, iterator);
460
461 end:
462 return status;
463 }
464
465 BT_HIDDEN
466 bt_self_component_status details_consume(bt_self_component_sink *comp)
467 {
468 bt_self_component_status ret = BT_SELF_COMPONENT_STATUS_OK;
469 bt_message_array_const msgs;
470 uint64_t count;
471 struct details_comp *details_comp;
472 bt_message_iterator_status it_ret;
473 uint64_t i;
474
475 details_comp = bt_self_component_get_data(
476 bt_self_component_sink_as_self_component(comp));
477 BT_ASSERT(details_comp);
478 BT_ASSERT(details_comp->msg_iter);
479
480 /* Consume messages */
481 it_ret = bt_self_component_port_input_message_iterator_next(
482 details_comp->msg_iter, &msgs, &count);
483 switch (it_ret) {
484 case BT_MESSAGE_ITERATOR_STATUS_OK:
485 ret = BT_SELF_COMPONENT_STATUS_OK;
486
487 for (i = 0; i < count; i++) {
488 int print_ret = details_write_message(details_comp,
489 msgs[i]);
490
491 if (print_ret) {
492 for (; i < count; i++) {
493 /* Put all remaining messages */
494 bt_message_put_ref(msgs[i]);
495 }
496
497 ret = BT_SELF_COMPONENT_STATUS_ERROR;
498 goto end;
499 }
500
501 /* Print output buffer to standard output and flush */
502 if (details_comp->str->len > 0) {
503 printf("%s", details_comp->str->str);
504 fflush(stdout);
505 details_comp->printed_something = true;
506 }
507
508 /* Put this message */
509 bt_message_put_ref(msgs[i]);
510 }
511
512 break;
513 case BT_MESSAGE_ITERATOR_STATUS_AGAIN:
514 ret = BT_SELF_COMPONENT_STATUS_AGAIN;
515 goto end;
516 case BT_MESSAGE_ITERATOR_STATUS_END:
517 ret = BT_SELF_COMPONENT_STATUS_END;
518 goto end;
519 case BT_MESSAGE_ITERATOR_STATUS_ERROR:
520 ret = BT_SELF_COMPONENT_STATUS_ERROR;
521 goto end;
522 case BT_MESSAGE_ITERATOR_STATUS_NOMEM:
523 ret = BT_SELF_COMPONENT_STATUS_NOMEM;
524 goto end;
525 default:
526 abort();
527 }
528
529 end:
530 return ret;
531 }
This page took 0.039633 seconds and 5 git commands to generate.