SoW-2019-0002: Dynamic Snapshot
[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/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
19 static const char help_msg[] =
20 #include <lttng-list-trigger.1.h>
21 ;
22 #endif
23
24 enum {
25 OPT_HELP,
26 OPT_LIST_OPTIONS,
27 };
28
29 static const
30 struct 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
36 static
37 void 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 printf(" 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 printf(", 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 printf(", 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 printf(", 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 printf("%s%s", i > 0 ? "," : "", exclusion);
99 }
100 }
101
102
103 printf(")\n");
104 }
105
106 static
107 void print_event_rule_kprobe(const struct lttng_event_rule *event_rule)
108 {
109 enum lttng_event_rule_status event_rule_status;
110 const char *name, *symbol_name;
111 uint64_t offset;
112
113 event_rule_status = lttng_event_rule_kprobe_get_name(event_rule, &name);
114 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
115 fprintf(stderr, "Failed to get kprobe event rule's name.\n");
116 goto end;
117 }
118
119 assert(lttng_event_rule_get_type(event_rule) == LTTNG_EVENT_RULE_TYPE_KPROBE);
120
121 printf(" rule: %s (type: probe, location: ", name);
122
123 // FIXME: When the location has been specified by address, this field
124 // contains the address as a string. The only downside is that we are
125 // missing a `0x` prefix.
126 symbol_name = lttng_event_rule_kprobe_get_symbol_name(event_rule);
127 printf("%s", symbol_name);
128
129 offset = lttng_event_rule_kprobe_get_offset(event_rule);
130 if (offset > 0) {
131 printf("+0x%" PRIx64, offset);
132 }
133
134 printf(")\n");
135
136 end:
137 return;
138 }
139
140 static
141 void print_event_rule_uprobe(const struct lttng_event_rule *event_rule)
142 {
143 enum lttng_event_rule_status event_rule_status;
144 const char *name;
145 const struct lttng_userspace_probe_location *location;
146 enum lttng_userspace_probe_location_type userspace_probe_location_type;
147
148 assert(lttng_event_rule_get_type(event_rule) == LTTNG_EVENT_RULE_TYPE_UPROBE);
149
150 event_rule_status = lttng_event_rule_uprobe_get_name(event_rule, &name);
151 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
152 fprintf(stderr, "Failed to get uprobe event rule's name.\n");
153 goto end;
154 }
155
156 event_rule_status = lttng_event_rule_uprobe_get_location(event_rule, &location);
157 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
158 fprintf(stderr, "Failed to get uprobe event rule's location.\n");
159 goto end;
160 }
161
162 printf(" rule: %s (type: userspace probe, location: ", name);
163
164 userspace_probe_location_type =
165 lttng_userspace_probe_location_get_type(location);
166
167 switch (userspace_probe_location_type) {
168 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
169 {
170 const char *binary_path, *function_name;
171
172 binary_path = lttng_userspace_probe_location_function_get_binary_path(location);
173 function_name = lttng_userspace_probe_location_function_get_function_name(location);
174
175 printf("%s:%s", binary_path, function_name);
176 break;
177 }
178
179 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
180 printf("SDT not implemented yet");
181 break;
182
183 default:
184 abort();
185 }
186
187 printf(")\n");
188
189 end:
190 return;
191 }
192
193 static
194 void print_event_rule_syscall(const struct lttng_event_rule *event_rule)
195 {
196 const char *pattern, *filter;
197 enum lttng_event_rule_status event_rule_status;
198
199 assert(lttng_event_rule_get_type(event_rule) == LTTNG_EVENT_RULE_TYPE_SYSCALL);
200
201 event_rule_status = lttng_event_rule_syscall_get_pattern(event_rule, &pattern);
202 assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK);
203
204 printf(" - rule: %s (type: syscall", pattern);
205
206 event_rule_status = lttng_event_rule_syscall_get_filter(
207 event_rule, &filter);
208 if (event_rule_status == LTTNG_EVENT_RULE_STATUS_OK) {
209 printf(", filter: %s", filter);
210 } else {
211 assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_UNSET);
212 }
213
214 printf(")\n");
215 }
216
217 static
218 void print_event_rule(const struct lttng_event_rule *event_rule)
219 {
220 enum lttng_event_rule_type event_rule_type =
221 lttng_event_rule_get_type(event_rule);
222
223 switch (event_rule_type) {
224 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT:
225 print_event_rule_tracepoint(event_rule);
226 break;
227
228 case LTTNG_EVENT_RULE_TYPE_KPROBE:
229 print_event_rule_kprobe(event_rule);
230 break;
231
232 case LTTNG_EVENT_RULE_TYPE_UPROBE:
233 print_event_rule_uprobe(event_rule);
234 break;
235
236 case LTTNG_EVENT_RULE_TYPE_SYSCALL:
237 print_event_rule_syscall(event_rule);
238 break;
239
240 default:
241 abort();
242 }
243 }
244
245 static
246 void print_condition_event_rule_hit(const struct lttng_condition *condition)
247 {
248 const struct lttng_event_rule *event_rule;
249 enum lttng_condition_status condition_status;
250
251 condition_status =
252 lttng_condition_event_rule_get_rule(condition, &event_rule);
253 assert(condition_status == LTTNG_CONDITION_STATUS_OK);
254
255 print_event_rule(event_rule);
256 }
257
258 static
259 void print_one_action(const struct lttng_action *action)
260 {
261 enum lttng_action_type action_type;
262 enum lttng_action_status action_status;
263 const char *value;
264
265 action_type = lttng_action_get_type(action);
266 assert(action_type != LTTNG_ACTION_TYPE_GROUP);
267
268 switch (action_type) {
269 case LTTNG_ACTION_TYPE_NOTIFY:
270 printf("notify\n");
271 break;
272
273 case LTTNG_ACTION_TYPE_START_SESSION:
274 action_status = lttng_action_start_session_get_session_name(
275 action, &value);
276 assert(action_status == LTTNG_ACTION_STATUS_OK);
277 printf("start session `%s`\n", value);
278 break;
279
280 case LTTNG_ACTION_TYPE_STOP_SESSION:
281 action_status = lttng_action_stop_session_get_session_name(
282 action, &value);
283 assert(action_status == LTTNG_ACTION_STATUS_OK);
284 printf("stop session `%s`\n", value);
285 break;
286
287 case LTTNG_ACTION_TYPE_ROTATE_SESSION:
288 action_status = lttng_action_rotate_session_get_session_name(
289 action, &value);
290 assert(action_status == LTTNG_ACTION_STATUS_OK);
291 printf("rotate session `%s`\n", value);
292 break;
293
294 case LTTNG_ACTION_TYPE_SNAPSHOT_SESSION:
295 {
296 const struct lttng_snapshot_output *output;
297
298 action_status = lttng_action_snapshot_session_get_session_name(
299 action, &value);
300 assert(action_status == LTTNG_ACTION_STATUS_OK);
301 printf("snapshot session `%s`", value);
302
303 action_status = lttng_action_snapshot_session_get_output_const(
304 action, &output);
305 if (action_status == LTTNG_ACTION_STATUS_OK) {
306 const char *name;
307 uint64_t max_size;
308 const char *ctrl_url, *data_url;
309 bool starts_with_file, starts_with_net, starts_with_net6;
310
311 ctrl_url = lttng_snapshot_output_get_ctrl_url(output);
312 assert(ctrl_url && strlen(ctrl_url) > 0);
313
314 data_url = lttng_snapshot_output_get_data_url(output);
315 assert(data_url);
316
317 starts_with_file = strncmp(ctrl_url, "file://", strlen("file://")) == 0;
318 starts_with_net = strncmp(ctrl_url, "net://", strlen("net://")) == 0;
319 starts_with_net6 = strncmp(ctrl_url, "net6://", strlen("net6://")) == 0;
320
321 if (ctrl_url[0] == '/' || starts_with_file) {
322 if (starts_with_file) {
323 ctrl_url += strlen("file://");
324 }
325
326 printf(", path: %s", ctrl_url);
327 } else if (starts_with_net || starts_with_net6) {
328 printf(", url: %s", ctrl_url);
329 } else {
330 assert(strlen(data_url) > 0);
331
332 printf(", control url: %s, data url: %s", ctrl_url, data_url);
333 }
334
335 name = lttng_snapshot_output_get_name(output);
336 assert(name);
337 if (strlen(name) > 0) {
338 printf(", name: %s", name);
339 }
340
341 max_size = lttng_snapshot_output_get_maxsize(output);
342 if (max_size != -1ULL) {
343 printf(", max size: %" PRIu64, max_size);
344 }
345 }
346
347 printf("\n");
348 break;
349 }
350
351 default:
352 abort();
353 }
354 }
355
356 static
357 void print_one_trigger(const struct lttng_trigger *trigger)
358 {
359 const struct lttng_condition *condition;
360 enum lttng_condition_type condition_type;
361 const struct lttng_action *action;
362 enum lttng_action_type action_type;
363 enum lttng_trigger_status trigger_status;
364 const char *name;
365 enum lttng_trigger_firing_policy_type policy_type;
366 unsigned long long threshold;
367
368 trigger_status = lttng_trigger_get_name(trigger, &name);
369 assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
370 printf("- id: %s\n", name);
371
372 trigger_status = lttng_trigger_get_firing_policy(trigger,
373 &policy_type, &threshold);
374 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
375 fprintf(stderr, "Failed to get trigger's firing policy.\n");
376 goto end;
377 }
378
379 switch (policy_type) {
380 case LTTNG_TRIGGER_FIRE_EVERY_N:
381 if (threshold > 1) {
382 printf(" firing policy: after every %llu occurences\n", threshold);
383 }
384 break;
385
386 case LTTNG_TRIGGER_FIRE_ONCE_AFTER_N:
387 printf(" firing policy: once after %llu occurences\n", threshold);
388 break;
389
390 default:
391 abort();
392 }
393
394 condition = lttng_trigger_get_const_condition(trigger);
395 condition_type = lttng_condition_get_type(condition);
396 printf(" condition: %s\n",
397 lttng_condition_type_str(condition_type));
398
399 switch (condition_type) {
400 case LTTNG_CONDITION_TYPE_EVENT_RULE_HIT:
401 print_condition_event_rule_hit(condition);
402 break;
403
404 default:
405 printf(" (condition type not handled in %s)\n", __func__);
406 break;
407 }
408
409 action = lttng_trigger_get_const_action(trigger);
410 action_type = lttng_action_get_type(action);
411 if (action_type == LTTNG_ACTION_TYPE_GROUP) {
412 enum lttng_action_status action_status;
413 unsigned int count, i;
414
415 printf(" actions:\n");
416
417 action_status = lttng_action_group_get_count(action, &count);
418 assert(action_status == LTTNG_ACTION_STATUS_OK);
419
420 for (i = 0; i < count; i++) {
421 const struct lttng_action *subaction =
422 lttng_action_group_get_at_index_const(action, i);
423
424 printf(" ");
425 print_one_action(subaction);
426 }
427 } else {
428 printf(" action:");
429 print_one_action(action);
430 }
431
432 end:
433 return;
434 }
435
436 static
437 int compare_triggers_by_name(const void *a, const void *b)
438 {
439 const struct lttng_trigger *trigger_a = *((const struct lttng_trigger **) a);
440 const struct lttng_trigger *trigger_b = *((const struct lttng_trigger **) b);
441 const char *name_a, *name_b;
442 enum lttng_trigger_status trigger_status;
443
444 trigger_status = lttng_trigger_get_name(trigger_a, &name_a);
445 assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
446
447 trigger_status = lttng_trigger_get_name(trigger_b, &name_b);
448 assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
449
450 return strcmp(name_a, name_b);
451 }
452
453 int cmd_list_triggers(int argc, const char **argv)
454 {
455 int ret;
456 struct argpar_parse_ret argpar_parse_ret = { 0 };
457 struct lttng_triggers *triggers = NULL;
458 int i;
459 const struct lttng_trigger **sorted_triggers = NULL;
460 enum lttng_trigger_status trigger_status;
461 unsigned int num_triggers;
462
463 argpar_parse_ret = argpar_parse(argc - 1, argv + 1,
464 list_trigger_options, true);
465 if (!argpar_parse_ret.items) {
466 fprintf(stderr, "Error: %s\n", argpar_parse_ret.error);
467 goto error;
468 }
469
470 for (i = 0; i < argpar_parse_ret.items->n_items; i++) {
471 struct argpar_item *item = argpar_parse_ret.items->items[i];
472
473 if (item->type == ARGPAR_ITEM_TYPE_OPT) {
474 struct argpar_item_opt *item_opt =
475 (struct argpar_item_opt *) item;
476
477 switch (item_opt->descr->id) {
478 case OPT_HELP:
479 SHOW_HELP();
480 ret = 0;
481 goto end;
482
483 case OPT_LIST_OPTIONS:
484 list_cmd_options_argpar(stdout,
485 list_trigger_options);
486 ret = 0;
487 goto end;
488
489 default:
490 abort();
491 }
492
493 } else {
494 struct argpar_item_non_opt *item_non_opt =
495 (struct argpar_item_non_opt *) item;
496
497 fprintf(stderr, "Unexpected argument: %s\n", item_non_opt->arg);
498 }
499 }
500
501 ret = lttng_list_triggers(&triggers);
502 if (ret != 0) {
503 fprintf(stderr, "Error listing triggers: %s.\n",
504 lttng_strerror(ret));
505 goto error;
506 }
507
508 trigger_status = lttng_triggers_get_count(triggers, &num_triggers);
509 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
510 fprintf(stderr, "Failed to get trigger count.\n");
511 goto error;
512 }
513
514 sorted_triggers = calloc(num_triggers, sizeof(struct lttng_trigger *));
515 if (!sorted_triggers) {
516 fprintf(stderr, "Failed to allocate array of struct lttng_trigger *.\n");
517 goto error;
518 }
519
520 for (i = 0; i < num_triggers; i++) {
521 sorted_triggers[i] = lttng_triggers_get_at_index(triggers, i);
522 }
523
524 qsort(sorted_triggers, num_triggers, sizeof(struct lttng_trigger *),
525 compare_triggers_by_name);
526
527 for (i = 0; i < num_triggers; i++) {
528 print_one_trigger(sorted_triggers[i]);
529 }
530
531 goto end;
532
533 error:
534 ret = 1;
535
536 end:
537 argpar_parse_ret_fini(&argpar_parse_ret);
538 lttng_triggers_destroy(triggers);
539
540 return ret;
541 }
This page took 0.041655 seconds and 5 git commands to generate.