CLI: make list-triggers command print capture expressions
[lttng-tools.git] / src / bin / lttng / commands / list_triggers.c
... / ...
CommitLineData
1/*
2 * Copyright (C) 2021 Simon Marchi <simon.marchi@efficios.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
8#include <stdio.h>
9
10#include "../command.h"
11
12#include "common/argpar/argpar.h"
13#include "common/dynamic-array.h"
14#include "common/mi-lttng.h"
15/* For lttng_condition_type_str(). */
16#include "lttng/condition/condition-internal.h"
17/* For lttng_domain_type_str(). */
18#include "lttng/domain-internal.h"
19
20#ifdef LTTNG_EMBED_HELP
21static const char help_msg[] =
22#include <lttng-list-triggers.1.h>
23;
24#endif
25
26enum {
27 OPT_HELP,
28 OPT_LIST_OPTIONS,
29};
30
31static const
32struct argpar_opt_descr list_trigger_options[] = {
33 { OPT_HELP, 'h', "help", false },
34 { OPT_LIST_OPTIONS, '\0', "list-options", false },
35 ARGPAR_OPT_DESCR_SENTINEL,
36};
37
38static
39void print_event_rule_tracepoint(const struct lttng_event_rule *event_rule)
40{
41 enum lttng_event_rule_status event_rule_status;
42 enum lttng_domain_type domain_type;
43 const char *pattern;
44 const char *filter;
45 int log_level;
46 unsigned int exclusions_count;
47 int i;
48
49 event_rule_status = lttng_event_rule_tracepoint_get_pattern(
50 event_rule, &pattern);
51 assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK);
52
53 event_rule_status = lttng_event_rule_tracepoint_get_domain_type(
54 event_rule, &domain_type);
55 assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK);
56
57 _MSG(" rule: %s (type: tracepoint, domain: %s", pattern,
58 lttng_domain_type_str(domain_type));
59
60 event_rule_status = lttng_event_rule_tracepoint_get_filter(
61 event_rule, &filter);
62 if (event_rule_status == LTTNG_EVENT_RULE_STATUS_OK) {
63 _MSG(", filter: %s", filter);
64 } else {
65 assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_UNSET);
66 }
67
68 event_rule_status = lttng_event_rule_tracepoint_get_log_level(
69 event_rule, &log_level);
70 if (event_rule_status == LTTNG_EVENT_RULE_STATUS_OK) {
71 enum lttng_loglevel_type log_level_type;
72 const char *log_level_op;
73
74 event_rule_status = lttng_event_rule_tracepoint_get_log_level_type(
75 event_rule, &log_level_type);
76 assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK);
77 assert(log_level_type == LTTNG_EVENT_LOGLEVEL_RANGE ||
78 log_level_type == LTTNG_EVENT_LOGLEVEL_SINGLE);
79
80 log_level_op = (log_level_type == LTTNG_EVENT_LOGLEVEL_RANGE ? "<=" : "==");
81
82 _MSG(", log level %s %s", log_level_op,
83 mi_lttng_loglevel_string(
84 log_level, domain_type));
85 } else {
86 assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_UNSET);
87 }
88
89 event_rule_status = lttng_event_rule_tracepoint_get_exclusions_count(
90 event_rule, &exclusions_count);
91 assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK);
92 if (exclusions_count > 0) {
93 _MSG(", exclusions: ");
94 for (i = 0; i < exclusions_count; i++) {
95 const char *exclusion;
96
97 event_rule_status = lttng_event_rule_tracepoint_get_exclusion_at_index(
98 event_rule, i, &exclusion);
99 assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK);
100
101 _MSG("%s%s", i > 0 ? "," : "", exclusion);
102 }
103 }
104
105 MSG(")");
106}
107
108static void print_kernel_probe_location(
109 const struct lttng_kernel_probe_location *location)
110{
111 enum lttng_kernel_probe_location_status status;
112 switch (lttng_kernel_probe_location_get_type(location)) {
113 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS:
114 {
115 uint64_t address;
116
117 status = lttng_kernel_probe_location_address_get_address(
118 location, &address);
119 if (status != LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK) {
120 ERR("Getting kernel probe location address failed.");
121 goto end;
122 }
123
124 _MSG("0x%" PRIx64, address);
125
126 break;
127 }
128 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET:
129 {
130 uint64_t offset;
131 const char *symbol_name;
132
133 symbol_name = lttng_kernel_probe_location_symbol_get_name(
134 location);
135 if (!symbol_name) {
136 ERR("Getting kernel probe location symbol name failed.");
137 goto end;
138 }
139
140 status = lttng_kernel_probe_location_symbol_get_offset(
141 location, &offset);
142 if (status != LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK) {
143 ERR("Getting kernel probe location address failed.");
144 goto end;
145 }
146
147 if (offset == 0) {
148 _MSG("%s", symbol_name);
149 } else {
150 _MSG("%s+0x%" PRIx64, symbol_name, offset);
151 }
152
153 break;
154 }
155 default:
156 abort();
157 };
158end:
159 return;
160}
161
162static
163void print_event_rule_kprobe(const struct lttng_event_rule *event_rule)
164{
165 enum lttng_event_rule_status event_rule_status;
166 const char *name;
167 const struct lttng_kernel_probe_location *location;
168
169 assert(lttng_event_rule_get_type(event_rule) == LTTNG_EVENT_RULE_TYPE_KPROBE);
170
171 event_rule_status = lttng_event_rule_kprobe_get_name(event_rule, &name);
172 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
173 ERR("Failed to get kprobe event rule's name.");
174 goto end;
175 }
176
177 event_rule_status = lttng_event_rule_kprobe_get_location(
178 event_rule, &location);
179 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
180 ERR("Failed to get kprobe event rule's location.");
181 goto end;
182 }
183
184 _MSG(" rule: %s (type: probe, location: ", name);
185
186 print_kernel_probe_location(location);
187
188 MSG(")");
189
190end:
191 return;
192}
193
194static
195void print_event_rule_uprobe(const struct lttng_event_rule *event_rule)
196{
197 enum lttng_event_rule_status event_rule_status;
198 const char *name;
199 const struct lttng_userspace_probe_location *location;
200 enum lttng_userspace_probe_location_type userspace_probe_location_type;
201
202 assert(lttng_event_rule_get_type(event_rule) == LTTNG_EVENT_RULE_TYPE_UPROBE);
203
204 event_rule_status = lttng_event_rule_uprobe_get_name(event_rule, &name);
205 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
206 ERR("Failed to get uprobe event rule's name.");
207 goto end;
208 }
209
210 event_rule_status = lttng_event_rule_uprobe_get_location(
211 event_rule, &location);
212 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
213 ERR("Failed to get uprobe event rule's location.");
214 goto end;
215 }
216
217 _MSG(" rule: %s (type: userspace probe, location: ", name);
218
219 userspace_probe_location_type =
220 lttng_userspace_probe_location_get_type(location);
221
222 switch (userspace_probe_location_type) {
223 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
224 {
225 const char *binary_path, *function_name;
226
227 binary_path = lttng_userspace_probe_location_function_get_binary_path(
228 location);
229 function_name = lttng_userspace_probe_location_function_get_function_name(
230 location);
231
232 _MSG("%s:%s", binary_path, function_name);
233 break;
234 }
235 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
236 _MSG("SDT not implemented yet");
237 break;
238 default:
239 abort();
240 }
241
242 MSG(")");
243
244end:
245 return;
246}
247
248static
249void print_event_rule_syscall(const struct lttng_event_rule *event_rule)
250{
251 const char *pattern, *filter;
252 enum lttng_event_rule_status event_rule_status;
253
254 assert(lttng_event_rule_get_type(event_rule) == LTTNG_EVENT_RULE_TYPE_SYSCALL);
255
256 event_rule_status = lttng_event_rule_syscall_get_pattern(
257 event_rule, &pattern);
258 assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK);
259
260 _MSG(" rule: %s (type: syscall", pattern);
261
262 event_rule_status = lttng_event_rule_syscall_get_filter(
263 event_rule, &filter);
264 if (event_rule_status == LTTNG_EVENT_RULE_STATUS_OK) {
265 _MSG(", filter: %s", filter);
266 } else {
267 assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_UNSET);
268 }
269
270 MSG(")");
271}
272
273static
274void print_event_rule(const struct lttng_event_rule *event_rule)
275{
276 const enum lttng_event_rule_type event_rule_type =
277 lttng_event_rule_get_type(event_rule);
278
279 switch (event_rule_type) {
280 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT:
281 print_event_rule_tracepoint(event_rule);
282 break;
283 case LTTNG_EVENT_RULE_TYPE_KPROBE:
284 print_event_rule_kprobe(event_rule);
285 break;
286 case LTTNG_EVENT_RULE_TYPE_UPROBE:
287 print_event_rule_uprobe(event_rule);
288 break;
289 case LTTNG_EVENT_RULE_TYPE_SYSCALL:
290 print_event_rule_syscall(event_rule);
291 break;
292 default:
293 abort();
294 }
295}
296
297static
298void print_one_event_expr(const struct lttng_event_expr *event_expr)
299{
300 enum lttng_event_expr_type type;
301
302 type = lttng_event_expr_get_type(event_expr);
303
304 switch (type) {
305 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD:
306 {
307 const char *name;
308
309 name = lttng_event_expr_event_payload_field_get_name(
310 event_expr);
311 _MSG("%s", name);
312
313 break;
314 }
315 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD:
316 {
317 const char *name;
318
319 name = lttng_event_expr_channel_context_field_get_name(
320 event_expr);
321 _MSG("$ctx.%s", name);
322
323 break;
324 }
325 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD:
326 {
327 const char *provider_name;
328 const char *type_name;
329
330 provider_name = lttng_event_expr_app_specific_context_field_get_provider_name(
331 event_expr);
332 type_name = lttng_event_expr_app_specific_context_field_get_type_name(
333 event_expr);
334
335 _MSG("$app.%s:%s", provider_name, type_name);
336
337 break;
338 }
339 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT:
340 {
341 unsigned int index;
342 const struct lttng_event_expr *parent_expr;
343 enum lttng_event_expr_status status;
344
345 parent_expr = lttng_event_expr_array_field_element_get_parent_expr(
346 event_expr);
347 assert(parent_expr != NULL);
348
349 print_one_event_expr(parent_expr);
350
351 status = lttng_event_expr_array_field_element_get_index(
352 event_expr, &index);
353 assert(status == LTTNG_EVENT_EXPR_STATUS_OK);
354
355 _MSG("[%u]", index);
356
357 break;
358 }
359 default:
360 abort();
361 }
362}
363
364static
365void print_condition_event_rule_hit(const struct lttng_condition *condition)
366{
367 const struct lttng_event_rule *event_rule;
368 enum lttng_condition_status condition_status;
369 unsigned int cap_desc_count, i;
370
371 condition_status =
372 lttng_condition_event_rule_get_rule(condition, &event_rule);
373 assert(condition_status == LTTNG_CONDITION_STATUS_OK);
374
375 print_event_rule(event_rule);
376
377 condition_status =
378 lttng_condition_event_rule_get_capture_descriptor_count(
379 condition, &cap_desc_count);
380 assert(condition_status == LTTNG_CONDITION_STATUS_OK);
381
382 if (cap_desc_count > 0) {
383 MSG(" captures:");
384
385 for (i = 0; i < cap_desc_count; i++) {
386 const struct lttng_event_expr *cap_desc =
387 lttng_condition_event_rule_get_capture_descriptor_at_index(
388 condition, i);
389
390 _MSG(" - ");
391 print_one_event_expr(cap_desc);
392 MSG("");
393 }
394 }
395}
396
397static
398void print_one_action(const struct lttng_action *action)
399{
400 enum lttng_action_type action_type;
401 enum lttng_action_status action_status;
402 const char *value;
403
404 action_type = lttng_action_get_type(action);
405 assert(action_type != LTTNG_ACTION_TYPE_GROUP);
406
407 switch (action_type) {
408 case LTTNG_ACTION_TYPE_NOTIFY:
409 MSG("notify");
410 break;
411 case LTTNG_ACTION_TYPE_START_SESSION:
412 action_status = lttng_action_start_session_get_session_name(
413 action, &value);
414 assert(action_status == LTTNG_ACTION_STATUS_OK);
415 MSG("start session `%s`", value);
416 break;
417 case LTTNG_ACTION_TYPE_STOP_SESSION:
418 action_status = lttng_action_stop_session_get_session_name(
419 action, &value);
420 assert(action_status == LTTNG_ACTION_STATUS_OK);
421 MSG("stop session `%s`", value);
422 break;
423 case LTTNG_ACTION_TYPE_ROTATE_SESSION:
424 action_status = lttng_action_rotate_session_get_session_name(
425 action, &value);
426 assert(action_status == LTTNG_ACTION_STATUS_OK);
427 MSG("rotate session `%s`", value);
428 break;
429 case LTTNG_ACTION_TYPE_SNAPSHOT_SESSION:
430 {
431 const struct lttng_snapshot_output *output;
432
433 action_status = lttng_action_snapshot_session_get_session_name(
434 action, &value);
435 assert(action_status == LTTNG_ACTION_STATUS_OK);
436 _MSG("snapshot session `%s`", value);
437
438 action_status = lttng_action_snapshot_session_get_output(
439 action, &output);
440 if (action_status == LTTNG_ACTION_STATUS_OK) {
441 const char *name;
442 uint64_t max_size;
443 const char *ctrl_url, *data_url;
444 bool starts_with_file, starts_with_net, starts_with_net6;
445
446 ctrl_url = lttng_snapshot_output_get_ctrl_url(output);
447 assert(ctrl_url && strlen(ctrl_url) > 0);
448
449 data_url = lttng_snapshot_output_get_data_url(output);
450 assert(data_url);
451
452 starts_with_file = strncmp(ctrl_url, "file://", strlen("file://")) == 0;
453 starts_with_net = strncmp(ctrl_url, "net://", strlen("net://")) == 0;
454 starts_with_net6 = strncmp(ctrl_url, "net6://", strlen("net6://")) == 0;
455
456 if (ctrl_url[0] == '/' || starts_with_file) {
457 if (starts_with_file) {
458 ctrl_url += strlen("file://");
459 }
460
461 _MSG(", path: %s", ctrl_url);
462 } else if (starts_with_net || starts_with_net6) {
463 _MSG(", url: %s", ctrl_url);
464 } else {
465 assert(strlen(data_url) > 0);
466
467 _MSG(", control url: %s, data url: %s", ctrl_url, data_url);
468 }
469
470 name = lttng_snapshot_output_get_name(output);
471 assert(name);
472 if (strlen(name) > 0) {
473 _MSG(", name: %s", name);
474 }
475
476 max_size = lttng_snapshot_output_get_maxsize(output);
477 if (max_size != -1ULL) {
478 _MSG(", max size: %" PRIu64, max_size);
479 }
480 }
481
482 MSG("");
483 break;
484 }
485
486 default:
487 abort();
488 }
489}
490
491static
492void print_one_trigger(const struct lttng_trigger *trigger)
493{
494 const struct lttng_condition *condition;
495 enum lttng_condition_type condition_type;
496 const struct lttng_action *action;
497 enum lttng_action_type action_type;
498 enum lttng_trigger_status trigger_status;
499 const char *name;
500 enum lttng_trigger_firing_policy firing_policy_type;
501 uint64_t threshold;
502 uid_t trigger_uid;
503
504 trigger_status = lttng_trigger_get_name(trigger, &name);
505 assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
506
507 trigger_status = lttng_trigger_get_owner_uid(trigger, &trigger_uid);
508 assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
509
510 MSG("- id: %s", name);
511 MSG(" user id: %d", trigger_uid);
512
513 trigger_status = lttng_trigger_get_firing_policy(
514 trigger, &firing_policy_type, &threshold);
515 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
516 ERR("Failed to get trigger's policy.");
517 goto end;
518 }
519
520 switch (firing_policy_type) {
521 case LTTNG_TRIGGER_FIRING_POLICY_EVERY_N:
522 if (threshold > 1) {
523 MSG(" firing policy: after every %" PRIu64 " occurences", threshold);
524 }
525 break;
526 case LTTNG_TRIGGER_FIRING_POLICY_ONCE_AFTER_N:
527 MSG(" firing policy: once after %" PRIu64 " occurences", threshold);
528 break;
529 default:
530 abort();
531 }
532
533 condition = lttng_trigger_get_const_condition(trigger);
534 condition_type = lttng_condition_get_type(condition);
535 MSG(" condition: %s", lttng_condition_type_str(condition_type));
536 switch (condition_type) {
537 case LTTNG_CONDITION_TYPE_EVENT_RULE_HIT:
538 print_condition_event_rule_hit(condition);
539 break;
540 default:
541 MSG(" (condition type not handled in %s)", __func__);
542 break;
543 }
544
545 action = lttng_trigger_get_const_action(trigger);
546 action_type = lttng_action_get_type(action);
547 if (action_type == LTTNG_ACTION_TYPE_GROUP) {
548 unsigned int count, i;
549 enum lttng_action_status action_status;
550
551 MSG(" actions:");
552
553 action_status = lttng_action_group_get_count(action, &count);
554 assert(action_status == LTTNG_ACTION_STATUS_OK);
555
556 for (i = 0; i < count; i++) {
557 const struct lttng_action *subaction =
558 lttng_action_group_get_at_index(
559 action, i);
560
561 _MSG(" ");
562 print_one_action(subaction);
563 }
564 } else {
565 _MSG(" action:");
566 print_one_action(action);
567 }
568
569end:
570 return;
571}
572
573static
574int compare_triggers_by_name(const void *a, const void *b)
575{
576 const struct lttng_trigger *trigger_a = *((const struct lttng_trigger **) a);
577 const struct lttng_trigger *trigger_b = *((const struct lttng_trigger **) b);
578 const char *name_a, *name_b;
579 enum lttng_trigger_status trigger_status;
580
581 trigger_status = lttng_trigger_get_name(trigger_a, &name_a);
582 assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
583
584 trigger_status = lttng_trigger_get_name(trigger_b, &name_b);
585 assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
586
587 return strcmp(name_a, name_b);
588}
589
590int cmd_list_triggers(int argc, const char **argv)
591{
592 int ret;
593 struct argpar_parse_ret argpar_parse_ret = {};
594 struct lttng_triggers *triggers = NULL;
595 int i;
596 struct lttng_dynamic_pointer_array sorted_triggers;
597 enum lttng_trigger_status trigger_status;
598 unsigned int num_triggers;
599
600 lttng_dynamic_pointer_array_init(&sorted_triggers, NULL);
601
602 argpar_parse_ret = argpar_parse(
603 argc - 1, argv + 1, list_trigger_options, true);
604 if (!argpar_parse_ret.items) {
605 ERR("%s", argpar_parse_ret.error);
606 goto error;
607 }
608
609 for (i = 0; i < argpar_parse_ret.items->n_items; i++) {
610 const struct argpar_item *item =
611 argpar_parse_ret.items->items[i];
612
613 if (item->type == ARGPAR_ITEM_TYPE_OPT) {
614 const struct argpar_item_opt *item_opt =
615 (const struct argpar_item_opt *) item;
616
617 switch (item_opt->descr->id) {
618 case OPT_HELP:
619 SHOW_HELP();
620 ret = 0;
621 goto end;
622
623 case OPT_LIST_OPTIONS:
624 list_cmd_options_argpar(stdout,
625 list_trigger_options);
626 ret = 0;
627 goto end;
628
629 default:
630 abort();
631 }
632
633 } else {
634 const struct argpar_item_non_opt *item_non_opt =
635 (const struct argpar_item_non_opt *) item;
636
637 ERR("Unexpected argument: %s", item_non_opt->arg);
638 }
639 }
640
641 ret = lttng_list_triggers(&triggers);
642 if (ret != LTTNG_OK) {
643 ERR("Error listing triggers: %s.", lttng_strerror(-ret));
644 goto error;
645 }
646
647 trigger_status = lttng_triggers_get_count(triggers, &num_triggers);
648 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
649 ERR("Failed to get trigger count.");
650 goto error;
651 }
652
653 for (i = 0; i < num_triggers; i++) {
654 const int add_ret = lttng_dynamic_pointer_array_add_pointer(
655 &sorted_triggers,
656 (void *) lttng_triggers_get_at_index(triggers, i));
657
658 if (add_ret) {
659 ERR("Failed to allocate array of struct lttng_trigger *.");
660 goto error;
661 }
662 }
663
664 qsort(sorted_triggers.array.buffer.data, num_triggers,
665 sizeof(struct lttng_trigger *),
666 compare_triggers_by_name);
667
668 for (i = 0; i < num_triggers; i++) {
669 const struct lttng_trigger *trigger_to_print =
670 (const struct lttng_trigger *)
671 lttng_dynamic_pointer_array_get_pointer(
672 &sorted_triggers, i);
673
674 print_one_trigger(trigger_to_print);
675 }
676
677 ret = 0;
678 goto end;
679
680error:
681 ret = 1;
682
683end:
684 argpar_parse_ret_fini(&argpar_parse_ret);
685 lttng_triggers_destroy(triggers);
686 lttng_dynamic_pointer_array_reset(&sorted_triggers);
687
688 return ret;
689}
This page took 0.02474 seconds and 4 git commands to generate.