4 * Babeltrace CTF Text Output Plugin Event Printing
6 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 * Copyright 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
9 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 #include <babeltrace/babeltrace.h>
31 #include <babeltrace/bitfield-internal.h>
32 #include <babeltrace/common-internal.h>
33 #include <babeltrace/compat/time-internal.h>
34 #include <babeltrace/assert-internal.h>
39 #define NSEC_PER_SEC 1000000000LL
41 #define COLOR_NAME BT_COMMON_COLOR_BOLD
42 #define COLOR_FIELD_NAME BT_COMMON_COLOR_FG_CYAN
43 #define COLOR_RST BT_COMMON_COLOR_RESET
44 #define COLOR_STRING_VALUE BT_COMMON_COLOR_BOLD
45 #define COLOR_NUMBER_VALUE BT_COMMON_COLOR_BOLD
46 #define COLOR_ENUM_MAPPING_NAME BT_COMMON_COLOR_BOLD
47 #define COLOR_UNKNOWN BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_RED
48 #define COLOR_EVENT_NAME BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_MAGENTA
49 #define COLOR_TIMESTAMP BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_YELLOW
52 int64_t real_timestamp
; /* Relative to UNIX epoch. */
53 uint64_t clock_value
; /* In cycles. */
57 enum bt_component_status
print_field(struct pretty_component
*pretty
,
58 struct bt_field
*field
, bool print_names
,
59 GQuark
*filters_fields
, int filter_array_len
);
62 void print_name_equal(struct pretty_component
*pretty
, const char *name
)
64 if (pretty
->use_colors
) {
65 g_string_append_printf(pretty
->string
, "%s%s%s = ", COLOR_NAME
,
68 g_string_append_printf(pretty
->string
, "%s = ", name
);
73 void print_field_name_equal(struct pretty_component
*pretty
, const char *name
)
75 if (pretty
->use_colors
) {
76 g_string_append_printf(pretty
->string
, "%s%s%s = ",
77 COLOR_FIELD_NAME
, name
, COLOR_RST
);
79 g_string_append_printf(pretty
->string
, "%s = ", name
);
84 void print_timestamp_cycles(struct pretty_component
*pretty
,
85 struct bt_event
*event
)
87 struct bt_clock_value
*clock_value
;
89 enum bt_clock_value_status cv_status
;
91 cv_status
= bt_event_borrow_default_clock_value(event
, &clock_value
);
92 if (cv_status
!= BT_CLOCK_VALUE_STATUS_KNOWN
|| !clock_value
) {
93 g_string_append(pretty
->string
, "????????????????????");
97 cycles
= bt_clock_value_get_value(clock_value
);
98 g_string_append_printf(pretty
->string
, "%020" PRIu64
, cycles
);
100 if (pretty
->last_cycles_timestamp
!= -1ULL) {
101 pretty
->delta_cycles
= cycles
- pretty
->last_cycles_timestamp
;
103 pretty
->last_cycles_timestamp
= cycles
;
107 void print_timestamp_wall(struct pretty_component
*pretty
,
108 struct bt_clock_value
*clock_value
)
111 int64_t ts_nsec
= 0; /* add configurable offset */
112 int64_t ts_sec
= 0; /* add configurable offset */
113 uint64_t ts_sec_abs
, ts_nsec_abs
;
117 g_string_append(pretty
->string
, "??:??:??.?????????");
121 ret
= bt_clock_value_get_ns_from_origin(clock_value
, &ts_nsec
);
123 // TODO: log, this is unexpected
124 g_string_append(pretty
->string
, "Error");
128 if (pretty
->last_real_timestamp
!= -1ULL) {
129 pretty
->delta_real_timestamp
= ts_nsec
- pretty
->last_real_timestamp
;
132 pretty
->last_real_timestamp
= ts_nsec
;
133 ts_sec
+= ts_nsec
/ NSEC_PER_SEC
;
134 ts_nsec
= ts_nsec
% NSEC_PER_SEC
;
136 if (ts_sec
>= 0 && ts_nsec
>= 0) {
139 ts_nsec_abs
= ts_nsec
;
140 } else if (ts_sec
> 0 && ts_nsec
< 0) {
142 ts_sec_abs
= ts_sec
- 1;
143 ts_nsec_abs
= NSEC_PER_SEC
+ ts_nsec
;
144 } else if (ts_sec
== 0 && ts_nsec
< 0) {
147 ts_nsec_abs
= -ts_nsec
;
148 } else if (ts_sec
< 0 && ts_nsec
> 0) {
150 ts_sec_abs
= -(ts_sec
+ 1);
151 ts_nsec_abs
= NSEC_PER_SEC
- ts_nsec
;
152 } else if (ts_sec
< 0 && ts_nsec
== 0) {
154 ts_sec_abs
= -ts_sec
;
155 ts_nsec_abs
= ts_nsec
;
156 } else { /* (ts_sec < 0 && ts_nsec < 0) */
158 ts_sec_abs
= -ts_sec
;
159 ts_nsec_abs
= -ts_nsec
;
162 if (!pretty
->options
.clock_seconds
) {
164 time_t time_s
= (time_t) ts_sec_abs
;
166 if (is_negative
&& !pretty
->negative_timestamp_warning_done
) {
168 fprintf(stderr
, "[warning] Fallback to [sec.ns] to print negative time value. Use --clock-seconds.\n");
169 pretty
->negative_timestamp_warning_done
= true;
173 if (!pretty
->options
.clock_gmt
) {
176 res
= bt_localtime_r(&time_s
, &tm
);
179 fprintf(stderr
, "[warning] Unable to get localtime.\n");
185 res
= bt_gmtime_r(&time_s
, &tm
);
188 fprintf(stderr
, "[warning] Unable to get gmtime.\n");
192 if (pretty
->options
.clock_date
) {
196 /* Print date and time */
197 res
= strftime(timestr
, sizeof(timestr
),
201 fprintf(stderr
, "[warning] Unable to print ascii time.\n");
205 g_string_append(pretty
->string
, timestr
);
208 /* Print time in HH:MM:SS.ns */
209 g_string_append_printf(pretty
->string
,
210 "%02d:%02d:%02d.%09" PRIu64
, tm
.tm_hour
, tm
.tm_min
,
211 tm
.tm_sec
, ts_nsec_abs
);
215 g_string_append_printf(pretty
->string
, "%s%" PRId64
".%09" PRIu64
,
216 is_negative
? "-" : "", ts_sec_abs
, ts_nsec_abs
);
222 enum bt_component_status
print_event_timestamp(struct pretty_component
*pretty
,
223 struct bt_event
*event
, bool *start_line
)
225 bool print_names
= pretty
->options
.print_header_field_names
;
226 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
227 struct bt_stream
*stream
= NULL
;
228 struct bt_stream_class
*stream_class
= NULL
;
229 struct bt_trace
*trace
= NULL
;
230 struct bt_clock_value
*clock_value
= NULL
;
231 enum bt_clock_value_status cv_status
;
233 stream
= bt_event_borrow_stream(event
);
235 ret
= BT_COMPONENT_STATUS_ERROR
;
239 stream_class
= bt_stream_borrow_class(stream
);
241 ret
= BT_COMPONENT_STATUS_ERROR
;
244 trace
= bt_stream_class_borrow_trace(stream_class
);
246 ret
= BT_COMPONENT_STATUS_ERROR
;
250 cv_status
= bt_event_borrow_default_clock_value(event
, &clock_value
);
251 if (cv_status
!= BT_CLOCK_VALUE_STATUS_KNOWN
|| !clock_value
) {
252 /* No default clock value: skip the timestamp without an error */
257 print_name_equal(pretty
, "timestamp");
259 g_string_append(pretty
->string
, "[");
261 if (pretty
->use_colors
) {
262 g_string_append(pretty
->string
, COLOR_TIMESTAMP
);
264 if (pretty
->options
.print_timestamp_cycles
) {
265 print_timestamp_cycles(pretty
, event
);
268 cv_status
= bt_event_borrow_default_clock_value(event
,
270 print_timestamp_wall(pretty
, clock_value
);
272 if (pretty
->use_colors
) {
273 g_string_append(pretty
->string
, COLOR_RST
);
277 g_string_append(pretty
->string
, "] ");
279 if (pretty
->options
.print_delta_field
) {
281 g_string_append(pretty
->string
, ", ");
282 print_name_equal(pretty
, "delta");
284 g_string_append(pretty
->string
, "(");
286 if (pretty
->options
.print_timestamp_cycles
) {
287 if (pretty
->delta_cycles
== -1ULL) {
288 g_string_append(pretty
->string
,
289 "+??????????\?\?) "); /* Not a trigraph. */
291 g_string_append_printf(pretty
->string
,
292 "+%012" PRIu64
, pretty
->delta_cycles
);
295 if (pretty
->delta_real_timestamp
!= -1ULL) {
296 uint64_t delta_sec
, delta_nsec
, delta
;
298 delta
= pretty
->delta_real_timestamp
;
299 delta_sec
= delta
/ NSEC_PER_SEC
;
300 delta_nsec
= delta
% NSEC_PER_SEC
;
301 g_string_append_printf(pretty
->string
,
302 "+%" PRIu64
".%09" PRIu64
,
303 delta_sec
, delta_nsec
);
305 g_string_append(pretty
->string
, "+?.?????????");
309 g_string_append(pretty
->string
, ") ");
312 *start_line
= !print_names
;
319 enum bt_component_status
print_event_header(struct pretty_component
*pretty
,
320 struct bt_event
*event
)
322 bool print_names
= pretty
->options
.print_header_field_names
;
323 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
324 struct bt_event_class
*event_class
= NULL
;
325 struct bt_stream_class
*stream_class
= NULL
;
326 struct bt_trace
*trace_class
= NULL
;
328 enum bt_property_availability prop_avail
;
330 event_class
= bt_event_borrow_class(event
);
332 ret
= BT_COMPONENT_STATUS_ERROR
;
335 stream_class
= bt_event_class_borrow_stream_class(event_class
);
337 ret
= BT_COMPONENT_STATUS_ERROR
;
340 trace_class
= bt_stream_class_borrow_trace(stream_class
);
342 ret
= BT_COMPONENT_STATUS_ERROR
;
345 ret
= print_event_timestamp(pretty
, event
, &pretty
->start_line
);
346 if (ret
!= BT_COMPONENT_STATUS_OK
) {
349 if (pretty
->options
.print_trace_field
) {
352 name
= bt_trace_get_name(trace_class
);
354 if (!pretty
->start_line
) {
355 g_string_append(pretty
->string
, ", ");
358 print_name_equal(pretty
, "trace");
361 g_string_append(pretty
->string
, name
);
364 g_string_append(pretty
->string
, " ");
368 if (pretty
->options
.print_trace_hostname_field
) {
369 struct bt_value
*hostname_str
;
371 hostname_str
= bt_trace_borrow_environment_entry_value_by_name(
372 trace_class
, "hostname");
376 if (!pretty
->start_line
) {
377 g_string_append(pretty
->string
, ", ");
380 print_name_equal(pretty
, "trace:hostname");
382 if (bt_value_string_get(hostname_str
, &str
)
383 == BT_VALUE_STATUS_OK
) {
384 g_string_append(pretty
->string
, str
);
389 if (pretty
->options
.print_trace_domain_field
) {
390 struct bt_value
*domain_str
;
392 domain_str
= bt_trace_borrow_environment_entry_value_by_name(
393 trace_class
, "domain");
397 if (!pretty
->start_line
) {
398 g_string_append(pretty
->string
, ", ");
401 print_name_equal(pretty
, "trace:domain");
402 } else if (dom_print
) {
403 g_string_append(pretty
->string
, ":");
405 if (bt_value_string_get(domain_str
, &str
)
406 == BT_VALUE_STATUS_OK
) {
407 g_string_append(pretty
->string
, str
);
412 if (pretty
->options
.print_trace_procname_field
) {
413 struct bt_value
*procname_str
;
415 procname_str
= bt_trace_borrow_environment_entry_value_by_name(
416 trace_class
, "procname");
420 if (!pretty
->start_line
) {
421 g_string_append(pretty
->string
, ", ");
424 print_name_equal(pretty
, "trace:procname");
425 } else if (dom_print
) {
426 g_string_append(pretty
->string
, ":");
428 if (bt_value_string_get(procname_str
, &str
)
429 == BT_VALUE_STATUS_OK
) {
430 g_string_append(pretty
->string
, str
);
436 if (pretty
->options
.print_trace_vpid_field
) {
437 struct bt_value
*vpid_value
;
439 vpid_value
= bt_trace_borrow_environment_entry_value_by_name(
440 trace_class
, "vpid");
444 if (!pretty
->start_line
) {
445 g_string_append(pretty
->string
, ", ");
448 print_name_equal(pretty
, "trace:vpid");
449 } else if (dom_print
) {
450 g_string_append(pretty
->string
, ":");
452 if (bt_value_integer_get(vpid_value
, &value
)
453 == BT_VALUE_STATUS_OK
) {
454 g_string_append_printf(pretty
->string
, "(%" PRId64
")", value
);
460 if (pretty
->options
.print_loglevel_field
) {
461 static const char *log_level_names
[] = {
462 [ BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
] = "TRACE_EMERG",
463 [ BT_EVENT_CLASS_LOG_LEVEL_ALERT
] = "TRACE_ALERT",
464 [ BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
] = "TRACE_CRIT",
465 [ BT_EVENT_CLASS_LOG_LEVEL_ERROR
] = "TRACE_ERR",
466 [ BT_EVENT_CLASS_LOG_LEVEL_WARNING
] = "TRACE_WARNING",
467 [ BT_EVENT_CLASS_LOG_LEVEL_NOTICE
] = "TRACE_NOTICE",
468 [ BT_EVENT_CLASS_LOG_LEVEL_INFO
] = "TRACE_INFO",
469 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
] = "TRACE_DEBUG_SYSTEM",
470 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
] = "TRACE_DEBUG_PROGRAM",
471 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
] = "TRACE_DEBUG_PROCESS",
472 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
] = "TRACE_DEBUG_MODULE",
473 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
] = "TRACE_DEBUG_UNIT",
474 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
] = "TRACE_DEBUG_FUNCTION",
475 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
] = "TRACE_DEBUG_LINE",
476 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG
] = "TRACE_DEBUG",
478 enum bt_event_class_log_level log_level
;
479 const char *log_level_str
= NULL
;
481 prop_avail
= bt_event_class_get_log_level(event_class
,
483 if (prop_avail
== BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
484 log_level_str
= log_level_names
[log_level
];
485 BT_ASSERT(log_level_str
);
487 if (!pretty
->start_line
) {
488 g_string_append(pretty
->string
, ", ");
491 print_name_equal(pretty
, "loglevel");
492 } else if (dom_print
) {
493 g_string_append(pretty
->string
, ":");
496 g_string_append(pretty
->string
, log_level_str
);
497 g_string_append_printf(
498 pretty
->string
, " (%d)", (int) log_level
);
502 if (pretty
->options
.print_emf_field
) {
505 uri_str
= bt_event_class_get_emf_uri(event_class
);
507 if (!pretty
->start_line
) {
508 g_string_append(pretty
->string
, ", ");
511 print_name_equal(pretty
, "model.emf.uri");
512 } else if (dom_print
) {
513 g_string_append(pretty
->string
, ":");
516 g_string_append(pretty
->string
, uri_str
);
520 if (dom_print
&& !print_names
) {
521 g_string_append(pretty
->string
, " ");
523 if (!pretty
->start_line
) {
524 g_string_append(pretty
->string
, ", ");
526 pretty
->start_line
= true;
528 print_name_equal(pretty
, "name");
530 if (pretty
->use_colors
) {
531 g_string_append(pretty
->string
, COLOR_EVENT_NAME
);
533 g_string_append(pretty
->string
, bt_event_class_get_name(event_class
));
534 if (pretty
->use_colors
) {
535 g_string_append(pretty
->string
, COLOR_RST
);
538 g_string_append(pretty
->string
, ": ");
540 g_string_append(pretty
->string
, ", ");
548 enum bt_component_status
print_integer(struct pretty_component
*pretty
,
549 struct bt_field
*field
)
551 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
552 enum bt_field_type_integer_preferred_display_base base
;
553 struct bt_field_type
*int_ft
;
558 bool rst_color
= false;
559 enum bt_field_type_id ft_id
;
561 int_ft
= bt_field_borrow_type(field
);
563 ft_id
= bt_field_get_type_id(field
);
564 if (ft_id
== BT_FIELD_TYPE_ID_UNSIGNED_INTEGER
||
565 ft_id
== BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION
) {
566 v
.u
= bt_field_unsigned_integer_get_value(field
);
568 v
.s
= bt_field_signed_integer_get_value(field
);
571 if (pretty
->use_colors
) {
572 g_string_append(pretty
->string
, COLOR_NUMBER_VALUE
);
576 base
= bt_field_type_integer_get_preferred_display_base(int_ft
);
578 case BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
:
582 len
= bt_field_type_integer_get_field_value_range(int_ft
);
583 g_string_append(pretty
->string
, "0b");
584 v
.u
= _bt_piecewise_lshift(v
.u
, 64 - len
);
585 for (bitnr
= 0; bitnr
< len
; bitnr
++) {
586 g_string_append_printf(pretty
->string
, "%u", (v
.u
& (1ULL << 63)) ? 1 : 0);
587 v
.u
= _bt_piecewise_lshift(v
.u
, 1);
591 case BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
:
593 if (ft_id
== BT_FIELD_TYPE_ID_SIGNED_INTEGER
||
594 ft_id
== BT_FIELD_TYPE_ID_SIGNED_ENUMERATION
) {
597 len
= bt_field_type_integer_get_field_value_range(
603 /* Round length to the nearest 3-bit */
604 rounded_len
= (((len
- 1) / 3) + 1) * 3;
605 v
.u
&= ((uint64_t) 1 << rounded_len
) - 1;
609 g_string_append_printf(pretty
->string
, "0%" PRIo64
, v
.u
);
612 case BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
:
613 if (ft_id
== BT_FIELD_TYPE_ID_UNSIGNED_INTEGER
||
614 ft_id
== BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION
) {
615 g_string_append_printf(pretty
->string
, "%" PRIu64
, v
.u
);
617 g_string_append_printf(pretty
->string
, "%" PRId64
, v
.s
);
620 case BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
:
624 len
= bt_field_type_integer_get_field_value_range(int_ft
);
626 /* Round length to the nearest nibble */
627 uint8_t rounded_len
= ((len
+ 3) & ~0x3);
629 v
.u
&= ((uint64_t) 1 << rounded_len
) - 1;
632 g_string_append_printf(pretty
->string
, "0x%" PRIX64
, v
.u
);
636 ret
= BT_COMPONENT_STATUS_ERROR
;
641 g_string_append(pretty
->string
, COLOR_RST
);
647 void print_escape_string(struct pretty_component
*pretty
, const char *str
)
651 g_string_append_c(pretty
->string
, '"');
653 for (i
= 0; i
< strlen(str
); i
++) {
654 /* Escape sequences not recognized by iscntrl(). */
657 g_string_append(pretty
->string
, "\\\\");
660 g_string_append(pretty
->string
, "\\\'");
663 g_string_append(pretty
->string
, "\\\"");
666 g_string_append(pretty
->string
, "\\\?");
670 /* Standard characters. */
671 if (!iscntrl(str
[i
])) {
672 g_string_append_c(pretty
->string
, str
[i
]);
678 g_string_append(pretty
->string
, "\\0");
681 g_string_append(pretty
->string
, "\\a");
684 g_string_append(pretty
->string
, "\\b");
687 g_string_append(pretty
->string
, "\\e");
690 g_string_append(pretty
->string
, "\\f");
693 g_string_append(pretty
->string
, "\\n");
696 g_string_append(pretty
->string
, "\\r");
699 g_string_append(pretty
->string
, "\\t");
702 g_string_append(pretty
->string
, "\\v");
705 /* Unhandled control-sequence, print as hex. */
706 g_string_append_printf(pretty
->string
, "\\x%02x", str
[i
]);
711 g_string_append_c(pretty
->string
, '"');
715 enum bt_component_status
print_enum(struct pretty_component
*pretty
,
716 struct bt_field
*field
)
718 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
719 struct bt_field_type
*enumeration_field_type
= NULL
;
720 bt_field_type_enumeration_mapping_label_array label_array
;
721 uint64_t label_count
;
724 enumeration_field_type
= bt_field_borrow_type(field
);
725 if (!enumeration_field_type
) {
726 ret
= BT_COMPONENT_STATUS_ERROR
;
730 switch (bt_field_get_type_id(field
)) {
731 case BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION
:
732 ret
= bt_field_unsigned_enumeration_get_mapping_labels(field
,
733 &label_array
, &label_count
);
735 case BT_FIELD_TYPE_ID_SIGNED_ENUMERATION
:
736 ret
= bt_field_signed_enumeration_get_mapping_labels(field
,
737 &label_array
, &label_count
);
744 ret
= BT_COMPONENT_STATUS_ERROR
;
748 g_string_append(pretty
->string
, "( ");
749 if (label_count
== 0) {
750 if (pretty
->use_colors
) {
751 g_string_append(pretty
->string
, COLOR_UNKNOWN
);
753 g_string_append(pretty
->string
, "<unknown>");
754 if (pretty
->use_colors
) {
755 g_string_append(pretty
->string
, COLOR_RST
);
759 for (i
= 0; i
< label_count
; i
++) {
760 const char *mapping_name
= label_array
[i
];
763 g_string_append(pretty
->string
, ", ");
765 if (pretty
->use_colors
) {
766 g_string_append(pretty
->string
, COLOR_ENUM_MAPPING_NAME
);
768 print_escape_string(pretty
, mapping_name
);
769 if (pretty
->use_colors
) {
770 g_string_append(pretty
->string
, COLOR_RST
);
774 g_string_append(pretty
->string
, " : container = ");
775 ret
= print_integer(pretty
, field
);
776 if (ret
!= BT_COMPONENT_STATUS_OK
) {
779 g_string_append(pretty
->string
, " )");
785 int filter_field_name(struct pretty_component
*pretty
, const char *field_name
,
786 GQuark
*filter_fields
, int filter_array_len
)
789 GQuark field_quark
= g_quark_try_string(field_name
);
791 if (!field_quark
|| pretty
->options
.verbose
) {
795 for (i
= 0; i
< filter_array_len
; i
++) {
796 if (field_quark
== filter_fields
[i
]) {
804 enum bt_component_status
print_struct_field(struct pretty_component
*pretty
,
805 struct bt_field
*_struct
,
806 struct bt_field_type
*struct_type
,
807 uint64_t i
, bool print_names
, uint64_t *nr_printed_fields
,
808 GQuark
*filter_fields
, int filter_array_len
)
810 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
811 const char *field_name
;
812 struct bt_field
*field
= NULL
;
813 struct bt_field_type
*field_type
= NULL
;;
815 field
= bt_field_structure_borrow_member_field_by_index(_struct
, i
);
817 ret
= BT_COMPONENT_STATUS_ERROR
;
821 bt_field_type_structure_borrow_member_by_index(struct_type
, i
,
822 &field_name
, &field_type
);
824 if (filter_fields
&& !filter_field_name(pretty
, field_name
,
825 filter_fields
, filter_array_len
)) {
826 ret
= BT_COMPONENT_STATUS_OK
;
830 if (*nr_printed_fields
> 0) {
831 g_string_append(pretty
->string
, ", ");
833 g_string_append(pretty
->string
, " ");
836 print_field_name_equal(pretty
, field_name
);
838 ret
= print_field(pretty
, field
, print_names
, NULL
, 0);
839 *nr_printed_fields
+= 1;
846 enum bt_component_status
print_struct(struct pretty_component
*pretty
,
847 struct bt_field
*_struct
, bool print_names
,
848 GQuark
*filter_fields
, int filter_array_len
)
850 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
851 struct bt_field_type
*struct_type
= NULL
;
852 uint64_t nr_fields
, i
, nr_printed_fields
;
854 struct_type
= bt_field_borrow_type(_struct
);
856 ret
= BT_COMPONENT_STATUS_ERROR
;
859 nr_fields
= bt_field_type_structure_get_member_count(struct_type
);
861 ret
= BT_COMPONENT_STATUS_ERROR
;
864 g_string_append(pretty
->string
, "{");
866 nr_printed_fields
= 0;
867 for (i
= 0; i
< nr_fields
; i
++) {
868 ret
= print_struct_field(pretty
, _struct
, struct_type
, i
,
869 print_names
, &nr_printed_fields
, filter_fields
,
871 if (ret
!= BT_COMPONENT_STATUS_OK
) {
876 g_string_append(pretty
->string
, " }");
883 enum bt_component_status
print_array_field(struct pretty_component
*pretty
,
884 struct bt_field
*array
, uint64_t i
, bool print_names
)
886 struct bt_field
*field
= NULL
;
889 g_string_append(pretty
->string
, ", ");
891 g_string_append(pretty
->string
, " ");
894 g_string_append_printf(pretty
->string
, "[%" PRIu64
"] = ", i
);
897 field
= bt_field_array_borrow_element_field_by_index(array
, i
);
899 return print_field(pretty
, field
, print_names
, NULL
, 0);
903 enum bt_component_status
print_array(struct pretty_component
*pretty
,
904 struct bt_field
*array
, bool print_names
)
906 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
907 struct bt_field_type
*array_type
= NULL
;
911 array_type
= bt_field_borrow_type(array
);
913 ret
= BT_COMPONENT_STATUS_ERROR
;
916 len
= bt_field_array_get_length(array
);
917 g_string_append(pretty
->string
, "[");
919 for (i
= 0; i
< len
; i
++) {
920 ret
= print_array_field(pretty
, array
, i
, print_names
);
921 if (ret
!= BT_COMPONENT_STATUS_OK
) {
926 g_string_append(pretty
->string
, " ]");
933 enum bt_component_status
print_sequence_field(struct pretty_component
*pretty
,
934 struct bt_field
*seq
, uint64_t i
, bool print_names
)
936 struct bt_field
*field
= NULL
;
939 g_string_append(pretty
->string
, ", ");
941 g_string_append(pretty
->string
, " ");
944 g_string_append_printf(pretty
->string
, "[%" PRIu64
"] = ", i
);
947 field
= bt_field_array_borrow_element_field_by_index(seq
, i
);
949 return print_field(pretty
, field
, print_names
, NULL
, 0);
953 enum bt_component_status
print_sequence(struct pretty_component
*pretty
,
954 struct bt_field
*seq
, bool print_names
)
956 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
960 len
= bt_field_array_get_length(seq
);
962 ret
= BT_COMPONENT_STATUS_ERROR
;
966 g_string_append(pretty
->string
, "[");
969 for (i
= 0; i
< len
; i
++) {
970 ret
= print_sequence_field(pretty
, seq
, i
, print_names
);
971 if (ret
!= BT_COMPONENT_STATUS_OK
) {
976 g_string_append(pretty
->string
, " ]");
983 enum bt_component_status
print_variant(struct pretty_component
*pretty
,
984 struct bt_field
*variant
, bool print_names
)
986 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
987 struct bt_field
*field
= NULL
;
989 field
= bt_field_variant_borrow_selected_option_field(variant
);
991 g_string_append(pretty
->string
, "{ ");
994 // TODO: find tag's name using field path
995 // print_field_name_equal(pretty, tag_choice);
997 ret
= print_field(pretty
, field
, print_names
, NULL
, 0);
998 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1002 g_string_append(pretty
->string
, " }");
1009 enum bt_component_status
print_field(struct pretty_component
*pretty
,
1010 struct bt_field
*field
, bool print_names
,
1011 GQuark
*filter_fields
, int filter_array_len
)
1013 enum bt_field_type_id type_id
;
1015 type_id
= bt_field_get_type_id(field
);
1017 case BT_FIELD_TYPE_ID_UNSIGNED_INTEGER
:
1018 case BT_FIELD_TYPE_ID_SIGNED_INTEGER
:
1019 return print_integer(pretty
, field
);
1020 case BT_FIELD_TYPE_ID_REAL
:
1024 v
= bt_field_real_get_value(field
);
1025 if (pretty
->use_colors
) {
1026 g_string_append(pretty
->string
, COLOR_NUMBER_VALUE
);
1028 g_string_append_printf(pretty
->string
, "%g", v
);
1029 if (pretty
->use_colors
) {
1030 g_string_append(pretty
->string
, COLOR_RST
);
1032 return BT_COMPONENT_STATUS_OK
;
1034 case BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION
:
1035 case BT_FIELD_TYPE_ID_SIGNED_ENUMERATION
:
1036 return print_enum(pretty
, field
);
1037 case BT_FIELD_TYPE_ID_STRING
:
1041 str
= bt_field_string_get_value(field
);
1043 return BT_COMPONENT_STATUS_ERROR
;
1046 if (pretty
->use_colors
) {
1047 g_string_append(pretty
->string
, COLOR_STRING_VALUE
);
1049 print_escape_string(pretty
, str
);
1050 if (pretty
->use_colors
) {
1051 g_string_append(pretty
->string
, COLOR_RST
);
1053 return BT_COMPONENT_STATUS_OK
;
1055 case BT_FIELD_TYPE_ID_STRUCTURE
:
1056 return print_struct(pretty
, field
, print_names
, filter_fields
,
1058 case BT_FIELD_TYPE_ID_VARIANT
:
1059 return print_variant(pretty
, field
, print_names
);
1060 case BT_FIELD_TYPE_ID_STATIC_ARRAY
:
1061 return print_array(pretty
, field
, print_names
);
1062 case BT_FIELD_TYPE_ID_DYNAMIC_ARRAY
:
1063 return print_sequence(pretty
, field
, print_names
);
1065 // TODO: log instead
1066 fprintf(pretty
->err
, "[error] Unknown type id: %d\n", (int) type_id
);
1067 return BT_COMPONENT_STATUS_ERROR
;
1072 enum bt_component_status
print_stream_packet_context(struct pretty_component
*pretty
,
1073 struct bt_event
*event
)
1075 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1076 struct bt_packet
*packet
= NULL
;
1077 struct bt_field
*main_field
= NULL
;
1079 packet
= bt_event_borrow_packet(event
);
1081 ret
= BT_COMPONENT_STATUS_ERROR
;
1084 main_field
= bt_packet_borrow_context_field(packet
);
1088 if (!pretty
->start_line
) {
1089 g_string_append(pretty
->string
, ", ");
1091 pretty
->start_line
= false;
1092 if (pretty
->options
.print_scope_field_names
) {
1093 print_name_equal(pretty
, "stream.packet.context");
1095 ret
= print_field(pretty
, main_field
,
1096 pretty
->options
.print_context_field_names
,
1097 stream_packet_context_quarks
,
1098 STREAM_PACKET_CONTEXT_QUARKS_LEN
);
1105 enum bt_component_status
print_event_header_raw(struct pretty_component
*pretty
,
1106 struct bt_event
*event
)
1108 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1109 struct bt_field
*main_field
= NULL
;
1111 main_field
= bt_event_borrow_header_field(event
);
1115 if (!pretty
->start_line
) {
1116 g_string_append(pretty
->string
, ", ");
1118 pretty
->start_line
= false;
1119 if (pretty
->options
.print_scope_field_names
) {
1120 print_name_equal(pretty
, "stream.event.header");
1122 ret
= print_field(pretty
, main_field
,
1123 pretty
->options
.print_header_field_names
, NULL
, 0);
1130 enum bt_component_status
print_stream_event_context(struct pretty_component
*pretty
,
1131 struct bt_event
*event
)
1133 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1134 struct bt_field
*main_field
= NULL
;
1136 main_field
= bt_event_borrow_common_context_field(event
);
1140 if (!pretty
->start_line
) {
1141 g_string_append(pretty
->string
, ", ");
1143 pretty
->start_line
= false;
1144 if (pretty
->options
.print_scope_field_names
) {
1145 print_name_equal(pretty
, "stream.event.context");
1147 ret
= print_field(pretty
, main_field
,
1148 pretty
->options
.print_context_field_names
, NULL
, 0);
1155 enum bt_component_status
print_event_context(struct pretty_component
*pretty
,
1156 struct bt_event
*event
)
1158 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1159 struct bt_field
*main_field
= NULL
;
1161 main_field
= bt_event_borrow_specific_context_field(event
);
1165 if (!pretty
->start_line
) {
1166 g_string_append(pretty
->string
, ", ");
1168 pretty
->start_line
= false;
1169 if (pretty
->options
.print_scope_field_names
) {
1170 print_name_equal(pretty
, "event.context");
1172 ret
= print_field(pretty
, main_field
,
1173 pretty
->options
.print_context_field_names
, NULL
, 0);
1180 enum bt_component_status
print_event_payload(struct pretty_component
*pretty
,
1181 struct bt_event
*event
)
1183 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1184 struct bt_field
*main_field
= NULL
;
1186 main_field
= bt_event_borrow_payload_field(event
);
1190 if (!pretty
->start_line
) {
1191 g_string_append(pretty
->string
, ", ");
1193 pretty
->start_line
= false;
1194 if (pretty
->options
.print_scope_field_names
) {
1195 print_name_equal(pretty
, "event.fields");
1197 ret
= print_field(pretty
, main_field
,
1198 pretty
->options
.print_payload_field_names
, NULL
, 0);
1205 int flush_buf(FILE *stream
, struct pretty_component
*pretty
)
1209 if (pretty
->string
->len
== 0) {
1213 if (fwrite(pretty
->string
->str
, pretty
->string
->len
, 1, stream
) != 1) {
1222 enum bt_component_status
pretty_print_event(struct pretty_component
*pretty
,
1223 struct bt_notification
*event_notif
)
1225 enum bt_component_status ret
;
1226 struct bt_event
*event
=
1227 bt_notification_event_borrow_event(event_notif
);
1230 pretty
->start_line
= true;
1231 g_string_assign(pretty
->string
, "");
1232 ret
= print_event_header(pretty
, event
);
1233 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1237 ret
= print_stream_packet_context(pretty
, event
);
1238 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1242 if (pretty
->options
.verbose
) {
1243 ret
= print_event_header_raw(pretty
, event
);
1244 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1249 ret
= print_stream_event_context(pretty
, event
);
1250 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1254 ret
= print_event_context(pretty
, event
);
1255 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1259 ret
= print_event_payload(pretty
, event
);
1260 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1264 g_string_append_c(pretty
->string
, '\n');
1265 if (flush_buf(pretty
->out
, pretty
)) {
1266 ret
= BT_COMPONENT_STATUS_ERROR
;
1275 enum bt_component_status
print_discarded_elements_msg(
1276 struct pretty_component
*pretty
, struct bt_packet
*packet
,
1277 uint64_t count
, const char *elem_type
)
1280 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1281 struct bt_stream
*stream
= NULL
;
1282 struct bt_stream_class
*stream_class
= NULL
;
1283 struct bt_trace
*trace
= NULL
;
1284 const char *stream_name
;
1285 const char *trace_name
;
1286 const unsigned char *trace_uuid
;
1287 int64_t stream_class_id
;
1289 struct bt_clock_value
*begin_clock_value
= NULL
;
1290 struct bt_clock_value
*end_clock_value
= NULL
;
1294 stream
= bt_packet_borrow_stream(packet
);
1296 stream_name
= bt_stream_get_name(stream
);
1298 /* Stream class ID */
1299 stream_class
= bt_stream_borrow_class(stream
);
1300 BT_ASSERT(stream_class
);
1301 stream_class_id
= bt_stream_class_get_id(stream_class
);
1304 stream_id
= bt_stream_get_id(stream
);
1307 trace
= bt_stream_class_borrow_trace(stream_class
);
1309 trace_name
= bt_trace_get_name(trace
);
1311 trace_name
= "(unknown)";
1315 trace_uuid
= bt_trace_get_uuid(trace
);
1317 /* Beginning and end times */
1318 (void) bt_packet_borrow_previous_packet_default_end_clock_value(
1319 packet
, &begin_clock_value
);
1320 (void) bt_packet_borrow_default_end_clock_value(packet
,
1323 /* Format message */
1324 g_string_assign(pretty
->string
, "");
1325 g_string_append_printf(pretty
->string
,
1326 "%s%sWARNING%s%s: Tracer discarded %" PRId64
" %s%s ",
1327 bt_common_color_fg_yellow(),
1328 bt_common_color_bold(),
1329 bt_common_color_reset(),
1330 bt_common_color_fg_yellow(),
1331 count
, elem_type
, count
== 1 ? "" : "s");
1333 if (begin_clock_value
&& end_clock_value
) {
1334 g_string_append(pretty
->string
, "between [");
1335 print_timestamp_wall(pretty
, begin_clock_value
);
1336 g_string_append(pretty
->string
, "] and [");
1337 print_timestamp_wall(pretty
, end_clock_value
);
1338 g_string_append(pretty
->string
, "]");
1340 g_string_append(pretty
->string
, "(unknown time range)");
1343 g_string_append_printf(pretty
->string
, " in trace \"%s\" ", trace_name
);
1346 g_string_append_printf(pretty
->string
,
1347 "(UUID: %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x) ",
1365 g_string_append(pretty
->string
, "(no UUID) ");
1368 g_string_append_printf(pretty
->string
,
1369 "within stream \"%s\" (stream class ID: %" PRId64
", ",
1370 stream_name
, stream_class_id
);
1372 if (stream_id
>= 0) {
1373 g_string_append_printf(pretty
->string
,
1374 "stream ID: %" PRId64
, stream_id
);
1376 g_string_append(pretty
->string
, "no stream ID");
1379 g_string_append_printf(pretty
->string
, ").%s\n",
1380 bt_common_color_reset());
1383 * Print to standard error stream to remain backward compatible
1384 * with Babeltrace 1.
1386 if (flush_buf(stderr
, pretty
)) {
1387 ret
= BT_COMPONENT_STATUS_ERROR
;
1396 enum bt_component_status
pretty_print_packet(struct pretty_component
*pretty
,
1397 struct bt_notification
*packet_beginning_notif
)
1400 struct bt_packet
*packet
= bt_notification_packet_begin_borrow_packet(
1401 packet_beginning_notif
);
1403 enum bt_component_status status
= BT_COMPONENT_STATUS_OK
;
1405 if (bt_packet_get_discarded_event_count(packet
, &count
) ==
1406 BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE
&&
1408 status
= print_discarded_elements_msg(pretty
, packet
,
1410 if (status
!= BT_COMPONENT_STATUS_OK
) {
1415 if (bt_packet_get_discarded_packet_count(packet
, &count
) ==
1416 BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE
&&
1418 status
= print_discarded_elements_msg(pretty
, packet
,
1420 if (status
!= BT_COMPONENT_STATUS_OK
) {