/* * List JUL events for a specific session using the handle. * * Return CMD_SUCCESS on success else a negative value. */ static int list_session_jul_events(void) { int ret, count, i; struct lttng_event *events = NULL; count = lttng_list_events(handle, "", &events); if (count < 0) { ret = count; ERR("%s", lttng_strerror(ret)); goto error; } MSG("Events (Logger name):\n---------------------"); if (count == 0) { MSG("%sNone\n", indent6); goto end; } for (i = 0; i < count; i++) { MSG("%s- %s%s", indent4, events[i].name, enabled_string(events[i].enabled)); } MSG(""); end: free(events); ret = CMD_SUCCESS; error: return ret; }
/* * List events of channel of session and domain. */ static int list_events(const char *channel_name) { int ret, count, i; struct lttng_event *events = NULL; count = lttng_list_events(handle, channel_name, &events); if (count < 0) { ret = count; ERR("%s", lttng_strerror(ret)); goto error; } MSG("\n%sEvents:", indent4); if (count == 0) { MSG("%sNone\n", indent6); goto end; } for (i = 0; i < count; i++) { print_events(&events[i]); } MSG(""); end: free(events); ret = CMD_SUCCESS; error: return ret; }
/* * destroy_session * * Unregister the provided session to the session daemon. On success, removes * the default configuration. */ static int destroy_session(struct lttng_session *session) { int ret; ret = lttng_destroy_session(session->name); if (ret < 0) { switch (-ret) { case LTTNG_ERR_SESS_NOT_FOUND: WARN("Session name %s not found", session->name); break; default: ERR("%s", lttng_strerror(ret)); break; } goto error; } MSG("Session %s destroyed", session->name); config_destroy_default(); if (lttng_opt_mi) { ret = mi_lttng_session(writer, session, 0); if (ret) { ret = CMD_ERROR; goto error; } } ret = CMD_SUCCESS; error: return ret; }
/* * List available domain(s) for a session. */ static int list_domains(const char *session_name) { int i, count, ret = CMD_SUCCESS; struct lttng_domain *domains = NULL; count = lttng_list_domains(session_name, &domains); if (count < 0) { ret = CMD_ERROR; ERR("%s", lttng_strerror(count)); goto end; } if (lttng_opt_mi) { /* Mi output */ ret = mi_list_domains(domains, count); if (ret) { ret = CMD_ERROR; goto error; } } else { /* Pretty print */ MSG("Domains:\n-------------"); if (count == 0) { MSG(" None"); goto end; } for (i = 0; i < count; i++) { switch (domains[i].type) { case LTTNG_DOMAIN_KERNEL: MSG(" - Kernel"); break; case LTTNG_DOMAIN_UST: MSG(" - UST global"); break; case LTTNG_DOMAIN_JUL: MSG(" - JUL (Java Util Logging)"); break; case LTTNG_DOMAIN_LOG4J: MSG(" - LOG4j (Logging for Java)"); break; case LTTNG_DOMAIN_PYTHON: MSG(" - Python (logging)"); break; default: break; } } } error: free(domains); end: return ret; }
/* * set_session */ static int set_session(void) { int ret = CMD_SUCCESS; int count, i; unsigned int session_found = 0; struct lttng_session *sessions; if (opt_session_name && strlen(opt_session_name) > NAME_MAX) { ERR("Session name too long. Length must be lower or equal to %d", NAME_MAX); ret = CMD_ERROR; goto end; } count = lttng_list_sessions(&sessions); if (count < 0) { ret = CMD_ERROR; ERR("%s", lttng_strerror(count)); goto end; } for (i = 0; i < count; i++) { if (strncmp(sessions[i].name, opt_session_name, NAME_MAX) == 0) { session_found = 1; break; } } if (!session_found) { ERR("Session '%s' not found", opt_session_name); ret = CMD_ERROR; goto error; } ret = config_init(opt_session_name); if (ret < 0) { ERR("Unable to set session name"); ret = CMD_ERROR; goto error; } MSG("Session set to %s", opt_session_name); if (lttng_opt_mi) { ret = mi_print(opt_session_name); if (ret) { ret = CMD_ERROR; goto error; } } ret = CMD_SUCCESS; error: free(sessions); end: return ret; }
/* * List available tracing session. List only basic information. * * If session_name is NULL, all sessions are listed. */ static int list_sessions(const char *session_name) { int ret, count, i; unsigned int session_found = 0; struct lttng_session *sessions; count = lttng_list_sessions(&sessions); DBG("Session count %d", count); if (count < 0) { ret = count; ERR("%s", lttng_strerror(ret)); goto error; } else if (count == 0) { MSG("Currently no available tracing session"); goto end; } if (session_name == NULL) { MSG("Available tracing sessions:"); } for (i = 0; i < count; i++) { if (session_name != NULL) { if (strncmp(sessions[i].name, session_name, NAME_MAX) == 0) { session_found = 1; MSG("Tracing session %s: [%s%s]", session_name, active_string(sessions[i].enabled), snapshot_string(sessions[i].snapshot_mode)); MSG("%sTrace path: %s\n", indent4, sessions[i].path); break; } } else { MSG(" %d) %s (%s) [%s%s]", i + 1, sessions[i].name, sessions[i].path, active_string(sessions[i].enabled), snapshot_string(sessions[i].snapshot_mode)); } } free(sessions); if (!session_found && session_name != NULL) { ERR("Session '%s' not found", session_name); ret = CMD_ERROR; goto error; } if (session_name == NULL) { MSG("\nUse lttng list <session_name> for more details"); } end: return CMD_SUCCESS; error: return ret; }
/* * Ask session daemon for all user space tracepoints available. */ static int list_ust_events(void) { int i, size; struct lttng_domain domain; struct lttng_handle *handle; struct lttng_event *event_list; pid_t cur_pid = 0; char *cmdline = NULL; memset(&domain, 0, sizeof(domain)); DBG("Getting UST tracing events"); domain.type = LTTNG_DOMAIN_UST; handle = lttng_create_handle(NULL, &domain); if (handle == NULL) { goto error; } size = lttng_list_tracepoints(handle, &event_list); if (size < 0) { ERR("Unable to list UST events: %s", lttng_strerror(size)); lttng_destroy_handle(handle); return size; } MSG("UST events:\n-------------"); if (size == 0) { MSG("None"); } for (i = 0; i < size; i++) { if (cur_pid != event_list[i].pid) { cur_pid = event_list[i].pid; cmdline = get_cmdline_by_pid(cur_pid); MSG("\nPID: %d - Name: %s", cur_pid, cmdline); free(cmdline); } print_events(&event_list[i]); } MSG(""); free(event_list); lttng_destroy_handle(handle); return CMD_SUCCESS; error: lttng_destroy_handle(handle); return -1; }
/* * Ask for all trace events in the kernel */ static int list_kernel_events(void) { int i, size, ret = CMD_SUCCESS; struct lttng_domain domain; struct lttng_handle *handle; struct lttng_event *event_list; memset(&domain, 0, sizeof(domain)); DBG("Getting kernel tracing events"); domain.type = LTTNG_DOMAIN_KERNEL; handle = lttng_create_handle(NULL, &domain); if (handle == NULL) { ret = CMD_ERROR; goto error; } size = lttng_list_tracepoints(handle, &event_list); if (size < 0) { ERR("Unable to list kernel events: %s", lttng_strerror(size)); lttng_destroy_handle(handle); return CMD_ERROR; } if (lttng_opt_mi) { /* Mi print */ ret = mi_list_kernel_events(event_list, size, &domain); if (ret) { ret = CMD_ERROR; goto end; } } else { MSG("Kernel events:\n-------------"); for (i = 0; i < size; i++) { print_events(&event_list[i]); } MSG(""); } end: free(event_list); lttng_destroy_handle(handle); return ret; error: lttng_destroy_handle(handle); return ret; }
/* * Retrieve the created session and mi output it based on provided argument * This is currently a summary of what was pretty printed and is subject to * enhancements. */ static int mi_created_session(const char *session_name) { int ret, i, count, found; struct lttng_session *sessions; /* session_name should not be null */ assert(session_name); assert(writer); count = lttng_list_sessions(&sessions); if (count < 0) { ret = count; ERR("%s", lttng_strerror(ret)); goto error; } if (count == 0) { ERR("Error session creation failed: session %s not found", session_name); ret = -LTTNG_ERR_SESS_NOT_FOUND; goto end; } found = 0; for (i = 0; i < count; i++) { if (strncmp(sessions[i].name, session_name, NAME_MAX) == 0) { found = 1; ret = mi_lttng_session(writer, &sessions[i], 0); if (ret) { goto error; } break; } } if (!found) { ret = -LTTNG_ERR_SESS_NOT_FOUND; } else { ret = CMD_SUCCESS; } error: free(sessions); end: return ret; }
/* * List agent events for a specific session using the handle. * * Return CMD_SUCCESS on success else a negative value. */ static int list_session_agent_events(void) { int ret = CMD_SUCCESS, count, i; struct lttng_event *events = NULL; count = lttng_list_events(handle, "", &events); if (count < 0) { ret = CMD_ERROR; ERR("%s", lttng_strerror(count)); goto error; } if (lttng_opt_mi) { /* Mi print */ ret = mi_list_session_agent_events(events, count); if (ret) { ret = CMD_ERROR; goto end; } } else { /* Pretty print */ MSG("Events (Logger name):\n---------------------"); if (count == 0) { MSG("%sNone\n", indent6); goto end; } for (i = 0; i < count; i++) { MSG("%s- %s%s (loglevel%s %s)", indent4, events[i].name, enabled_string(events[i].enabled), logleveltype_string(events[i].loglevel_type), mi_lttng_loglevel_string(events[i].loglevel, handle->domain.type)); } MSG(""); } end: free(events); error: return ret; }
/* * destroy_all_sessions * * Call destroy_sessions for each registered sessions */ static int destroy_all_sessions(struct lttng_session *sessions, int count) { int i, ret = CMD_SUCCESS; if (count == 0) { MSG("No session found, nothing to do."); } else if (count < 0) { ERR("%s", lttng_strerror(ret)); goto error; } for (i = 0; i < count; i++) { ret = destroy_session(&sessions[i]); if (ret < 0) { goto error; } } error: return ret; }
/* * List available domain(s) for a session. */ static int list_domains(const char *session_name) { int i, count, ret = CMD_SUCCESS; struct lttng_domain *domains = NULL; MSG("Domains:\n-------------"); count = lttng_list_domains(session_name, &domains); if (count < 0) { ret = count; ERR("%s", lttng_strerror(ret)); goto error; } else if (count == 0) { MSG(" None"); goto end; } for (i = 0; i < count; i++) { switch (domains[i].type) { case LTTNG_DOMAIN_KERNEL: MSG(" - Kernel"); break; case LTTNG_DOMAIN_UST: MSG(" - UST global"); break; case LTTNG_DOMAIN_JUL: MSG(" - JUL (Java Util Logging)"); break; default: break; } } end: free(domains); error: return ret; }
/* * Ask for kernel system calls. */ static int list_syscalls(void) { int i, size, ret = CMD_SUCCESS; struct lttng_event *event_list; DBG("Getting kernel system call events"); size = lttng_list_syscalls(&event_list); if (size < 0) { ERR("Unable to list system calls: %s", lttng_strerror(size)); ret = CMD_ERROR; goto error; } if (lttng_opt_mi) { /* Mi print */ ret = mi_list_syscalls(event_list, size); if (ret) { ret = CMD_ERROR; goto end; } } else { MSG("System calls:\n-------------"); for (i = 0; i < size; i++) { print_events(&event_list[i]); } MSG(""); } end: free(event_list); return ret; error: return ret; }
/* * List events of channel of session and domain. */ static int list_events(const char *channel_name) { int ret = CMD_SUCCESS, count, i; struct lttng_event *events = NULL; count = lttng_list_events(handle, channel_name, &events); if (count < 0) { ret = CMD_ERROR; ERR("%s", lttng_strerror(count)); goto error; } if (lttng_opt_mi) { /* Mi print */ ret = mi_list_events(events, count); if (ret) { ret = CMD_ERROR; goto end; } } else { /* Pretty print */ MSG("\n%sEvents:", indent4); if (count == 0) { MSG("%sNone\n", indent6); goto end; } for (i = 0; i < count; i++) { print_events(&events[i]); } MSG(""); } end: free(events); error: return ret; }
/* * disable_events * * Disabling event using the lttng API. */ static int disable_events(char *session_name) { int ret = CMD_SUCCESS, warn = 0, command_ret = CMD_SUCCESS; int enabled = 1, success = 1; char *event_name, *channel_name = NULL; struct lttng_domain dom; struct lttng_event event; memset(&dom, 0, sizeof(dom)); /* Create lttng domain */ if (opt_kernel) { dom.type = LTTNG_DOMAIN_KERNEL; } else if (opt_userspace) { dom.type = LTTNG_DOMAIN_UST; } else if (opt_jul) { dom.type = LTTNG_DOMAIN_JUL; } else if (opt_log4j) { dom.type = LTTNG_DOMAIN_LOG4J; } else if (opt_python) { dom.type = LTTNG_DOMAIN_PYTHON; } else { /* Checked by the caller. */ assert(0); } channel_name = opt_channel_name; handle = lttng_create_handle(session_name, &dom); if (handle == NULL) { ret = -1; goto error; } /* Mi print the channel and open the events element */ if (lttng_opt_mi) { ret = mi_lttng_writer_open_element(writer, config_element_channel); if (ret) { ret = CMD_ERROR; goto end; } ret = mi_lttng_writer_write_element_string(writer, config_element_name, print_channel_name(channel_name)); if (ret) { ret = CMD_ERROR; goto end; } /* Open events element */ ret = mi_lttng_writer_open_element(writer, config_element_events); if (ret) { ret = CMD_ERROR; goto end; } } memset(&event, 0, sizeof(event)); /* Set default loglevel to any/unknown */ event.loglevel = -1; /* opt_event_type contain the event type to disable at this point */ event.type = opt_event_type; if (opt_disable_all) { command_ret = lttng_disable_event_ext(handle, &event, channel_name, NULL); if (command_ret < 0) { ERR("%s", lttng_strerror(command_ret)); enabled = 1; success = 0; } else { enabled = 0; success = 1; MSG("All %s events of type %s are disabled in channel %s", get_domain_str(dom.type), print_event_type(opt_event_type), print_channel_name(channel_name)); } if (lttng_opt_mi) { ret = mi_print_event("*", enabled, success); if (ret) { ret = CMD_ERROR; goto error; } } } else { /* Strip event list */ event_name = strtok(opt_event_list, ","); while (event_name != NULL) { DBG("Disabling event %s", event_name); strncpy(event.name, event_name, sizeof(event.name)); event.name[sizeof(event.name) - 1] = '\0'; command_ret = lttng_disable_event_ext(handle, &event, channel_name, NULL); if (command_ret < 0) { ERR("%s of type %s : %s (channel %s, session %s)", event_name, print_event_type(opt_event_type), lttng_strerror(command_ret), command_ret == -LTTNG_ERR_NEED_CHANNEL_NAME ? print_raw_channel_name(channel_name) : print_channel_name(channel_name), session_name); warn = 1; success = 0; /* * If an error occurred we assume that the event is still * enabled. */ enabled = 1; } else { MSG("%s %s of type %s disabled in channel %s for session %s", get_domain_str(dom.type), event_name, print_event_type(opt_event_type), print_channel_name(channel_name), session_name); success = 1; enabled = 0; } if (lttng_opt_mi) { ret = mi_print_event(event_name, enabled, success); if (ret) { ret = CMD_ERROR; goto error; } } /* Next event */ event_name = strtok(NULL, ","); } } end: if (lttng_opt_mi) { /* Close events element and channel element */ ret = mi_lttng_close_multi_element(writer, 2); if (ret) { ret = CMD_ERROR; } } error: /* if there is already an error preserve it */ if (warn && !ret) { ret = CMD_WARNING; } /* Overwrite ret if an error occurred */ ret = command_ret ? command_ret : ret; lttng_destroy_handle(handle); return ret; }
/* * Enabling event using the lttng API. * Note: in case of error only the last error code will be return. */ static int enable_events(char *session_name) { int ret = CMD_SUCCESS, command_ret = CMD_SUCCESS; int error_holder = CMD_SUCCESS, warn = 0, error = 0, success = 1; char *event_name, *channel_name = NULL; struct lttng_event *ev; struct lttng_domain dom; char **exclusion_list = NULL; memset(&dom, 0, sizeof(dom)); ev = lttng_event_create(); if (!ev) { ret = CMD_ERROR; goto error; } if (opt_kernel) { if (opt_loglevel) { WARN("Kernel loglevels are not supported."); } } /* Create lttng domain */ if (opt_kernel) { dom.type = LTTNG_DOMAIN_KERNEL; dom.buf_type = LTTNG_BUFFER_GLOBAL; } else if (opt_userspace) { dom.type = LTTNG_DOMAIN_UST; /* Default. */ dom.buf_type = LTTNG_BUFFER_PER_UID; } else if (opt_jul) { dom.type = LTTNG_DOMAIN_JUL; /* Default. */ dom.buf_type = LTTNG_BUFFER_PER_UID; } else if (opt_log4j) { dom.type = LTTNG_DOMAIN_LOG4J; /* Default. */ dom.buf_type = LTTNG_BUFFER_PER_UID; } else if (opt_python) { dom.type = LTTNG_DOMAIN_PYTHON; /* Default. */ dom.buf_type = LTTNG_BUFFER_PER_UID; } else { /* Checked by the caller. */ assert(0); } if (opt_exclude) { switch (dom.type) { case LTTNG_DOMAIN_KERNEL: case LTTNG_DOMAIN_JUL: case LTTNG_DOMAIN_LOG4J: case LTTNG_DOMAIN_PYTHON: ERR("Event name exclusions are not yet implemented for %s events", get_domain_str(dom.type)); ret = CMD_ERROR; goto error; case LTTNG_DOMAIN_UST: /* Exclusions supported */ break; default: assert(0); } } /* * Adding a filter to a probe, function or userspace-probe would be * denied by the kernel tracer as it's not supported at the moment. We * do an early check here to warn the user. */ if (opt_filter && opt_kernel) { switch (opt_event_type) { case LTTNG_EVENT_ALL: case LTTNG_EVENT_TRACEPOINT: case LTTNG_EVENT_SYSCALL: break; case LTTNG_EVENT_PROBE: case LTTNG_EVENT_USERSPACE_PROBE: case LTTNG_EVENT_FUNCTION: ERR("Filter expressions are not supported for %s events", get_event_type_str(opt_event_type)); ret = CMD_ERROR; goto error; default: ret = CMD_UNDEFINED; goto error; } } channel_name = opt_channel_name; handle = lttng_create_handle(session_name, &dom); if (handle == NULL) { ret = -1; goto error; } /* Prepare Mi */ if (lttng_opt_mi) { /* Open a events element */ ret = mi_lttng_writer_open_element(writer, config_element_events); if (ret) { ret = CMD_ERROR; goto error; } } if (opt_enable_all) { /* Default setup for enable all */ if (opt_kernel) { ev->type = opt_event_type; strcpy(ev->name, "*"); /* kernel loglevels not implemented */ ev->loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL; } else { ev->type = LTTNG_EVENT_TRACEPOINT; strcpy(ev->name, "*"); ev->loglevel_type = opt_loglevel_type; if (opt_loglevel) { assert(opt_userspace || opt_jul || opt_log4j || opt_python); if (opt_userspace) { ev->loglevel = loglevel_str_to_value(opt_loglevel); } else if (opt_jul) { ev->loglevel = loglevel_jul_str_to_value(opt_loglevel); } else if (opt_log4j) { ev->loglevel = loglevel_log4j_str_to_value(opt_loglevel); } else if (opt_python) { ev->loglevel = loglevel_python_str_to_value(opt_loglevel); } if (ev->loglevel == -1) { ERR("Unknown loglevel %s", opt_loglevel); ret = -LTTNG_ERR_INVALID; goto error; } } else { assert(opt_userspace || opt_jul || opt_log4j || opt_python); if (opt_userspace) { ev->loglevel = -1; } else if (opt_jul) { ev->loglevel = LTTNG_LOGLEVEL_JUL_ALL; } else if (opt_log4j) { ev->loglevel = LTTNG_LOGLEVEL_LOG4J_ALL; } else if (opt_python) { ev->loglevel = LTTNG_LOGLEVEL_PYTHON_DEBUG; } } } if (opt_exclude) { ret = create_exclusion_list_and_validate("*", opt_exclude, &exclusion_list); if (ret) { ret = CMD_ERROR; goto error; } ev->exclusion = 1; warn_on_truncated_exclusion_names(exclusion_list, &warn); } if (!opt_filter) { ret = lttng_enable_event_with_exclusions(handle, ev, channel_name, NULL, exclusion_list ? strutils_array_of_strings_len(exclusion_list) : 0, exclusion_list); if (ret < 0) { switch (-ret) { case LTTNG_ERR_KERN_EVENT_EXIST: WARN("Kernel events already enabled (channel %s, session %s)", print_channel_name(channel_name), session_name); warn = 1; break; case LTTNG_ERR_TRACE_ALREADY_STARTED: { const char *msg = "The command tried to enable an event in a new domain for a session that has already been started once."; ERR("Events: %s (channel %s, session %s)", msg, print_channel_name(channel_name), session_name); error = 1; break; } default: ERR("Events: %s (channel %s, session %s)", lttng_strerror(ret), ret == -LTTNG_ERR_NEED_CHANNEL_NAME ? print_raw_channel_name(channel_name) : print_channel_name(channel_name), session_name); error = 1; break; } goto end; } switch (opt_event_type) { case LTTNG_EVENT_TRACEPOINT: if (opt_loglevel && dom.type != LTTNG_DOMAIN_KERNEL) { char *exclusion_string = print_exclusions(exclusion_list); if (!exclusion_string) { PERROR("Cannot allocate exclusion_string"); error = 1; goto end; } MSG("All %s tracepoints%s are enabled in channel %s for loglevel %s", get_domain_str(dom.type), exclusion_string, print_channel_name(channel_name), opt_loglevel); free(exclusion_string); } else { char *exclusion_string = print_exclusions(exclusion_list); if (!exclusion_string) { PERROR("Cannot allocate exclusion_string"); error = 1; goto end; } MSG("All %s tracepoints%s are enabled in channel %s", get_domain_str(dom.type), exclusion_string, print_channel_name(channel_name)); free(exclusion_string); } break; case LTTNG_EVENT_SYSCALL: if (opt_kernel) { MSG("All %s system calls are enabled in channel %s", get_domain_str(dom.type), print_channel_name(channel_name)); } break; case LTTNG_EVENT_ALL: if (opt_loglevel && dom.type != LTTNG_DOMAIN_KERNEL) { char *exclusion_string = print_exclusions(exclusion_list); if (!exclusion_string) { PERROR("Cannot allocate exclusion_string"); error = 1; goto end; } MSG("All %s events%s are enabled in channel %s for loglevel %s", get_domain_str(dom.type), exclusion_string, print_channel_name(channel_name), opt_loglevel); free(exclusion_string); } else { char *exclusion_string = print_exclusions(exclusion_list); if (!exclusion_string) { PERROR("Cannot allocate exclusion_string"); error = 1; goto end; } MSG("All %s events%s are enabled in channel %s", get_domain_str(dom.type), exclusion_string, print_channel_name(channel_name)); free(exclusion_string); } break; default: /* * We should not be here since lttng_enable_event should have * failed on the event type. */ goto error; } } if (opt_filter) { command_ret = lttng_enable_event_with_exclusions(handle, ev, channel_name, opt_filter, exclusion_list ? strutils_array_of_strings_len(exclusion_list) : 0, exclusion_list); if (command_ret < 0) { switch (-command_ret) { case LTTNG_ERR_FILTER_EXIST: WARN("Filter on all events is already enabled" " (channel %s, session %s)", print_channel_name(channel_name), session_name); warn = 1; break; case LTTNG_ERR_TRACE_ALREADY_STARTED: { const char *msg = "The command tried to enable an event in a new domain for a session that has already been started once."; ERR("All events: %s (channel %s, session %s, filter \'%s\')", msg, print_channel_name(channel_name), session_name, opt_filter); error = 1; break; } default: ERR("All events: %s (channel %s, session %s, filter \'%s\')", lttng_strerror(command_ret), command_ret == -LTTNG_ERR_NEED_CHANNEL_NAME ? print_raw_channel_name(channel_name) : print_channel_name(channel_name), session_name, opt_filter); error = 1; break; } error_holder = command_ret; } else { ev->filter = 1; MSG("Filter '%s' successfully set", opt_filter); } } if (lttng_opt_mi) { /* The wildcard * is used for kernel and ust domain to * represent ALL. We copy * in event name to force the wildcard use * for kernel domain * * Note: this is strictly for semantic and printing while in * machine interface mode. */ strcpy(ev->name, "*"); /* If we reach here the events are enabled */ if (!error && !warn) { ev->enabled = 1; } else { ev->enabled = 0; success = 0; } ret = mi_lttng_event(writer, ev, 1, handle->domain.type); if (ret) { ret = CMD_ERROR; goto error; } /* print exclusion */ ret = mi_print_exclusion(exclusion_list); if (ret) { ret = CMD_ERROR; goto error; } /* Success ? */ ret = mi_lttng_writer_write_element_bool(writer, mi_lttng_element_command_success, success); if (ret) { ret = CMD_ERROR; goto error; } /* Close event element */ ret = mi_lttng_writer_close_element(writer); if (ret) { ret = CMD_ERROR; goto error; } } goto end; } /* Strip event list */ event_name = strtok(opt_event_list, ","); while (event_name != NULL) { /* Copy name and type of the event */ strncpy(ev->name, event_name, LTTNG_SYMBOL_NAME_LEN); ev->name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; ev->type = opt_event_type; /* Kernel tracer action */ if (opt_kernel) { DBG("Enabling kernel event %s for channel %s", event_name, print_channel_name(channel_name)); switch (opt_event_type) { case LTTNG_EVENT_ALL: /* Enable tracepoints and syscalls */ /* If event name differs from *, select tracepoint. */ if (strcmp(ev->name, "*")) { ev->type = LTTNG_EVENT_TRACEPOINT; } break; case LTTNG_EVENT_TRACEPOINT: break; case LTTNG_EVENT_PROBE: ret = parse_probe_opts(ev, opt_probe); if (ret) { ERR("Unable to parse probe options"); ret = CMD_ERROR; goto error; } break; case LTTNG_EVENT_USERSPACE_PROBE: ret = parse_userspace_probe_opts(ev, opt_userspace_probe); if (ret) { switch (ret) { case CMD_UNSUPPORTED: /* * Error message describing * what is not supported was * printed in the function. */ break; case CMD_ERROR: default: ERR("Unable to parse userspace probe options"); break; } goto error; } break; case LTTNG_EVENT_FUNCTION: ret = parse_probe_opts(ev, opt_function); if (ret) { ERR("Unable to parse function probe options"); ret = CMD_ERROR; goto error; } break; case LTTNG_EVENT_SYSCALL: ev->type = LTTNG_EVENT_SYSCALL; break; default: ret = CMD_UNDEFINED; goto error; } /* kernel loglevels not implemented */ ev->loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL; } else if (opt_userspace) { /* User-space tracer action */ DBG("Enabling UST event %s for channel %s, loglevel %s", event_name, print_channel_name(channel_name), opt_loglevel ? : "<all>"); switch (opt_event_type) { case LTTNG_EVENT_ALL: /* Default behavior is tracepoint */ /* Fall-through */ case LTTNG_EVENT_TRACEPOINT: /* Copy name and type of the event */ ev->type = LTTNG_EVENT_TRACEPOINT; strncpy(ev->name, event_name, LTTNG_SYMBOL_NAME_LEN); ev->name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; break; case LTTNG_EVENT_PROBE: case LTTNG_EVENT_FUNCTION: case LTTNG_EVENT_SYSCALL: case LTTNG_EVENT_USERSPACE_PROBE: default: ERR("Event type not available for user-space tracing"); ret = CMD_UNSUPPORTED; goto error; } if (opt_exclude) { ev->exclusion = 1; if (opt_event_type != LTTNG_EVENT_ALL && opt_event_type != LTTNG_EVENT_TRACEPOINT) { ERR("Exclusion option can only be used with tracepoint events"); ret = CMD_ERROR; goto error; } /* Free previously allocated items */ strutils_free_null_terminated_array_of_strings( exclusion_list); exclusion_list = NULL; ret = create_exclusion_list_and_validate( event_name, opt_exclude, &exclusion_list); if (ret) { ret = CMD_ERROR; goto error; } warn_on_truncated_exclusion_names( exclusion_list, &warn); } ev->loglevel_type = opt_loglevel_type; if (opt_loglevel) { ev->loglevel = loglevel_str_to_value(opt_loglevel); if (ev->loglevel == -1) { ERR("Unknown loglevel %s", opt_loglevel); ret = -LTTNG_ERR_INVALID; goto error; } } else { ev->loglevel = -1; } } else if (opt_jul || opt_log4j || opt_python) { if (opt_event_type != LTTNG_EVENT_ALL && opt_event_type != LTTNG_EVENT_TRACEPOINT) { ERR("Event type not supported for domain."); ret = CMD_UNSUPPORTED; goto error; } ev->loglevel_type = opt_loglevel_type; if (opt_loglevel) { if (opt_jul) { ev->loglevel = loglevel_jul_str_to_value(opt_loglevel); } else if (opt_log4j) { ev->loglevel = loglevel_log4j_str_to_value(opt_loglevel); } else if (opt_python) { ev->loglevel = loglevel_python_str_to_value(opt_loglevel); } if (ev->loglevel == -1) { ERR("Unknown loglevel %s", opt_loglevel); ret = -LTTNG_ERR_INVALID; goto error; } } else { if (opt_jul) { ev->loglevel = LTTNG_LOGLEVEL_JUL_ALL; } else if (opt_log4j) { ev->loglevel = LTTNG_LOGLEVEL_LOG4J_ALL; } else if (opt_python) { ev->loglevel = LTTNG_LOGLEVEL_PYTHON_DEBUG; } } ev->type = LTTNG_EVENT_TRACEPOINT; strncpy(ev->name, event_name, LTTNG_SYMBOL_NAME_LEN); ev->name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; } else { assert(0); } if (!opt_filter) { char *exclusion_string; command_ret = lttng_enable_event_with_exclusions(handle, ev, channel_name, NULL, exclusion_list ? strutils_array_of_strings_len(exclusion_list) : 0, exclusion_list); exclusion_string = print_exclusions(exclusion_list); if (!exclusion_string) { PERROR("Cannot allocate exclusion_string"); error = 1; goto end; } if (command_ret < 0) { /* Turn ret to positive value to handle the positive error code */ switch (-command_ret) { case LTTNG_ERR_KERN_EVENT_EXIST: WARN("Kernel event %s%s already enabled (channel %s, session %s)", event_name, exclusion_string, print_channel_name(channel_name), session_name); warn = 1; break; case LTTNG_ERR_TRACE_ALREADY_STARTED: { const char *msg = "The command tried to enable an event in a new domain for a session that has already been started once."; ERR("Event %s%s: %s (channel %s, session %s)", event_name, exclusion_string, msg, print_channel_name(channel_name), session_name); error = 1; break; } case LTTNG_ERR_SDT_PROBE_SEMAPHORE: ERR("SDT probes %s guarded by semaphores are not supported (channel %s, session %s)", event_name, print_channel_name(channel_name), session_name); error = 1; break; default: ERR("Event %s%s: %s (channel %s, session %s)", event_name, exclusion_string, lttng_strerror(command_ret), command_ret == -LTTNG_ERR_NEED_CHANNEL_NAME ? print_raw_channel_name(channel_name) : print_channel_name(channel_name), session_name); error = 1; break; } error_holder = command_ret; } else { switch (dom.type) { case LTTNG_DOMAIN_KERNEL: case LTTNG_DOMAIN_UST: MSG("%s event %s%s created in channel %s", get_domain_str(dom.type), event_name, exclusion_string, print_channel_name(channel_name)); break; case LTTNG_DOMAIN_JUL: case LTTNG_DOMAIN_LOG4J: case LTTNG_DOMAIN_PYTHON: /* * Don't print the default channel * name for agent domains. */ MSG("%s event %s%s enabled", get_domain_str(dom.type), event_name, exclusion_string); break; default: assert(0); } } free(exclusion_string); } if (opt_filter) { char *exclusion_string; /* Filter present */ ev->filter = 1; command_ret = lttng_enable_event_with_exclusions(handle, ev, channel_name, opt_filter, exclusion_list ? strutils_array_of_strings_len(exclusion_list) : 0, exclusion_list); exclusion_string = print_exclusions(exclusion_list); if (!exclusion_string) { PERROR("Cannot allocate exclusion_string"); error = 1; goto end; } if (command_ret < 0) { switch (-command_ret) { case LTTNG_ERR_FILTER_EXIST: WARN("Filter on event %s%s is already enabled" " (channel %s, session %s)", event_name, exclusion_string, print_channel_name(channel_name), session_name); warn = 1; break; case LTTNG_ERR_TRACE_ALREADY_STARTED: { const char *msg = "The command tried to enable an event in a new domain for a session that has already been started once."; ERR("Event %s%s: %s (channel %s, session %s, filter \'%s\')", ev->name, exclusion_string, msg, print_channel_name(channel_name), session_name, opt_filter); error = 1; break; } default: ERR("Event %s%s: %s (channel %s, session %s, filter \'%s\')", ev->name, exclusion_string, lttng_strerror(command_ret), command_ret == -LTTNG_ERR_NEED_CHANNEL_NAME ? print_raw_channel_name(channel_name) : print_channel_name(channel_name), session_name, opt_filter); error = 1; break; } error_holder = command_ret; } else { MSG("Event %s%s: Filter '%s' successfully set", event_name, exclusion_string, opt_filter); } free(exclusion_string); } if (lttng_opt_mi) { if (command_ret) { success = 0; ev->enabled = 0; } else { ev->enabled = 1; } ret = mi_lttng_event(writer, ev, 1, handle->domain.type); if (ret) { ret = CMD_ERROR; goto error; } /* print exclusion */ ret = mi_print_exclusion(exclusion_list); if (ret) { ret = CMD_ERROR; goto error; } /* Success ? */ ret = mi_lttng_writer_write_element_bool(writer, mi_lttng_element_command_success, success); if (ret) { ret = CMD_ERROR; goto end; } /* Close event element */ ret = mi_lttng_writer_close_element(writer); if (ret) { ret = CMD_ERROR; goto end; } } /* Next event */ event_name = strtok(NULL, ","); /* Reset warn, error and success */ success = 1; }
/* * Enabling event using the lttng API. * Note: in case of error only the last error code will be return. */ static int enable_events(char *session_name) { int ret = CMD_SUCCESS, command_ret = CMD_SUCCESS; int error_holder = CMD_SUCCESS, warn = 0, error = 0, success = 1; char *event_name, *channel_name = NULL; struct lttng_event ev; struct lttng_domain dom; int exclusion_count = 0; char **exclusion_list = NULL; memset(&ev, 0, sizeof(ev)); memset(&dom, 0, sizeof(dom)); if (opt_kernel) { if (opt_filter) { ERR("Filter not implement for kernel tracing yet"); ret = CMD_ERROR; goto error; } if (opt_loglevel) { WARN("Kernel loglevels are not supported."); } } /* Create lttng domain */ if (opt_kernel) { dom.type = LTTNG_DOMAIN_KERNEL; dom.buf_type = LTTNG_BUFFER_GLOBAL; } else if (opt_userspace) { dom.type = LTTNG_DOMAIN_UST; /* Default. */ dom.buf_type = LTTNG_BUFFER_PER_UID; } else if (opt_jul) { dom.type = LTTNG_DOMAIN_JUL; /* Default. */ dom.buf_type = LTTNG_BUFFER_PER_UID; } else if (opt_log4j) { dom.type = LTTNG_DOMAIN_LOG4J; /* Default. */ dom.buf_type = LTTNG_BUFFER_PER_UID; } else if (opt_python) { dom.type = LTTNG_DOMAIN_PYTHON; /* Default. */ dom.buf_type = LTTNG_BUFFER_PER_UID; } else { print_missing_domain(); ret = CMD_ERROR; goto error; } if (opt_kernel && opt_exclude) { ERR("Event name exclusions are not yet implemented for kernel events"); ret = CMD_ERROR; goto error; } channel_name = opt_channel_name; handle = lttng_create_handle(session_name, &dom); if (handle == NULL) { ret = -1; goto error; } /* Prepare Mi */ if (lttng_opt_mi) { /* Open a events element */ ret = mi_lttng_writer_open_element(writer, config_element_events); if (ret) { ret = CMD_ERROR; goto error; } } if (opt_enable_all) { /* Default setup for enable all */ if (opt_kernel) { ev.type = opt_event_type; ev.name[0] = '\0'; /* kernel loglevels not implemented */ ev.loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL; } else { ev.type = LTTNG_EVENT_TRACEPOINT; strcpy(ev.name, "*"); ev.loglevel_type = opt_loglevel_type; if (opt_loglevel) { assert(opt_userspace || opt_jul || opt_log4j || opt_python); if (opt_userspace) { ev.loglevel = loglevel_str_to_value(opt_loglevel); } else if (opt_jul) { ev.loglevel = loglevel_jul_str_to_value(opt_loglevel); } else if (opt_log4j) { ev.loglevel = loglevel_log4j_str_to_value(opt_loglevel); } else if (opt_python) { ev.loglevel = loglevel_python_str_to_value(opt_loglevel); } if (ev.loglevel == -1) { ERR("Unknown loglevel %s", opt_loglevel); ret = -LTTNG_ERR_INVALID; goto error; } } else { assert(opt_userspace || opt_jul || opt_log4j || opt_python); if (opt_userspace) { ev.loglevel = -1; } else if (opt_jul || opt_log4j) { ev.loglevel = LTTNG_LOGLEVEL_JUL_ALL; } else if (opt_python) { ev.loglevel = LTTNG_LOGLEVEL_PYTHON_DEBUG; } } } if (opt_exclude) { ret = check_exclusion_subsets("*", opt_exclude, &exclusion_count, &exclusion_list); if (ret == CMD_ERROR) { goto error; } ev.exclusion = 1; } if (!opt_filter) { ret = lttng_enable_event_with_exclusions(handle, &ev, channel_name, NULL, exclusion_count, exclusion_list); if (ret < 0) { switch (-ret) { case LTTNG_ERR_KERN_EVENT_EXIST: WARN("Kernel events already enabled (channel %s, session %s)", print_channel_name(channel_name), session_name); warn = 1; break; case LTTNG_ERR_TRACE_ALREADY_STARTED: { const char *msg = "The command tried to enable an event in a new domain for a session that has already been started once."; ERR("Events: %s (channel %s, session %s)", msg, print_channel_name(channel_name), session_name); error = 1; break; } default: ERR("Events: %s (channel %s, session %s)", lttng_strerror(ret), ret == -LTTNG_ERR_NEED_CHANNEL_NAME ? print_raw_channel_name(channel_name) : print_channel_name(channel_name), session_name); error = 1; break; } goto end; } switch (opt_event_type) { case LTTNG_EVENT_TRACEPOINT: if (opt_loglevel && dom.type != LTTNG_DOMAIN_KERNEL) { char *exclusion_string = print_exclusions(exclusion_count, exclusion_list); if (!exclusion_string) { PERROR("Cannot allocate exclusion_string"); error = 1; goto end; } MSG("All %s tracepoints%s are enabled in channel %s for loglevel %s", get_domain_str(dom.type), exclusion_string, print_channel_name(channel_name), opt_loglevel); free(exclusion_string); } else { char *exclusion_string = print_exclusions(exclusion_count, exclusion_list); if (!exclusion_string) { PERROR("Cannot allocate exclusion_string"); error = 1; goto end; } MSG("All %s tracepoints%s are enabled in channel %s", get_domain_str(dom.type), exclusion_string, print_channel_name(channel_name)); free(exclusion_string); } break; case LTTNG_EVENT_SYSCALL: if (opt_kernel) { MSG("All %s system calls are enabled in channel %s", get_domain_str(dom.type), print_channel_name(channel_name)); } break; case LTTNG_EVENT_ALL: if (opt_loglevel && dom.type != LTTNG_DOMAIN_KERNEL) { char *exclusion_string = print_exclusions(exclusion_count, exclusion_list); if (!exclusion_string) { PERROR("Cannot allocate exclusion_string"); error = 1; goto end; } MSG("All %s events%s are enabled in channel %s for loglevel %s", get_domain_str(dom.type), exclusion_string, print_channel_name(channel_name), opt_loglevel); free(exclusion_string); } else { char *exclusion_string = print_exclusions(exclusion_count, exclusion_list); if (!exclusion_string) { PERROR("Cannot allocate exclusion_string"); error = 1; goto end; } MSG("All %s events%s are enabled in channel %s", get_domain_str(dom.type), exclusion_string, print_channel_name(channel_name)); free(exclusion_string); } break; default: /* * We should not be here since lttng_enable_event should have * failed on the event type. */ goto error; } } if (opt_filter) { command_ret = lttng_enable_event_with_exclusions(handle, &ev, channel_name, opt_filter, exclusion_count, exclusion_list); if (command_ret < 0) { switch (-command_ret) { case LTTNG_ERR_FILTER_EXIST: WARN("Filter on all events is already enabled" " (channel %s, session %s)", print_channel_name(channel_name), session_name); warn = 1; break; case LTTNG_ERR_TRACE_ALREADY_STARTED: { const char *msg = "The command tried to enable an event in a new domain for a session that has already been started once."; ERR("All events: %s (channel %s, session %s, filter \'%s\')", msg, print_channel_name(channel_name), session_name, opt_filter); error = 1; break; } default: ERR("All events: %s (channel %s, session %s, filter \'%s\')", lttng_strerror(command_ret), command_ret == -LTTNG_ERR_NEED_CHANNEL_NAME ? print_raw_channel_name(channel_name) : print_channel_name(channel_name), session_name, opt_filter); error = 1; break; } error_holder = command_ret; } else { ev.filter = 1; MSG("Filter '%s' successfully set", opt_filter); } } if (lttng_opt_mi) { /* The wildcard * is used for kernel and ust domain to * represent ALL. We copy * in event name to force the wildcard use * for kernel domain * * Note: this is strictly for semantic and printing while in * machine interface mode. */ strcpy(ev.name, "*"); /* If we reach here the events are enabled */ if (!error && !warn) { ev.enabled = 1; } else { ev.enabled = 0; success = 0; } ret = mi_lttng_event(writer, &ev, 1, handle->domain.type); if (ret) { ret = CMD_ERROR; goto error; } /* print exclusion */ ret = mi_print_exclusion(exclusion_count, exclusion_list); if (ret) { ret = CMD_ERROR; goto error; } /* Success ? */ ret = mi_lttng_writer_write_element_bool(writer, mi_lttng_element_command_success, success); if (ret) { ret = CMD_ERROR; goto error; } /* Close event element */ ret = mi_lttng_writer_close_element(writer); if (ret) { ret = CMD_ERROR; goto error; } } goto end; } /* Strip event list */ event_name = strtok(opt_event_list, ","); while (event_name != NULL) { /* Copy name and type of the event */ strncpy(ev.name, event_name, LTTNG_SYMBOL_NAME_LEN); ev.name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; ev.type = opt_event_type; /* Kernel tracer action */ if (opt_kernel) { DBG("Enabling kernel event %s for channel %s", event_name, print_channel_name(channel_name)); switch (opt_event_type) { case LTTNG_EVENT_ALL: /* Default behavior is tracepoint */ ev.type = LTTNG_EVENT_TRACEPOINT; /* Fall-through */ case LTTNG_EVENT_TRACEPOINT: break; case LTTNG_EVENT_PROBE: ret = parse_probe_opts(&ev, opt_probe); if (ret) { ERR("Unable to parse probe options"); ret = 0; goto error; } break; case LTTNG_EVENT_FUNCTION: ret = parse_probe_opts(&ev, opt_function); if (ret) { ERR("Unable to parse function probe options"); ret = 0; goto error; } break; case LTTNG_EVENT_FUNCTION_ENTRY: strncpy(ev.attr.ftrace.symbol_name, opt_function_entry_symbol, LTTNG_SYMBOL_NAME_LEN); ev.attr.ftrace.symbol_name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; break; case LTTNG_EVENT_SYSCALL: ev.type = LTTNG_EVENT_SYSCALL; break; default: ret = CMD_UNDEFINED; goto error; } /* kernel loglevels not implemented */ ev.loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL; } else if (opt_userspace) { /* User-space tracer action */ #if 0 if (opt_cmd_name != NULL || opt_pid) { MSG("Only supporting tracing all UST processes (-u) for now."); ret = CMD_UNDEFINED; goto error; } #endif DBG("Enabling UST event %s for channel %s, loglevel %s", event_name, print_channel_name(channel_name), opt_loglevel ? : "<all>"); switch (opt_event_type) { case LTTNG_EVENT_ALL: /* Default behavior is tracepoint */ /* Fall-through */ case LTTNG_EVENT_TRACEPOINT: /* Copy name and type of the event */ ev.type = LTTNG_EVENT_TRACEPOINT; strncpy(ev.name, event_name, LTTNG_SYMBOL_NAME_LEN); ev.name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; break; case LTTNG_EVENT_PROBE: case LTTNG_EVENT_FUNCTION: case LTTNG_EVENT_FUNCTION_ENTRY: case LTTNG_EVENT_SYSCALL: default: ERR("Event type not available for user-space tracing"); ret = CMD_UNSUPPORTED; goto error; } if (opt_exclude) { ev.exclusion = 1; if (opt_event_type != LTTNG_EVENT_ALL && opt_event_type != LTTNG_EVENT_TRACEPOINT) { ERR("Exclusion option can only be used with tracepoint events"); ret = CMD_ERROR; goto error; } /* Free previously allocated items */ if (exclusion_list != NULL) { while (exclusion_count--) { free(exclusion_list[exclusion_count]); } free(exclusion_list); exclusion_list = NULL; } /* Check for proper subsets */ ret = check_exclusion_subsets(event_name, opt_exclude, &exclusion_count, &exclusion_list); if (ret == CMD_ERROR) { goto error; } } ev.loglevel_type = opt_loglevel_type; if (opt_loglevel) { ev.loglevel = loglevel_str_to_value(opt_loglevel); if (ev.loglevel == -1) { ERR("Unknown loglevel %s", opt_loglevel); ret = -LTTNG_ERR_INVALID; goto error; } } else { ev.loglevel = -1; } } else if (opt_jul || opt_log4j || opt_python) { if (opt_event_type != LTTNG_EVENT_ALL && opt_event_type != LTTNG_EVENT_TRACEPOINT) { ERR("Event type not supported for domain."); ret = CMD_UNSUPPORTED; goto error; } ev.loglevel_type = opt_loglevel_type; if (opt_loglevel) { if (opt_jul) { ev.loglevel = loglevel_jul_str_to_value(opt_loglevel); } else if (opt_log4j) { ev.loglevel = loglevel_log4j_str_to_value(opt_loglevel); } else if (opt_python) { ev.loglevel = loglevel_python_str_to_value(opt_loglevel); } if (ev.loglevel == -1) { ERR("Unknown loglevel %s", opt_loglevel); ret = -LTTNG_ERR_INVALID; goto error; } } else { if (opt_jul) { ev.loglevel = LTTNG_LOGLEVEL_JUL_ALL; } else if (opt_log4j) { ev.loglevel = LTTNG_LOGLEVEL_LOG4J_ALL; } else if (opt_python) { ev.loglevel = LTTNG_LOGLEVEL_PYTHON_DEBUG; } } ev.type = LTTNG_EVENT_TRACEPOINT; strncpy(ev.name, event_name, LTTNG_SYMBOL_NAME_LEN); ev.name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; } else { print_missing_domain(); ret = CMD_ERROR; goto error; } if (!opt_filter) { char *exclusion_string; command_ret = lttng_enable_event_with_exclusions(handle, &ev, channel_name, NULL, exclusion_count, exclusion_list); exclusion_string = print_exclusions(exclusion_count, exclusion_list); if (!exclusion_string) { PERROR("Cannot allocate exclusion_string"); error = 1; goto end; } if (command_ret < 0) { /* Turn ret to positive value to handle the positive error code */ switch (-command_ret) { case LTTNG_ERR_KERN_EVENT_EXIST: WARN("Kernel event %s%s already enabled (channel %s, session %s)", event_name, exclusion_string, print_channel_name(channel_name), session_name); warn = 1; break; case LTTNG_ERR_TRACE_ALREADY_STARTED: { const char *msg = "The command tried to enable an event in a new domain for a session that has already been started once."; ERR("Event %s%s: %s (channel %s, session %s)", event_name, exclusion_string, msg, print_channel_name(channel_name), session_name); error = 1; break; } default: ERR("Event %s%s: %s (channel %s, session %s)", event_name, exclusion_string, lttng_strerror(command_ret), command_ret == -LTTNG_ERR_NEED_CHANNEL_NAME ? print_raw_channel_name(channel_name) : print_channel_name(channel_name), session_name); error = 1; break; } error_holder = command_ret; } else { /* So we don't print the default channel name for agent domain. */ if (dom.type == LTTNG_DOMAIN_JUL || dom.type == LTTNG_DOMAIN_LOG4J) { MSG("%s event %s%s enabled.", get_domain_str(dom.type), event_name, exclusion_string); } else { MSG("%s event %s%s created in channel %s", get_domain_str(dom.type), event_name, exclusion_string, print_channel_name(channel_name)); } } free(exclusion_string); } if (opt_filter) { char *exclusion_string; /* Filter present */ ev.filter = 1; command_ret = lttng_enable_event_with_exclusions(handle, &ev, channel_name, opt_filter, exclusion_count, exclusion_list); exclusion_string = print_exclusions(exclusion_count, exclusion_list); if (!exclusion_string) { PERROR("Cannot allocate exclusion_string"); error = 1; goto end; } if (command_ret < 0) { switch (-command_ret) { case LTTNG_ERR_FILTER_EXIST: WARN("Filter on event %s%s is already enabled" " (channel %s, session %s)", event_name, exclusion_string, print_channel_name(channel_name), session_name); warn = 1; break; case LTTNG_ERR_TRACE_ALREADY_STARTED: { const char *msg = "The command tried to enable an event in a new domain for a session that has already been started once."; ERR("Event %s%s: %s (channel %s, session %s, filter \'%s\')", ev.name, exclusion_string, msg, print_channel_name(channel_name), session_name, opt_filter); error = 1; break; } default: ERR("Event %s%s: %s (channel %s, session %s, filter \'%s\')", ev.name, exclusion_string, lttng_strerror(command_ret), command_ret == -LTTNG_ERR_NEED_CHANNEL_NAME ? print_raw_channel_name(channel_name) : print_channel_name(channel_name), session_name, opt_filter); error = 1; break; } error_holder = command_ret; } else { MSG("Event %s%s: Filter '%s' successfully set", event_name, exclusion_string, opt_filter); } free(exclusion_string); } if (lttng_opt_mi) { if (command_ret) { success = 0; ev.enabled = 0; } else { ev.enabled = 1; } ret = mi_lttng_event(writer, &ev, 1, handle->domain.type); if (ret) { ret = CMD_ERROR; goto error; } /* print exclusion */ ret = mi_print_exclusion(exclusion_count, exclusion_list); if (ret) { ret = CMD_ERROR; goto error; } /* Success ? */ ret = mi_lttng_writer_write_element_bool(writer, mi_lttng_element_command_success, success); if (ret) { ret = CMD_ERROR; goto end; } /* Close event element */ ret = mi_lttng_writer_close_element(writer); if (ret) { ret = CMD_ERROR; goto end; } } /* Next event */ event_name = strtok(NULL, ","); /* Reset warn, error and success */ success = 1; }
static enum cmd_error_code track_untrack_pid(enum cmd_type cmd_type, const char *cmd_str, const char *session_name, const char *pid_string, int all, struct mi_writer *writer) { int ret, success = 1 , i; enum cmd_error_code retval = CMD_SUCCESS; int *pid_list = NULL; int nr_pids; struct lttng_domain dom; struct lttng_handle *handle = NULL; int (*cmd_func)(struct lttng_handle *handle, int pid); switch (cmd_type) { case CMD_TRACK: cmd_func = lttng_track_pid; break; case CMD_UNTRACK: cmd_func = lttng_untrack_pid; break; default: ERR("Unknown command"); retval = CMD_ERROR; goto end; } memset(&dom, 0, sizeof(dom)); if (opt_kernel) { dom.type = LTTNG_DOMAIN_KERNEL; } else if (opt_userspace) { dom.type = LTTNG_DOMAIN_UST; } else { /* Checked by the caller. */ assert(0); } ret = parse_pid_string(pid_string, all, &pid_list, &nr_pids); if (ret != CMD_SUCCESS) { ERR("Error parsing PID string"); retval = CMD_ERROR; goto end; } handle = lttng_create_handle(session_name, &dom); if (handle == NULL) { retval = CMD_ERROR; goto end; } if (writer) { /* Open process element */ ret = mi_lttng_targets_open(writer); if (ret) { retval = CMD_ERROR; goto end; } } for (i = 0; i < nr_pids; i++) { DBG("%s PID %d", cmd_str, pid_list[i]); ret = cmd_func(handle, pid_list[i]); if (ret) { switch (-ret) { case LTTNG_ERR_PID_TRACKED: WARN("PID %i already tracked in session %s", pid_list[i], session_name); success = 1; retval = CMD_SUCCESS; break; case LTTNG_ERR_PID_NOT_TRACKED: WARN("PID %i not tracked in session %s", pid_list[i], session_name); success = 1; retval = CMD_SUCCESS; break; default: ERR("%s", lttng_strerror(ret)); success = 0; retval = CMD_ERROR; break; } } else { MSG("PID %i %sed in session %s", pid_list[i], cmd_str, session_name); success = 1; } /* Mi */ if (writer) { ret = mi_lttng_pid_target(writer, pid_list[i], 1); if (ret) { retval = CMD_ERROR; goto end; } ret = mi_lttng_writer_write_element_bool(writer, mi_lttng_element_success, success); if (ret) { retval = CMD_ERROR; goto end; } ret = mi_lttng_writer_close_element(writer); if (ret) { retval = CMD_ERROR; goto end; } } } if (writer) { /* Close targets element */ ret = mi_lttng_writer_close_element(writer); if (ret) { retval = CMD_ERROR; goto end; } } end: if (handle) { lttng_destroy_handle(handle); } free(pid_list); return retval; }
/* * Start tracing for all trace of the session. */ static int stop_tracing(void) { int ret; char *session_name; if (opt_session_name == NULL) { session_name = get_session_name(); if (session_name == NULL) { ret = CMD_ERROR; goto error; } } else { session_name = opt_session_name; } ret = lttng_stop_tracing_no_wait(session_name); if (ret < 0) { switch (-ret) { case LTTNG_ERR_TRACE_ALREADY_STOPPED: WARN("Tracing already stopped for session %s", session_name); break; default: ERR("%s", lttng_strerror(ret)); break; } goto free_name; } if (!opt_no_wait) { _MSG("Waiting for data availability"); fflush(stdout); do { ret = lttng_data_pending(session_name); if (ret < 0) { /* Return the data available call error. */ goto free_name; } /* * Data sleep time before retrying (in usec). Don't sleep if the call * returned value indicates availability. */ if (ret) { usleep(DEFAULT_DATA_AVAILABILITY_WAIT_TIME); _MSG("."); fflush(stdout); } } while (ret != 0); MSG(""); } ret = CMD_SUCCESS; print_session_stats(session_name); MSG("Tracing stopped for session %s", session_name); if (lttng_opt_mi) { ret = mi_print_session(session_name, 0); if (ret) { goto free_name; } } free_name: if (opt_session_name == NULL) { free(session_name); } error: return ret; }
/* * The 'destroy <options>' first level command */ int cmd_destroy(int argc, const char **argv) { int opt; int ret = CMD_SUCCESS , i, command_ret = CMD_SUCCESS, success = 1; static poptContext pc; char *session_name = NULL; const char *leftover = NULL; struct lttng_session *sessions; int count; int found; pc = poptGetContext(NULL, argc, argv, long_options, 0); poptReadDefaultConfig(pc, 0); while ((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { case OPT_HELP: SHOW_HELP(); break; case OPT_LIST_OPTIONS: list_cmd_options(stdout, long_options); break; default: ret = CMD_UNDEFINED; break; } goto end; } /* Mi preparation */ if (lttng_opt_mi) { writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi); if (!writer) { ret = -LTTNG_ERR_NOMEM; goto end; } /* Open command element */ ret = mi_lttng_writer_command_open(writer, mi_lttng_element_command_destroy); if (ret) { ret = CMD_ERROR; goto end; } /* Open output element */ ret = mi_lttng_writer_open_element(writer, mi_lttng_element_command_output); if (ret) { ret = CMD_ERROR; goto end; } /* For validation and semantic purpose we open a sessions element */ ret = mi_lttng_sessions_open(writer); if (ret) { ret = CMD_ERROR; goto end; } } /* Recuperate all sessions for further operation */ count = lttng_list_sessions(&sessions); if (count < 0) { ERR("%s", lttng_strerror(count)); command_ret = CMD_ERROR; success = 0; goto mi_closing; } /* Ignore session name in case all sessions are to be destroyed */ if (opt_destroy_all) { command_ret = destroy_all_sessions(sessions, count); if (command_ret) { success = 0; } } else { opt_session_name = (char *) poptGetArg(pc); if (!opt_session_name) { /* No session name specified, lookup default */ session_name = get_session_name(); if (session_name == NULL) { command_ret = CMD_ERROR; success = 0; goto mi_closing; } } else { session_name = opt_session_name; } /* Find the corresponding lttng_session struct */ found = 0; for (i = 0; i < count; i++) { if (strncmp(sessions[i].name, session_name, NAME_MAX) == 0) { found = 1; command_ret = destroy_session(&sessions[i]); if (command_ret) { success = 0; } } } if (!found) { ERR("Session name %s not found", session_name); command_ret = LTTNG_ERR_SESS_NOT_FOUND; success = 0; goto mi_closing; } } leftover = poptGetArg(pc); if (leftover) { ERR("Unknown argument: %s", leftover); ret = CMD_ERROR; success = 0; goto mi_closing; } mi_closing: /* Mi closing */ if (lttng_opt_mi) { /* Close sessions and output element element */ ret = mi_lttng_close_multi_element(writer, 2); if (ret) { ret = CMD_ERROR; goto end; } /* Success ? */ ret = mi_lttng_writer_write_element_bool(writer, mi_lttng_element_command_success, success); if (ret) { ret = CMD_ERROR; goto end; } /* Command element close */ ret = mi_lttng_writer_command_close(writer); if (ret) { ret = CMD_ERROR; goto end; } } end: /* Mi clean-up */ if (writer && mi_lttng_writer_destroy(writer)) { /* Preserve original error code */ ret = ret ? ret : -LTTNG_ERR_MI_IO_FAIL; } if (opt_session_name == NULL) { free(session_name); } /* Overwrite ret if an error occurred during destroy_session/all */ ret = command_ret ? command_ret : ret; poptFreeContext(pc); return ret; }
/* * The 'snapshot <cmd> <options>' first level command */ int cmd_snapshot(int argc, const char **argv) { int opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS, success = 1; char *session_name = NULL; static poptContext pc; pc = poptGetContext(NULL, argc, argv, snapshot_opts, 0); poptReadDefaultConfig(pc, 0); /* Mi check */ if (lttng_opt_mi) { writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi); if (!writer) { ret = -LTTNG_ERR_NOMEM; goto end; } /* Open command element */ ret = mi_lttng_writer_command_open(writer, mi_lttng_element_command_snapshot); if (ret) { ret = CMD_ERROR; goto end; } /* Open output element */ ret = mi_lttng_writer_open_element(writer, mi_lttng_element_command_output); if (ret) { ret = CMD_ERROR; goto end; } } while ((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { case OPT_HELP: usage(stdout); goto end; case OPT_LIST_OPTIONS: list_cmd_options(stdout, snapshot_opts); goto end; case OPT_LIST_COMMANDS: list_commands(actions, stdout); goto end; case OPT_MAX_SIZE: { uint64_t val; const char *opt = poptGetOptArg(pc); if (utils_parse_size_suffix((char *) opt, &val) < 0) { ERR("Unable to handle max-size value %s", opt); ret = CMD_ERROR; goto end; } opt_max_size = val; break; } default: usage(stderr); ret = CMD_UNDEFINED; goto end; } } if (!opt_session_name) { session_name = get_session_name(); if (session_name == NULL) { ret = CMD_ERROR; goto end; } current_session_name = session_name; } else { current_session_name = opt_session_name; } command_ret = handle_command(poptGetArgs(pc)); if (command_ret) { switch (-command_ret) { case LTTNG_ERR_EPERM: ERR("The session needs to be set in no output mode (--no-output)"); break; case LTTNG_ERR_SNAPSHOT_NODATA: WARN("%s", lttng_strerror(command_ret)); break; default: ERR("%s", lttng_strerror(command_ret)); break; } success = 0; } if (lttng_opt_mi) { /* Close output element */ ret = mi_lttng_writer_close_element(writer); if (ret) { ret = CMD_ERROR; goto end; } /* Success ? */ ret = mi_lttng_writer_write_element_bool(writer, mi_lttng_element_command_success, success); if (ret) { ret = CMD_ERROR; goto end; } /* Command element close */ ret = mi_lttng_writer_command_close(writer); if (ret) { ret = CMD_ERROR; goto end; } } end: /* Mi clean-up */ if (writer && mi_lttng_writer_destroy(writer)) { /* Preserve original error code */ ret = ret ? ret : -LTTNG_ERR_MI_IO_FAIL; } if (!opt_session_name) { free(session_name); } /* Overwrite ret if an error occured during handle_command */ ret = command_ret ? command_ret : ret; poptFreeContext(pc); return ret; }
int main(int argc, char **argv) { int ret = 0; enum lttng_condition_status condition_status; enum lttng_notification_channel_status nc_status; struct lttng_notification_channel *notification_channel = NULL; struct lttng_condition *condition = NULL; struct lttng_action *action = NULL; struct lttng_trigger *trigger = NULL; /* * Disable buffering on stdout. * Safety measure to prevent hang on the validation side since * stdout is used for outside synchronization. */ setbuf(stdout, NULL); if (argc < 8) { printf("error: Missing arguments for tests\n"); ret = 1; goto end; } ret = parse_arguments(argv); if (ret) { printf("error: Could not parse arguments\n"); goto end; } /* Setup */ notification_channel = lttng_notification_channel_create( lttng_session_daemon_notification_endpoint); if (!notification_channel) { printf("error: Could not create notification channel\n"); ret = 1; goto end; } switch (buffer_usage_type) { case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW: condition = lttng_condition_buffer_usage_low_create(); break; case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH: condition = lttng_condition_buffer_usage_high_create(); break; default: printf("error: Invalid buffer_usage_type\n"); ret = 1; goto end; } if (!condition) { printf("error: Could not create condition object\n"); ret = 1; goto end; } if (is_threshold_ratio) { condition_status = lttng_condition_buffer_usage_set_threshold_ratio( condition, threshold_ratio); } else { condition_status = lttng_condition_buffer_usage_set_threshold( condition, threshold_bytes); } if (condition_status != LTTNG_CONDITION_STATUS_OK) { printf("error: Could not set threshold\n"); ret = 1; goto end; } condition_status = lttng_condition_buffer_usage_set_session_name( condition, session_name); if (condition_status != LTTNG_CONDITION_STATUS_OK) { printf("error: Could not set session name\n"); ret = 1; goto end; } condition_status = lttng_condition_buffer_usage_set_channel_name( condition, channel_name); if (condition_status != LTTNG_CONDITION_STATUS_OK) { printf("error: Could not set channel name\n"); ret = 1; goto end; } condition_status = lttng_condition_buffer_usage_set_domain_type( condition, domain_type); if (condition_status != LTTNG_CONDITION_STATUS_OK) { printf("error: Could not set domain type\n"); ret = 1; goto end; } action = lttng_action_notify_create(); if (!action) { printf("error: Could not create action notify\n"); ret = 1; goto end; } trigger = lttng_trigger_create(condition, action); if (!trigger) { printf("error: Could not create trigger\n"); ret = 1; goto end; } ret = lttng_register_trigger(trigger); /* * An equivalent trigger might already be registered if an other app * registered an equivalent trigger. */ if (ret < 0 && ret != -LTTNG_ERR_TRIGGER_EXISTS) { printf("error: %s\n", lttng_strerror(ret)); ret = 1; goto end; } nc_status = lttng_notification_channel_subscribe(notification_channel, condition); if (nc_status != LTTNG_NOTIFICATION_CHANNEL_STATUS_OK) { printf("error: Could not subscribe\n"); ret = 1; goto end; } /* Tell outside process that the client is ready */ printf("sync: ready\n"); for (;;) { struct lttng_notification *notification; enum lttng_notification_channel_status status; const struct lttng_evaluation *notification_evaluation; const struct lttng_condition *notification_condition; if (nr_notifications == nr_expected_notifications) { ret = 0; goto end; } /* Receive the next notification. */ status = lttng_notification_channel_get_next_notification( notification_channel, ¬ification); switch (status) { case LTTNG_NOTIFICATION_CHANNEL_STATUS_OK: break; case LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED: ret = 1; printf("error: No drop should be observed during this test app\n"); goto end; case LTTNG_NOTIFICATION_CHANNEL_STATUS_CLOSED: /* * The notification channel has been closed by the * session daemon. This is typically caused by a session * daemon shutting down (cleanly or because of a crash). */ printf("error: Notification channel was closed\n"); ret = 1; goto end; default: /* Unhandled conditions / errors. */ printf("error: Unknown notification channel status\n"); ret = 1; goto end; } notification_condition = lttng_notification_get_condition(notification); notification_evaluation = lttng_notification_get_evaluation(notification); ret = handle_condition(notification_condition, notification_evaluation); nr_notifications++; lttng_notification_destroy(notification); if (ret != 0) { goto end; } } end: if (trigger) { lttng_unregister_trigger(trigger); } if (lttng_notification_channel_unsubscribe(notification_channel, condition)) { printf("error: channel unsubscribe error\n"); } lttng_trigger_destroy(trigger); lttng_condition_destroy(condition); lttng_action_destroy(action); lttng_notification_channel_destroy(notification_channel); printf("exit: %d\n", ret); return ret; }
/* * List available tracing session. List only basic information. * * If session_name is NULL, all sessions are listed. */ static int list_sessions(const char *session_name) { int ret = CMD_SUCCESS; int count, i; unsigned int session_found = 0; struct lttng_session *sessions; count = lttng_list_sessions(&sessions); DBG("Session count %d", count); if (count < 0) { ret = CMD_ERROR; ERR("%s", lttng_strerror(count)); goto end; } if (lttng_opt_mi) { /* Mi */ if (session_name == NULL) { /* List all session */ ret = mi_list_sessions(sessions, count); } else { /* Note : this return an open session element */ ret = mi_list_session(session_name, sessions, count); } if (ret) { ret = CMD_ERROR; goto error; } } else { /* Pretty print */ if (count == 0) { MSG("Currently no available tracing session"); goto end; } if (session_name == NULL) { MSG("Available tracing sessions:"); } for (i = 0; i < count; i++) { if (session_name != NULL) { if (strncmp(sessions[i].name, session_name, NAME_MAX) == 0) { session_found = 1; MSG("Tracing session %s: [%s%s]", session_name, active_string(sessions[i].enabled), snapshot_string(sessions[i].snapshot_mode)); MSG("%sTrace path: %s\n", indent4, sessions[i].path); break; } } else { MSG(" %d) %s (%s) [%s%s]", i + 1, sessions[i].name, sessions[i].path, active_string(sessions[i].enabled), snapshot_string(sessions[i].snapshot_mode)); MSG("%sTrace path: %s", indent4, sessions[i].path); if (sessions[i].live_timer_interval != 0) { MSG("%sLive timer interval (usec): %u", indent4, sessions[i].live_timer_interval); } MSG(""); } } if (!session_found && session_name != NULL) { ERR("Session '%s' not found", session_name); ret = CMD_ERROR; goto error; } if (session_name == NULL) { MSG("\nUse lttng list <session_name> for more details"); } } error: free(sessions); end: return ret; }
/* * List channel(s) of session and domain. * * If channel_name is NULL, all channels are listed. */ static int list_channels(const char *channel_name) { int count, i, ret = CMD_SUCCESS; unsigned int chan_found = 0; struct lttng_channel *channels = NULL; DBG("Listing channel(s) (%s)", channel_name ? : "<all>"); count = lttng_list_channels(handle, &channels); if (count < 0) { switch (-count) { case LTTNG_ERR_KERN_CHAN_NOT_FOUND: if (lttng_opt_mi) { /* When printing mi this is not an error * but an empty channels element */ count = 0; } else { ret = CMD_SUCCESS; WARN("No kernel channel"); goto error_channels; } break; default: /* We had a real error */ ret = CMD_ERROR; ERR("%s", lttng_strerror(count)); goto error_channels; break; } } if (lttng_opt_mi) { /* Mi print */ ret = mi_list_channels(channels, count, channel_name); if (ret) { ret = CMD_ERROR; goto error; } } else { /* Pretty print */ if (count) { MSG("Channels:\n-------------"); } for (i = 0; i < count; i++) { if (channel_name != NULL) { if (strncmp(channels[i].name, channel_name, NAME_MAX) == 0) { chan_found = 1; } else { continue; } } print_channel(&channels[i]); /* Listing events per channel */ ret = list_events(channels[i].name); if (ret) { goto error; } if (chan_found) { break; } } if (!chan_found && channel_name != NULL) { ret = CMD_ERROR; ERR("Channel %s not found", channel_name); goto error; } } error: free(channels); error_channels: return ret; }
/* * destroy_session * * Unregister the provided session to the session daemon. On success, removes * the default configuration. */ static int destroy_session(struct lttng_session *session) { int ret; char *session_name = NULL; bool session_was_stopped; ret = lttng_stop_tracing_no_wait(session->name); if (ret < 0 && ret != -LTTNG_ERR_TRACE_ALREADY_STOPPED) { ERR("%s", lttng_strerror(ret)); } session_was_stopped = ret == -LTTNG_ERR_TRACE_ALREADY_STOPPED; if (!opt_no_wait) { bool printed_wait_msg = false; do { ret = lttng_data_pending(session->name); if (ret < 0) { /* Return the data available call error. */ goto error; } /* * Data sleep time before retrying (in usec). Don't sleep if the call * returned value indicates availability. */ if (ret) { if (!printed_wait_msg) { _MSG("Waiting for data availability"); fflush(stdout); } printed_wait_msg = true; usleep(DEFAULT_DATA_AVAILABILITY_WAIT_TIME); _MSG("."); fflush(stdout); } } while (ret != 0); if (printed_wait_msg) { MSG(""); } } if (!session_was_stopped) { /* * Don't print the event and packet loss warnings since the user * already saw them when stopping the trace. */ print_session_stats(session->name); } ret = lttng_destroy_session_no_wait(session->name); if (ret < 0) { goto error; } MSG("Session %s destroyed", session->name); session_name = get_session_name_quiet(); if (session_name && !strncmp(session->name, session_name, NAME_MAX)) { config_destroy_default(); } if (lttng_opt_mi) { ret = mi_lttng_session(writer, session, 0); if (ret) { ret = CMD_ERROR; goto error; } } ret = CMD_SUCCESS; error: free(session_name); return ret; }
/* * Ask session daemon for all user space tracepoint fields available. */ static int list_ust_event_fields(void) { int i, size, ret = CMD_SUCCESS; struct lttng_domain domain; struct lttng_handle *handle; struct lttng_event_field *event_field_list; pid_t cur_pid = 0; char *cmdline = NULL; struct lttng_event cur_event; memset(&domain, 0, sizeof(domain)); memset(&cur_event, 0, sizeof(cur_event)); DBG("Getting UST tracing event fields"); domain.type = LTTNG_DOMAIN_UST; handle = lttng_create_handle(NULL, &domain); if (handle == NULL) { ret = CMD_ERROR; goto end; } size = lttng_list_tracepoint_fields(handle, &event_field_list); if (size < 0) { ERR("Unable to list UST event fields: %s", lttng_strerror(size)); ret = CMD_ERROR; goto end; } if (lttng_opt_mi) { /* Mi print */ ret = mi_list_ust_event_fields(event_field_list, size, &domain); if (ret) { ret = CMD_ERROR; goto error; } } else { /* Pretty print */ MSG("UST events:\n-------------"); if (size == 0) { MSG("None"); } for (i = 0; i < size; i++) { if (cur_pid != event_field_list[i].event.pid) { cur_pid = event_field_list[i].event.pid; cmdline = get_cmdline_by_pid(cur_pid); if (cmdline == NULL) { ret = CMD_ERROR; goto error; } MSG("\nPID: %d - Name: %s", cur_pid, cmdline); free(cmdline); /* Wipe current event since we are about to print a new PID. */ memset(&cur_event, 0, sizeof(cur_event)); } if (strcmp(cur_event.name, event_field_list[i].event.name) != 0) { print_events(&event_field_list[i].event); memcpy(&cur_event, &event_field_list[i].event, sizeof(cur_event)); } print_event_field(&event_field_list[i]); } MSG(""); } error: free(event_field_list); end: lttng_destroy_handle(handle); return ret; }
/* * Adding channel using the lttng API. */ static int enable_channel(char *session_name) { int ret = CMD_SUCCESS, warn = 0, error = 0, success = 0; char *channel_name; struct lttng_domain dom; memset(&dom, 0, sizeof(dom)); /* Create lttng domain */ if (opt_kernel) { dom.type = LTTNG_DOMAIN_KERNEL; dom.buf_type = LTTNG_BUFFER_GLOBAL; if (opt_buffer_uid || opt_buffer_pid) { ERR("Buffer type not supported for domain -k"); ret = CMD_ERROR; goto error; } } else if (opt_userspace) { dom.type = LTTNG_DOMAIN_UST; if (opt_buffer_pid) { dom.buf_type = LTTNG_BUFFER_PER_PID; } else { if (opt_buffer_global) { ERR("Buffer type not supported for domain -u"); ret = CMD_ERROR; goto error; } dom.buf_type = LTTNG_BUFFER_PER_UID; } } else { print_missing_domain(); ret = CMD_ERROR; goto error; } set_default_attr(&dom); if (chan.attr.tracefile_size == 0 && chan.attr.tracefile_count) { ERR("Missing option --tracefile-size. " "A file count without a size won't do anything."); ret = CMD_ERROR; goto error; } if ((chan.attr.tracefile_size > 0) && (chan.attr.tracefile_size < chan.attr.subbuf_size)) { WARN("Tracefile size rounded up from (%" PRIu64 ") to subbuffer size (%" PRIu64 ")", chan.attr.tracefile_size, chan.attr.subbuf_size); chan.attr.tracefile_size = chan.attr.subbuf_size; } /* Setting channel output */ if (opt_output) { if (!strncmp(output_mmap, opt_output, strlen(output_mmap))) { chan.attr.output = LTTNG_EVENT_MMAP; } else if (!strncmp(output_splice, opt_output, strlen(output_splice))) { chan.attr.output = LTTNG_EVENT_SPLICE; } else { ERR("Unknown output type %s. Possible values are: %s, %s\n", opt_output, output_mmap, output_splice); usage(stderr); ret = CMD_ERROR; goto error; } } handle = lttng_create_handle(session_name, &dom); if (handle == NULL) { ret = -1; goto error; } /* Mi open channels element */ if (lttng_opt_mi) { assert(writer); ret = mi_lttng_channels_open(writer); if (ret) { ret = CMD_ERROR; goto error; } } /* Strip channel list (format: chan1,chan2,...) */ channel_name = strtok(opt_channels, ","); while (channel_name != NULL) { /* Copy channel name and normalize it */ strncpy(chan.name, channel_name, NAME_MAX); chan.name[NAME_MAX - 1] = '\0'; DBG("Enabling channel %s", channel_name); ret = lttng_enable_channel(handle, &chan); if (ret < 0) { success = 0; switch (-ret) { case LTTNG_ERR_KERN_CHAN_EXIST: case LTTNG_ERR_UST_CHAN_EXIST: case LTTNG_ERR_CHAN_EXIST: WARN("Channel %s: %s (session %s)", channel_name, lttng_strerror(ret), session_name); warn = 1; break; default: ERR("Channel %s: %s (session %s)", channel_name, lttng_strerror(ret), session_name); error = 1; break; } } else { MSG("%s channel %s enabled for session %s", get_domain_str(dom.type), channel_name, session_name); success = 1; } if (lttng_opt_mi) { /* Mi print the channel element and leave it open */ ret = mi_lttng_channel(writer, &chan, 1); if (ret) { ret = CMD_ERROR; goto error; } /* Individual Success ? */ ret = mi_lttng_writer_write_element_bool(writer, mi_lttng_element_command_success, success); if (ret) { ret = CMD_ERROR; goto error; } /* Close channel element */ ret = mi_lttng_writer_close_element(writer); if (ret) { ret = CMD_ERROR; goto error; } } /* Next channel */ channel_name = strtok(NULL, ","); } if (lttng_opt_mi) { /* Close channels element */ ret = mi_lttng_writer_close_element(writer); if (ret) { ret = CMD_ERROR; goto error; } } ret = CMD_SUCCESS; error: /* If more important error happen bypass the warning */ if (!ret && warn) { ret = CMD_WARNING; } /* If more important error happen bypass the warning */ if (!ret && error) { ret = CMD_ERROR; } lttng_destroy_handle(handle); return ret; }
/* * The 'list <options>' first level command */ int cmd_list(int argc, const char **argv) { int opt, ret = CMD_SUCCESS; const char *session_name; static poptContext pc; struct lttng_domain domain; struct lttng_domain *domains = NULL; memset(&domain, 0, sizeof(domain)); if (argc < 1) { usage(stderr); ret = CMD_ERROR; goto end; } pc = poptGetContext(NULL, argc, argv, long_options, 0); poptReadDefaultConfig(pc, 0); while ((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { case OPT_HELP: usage(stdout); goto end; case OPT_USERSPACE: opt_userspace = 1; break; case OPT_LIST_OPTIONS: list_cmd_options(stdout, long_options); goto end; default: usage(stderr); ret = CMD_UNDEFINED; goto end; } } /* Mi check */ if (lttng_opt_mi) { writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi); if (!writer) { ret = CMD_ERROR; goto end; } /* Open command element */ ret = mi_lttng_writer_command_open(writer, mi_lttng_element_command_list); if (ret) { ret = CMD_ERROR; goto end; } /* Open output element */ ret = mi_lttng_writer_open_element(writer, mi_lttng_element_command_output); if (ret) { ret = CMD_ERROR; goto end; } } /* Get session name (trailing argument) */ session_name = poptGetArg(pc); DBG2("Session name: %s", session_name); if (opt_kernel) { domain.type = LTTNG_DOMAIN_KERNEL; } else if (opt_userspace) { DBG2("Listing userspace global domain"); domain.type = LTTNG_DOMAIN_UST; } else if (opt_jul) { DBG2("Listing JUL domain"); domain.type = LTTNG_DOMAIN_JUL; } else if (opt_log4j) { domain.type = LTTNG_DOMAIN_LOG4J; } else if (opt_python) { domain.type = LTTNG_DOMAIN_PYTHON; } if (!opt_kernel && opt_syscall) { WARN("--syscall will only work with the Kernel domain (-k)"); ret = CMD_ERROR; goto end; } if (opt_kernel || opt_userspace || opt_jul || opt_log4j || opt_python) { handle = lttng_create_handle(session_name, &domain); if (handle == NULL) { ret = CMD_FATAL; goto end; } } if (session_name == NULL) { if (!opt_kernel && !opt_userspace && !opt_jul && !opt_log4j && !opt_python) { ret = list_sessions(NULL); if (ret) { goto end; } } if (opt_kernel) { if (opt_syscall) { ret = list_syscalls(); if (ret) { goto end; } } else { ret = list_kernel_events(); if (ret) { goto end; } } } if (opt_userspace) { if (opt_fields) { ret = list_ust_event_fields(); } else { ret = list_ust_events(); } if (ret) { goto end; } } if (opt_jul || opt_log4j || opt_python) { ret = list_agent_events(); if (ret) { goto end; } } } else { /* List session attributes */ if (lttng_opt_mi) { /* Open element sessions * Present for xml consistency */ ret = mi_lttng_sessions_open(writer); if (ret) { goto end; } } /* MI: the ouptut of list_sessions is an unclosed session element */ ret = list_sessions(session_name); if (ret) { goto end; } /* Domain listing */ if (opt_domain) { ret = list_domains(session_name); goto end; } /* Channel listing */ if (opt_kernel || opt_userspace) { if (lttng_opt_mi) { /* Add of domains and domain element for xml * consistency and validation */ ret = mi_lttng_domains_open(writer); if (ret) { goto end; } /* Open domain and leave it open for * nested channels printing */ ret = mi_lttng_domain(writer, &domain, 1); if (ret) { goto end; } } ret = list_tracker_pids(); if (ret) { goto end; } ret = list_channels(opt_channel); if (ret) { goto end; } if (lttng_opt_mi) { /* Close domain and domain element */ ret = mi_lttng_close_multi_element(writer, 2); } if (ret) { goto end; } } else { int i, nb_domain; /* We want all domain(s) */ nb_domain = lttng_list_domains(session_name, &domains); if (nb_domain < 0) { ret = CMD_ERROR; ERR("%s", lttng_strerror(nb_domain)); goto end; } if (lttng_opt_mi) { ret = mi_lttng_domains_open(writer); if (ret) { ret = CMD_ERROR; goto end; } } for (i = 0; i < nb_domain; i++) { switch (domains[i].type) { case LTTNG_DOMAIN_KERNEL: MSG("=== Domain: Kernel ===\n"); break; case LTTNG_DOMAIN_UST: MSG("=== Domain: UST global ===\n"); MSG("Buffer type: %s\n", domains[i].buf_type == LTTNG_BUFFER_PER_PID ? "per PID" : "per UID"); break; case LTTNG_DOMAIN_JUL: MSG("=== Domain: JUL (Java Util Logging) ===\n"); break; case LTTNG_DOMAIN_LOG4J: MSG("=== Domain: LOG4j (Logging for Java) ===\n"); break; case LTTNG_DOMAIN_PYTHON: MSG("=== Domain: Python (logging) ===\n"); break; default: MSG("=== Domain: Unimplemented ===\n"); break; } if (lttng_opt_mi) { ret = mi_lttng_domain(writer, &domains[i], 1); if (ret) { ret = CMD_ERROR; goto end; } } /* Clean handle before creating a new one */ if (handle) { lttng_destroy_handle(handle); } handle = lttng_create_handle(session_name, &domains[i]); if (handle == NULL) { ret = CMD_FATAL; goto end; } if (domains[i].type == LTTNG_DOMAIN_JUL || domains[i].type == LTTNG_DOMAIN_LOG4J || domains[i].type == LTTNG_DOMAIN_PYTHON) { ret = list_session_agent_events(); if (ret) { goto end; } continue; } switch (domains[i].type) { case LTTNG_DOMAIN_KERNEL: case LTTNG_DOMAIN_UST: ret = list_tracker_pids(); if (ret) { goto end; } break; default: break; } ret = list_channels(opt_channel); if (ret) { goto end; } if (lttng_opt_mi) { /* Close domain element */ ret = mi_lttng_writer_close_element(writer); if (ret) { ret = CMD_ERROR; goto end; } } } if (lttng_opt_mi) { /* Close the domains, session and sessions element */ ret = mi_lttng_close_multi_element(writer, 3); if (ret) { ret = CMD_ERROR; goto end; } } } } /* Mi closing */ if (lttng_opt_mi) { /* Close output element */ ret = mi_lttng_writer_close_element(writer); if (ret) { ret = CMD_ERROR; goto end; } /* Command element close */ ret = mi_lttng_writer_command_close(writer); if (ret) { ret = CMD_ERROR; goto end; } } end: /* Mi clean-up */ if (writer && mi_lttng_writer_destroy(writer)) { /* Preserve original error code */ ret = ret ? ret : -LTTNG_ERR_MI_IO_FAIL; } free(domains); if (handle) { lttng_destroy_handle(handle); } poptFreeContext(pc); return ret; }
/* * Adding channel using the lttng API. */ static int enable_channel(char *session_name) { int ret = CMD_SUCCESS, warn = 0; char *channel_name; struct lttng_domain dom; memset(&dom, 0, sizeof(dom)); /* Create lttng domain */ if (opt_kernel) { dom.type = LTTNG_DOMAIN_KERNEL; dom.buf_type = LTTNG_BUFFER_GLOBAL; if (opt_buffer_uid || opt_buffer_pid) { ERR("Buffer type not supported for domain -k"); ret = CMD_ERROR; goto error; } } else if (opt_userspace) { dom.type = LTTNG_DOMAIN_UST; if (opt_buffer_uid) { dom.buf_type = LTTNG_BUFFER_PER_UID; } else { if (opt_buffer_global) { ERR("Buffer type not supported for domain -u"); ret = CMD_ERROR; goto error; } dom.buf_type = LTTNG_BUFFER_PER_PID; } } else { ERR("Please specify a tracer (-k/--kernel or -u/--userspace)"); ret = CMD_ERROR; goto error; } set_default_attr(&dom); if (chan.attr.tracefile_size == 0 && chan.attr.tracefile_count) { ERR("Missing option --tracefile-size. " "A file count without a size won't do anything."); ret = CMD_ERROR; goto error; } if ((chan.attr.tracefile_size > 0) && (chan.attr.tracefile_size < chan.attr.subbuf_size)) { WARN("Tracefile size rounded up from (%" PRIu64 ") to subbuffer size (%" PRIu64 ")", chan.attr.tracefile_size, chan.attr.subbuf_size); chan.attr.tracefile_size = chan.attr.subbuf_size; } /* Setting channel output */ if (opt_output) { if (!strncmp(output_mmap, opt_output, strlen(output_mmap))) { chan.attr.output = LTTNG_EVENT_MMAP; } else if (!strncmp(output_splice, opt_output, strlen(output_splice))) { chan.attr.output = LTTNG_EVENT_SPLICE; } else { ERR("Unknown output type %s. Possible values are: %s, %s\n", opt_output, output_mmap, output_splice); usage(stderr); ret = CMD_ERROR; goto error; } } handle = lttng_create_handle(session_name, &dom); if (handle == NULL) { ret = -1; goto error; } /* Strip channel list (format: chan1,chan2,...) */ channel_name = strtok(opt_channels, ","); while (channel_name != NULL) { /* Copy channel name and normalize it */ strncpy(chan.name, channel_name, NAME_MAX); chan.name[NAME_MAX - 1] = '\0'; DBG("Enabling channel %s", channel_name); ret = lttng_enable_channel(handle, &chan); if (ret < 0) { switch (-ret) { case LTTNG_ERR_KERN_CHAN_EXIST: case LTTNG_ERR_UST_CHAN_EXIST: WARN("Channel %s: %s (session %s)", channel_name, lttng_strerror(ret), session_name); goto error; default: ERR("Channel %s: %s (session %s)", channel_name, lttng_strerror(ret), session_name); break; } warn = 1; } else { MSG("%s channel %s enabled for session %s", opt_kernel ? "Kernel" : "UST", channel_name, session_name); } /* Next event */ channel_name = strtok(NULL, ","); } ret = CMD_SUCCESS; error: if (warn) { ret = CMD_WARNING; } lttng_destroy_handle(handle); return ret; }
static int list_agent_events(void) { int i, size, ret = CMD_SUCCESS; struct lttng_domain domain; struct lttng_handle *handle = NULL; struct lttng_event *event_list = NULL; pid_t cur_pid = 0; char *cmdline = NULL; const char *agent_domain_str; memset(&domain, 0, sizeof(domain)); if (opt_jul) { domain.type = LTTNG_DOMAIN_JUL; } else if (opt_log4j) { domain.type = LTTNG_DOMAIN_LOG4J; } else if (opt_python) { domain.type = LTTNG_DOMAIN_PYTHON; } else { ERR("Invalid agent domain selected."); ret = CMD_ERROR; goto error; } agent_domain_str = get_domain_str(domain.type); DBG("Getting %s tracing events", agent_domain_str); handle = lttng_create_handle(NULL, &domain); if (handle == NULL) { ret = CMD_ERROR; goto end; } size = lttng_list_tracepoints(handle, &event_list); if (size < 0) { ERR("Unable to list %s events: %s", agent_domain_str, lttng_strerror(size)); ret = CMD_ERROR; goto end; } if (lttng_opt_mi) { /* Mi print */ ret = mi_list_agent_ust_events(event_list, size, &domain); if (ret) { ret = CMD_ERROR; goto error; } } else { /* Pretty print */ MSG("%s events (Logger name):\n-------------------------", agent_domain_str); if (size == 0) { MSG("None"); } for (i = 0; i < size; i++) { if (cur_pid != event_list[i].pid) { cur_pid = event_list[i].pid; cmdline = get_cmdline_by_pid(cur_pid); if (cmdline == NULL) { ret = CMD_ERROR; goto error; } MSG("\nPID: %d - Name: %s", cur_pid, cmdline); free(cmdline); } MSG("%s- %s", indent6, event_list[i].name); } MSG(""); } error: free(event_list); end: lttng_destroy_handle(handle); return ret; }