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>
43 #include <babeltrace/compat/time-internal.h>
48 #define NSEC_PER_SEC 1000000000LL
50 #define COLOR_NAME BT_COMMON_COLOR_BOLD
51 #define COLOR_FIELD_NAME BT_COMMON_COLOR_FG_CYAN
52 #define COLOR_RST BT_COMMON_COLOR_RESET
53 #define COLOR_STRING_VALUE BT_COMMON_COLOR_BOLD
54 #define COLOR_NUMBER_VALUE BT_COMMON_COLOR_BOLD
55 #define COLOR_ENUM_MAPPING_NAME BT_COMMON_COLOR_BOLD
56 #define COLOR_UNKNOWN BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_RED
57 #define COLOR_EVENT_NAME BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_MAGENTA
58 #define COLOR_TIMESTAMP BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_YELLOW
61 const char *rem_(const char *str
)
70 int64_t real_timestamp
; /* Relative to UNIX epoch. */
71 uint64_t clock_value
; /* In cycles. */
75 enum bt_component_status
print_field(struct pretty_component
*pretty
,
76 struct bt_ctf_field
*field
, bool print_names
,
77 GQuark
*filters_fields
, int filter_array_len
);
80 void print_name_equal(struct pretty_component
*pretty
, const char *name
)
82 if (pretty
->use_colors
) {
83 g_string_append_printf(pretty
->string
, "%s%s%s = ", COLOR_NAME
,
86 g_string_append_printf(pretty
->string
, "%s = ", name
);
91 void print_field_name_equal(struct pretty_component
*pretty
, const char *name
)
93 if (pretty
->use_colors
) {
94 g_string_append_printf(pretty
->string
, "%s%s%s = ",
95 COLOR_FIELD_NAME
, name
, COLOR_RST
);
97 g_string_append_printf(pretty
->string
, "%s = ", name
);
102 void print_timestamp_cycles(struct pretty_component
*pretty
,
103 struct bt_ctf_clock_class
*clock_class
,
104 struct bt_ctf_event
*event
)
107 struct bt_ctf_clock_value
*clock_value
;
110 clock_value
= bt_ctf_event_get_clock_value(event
, clock_class
);
112 g_string_append(pretty
->string
, "????????????????????");
116 ret
= bt_ctf_clock_value_get_value(clock_value
, &cycles
);
119 // TODO: log, this is unexpected
120 g_string_append(pretty
->string
, "Error");
124 g_string_append_printf(pretty
->string
, "%020" PRIu64
, cycles
);
126 if (pretty
->last_cycles_timestamp
!= -1ULL) {
127 pretty
->delta_cycles
= cycles
- pretty
->last_cycles_timestamp
;
129 pretty
->last_cycles_timestamp
= cycles
;
133 void print_timestamp_wall(struct pretty_component
*pretty
,
134 struct bt_ctf_clock_class
*clock_class
,
135 struct bt_ctf_event
*event
)
138 struct bt_ctf_clock_value
*clock_value
;
139 int64_t ts_nsec
= 0; /* add configurable offset */
140 int64_t ts_sec
= 0; /* add configurable offset */
141 uint64_t ts_sec_abs
, ts_nsec_abs
;
144 clock_value
= bt_ctf_event_get_clock_value(event
, clock_class
);
146 g_string_append(pretty
->string
, "??:??:??.?????????");
150 ret
= bt_ctf_clock_value_get_value_ns_from_epoch(clock_value
, &ts_nsec
);
153 // TODO: log, this is unexpected
154 g_string_append(pretty
->string
, "Error");
158 if (pretty
->last_real_timestamp
!= -1ULL) {
159 pretty
->delta_real_timestamp
= ts_nsec
- pretty
->last_real_timestamp
;
162 pretty
->last_real_timestamp
= ts_nsec
;
163 ts_sec
+= ts_nsec
/ NSEC_PER_SEC
;
164 ts_nsec
= ts_nsec
% NSEC_PER_SEC
;
166 if (ts_sec
>= 0 && ts_nsec
>= 0) {
169 ts_nsec_abs
= ts_nsec
;
170 } else if (ts_sec
> 0 && ts_nsec
< 0) {
172 ts_sec_abs
= ts_sec
- 1;
173 ts_nsec_abs
= NSEC_PER_SEC
+ ts_nsec
;
174 } else if (ts_sec
== 0 && ts_nsec
< 0) {
177 ts_nsec_abs
= -ts_nsec
;
178 } else if (ts_sec
< 0 && ts_nsec
> 0) {
180 ts_sec_abs
= -(ts_sec
+ 1);
181 ts_nsec_abs
= NSEC_PER_SEC
- ts_nsec
;
182 } else if (ts_sec
< 0 && ts_nsec
== 0) {
184 ts_sec_abs
= -ts_sec
;
185 ts_nsec_abs
= ts_nsec
;
186 } else { /* (ts_sec < 0 && ts_nsec < 0) */
188 ts_sec_abs
= -ts_sec
;
189 ts_nsec_abs
= -ts_nsec
;
192 if (!pretty
->options
.clock_seconds
) {
194 time_t time_s
= (time_t) ts_sec_abs
;
198 fprintf(stderr
, "[warning] Fallback to [sec.ns] to print negative time value. Use --clock-seconds.\n");
202 if (!pretty
->options
.clock_gmt
) {
205 res
= bt_localtime_r(&time_s
, &tm
);
208 fprintf(stderr
, "[warning] Unable to get localtime.\n");
214 res
= bt_gmtime_r(&time_s
, &tm
);
217 fprintf(stderr
, "[warning] Unable to get gmtime.\n");
221 if (pretty
->options
.clock_date
) {
225 /* Print date and time */
226 res
= strftime(timestr
, sizeof(timestr
),
230 fprintf(stderr
, "[warning] Unable to print ascii time.\n");
234 g_string_append(pretty
->string
, timestr
);
237 /* Print time in HH:MM:SS.ns */
238 g_string_append_printf(pretty
->string
,
239 "%02d:%02d:%02d.%09" PRIu64
, tm
.tm_hour
, tm
.tm_min
,
240 tm
.tm_sec
, ts_nsec_abs
);
244 g_string_append_printf(pretty
->string
, "%s%" PRId64
".%09" PRIu64
,
245 is_negative
? "-" : "", ts_sec_abs
, ts_nsec_abs
);
251 enum bt_component_status
print_event_timestamp(struct pretty_component
*pretty
,
252 struct bt_ctf_event
*event
,
253 struct bt_clock_class_priority_map
*cc_prio_map
,
256 bool print_names
= pretty
->options
.print_header_field_names
;
257 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
258 struct bt_ctf_stream
*stream
= NULL
;
259 struct bt_ctf_stream_class
*stream_class
= NULL
;
260 struct bt_ctf_trace
*trace
= NULL
;
261 struct bt_ctf_clock_class
*clock_class
= NULL
;
263 stream
= bt_ctf_event_get_stream(event
);
265 ret
= BT_COMPONENT_STATUS_ERROR
;
269 stream_class
= bt_ctf_stream_get_class(stream
);
271 ret
= BT_COMPONENT_STATUS_ERROR
;
274 trace
= bt_ctf_stream_class_get_trace(stream_class
);
276 ret
= BT_COMPONENT_STATUS_ERROR
;
280 if (bt_clock_class_priority_map_get_clock_class_count(cc_prio_map
) == 0) {
281 /* No clock class: skip the timestamp without an error */
286 bt_clock_class_priority_map_get_highest_priority_clock_class(
289 ret
= BT_COMPONENT_STATUS_ERROR
;
294 print_name_equal(pretty
, "timestamp");
296 g_string_append(pretty
->string
, "[");
298 if (pretty
->use_colors
) {
299 g_string_append(pretty
->string
, COLOR_TIMESTAMP
);
301 if (pretty
->options
.print_timestamp_cycles
) {
302 print_timestamp_cycles(pretty
, clock_class
, event
);
304 print_timestamp_wall(pretty
, clock_class
, event
);
306 if (pretty
->use_colors
) {
307 g_string_append(pretty
->string
, COLOR_RST
);
311 g_string_append(pretty
->string
, "] ");
313 if (pretty
->options
.print_delta_field
) {
315 g_string_append(pretty
->string
, ", ");
316 print_name_equal(pretty
, "delta");
318 g_string_append(pretty
->string
, "(");
320 if (pretty
->options
.print_timestamp_cycles
) {
321 if (pretty
->delta_cycles
== -1ULL) {
322 g_string_append(pretty
->string
,
323 "+??????????\?\?) "); /* Not a trigraph. */
325 g_string_append_printf(pretty
->string
,
326 "+%012" PRIu64
, pretty
->delta_cycles
);
329 if (pretty
->delta_real_timestamp
!= -1ULL) {
330 uint64_t delta_sec
, delta_nsec
, delta
;
332 delta
= pretty
->delta_real_timestamp
;
333 delta_sec
= delta
/ NSEC_PER_SEC
;
334 delta_nsec
= delta
% NSEC_PER_SEC
;
335 g_string_append_printf(pretty
->string
,
336 "+%" PRIu64
".%09" PRIu64
,
337 delta_sec
, delta_nsec
);
339 g_string_append(pretty
->string
, "+?.?????????");
343 g_string_append(pretty
->string
, ") ");
346 *start_line
= !print_names
;
351 bt_put(stream_class
);
357 enum bt_component_status
print_event_header(struct pretty_component
*pretty
,
358 struct bt_ctf_event
*event
,
359 struct bt_clock_class_priority_map
*cc_prio_map
)
361 bool print_names
= pretty
->options
.print_header_field_names
;
362 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
363 struct bt_ctf_event_class
*event_class
= NULL
;
364 struct bt_ctf_stream_class
*stream_class
= NULL
;
365 struct bt_ctf_trace
*trace_class
= NULL
;
368 event_class
= bt_ctf_event_get_class(event
);
370 ret
= BT_COMPONENT_STATUS_ERROR
;
373 stream_class
= bt_ctf_event_class_get_stream_class(event_class
);
375 ret
= BT_COMPONENT_STATUS_ERROR
;
378 trace_class
= bt_ctf_stream_class_get_trace(stream_class
);
380 ret
= BT_COMPONENT_STATUS_ERROR
;
383 ret
= print_event_timestamp(pretty
, event
, cc_prio_map
,
384 &pretty
->start_line
);
385 if (ret
!= BT_COMPONENT_STATUS_OK
) {
388 if (pretty
->options
.print_trace_field
) {
391 name
= bt_ctf_trace_get_name(trace_class
);
393 if (!pretty
->start_line
) {
394 g_string_append(pretty
->string
, ", ");
397 print_name_equal(pretty
, "trace");
400 g_string_append(pretty
->string
, name
);
403 g_string_append(pretty
->string
, " ");
407 if (pretty
->options
.print_trace_hostname_field
) {
408 struct bt_value
*hostname_str
;
410 hostname_str
= bt_ctf_trace_get_environment_field_value_by_name(trace_class
,
415 if (!pretty
->start_line
) {
416 g_string_append(pretty
->string
, ", ");
419 print_name_equal(pretty
, "trace:hostname");
421 if (bt_value_string_get(hostname_str
, &str
)
422 == BT_VALUE_STATUS_OK
) {
423 g_string_append(pretty
->string
, str
);
425 bt_put(hostname_str
);
429 if (pretty
->options
.print_trace_domain_field
) {
430 struct bt_value
*domain_str
;
432 domain_str
= bt_ctf_trace_get_environment_field_value_by_name(trace_class
,
437 if (!pretty
->start_line
) {
438 g_string_append(pretty
->string
, ", ");
441 print_name_equal(pretty
, "trace:domain");
442 } else if (dom_print
) {
443 g_string_append(pretty
->string
, ":");
445 if (bt_value_string_get(domain_str
, &str
)
446 == BT_VALUE_STATUS_OK
) {
447 g_string_append(pretty
->string
, str
);
453 if (pretty
->options
.print_trace_procname_field
) {
454 struct bt_value
*procname_str
;
456 procname_str
= bt_ctf_trace_get_environment_field_value_by_name(trace_class
,
461 if (!pretty
->start_line
) {
462 g_string_append(pretty
->string
, ", ");
465 print_name_equal(pretty
, "trace:procname");
466 } else if (dom_print
) {
467 g_string_append(pretty
->string
, ":");
469 if (bt_value_string_get(procname_str
, &str
)
470 == BT_VALUE_STATUS_OK
) {
471 g_string_append(pretty
->string
, str
);
473 bt_put(procname_str
);
477 if (pretty
->options
.print_trace_vpid_field
) {
478 struct bt_value
*vpid_value
;
480 vpid_value
= bt_ctf_trace_get_environment_field_value_by_name(trace_class
,
485 if (!pretty
->start_line
) {
486 g_string_append(pretty
->string
, ", ");
489 print_name_equal(pretty
, "trace:vpid");
490 } else if (dom_print
) {
491 g_string_append(pretty
->string
, ":");
493 if (bt_value_integer_get(vpid_value
, &value
)
494 == BT_VALUE_STATUS_OK
) {
495 g_string_append_printf(pretty
->string
, "(%" PRId64
")", value
);
501 if (pretty
->options
.print_loglevel_field
) {
502 static const char *log_level_names
[] = {
503 [ BT_CTF_EVENT_CLASS_LOG_LEVEL_EMERGENCY
] = "TRACE_EMERG",
504 [ BT_CTF_EVENT_CLASS_LOG_LEVEL_ALERT
] = "TRACE_ALERT",
505 [ BT_CTF_EVENT_CLASS_LOG_LEVEL_CRITICAL
] = "TRACE_CRIT",
506 [ BT_CTF_EVENT_CLASS_LOG_LEVEL_ERROR
] = "TRACE_ERR",
507 [ BT_CTF_EVENT_CLASS_LOG_LEVEL_WARNING
] = "TRACE_WARNING",
508 [ BT_CTF_EVENT_CLASS_LOG_LEVEL_NOTICE
] = "TRACE_NOTICE",
509 [ BT_CTF_EVENT_CLASS_LOG_LEVEL_INFO
] = "TRACE_INFO",
510 [ BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
] = "TRACE_DEBUG_SYSTEM",
511 [ BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
] = "TRACE_DEBUG_PROGRAM",
512 [ BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
] = "TRACE_DEBUG_PROCESS",
513 [ BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
] = "TRACE_DEBUG_MODULE",
514 [ BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
] = "TRACE_DEBUG_UNIT",
515 [ BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
] = "TRACE_DEBUG_FUNCTION",
516 [ BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
] = "TRACE_DEBUG_LINE",
517 [ BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG
] = "TRACE_DEBUG",
519 enum bt_ctf_event_class_log_level log_level
;
520 const char *log_level_str
= NULL
;
522 log_level
= bt_ctf_event_class_get_log_level(event_class
);
523 assert(log_level
!= BT_CTF_EVENT_CLASS_LOG_LEVEL_UNKNOWN
);
524 if (log_level
!= BT_CTF_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED
) {
525 log_level_str
= log_level_names
[log_level
];
529 if (!pretty
->start_line
) {
530 g_string_append(pretty
->string
, ", ");
533 print_name_equal(pretty
, "loglevel");
534 } else if (dom_print
) {
535 g_string_append(pretty
->string
, ":");
538 g_string_append(pretty
->string
, log_level_str
);
539 g_string_append_printf(
540 pretty
->string
, " (%d)", (int) log_level
);
544 if (pretty
->options
.print_emf_field
) {
547 uri_str
= bt_ctf_event_class_get_emf_uri(event_class
);
549 if (!pretty
->start_line
) {
550 g_string_append(pretty
->string
, ", ");
553 print_name_equal(pretty
, "model.emf.uri");
554 } else if (dom_print
) {
555 g_string_append(pretty
->string
, ":");
558 g_string_append(pretty
->string
, uri_str
);
562 if (dom_print
&& !print_names
) {
563 g_string_append(pretty
->string
, " ");
565 if (!pretty
->start_line
) {
566 g_string_append(pretty
->string
, ", ");
568 pretty
->start_line
= true;
570 print_name_equal(pretty
, "name");
572 if (pretty
->use_colors
) {
573 g_string_append(pretty
->string
, COLOR_EVENT_NAME
);
575 g_string_append(pretty
->string
, bt_ctf_event_class_get_name(event_class
));
576 if (pretty
->use_colors
) {
577 g_string_append(pretty
->string
, COLOR_RST
);
580 g_string_append(pretty
->string
, ": ");
582 g_string_append(pretty
->string
, ", ");
586 bt_put(stream_class
);
592 enum bt_component_status
print_integer(struct pretty_component
*pretty
,
593 struct bt_ctf_field
*field
)
595 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
596 struct bt_ctf_field_type
*field_type
= NULL
;
597 enum bt_ctf_integer_base base
;
598 enum bt_ctf_string_encoding encoding
;
604 bool rst_color
= false;
606 field_type
= bt_ctf_field_get_type(field
);
608 ret
= BT_COMPONENT_STATUS_ERROR
;
611 signedness
= bt_ctf_field_type_integer_get_signed(field_type
);
612 if (signedness
< 0) {
613 ret
= BT_COMPONENT_STATUS_ERROR
;
617 if (bt_ctf_field_unsigned_integer_get_value(field
, &v
.u
) < 0) {
618 ret
= BT_COMPONENT_STATUS_ERROR
;
622 if (bt_ctf_field_signed_integer_get_value(field
, &v
.s
) < 0) {
623 ret
= BT_COMPONENT_STATUS_ERROR
;
628 encoding
= bt_ctf_field_type_integer_get_encoding(field_type
);
630 case BT_CTF_STRING_ENCODING_UTF8
:
631 case BT_CTF_STRING_ENCODING_ASCII
:
632 g_string_append_c(pretty
->tmp_string
, (int) v
.u
);
634 case BT_CTF_STRING_ENCODING_NONE
:
635 case BT_CTF_STRING_ENCODING_UNKNOWN
:
638 ret
= BT_COMPONENT_STATUS_ERROR
;
642 if (pretty
->use_colors
) {
643 g_string_append(pretty
->string
, COLOR_NUMBER_VALUE
);
647 base
= bt_ctf_field_type_integer_get_base(field_type
);
649 case BT_CTF_INTEGER_BASE_BINARY
:
653 len
= bt_ctf_field_type_integer_get_size(field_type
);
655 ret
= BT_COMPONENT_STATUS_ERROR
;
658 g_string_append(pretty
->string
, "0b");
659 v
.u
= _bt_piecewise_lshift(v
.u
, 64 - len
);
660 for (bitnr
= 0; bitnr
< len
; bitnr
++) {
661 g_string_append_printf(pretty
->string
, "%u", (v
.u
& (1ULL << 63)) ? 1 : 0);
662 v
.u
= _bt_piecewise_lshift(v
.u
, 1);
666 case BT_CTF_INTEGER_BASE_OCTAL
:
671 len
= bt_ctf_field_type_integer_get_size(field_type
);
673 ret
= BT_COMPONENT_STATUS_ERROR
;
680 /* Round length to the nearest 3-bit */
681 rounded_len
= (((len
- 1) / 3) + 1) * 3;
682 v
.u
&= ((uint64_t) 1 << rounded_len
) - 1;
686 g_string_append_printf(pretty
->string
, "0%" PRIo64
, v
.u
);
689 case BT_CTF_INTEGER_BASE_DECIMAL
:
690 case BT_CTF_INTEGER_BASE_UNSPECIFIED
:
692 g_string_append_printf(pretty
->string
, "%" PRIu64
, v
.u
);
694 g_string_append_printf(pretty
->string
, "%" PRId64
, v
.s
);
697 case BT_CTF_INTEGER_BASE_HEXADECIMAL
:
701 len
= bt_ctf_field_type_integer_get_size(field_type
);
703 ret
= BT_COMPONENT_STATUS_ERROR
;
707 /* Round length to the nearest nibble */
708 uint8_t rounded_len
= ((len
+ 3) & ~0x3);
710 v
.u
&= ((uint64_t) 1 << rounded_len
) - 1;
713 g_string_append_printf(pretty
->string
, "0x%" PRIX64
, v
.u
);
717 ret
= BT_COMPONENT_STATUS_ERROR
;
722 g_string_append(pretty
->string
, COLOR_RST
);
729 void print_escape_string(struct pretty_component
*pretty
, const char *str
)
733 g_string_append_c(pretty
->string
, '"');
735 for (i
= 0; i
< strlen(str
); i
++) {
736 /* Escape sequences not recognized by iscntrl(). */
739 g_string_append(pretty
->string
, "\\\\");
742 g_string_append(pretty
->string
, "\\\'");
745 g_string_append(pretty
->string
, "\\\"");
748 g_string_append(pretty
->string
, "\\\?");
752 /* Standard characters. */
753 if (!iscntrl(str
[i
])) {
754 g_string_append_c(pretty
->string
, str
[i
]);
760 g_string_append(pretty
->string
, "\\0");
763 g_string_append(pretty
->string
, "\\a");
766 g_string_append(pretty
->string
, "\\b");
769 g_string_append(pretty
->string
, "\\e");
772 g_string_append(pretty
->string
, "\\f");
775 g_string_append(pretty
->string
, "\\n");
778 g_string_append(pretty
->string
, "\\r");
781 g_string_append(pretty
->string
, "\\t");
784 g_string_append(pretty
->string
, "\\v");
787 /* Unhandled control-sequence, print as hex. */
788 g_string_append_printf(pretty
->string
, "\\x%02x", str
[i
]);
793 g_string_append_c(pretty
->string
, '"');
797 enum bt_component_status
print_enum(struct pretty_component
*pretty
,
798 struct bt_ctf_field
*field
)
800 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
801 struct bt_ctf_field
*container_field
= NULL
;
802 struct bt_ctf_field_type
*enumeration_field_type
= NULL
;
803 struct bt_ctf_field_type
*container_field_type
= NULL
;
804 struct bt_ctf_field_type_enumeration_mapping_iterator
*iter
= NULL
;
808 enumeration_field_type
= bt_ctf_field_get_type(field
);
809 if (!enumeration_field_type
) {
810 ret
= BT_COMPONENT_STATUS_ERROR
;
813 container_field
= bt_ctf_field_enumeration_get_container(field
);
814 if (!container_field
) {
815 ret
= BT_COMPONENT_STATUS_ERROR
;
818 container_field_type
= bt_ctf_field_get_type(container_field
);
819 if (!container_field_type
) {
820 ret
= BT_COMPONENT_STATUS_ERROR
;
823 is_signed
= bt_ctf_field_type_integer_get_signed(container_field_type
);
825 ret
= BT_COMPONENT_STATUS_ERROR
;
831 if (bt_ctf_field_signed_integer_get_value(container_field
,
833 ret
= BT_COMPONENT_STATUS_ERROR
;
836 iter
= bt_ctf_field_type_enumeration_find_mappings_by_signed_value(
837 enumeration_field_type
, value
);
841 if (bt_ctf_field_unsigned_integer_get_value(container_field
,
843 ret
= BT_COMPONENT_STATUS_ERROR
;
846 iter
= bt_ctf_field_type_enumeration_find_mappings_by_unsigned_value(
847 enumeration_field_type
, value
);
850 ret
= BT_COMPONENT_STATUS_ERROR
;
853 g_string_append(pretty
->string
, "( ");
855 const char *mapping_name
;
857 if (bt_ctf_field_type_enumeration_mapping_iterator_get_signed(
858 iter
, &mapping_name
, NULL
, NULL
) < 0) {
859 ret
= BT_COMPONENT_STATUS_ERROR
;
863 g_string_append(pretty
->string
, ", ");
864 if (pretty
->use_colors
) {
865 g_string_append(pretty
->string
, COLOR_ENUM_MAPPING_NAME
);
867 print_escape_string(pretty
, mapping_name
);
868 if (pretty
->use_colors
) {
869 g_string_append(pretty
->string
, COLOR_RST
);
871 if (bt_ctf_field_type_enumeration_mapping_iterator_next(iter
) < 0) {
876 if (pretty
->use_colors
) {
877 g_string_append(pretty
->string
, COLOR_UNKNOWN
);
879 g_string_append(pretty
->string
, "<unknown>");
880 if (pretty
->use_colors
) {
881 g_string_append(pretty
->string
, COLOR_RST
);
884 g_string_append(pretty
->string
, " : container = ");
885 ret
= print_integer(pretty
, container_field
);
886 if (ret
!= BT_COMPONENT_STATUS_OK
) {
889 g_string_append(pretty
->string
, " )");
892 bt_put(container_field_type
);
893 bt_put(container_field
);
894 bt_put(enumeration_field_type
);
899 int filter_field_name(struct pretty_component
*pretty
, const char *field_name
,
900 GQuark
*filter_fields
, int filter_array_len
)
903 GQuark field_quark
= g_quark_try_string(field_name
);
905 if (!field_quark
|| pretty
->options
.verbose
) {
909 for (i
= 0; i
< filter_array_len
; i
++) {
910 if (field_quark
== filter_fields
[i
]) {
918 enum bt_component_status
print_struct_field(struct pretty_component
*pretty
,
919 struct bt_ctf_field
*_struct
,
920 struct bt_ctf_field_type
*struct_type
,
921 int i
, bool print_names
, int *nr_printed_fields
,
922 GQuark
*filter_fields
, int filter_array_len
)
924 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
925 const char *field_name
;
926 struct bt_ctf_field
*field
= NULL
;
927 struct bt_ctf_field_type
*field_type
= NULL
;;
929 field
= bt_ctf_field_structure_get_field_by_index(_struct
, i
);
931 ret
= BT_COMPONENT_STATUS_ERROR
;
934 if (bt_ctf_field_type_structure_get_field(struct_type
,
935 &field_name
, &field_type
, i
) < 0) {
936 ret
= BT_COMPONENT_STATUS_ERROR
;
940 if (filter_fields
&& !filter_field_name(pretty
, field_name
,
941 filter_fields
, filter_array_len
)) {
942 ret
= BT_COMPONENT_STATUS_OK
;
946 if (*nr_printed_fields
> 0) {
947 g_string_append(pretty
->string
, ", ");
949 g_string_append(pretty
->string
, " ");
952 print_field_name_equal(pretty
, rem_(field_name
));
954 ret
= print_field(pretty
, field
, print_names
, NULL
, 0);
955 *nr_printed_fields
+= 1;
963 enum bt_component_status
print_struct(struct pretty_component
*pretty
,
964 struct bt_ctf_field
*_struct
, bool print_names
,
965 GQuark
*filter_fields
, int filter_array_len
)
967 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
968 struct bt_ctf_field_type
*struct_type
= NULL
;
969 int nr_fields
, i
, nr_printed_fields
;
971 struct_type
= bt_ctf_field_get_type(_struct
);
973 ret
= BT_COMPONENT_STATUS_ERROR
;
976 nr_fields
= bt_ctf_field_type_structure_get_field_count(struct_type
);
978 ret
= BT_COMPONENT_STATUS_ERROR
;
981 g_string_append(pretty
->string
, "{");
983 nr_printed_fields
= 0;
984 for (i
= 0; i
< nr_fields
; i
++) {
985 ret
= print_struct_field(pretty
, _struct
, struct_type
, i
,
986 print_names
, &nr_printed_fields
, filter_fields
,
988 if (ret
!= BT_COMPONENT_STATUS_OK
) {
993 g_string_append(pretty
->string
, " }");
1000 enum bt_component_status
print_array_field(struct pretty_component
*pretty
,
1001 struct bt_ctf_field
*array
, uint64_t i
,
1002 bool is_string
, bool print_names
)
1004 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1005 struct bt_ctf_field
*field
= NULL
;
1009 g_string_append(pretty
->string
, ", ");
1011 g_string_append(pretty
->string
, " ");
1014 g_string_append_printf(pretty
->string
, "[%" PRIu64
"] = ", i
);
1017 field
= bt_ctf_field_array_get_field(array
, i
);
1019 ret
= BT_COMPONENT_STATUS_ERROR
;
1022 ret
= print_field(pretty
, field
, print_names
, NULL
, 0);
1029 enum bt_component_status
print_array(struct pretty_component
*pretty
,
1030 struct bt_ctf_field
*array
, bool print_names
)
1032 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1033 struct bt_ctf_field_type
*array_type
= NULL
, *field_type
= NULL
;
1034 enum bt_ctf_field_type_id type_id
;
1037 bool is_string
= false;
1039 array_type
= bt_ctf_field_get_type(array
);
1041 ret
= BT_COMPONENT_STATUS_ERROR
;
1044 field_type
= bt_ctf_field_type_array_get_element_type(array_type
);
1046 ret
= BT_COMPONENT_STATUS_ERROR
;
1049 len
= bt_ctf_field_type_array_get_length(array_type
);
1051 ret
= BT_COMPONENT_STATUS_ERROR
;
1054 type_id
= bt_ctf_field_type_get_type_id(field_type
);
1055 if (type_id
== BT_CTF_FIELD_TYPE_ID_INTEGER
) {
1056 enum bt_ctf_string_encoding encoding
;
1058 encoding
= bt_ctf_field_type_integer_get_encoding(field_type
);
1059 if (encoding
== BT_CTF_STRING_ENCODING_UTF8
1060 || encoding
== BT_CTF_STRING_ENCODING_ASCII
) {
1061 int integer_len
, integer_alignment
;
1063 integer_len
= bt_ctf_field_type_integer_get_size(field_type
);
1064 if (integer_len
< 0) {
1065 return BT_COMPONENT_STATUS_ERROR
;
1067 integer_alignment
= bt_ctf_field_type_get_alignment(field_type
);
1068 if (integer_alignment
< 0) {
1069 return BT_COMPONENT_STATUS_ERROR
;
1071 if (integer_len
== CHAR_BIT
1072 && integer_alignment
== CHAR_BIT
) {
1079 g_string_assign(pretty
->tmp_string
, "");
1081 g_string_append(pretty
->string
, "[");
1085 for (i
= 0; i
< len
; i
++) {
1086 ret
= print_array_field(pretty
, array
, i
, is_string
, print_names
);
1087 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1094 if (pretty
->use_colors
) {
1095 g_string_append(pretty
->string
, COLOR_STRING_VALUE
);
1097 print_escape_string(pretty
, pretty
->tmp_string
->str
);
1098 if (pretty
->use_colors
) {
1099 g_string_append(pretty
->string
, COLOR_RST
);
1102 g_string_append(pretty
->string
, " ]");
1111 enum bt_component_status
print_sequence_field(struct pretty_component
*pretty
,
1112 struct bt_ctf_field
*seq
, uint64_t i
,
1113 bool is_string
, bool print_names
)
1115 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1116 struct bt_ctf_field
*field
= NULL
;
1120 g_string_append(pretty
->string
, ", ");
1122 g_string_append(pretty
->string
, " ");
1125 g_string_append_printf(pretty
->string
, "[%" PRIu64
"] = ", i
);
1128 field
= bt_ctf_field_sequence_get_field(seq
, i
);
1130 ret
= BT_COMPONENT_STATUS_ERROR
;
1133 ret
= print_field(pretty
, field
, print_names
, NULL
, 0);
1140 enum bt_component_status
print_sequence(struct pretty_component
*pretty
,
1141 struct bt_ctf_field
*seq
, bool print_names
)
1143 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1144 struct bt_ctf_field_type
*seq_type
= NULL
, *field_type
= NULL
;
1145 struct bt_ctf_field
*length_field
= NULL
;
1146 enum bt_ctf_field_type_id type_id
;
1149 bool is_string
= false;
1151 seq_type
= bt_ctf_field_get_type(seq
);
1153 ret
= BT_COMPONENT_STATUS_ERROR
;
1156 length_field
= bt_ctf_field_sequence_get_length(seq
);
1157 if (!length_field
) {
1158 ret
= BT_COMPONENT_STATUS_ERROR
;
1161 if (bt_ctf_field_unsigned_integer_get_value(length_field
, &len
) < 0) {
1162 ret
= BT_COMPONENT_STATUS_ERROR
;
1165 field_type
= bt_ctf_field_type_sequence_get_element_type(seq_type
);
1167 ret
= BT_COMPONENT_STATUS_ERROR
;
1170 type_id
= bt_ctf_field_type_get_type_id(field_type
);
1171 if (type_id
== BT_CTF_FIELD_TYPE_ID_INTEGER
) {
1172 enum bt_ctf_string_encoding encoding
;
1174 encoding
= bt_ctf_field_type_integer_get_encoding(field_type
);
1175 if (encoding
== BT_CTF_STRING_ENCODING_UTF8
1176 || encoding
== BT_CTF_STRING_ENCODING_ASCII
) {
1177 int integer_len
, integer_alignment
;
1179 integer_len
= bt_ctf_field_type_integer_get_size(field_type
);
1180 if (integer_len
< 0) {
1181 ret
= BT_COMPONENT_STATUS_ERROR
;
1184 integer_alignment
= bt_ctf_field_type_get_alignment(field_type
);
1185 if (integer_alignment
< 0) {
1186 ret
= BT_COMPONENT_STATUS_ERROR
;
1189 if (integer_len
== CHAR_BIT
1190 && integer_alignment
== CHAR_BIT
) {
1197 g_string_assign(pretty
->tmp_string
, "");
1199 g_string_append(pretty
->string
, "[");
1203 for (i
= 0; i
< len
; i
++) {
1204 ret
= print_sequence_field(pretty
, seq
, i
,
1205 is_string
, print_names
);
1206 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1213 if (pretty
->use_colors
) {
1214 g_string_append(pretty
->string
, COLOR_STRING_VALUE
);
1216 print_escape_string(pretty
, pretty
->tmp_string
->str
);
1217 if (pretty
->use_colors
) {
1218 g_string_append(pretty
->string
, COLOR_RST
);
1221 g_string_append(pretty
->string
, " ]");
1224 bt_put(length_field
);
1231 enum bt_component_status
print_variant(struct pretty_component
*pretty
,
1232 struct bt_ctf_field
*variant
, bool print_names
)
1234 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1235 struct bt_ctf_field
*field
= NULL
;
1237 field
= bt_ctf_field_variant_get_current_field(variant
);
1239 ret
= BT_COMPONENT_STATUS_ERROR
;
1242 g_string_append(pretty
->string
, "{ ");
1246 struct bt_ctf_field
*tag_field
= NULL
;
1247 const char *tag_choice
;
1248 struct bt_ctf_field_type_enumeration_mapping_iterator
*iter
;
1250 tag_field
= bt_ctf_field_variant_get_tag(variant
);
1252 ret
= BT_COMPONENT_STATUS_ERROR
;
1256 iter
= bt_ctf_field_enumeration_get_mappings(tag_field
);
1259 ret
= BT_COMPONENT_STATUS_ERROR
;
1264 bt_ctf_field_type_enumeration_mapping_iterator_get_signed(
1265 iter
, &tag_choice
, NULL
, NULL
);
1269 ret
= BT_COMPONENT_STATUS_ERROR
;
1272 print_field_name_equal(pretty
, rem_(tag_choice
));
1276 ret
= print_field(pretty
, field
, print_names
, NULL
, 0);
1277 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1281 g_string_append(pretty
->string
, " }");
1288 enum bt_component_status
print_field(struct pretty_component
*pretty
,
1289 struct bt_ctf_field
*field
, bool print_names
,
1290 GQuark
*filter_fields
, int filter_array_len
)
1292 enum bt_ctf_field_type_id type_id
;
1294 type_id
= bt_ctf_field_get_type_id(field
);
1296 case CTF_TYPE_INTEGER
:
1297 return print_integer(pretty
, field
);
1298 case CTF_TYPE_FLOAT
:
1302 if (bt_ctf_field_floating_point_get_value(field
, &v
)) {
1303 return BT_COMPONENT_STATUS_ERROR
;
1305 if (pretty
->use_colors
) {
1306 g_string_append(pretty
->string
, COLOR_NUMBER_VALUE
);
1308 g_string_append_printf(pretty
->string
, "%g", v
);
1309 if (pretty
->use_colors
) {
1310 g_string_append(pretty
->string
, COLOR_RST
);
1312 return BT_COMPONENT_STATUS_OK
;
1315 return print_enum(pretty
, field
);
1316 case CTF_TYPE_STRING
:
1317 if (pretty
->use_colors
) {
1318 g_string_append(pretty
->string
, COLOR_STRING_VALUE
);
1320 print_escape_string(pretty
, bt_ctf_field_string_get_value(field
));
1321 if (pretty
->use_colors
) {
1322 g_string_append(pretty
->string
, COLOR_RST
);
1324 return BT_COMPONENT_STATUS_OK
;
1325 case CTF_TYPE_STRUCT
:
1326 return print_struct(pretty
, field
, print_names
, filter_fields
,
1328 case CTF_TYPE_VARIANT
:
1329 return print_variant(pretty
, field
, print_names
);
1330 case CTF_TYPE_ARRAY
:
1331 return print_array(pretty
, field
, print_names
);
1332 case CTF_TYPE_SEQUENCE
:
1333 return print_sequence(pretty
, field
, print_names
);
1335 // TODO: log instead
1336 fprintf(pretty
->err
, "[error] Unknown type id: %d\n", (int) type_id
);
1337 return BT_COMPONENT_STATUS_ERROR
;
1342 enum bt_component_status
print_stream_packet_context(struct pretty_component
*pretty
,
1343 struct bt_ctf_event
*event
)
1345 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1346 struct bt_ctf_packet
*packet
= NULL
;
1347 struct bt_ctf_field
*main_field
= NULL
;
1349 packet
= bt_ctf_event_get_packet(event
);
1351 ret
= BT_COMPONENT_STATUS_ERROR
;
1354 main_field
= bt_ctf_packet_get_context(packet
);
1358 if (!pretty
->start_line
) {
1359 g_string_append(pretty
->string
, ", ");
1361 pretty
->start_line
= false;
1362 if (pretty
->options
.print_scope_field_names
) {
1363 print_name_equal(pretty
, "stream.packet.context");
1365 ret
= print_field(pretty
, main_field
,
1366 pretty
->options
.print_context_field_names
,
1367 stream_packet_context_quarks
,
1368 STREAM_PACKET_CONTEXT_QUARKS_LEN
);
1376 enum bt_component_status
print_event_header_raw(struct pretty_component
*pretty
,
1377 struct bt_ctf_event
*event
)
1379 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1380 struct bt_ctf_field
*main_field
= NULL
;
1382 main_field
= bt_ctf_event_get_header(event
);
1386 if (!pretty
->start_line
) {
1387 g_string_append(pretty
->string
, ", ");
1389 pretty
->start_line
= false;
1390 if (pretty
->options
.print_scope_field_names
) {
1391 print_name_equal(pretty
, "stream.event.header");
1393 ret
= print_field(pretty
, main_field
,
1394 pretty
->options
.print_header_field_names
, NULL
, 0);
1401 enum bt_component_status
print_stream_event_context(struct pretty_component
*pretty
,
1402 struct bt_ctf_event
*event
)
1404 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1405 struct bt_ctf_field
*main_field
= NULL
;
1407 main_field
= bt_ctf_event_get_stream_event_context(event
);
1411 if (!pretty
->start_line
) {
1412 g_string_append(pretty
->string
, ", ");
1414 pretty
->start_line
= false;
1415 if (pretty
->options
.print_scope_field_names
) {
1416 print_name_equal(pretty
, "stream.event.context");
1418 ret
= print_field(pretty
, main_field
,
1419 pretty
->options
.print_context_field_names
, NULL
, 0);
1426 enum bt_component_status
print_event_context(struct pretty_component
*pretty
,
1427 struct bt_ctf_event
*event
)
1429 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1430 struct bt_ctf_field
*main_field
= NULL
;
1432 main_field
= bt_ctf_event_get_event_context(event
);
1436 if (!pretty
->start_line
) {
1437 g_string_append(pretty
->string
, ", ");
1439 pretty
->start_line
= false;
1440 if (pretty
->options
.print_scope_field_names
) {
1441 print_name_equal(pretty
, "event.context");
1443 ret
= print_field(pretty
, main_field
,
1444 pretty
->options
.print_context_field_names
, NULL
, 0);
1451 enum bt_component_status
print_event_payload(struct pretty_component
*pretty
,
1452 struct bt_ctf_event
*event
)
1454 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1455 struct bt_ctf_field
*main_field
= NULL
;
1457 main_field
= bt_ctf_event_get_event_payload(event
);
1461 if (!pretty
->start_line
) {
1462 g_string_append(pretty
->string
, ", ");
1464 pretty
->start_line
= false;
1465 if (pretty
->options
.print_scope_field_names
) {
1466 print_name_equal(pretty
, "event.fields");
1468 ret
= print_field(pretty
, main_field
,
1469 pretty
->options
.print_payload_field_names
, NULL
, 0);
1476 enum bt_component_status
pretty_print_event(struct pretty_component
*pretty
,
1477 struct bt_notification
*event_notif
)
1479 enum bt_component_status ret
;
1480 struct bt_ctf_event
*event
=
1481 bt_notification_event_get_event(event_notif
);
1482 struct bt_clock_class_priority_map
*cc_prio_map
=
1483 bt_notification_event_get_clock_class_priority_map(event_notif
);
1486 assert(cc_prio_map
);
1487 pretty
->start_line
= true;
1488 g_string_assign(pretty
->string
, "");
1489 ret
= print_event_header(pretty
, event
, cc_prio_map
);
1490 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1494 ret
= print_stream_packet_context(pretty
, event
);
1495 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1499 if (pretty
->options
.verbose
) {
1500 ret
= print_event_header_raw(pretty
, event
);
1501 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1506 ret
= print_stream_event_context(pretty
, event
);
1507 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1511 ret
= print_event_context(pretty
, event
);
1512 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1516 ret
= print_event_payload(pretty
, event
);
1517 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1521 g_string_append_c(pretty
->string
, '\n');
1522 if (fwrite(pretty
->string
->str
, pretty
->string
->len
, 1, pretty
->out
) != 1) {
1523 ret
= BT_COMPONENT_STATUS_ERROR
;
1529 bt_put(cc_prio_map
);