2 * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * SPDX-License-Identifier: MIT
8 #include <lttng/lttng.h>
19 #include <common/macros.h>
21 static int print_capture(const struct lttng_condition
*condition
,
22 const struct lttng_event_field_value
*capture
,
23 unsigned int indent_level
);
24 static int print_array(const struct lttng_condition
*condition
,
25 const struct lttng_event_field_value
*array
,
26 unsigned int indent_level
);
28 static void indent(unsigned int indentation_level
)
31 for (i
= 0; i
< indentation_level
; i
++) {
36 static void print_one_event_expr(const struct lttng_event_expr
*event_expr
)
38 enum lttng_event_expr_type type
;
40 type
= lttng_event_expr_get_type(event_expr
);
43 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
47 name
= lttng_event_expr_event_payload_field_get_name(
54 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
58 name
= lttng_event_expr_channel_context_field_get_name(
60 printf("$ctx.%s", name
);
65 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
67 const char *provider_name
;
68 const char *type_name
;
70 provider_name
= lttng_event_expr_app_specific_context_field_get_provider_name(
72 type_name
= lttng_event_expr_app_specific_context_field_get_type_name(
75 printf("$app.%s:%s", provider_name
, type_name
);
80 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
83 const struct lttng_event_expr
*parent_expr
;
84 enum lttng_event_expr_status status
;
86 parent_expr
= lttng_event_expr_array_field_element_get_parent_expr(
88 LTTNG_ASSERT(parent_expr
!= NULL
);
90 print_one_event_expr(parent_expr
);
92 status
= lttng_event_expr_array_field_element_get_index(
94 LTTNG_ASSERT(status
== LTTNG_EVENT_EXPR_STATUS_OK
);
96 printf("[%u]", index
);
106 static bool action_group_contains_notify(
107 const struct lttng_action
*action_group
)
109 unsigned int i
, count
;
110 enum lttng_action_status status
=
111 lttng_action_list_get_count(action_group
, &count
);
113 if (status
!= LTTNG_ACTION_STATUS_OK
) {
114 printf("Failed to get action count from action group\n");
118 for (i
= 0; i
< count
; i
++) {
119 const struct lttng_action
*action
=
120 lttng_action_list_get_at_index(action_group
, i
);
121 const enum lttng_action_type action_type
=
122 lttng_action_get_type(action
);
124 if (action_type
== LTTNG_ACTION_TYPE_NOTIFY
) {
131 static int print_capture(const struct lttng_condition
*condition
,
132 const struct lttng_event_field_value
*capture
,
133 unsigned int indent_level
)
136 enum lttng_event_field_value_status event_field_status
;
140 const char *string_val
= NULL
;
142 switch (lttng_event_field_value_get_type(capture
)) {
143 case LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_INT
:
146 lttng_event_field_value_unsigned_int_get_value(
148 if (event_field_status
!= LTTNG_EVENT_FIELD_VALUE_STATUS_OK
) {
153 printf("[Unsigned int] %" PRIu64
, u_val
);
156 case LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_INT
:
159 lttng_event_field_value_signed_int_get_value(
161 if (event_field_status
!= LTTNG_EVENT_FIELD_VALUE_STATUS_OK
) {
166 printf("[Signed int] %" PRId64
, s_val
);
169 case LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM
:
172 lttng_event_field_value_unsigned_int_get_value(
174 if (event_field_status
!= LTTNG_EVENT_FIELD_VALUE_STATUS_OK
) {
179 printf("[Unsigned enum] %" PRIu64
, u_val
);
182 case LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM
:
185 lttng_event_field_value_signed_int_get_value(
187 if (event_field_status
!= LTTNG_EVENT_FIELD_VALUE_STATUS_OK
) {
192 printf("[Signed enum] %" PRId64
, s_val
);
195 case LTTNG_EVENT_FIELD_VALUE_TYPE_REAL
:
197 event_field_status
= lttng_event_field_value_real_get_value(
199 if (event_field_status
!= LTTNG_EVENT_FIELD_VALUE_STATUS_OK
) {
204 printf("[Real] %lf", d_val
);
207 case LTTNG_EVENT_FIELD_VALUE_TYPE_STRING
:
209 event_field_status
= lttng_event_field_value_string_get_value(
210 capture
, &string_val
);
211 if (event_field_status
!= LTTNG_EVENT_FIELD_VALUE_STATUS_OK
) {
216 printf("[String] %s", string_val
);
219 case LTTNG_EVENT_FIELD_VALUE_TYPE_ARRAY
:
220 printf("[Array] [\n");
221 print_array(condition
, capture
, indent_level
);
222 indent(indent_level
);
225 case LTTNG_EVENT_FIELD_VALUE_TYPE_UNKNOWN
:
226 case LTTNG_EVENT_FIELD_VALUE_TYPE_INVALID
:
236 static void print_unavailabe(void)
238 printf("Capture unavailable");
241 static int print_array(const struct lttng_condition
*condition
,
242 const struct lttng_event_field_value
*array
,
243 unsigned int indent_level
)
246 enum lttng_event_field_value_status event_field_status
;
247 unsigned int captured_field_count
;
249 event_field_status
= lttng_event_field_value_array_get_length(
250 array
, &captured_field_count
);
251 if (event_field_status
!= LTTNG_EVENT_FIELD_VALUE_STATUS_OK
) {
256 for (unsigned int i
= 0; i
< captured_field_count
; i
++) {
257 const struct lttng_event_field_value
*captured_field
= NULL
;
258 const struct lttng_event_expr
*expr
=
259 lttng_condition_event_rule_matches_get_capture_descriptor_at_index(
263 indent(indent_level
+ 1);
266 print_one_event_expr(expr
);
270 lttng_event_field_value_array_get_element_at_index(
271 array
, i
, &captured_field
);
272 if (event_field_status
!= LTTNG_EVENT_FIELD_VALUE_STATUS_OK
) {
273 if (event_field_status
==
274 LTTNG_EVENT_FIELD_VALUE_STATUS_UNAVAILABLE
) {
281 print_capture(condition
, captured_field
,
285 if (i
+ 1 < captured_field_count
) {
297 static int print_captures(struct lttng_notification
*notification
)
300 const struct lttng_evaluation
*evaluation
=
301 lttng_notification_get_evaluation(notification
);
302 const struct lttng_condition
*condition
=
303 lttng_notification_get_condition(notification
);
306 enum lttng_condition_status condition_status
;
307 enum lttng_evaluation_event_rule_matches_status evaluation_status
;
309 const struct lttng_event_field_value
*captured_field_array
= NULL
;
310 unsigned int expected_capture_field_count
;
312 LTTNG_ASSERT(lttng_evaluation_get_type(evaluation
) ==
313 LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES
);
316 lttng_condition_event_rule_matches_get_capture_descriptor_count(
318 &expected_capture_field_count
);
319 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
324 if (expected_capture_field_count
== 0) {
330 lttng_evaluation_event_rule_matches_get_captured_values(
331 evaluation
, &captured_field_array
);
332 if (evaluation_status
!= LTTNG_EVALUATION_EVENT_RULE_MATCHES_STATUS_OK
) {
337 printf("Captured field values:\n");
338 print_array(condition
, captured_field_array
, 1);
343 static int print_notification(struct lttng_notification
*notification
)
346 const struct lttng_evaluation
*evaluation
=
347 lttng_notification_get_evaluation(notification
);
348 const enum lttng_condition_type type
=
349 lttng_evaluation_get_type(evaluation
);
352 case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE
:
353 printf("Received consumed size notification\n");
355 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
:
356 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
:
357 printf("Received buffer usage notification\n");
359 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING
:
360 printf("Received session rotation ongoing notification\n");
362 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
:
363 printf("Received session rotation completed notification\n");
365 case LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES
:
367 const char *trigger_name
;
368 enum lttng_trigger_status trigger_status
;
372 const struct lttng_trigger
*trigger
= NULL
;
374 gettimeofday(&tv
, NULL
);
375 the_time
= tv
.tv_sec
;
377 strftime(time_str
, sizeof(time_str
), "[%m-%d-%Y] %T",
378 localtime(&the_time
));
379 printf("%s.%ld - ", time_str
, tv
.tv_usec
);
381 trigger
= lttng_notification_get_trigger(notification
);
383 fprintf(stderr
, "Failed to retrieve notification's trigger");
387 trigger_status
= lttng_trigger_get_name(trigger
, &trigger_name
);
388 if (trigger_status
!= LTTNG_TRIGGER_STATUS_OK
) {
389 fprintf(stderr
, "Failed to retrieve trigger's name");
393 printf("Received notification of event rule matches trigger \"%s\"\n",
395 ret
= print_captures(notification
);
399 fprintf(stderr
, "Unknown notification type (%d)\n", type
);
406 int main(int argc
, char **argv
)
409 struct lttng_triggers
*triggers
= NULL
;
410 unsigned int count
, i
, j
, subcription_count
= 0, trigger_count
;
411 enum lttng_trigger_status trigger_status
;
412 struct lttng_notification_channel
*notification_channel
= NULL
;
415 fprintf(stderr
, "Missing trigger name(s)\n");
416 fprintf(stderr
, "Usage: notification-client TRIGGER_NAME ...");
421 trigger_count
= argc
- 1;
423 notification_channel
= lttng_notification_channel_create(
424 lttng_session_daemon_notification_endpoint
);
425 if (!notification_channel
) {
426 fprintf(stderr
, "Failed to create notification channel\n");
431 ret
= lttng_list_triggers(&triggers
);
432 if (ret
!= LTTNG_OK
) {
433 fprintf(stderr
, "Failed to list triggers\n");
437 trigger_status
= lttng_triggers_get_count(triggers
, &count
);
438 if (trigger_status
!= LTTNG_TRIGGER_STATUS_OK
) {
439 fprintf(stderr
, "Failed to get trigger count\n");
444 for (i
= 0; i
< count
; i
++) {
445 const struct lttng_trigger
*trigger
=
446 lttng_triggers_get_at_index(triggers
, i
);
447 const struct lttng_condition
*condition
=
448 lttng_trigger_get_const_condition(trigger
);
449 const struct lttng_action
*action
=
450 lttng_trigger_get_const_action(trigger
);
451 const enum lttng_action_type action_type
=
452 lttng_action_get_type(action
);
453 enum lttng_notification_channel_status channel_status
;
454 const char *trigger_name
= NULL
;
455 bool subscribe
= false;
457 lttng_trigger_get_name(trigger
, &trigger_name
);
458 for (j
= 0; j
< trigger_count
; j
++) {
459 if (!strcmp(trigger_name
, argv
[j
+ 1])) {
469 if (!((action_type
== LTTNG_ACTION_TYPE_LIST
&&
470 action_group_contains_notify(action
)) ||
471 action_type
== LTTNG_ACTION_TYPE_NOTIFY
)) {
472 printf("The action of trigger \"%s\" is not \"notify\", skipping.\n",
477 channel_status
= lttng_notification_channel_subscribe(
478 notification_channel
, condition
);
479 if (channel_status
==
480 LTTNG_NOTIFICATION_CHANNEL_STATUS_ALREADY_SUBSCRIBED
) {
483 if (channel_status
) {
484 fprintf(stderr
, "Failed to subscribe to notifications of trigger \"%s\"\n",
490 printf("Subscribed to notifications of trigger \"%s\"\n",
495 if (subcription_count
== 0) {
496 printf("No matching trigger with a notify action found.\n");
502 struct lttng_notification
*notification
;
503 enum lttng_notification_channel_status channel_status
;
506 lttng_notification_channel_get_next_notification(
507 notification_channel
,
509 switch (channel_status
) {
510 case LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED
:
511 printf("Dropped notification\n");
513 case LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED
:
516 case LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
:
518 case LTTNG_NOTIFICATION_CHANNEL_STATUS_CLOSED
:
519 printf("Notification channel was closed by peer.\n");
522 fprintf(stderr
, "A communication error occurred on the notification channel.\n");
527 ret
= print_notification(notification
);
528 lttng_notification_destroy(notification
);
534 lttng_triggers_destroy(triggers
);
535 lttng_notification_channel_destroy(notification_channel
);