2 * Session rotation example control application
4 * Copyright 2017, Julien Desfossez <jdesfossez@efficios.com>
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * gcc -o rotate-client rotate-client-example.c -llttng-ctl
29 * Run with the following command to rotate the session every second and
30 * compress the chunk, until ctrl-c:
31 * ./rotate-client mysession 1 -1 ./rotate-client-compress.sh
34 #include <lttng/lttng.h>
42 #define DEFAULT_DATA_AVAILABILITY_WAIT_TIME 200000 /* usec */
44 static volatile int quit
= 0;
46 static void sighandler(int signal
__attribute__((unused
)))
48 const char msg
[] = "Signal caught, exiting\n";
49 const int ret
= write(STDOUT_FILENO
, msg
, sizeof(msg
));
51 assert(ret
== 0); /* NOLINT assert is not async signal safe */
55 static int setup_session(const char *session_name
, const char *path
)
58 struct lttng_domain dom
;
59 struct lttng_event ev
;
60 struct lttng_handle
*chan_handle
= NULL
;
62 printf("Creating session %s\n", session_name
);
63 ret
= lttng_create_session(session_name
, path
);
65 fprintf(stderr
, "Failed to create session, ret = %d\n", ret
);
69 dom
.type
= LTTNG_DOMAIN_KERNEL
;
70 dom
.buf_type
= LTTNG_BUFFER_GLOBAL
;
72 chan_handle
= lttng_create_handle(session_name
, &dom
);
73 if (chan_handle
== NULL
) {
78 memset(&ev
, 0, sizeof(ev
));
79 ev
.type
= LTTNG_EVENT_SYSCALL
;
81 ev
.loglevel_type
= LTTNG_EVENT_LOGLEVEL_ALL
;
83 ret
= lttng_enable_event_with_exclusions(
84 chan_handle
, &ev
, "mychan", NULL
, 0, NULL
);
86 fprintf(stderr
, "Failed to enable events (ret = %i)\n", ret
);
89 printf("Enabled all system call kernel events\n");
91 ret
= lttng_start_tracing(session_name
);
93 fprintf(stderr
, "Failed to start tracing\n");
100 lttng_destroy_handle(chan_handle
);
104 static int cleanup_session(const char *session_name
)
108 printf("Stopping session %s", session_name
);
109 ret
= lttng_stop_tracing_no_wait(session_name
);
111 fprintf(stderr
, "Failed to stop tracing\n");
117 ret
= lttng_data_pending(session_name
);
119 /* Return the data available call error. */
124 * Data sleep time before retrying (in usec). Don't sleep if the
125 * call returned value indicates availability.
128 usleep(DEFAULT_DATA_AVAILABILITY_WAIT_TIME
);
135 printf("Destroying session %s\n", session_name
);
136 ret
= lttng_destroy_session(session_name
);
138 fprintf(stderr
, "Failed to destroy the session\n");
148 static int rotate_session(const char *session_name
, const char *ext_program
)
151 struct lttng_rotation_handle
*handle
= NULL
;
152 enum lttng_rotation_status rotation_status
;
153 enum lttng_rotation_state rotation_state
= LTTNG_ROTATION_STATE_ONGOING
;
156 printf("Rotating the output files of session %s", session_name
);
158 ret
= lttng_rotate_session(session_name
, NULL
, &handle
);
160 fprintf(stderr
, "Failed to rotate session, %s\n",
161 lttng_strerror(ret
));
168 rotation_status
= lttng_rotation_handle_get_state(
169 handle
, &rotation_state
);
170 if (rotation_status
!= LTTNG_ROTATION_STATUS_OK
) {
172 fprintf(stderr
, "Failed to get the current rotation's state\n");
177 * Data sleep time before retrying (in usec). Don't
178 * sleep if the call returned value indicates
181 if (rotation_state
== LTTNG_ROTATION_STATE_ONGOING
) {
182 usleep(DEFAULT_DATA_AVAILABILITY_WAIT_TIME
);
186 } while (rotation_state
== LTTNG_ROTATION_STATE_ONGOING
);
189 switch (rotation_state
) {
190 case LTTNG_ROTATION_STATE_COMPLETED
:
192 const struct lttng_trace_archive_location
*location
;
193 const char *absolute_path
;
194 enum lttng_trace_archive_location_status location_status
;
196 rotation_status
= lttng_rotation_handle_get_archive_location(
198 if (rotation_status
!= LTTNG_ROTATION_STATUS_OK
) {
199 fprintf(stderr
, "Failed to retrieve the rotation's completed chunk archive location\n");
205 lttng_trace_archive_location_local_get_absolute_path(
206 location
, &absolute_path
);
207 if (location_status
!= LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK
) {
208 fprintf(stderr
, "Failed to get absolute path of completed chunk archive");
213 printf("Output files of session %s rotated to %s\n",
214 session_name
, absolute_path
);
215 ret
= snprintf(cmd
, PATH_MAX
, "%s %s", ext_program
,
218 fprintf(stderr
, "Failed to prepare command string\n");
224 case LTTNG_ROTATION_STATE_EXPIRED
:
225 printf("Output files of session %s rotated, but the handle expired\n",
229 case LTTNG_ROTATION_STATE_ERROR
:
230 fprintf(stderr
, "An error occurred with the rotation of session %s\n",
234 case LTTNG_ROTATION_STATE_ONGOING
:
237 case LTTNG_ROTATION_STATE_NO_ROTATION
:
238 fprintf(stderr
, "No rotation was performed on rotation request for session %s\n",
245 lttng_rotation_handle_destroy(handle
);
249 static int cleanup_dir(const char *path
)
254 ret
= snprintf(cmd
, PATH_MAX
, "rm -rf %s", path
);
256 fprintf(stderr
, "Failed to prepare rm -rf command string\n");
265 static void usage(const char *prog_name
)
267 fprintf(stderr
, "Usage: %s <session-name> <delay-sec> <nr-rotate> <program>\n",
269 fprintf(stderr
, " <session-name>: the name of the session you want to create\n");
270 fprintf(stderr
, " <delay-sec>: the delay in seconds between each rotation\n");
272 " <nr-rotate>: the number of rotation you want to perform, "
273 "-1 for infinite until ctrl-c\n");
275 " <program>: program to run on each chunk, it must be "
276 "executable, and expect a trace folder as only argument\n");
277 fprintf(stderr
, "\nThe trace folder is deleted when this program completes.\n");
280 int main(int argc
, char **argv
)
283 char tmppath
[] = "/tmp/lttng-rotate-XXXXXX";
284 char *session_name
, *path
, *ext_program
;
293 session_name
= argv
[1];
294 delay
= atoi(argv
[2]);
296 ext_program
= argv
[4];
299 fprintf(stderr
, "delay-sec must be a positive values\n");
304 if (signal(SIGINT
, sighandler
) == SIG_ERR
) {
306 perror("signal handler");
310 path
= mkdtemp(tmppath
);
312 fprintf(stderr
, "Failed to create temporary path\n");
315 printf("Output directory: %s\n", path
);
317 ret
= setup_session(session_name
, path
);
319 goto end_cleanup_dir
;
323 unsigned int sleep_time
;
326 for (i
= 0; i
< nr
; i
++) {
327 ret
= rotate_session(session_name
, ext_program
);
332 while (sleep_time
> 0) {
333 sleep_time
= sleep(sleep_time
);
341 ret
= rotate_session(session_name
, ext_program
);
350 ret
= cleanup_session(session_name
);
355 ret
= cleanup_dir(path
);