2 * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * SPDX-License-Identifier: MIT
8 #include <lttng/condition/event-rule.h>
9 #include <lttng/lttng.h>
21 static int print_capture(const struct lttng_event_field_value
*capture
,
22 unsigned int indent_level
);
23 static int print_array(const struct lttng_event_field_value
*array
,
24 unsigned int indent_level
);
26 static void indent(unsigned int indentation_level
)
29 for (i
= 0; i
< indentation_level
; i
++) {
34 static bool action_group_contains_notify(
35 const struct lttng_action
*action_group
)
37 unsigned int i
, count
;
38 enum lttng_action_status status
=
39 lttng_action_group_get_count(action_group
, &count
);
41 if (status
!= LTTNG_ACTION_STATUS_OK
) {
42 printf("Failed to get action count from action group\n");
46 for (i
= 0; i
< count
; i
++) {
47 const struct lttng_action
*action
=
48 lttng_action_group_get_at_index_const(
50 const enum lttng_action_type action_type
=
51 lttng_action_get_type(action
);
53 if (action_type
== LTTNG_ACTION_TYPE_NOTIFY
) {
60 static int print_capture(const struct lttng_event_field_value
*capture
,
61 unsigned int indent_level
)
64 enum lttng_event_field_value_status event_field_status
;
65 enum lttng_event_field_value_type type
;
69 const char *string_val
= NULL
;
73 switch (lttng_event_field_value_get_type(capture
)) {
74 case LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_INT
:
77 lttng_event_field_value_unsigned_int_get_value(
79 if (event_field_status
!= LTTNG_EVENT_FIELD_VALUE_STATUS_OK
) {
84 printf("Unsigned int: %" PRIu64
, u_val
);
87 case LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_INT
:
90 lttng_event_field_value_signed_int_get_value(
92 if (event_field_status
!= LTTNG_EVENT_FIELD_VALUE_STATUS_OK
) {
97 printf("Signed int: %" PRId64
, s_val
);
100 case LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM
:
103 lttng_event_field_value_unsigned_int_get_value(
105 if (event_field_status
!= LTTNG_EVENT_FIELD_VALUE_STATUS_OK
) {
110 printf("Unsigned enum: %" PRIu64
, u_val
);
113 case LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM
:
116 lttng_event_field_value_signed_int_get_value(
118 if (event_field_status
!= LTTNG_EVENT_FIELD_VALUE_STATUS_OK
) {
123 printf("Signed enum: %" PRId64
, s_val
);
126 case LTTNG_EVENT_FIELD_VALUE_TYPE_REAL
:
128 event_field_status
= lttng_event_field_value_real_get_value(
130 if (event_field_status
!= LTTNG_EVENT_FIELD_VALUE_STATUS_OK
) {
135 printf("Real: %lf", d_val
);
138 case LTTNG_EVENT_FIELD_VALUE_TYPE_STRING
:
140 string_val
= lttng_event_field_value_string_get_value(capture
);
141 if (string_val
== NULL
) {
146 printf("String: %s", string_val
);
149 case LTTNG_EVENT_FIELD_VALUE_TYPE_ARRAY
:
150 printf("Array: [\n");
151 print_array(capture
, indent_level
);
152 indent(indent_level
);
155 case LTTNG_EVENT_FIELD_VALUE_TYPE_UNKNOWN
:
156 case LTTNG_EVENT_FIELD_VALUE_TYPE_INVALID
:
166 static void print_unavailabe(unsigned int indent_level
)
168 indent(indent_level
);
169 printf("CAPTURE UNAVAILABE");
172 static int print_array(const struct lttng_event_field_value
*array
,
173 unsigned int indent_level
)
176 enum lttng_event_field_value_status event_field_status
;
177 unsigned int captured_field_count
;
179 event_field_status
= lttng_event_field_value_array_get_length(
180 array
, &captured_field_count
);
181 if (event_field_status
!= LTTNG_EVENT_FIELD_VALUE_STATUS_OK
) {
186 for (unsigned int i
= 0; i
< captured_field_count
; i
++) {
187 const struct lttng_event_field_value
*captured_field
= NULL
;
189 lttng_event_field_value_array_get_element_at_index(
190 array
, i
, &captured_field
);
191 if (event_field_status
!= LTTNG_EVENT_FIELD_VALUE_STATUS_OK
) {
192 if (event_field_status
==
193 LTTNG_EVENT_FIELD_VALUE_STATUS_UNAVAILABLE
) {
194 print_unavailabe(indent_level
+ 1);
200 print_capture(captured_field
, indent_level
+ 1);
202 if (i
+ 1 < captured_field_count
) {
212 static int print_captures(struct lttng_notification
*notification
)
215 const struct lttng_evaluation
*evaluation
=
216 lttng_notification_get_evaluation(notification
);
217 const struct lttng_condition
*condition
=
218 lttng_notification_get_condition(notification
);
221 enum lttng_condition_status condition_status
;
222 enum lttng_evaluation_status evaluation_status
;
223 enum lttng_event_field_value_status event_field_status
;
225 const struct lttng_event_field_value
*captured_field_array
= NULL
;
226 unsigned int expected_capture_field_count
;
227 unsigned int captured_field_count
;
229 assert(lttng_evaluation_get_type(evaluation
) ==
230 LTTNG_CONDITION_TYPE_EVENT_RULE_HIT
);
233 lttng_condition_event_rule_get_capture_descriptor_count(
235 &expected_capture_field_count
);
236 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
241 if (expected_capture_field_count
== 0) {
246 evaluation_status
= lttng_evaluation_get_captured_values(
247 evaluation
, &captured_field_array
);
248 if (evaluation_status
!= LTTNG_EVALUATION_STATUS_OK
) {
253 printf("Captured field values:\n");
254 print_array(captured_field_array
, 1);
259 static int print_notification(struct lttng_notification
*notification
)
262 const struct lttng_evaluation
*evaluation
=
263 lttng_notification_get_evaluation(notification
);
264 const enum lttng_condition_type type
=
265 lttng_evaluation_get_type(evaluation
);
268 case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE
:
269 printf("Received consumed size notification\n");
271 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
:
272 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
:
273 printf("Received buffer usage notification\n");
275 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING
:
276 printf("Received session rotation ongoing notification\n");
278 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
:
279 printf("Received session rotation completed notification\n");
281 case LTTNG_CONDITION_TYPE_EVENT_RULE_HIT
:
283 const char *trigger_name
;
284 enum lttng_evaluation_status evaluation_status
;
289 gettimeofday(&tv
, NULL
);
290 the_time
= tv
.tv_sec
;
292 strftime(time_str
, sizeof(time_str
), "[%m-%d-%Y] %T",
293 localtime(&the_time
));
294 printf("%s.%ld - ", time_str
, tv
.tv_usec
);
297 lttng_evaluation_event_rule_get_trigger_name(
298 evaluation
, &trigger_name
);
299 if (evaluation_status
!= LTTNG_EVALUATION_STATUS_OK
) {
300 fprintf(stderr
, "Failed to get trigger name of event rule notification\n");
305 printf("Received notification of event rule trigger \"%s\"\n",
307 ret
= print_captures(notification
);
311 fprintf(stderr
, "Unknown notification type (%d)\n", type
);
317 int main(int argc
, char **argv
)
320 struct lttng_triggers
*triggers
= NULL
;
321 unsigned int count
, i
, j
, subcription_count
= 0, trigger_count
;
322 enum lttng_trigger_status trigger_status
;
323 struct lttng_notification_channel
*notification_channel
= NULL
;
326 fprintf(stderr
, "Missing trigger name(s)\n");
327 fprintf(stderr
, "Usage: notification-client TRIGGER_NAME ...");
332 trigger_count
= argc
- 1;
334 notification_channel
= lttng_notification_channel_create(
335 lttng_session_daemon_notification_endpoint
);
336 if (!notification_channel
) {
337 fprintf(stderr
, "Failed to create notification channel\n");
342 ret
= lttng_list_triggers(&triggers
);
344 fprintf(stderr
, "Failed to list triggers\n");
348 trigger_status
= lttng_triggers_get_count(triggers
, &count
);
349 if (trigger_status
!= LTTNG_TRIGGER_STATUS_OK
) {
350 fprintf(stderr
, "Failed to get trigger count\n");
355 for (i
= 0; i
< count
; i
++) {
356 const struct lttng_trigger
*trigger
=
357 lttng_triggers_get_at_index(triggers
, i
);
358 const struct lttng_condition
*condition
=
359 lttng_trigger_get_const_condition(trigger
);
360 const struct lttng_action
*action
=
361 lttng_trigger_get_const_action(trigger
);
362 const enum lttng_action_type action_type
=
363 lttng_action_get_type(action
);
364 enum lttng_notification_channel_status channel_status
;
365 const char *trigger_name
= NULL
;
366 bool subscribe
= false;
368 lttng_trigger_get_name(trigger
, &trigger_name
);
369 for (j
= 0; j
< trigger_count
; j
++) {
370 if (!strcmp(trigger_name
, argv
[j
+ 1])) {
380 if (!((action_type
== LTTNG_ACTION_TYPE_GROUP
&&
381 action_group_contains_notify(action
)) ||
382 action_type
== LTTNG_ACTION_TYPE_NOTIFY
)) {
383 printf("The action of trigger \"%s\" is not \"notify\", skipping.\n",
388 channel_status
= lttng_notification_channel_subscribe(
389 notification_channel
, condition
);
390 if (channel_status
==
391 LTTNG_NOTIFICATION_CHANNEL_STATUS_ALREADY_SUBSCRIBED
) {
394 if (channel_status
) {
395 fprintf(stderr
, "Failed to subscribe to notifications of trigger \"%s\"\n",
401 printf("Subscribed to notifications of trigger \"%s\"\n",
406 if (subcription_count
== 0) {
407 printf("No matching trigger with a notify action found.\n");
413 struct lttng_notification
*notification
;
414 enum lttng_notification_channel_status channel_status
;
417 lttng_notification_channel_get_next_notification(
418 notification_channel
,
420 switch (channel_status
) {
421 case LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED
:
422 printf("Dropped notification\n");
424 case LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED
:
427 case LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
:
429 case LTTNG_NOTIFICATION_CHANNEL_STATUS_CLOSED
:
430 printf("Notification channel was closed by peer.\n");
433 fprintf(stderr
, "A communication error occurred on the notification channel.\n");
438 ret
= print_notification(notification
);
439 lttng_notification_destroy(notification
);
445 lttng_triggers_destroy(triggers
);
446 lttng_notification_channel_destroy(notification_channel
);