SoW-2019-0002: Dynamic Snapshot
[lttng-tools.git] / doc / examples / trigger-on-event / notification-client.c
1 /*
2 * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 */
7
8 #include <lttng/condition/event-rule.h>
9 #include <lttng/lttng.h>
10
11 #include <stdbool.h>
12 #include <stddef.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <sys/time.h>
17 #include <time.h>
18
19 bool action_group_contains_notify(const struct lttng_action *action_group)
20 {
21 unsigned int i, count;
22 enum lttng_action_status status =
23 lttng_action_group_get_count(action_group, &count);
24
25 if (status != LTTNG_ACTION_STATUS_OK) {
26 printf("Failed to get action count from action group\n");
27 exit(1);
28 }
29
30 for (i = 0; i < count; i++) {
31 const struct lttng_action *action =
32 lttng_action_group_get_at_index_const(
33 action_group, i);
34 const enum lttng_action_type action_type =
35 lttng_action_get_type(action);
36
37 if (action_type == LTTNG_ACTION_TYPE_NOTIFY) {
38 return true;
39 }
40 }
41 return false;
42 }
43
44 int print_notification(struct lttng_notification *notification)
45 {
46 int ret = 0;
47 const struct lttng_condition *condition =
48 lttng_notification_get_condition(notification);
49 const struct lttng_evaluation *evaluation =
50 lttng_notification_get_evaluation(notification);
51 const enum lttng_condition_type type =
52 lttng_evaluation_get_type(evaluation);
53
54 switch (type) {
55 case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE:
56 printf("Received consumed size notification\n");
57 break;
58 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
59 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
60 printf("Received buffer usage notification\n");
61 break;
62 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
63 printf("Received session rotation ongoing notification\n");
64 break;
65 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
66 printf("Received session rotation completed notification\n");
67 break;
68 case LTTNG_CONDITION_TYPE_EVENT_RULE_HIT:
69 {
70 const char *trigger_name;
71 enum lttng_evaluation_status evaluation_status;
72 char time_str[64];
73 struct timeval tv;
74 time_t the_time;
75
76 gettimeofday(&tv, NULL);
77 the_time = tv.tv_sec;
78
79 strftime(time_str, sizeof(time_str), "[%m-%d-%Y] %T",
80 localtime(&the_time));
81 printf("%s.%ld - ", time_str, tv.tv_usec);
82
83 evaluation_status =
84 lttng_evaluation_event_rule_get_trigger_name(
85 evaluation, &trigger_name);
86 if (evaluation_status != LTTNG_EVALUATION_STATUS_OK) {
87 fprintf(stderr, "Failed to get trigger name of event rule notification\n");
88 ret = -1;
89 break;
90 }
91
92 printf("Received notification of event rule trigger \"%s\"\n",
93 trigger_name);
94 break;
95 }
96 default:
97 fprintf(stderr, "Unknown notification type (%d)\n", type);
98 }
99
100 return ret;
101 }
102
103 int main(int argc, char **argv)
104 {
105 int ret;
106 struct lttng_triggers *triggers = NULL;
107 unsigned int count, i, subcription_count = 0;
108 enum lttng_trigger_status trigger_status;
109 struct lttng_notification_channel *notification_channel = NULL;
110
111 if (argc != 2) {
112 fprintf(stderr, "Missing trigger name\n");
113 fprintf(stderr, "Usage: notification-client TRIGGER_NAME\n");
114 goto end;
115 }
116
117 notification_channel = lttng_notification_channel_create(
118 lttng_session_daemon_notification_endpoint);
119 if (!notification_channel) {
120 fprintf(stderr, "Failed to create notification channel\n");
121 ret = -1;
122 goto end;
123 }
124
125 ret = lttng_list_triggers(&triggers);
126 if (ret) {
127 fprintf(stderr, "Failed to list triggers\n");
128 goto end;
129 }
130
131 trigger_status = lttng_triggers_get_count(triggers, &count);
132 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
133 fprintf(stderr, "Failed to get trigger count\n");
134 ret = -1;
135 goto end;
136 }
137
138 for (i = 0; i < count; i++) {
139 const struct lttng_trigger *trigger =
140 lttng_triggers_get_at_index(triggers, i);
141 const struct lttng_condition *condition =
142 lttng_trigger_get_const_condition(trigger);
143 const struct lttng_action *action =
144 lttng_trigger_get_const_action(trigger);
145 const enum lttng_action_type action_type =
146 lttng_action_get_type(action);
147 enum lttng_notification_channel_status channel_status;
148 const char *trigger_name = NULL;
149 enum lttng_trigger_status trigger_status;
150
151 lttng_trigger_get_name(trigger, &trigger_name);
152 if (strcmp(trigger_name, argv[1])) {
153 continue;
154 }
155
156 if (!((action_type == LTTNG_ACTION_TYPE_GROUP &&
157 action_group_contains_notify(action)) ||
158 action_type == LTTNG_ACTION_TYPE_NOTIFY)) {
159 printf("The action of trigger \"%s\" is not \"notify\", skipping.\n",
160 trigger_name);
161 continue;
162 }
163
164 channel_status = lttng_notification_channel_subscribe(
165 notification_channel, condition);
166 if (channel_status) {
167 fprintf(stderr, "Failed to subscribe to notifications of trigger \"%s\"\n",
168 trigger_name);
169 ret = -1;
170 goto end;
171 }
172
173 printf("Subscribed to notifications of trigger \"%s\"\n",
174 trigger_name);
175 subcription_count++;
176 }
177
178 if (subcription_count == 0) {
179 printf("No matching trigger with a notify action found.\n");
180 ret = 0;
181 goto end;
182 }
183
184 for (;;) {
185 struct lttng_notification *notification;
186 enum lttng_notification_channel_status channel_status;
187
188 channel_status =
189 lttng_notification_channel_get_next_notification(
190 notification_channel,
191 &notification);
192 switch (channel_status) {
193 case LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED:
194 printf("Dropped notification\n");
195 break;
196 case LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED:
197 ret = 0;
198 goto end;
199 case LTTNG_NOTIFICATION_CHANNEL_STATUS_OK:
200 break;
201 case LTTNG_NOTIFICATION_CHANNEL_STATUS_CLOSED:
202 printf("Notification channel was closed by peer.\n");
203 break;
204 default:
205 fprintf(stderr, "A communication error occurred on the notification channel.\n");
206 ret = -1;
207 goto end;
208 }
209
210 ret = print_notification(notification);
211 lttng_notification_destroy(notification);
212 if (ret) {
213 goto end;
214 }
215 }
216 end:
217 lttng_triggers_destroy(triggers);
218 lttng_notification_channel_destroy(notification_channel);
219 return !!ret;
220 }
This page took 0.050715 seconds and 5 git commands to generate.