Fix: define _LGPL_SOURCE in C files
[lttng-tools.git] / src / bin / lttng / commands / enable_events.c
index 1f4e02470bb6a176a350aab16ecbffdced00b2b5..5ef349097c5622d6e8abc85521e4ae59e937bf95 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #define _GNU_SOURCE
+#define _LGPL_SOURCE
 #include <assert.h>
 #include <popt.h>
 #include <stdio.h>
@@ -46,6 +47,8 @@ static int opt_kernel;
 static char *opt_session_name;
 static int opt_userspace;
 static int opt_jul;
+static int opt_log4j;
+static int opt_python;
 static int opt_enable_all;
 static char *opt_probe;
 static char *opt_function;
@@ -86,6 +89,8 @@ static struct poptOption long_options[] = {
        {"kernel",         'k', POPT_ARG_VAL, &opt_kernel, 1, 0, 0},
        {"userspace",      'u', POPT_ARG_NONE, 0, OPT_USERSPACE, 0, 0},
        {"jul",            'j', POPT_ARG_VAL, &opt_jul, 1, 0, 0},
+       {"log4j",          'l', POPT_ARG_VAL, &opt_log4j, 1, 0, 0},
+       {"python",         'p', POPT_ARG_VAL, &opt_python, 1, 0, 0},
        {"tracepoint",     0,   POPT_ARG_NONE, 0, OPT_TRACEPOINT, 0, 0},
        {"probe",          0,   POPT_ARG_STRING, &opt_probe, OPT_PROBE, 0, 0},
        {"function",       0,   POPT_ARG_STRING, &opt_function, OPT_FUNCTION, 0, 0},
@@ -121,6 +126,8 @@ static void usage(FILE *ofp)
        fprintf(ofp, "  -k, --kernel             Apply for the kernel tracer\n");
        fprintf(ofp, "  -u, --userspace          Apply to the user-space tracer\n");
        fprintf(ofp, "  -j, --jul                Apply for Java application using JUL\n");
+       fprintf(ofp, "  -l, --log4j              Apply for Java application using LOG4j\n");
+       fprintf(ofp, "  -p, --python             Apply for Java application using LOG4j\n");
        fprintf(ofp, "\n");
        fprintf(ofp, "Event options:\n");
        fprintf(ofp, "    --tracepoint           Tracepoint event (default)\n");
@@ -145,7 +152,7 @@ static void usage(FILE *ofp)
        fprintf(ofp, "\n");
        fprintf(ofp, "    --loglevel name\n");
        fprintf(ofp, "                           Tracepoint loglevel range from 0 to loglevel.\n");
-       fprintf(ofp, "                           For JUL domain, see the table below for the range values.\n");
+       fprintf(ofp, "                           For JUL/LOG4j domain, see the table below for the range values.\n");
        fprintf(ofp, "    --loglevel-only name\n");
        fprintf(ofp, "                           Tracepoint loglevel (only this loglevel)\n");
        fprintf(ofp, "\n");
@@ -183,6 +190,26 @@ static void usage(FILE *ofp)
        fprintf(ofp, "                               JUL_ALL            = INT32_MIN\n");
        fprintf(ofp, "                               (shortcuts such as \"severe\" are allowed)\n");
        fprintf(ofp, "\n");
+       fprintf(ofp, "                           Available LOG4j domain loglevels:\n");
+       fprintf(ofp, "                               LOG4J_OFF            = INT32_MAX\n");
+       fprintf(ofp, "                               LOG4J_FATAL          = %d\n", LTTNG_LOGLEVEL_LOG4J_FATAL);
+       fprintf(ofp, "                               LOG4J_ERROR          = %d\n", LTTNG_LOGLEVEL_LOG4J_ERROR);
+       fprintf(ofp, "                               LOG4J_WARN           = %d\n", LTTNG_LOGLEVEL_LOG4J_WARN);
+       fprintf(ofp, "                               LOG4J_INFO           = %d\n", LTTNG_LOGLEVEL_LOG4J_INFO);
+       fprintf(ofp, "                               LOG4J_DEBUG          = %d\n", LTTNG_LOGLEVEL_LOG4J_DEBUG);
+       fprintf(ofp, "                               LOG4J_TRACE          = %d\n", LTTNG_LOGLEVEL_LOG4J_TRACE);
+       fprintf(ofp, "                               LOG4J_ALL            = INT32_MIN\n");
+       fprintf(ofp, "                               (shortcuts such as \"severe\" are allowed)\n");
+       fprintf(ofp, "\n");
+       fprintf(ofp, "                           Available Python domain loglevels:\n");
+       fprintf(ofp, "                               PYTHON_CRITICAL      = %d\n", LTTNG_LOGLEVEL_PYTHON_CRITICAL);
+       fprintf(ofp, "                               PYTHON_ERROR         = %d\n", LTTNG_LOGLEVEL_PYTHON_ERROR);
+       fprintf(ofp, "                               PYTHON_WARNING       = %d\n", LTTNG_LOGLEVEL_PYTHON_WARNING);
+       fprintf(ofp, "                               PYTHON_INFO          = %d\n", LTTNG_LOGLEVEL_PYTHON_INFO);
+       fprintf(ofp, "                               PYTHON_DEBUG         = %d\n", LTTNG_LOGLEVEL_PYTHON_DEBUG);
+       fprintf(ofp, "                               PYTHON_NOTSET        = %d\n", LTTNG_LOGLEVEL_PYTHON_NOTSET);
+       fprintf(ofp, "                               (shortcuts such as \"critical\" are allowed)\n");
+       fprintf(ofp, "\n");
        fprintf(ofp, "  -f, --filter \'expression\'\n");
        fprintf(ofp, "                           Filter expression on event fields and context.\n");
        fprintf(ofp, "                           Event recording depends on evaluation.\n");
@@ -233,26 +260,27 @@ static void usage(FILE *ofp)
  */
 static int parse_probe_opts(struct lttng_event *ev, char *opt)
 {
-       int ret;
+       int ret = CMD_SUCCESS;
+       int match;
        char s_hex[19];
 #define S_HEX_LEN_SCANF_IS_A_BROKEN_API "18"   /* 18 is (19 - 1) (\0 is extra) */
        char name[LTTNG_SYMBOL_NAME_LEN];
 
        if (opt == NULL) {
-               ret = -1;
+               ret = CMD_ERROR;
                goto end;
        }
 
        /* Check for symbol+offset */
-       ret = sscanf(opt, "%" LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API
+       match = sscanf(opt, "%" LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API
                        "[^'+']+%" S_HEX_LEN_SCANF_IS_A_BROKEN_API "s", name, s_hex);
-       if (ret == 2) {
+       if (match == 2) {
                strncpy(ev->attr.probe.symbol_name, name, LTTNG_SYMBOL_NAME_LEN);
                ev->attr.probe.symbol_name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
                DBG("probe symbol %s", ev->attr.probe.symbol_name);
                if (*s_hex == '\0') {
                        ERR("Invalid probe offset %s", s_hex);
-                       ret = -1;
+                       ret = CMD_ERROR;
                        goto end;
                }
                ev->attr.probe.offset = strtoul(s_hex, NULL, 0);
@@ -263,9 +291,9 @@ static int parse_probe_opts(struct lttng_event *ev, char *opt)
 
        /* Check for symbol */
        if (isalpha(name[0])) {
-               ret = sscanf(opt, "%" LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API "s",
+               match = sscanf(opt, "%" LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API "s",
                        name);
-               if (ret == 1) {
+               if (match == 1) {
                        strncpy(ev->attr.probe.symbol_name, name, LTTNG_SYMBOL_NAME_LEN);
                        ev->attr.probe.symbol_name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
                        DBG("probe symbol %s", ev->attr.probe.symbol_name);
@@ -277,11 +305,11 @@ static int parse_probe_opts(struct lttng_event *ev, char *opt)
        }
 
        /* Check for address */
-       ret = sscanf(opt, "%" S_HEX_LEN_SCANF_IS_A_BROKEN_API "s", s_hex);
-       if (ret > 0) {
+       match = sscanf(opt, "%" S_HEX_LEN_SCANF_IS_A_BROKEN_API "s", s_hex);
+       if (match > 0) {
                if (*s_hex == '\0') {
                        ERR("Invalid probe address %s", s_hex);
-                       ret = -1;
+                       ret = CMD_ERROR;
                        goto end;
                }
                ev->attr.probe.addr = strtoul(s_hex, NULL, 0);
@@ -292,12 +320,51 @@ static int parse_probe_opts(struct lttng_event *ev, char *opt)
        }
 
        /* No match */
-       ret = -1;
+       ret = CMD_ERROR;
 
 end:
        return ret;
 }
 
+/*
+ * Maps LOG4j loglevel from string to value
+ */
+static int loglevel_log4j_str_to_value(const char *inputstr)
+{
+       int i = 0;
+       char str[LTTNG_SYMBOL_NAME_LEN];
+
+       /*
+        * Loop up to LTTNG_SYMBOL_NAME_LEN minus one because the NULL bytes is
+        * added at the end of the loop so a the upper bound we avoid the overflow.
+        */
+       while (i < (LTTNG_SYMBOL_NAME_LEN - 1) && inputstr[i] != '\0') {
+               str[i] = toupper(inputstr[i]);
+               i++;
+       }
+       str[i] = '\0';
+
+       if (!strcmp(str, "LOG4J_OFF") || !strcmp(str, "OFF")) {
+               return LTTNG_LOGLEVEL_LOG4J_OFF;
+       } else if (!strcmp(str, "LOG4J_FATAL") || !strcmp(str, "FATAL")) {
+               return LTTNG_LOGLEVEL_LOG4J_FATAL;
+       } else if (!strcmp(str, "LOG4J_ERROR") || !strcmp(str, "ERROR")) {
+               return LTTNG_LOGLEVEL_LOG4J_ERROR;
+       } else if (!strcmp(str, "LOG4J_WARN") || !strcmp(str, "WARN")) {
+               return LTTNG_LOGLEVEL_LOG4J_WARN;
+       } else if (!strcmp(str, "LOG4J_INFO") || !strcmp(str, "INFO")) {
+               return LTTNG_LOGLEVEL_LOG4J_INFO;
+       } else if (!strcmp(str, "LOG4J_DEBUG") || !strcmp(str, "DEBUG")) {
+               return LTTNG_LOGLEVEL_LOG4J_DEBUG;
+       } else if (!strcmp(str, "LOG4J_TRACE") || !strcmp(str, "TRACE")) {
+               return LTTNG_LOGLEVEL_LOG4J_TRACE;
+       } else if (!strcmp(str, "LOG4J_ALL") || !strcmp(str, "ALL")) {
+               return LTTNG_LOGLEVEL_LOG4J_ALL;
+       } else {
+               return -1;
+       }
+}
+
 /*
  * Maps JUL loglevel from string to value
  */
@@ -339,6 +406,41 @@ static int loglevel_jul_str_to_value(const char *inputstr)
        }
 }
 
+/*
+ * Maps Python loglevel from string to value
+ */
+static int loglevel_python_str_to_value(const char *inputstr)
+{
+       int i = 0;
+       char str[LTTNG_SYMBOL_NAME_LEN];
+
+       /*
+        * Loop up to LTTNG_SYMBOL_NAME_LEN minus one because the NULL bytes is
+        * added at the end of the loop so a the upper bound we avoid the overflow.
+        */
+       while (i < (LTTNG_SYMBOL_NAME_LEN - 1) && inputstr[i] != '\0') {
+               str[i] = toupper(inputstr[i]);
+               i++;
+       }
+       str[i] = '\0';
+
+       if (!strcmp(str, "PYTHON_CRITICAL") || !strcmp(str, "CRITICAL")) {
+               return LTTNG_LOGLEVEL_PYTHON_CRITICAL;
+       } else if (!strcmp(str, "PYTHON_ERROR") || !strcmp(str, "ERROR")) {
+               return LTTNG_LOGLEVEL_PYTHON_ERROR;
+       } else if (!strcmp(str, "PYTHON_WARNING") || !strcmp(str, "WARNING")) {
+               return LTTNG_LOGLEVEL_PYTHON_WARNING;
+       } else if (!strcmp(str, "PYTHON_INFO") || !strcmp(str, "INFO")) {
+               return LTTNG_LOGLEVEL_PYTHON_INFO;
+       } else if (!strcmp(str, "PYTNON_DEBUG") || !strcmp(str, "DEBUG")) {
+               return LTTNG_LOGLEVEL_PYTHON_DEBUG;
+       } else if (!strcmp(str, "PYTHON_NOTSET") || !strcmp(str, "NOTSET")) {
+               return LTTNG_LOGLEVEL_PYTHON_NOTSET;
+       } else {
+               return -1;
+       }
+}
+
 /*
  * Maps loglevel from string to value
  */
@@ -600,6 +702,14 @@ static int enable_events(char *session_name)
                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;
@@ -642,11 +752,15 @@ static int enable_events(char *session_name)
                        strcpy(ev.name, "*");
                        ev.loglevel_type = opt_loglevel_type;
                        if (opt_loglevel) {
-                               assert(opt_userspace || opt_jul);
+                               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);
@@ -654,11 +768,13 @@ static int enable_events(char *session_name)
                                        goto error;
                                }
                        } else {
-                               assert(opt_userspace || opt_jul);
+                               assert(opt_userspace || opt_jul || opt_log4j || opt_python);
                                if (opt_userspace) {
                                        ev.loglevel = -1;
-                               } else if (opt_jul) {
+                               } else if (opt_jul || opt_log4j) {
                                        ev.loglevel = LTTNG_LOGLEVEL_JUL_ALL;
+                               } else if (opt_python) {
+                                       ev.loglevel = LTTNG_LOGLEVEL_PYTHON_DEBUG;
                                }
                        }
                }
@@ -683,6 +799,16 @@ static int enable_events(char *session_name)
                                                        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),
@@ -717,7 +843,8 @@ static int enable_events(char *session_name)
                                break;
                        case LTTNG_EVENT_SYSCALL:
                                if (opt_kernel) {
-                                       MSG("All kernel system calls are enabled in channel %s",
+                                       MSG("All %s system calls are enabled in channel %s",
+                                                       get_domain_str(dom.type),
                                                        print_channel_name(channel_name));
                                }
                                break;
@@ -759,10 +886,20 @@ static int enable_events(char *session_name)
                                                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(ret),
-                                                       ret == -LTTNG_ERR_NEED_CHANNEL_NAME
+                                                       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);
@@ -793,7 +930,7 @@ static int enable_events(char *session_name)
                                ev.enabled = 0;
                                success = 0;
                        }
-                       ret = mi_lttng_event(writer, &ev, 1);
+                       ret = mi_lttng_event(writer, &ev, 1, handle->domain.type);
                        if (ret) {
                                ret = CMD_ERROR;
                                goto error;
@@ -847,7 +984,7 @@ static int enable_events(char *session_name)
                                break;
                        case LTTNG_EVENT_PROBE:
                                ret = parse_probe_opts(&ev, opt_probe);
-                               if (ret < 0) {
+                               if (ret) {
                                        ERR("Unable to parse probe options");
                                        ret = 0;
                                        goto error;
@@ -855,7 +992,7 @@ static int enable_events(char *session_name)
                                break;
                        case LTTNG_EVENT_FUNCTION:
                                ret = parse_probe_opts(&ev, opt_function);
-                               if (ret < 0) {
+                               if (ret) {
                                        ERR("Unable to parse function probe options");
                                        ret = 0;
                                        goto error;
@@ -867,8 +1004,8 @@ static int enable_events(char *session_name)
                                ev.attr.ftrace.symbol_name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
                                break;
                        case LTTNG_EVENT_SYSCALL:
-                               MSG("per-syscall selection not supported yet. Use \"-a\" "
-                                               "for all syscalls.");
+                               ev.type = LTTNG_EVENT_SYSCALL;
+                               break;
                        default:
                                ret = CMD_UNDEFINED;
                                goto error;
@@ -941,24 +1078,36 @@ static int enable_events(char *session_name)
                        } else {
                                ev.loglevel = -1;
                        }
-               } else if (opt_jul) {
+               } 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 JUL domain.");
+                               ERR("Event type not supported for domain.");
                                ret = CMD_UNSUPPORTED;
                                goto error;
                        }
 
                        ev.loglevel_type = opt_loglevel_type;
                        if (opt_loglevel) {
-                               ev.loglevel = loglevel_jul_str_to_value(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 {
-                               ev.loglevel = LTTNG_LOGLEVEL_JUL_ALL;
+                               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);
@@ -986,11 +1135,22 @@ static int enable_events(char *session_name)
                                                        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(ret),
-                                                       ret == -LTTNG_ERR_NEED_CHANNEL_NAME
+                                                       lttng_strerror(command_ret),
+                                                       command_ret == -LTTNG_ERR_NEED_CHANNEL_NAME
                                                                ? print_raw_channel_name(channel_name)
                                                                : print_channel_name(channel_name),
                                                        session_name);
@@ -999,8 +1159,9 @@ static int enable_events(char *session_name)
                                }
                                error_holder = command_ret;
                        } else {
-                               /* So we don't print the default channel name for JUL. */
-                               if (dom.type == LTTNG_DOMAIN_JUL) {
+                               /* 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);
@@ -1034,11 +1195,22 @@ static int enable_events(char *session_name)
                                                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(ret),
-                                                       ret == -LTTNG_ERR_NEED_CHANNEL_NAME
+                                                       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);
@@ -1063,7 +1235,7 @@ static int enable_events(char *session_name)
                                ev.enabled = 1;
                        }
 
-                       ret = mi_lttng_event(writer, &ev, 1);
+                       ret = mi_lttng_event(writer, &ev, 1, handle->domain.type);
                        if (ret) {
                                ret = CMD_ERROR;
                                goto error;
This page took 0.031781 seconds and 5 git commands to generate.