Fix: syscall event rule: emission sites not compared in is_equal
[lttng-tools.git] / doc / examples / trigger-condition-event-matches / notification-client.cpp
CommitLineData
595ed92e
JR
1/*
2 * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 */
7
28ab034a
JG
8#include <common/macros.hpp>
9
595ed92e
JR
10#include <lttng/lttng.h>
11
595ed92e
JR
12#include <inttypes.h>
13#include <stdbool.h>
14#include <stddef.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18#include <sys/time.h>
19#include <time.h>
20
21static int print_capture(const struct lttng_condition *condition,
28ab034a
JG
22 const struct lttng_event_field_value *capture,
23 unsigned int indent_level);
595ed92e 24static int print_array(const struct lttng_condition *condition,
28ab034a
JG
25 const struct lttng_event_field_value *array,
26 unsigned int indent_level);
595ed92e
JR
27
28static void indent(unsigned int indentation_level)
29{
30 unsigned int i;
31 for (i = 0; i < indentation_level; i++) {
32 printf(" ");
33 }
34}
35
36static void print_one_event_expr(const struct lttng_event_expr *event_expr)
37{
38 enum lttng_event_expr_type type;
39
40 type = lttng_event_expr_get_type(event_expr);
41
42 switch (type) {
43 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD:
44 {
45 const char *name;
46
28ab034a 47 name = lttng_event_expr_event_payload_field_get_name(event_expr);
595ed92e
JR
48 printf("%s", name);
49
50 break;
51 }
52
53 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD:
54 {
55 const char *name;
56
28ab034a 57 name = lttng_event_expr_channel_context_field_get_name(event_expr);
595ed92e
JR
58 printf("$ctx.%s", name);
59
60 break;
61 }
62
63 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD:
64 {
65 const char *provider_name;
66 const char *type_name;
67
28ab034a
JG
68 provider_name =
69 lttng_event_expr_app_specific_context_field_get_provider_name(event_expr);
70 type_name = lttng_event_expr_app_specific_context_field_get_type_name(event_expr);
595ed92e
JR
71
72 printf("$app.%s:%s", provider_name, type_name);
73
74 break;
75 }
76
77 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT:
78 {
79 unsigned int index;
80 const struct lttng_event_expr *parent_expr;
81 enum lttng_event_expr_status status;
82
28ab034a 83 parent_expr = lttng_event_expr_array_field_element_get_parent_expr(event_expr);
cd9adb8b 84 LTTNG_ASSERT(parent_expr != nullptr);
595ed92e
JR
85
86 print_one_event_expr(parent_expr);
87
28ab034a 88 status = lttng_event_expr_array_field_element_get_index(event_expr, &index);
a0377dfe 89 LTTNG_ASSERT(status == LTTNG_EVENT_EXPR_STATUS_OK);
595ed92e
JR
90
91 printf("[%u]", index);
92
93 break;
94 }
95
96 default:
97 abort();
98 }
99}
100
28ab034a 101static bool action_group_contains_notify(const struct lttng_action *action_group)
595ed92e
JR
102{
103 unsigned int i, count;
28ab034a 104 enum lttng_action_status status = lttng_action_list_get_count(action_group, &count);
595ed92e
JR
105
106 if (status != LTTNG_ACTION_STATUS_OK) {
107 printf("Failed to get action count from action group\n");
108 exit(1);
109 }
110
111 for (i = 0; i < count; i++) {
28ab034a
JG
112 const struct lttng_action *action = lttng_action_list_get_at_index(action_group, i);
113 const enum lttng_action_type action_type = lttng_action_get_type(action);
595ed92e
JR
114
115 if (action_type == LTTNG_ACTION_TYPE_NOTIFY) {
116 return true;
117 }
118 }
119 return false;
120}
121
122static int print_capture(const struct lttng_condition *condition,
28ab034a
JG
123 const struct lttng_event_field_value *capture,
124 unsigned int indent_level)
595ed92e
JR
125{
126 int ret = 0;
127 enum lttng_event_field_value_status event_field_status;
128 uint64_t u_val;
129 int64_t s_val;
130 double d_val;
cd9adb8b 131 const char *string_val = nullptr;
595ed92e
JR
132
133 switch (lttng_event_field_value_get_type(capture)) {
134 case LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_INT:
135 {
136 event_field_status =
28ab034a 137 lttng_event_field_value_unsigned_int_get_value(capture, &u_val);
595ed92e
JR
138 if (event_field_status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
139 ret = 1;
140 goto end;
141 }
142
143 printf("[Unsigned int] %" PRIu64, u_val);
144 break;
145 }
146 case LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_INT:
147 {
28ab034a 148 event_field_status = lttng_event_field_value_signed_int_get_value(capture, &s_val);
595ed92e
JR
149 if (event_field_status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
150 ret = 1;
151 goto end;
152 }
153
154 printf("[Signed int] %" PRId64, s_val);
155 break;
156 }
157 case LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM:
158 {
159 event_field_status =
28ab034a 160 lttng_event_field_value_unsigned_int_get_value(capture, &u_val);
595ed92e
JR
161 if (event_field_status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
162 ret = 1;
163 goto end;
164 }
165
166 printf("[Unsigned enum] %" PRIu64, u_val);
167 break;
168 }
169 case LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM:
170 {
28ab034a 171 event_field_status = lttng_event_field_value_signed_int_get_value(capture, &s_val);
595ed92e
JR
172 if (event_field_status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
173 ret = 1;
174 goto end;
175 }
176
177 printf("[Signed enum] %" PRId64, s_val);
178 break;
179 }
180 case LTTNG_EVENT_FIELD_VALUE_TYPE_REAL:
181 {
28ab034a 182 event_field_status = lttng_event_field_value_real_get_value(capture, &d_val);
595ed92e
JR
183 if (event_field_status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
184 ret = 1;
185 goto end;
186 }
187
188 printf("[Real] %lf", d_val);
189 break;
190 }
191 case LTTNG_EVENT_FIELD_VALUE_TYPE_STRING:
192 {
28ab034a 193 event_field_status = lttng_event_field_value_string_get_value(capture, &string_val);
595ed92e
JR
194 if (event_field_status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
195 ret = 1;
196 goto end;
197 }
198
199 printf("[String] %s", string_val);
200 break;
201 }
202 case LTTNG_EVENT_FIELD_VALUE_TYPE_ARRAY:
203 printf("[Array] [\n");
204 print_array(condition, capture, indent_level);
205 indent(indent_level);
206 printf("]\n");
207 break;
208 case LTTNG_EVENT_FIELD_VALUE_TYPE_UNKNOWN:
209 case LTTNG_EVENT_FIELD_VALUE_TYPE_INVALID:
210 default:
211 ret = 1;
212 break;
213 }
214
215end:
216 return ret;
217}
218
cd9adb8b 219static void print_unavailabe()
595ed92e
JR
220{
221 printf("Capture unavailable");
222}
223
224static int print_array(const struct lttng_condition *condition,
28ab034a
JG
225 const struct lttng_event_field_value *array,
226 unsigned int indent_level)
595ed92e
JR
227{
228 int ret = 0;
229 enum lttng_event_field_value_status event_field_status;
230 unsigned int captured_field_count;
231
28ab034a 232 event_field_status = lttng_event_field_value_array_get_length(array, &captured_field_count);
595ed92e
JR
233 if (event_field_status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
234 ret = 1;
235 goto end;
236 }
237
238 for (unsigned int i = 0; i < captured_field_count; i++) {
cd9adb8b 239 const struct lttng_event_field_value *captured_field = nullptr;
595ed92e 240 const struct lttng_event_expr *expr =
28ab034a
JG
241 lttng_condition_event_rule_matches_get_capture_descriptor_at_index(
242 condition, i);
a0377dfe 243 LTTNG_ASSERT(expr);
595ed92e
JR
244
245 indent(indent_level + 1);
246
247 printf("Field: ");
248 print_one_event_expr(expr);
249 printf(" Value: ");
250
28ab034a
JG
251 event_field_status = lttng_event_field_value_array_get_element_at_index(
252 array, i, &captured_field);
595ed92e 253 if (event_field_status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
28ab034a 254 if (event_field_status == LTTNG_EVENT_FIELD_VALUE_STATUS_UNAVAILABLE) {
595ed92e
JR
255 print_unavailabe();
256 } else {
257 ret = 1;
258 goto end;
259 }
260 } else {
28ab034a 261 print_capture(condition, captured_field, indent_level + 1);
595ed92e
JR
262 }
263
264 if (i + 1 < captured_field_count) {
265 printf(",");
266 } else {
267 printf(".");
268 }
269 printf("\n");
270 }
271
272end:
273 return ret;
274}
275
276static int print_captures(struct lttng_notification *notification)
277{
278 int ret = 0;
28ab034a
JG
279 const struct lttng_evaluation *evaluation = lttng_notification_get_evaluation(notification);
280 const struct lttng_condition *condition = lttng_notification_get_condition(notification);
595ed92e
JR
281
282 /* Status */
283 enum lttng_condition_status condition_status;
284 enum lttng_evaluation_event_rule_matches_status evaluation_status;
285
cd9adb8b 286 const struct lttng_event_field_value *captured_field_array = nullptr;
595ed92e
JR
287 unsigned int expected_capture_field_count;
288
a0377dfe 289 LTTNG_ASSERT(lttng_evaluation_get_type(evaluation) ==
28ab034a 290 LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES);
595ed92e 291
28ab034a
JG
292 condition_status = lttng_condition_event_rule_matches_get_capture_descriptor_count(
293 condition, &expected_capture_field_count);
595ed92e
JR
294 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
295 ret = 1;
296 goto end;
297 }
298
299 if (expected_capture_field_count == 0) {
300 ret = 0;
301 goto end;
302 }
303
28ab034a
JG
304 evaluation_status = lttng_evaluation_event_rule_matches_get_captured_values(
305 evaluation, &captured_field_array);
595ed92e
JR
306 if (evaluation_status != LTTNG_EVALUATION_EVENT_RULE_MATCHES_STATUS_OK) {
307 ret = 1;
308 goto end;
309 }
310
311 printf("Captured field values:\n");
312 print_array(condition, captured_field_array, 1);
313end:
314 return ret;
315}
316
317static int print_notification(struct lttng_notification *notification)
318{
319 int ret = 0;
28ab034a
JG
320 const struct lttng_evaluation *evaluation = lttng_notification_get_evaluation(notification);
321 const enum lttng_condition_type type = lttng_evaluation_get_type(evaluation);
595ed92e
JR
322
323 switch (type) {
324 case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE:
325 printf("Received consumed size notification\n");
326 break;
327 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
328 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
329 printf("Received buffer usage notification\n");
330 break;
331 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
332 printf("Received session rotation ongoing notification\n");
333 break;
334 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
335 printf("Received session rotation completed notification\n");
336 break;
337 case LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES:
338 {
339 const char *trigger_name;
340 enum lttng_trigger_status trigger_status;
341 char time_str[64];
342 struct timeval tv;
343 time_t the_time;
cd9adb8b 344 const struct lttng_trigger *trigger = nullptr;
595ed92e 345
cd9adb8b 346 gettimeofday(&tv, nullptr);
595ed92e
JR
347 the_time = tv.tv_sec;
348
28ab034a 349 strftime(time_str, sizeof(time_str), "[%m-%d-%Y] %T", localtime(&the_time));
595ed92e
JR
350 printf("%s.%ld - ", time_str, tv.tv_usec);
351
352 trigger = lttng_notification_get_trigger(notification);
353 if (!trigger) {
354 fprintf(stderr, "Failed to retrieve notification's trigger");
355 goto end;
356 }
357
358 trigger_status = lttng_trigger_get_name(trigger, &trigger_name);
359 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
360 fprintf(stderr, "Failed to retrieve trigger's name");
361 goto end;
362 }
363
364 printf("Received notification of event rule matches trigger \"%s\"\n",
28ab034a 365 trigger_name);
595ed92e
JR
366 ret = print_captures(notification);
367 break;
368 }
369 default:
370 fprintf(stderr, "Unknown notification type (%d)\n", type);
371 }
372
373end:
374 return ret;
375}
376
377int main(int argc, char **argv)
378{
379 int ret;
cd9adb8b 380 struct lttng_triggers *triggers = nullptr;
595ed92e
JR
381 unsigned int count, i, j, subcription_count = 0, trigger_count;
382 enum lttng_trigger_status trigger_status;
cd9adb8b 383 struct lttng_notification_channel *notification_channel = nullptr;
595ed92e
JR
384
385 if (argc < 2) {
386 fprintf(stderr, "Missing trigger name(s)\n");
387 fprintf(stderr, "Usage: notification-client TRIGGER_NAME ...");
388 ret = -1;
389 goto end;
390 }
391
392 trigger_count = argc - 1;
393
28ab034a
JG
394 notification_channel =
395 lttng_notification_channel_create(lttng_session_daemon_notification_endpoint);
595ed92e
JR
396 if (!notification_channel) {
397 fprintf(stderr, "Failed to create notification channel\n");
398 ret = -1;
399 goto end;
400 }
401
402 ret = lttng_list_triggers(&triggers);
403 if (ret != LTTNG_OK) {
404 fprintf(stderr, "Failed to list triggers\n");
405 goto end;
406 }
407
408 trigger_status = lttng_triggers_get_count(triggers, &count);
409 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
410 fprintf(stderr, "Failed to get trigger count\n");
411 ret = -1;
412 goto end;
413 }
414
415 for (i = 0; i < count; i++) {
28ab034a 416 const struct lttng_trigger *trigger = lttng_triggers_get_at_index(triggers, i);
595ed92e 417 const struct lttng_condition *condition =
28ab034a
JG
418 lttng_trigger_get_const_condition(trigger);
419 const struct lttng_action *action = lttng_trigger_get_const_action(trigger);
420 const enum lttng_action_type action_type = lttng_action_get_type(action);
595ed92e 421 enum lttng_notification_channel_status channel_status;
cd9adb8b 422 const char *trigger_name = nullptr;
595ed92e
JR
423 bool subscribe = false;
424
425 lttng_trigger_get_name(trigger, &trigger_name);
426 for (j = 0; j < trigger_count; j++) {
427 if (!strcmp(trigger_name, argv[j + 1])) {
428 subscribe = true;
429 break;
430 }
431 }
432
433 if (!subscribe) {
434 continue;
435 }
436
437 if (!((action_type == LTTNG_ACTION_TYPE_LIST &&
28ab034a
JG
438 action_group_contains_notify(action)) ||
439 action_type == LTTNG_ACTION_TYPE_NOTIFY)) {
595ed92e 440 printf("The action of trigger \"%s\" is not \"notify\", skipping.\n",
28ab034a 441 trigger_name);
595ed92e
JR
442 continue;
443 }
444
28ab034a
JG
445 channel_status =
446 lttng_notification_channel_subscribe(notification_channel, condition);
447 if (channel_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_ALREADY_SUBSCRIBED) {
595ed92e
JR
448 continue;
449 }
450 if (channel_status) {
28ab034a
JG
451 fprintf(stderr,
452 "Failed to subscribe to notifications of trigger \"%s\"\n",
453 trigger_name);
595ed92e
JR
454 ret = -1;
455 goto end;
456 }
457
28ab034a 458 printf("Subscribed to notifications of trigger \"%s\"\n", trigger_name);
595ed92e
JR
459 subcription_count++;
460 }
461
462 if (subcription_count == 0) {
463 printf("No matching trigger with a notify action found.\n");
464 ret = 0;
465 goto end;
466 }
467
468 for (;;) {
469 struct lttng_notification *notification;
470 enum lttng_notification_channel_status channel_status;
471
28ab034a
JG
472 channel_status = lttng_notification_channel_get_next_notification(
473 notification_channel, &notification);
595ed92e
JR
474 switch (channel_status) {
475 case LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED:
476 printf("Dropped notification\n");
477 break;
478 case LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED:
479 ret = 0;
480 goto end;
481 case LTTNG_NOTIFICATION_CHANNEL_STATUS_OK:
bdfd0a8e
JR
482 ret = print_notification(notification);
483 lttng_notification_destroy(notification);
484 if (ret) {
485 goto end;
486 }
595ed92e
JR
487 break;
488 case LTTNG_NOTIFICATION_CHANNEL_STATUS_CLOSED:
489 printf("Notification channel was closed by peer.\n");
490 break;
491 default:
28ab034a
JG
492 fprintf(stderr,
493 "A communication error occurred on the notification channel.\n");
595ed92e
JR
494 ret = -1;
495 goto end;
496 }
595ed92e
JR
497 }
498end:
499 lttng_triggers_destroy(triggers);
500 lttng_notification_channel_destroy(notification_channel);
501 return !!ret;
502}
This page took 0.058859 seconds and 5 git commands to generate.