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