2 * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * SPDX-License-Identifier: MIT
8 #include <lttng/lttng.h>
20 static int print_capture(const struct lttng_condition
*condition
,
21 const struct lttng_event_field_value
*capture
,
22 unsigned int indent_level
);
23 static int print_array(const struct lttng_condition
*condition
,
24 const struct lttng_event_field_value
*array
,
25 unsigned int indent_level
);
27 static void indent(unsigned int indentation_level
)
30 for (i
= 0; i
< indentation_level
; i
++) {
35 static void print_one_event_expr(const struct lttng_event_expr
*event_expr
)
37 enum lttng_event_expr_type type
;
39 type
= lttng_event_expr_get_type(event_expr
);
42 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
46 name
= lttng_event_expr_event_payload_field_get_name(
53 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
57 name
= lttng_event_expr_channel_context_field_get_name(
59 printf("$ctx.%s", name
);
64 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
66 const char *provider_name
;
67 const char *type_name
;
69 provider_name
= lttng_event_expr_app_specific_context_field_get_provider_name(
71 type_name
= lttng_event_expr_app_specific_context_field_get_type_name(
74 printf("$app.%s:%s", provider_name
, type_name
);
79 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
82 const struct lttng_event_expr
*parent_expr
;
83 enum lttng_event_expr_status status
;
85 parent_expr
= lttng_event_expr_array_field_element_get_parent_expr(
87 assert(parent_expr
!= NULL
);
89 print_one_event_expr(parent_expr
);
91 status
= lttng_event_expr_array_field_element_get_index(
93 assert(status
== LTTNG_EVENT_EXPR_STATUS_OK
);
95 printf("[%u]", index
);
105 static bool action_group_contains_notify(
106 const struct lttng_action
*action_group
)
108 unsigned int i
, count
;
109 enum lttng_action_status status
=
110 lttng_action_list_get_count(action_group
, &count
);
112 if (status
!= LTTNG_ACTION_STATUS_OK
) {
113 printf("Failed to get action count from action group\n");
117 for (i
= 0; i
< count
; i
++) {
118 const struct lttng_action
*action
=
119 lttng_action_list_get_at_index(action_group
, i
);
120 const enum lttng_action_type action_type
=
121 lttng_action_get_type(action
);
123 if (action_type
== LTTNG_ACTION_TYPE_NOTIFY
) {
130 static int print_capture(const struct lttng_condition
*condition
,
131 const struct lttng_event_field_value
*capture
,
132 unsigned int indent_level
)
135 enum lttng_event_field_value_status event_field_status
;
139 const char *string_val
= NULL
;
141 switch (lttng_event_field_value_get_type(capture
)) {
142 case LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_INT
:
145 lttng_event_field_value_unsigned_int_get_value(
147 if (event_field_status
!= LTTNG_EVENT_FIELD_VALUE_STATUS_OK
) {
152 printf("[Unsigned int] %" PRIu64
, u_val
);
155 case LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_INT
:
158 lttng_event_field_value_signed_int_get_value(
160 if (event_field_status
!= LTTNG_EVENT_FIELD_VALUE_STATUS_OK
) {
165 printf("[Signed int] %" PRId64
, s_val
);
168 case LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM
:
171 lttng_event_field_value_unsigned_int_get_value(
173 if (event_field_status
!= LTTNG_EVENT_FIELD_VALUE_STATUS_OK
) {
178 printf("[Unsigned enum] %" PRIu64
, u_val
);
181 case LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM
:
184 lttng_event_field_value_signed_int_get_value(
186 if (event_field_status
!= LTTNG_EVENT_FIELD_VALUE_STATUS_OK
) {
191 printf("[Signed enum] %" PRId64
, s_val
);
194 case LTTNG_EVENT_FIELD_VALUE_TYPE_REAL
:
196 event_field_status
= lttng_event_field_value_real_get_value(
198 if (event_field_status
!= LTTNG_EVENT_FIELD_VALUE_STATUS_OK
) {
203 printf("[Real] %lf", d_val
);
206 case LTTNG_EVENT_FIELD_VALUE_TYPE_STRING
:
208 event_field_status
= lttng_event_field_value_string_get_value(
209 capture
, &string_val
);
210 if (event_field_status
!= LTTNG_EVENT_FIELD_VALUE_STATUS_OK
) {
215 printf("[String] %s", string_val
);
218 case LTTNG_EVENT_FIELD_VALUE_TYPE_ARRAY
:
219 printf("[Array] [\n");
220 print_array(condition
, capture
, indent_level
);
221 indent(indent_level
);
224 case LTTNG_EVENT_FIELD_VALUE_TYPE_UNKNOWN
:
225 case LTTNG_EVENT_FIELD_VALUE_TYPE_INVALID
:
235 static void print_unavailabe(void)
237 printf("Capture unavailable");
240 static int print_array(const struct lttng_condition
*condition
,
241 const struct lttng_event_field_value
*array
,
242 unsigned int indent_level
)
245 enum lttng_event_field_value_status event_field_status
;
246 unsigned int captured_field_count
;
248 event_field_status
= lttng_event_field_value_array_get_length(
249 array
, &captured_field_count
);
250 if (event_field_status
!= LTTNG_EVENT_FIELD_VALUE_STATUS_OK
) {
255 for (unsigned int i
= 0; i
< captured_field_count
; i
++) {
256 const struct lttng_event_field_value
*captured_field
= NULL
;
257 const struct lttng_event_expr
*expr
=
258 lttng_condition_event_rule_matches_get_capture_descriptor_at_index(
262 indent(indent_level
+ 1);
265 print_one_event_expr(expr
);
269 lttng_event_field_value_array_get_element_at_index(
270 array
, i
, &captured_field
);
271 if (event_field_status
!= LTTNG_EVENT_FIELD_VALUE_STATUS_OK
) {
272 if (event_field_status
==
273 LTTNG_EVENT_FIELD_VALUE_STATUS_UNAVAILABLE
) {
280 print_capture(condition
, captured_field
,
284 if (i
+ 1 < captured_field_count
) {
296 static int print_captures(struct lttng_notification
*notification
)
299 const struct lttng_evaluation
*evaluation
=
300 lttng_notification_get_evaluation(notification
);
301 const struct lttng_condition
*condition
=
302 lttng_notification_get_condition(notification
);
305 enum lttng_condition_status condition_status
;
306 enum lttng_evaluation_event_rule_matches_status evaluation_status
;
308 const struct lttng_event_field_value
*captured_field_array
= NULL
;
309 unsigned int expected_capture_field_count
;
311 assert(lttng_evaluation_get_type(evaluation
) ==
312 LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES
);
315 lttng_condition_event_rule_matches_get_capture_descriptor_count(
317 &expected_capture_field_count
);
318 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
323 if (expected_capture_field_count
== 0) {
329 lttng_evaluation_event_rule_matches_get_captured_values(
330 evaluation
, &captured_field_array
);
331 if (evaluation_status
!= LTTNG_EVALUATION_EVENT_RULE_MATCHES_STATUS_OK
) {
336 printf("Captured field values:\n");
337 print_array(condition
, captured_field_array
, 1);
342 static int print_notification(struct lttng_notification
*notification
)
345 const struct lttng_evaluation
*evaluation
=
346 lttng_notification_get_evaluation(notification
);
347 const enum lttng_condition_type type
=
348 lttng_evaluation_get_type(evaluation
);
351 case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE
:
352 printf("Received consumed size notification\n");
354 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
:
355 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
:
356 printf("Received buffer usage notification\n");
358 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING
:
359 printf("Received session rotation ongoing notification\n");
361 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
:
362 printf("Received session rotation completed notification\n");
364 case LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES
:
366 const char *trigger_name
;
367 enum lttng_trigger_status trigger_status
;
371 const struct lttng_trigger
*trigger
= NULL
;
373 gettimeofday(&tv
, NULL
);
374 the_time
= tv
.tv_sec
;
376 strftime(time_str
, sizeof(time_str
), "[%m-%d-%Y] %T",
377 localtime(&the_time
));
378 printf("%s.%ld - ", time_str
, tv
.tv_usec
);
380 trigger
= lttng_notification_get_trigger(notification
);
382 fprintf(stderr
, "Failed to retrieve notification's trigger");
386 trigger_status
= lttng_trigger_get_name(trigger
, &trigger_name
);
387 if (trigger_status
!= LTTNG_TRIGGER_STATUS_OK
) {
388 fprintf(stderr
, "Failed to retrieve trigger's name");
392 printf("Received notification of event rule matches trigger \"%s\"\n",
394 ret
= print_captures(notification
);
398 fprintf(stderr
, "Unknown notification type (%d)\n", type
);
405 int main(int argc
, char **argv
)
408 struct lttng_triggers
*triggers
= NULL
;
409 unsigned int count
, i
, j
, subcription_count
= 0, trigger_count
;
410 enum lttng_trigger_status trigger_status
;
411 struct lttng_notification_channel
*notification_channel
= NULL
;
414 fprintf(stderr
, "Missing trigger name(s)\n");
415 fprintf(stderr
, "Usage: notification-client TRIGGER_NAME ...");
420 trigger_count
= argc
- 1;
422 notification_channel
= lttng_notification_channel_create(
423 lttng_session_daemon_notification_endpoint
);
424 if (!notification_channel
) {
425 fprintf(stderr
, "Failed to create notification channel\n");
430 ret
= lttng_list_triggers(&triggers
);
431 if (ret
!= LTTNG_OK
) {
432 fprintf(stderr
, "Failed to list triggers\n");
436 trigger_status
= lttng_triggers_get_count(triggers
, &count
);
437 if (trigger_status
!= LTTNG_TRIGGER_STATUS_OK
) {
438 fprintf(stderr
, "Failed to get trigger count\n");
443 for (i
= 0; i
< count
; i
++) {
444 const struct lttng_trigger
*trigger
=
445 lttng_triggers_get_at_index(triggers
, i
);
446 const struct lttng_condition
*condition
=
447 lttng_trigger_get_const_condition(trigger
);
448 const struct lttng_action
*action
=
449 lttng_trigger_get_const_action(trigger
);
450 const enum lttng_action_type action_type
=
451 lttng_action_get_type(action
);
452 enum lttng_notification_channel_status channel_status
;
453 const char *trigger_name
= NULL
;
454 bool subscribe
= false;
456 lttng_trigger_get_name(trigger
, &trigger_name
);
457 for (j
= 0; j
< trigger_count
; j
++) {
458 if (!strcmp(trigger_name
, argv
[j
+ 1])) {
468 if (!((action_type
== LTTNG_ACTION_TYPE_LIST
&&
469 action_group_contains_notify(action
)) ||
470 action_type
== LTTNG_ACTION_TYPE_NOTIFY
)) {
471 printf("The action of trigger \"%s\" is not \"notify\", skipping.\n",
476 channel_status
= lttng_notification_channel_subscribe(
477 notification_channel
, condition
);
478 if (channel_status
==
479 LTTNG_NOTIFICATION_CHANNEL_STATUS_ALREADY_SUBSCRIBED
) {
482 if (channel_status
) {
483 fprintf(stderr
, "Failed to subscribe to notifications of trigger \"%s\"\n",
489 printf("Subscribed to notifications of trigger \"%s\"\n",
494 if (subcription_count
== 0) {
495 printf("No matching trigger with a notify action found.\n");
501 struct lttng_notification
*notification
;
502 enum lttng_notification_channel_status channel_status
;
505 lttng_notification_channel_get_next_notification(
506 notification_channel
,
508 switch (channel_status
) {
509 case LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED
:
510 printf("Dropped notification\n");
512 case LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED
:
515 case LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
:
517 case LTTNG_NOTIFICATION_CHANNEL_STATUS_CLOSED
:
518 printf("Notification channel was closed by peer.\n");
521 fprintf(stderr
, "A communication error occurred on the notification channel.\n");
526 ret
= print_notification(notification
);
527 lttng_notification_destroy(notification
);
533 lttng_triggers_destroy(triggers
);
534 lttng_notification_channel_destroy(notification_channel
);