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