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/ctf-ir/event.h>
31 #include <babeltrace/ctf-ir/event-class.h>
32 #include <babeltrace/ctf-ir/packet.h>
33 #include <babeltrace/ctf-ir/stream.h>
34 #include <babeltrace/ctf-ir/stream-class.h>
35 #include <babeltrace/ctf-ir/clock-class.h>
36 #include <babeltrace/ctf-ir/field-types.h>
37 #include <babeltrace/ctf-ir/fields.h>
38 #include <babeltrace/ctf-ir/trace.h>
39 #include <babeltrace/graph/notification-event.h>
40 #include <babeltrace/graph/clock-class-priority-map.h>
41 #include <babeltrace/bitfield-internal.h>
42 #include <babeltrace/common-internal.h>
47 #define NSEC_PER_SEC 1000000000LL
49 #define COLOR_NAME BT_COMMON_COLOR_BOLD
50 #define COLOR_FIELD_NAME BT_COMMON_COLOR_FG_CYAN
51 #define COLOR_RST BT_COMMON_COLOR_RESET
52 #define COLOR_STRING_VALUE BT_COMMON_COLOR_BOLD
53 #define COLOR_NUMBER_VALUE BT_COMMON_COLOR_BOLD
54 #define COLOR_ENUM_MAPPING_NAME BT_COMMON_COLOR_BOLD
55 #define COLOR_UNKNOWN BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_RED
56 #define COLOR_EVENT_NAME BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_MAGENTA
57 #define COLOR_TIMESTAMP BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_YELLOW
60 const char *rem_(const char *str
)
69 int64_t real_timestamp
; /* Relative to UNIX epoch. */
70 uint64_t clock_value
; /* In cycles. */
74 enum bt_component_status
print_field(struct pretty_component
*pretty
,
75 struct bt_ctf_field
*field
, bool print_names
,
76 GQuark
*filters_fields
, int filter_array_len
);
79 void print_name_equal(struct pretty_component
*pretty
, const char *name
)
81 if (pretty
->use_colors
) {
82 g_string_append_printf(pretty
->string
, "%s%s%s = ", COLOR_NAME
,
85 g_string_append_printf(pretty
->string
, "%s = ", name
);
90 void print_field_name_equal(struct pretty_component
*pretty
, const char *name
)
92 if (pretty
->use_colors
) {
93 g_string_append_printf(pretty
->string
, "%s%s%s = ",
94 COLOR_FIELD_NAME
, name
, COLOR_RST
);
96 g_string_append_printf(pretty
->string
, "%s = ", name
);
101 void print_timestamp_cycles(struct pretty_component
*pretty
,
102 struct bt_ctf_clock_class
*clock_class
,
103 struct bt_ctf_event
*event
)
106 struct bt_ctf_clock_value
*clock_value
;
109 clock_value
= bt_ctf_event_get_clock_value(event
, clock_class
);
111 g_string_append(pretty
->string
, "????????????????????");
115 ret
= bt_ctf_clock_value_get_value(clock_value
, &cycles
);
118 // TODO: log, this is unexpected
119 g_string_append(pretty
->string
, "Error");
123 g_string_append_printf(pretty
->string
, "%020" PRIu64
, cycles
);
125 if (pretty
->last_cycles_timestamp
!= -1ULL) {
126 pretty
->delta_cycles
= cycles
- pretty
->last_cycles_timestamp
;
128 pretty
->last_cycles_timestamp
= cycles
;
132 void print_timestamp_wall(struct pretty_component
*pretty
,
133 struct bt_ctf_clock_class
*clock_class
,
134 struct bt_ctf_event
*event
)
137 struct bt_ctf_clock_value
*clock_value
;
138 int64_t ts_nsec
= 0; /* add configurable offset */
139 int64_t ts_sec
= 0; /* add configurable offset */
140 uint64_t ts_sec_abs
, ts_nsec_abs
;
143 clock_value
= bt_ctf_event_get_clock_value(event
, clock_class
);
145 g_string_append(pretty
->string
, "??:??:??.?????????");
149 ret
= bt_ctf_clock_value_get_value_ns_from_epoch(clock_value
, &ts_nsec
);
152 // TODO: log, this is unexpected
153 g_string_append(pretty
->string
, "Error");
157 if (pretty
->last_real_timestamp
!= -1ULL) {
158 pretty
->delta_real_timestamp
= ts_nsec
- pretty
->last_real_timestamp
;
161 pretty
->last_real_timestamp
= ts_nsec
;
162 ts_sec
+= ts_nsec
/ NSEC_PER_SEC
;
163 ts_nsec
= ts_nsec
% NSEC_PER_SEC
;
165 if (ts_sec
>= 0 && ts_nsec
>= 0) {
168 ts_nsec_abs
= ts_nsec
;
169 } else if (ts_sec
> 0 && ts_nsec
< 0) {
171 ts_sec_abs
= ts_sec
- 1;
172 ts_nsec_abs
= NSEC_PER_SEC
+ ts_nsec
;
173 } else if (ts_sec
== 0 && ts_nsec
< 0) {
176 ts_nsec_abs
= -ts_nsec
;
177 } else if (ts_sec
< 0 && ts_nsec
> 0) {
179 ts_sec_abs
= -(ts_sec
+ 1);
180 ts_nsec_abs
= NSEC_PER_SEC
- ts_nsec
;
181 } else if (ts_sec
< 0 && ts_nsec
== 0) {
183 ts_sec_abs
= -ts_sec
;
184 ts_nsec_abs
= ts_nsec
;
185 } else { /* (ts_sec < 0 && ts_nsec < 0) */
187 ts_sec_abs
= -ts_sec
;
188 ts_nsec_abs
= -ts_nsec
;
191 if (!pretty
->options
.clock_seconds
) {
193 time_t time_s
= (time_t) ts_sec_abs
;
197 fprintf(stderr
, "[warning] Fallback to [sec.ns] to print negative time value. Use --clock-seconds.\n");
201 if (!pretty
->options
.clock_gmt
) {
204 res
= localtime_r(&time_s
, &tm
);
207 fprintf(stderr
, "[warning] Unable to get localtime.\n");
213 res
= gmtime_r(&time_s
, &tm
);
216 fprintf(stderr
, "[warning] Unable to get gmtime.\n");
220 if (pretty
->options
.clock_date
) {
224 /* Print date and time */
225 res
= strftime(timestr
, sizeof(timestr
),
229 fprintf(stderr
, "[warning] Unable to print ascii time.\n");
233 g_string_append(pretty
->string
, timestr
);
236 /* Print time in HH:MM:SS.ns */
237 g_string_append_printf(pretty
->string
,
238 "%02d:%02d:%02d.%09" PRIu64
, tm
.tm_hour
, tm
.tm_min
,
239 tm
.tm_sec
, ts_nsec_abs
);
243 g_string_append_printf(pretty
->string
, "%s%" PRId64
".%09" PRIu64
,
244 is_negative
? "-" : "", ts_sec_abs
, ts_nsec_abs
);
250 enum bt_component_status
print_event_timestamp(struct pretty_component
*pretty
,
251 struct bt_ctf_event
*event
,
252 struct bt_clock_class_priority_map
*cc_prio_map
,
255 bool print_names
= pretty
->options
.print_header_field_names
;
256 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
257 struct bt_ctf_stream
*stream
= NULL
;
258 struct bt_ctf_stream_class
*stream_class
= NULL
;
259 struct bt_ctf_trace
*trace
= NULL
;
260 struct bt_ctf_clock_class
*clock_class
= NULL
;
262 stream
= bt_ctf_event_get_stream(event
);
264 ret
= BT_COMPONENT_STATUS_ERROR
;
268 stream_class
= bt_ctf_stream_get_class(stream
);
270 ret
= BT_COMPONENT_STATUS_ERROR
;
273 trace
= bt_ctf_stream_class_get_trace(stream_class
);
275 ret
= BT_COMPONENT_STATUS_ERROR
;
279 if (bt_clock_class_priority_map_get_clock_class_count(cc_prio_map
) == 0) {
280 /* No clock class: skip the timestamp without an error */
285 bt_clock_class_priority_map_get_highest_priority_clock_class(
288 ret
= BT_COMPONENT_STATUS_ERROR
;
293 print_name_equal(pretty
, "timestamp");
295 g_string_append(pretty
->string
, "[");
297 if (pretty
->use_colors
) {
298 g_string_append(pretty
->string
, COLOR_TIMESTAMP
);
300 if (pretty
->options
.print_timestamp_cycles
) {
301 print_timestamp_cycles(pretty
, clock_class
, event
);
303 print_timestamp_wall(pretty
, clock_class
, event
);
305 if (pretty
->use_colors
) {
306 g_string_append(pretty
->string
, COLOR_RST
);
310 g_string_append(pretty
->string
, "] ");
312 if (pretty
->options
.print_delta_field
) {
314 g_string_append(pretty
->string
, ", ");
315 print_name_equal(pretty
, "delta");
317 g_string_append(pretty
->string
, "(");
319 if (pretty
->options
.print_timestamp_cycles
) {
320 if (pretty
->delta_cycles
== -1ULL) {
321 g_string_append(pretty
->string
,
322 "+??????????\?\?) "); /* Not a trigraph. */
324 g_string_append_printf(pretty
->string
,
325 "+%012" PRIu64
, pretty
->delta_cycles
);
328 if (pretty
->delta_real_timestamp
!= -1ULL) {
329 uint64_t delta_sec
, delta_nsec
, delta
;
331 delta
= pretty
->delta_real_timestamp
;
332 delta_sec
= delta
/ NSEC_PER_SEC
;
333 delta_nsec
= delta
% NSEC_PER_SEC
;
334 g_string_append_printf(pretty
->string
,
335 "+%" PRIu64
".%09" PRIu64
,
336 delta_sec
, delta_nsec
);
338 g_string_append(pretty
->string
, "+?.?????????");
342 g_string_append(pretty
->string
, ") ");
345 *start_line
= !print_names
;
350 bt_put(stream_class
);
356 enum bt_component_status
print_event_header(struct pretty_component
*pretty
,
357 struct bt_ctf_event
*event
,
358 struct bt_clock_class_priority_map
*cc_prio_map
)
360 bool print_names
= pretty
->options
.print_header_field_names
;
361 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
362 struct bt_ctf_event_class
*event_class
= NULL
;
363 struct bt_ctf_stream_class
*stream_class
= NULL
;
364 struct bt_ctf_trace
*trace_class
= NULL
;
367 event_class
= bt_ctf_event_get_class(event
);
369 ret
= BT_COMPONENT_STATUS_ERROR
;
372 stream_class
= bt_ctf_event_class_get_stream_class(event_class
);
374 ret
= BT_COMPONENT_STATUS_ERROR
;
377 trace_class
= bt_ctf_stream_class_get_trace(stream_class
);
379 ret
= BT_COMPONENT_STATUS_ERROR
;
382 ret
= print_event_timestamp(pretty
, event
, cc_prio_map
,
383 &pretty
->start_line
);
384 if (ret
!= BT_COMPONENT_STATUS_OK
) {
387 if (pretty
->options
.print_trace_field
) {
390 name
= bt_ctf_trace_get_name(trace_class
);
392 if (!pretty
->start_line
) {
393 g_string_append(pretty
->string
, ", ");
396 print_name_equal(pretty
, "trace");
399 g_string_append(pretty
->string
, name
);
402 g_string_append(pretty
->string
, " ");
406 if (pretty
->options
.print_trace_hostname_field
) {
407 struct bt_value
*hostname_str
;
409 hostname_str
= bt_ctf_trace_get_environment_field_value_by_name(trace_class
,
414 if (!pretty
->start_line
) {
415 g_string_append(pretty
->string
, ", ");
418 print_name_equal(pretty
, "trace:hostname");
420 if (bt_value_string_get(hostname_str
, &str
)
421 == BT_VALUE_STATUS_OK
) {
422 g_string_append(pretty
->string
, str
);
424 bt_put(hostname_str
);
428 if (pretty
->options
.print_trace_domain_field
) {
429 struct bt_value
*domain_str
;
431 domain_str
= bt_ctf_trace_get_environment_field_value_by_name(trace_class
,
436 if (!pretty
->start_line
) {
437 g_string_append(pretty
->string
, ", ");
440 print_name_equal(pretty
, "trace:domain");
441 } else if (dom_print
) {
442 g_string_append(pretty
->string
, ":");
444 if (bt_value_string_get(domain_str
, &str
)
445 == BT_VALUE_STATUS_OK
) {
446 g_string_append(pretty
->string
, str
);
452 if (pretty
->options
.print_trace_procname_field
) {
453 struct bt_value
*procname_str
;
455 procname_str
= bt_ctf_trace_get_environment_field_value_by_name(trace_class
,
460 if (!pretty
->start_line
) {
461 g_string_append(pretty
->string
, ", ");
464 print_name_equal(pretty
, "trace:procname");
465 } else if (dom_print
) {
466 g_string_append(pretty
->string
, ":");
468 if (bt_value_string_get(procname_str
, &str
)
469 == BT_VALUE_STATUS_OK
) {
470 g_string_append(pretty
->string
, str
);
472 bt_put(procname_str
);
476 if (pretty
->options
.print_trace_vpid_field
) {
477 struct bt_value
*vpid_value
;
479 vpid_value
= bt_ctf_trace_get_environment_field_value_by_name(trace_class
,
484 if (!pretty
->start_line
) {
485 g_string_append(pretty
->string
, ", ");
488 print_name_equal(pretty
, "trace:vpid");
489 } else if (dom_print
) {
490 g_string_append(pretty
->string
, ":");
492 if (bt_value_integer_get(vpid_value
, &value
)
493 == BT_VALUE_STATUS_OK
) {
494 g_string_append_printf(pretty
->string
, "(%" PRId64
")", value
);
500 if (pretty
->options
.print_loglevel_field
) {
501 struct bt_value
*loglevel_str
, *loglevel_value
;
503 loglevel_str
= bt_ctf_event_class_get_attribute_value_by_name(event_class
,
505 loglevel_value
= bt_ctf_event_class_get_attribute_value_by_name(event_class
,
507 if (loglevel_str
|| loglevel_value
) {
508 bool has_str
= false;
510 if (!pretty
->start_line
) {
511 g_string_append(pretty
->string
, ", ");
514 print_name_equal(pretty
, "loglevel");
515 } else if (dom_print
) {
516 g_string_append(pretty
->string
, ":");
521 if (bt_value_string_get(loglevel_str
, &str
)
522 == BT_VALUE_STATUS_OK
) {
523 g_string_append(pretty
->string
, str
);
527 if (loglevel_value
) {
530 if (bt_value_integer_get(loglevel_value
, &value
)
531 == BT_VALUE_STATUS_OK
) {
532 g_string_append_printf(pretty
->string
, "%s(%" PRId64
")",
533 has_str
? " " : "", value
);
536 bt_put(loglevel_str
);
537 bt_put(loglevel_value
);
541 if (pretty
->options
.print_emf_field
) {
542 struct bt_value
*uri_str
;
544 uri_str
= bt_ctf_event_class_get_attribute_value_by_name(event_class
,
547 if (!pretty
->start_line
) {
548 g_string_append(pretty
->string
, ", ");
551 print_name_equal(pretty
, "model.emf.uri");
552 } else if (dom_print
) {
553 g_string_append(pretty
->string
, ":");
558 if (bt_value_string_get(uri_str
, &str
)
559 == BT_VALUE_STATUS_OK
) {
560 g_string_append(pretty
->string
, str
);
567 if (dom_print
&& !print_names
) {
568 g_string_append(pretty
->string
, " ");
570 if (!pretty
->start_line
) {
571 g_string_append(pretty
->string
, ", ");
573 pretty
->start_line
= true;
575 print_name_equal(pretty
, "name");
577 if (pretty
->use_colors
) {
578 g_string_append(pretty
->string
, COLOR_EVENT_NAME
);
580 g_string_append(pretty
->string
, bt_ctf_event_class_get_name(event_class
));
581 if (pretty
->use_colors
) {
582 g_string_append(pretty
->string
, COLOR_RST
);
585 g_string_append(pretty
->string
, ": ");
587 g_string_append(pretty
->string
, ", ");
591 bt_put(stream_class
);
597 enum bt_component_status
print_integer(struct pretty_component
*pretty
,
598 struct bt_ctf_field
*field
)
600 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
601 struct bt_ctf_field_type
*field_type
= NULL
;
602 enum bt_ctf_integer_base base
;
603 enum bt_ctf_string_encoding encoding
;
609 bool rst_color
= false;
611 field_type
= bt_ctf_field_get_type(field
);
613 ret
= BT_COMPONENT_STATUS_ERROR
;
616 signedness
= bt_ctf_field_type_integer_get_signed(field_type
);
617 if (signedness
< 0) {
618 ret
= BT_COMPONENT_STATUS_ERROR
;
622 if (bt_ctf_field_unsigned_integer_get_value(field
, &v
.u
) < 0) {
623 ret
= BT_COMPONENT_STATUS_ERROR
;
627 if (bt_ctf_field_signed_integer_get_value(field
, &v
.s
) < 0) {
628 ret
= BT_COMPONENT_STATUS_ERROR
;
633 encoding
= bt_ctf_field_type_integer_get_encoding(field_type
);
635 case BT_CTF_STRING_ENCODING_UTF8
:
636 case BT_CTF_STRING_ENCODING_ASCII
:
637 g_string_append_c(pretty
->tmp_string
, (int) v
.u
);
639 case BT_CTF_STRING_ENCODING_NONE
:
640 case BT_CTF_STRING_ENCODING_UNKNOWN
:
643 ret
= BT_COMPONENT_STATUS_ERROR
;
647 if (pretty
->use_colors
) {
648 g_string_append(pretty
->string
, COLOR_NUMBER_VALUE
);
652 base
= bt_ctf_field_type_integer_get_base(field_type
);
654 case BT_CTF_INTEGER_BASE_BINARY
:
658 len
= bt_ctf_field_type_integer_get_size(field_type
);
660 ret
= BT_COMPONENT_STATUS_ERROR
;
663 g_string_append(pretty
->string
, "0b");
664 v
.u
= _bt_piecewise_lshift(v
.u
, 64 - len
);
665 for (bitnr
= 0; bitnr
< len
; bitnr
++) {
666 g_string_append_printf(pretty
->string
, "%u", (v
.u
& (1ULL << 63)) ? 1 : 0);
667 v
.u
= _bt_piecewise_lshift(v
.u
, 1);
671 case BT_CTF_INTEGER_BASE_OCTAL
:
676 len
= bt_ctf_field_type_integer_get_size(field_type
);
678 ret
= BT_COMPONENT_STATUS_ERROR
;
685 /* Round length to the nearest 3-bit */
686 rounded_len
= (((len
- 1) / 3) + 1) * 3;
687 v
.u
&= ((uint64_t) 1 << rounded_len
) - 1;
691 g_string_append_printf(pretty
->string
, "0%" PRIo64
, v
.u
);
694 case BT_CTF_INTEGER_BASE_DECIMAL
:
696 g_string_append_printf(pretty
->string
, "%" PRIu64
, v
.u
);
698 g_string_append_printf(pretty
->string
, "%" PRId64
, v
.s
);
701 case BT_CTF_INTEGER_BASE_HEXADECIMAL
:
705 len
= bt_ctf_field_type_integer_get_size(field_type
);
707 ret
= BT_COMPONENT_STATUS_ERROR
;
711 /* Round length to the nearest nibble */
712 uint8_t rounded_len
= ((len
+ 3) & ~0x3);
714 v
.u
&= ((uint64_t) 1 << rounded_len
) - 1;
717 g_string_append_printf(pretty
->string
, "0x%" PRIX64
, v
.u
);
721 ret
= BT_COMPONENT_STATUS_ERROR
;
726 g_string_append(pretty
->string
, COLOR_RST
);
733 void print_escape_string(struct pretty_component
*pretty
, const char *str
)
737 g_string_append_c(pretty
->string
, '"');
739 for (i
= 0; i
< strlen(str
); i
++) {
740 /* Escape sequences not recognized by iscntrl(). */
743 g_string_append(pretty
->string
, "\\\\");
746 g_string_append(pretty
->string
, "\\\'");
749 g_string_append(pretty
->string
, "\\\"");
752 g_string_append(pretty
->string
, "\\\?");
756 /* Standard characters. */
757 if (!iscntrl(str
[i
])) {
758 g_string_append_c(pretty
->string
, str
[i
]);
764 g_string_append(pretty
->string
, "\\0");
767 g_string_append(pretty
->string
, "\\a");
770 g_string_append(pretty
->string
, "\\b");
773 g_string_append(pretty
->string
, "\\e");
776 g_string_append(pretty
->string
, "\\f");
779 g_string_append(pretty
->string
, "\\n");
782 g_string_append(pretty
->string
, "\\r");
785 g_string_append(pretty
->string
, "\\t");
788 g_string_append(pretty
->string
, "\\v");
791 /* Unhandled control-sequence, print as hex. */
792 g_string_append_printf(pretty
->string
, "\\x%02x", str
[i
]);
797 g_string_append_c(pretty
->string
, '"');
801 enum bt_component_status
print_enum(struct pretty_component
*pretty
,
802 struct bt_ctf_field
*field
)
804 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
805 struct bt_ctf_field
*container_field
= NULL
;
806 struct bt_ctf_field_type
*enumeration_field_type
= NULL
;
807 struct bt_ctf_field_type
*container_field_type
= NULL
;
808 struct bt_ctf_field_type_enumeration_mapping_iterator
*iter
= NULL
;
812 enumeration_field_type
= bt_ctf_field_get_type(field
);
813 if (!enumeration_field_type
) {
814 ret
= BT_COMPONENT_STATUS_ERROR
;
817 container_field
= bt_ctf_field_enumeration_get_container(field
);
818 if (!container_field
) {
819 ret
= BT_COMPONENT_STATUS_ERROR
;
822 container_field_type
= bt_ctf_field_get_type(container_field
);
823 if (!container_field_type
) {
824 ret
= BT_COMPONENT_STATUS_ERROR
;
827 is_signed
= bt_ctf_field_type_integer_get_signed(container_field_type
);
829 ret
= BT_COMPONENT_STATUS_ERROR
;
835 if (bt_ctf_field_signed_integer_get_value(container_field
,
837 ret
= BT_COMPONENT_STATUS_ERROR
;
840 iter
= bt_ctf_field_type_enumeration_find_mappings_by_signed_value(
841 enumeration_field_type
, value
);
845 if (bt_ctf_field_unsigned_integer_get_value(container_field
,
847 ret
= BT_COMPONENT_STATUS_ERROR
;
850 iter
= bt_ctf_field_type_enumeration_find_mappings_by_unsigned_value(
851 enumeration_field_type
, value
);
854 ret
= BT_COMPONENT_STATUS_ERROR
;
857 g_string_append(pretty
->string
, "( ");
859 const char *mapping_name
;
861 if (bt_ctf_field_type_enumeration_mapping_iterator_get_signed(
862 iter
, &mapping_name
, NULL
, NULL
) < 0) {
863 ret
= BT_COMPONENT_STATUS_ERROR
;
867 g_string_append(pretty
->string
, ", ");
868 if (pretty
->use_colors
) {
869 g_string_append(pretty
->string
, COLOR_ENUM_MAPPING_NAME
);
871 print_escape_string(pretty
, mapping_name
);
872 if (pretty
->use_colors
) {
873 g_string_append(pretty
->string
, COLOR_RST
);
875 if (bt_ctf_field_type_enumeration_mapping_iterator_next(iter
) < 0) {
880 if (pretty
->use_colors
) {
881 g_string_append(pretty
->string
, COLOR_UNKNOWN
);
883 g_string_append(pretty
->string
, "<unknown>");
884 if (pretty
->use_colors
) {
885 g_string_append(pretty
->string
, COLOR_RST
);
888 g_string_append(pretty
->string
, " : container = ");
889 ret
= print_integer(pretty
, container_field
);
890 if (ret
!= BT_COMPONENT_STATUS_OK
) {
893 g_string_append(pretty
->string
, " )");
896 bt_put(container_field_type
);
897 bt_put(container_field
);
898 bt_put(enumeration_field_type
);
903 int filter_field_name(struct pretty_component
*pretty
, const char *field_name
,
904 GQuark
*filter_fields
, int filter_array_len
)
907 GQuark field_quark
= g_quark_try_string(field_name
);
909 if (!field_quark
|| pretty
->options
.verbose
) {
913 for (i
= 0; i
< filter_array_len
; i
++) {
914 if (field_quark
== filter_fields
[i
]) {
922 enum bt_component_status
print_struct_field(struct pretty_component
*pretty
,
923 struct bt_ctf_field
*_struct
,
924 struct bt_ctf_field_type
*struct_type
,
925 int i
, bool print_names
, int *nr_printed_fields
,
926 GQuark
*filter_fields
, int filter_array_len
)
928 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
929 const char *field_name
;
930 struct bt_ctf_field
*field
= NULL
;
931 struct bt_ctf_field_type
*field_type
= NULL
;;
933 field
= bt_ctf_field_structure_get_field_by_index(_struct
, i
);
935 ret
= BT_COMPONENT_STATUS_ERROR
;
938 if (bt_ctf_field_type_structure_get_field(struct_type
,
939 &field_name
, &field_type
, i
) < 0) {
940 ret
= BT_COMPONENT_STATUS_ERROR
;
944 if (filter_fields
&& !filter_field_name(pretty
, field_name
,
945 filter_fields
, filter_array_len
)) {
946 ret
= BT_COMPONENT_STATUS_OK
;
950 if (*nr_printed_fields
> 0) {
951 g_string_append(pretty
->string
, ", ");
953 g_string_append(pretty
->string
, " ");
956 print_field_name_equal(pretty
, rem_(field_name
));
958 ret
= print_field(pretty
, field
, print_names
, NULL
, 0);
959 *nr_printed_fields
+= 1;
967 enum bt_component_status
print_struct(struct pretty_component
*pretty
,
968 struct bt_ctf_field
*_struct
, bool print_names
,
969 GQuark
*filter_fields
, int filter_array_len
)
971 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
972 struct bt_ctf_field_type
*struct_type
= NULL
;
973 int nr_fields
, i
, nr_printed_fields
;
975 struct_type
= bt_ctf_field_get_type(_struct
);
977 ret
= BT_COMPONENT_STATUS_ERROR
;
980 nr_fields
= bt_ctf_field_type_structure_get_field_count(struct_type
);
982 ret
= BT_COMPONENT_STATUS_ERROR
;
985 g_string_append(pretty
->string
, "{");
987 nr_printed_fields
= 0;
988 for (i
= 0; i
< nr_fields
; i
++) {
989 ret
= print_struct_field(pretty
, _struct
, struct_type
, i
,
990 print_names
, &nr_printed_fields
, filter_fields
,
992 if (ret
!= BT_COMPONENT_STATUS_OK
) {
997 g_string_append(pretty
->string
, " }");
1004 enum bt_component_status
print_array_field(struct pretty_component
*pretty
,
1005 struct bt_ctf_field
*array
, uint64_t i
,
1006 bool is_string
, bool print_names
)
1008 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1009 struct bt_ctf_field
*field
= NULL
;
1013 g_string_append(pretty
->string
, ", ");
1015 g_string_append(pretty
->string
, " ");
1018 g_string_append_printf(pretty
->string
, "[%" PRIu64
"] = ", i
);
1021 field
= bt_ctf_field_array_get_field(array
, i
);
1023 ret
= BT_COMPONENT_STATUS_ERROR
;
1026 ret
= print_field(pretty
, field
, print_names
, NULL
, 0);
1033 enum bt_component_status
print_array(struct pretty_component
*pretty
,
1034 struct bt_ctf_field
*array
, bool print_names
)
1036 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1037 struct bt_ctf_field_type
*array_type
= NULL
, *field_type
= NULL
;
1038 enum bt_ctf_field_type_id type_id
;
1041 bool is_string
= false;
1043 array_type
= bt_ctf_field_get_type(array
);
1045 ret
= BT_COMPONENT_STATUS_ERROR
;
1048 field_type
= bt_ctf_field_type_array_get_element_type(array_type
);
1050 ret
= BT_COMPONENT_STATUS_ERROR
;
1053 len
= bt_ctf_field_type_array_get_length(array_type
);
1055 ret
= BT_COMPONENT_STATUS_ERROR
;
1058 type_id
= bt_ctf_field_type_get_type_id(field_type
);
1059 if (type_id
== BT_CTF_FIELD_TYPE_ID_INTEGER
) {
1060 enum bt_ctf_string_encoding encoding
;
1062 encoding
= bt_ctf_field_type_integer_get_encoding(field_type
);
1063 if (encoding
== BT_CTF_STRING_ENCODING_UTF8
1064 || encoding
== BT_CTF_STRING_ENCODING_ASCII
) {
1065 int integer_len
, integer_alignment
;
1067 integer_len
= bt_ctf_field_type_integer_get_size(field_type
);
1068 if (integer_len
< 0) {
1069 return BT_COMPONENT_STATUS_ERROR
;
1071 integer_alignment
= bt_ctf_field_type_get_alignment(field_type
);
1072 if (integer_alignment
< 0) {
1073 return BT_COMPONENT_STATUS_ERROR
;
1075 if (integer_len
== CHAR_BIT
1076 && integer_alignment
== CHAR_BIT
) {
1083 g_string_assign(pretty
->tmp_string
, "");
1085 g_string_append(pretty
->string
, "[");
1089 for (i
= 0; i
< len
; i
++) {
1090 ret
= print_array_field(pretty
, array
, i
, is_string
, print_names
);
1091 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1098 if (pretty
->use_colors
) {
1099 g_string_append(pretty
->string
, COLOR_STRING_VALUE
);
1101 print_escape_string(pretty
, pretty
->tmp_string
->str
);
1102 if (pretty
->use_colors
) {
1103 g_string_append(pretty
->string
, COLOR_RST
);
1106 g_string_append(pretty
->string
, " ]");
1115 enum bt_component_status
print_sequence_field(struct pretty_component
*pretty
,
1116 struct bt_ctf_field
*seq
, uint64_t i
,
1117 bool is_string
, bool print_names
)
1119 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1120 struct bt_ctf_field
*field
= NULL
;
1124 g_string_append(pretty
->string
, ", ");
1126 g_string_append(pretty
->string
, " ");
1129 g_string_append_printf(pretty
->string
, "[%" PRIu64
"] = ", i
);
1132 field
= bt_ctf_field_sequence_get_field(seq
, i
);
1134 ret
= BT_COMPONENT_STATUS_ERROR
;
1137 ret
= print_field(pretty
, field
, print_names
, NULL
, 0);
1144 enum bt_component_status
print_sequence(struct pretty_component
*pretty
,
1145 struct bt_ctf_field
*seq
, bool print_names
)
1147 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1148 struct bt_ctf_field_type
*seq_type
= NULL
, *field_type
= NULL
;
1149 struct bt_ctf_field
*length_field
= NULL
;
1150 enum bt_ctf_field_type_id type_id
;
1153 bool is_string
= false;
1155 seq_type
= bt_ctf_field_get_type(seq
);
1157 ret
= BT_COMPONENT_STATUS_ERROR
;
1160 length_field
= bt_ctf_field_sequence_get_length(seq
);
1161 if (!length_field
) {
1162 ret
= BT_COMPONENT_STATUS_ERROR
;
1165 if (bt_ctf_field_unsigned_integer_get_value(length_field
, &len
) < 0) {
1166 ret
= BT_COMPONENT_STATUS_ERROR
;
1169 field_type
= bt_ctf_field_type_sequence_get_element_type(seq_type
);
1171 ret
= BT_COMPONENT_STATUS_ERROR
;
1174 type_id
= bt_ctf_field_type_get_type_id(field_type
);
1175 if (type_id
== BT_CTF_FIELD_TYPE_ID_INTEGER
) {
1176 enum bt_ctf_string_encoding encoding
;
1178 encoding
= bt_ctf_field_type_integer_get_encoding(field_type
);
1179 if (encoding
== BT_CTF_STRING_ENCODING_UTF8
1180 || encoding
== BT_CTF_STRING_ENCODING_ASCII
) {
1181 int integer_len
, integer_alignment
;
1183 integer_len
= bt_ctf_field_type_integer_get_size(field_type
);
1184 if (integer_len
< 0) {
1185 ret
= BT_COMPONENT_STATUS_ERROR
;
1188 integer_alignment
= bt_ctf_field_type_get_alignment(field_type
);
1189 if (integer_alignment
< 0) {
1190 ret
= BT_COMPONENT_STATUS_ERROR
;
1193 if (integer_len
== CHAR_BIT
1194 && integer_alignment
== CHAR_BIT
) {
1201 g_string_assign(pretty
->tmp_string
, "");
1203 g_string_append(pretty
->string
, "[");
1207 for (i
= 0; i
< len
; i
++) {
1208 ret
= print_sequence_field(pretty
, seq
, i
,
1209 is_string
, print_names
);
1210 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1217 if (pretty
->use_colors
) {
1218 g_string_append(pretty
->string
, COLOR_STRING_VALUE
);
1220 print_escape_string(pretty
, pretty
->tmp_string
->str
);
1221 if (pretty
->use_colors
) {
1222 g_string_append(pretty
->string
, COLOR_RST
);
1225 g_string_append(pretty
->string
, " ]");
1228 bt_put(length_field
);
1235 enum bt_component_status
print_variant(struct pretty_component
*pretty
,
1236 struct bt_ctf_field
*variant
, bool print_names
)
1238 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1239 struct bt_ctf_field
*field
= NULL
;
1241 field
= bt_ctf_field_variant_get_current_field(variant
);
1243 ret
= BT_COMPONENT_STATUS_ERROR
;
1246 g_string_append(pretty
->string
, "{ ");
1250 struct bt_ctf_field
*tag_field
= NULL
;
1251 const char *tag_choice
;
1252 struct bt_ctf_field_type_enumeration_mapping_iterator
*iter
;
1254 tag_field
= bt_ctf_field_variant_get_tag(variant
);
1256 ret
= BT_COMPONENT_STATUS_ERROR
;
1260 iter
= bt_ctf_field_enumeration_get_mappings(tag_field
);
1263 ret
= BT_COMPONENT_STATUS_ERROR
;
1268 bt_ctf_field_type_enumeration_mapping_iterator_get_signed(
1269 iter
, &tag_choice
, NULL
, NULL
);
1273 ret
= BT_COMPONENT_STATUS_ERROR
;
1276 print_field_name_equal(pretty
, rem_(tag_choice
));
1280 ret
= print_field(pretty
, field
, print_names
, NULL
, 0);
1281 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1285 g_string_append(pretty
->string
, " }");
1292 enum bt_component_status
print_field(struct pretty_component
*pretty
,
1293 struct bt_ctf_field
*field
, bool print_names
,
1294 GQuark
*filter_fields
, int filter_array_len
)
1296 enum bt_ctf_field_type_id type_id
;
1298 type_id
= bt_ctf_field_get_type_id(field
);
1300 case CTF_TYPE_INTEGER
:
1301 return print_integer(pretty
, field
);
1302 case CTF_TYPE_FLOAT
:
1306 if (bt_ctf_field_floating_point_get_value(field
, &v
)) {
1307 return BT_COMPONENT_STATUS_ERROR
;
1309 if (pretty
->use_colors
) {
1310 g_string_append(pretty
->string
, COLOR_NUMBER_VALUE
);
1312 g_string_append_printf(pretty
->string
, "%g", v
);
1313 if (pretty
->use_colors
) {
1314 g_string_append(pretty
->string
, COLOR_RST
);
1316 return BT_COMPONENT_STATUS_OK
;
1319 return print_enum(pretty
, field
);
1320 case CTF_TYPE_STRING
:
1321 if (pretty
->use_colors
) {
1322 g_string_append(pretty
->string
, COLOR_STRING_VALUE
);
1324 print_escape_string(pretty
, bt_ctf_field_string_get_value(field
));
1325 if (pretty
->use_colors
) {
1326 g_string_append(pretty
->string
, COLOR_RST
);
1328 return BT_COMPONENT_STATUS_OK
;
1329 case CTF_TYPE_STRUCT
:
1330 return print_struct(pretty
, field
, print_names
, filter_fields
,
1332 case CTF_TYPE_VARIANT
:
1333 return print_variant(pretty
, field
, print_names
);
1334 case CTF_TYPE_ARRAY
:
1335 return print_array(pretty
, field
, print_names
);
1336 case CTF_TYPE_SEQUENCE
:
1337 return print_sequence(pretty
, field
, print_names
);
1339 // TODO: log instead
1340 fprintf(pretty
->err
, "[error] Unknown type id: %d\n", (int) type_id
);
1341 return BT_COMPONENT_STATUS_ERROR
;
1346 enum bt_component_status
print_stream_packet_context(struct pretty_component
*pretty
,
1347 struct bt_ctf_event
*event
)
1349 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1350 struct bt_ctf_packet
*packet
= NULL
;
1351 struct bt_ctf_field
*main_field
= NULL
;
1353 packet
= bt_ctf_event_get_packet(event
);
1355 ret
= BT_COMPONENT_STATUS_ERROR
;
1358 main_field
= bt_ctf_packet_get_context(packet
);
1362 if (!pretty
->start_line
) {
1363 g_string_append(pretty
->string
, ", ");
1365 pretty
->start_line
= false;
1366 if (pretty
->options
.print_scope_field_names
) {
1367 print_name_equal(pretty
, "stream.packet.context");
1369 ret
= print_field(pretty
, main_field
,
1370 pretty
->options
.print_context_field_names
,
1371 stream_packet_context_quarks
,
1372 STREAM_PACKET_CONTEXT_QUARKS_LEN
);
1380 enum bt_component_status
print_event_header_raw(struct pretty_component
*pretty
,
1381 struct bt_ctf_event
*event
)
1383 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1384 struct bt_ctf_field
*main_field
= NULL
;
1386 main_field
= bt_ctf_event_get_header(event
);
1390 if (!pretty
->start_line
) {
1391 g_string_append(pretty
->string
, ", ");
1393 pretty
->start_line
= false;
1394 if (pretty
->options
.print_scope_field_names
) {
1395 print_name_equal(pretty
, "stream.event.header");
1397 ret
= print_field(pretty
, main_field
,
1398 pretty
->options
.print_header_field_names
, NULL
, 0);
1405 enum bt_component_status
print_stream_event_context(struct pretty_component
*pretty
,
1406 struct bt_ctf_event
*event
)
1408 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1409 struct bt_ctf_field
*main_field
= NULL
;
1411 main_field
= bt_ctf_event_get_stream_event_context(event
);
1415 if (!pretty
->start_line
) {
1416 g_string_append(pretty
->string
, ", ");
1418 pretty
->start_line
= false;
1419 if (pretty
->options
.print_scope_field_names
) {
1420 print_name_equal(pretty
, "stream.event.context");
1422 ret
= print_field(pretty
, main_field
,
1423 pretty
->options
.print_context_field_names
, NULL
, 0);
1430 enum bt_component_status
print_event_context(struct pretty_component
*pretty
,
1431 struct bt_ctf_event
*event
)
1433 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1434 struct bt_ctf_field
*main_field
= NULL
;
1436 main_field
= bt_ctf_event_get_event_context(event
);
1440 if (!pretty
->start_line
) {
1441 g_string_append(pretty
->string
, ", ");
1443 pretty
->start_line
= false;
1444 if (pretty
->options
.print_scope_field_names
) {
1445 print_name_equal(pretty
, "event.context");
1447 ret
= print_field(pretty
, main_field
,
1448 pretty
->options
.print_context_field_names
, NULL
, 0);
1455 enum bt_component_status
print_event_payload(struct pretty_component
*pretty
,
1456 struct bt_ctf_event
*event
)
1458 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1459 struct bt_ctf_field
*main_field
= NULL
;
1461 main_field
= bt_ctf_event_get_event_payload(event
);
1465 if (!pretty
->start_line
) {
1466 g_string_append(pretty
->string
, ", ");
1468 pretty
->start_line
= false;
1469 if (pretty
->options
.print_scope_field_names
) {
1470 print_name_equal(pretty
, "event.fields");
1472 ret
= print_field(pretty
, main_field
,
1473 pretty
->options
.print_payload_field_names
, NULL
, 0);
1480 enum bt_component_status
pretty_print_event(struct pretty_component
*pretty
,
1481 struct bt_notification
*event_notif
)
1483 enum bt_component_status ret
;
1484 struct bt_ctf_event
*event
=
1485 bt_notification_event_get_event(event_notif
);
1486 struct bt_clock_class_priority_map
*cc_prio_map
=
1487 bt_notification_event_get_clock_class_priority_map(event_notif
);
1490 assert(cc_prio_map
);
1491 pretty
->start_line
= true;
1492 g_string_assign(pretty
->string
, "");
1493 ret
= print_event_header(pretty
, event
, cc_prio_map
);
1494 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1498 ret
= print_stream_packet_context(pretty
, event
);
1499 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1503 if (pretty
->options
.verbose
) {
1504 ret
= print_event_header_raw(pretty
, event
);
1505 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1510 ret
= print_stream_event_context(pretty
, event
);
1511 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1515 ret
= print_event_context(pretty
, event
);
1516 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1520 ret
= print_event_payload(pretty
, event
);
1521 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1525 g_string_append_c(pretty
->string
, '\n');
1526 if (fwrite(pretty
->string
->str
, pretty
->string
->len
, 1, pretty
->out
) != 1) {
1527 ret
= BT_COMPONENT_STATUS_ERROR
;
1533 bt_put(cc_prio_map
);