Add a Log4j 2.x agent specific domain 'log4j2'
authorMichael Jeanson <mjeanson@efficios.com>
Wed, 2 Feb 2022 20:04:09 +0000 (20:04 +0000)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Fri, 30 Aug 2024 20:38:49 +0000 (16:38 -0400)
The initial version of the new LTTng-UST Log4j 2.x agent only operated
in a compatibility mode making use of the existing 'log4j' tracing
domain currently implemented in LTTng-Tools.

While this is useful when migrating existing Log4j applications using
the compatibility bridge it does require converting the log levels from
the new Log4j 2.x values to the old Log4j 1.x standard. This results in
hiding the actual log level values from the users for applications
natively using Log4j 2.x.

Exposing the native Log4j 2.x log level values requires a new domain
since the changes are significant:

  * The same list of standard log levels and names
  * Each standard log level has a new integer value
  * The log levels scale is reversed and shortened from
    'int32_max -> int32_min' to '0 -> int32_max'
  * The interval between standard log levels has changed

This new 'log4j2' domain is basicaly a straight copy of the current
'log4j' domain with minor adjustements for the reversed and shortened
scale.

Change-Id: I89f9c0a428ffe1d0bd26f7af547e9e21503de653
Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
45 files changed:
include/Makefile.am
include/lttng/domain.h
include/lttng/event-rule/event-rule.h
include/lttng/event-rule/jul-logging-internal.hpp
include/lttng/event-rule/log4j-logging-internal.hpp
include/lttng/event-rule/log4j2-logging-internal.hpp [new file with mode: 0644]
include/lttng/event-rule/log4j2-logging.h [new file with mode: 0644]
include/lttng/event.h
include/lttng/lttng.h
src/bin/lttng-sessiond/agent-thread.cpp
src/bin/lttng-sessiond/agent.cpp
src/bin/lttng-sessiond/channel.cpp
src/bin/lttng-sessiond/client.cpp
src/bin/lttng-sessiond/cmd.cpp
src/bin/lttng-sessiond/context.cpp
src/bin/lttng-sessiond/event-notifier-error-accounting.cpp
src/bin/lttng-sessiond/event.cpp
src/bin/lttng-sessiond/save.cpp
src/bin/lttng-sessiond/trace-ust.hpp
src/bin/lttng-sessiond/ust-app.cpp
src/bin/lttng/commands/add_context.cpp
src/bin/lttng/commands/add_trigger.cpp
src/bin/lttng/commands/disable_events.cpp
src/bin/lttng/commands/enable_events.cpp
src/bin/lttng/commands/list.cpp
src/bin/lttng/commands/list_triggers.cpp
src/bin/lttng/loglevel.cpp
src/bin/lttng/loglevel.hpp
src/bin/lttng/utils.cpp
src/common/Makefile.am
src/common/conditions/event-rule-matches.cpp
src/common/config/config-session-abi.hpp
src/common/config/session-config.cpp
src/common/defaults.hpp
src/common/domain.cpp
src/common/event-rule/event-rule.cpp
src/common/event-rule/jul-logging.cpp
src/common/event-rule/log4j-logging.cpp
src/common/event-rule/log4j2-logging.cpp [new file with mode: 0644]
src/common/mi-lttng-4.1.xsd
src/common/mi-lttng.cpp
src/common/mi-lttng.hpp
src/common/session.xsd
src/lib/lttng-ctl/liblttng-ctl.sym
src/lib/lttng-ctl/lttng-ctl.cpp

index a2d6a5cf015eea6c9b3b907b4ca917d00b541814..0ce426826ae0807832d02e60a7cf1b872796f1f7 100644 (file)
@@ -160,6 +160,7 @@ lttngeventruleinclude_HEADERS= \
        lttng/event-rule/kernel-tracepoint.h \
        lttng/event-rule/kernel-uprobe.h \
        lttng/event-rule/log4j-logging.h \
+       lttng/event-rule/log4j2-logging.h \
        lttng/event-rule/python-logging.h \
        lttng/event-rule/user-tracepoint.h
 
@@ -193,6 +194,7 @@ noinst_HEADERS = \
        lttng/event-rule/kernel-tracepoint-internal.hpp \
        lttng/event-rule/kernel-uprobe-internal.hpp \
        lttng/event-rule/log4j-logging-internal.hpp \
+       lttng/event-rule/log4j2-logging-internal.hpp \
        lttng/event-rule/python-logging-internal.hpp \
        lttng/event-rule/user-tracepoint-internal.hpp \
        lttng/health-internal.hpp \
index da19ebf1c4d37f4fac8a2c0d8fab5adc90bed5d4..0c0335e2e2c06c2ca592ab19470845e6e5444a68 100644 (file)
@@ -37,11 +37,14 @@ enum lttng_domain_type {
        /// <code>java.util.logging</code> (JUL).
        LTTNG_DOMAIN_JUL = 3,
 
-       /// Apache log4j.
+       /// Apache Log4j 1.x.
        LTTNG_DOMAIN_LOG4J = 4,
 
        /// Python logging.
        LTTNG_DOMAIN_PYTHON = 5,
+
+       /// Apache Log4j 2.
+       LTTNG_DOMAIN_LOG4J2 = 6,
 };
 
 /*!
index a75db771e9e2155e20ef7de2f2fd7609256e998b..78a34ab16a5d76491a682872f72a13a66fc13dec 100644 (file)
@@ -26,6 +26,7 @@ enum lttng_event_rule_type {
        LTTNG_EVENT_RULE_TYPE_JUL_LOGGING = 5,
        LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING = 6,
        LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING = 7,
+       LTTNG_EVENT_RULE_TYPE_LOG4J2_LOGGING = 8,
 };
 
 enum lttng_event_rule_status {
index c84ab7a7f86e39281577e526d4f4a5c319014e32..b6ddc36449366e52229816cf37dcf331d12a18c7 100644 (file)
@@ -17,6 +17,8 @@
 #include <lttng/event.h>
 #include <lttng/log-level-rule-internal.hpp>
 
+#define LTTNG_JUL_EVENT_RULE_AT_LEAST_AS_SEVERE_AS_OP ">="
+
 struct lttng_event_rule_jul_logging {
        struct lttng_event_rule parent;
 
index 239bf98ee41e0769d0c481e572e11f33760c0974..31b2e9e2e29cdba0570d32277c1d32d39a199047 100644 (file)
@@ -17,6 +17,8 @@
 #include <lttng/event.h>
 #include <lttng/log-level-rule-internal.hpp>
 
+#define LTTNG_LOG4J_EVENT_RULE_AT_LEAST_AS_SEVERE_AS_OP ">="
+
 struct lttng_event_rule_log4j_logging {
        struct lttng_event_rule parent;
 
diff --git a/include/lttng/event-rule/log4j2-logging-internal.hpp b/include/lttng/event-rule/log4j2-logging-internal.hpp
new file mode 100644 (file)
index 0000000..5358ed3
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 Michael Jeanson <mjeanson@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_EVENT_RULE_LOG4J2_LOGGING_INTERNAL_H
+#define LTTNG_EVENT_RULE_LOG4J2_LOGGING_INTERNAL_H
+
+#include <common/macros.hpp>
+#include <common/optional.hpp>
+#include <common/payload-view.hpp>
+
+#include <lttng/event-rule/event-rule-internal.hpp>
+#include <lttng/event-rule/log4j2-logging.h>
+#include <lttng/event.h>
+#include <lttng/log-level-rule-internal.hpp>
+
+#define LTTNG_LOG4J2_EVENT_RULE_AT_LEAST_AS_SEVERE_AS_OP "<="
+
+struct lttng_event_rule_log4j2_logging {
+       struct lttng_event_rule parent;
+
+       /* Name pattern. */
+       char *pattern;
+
+       /* Filter. */
+       char *filter_expression;
+
+       /* Log level. */
+       struct lttng_log_level_rule *log_level_rule;
+
+       /* internal use only. */
+       struct {
+               char *filter;
+               struct lttng_bytecode *bytecode;
+       } internal_filter;
+};
+
+struct lttng_event_rule_log4j2_logging_comm {
+       /* Includes terminator `\0`. */
+       uint32_t pattern_len;
+       /* Includes terminator `\0`. */
+       uint32_t filter_expression_len;
+       /*  enum lttng_log_level_rule_comm + payload if any */
+       uint32_t log_level_rule_len;
+       /*
+        * Payload is composed of, in that order:
+        *   - pattern (null terminated),
+        *   - filter expression (null terminated),
+        *   - log level rule serialized object,
+        */
+       char payload[];
+} LTTNG_PACKED;
+
+ssize_t lttng_event_rule_log4j2_logging_create_from_payload(struct lttng_payload_view *view,
+                                                           struct lttng_event_rule **rule);
+
+#endif /* LTTNG_EVENT_RULE_LOG4J2_LOGGING_INTERNAL_H */
diff --git a/include/lttng/event-rule/log4j2-logging.h b/include/lttng/event-rule/log4j2-logging.h
new file mode 100644 (file)
index 0000000..fc942c7
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2024 Michael Jeanson <mjeanson@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_EVENT_RULE_LOG4J2_LOGGING_H
+#define LTTNG_EVENT_RULE_LOG4J2_LOGGING_H
+
+#include <lttng/event-rule/event-rule.h>
+#include <lttng/event.h>
+#include <lttng/log-level-rule.h>
+#include <lttng/lttng-export.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Create a newly allocated log4j2 logging event rule.
+ *
+ * The default name pattern is '*'.
+ *
+ * Returns a new event rule on success, NULL on failure. This event rule must be
+ * destroyed using lttng_event_rule_destroy().
+ */
+LTTNG_EXPORT extern struct lttng_event_rule *lttng_event_rule_log4j2_logging_create(void);
+
+/*
+ * Set the name pattern of a log4j2 logging event rule.
+ *
+ * Pattern can contain wildcard '*'. See man lttng-enable-event.
+ *
+ * Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
+ * if invalid parameters are passed.
+ */
+LTTNG_EXPORT extern enum lttng_event_rule_status
+lttng_event_rule_log4j2_logging_set_name_pattern(struct lttng_event_rule *rule,
+                                                const char *pattern);
+
+/*
+ * Get the name pattern of a log4j2 logging event rule.
+ *
+ * The caller does not assume the ownership of the returned pattern. The
+ * pattern shall only only be used for the duration of the event rule's
+ * lifetime, or before a different pattern is set.
+ *
+ * Returns LTTNG_EVENT_RULE_STATUS_OK and a pointer to the event rule's pattern
+ * on success, LTTNG_EVENT_RULE_STATUS_INVALID if an invalid
+ * parameter is passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a pattern
+ * was not set prior to this call.
+ */
+LTTNG_EXPORT extern enum lttng_event_rule_status
+lttng_event_rule_log4j2_logging_get_name_pattern(const struct lttng_event_rule *rule,
+                                                const char **pattern);
+
+/*
+ * Set the filter expression of a log4j2 logging event rule.
+ *
+ * The expression is copied internally.
+ *
+ * Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
+ * if invalid parameters are passed.
+ */
+LTTNG_EXPORT extern enum lttng_event_rule_status
+lttng_event_rule_log4j2_logging_set_filter(struct lttng_event_rule *rule, const char *expression);
+
+/*
+ * Get the filter expression of a log4j2 logging event rule.
+ *
+ * The caller does not assume the ownership of the returned filter expression.
+ * The filter expression shall only only be used for the duration of the event
+ * rule's lifetime, or before a different filter expression is set.
+ *
+ * Returns LTTNG_EVENT_RULE_STATUS_OK and a pointer to the event rule's filter
+ * expression on success, LTTNG_EVENT_RULE_STATUS_INVALID if an invalid
+ * parameter is passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a filter expression
+ * was not set prior to this call.
+ */
+LTTNG_EXPORT extern enum lttng_event_rule_status
+lttng_event_rule_log4j2_logging_get_filter(const struct lttng_event_rule *rule,
+                                          const char **expression);
+
+/*
+ * Set the log level rule of a log4j2 logging event rule.
+ *
+ * The log level rule is copied internally.
+ *
+ * Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
+ * if invalid parameters are passed.
+ */
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_log4j2_logging_set_log_level_rule(
+       struct lttng_event_rule *rule, const struct lttng_log_level_rule *log_level_rule);
+
+/*
+ * Get the log level rule of a log4j2 logging event rule.
+ *
+ * The caller does not assume the ownership of the returned log level rule. The
+ * log level rule shall only only be used for the duration of the event rule's
+ * lifetime, or before a different log level rule is set.
+ *
+ * Returns LTTNG_EVENT_RULE_STATUS_OK and sets the log level rule output
+ * parameter on success, LTTNG_EVENT_RULE_STATUS_INVALID if an invalid parameter
+ * is passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a log level rule was not set prior
+ * to this call.
+ */
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_log4j2_logging_get_log_level_rule(
+       const struct lttng_event_rule *rule, const struct lttng_log_level_rule **log_level_rule);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LTTNG_EVENT_RULE_LOG4J2_LOGGING_H */
index 64bd2ad23f32ca4c6f8cfa8c605ca0f2d7931e90..397ac6344109ef8479f60315c29bae3404f44746 100644 (file)
@@ -202,7 +202,7 @@ enum lttng_loglevel_jul {
     Value of the
     \ref api-rer-conds-ll "instrumentation point log level condition"
     of an
-    \link #LTTNG_DOMAIN_LOG4J Apache log4j\endlink
+    \link #LTTNG_DOMAIN_LOG4J Apache Log4j 1.x\endlink
     recording event rule.
 
 @ingroup api_rer
@@ -251,6 +251,60 @@ enum lttng_loglevel_log4j {
        LTTNG_LOGLEVEL_LOG4J_ALL = INT32_MIN,
 };
 
+/*!
+@brief
+    Value of the
+    \ref api-rer-conds-ll "instrumentation point log level condition"
+    of a
+    \link #LTTNG_DOMAIN_LOG4J2 Apache Log4j 2\endlink
+    recording event rule.
+
+@ingroup api_rer
+
+@sa #lttng_loglevel_type --
+    Operand of the log level condition of a recording event rule.
+*/
+enum lttng_loglevel_log4j2 {
+       /// Logging turned off.
+       LTTNG_LOGLEVEL_LOG4J2_OFF = 0,
+
+       /*!
+       Very severe error events that will presumably lead the
+       application to abort.
+       */
+       LTTNG_LOGLEVEL_LOG4J2_FATAL = 100,
+
+       /*!
+       Error events that might still allow the application to continue
+       running.
+       */
+       LTTNG_LOGLEVEL_LOG4J2_ERROR = 200,
+
+       /// Potentially harmful situations.
+       LTTNG_LOGLEVEL_LOG4J2_WARN = 300,
+
+       /*!
+       Informational messages that highlight the progress of the
+       application at coarse-grained level.
+       */
+       LTTNG_LOGLEVEL_LOG4J2_INFO = 400,
+
+       /*!
+       Fine-grained informational events that are most useful to debug
+       an application.
+       */
+       LTTNG_LOGLEVEL_LOG4J2_DEBUG = 500,
+
+       /*!
+       Finer-grained informational events than the
+       #LTTNG_LOGLEVEL_LOG4J2_DEBUG level.
+       */
+       LTTNG_LOGLEVEL_LOG4J2_TRACE = 600,
+
+       /// All levels, including custom levels.
+       LTTNG_LOGLEVEL_LOG4J2_ALL = INT32_MAX,
+};
+
 /*!
 @brief
     Value of the
index 6ae331bdaac7fd084b09d0053e3d6eb410549644..7c63e6335ae41df24e6ab6e5557245361b451b1b 100644 (file)
@@ -50,6 +50,7 @@
 #include <lttng/event-rule/kernel-tracepoint.h>
 #include <lttng/event-rule/kernel-uprobe.h>
 #include <lttng/event-rule/log4j-logging.h>
+#include <lttng/event-rule/log4j2-logging.h>
 #include <lttng/event-rule/python-logging.h>
 #include <lttng/event-rule/user-tracepoint.h>
 #include <lttng/event.h>
index 82c74b10a76e6028728174d33c5711a8dc209f88..9b5a5b569f5bc75245f0093b32e3cb2bb9ae2dcb 100644 (file)
@@ -216,6 +216,8 @@ static const char *domain_type_str(enum lttng_domain_type domain_type)
                return "jul";
        case LTTNG_DOMAIN_LOG4J:
                return "log4j";
+       case LTTNG_DOMAIN_LOG4J2:
+               return "log4j2";
        case LTTNG_DOMAIN_PYTHON:
                return "python";
        default:
index 4be1c32fcbed7a7d32344ced3f306eee8686cfaa..2beb7e9aa7a0b1e3634d08c861eb4a6c2f3a8936 100644 (file)
@@ -24,6 +24,7 @@
 #include <lttng/event-rule/event-rule.h>
 #include <lttng/event-rule/jul-logging.h>
 #include <lttng/event-rule/log4j-logging.h>
+#include <lttng/event-rule/log4j2-logging.h>
 #include <lttng/event-rule/python-logging.h>
 #include <lttng/log-level-rule-internal.hpp>
 
@@ -1257,6 +1258,10 @@ struct agent_event *agent_find_event_by_trigger(const struct lttng_trigger *trig
                logging_get_name_pattern = lttng_event_rule_log4j_logging_get_name_pattern;
                logging_get_log_level_rule = lttng_event_rule_log4j_logging_get_log_level_rule;
                break;
+       case LTTNG_EVENT_RULE_TYPE_LOG4J2_LOGGING:
+               logging_get_name_pattern = lttng_event_rule_log4j2_logging_get_name_pattern;
+               logging_get_log_level_rule = lttng_event_rule_log4j2_logging_get_log_level_rule;
+               break;
        case LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING:
                logging_get_name_pattern = lttng_event_rule_python_logging_get_name_pattern;
                logging_get_log_level_rule = lttng_event_rule_python_logging_get_log_level_rule;
@@ -1268,7 +1273,7 @@ struct agent_event *agent_find_event_by_trigger(const struct lttng_trigger *trig
 
        domain = lttng_event_rule_get_domain_type(rule);
        LTTNG_ASSERT(domain == LTTNG_DOMAIN_JUL || domain == LTTNG_DOMAIN_LOG4J ||
-                    domain == LTTNG_DOMAIN_PYTHON);
+                    domain == LTTNG_DOMAIN_LOG4J2 || domain == LTTNG_DOMAIN_PYTHON);
 
        /* Get the event's pattern name ('name' in the legacy terminology). */
        er_status = logging_get_name_pattern(rule, &name);
index 77c073e2c5a774d6c06c70a7f078751ea546cfaa..5bc446701916c73cf4cfb2b3bfbaf83d7cd3f8ad 100644 (file)
@@ -70,6 +70,9 @@ struct lttng_channel *channel_new_default_attr(int dom, enum lttng_buffer_type t
        case LTTNG_DOMAIN_LOG4J:
                channel_name = DEFAULT_LOG4J_CHANNEL_NAME;
                goto common_ust;
+       case LTTNG_DOMAIN_LOG4J2:
+               channel_name = DEFAULT_LOG4J2_CHANNEL_NAME;
+               goto common_ust;
        case LTTNG_DOMAIN_PYTHON:
                channel_name = DEFAULT_PYTHON_CHANNEL_NAME;
                goto common_ust;
@@ -346,6 +349,8 @@ enum lttng_error_code channel_ust_create(struct ltt_ust_session *usess,
                        domain = LTTNG_DOMAIN_JUL;
                } else if (!strcmp(attr->name, DEFAULT_LOG4J_CHANNEL_NAME)) {
                        domain = LTTNG_DOMAIN_LOG4J;
+               } else if (!strcmp(attr->name, DEFAULT_LOG4J2_CHANNEL_NAME)) {
+                       domain = LTTNG_DOMAIN_LOG4J2;
                } else if (!strcmp(attr->name, DEFAULT_PYTHON_CHANNEL_NAME)) {
                        domain = LTTNG_DOMAIN_PYTHON;
                }
index db9442b8e4bb1d3663acfc5a080f0e7b8abfbea8..310b79f8b381dfb8884519049a187ef41dabd697 100644 (file)
@@ -448,6 +448,7 @@ static int copy_session_consumer(int domain, const ltt_session::locked_ref& sess
                break;
        case LTTNG_DOMAIN_JUL:
        case LTTNG_DOMAIN_LOG4J:
+       case LTTNG_DOMAIN_LOG4J2:
        case LTTNG_DOMAIN_PYTHON:
        case LTTNG_DOMAIN_UST:
                DBG3("Copying tracing session consumer output in UST session");
@@ -492,6 +493,7 @@ static int create_ust_session(const ltt_session::locked_ref& session,
        switch (domain->type) {
        case LTTNG_DOMAIN_JUL:
        case LTTNG_DOMAIN_LOG4J:
+       case LTTNG_DOMAIN_LOG4J2:
        case LTTNG_DOMAIN_PYTHON:
        case LTTNG_DOMAIN_UST:
                break;
@@ -1180,6 +1182,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int *sock, int *sock_
                        break;
                case LTTNG_DOMAIN_JUL:
                case LTTNG_DOMAIN_LOG4J:
+               case LTTNG_DOMAIN_LOG4J2:
                case LTTNG_DOMAIN_PYTHON:
                case LTTNG_DOMAIN_UST:
                        if (!(*target_session)->ust_session) {
@@ -1263,6 +1266,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int *sock, int *sock_
                break;
        case LTTNG_DOMAIN_JUL:
        case LTTNG_DOMAIN_LOG4J:
+       case LTTNG_DOMAIN_LOG4J2:
        case LTTNG_DOMAIN_PYTHON:
                if (!agent_tracing_is_enabled()) {
                        ret = LTTNG_ERR_AGENT_TRACING_DISABLED;
@@ -1368,6 +1372,7 @@ skip_domain:
                        break;
                case LTTNG_DOMAIN_JUL:
                case LTTNG_DOMAIN_LOG4J:
+               case LTTNG_DOMAIN_LOG4J2:
                case LTTNG_DOMAIN_PYTHON:
                case LTTNG_DOMAIN_UST:
                        if (uatomic_read(&the_ust_consumerd_state) != CONSUMER_STARTED) {
index e2f10d2a3e624a19144d2d73071328bc14199b99..f1b29da9ccdd9c9f937209df70061bbcb76607e0 100644 (file)
@@ -1384,6 +1384,7 @@ static enum lttng_error_code cmd_enable_channel_internal(ltt_session::locked_ref
                break;
        case LTTNG_DOMAIN_JUL:
        case LTTNG_DOMAIN_LOG4J:
+       case LTTNG_DOMAIN_LOG4J2:
        case LTTNG_DOMAIN_PYTHON:
                if (!agent_tracing_is_enabled()) {
                        DBG("Attempted to enable a channel in an agent domain but the agent thread is not running");
@@ -1434,6 +1435,7 @@ static enum lttng_error_code cmd_enable_channel_internal(ltt_session::locked_ref
        case LTTNG_DOMAIN_UST:
        case LTTNG_DOMAIN_JUL:
        case LTTNG_DOMAIN_LOG4J:
+       case LTTNG_DOMAIN_LOG4J2:
        case LTTNG_DOMAIN_PYTHON:
        {
                struct ltt_ust_channel *uchan;
@@ -1460,6 +1462,13 @@ static enum lttng_error_code cmd_enable_channel_internal(ltt_session::locked_ref
                                ret_code = LTTNG_ERR_INVALID_CHANNEL_NAME;
                                goto error;
                        }
+               } else if (domain->type == LTTNG_DOMAIN_LOG4J2) {
+                       if (strncmp(attr->name,
+                                   DEFAULT_LOG4J2_CHANNEL_NAME,
+                                   LTTNG_SYMBOL_NAME_LEN - 1) != 0) {
+                               ret_code = LTTNG_ERR_INVALID_CHANNEL_NAME;
+                               goto error;
+                       }
                } else if (domain->type == LTTNG_DOMAIN_PYTHON) {
                        if (strncmp(attr->name,
                                    DEFAULT_PYTHON_CHANNEL_NAME,
@@ -1848,6 +1857,7 @@ int cmd_disable_event(struct command_ctx *cmd_ctx,
                break;
        }
        case LTTNG_DOMAIN_LOG4J:
+       case LTTNG_DOMAIN_LOG4J2:
        case LTTNG_DOMAIN_JUL:
        case LTTNG_DOMAIN_PYTHON:
        {
@@ -1942,6 +1952,7 @@ int cmd_add_context(struct command_ctx *cmd_ctx,
                break;
        case LTTNG_DOMAIN_JUL:
        case LTTNG_DOMAIN_LOG4J:
+       case LTTNG_DOMAIN_LOG4J2:
        {
                /*
                 * Validate channel name.
@@ -1958,6 +1969,10 @@ int cmd_add_context(struct command_ctx *cmd_ctx,
                           strcmp(channel_name, DEFAULT_LOG4J_CHANNEL_NAME) != 0) {
                        ret = LTTNG_ERR_UST_CHAN_NOT_FOUND;
                        goto error;
+               } else if (domain == LTTNG_DOMAIN_LOG4J2 && *channel_name &&
+                          strcmp(channel_name, DEFAULT_LOG4J2_CHANNEL_NAME) != 0) {
+                       ret = LTTNG_ERR_UST_CHAN_NOT_FOUND;
+                       goto error;
                }
        }
        /* fall through */
@@ -2046,6 +2061,7 @@ static int validate_ust_event_name(const char *name)
         */
        if (name_starts_with(name, DEFAULT_JUL_EVENT_COMPONENT) ||
            name_starts_with(name, DEFAULT_LOG4J_EVENT_COMPONENT) ||
+           name_starts_with(name, DEFAULT_LOG4J2_EVENT_COMPONENT) ||
            name_starts_with(name, DEFAULT_PYTHON_EVENT_COMPONENT)) {
                ret = -1;
        }
@@ -2304,6 +2320,7 @@ static int _cmd_enable_event(ltt_session::locked_ref& locked_session,
                break;
        }
        case LTTNG_DOMAIN_LOG4J:
+       case LTTNG_DOMAIN_LOG4J2:
        case LTTNG_DOMAIN_JUL:
        case LTTNG_DOMAIN_PYTHON:
        {
@@ -2356,6 +2373,9 @@ static int _cmd_enable_event(ltt_session::locked_ref& locked_session,
                case LTTNG_DOMAIN_LOG4J:
                        default_chan_name = DEFAULT_LOG4J_CHANNEL_NAME;
                        break;
+               case LTTNG_DOMAIN_LOG4J2:
+                       default_chan_name = DEFAULT_LOG4J2_CHANNEL_NAME;
+                       break;
                case LTTNG_DOMAIN_JUL:
                        default_chan_name = DEFAULT_JUL_CHANNEL_NAME;
                        break;
@@ -2547,6 +2567,7 @@ enum lttng_error_code cmd_list_tracepoints(enum lttng_domain_type domain,
                }
                break;
        case LTTNG_DOMAIN_LOG4J:
+       case LTTNG_DOMAIN_LOG4J2:
        case LTTNG_DOMAIN_JUL:
        case LTTNG_DOMAIN_PYTHON:
                nb_events = agent_list_events(&events, domain);
@@ -3907,6 +3928,7 @@ enum lttng_error_code cmd_list_events(enum lttng_domain_type domain,
                break;
        }
        case LTTNG_DOMAIN_LOG4J:
+       case LTTNG_DOMAIN_LOG4J2:
        case LTTNG_DOMAIN_JUL:
        case LTTNG_DOMAIN_PYTHON:
                if (session->ust_session) {
@@ -4475,6 +4497,7 @@ synchronize_tracer_notifier_register(struct notification_thread_handle *notifica
                break;
        case LTTNG_DOMAIN_JUL:
        case LTTNG_DOMAIN_LOG4J:
+       case LTTNG_DOMAIN_LOG4J2:
        case LTTNG_DOMAIN_PYTHON:
        {
                /* Agent domains. */
@@ -4630,6 +4653,7 @@ synchronize_tracer_notifier_unregister(const struct lttng_trigger *trigger)
                break;
        case LTTNG_DOMAIN_JUL:
        case LTTNG_DOMAIN_LOG4J:
+       case LTTNG_DOMAIN_LOG4J2:
        case LTTNG_DOMAIN_PYTHON:
        {
                /* Agent domains. */
index 153465c66a543d94a9883fba45453647dd297f2a..9a098841cb3aaa2e1ccf98fc69a55b87cc067d2b 100644 (file)
@@ -119,6 +119,7 @@ static int add_uctx_to_channel(struct ltt_ust_session *usess,
        switch (domain) {
        case LTTNG_DOMAIN_JUL:
        case LTTNG_DOMAIN_LOG4J:
+       case LTTNG_DOMAIN_LOG4J2:
        {
                struct agent *agt;
 
index 447585f7d563281611049a5786ec15c379fbc751..512440c3bfa11fb435581ee85ced995d9055ec55 100644 (file)
@@ -1073,6 +1073,7 @@ event_notifier_error_accounting_register_event_notifier(const struct lttng_trigg
        case LTTNG_DOMAIN_PYTHON:
        case LTTNG_DOMAIN_JUL:
        case LTTNG_DOMAIN_LOG4J:
+       case LTTNG_DOMAIN_LOG4J2:
                state = &ust_state;
                break;
        default:
@@ -1123,6 +1124,7 @@ event_notifier_error_accounting_register_event_notifier(const struct lttng_trigg
        case LTTNG_DOMAIN_PYTHON:
        case LTTNG_DOMAIN_JUL:
        case LTTNG_DOMAIN_LOG4J:
+       case LTTNG_DOMAIN_LOG4J2:
                pthread_mutex_lock(&the_event_notifier_counter.lock);
                the_event_notifier_counter.count++;
                if (the_event_notifier_counter.count == 1) {
@@ -1211,6 +1213,7 @@ event_notifier_error_accounting_get_count(const struct lttng_trigger *trigger, u
        case LTTNG_DOMAIN_PYTHON:
        case LTTNG_DOMAIN_JUL:
        case LTTNG_DOMAIN_LOG4J:
+       case LTTNG_DOMAIN_LOG4J2:
 #ifdef HAVE_LIBLTTNG_UST_CTL
                return event_notifier_error_accounting_ust_get_count(trigger, count);
 #else
@@ -1232,6 +1235,7 @@ event_notifier_error_accounting_clear(const struct lttng_trigger *trigger)
        case LTTNG_DOMAIN_PYTHON:
        case LTTNG_DOMAIN_JUL:
        case LTTNG_DOMAIN_LOG4J:
+       case LTTNG_DOMAIN_LOG4J2:
 #ifdef HAVE_LIBLTTNG_UST_CTL
                return event_notifier_error_accounting_ust_clear(trigger);
 #else
@@ -1276,6 +1280,7 @@ void event_notifier_error_accounting_unregister_event_notifier(const struct lttn
        case LTTNG_DOMAIN_PYTHON:
        case LTTNG_DOMAIN_JUL:
        case LTTNG_DOMAIN_LOG4J:
+       case LTTNG_DOMAIN_LOG4J2:
                state = &ust_state;
 
                pthread_mutex_lock(&the_event_notifier_counter.lock);
index 6d4dd6c26f40317129ea606b97c81ca286c124dd..0371b27b543a80a3e84cb4dbdacd3e2d7db91c9f 100644 (file)
@@ -598,6 +598,7 @@ int trigger_agent_enable(const struct lttng_trigger *trigger, struct agent *agt)
        switch (lttng_event_rule_get_type(rule)) {
        case LTTNG_EVENT_RULE_TYPE_JUL_LOGGING:
        case LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING:
+       case LTTNG_EVENT_RULE_TYPE_LOG4J2_LOGGING:
        case LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING:
                break;
        default:
@@ -663,6 +664,9 @@ const char *event_get_default_agent_ust_name(enum lttng_domain_type domain)
        case LTTNG_DOMAIN_LOG4J:
                default_event_name = DEFAULT_LOG4J_EVENT_NAME;
                break;
+       case LTTNG_DOMAIN_LOG4J2:
+               default_event_name = DEFAULT_LOG4J2_EVENT_NAME;
+               break;
        case LTTNG_DOMAIN_JUL:
                default_event_name = DEFAULT_JUL_EVENT_NAME;
                break;
@@ -749,6 +753,8 @@ static int event_agent_disable_one(struct ltt_ust_session *usess,
                ust_channel_name = DEFAULT_JUL_CHANNEL_NAME;
        } else if (agt->domain == LTTNG_DOMAIN_LOG4J) {
                ust_channel_name = DEFAULT_LOG4J_CHANNEL_NAME;
+       } else if (agt->domain == LTTNG_DOMAIN_LOG4J2) {
+               ust_channel_name = DEFAULT_LOG4J2_CHANNEL_NAME;
        } else if (agt->domain == LTTNG_DOMAIN_PYTHON) {
                ust_channel_name = DEFAULT_PYTHON_CHANNEL_NAME;
        } else {
index 715325a4a25ace439c0e698dc5a599f8173ed29e..6c6339c36fbf51fecb9b22a10b54a2f4b6b54ac2 100644 (file)
@@ -1725,6 +1725,9 @@ static const char *get_config_domain_str(enum lttng_domain_type domain)
        case LTTNG_DOMAIN_LOG4J:
                str_dom = config_domain_type_log4j;
                break;
+       case LTTNG_DOMAIN_LOG4J2:
+               str_dom = config_domain_type_log4j2;
+               break;
        case LTTNG_DOMAIN_PYTHON:
                str_dom = config_domain_type_python;
                break;
@@ -1798,6 +1801,7 @@ static int save_process_attr_tracker(struct config_writer *writer,
        }
        case LTTNG_DOMAIN_JUL:
        case LTTNG_DOMAIN_LOG4J:
+       case LTTNG_DOMAIN_LOG4J2:
        case LTTNG_DOMAIN_PYTHON:
        default:
                ret = LTTNG_ERR_UNSUPPORTED_DOMAIN;
@@ -2148,6 +2152,11 @@ static int save_domains(struct config_writer *writer, const ltt_session::locked_
                        goto end;
                }
 
+               ret = save_ust_domain(writer, session, LTTNG_DOMAIN_LOG4J2);
+               if (ret != LTTNG_OK) {
+                       goto end;
+               }
+
                ret = save_ust_domain(writer, session, LTTNG_DOMAIN_PYTHON);
                if (ret != LTTNG_OK) {
                        goto end;
index 7788707175bd0748c9bb261b5745b9936bf5dee7..3ae9c09aa5d446eb0fb13e52bf1c27012524f792 100644 (file)
@@ -61,7 +61,7 @@ struct ltt_ust_channel {
        bool enabled;
        /*
         * A UST channel can be part of a userspace sub-domain such as JUL,
-        * Log4j, Python.
+        * Log4j, Log4j2, Python.
         */
        enum lttng_domain_type domain;
        char name[LTTNG_UST_ABI_SYM_NAME_LEN];
index 217d5622ed57df50d42b8145e4e7ff5a62c307b5..802b593dcb2c0b9e888afe5557b1ee97791f1c41 100644 (file)
@@ -2240,6 +2240,7 @@ static int create_ust_event_notifier(struct ust_app *app,
        LTTNG_ASSERT(event_rule_type == LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT ||
                     event_rule_type == LTTNG_EVENT_RULE_TYPE_JUL_LOGGING ||
                     event_rule_type == LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING ||
+                    event_rule_type == LTTNG_EVENT_RULE_TYPE_LOG4J2_LOGGING ||
                     event_rule_type == LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING);
 
        init_ust_event_notifier_from_event_rule(event_rule, &event_notifier);
index 3a0613bd00d6f55c1d40fb5973035c6d90b4213e..497a12065b26de4225bc9ebb0ce7cc28c75acf45 100644 (file)
@@ -29,6 +29,7 @@ static int opt_kernel;
 static int opt_userspace;
 static int opt_jul;
 static int opt_log4j;
+static int opt_log4j2;
 static char *opt_type;
 
 #ifdef LTTNG_EMBED_HELP
@@ -43,6 +44,7 @@ enum {
        OPT_USERSPACE,
        OPT_JUL,
        OPT_LOG4J,
+       OPT_LOG4J2,
        OPT_LIST_OPTIONS,
        OPT_LIST,
 };
@@ -175,6 +177,7 @@ static struct poptOption long_options[] = {
        { "userspace", 'u', POPT_ARG_NONE, nullptr, OPT_USERSPACE, nullptr, nullptr },
        { "jul", 'j', POPT_ARG_NONE, nullptr, OPT_JUL, nullptr, nullptr },
        { "log4j", 'l', POPT_ARG_NONE, nullptr, OPT_LOG4J, nullptr, nullptr },
+       { "log4j2", 0, POPT_ARG_NONE, nullptr, OPT_LOG4J2, nullptr, nullptr },
        { "type", 't', POPT_ARG_STRING, &opt_type, OPT_TYPE, nullptr, nullptr },
        { "list", 0, POPT_ARG_NONE, nullptr, OPT_LIST, nullptr, nullptr },
        { "list-options", 0, POPT_ARG_NONE, nullptr, OPT_LIST_OPTIONS, nullptr, nullptr },
@@ -514,6 +517,8 @@ static enum lttng_domain_type get_domain()
                return LTTNG_DOMAIN_JUL;
        } else if (opt_log4j) {
                return LTTNG_DOMAIN_LOG4J;
+       } else if (opt_log4j2) {
+               return LTTNG_DOMAIN_LOG4J2;
        } else {
                abort();
        }
@@ -1081,6 +1086,9 @@ int cmd_add_context(int argc, const char **argv)
                case OPT_LOG4J:
                        opt_log4j = 1;
                        break;
+               case OPT_LOG4J2:
+                       opt_log4j2 = 1;
+                       break;
                case OPT_LIST_OPTIONS:
                        list_cmd_options(stdout, long_options);
                        goto end;
@@ -1097,8 +1105,8 @@ int cmd_add_context(int argc, const char **argv)
                goto end;
        }
 
-       ret = print_missing_or_multiple_domains(opt_kernel + opt_userspace + opt_jul + opt_log4j,
-                                               true);
+       ret = print_missing_or_multiple_domains(
+               opt_kernel + opt_userspace + opt_jul + opt_log4j + opt_log4j2, true);
        if (ret) {
                ret = CMD_ERROR;
                goto end;
index fa20cda61bcec86cb10de90e24af2b3de44ec0ed..a733bf57e917a602c1a4c85929cdded69c793173 100644 (file)
@@ -122,6 +122,8 @@ static bool assign_event_rule_type(enum lttng_event_rule_type *dest, const char
                *dest = LTTNG_EVENT_RULE_TYPE_JUL_LOGGING;
        } else if (strcmp(arg, "log4j") == 0 || strcmp(arg, "log4j:logging") == 0) {
                *dest = LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING;
+       } else if (strcmp(arg, "log4j2") == 0 || strcmp(arg, "log4j2:logging") == 0) {
+               *dest = LTTNG_EVENT_RULE_TYPE_LOG4J2_LOGGING;
        } else if (strcmp(arg, "python") == 0 || strcmp(arg, "python:logging") == 0) {
                *dest = LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING;
        } else if (strcmp(arg, "kprobe") == 0 || strcmp(arg, "kernel:kprobe") == 0) {
@@ -266,6 +268,23 @@ static bool parse_log_level_string(const char *str,
                *log_level_only = log_level_min == log_level_max;
                break;
        }
+       case LTTNG_EVENT_RULE_TYPE_LOG4J2_LOGGING:
+       {
+               enum lttng_loglevel_log4j2 log_level_min, log_level_max;
+               if (!loglevel_log4j2_parse_range_string(str, &log_level_min, &log_level_max)) {
+                       goto error;
+               }
+
+               /* Only support VAL and VAL.. for now. */
+               if (log_level_min != log_level_max &&
+                   log_level_max != LTTNG_LOGLEVEL_LOG4J2_FATAL) {
+                       goto error;
+               }
+
+               *log_level = (int) log_level_min;
+               *log_level_only = log_level_min == log_level_max;
+               break;
+       }
        case LTTNG_EVENT_RULE_TYPE_JUL_LOGGING:
        {
                enum lttng_loglevel_jul log_level_min, log_level_max;
@@ -788,14 +807,15 @@ static struct parse_event_rule_res parse_event_rule(int *argc, const char ***arg
 
        /*
         * Option --name is applicable to event rules of type kernel, user, jul,
-        * log4j,python and syscall.  If --name is omitted, it is implicitly
-        * "*".
+        * log4j, log4j2, python and syscall.  If --name is omitted, it is
+        * implicitly "*".
         */
        switch (event_rule_type) {
        case LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT:
        case LTTNG_EVENT_RULE_TYPE_KERNEL_TRACEPOINT:
        case LTTNG_EVENT_RULE_TYPE_JUL_LOGGING:
        case LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING:
+       case LTTNG_EVENT_RULE_TYPE_LOG4J2_LOGGING:
        case LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING:
        case LTTNG_EVENT_RULE_TYPE_KERNEL_SYSCALL:
                if (!name) {
@@ -872,6 +892,7 @@ static struct parse_event_rule_res parse_event_rule(int *argc, const char ***arg
                case LTTNG_EVENT_RULE_TYPE_KERNEL_TRACEPOINT:
                case LTTNG_EVENT_RULE_TYPE_JUL_LOGGING:
                case LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING:
+               case LTTNG_EVENT_RULE_TYPE_LOG4J2_LOGGING:
                case LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING:
                case LTTNG_EVENT_RULE_TYPE_KERNEL_SYSCALL:
                        break;
@@ -908,6 +929,7 @@ static struct parse_event_rule_res parse_event_rule(int *argc, const char ***arg
                case LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT:
                case LTTNG_EVENT_RULE_TYPE_JUL_LOGGING:
                case LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING:
+               case LTTNG_EVENT_RULE_TYPE_LOG4J2_LOGGING:
                case LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING:
                {
                        int log_level;
@@ -1117,6 +1139,45 @@ static struct parse_event_rule_res parse_event_rule(int *argc, const char ***arg
                }
                break;
        }
+       case LTTNG_EVENT_RULE_TYPE_LOG4J2_LOGGING:
+       {
+               enum lttng_event_rule_status event_rule_status;
+
+               res.er = lttng_event_rule_log4j2_logging_create();
+               if (!res.er) {
+                       ERR("Failed to create log4j2_logging event rule.");
+                       goto error;
+               }
+
+               /* Set pattern. */
+               event_rule_status = lttng_event_rule_log4j2_logging_set_name_pattern(res.er, name);
+               if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
+                       ERR("Failed to set log4j2_logging event rule's pattern to '%s'.", name);
+                       goto error;
+               }
+
+               /* Set filter. */
+               if (filter) {
+                       event_rule_status =
+                               lttng_event_rule_log4j2_logging_set_filter(res.er, filter);
+                       if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
+                               ERR("Failed to set log4j2_logging event rule's filter to '%s'.",
+                                   filter);
+                               goto error;
+                       }
+               }
+
+               if (log_level_rule) {
+                       event_rule_status = lttng_event_rule_log4j2_logging_set_log_level_rule(
+                               res.er, log_level_rule);
+
+                       if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
+                               ERR("Failed to set log level on event fule.");
+                               goto error;
+                       }
+               }
+               break;
+       }
        case LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING:
        {
                enum lttng_event_rule_status event_rule_status;
index 40e85e7c8afe6b447f1cacda25ba6d4d20ef0de9..db0b9aabab9ab3a65e13c34eed3107a0962864e5 100644 (file)
@@ -27,6 +27,7 @@ static int opt_userspace;
 static int opt_disable_all;
 static int opt_jul;
 static int opt_log4j;
+static int opt_log4j2;
 static int opt_python;
 static int opt_event_type;
 
@@ -57,6 +58,7 @@ static struct poptOption long_options[] = {
        { "channel", 'c', POPT_ARG_STRING, &opt_channel_name, 0, nullptr, nullptr },
        { "jul", 'j', POPT_ARG_VAL, &opt_jul, 1, nullptr, nullptr },
        { "log4j", 'l', POPT_ARG_VAL, &opt_log4j, 1, nullptr, nullptr },
+       { "log4j2", 0, POPT_ARG_VAL, &opt_log4j2, 1, nullptr, nullptr },
        { "python", 'p', POPT_ARG_VAL, &opt_python, 1, nullptr, nullptr },
        { "kernel", 'k', POPT_ARG_VAL, &opt_kernel, 1, nullptr, nullptr },
        { "userspace", 'u', POPT_ARG_VAL, &opt_userspace, 1, nullptr, nullptr },
@@ -164,6 +166,8 @@ static int disable_events(char *session_name, char *event_list)
                dom.type = LTTNG_DOMAIN_JUL;
        } else if (opt_log4j) {
                dom.type = LTTNG_DOMAIN_LOG4J;
+       } else if (opt_log4j2) {
+               dom.type = LTTNG_DOMAIN_LOG4J2;
        } else if (opt_python) {
                dom.type = LTTNG_DOMAIN_PYTHON;
        } else {
@@ -371,16 +375,16 @@ int cmd_disable_events(int argc, const char **argv)
        }
 
        ret = print_missing_or_multiple_domains(
-               opt_kernel + opt_userspace + opt_jul + opt_log4j + opt_python, true);
+               opt_kernel + opt_userspace + opt_jul + opt_log4j + opt_log4j2 + opt_python, true);
        if (ret) {
                ret = CMD_ERROR;
                goto end;
        }
 
        /* Ust and agent only support ALL event type */
-       if ((opt_userspace || opt_jul || opt_log4j || opt_python) &&
+       if ((opt_userspace || opt_jul || opt_log4j || opt_log4j2 || opt_python) &&
            opt_event_type != LTTNG_EVENT_ALL) {
-               ERR("Disabling userspace and agent (-j | -l | -p) event(s) based on instrumentation type is not supported.\n");
+               ERR("Disabling userspace and agent event(s) based on instrumentation type is not supported.\n");
                ret = CMD_ERROR;
                goto end;
        }
index b081adeeed7f3f68d7d97f57722002091c40bef0..1f1c8b4593ddb8a324e70c0045d7a1b65e932301 100644 (file)
@@ -61,6 +61,7 @@ char *opt_session_name;
 int opt_userspace;
 int opt_jul;
 int opt_log4j;
+int opt_log4j2;
 int opt_python;
 int opt_enable_all;
 char *opt_probe;
@@ -104,6 +105,7 @@ struct poptOption long_options[] = {
        { "userspace", 'u', POPT_ARG_NONE, nullptr, OPT_USERSPACE, nullptr, nullptr },
        { "jul", 'j', POPT_ARG_VAL, &opt_jul, 1, nullptr, nullptr },
        { "log4j", 'l', POPT_ARG_VAL, &opt_log4j, 1, nullptr, nullptr },
+       { "log4j2", 0, POPT_ARG_VAL, &opt_log4j2, 1, nullptr, nullptr },
        { "python", 'p', POPT_ARG_VAL, &opt_python, 1, nullptr, nullptr },
        { "tracepoint", 0, POPT_ARG_NONE, nullptr, OPT_TRACEPOINT, nullptr, nullptr },
        { "probe", 0, POPT_ARG_STRING, &opt_probe, OPT_PROBE, nullptr, nullptr },
@@ -444,6 +446,10 @@ int enable_events(const std::string& session_name, const event_rule_patterns& pa
                dom.type = LTTNG_DOMAIN_LOG4J;
                /* Default. */
                dom.buf_type = LTTNG_BUFFER_PER_UID;
+       } else if (opt_log4j2) {
+               dom.type = LTTNG_DOMAIN_LOG4J2;
+               /* Default. */
+               dom.buf_type = LTTNG_BUFFER_PER_UID;
        } else if (opt_python) {
                dom.type = LTTNG_DOMAIN_PYTHON;
                /* Default. */
@@ -458,6 +464,7 @@ int enable_events(const std::string& session_name, const event_rule_patterns& pa
                case LTTNG_DOMAIN_KERNEL:
                case LTTNG_DOMAIN_JUL:
                case LTTNG_DOMAIN_LOG4J:
+               case LTTNG_DOMAIN_LOG4J2:
                case LTTNG_DOMAIN_PYTHON:
                        ERR("Event name exclusions are not supported for %s event rules",
                            lttng_domain_type_str(dom.type));
@@ -653,7 +660,7 @@ int enable_events(const std::string& session_name, const event_rule_patterns& pa
                        } else {
                                ev->loglevel = -1;
                        }
-               } else if (opt_jul || opt_log4j || opt_python) {
+               } else if (opt_jul || opt_log4j || opt_log4j2 || opt_python) {
                        if (opt_event_type != LTTNG_EVENT_ALL &&
                            opt_event_type != LTTNG_EVENT_TRACEPOINT) {
                                ERR("Instrumentation point type not supported for the %s domain",
@@ -678,6 +685,12 @@ int enable_events(const std::string& session_name, const event_rule_patterns& pa
                                        name_search_ret = loglevel_log4j_name_to_value(opt_loglevel,
                                                                                       &loglevel);
                                        ev->loglevel = (int) loglevel;
+                               } else if (opt_log4j2) {
+                                       enum lttng_loglevel_log4j2 loglevel;
+
+                                       name_search_ret = loglevel_log4j2_name_to_value(
+                                               opt_loglevel, &loglevel);
+                                       ev->loglevel = (int) loglevel;
                                } else {
                                        /* python domain. */
                                        enum lttng_loglevel_python loglevel;
@@ -697,6 +710,8 @@ int enable_events(const std::string& session_name, const event_rule_patterns& pa
                                        ev->loglevel = LTTNG_LOGLEVEL_JUL_ALL;
                                } else if (opt_log4j) {
                                        ev->loglevel = LTTNG_LOGLEVEL_LOG4J_ALL;
+                               } else if (opt_log4j2) {
+                                       ev->loglevel = LTTNG_LOGLEVEL_LOG4J2_ALL;
                                } else if (opt_python) {
                                        ev->loglevel = LTTNG_LOGLEVEL_PYTHON_DEBUG;
                                }
@@ -792,6 +807,7 @@ int enable_events(const std::string& session_name, const event_rule_patterns& pa
                                }
                                case LTTNG_DOMAIN_JUL:
                                case LTTNG_DOMAIN_LOG4J:
+                               case LTTNG_DOMAIN_LOG4J2:
                                case LTTNG_DOMAIN_PYTHON:
                                        /*
                                         * Don't print the default channel
@@ -1082,7 +1098,7 @@ int cmd_enable_events(int argc, const char **argv)
        }
 
        ret = print_missing_or_multiple_domains(
-               opt_kernel + opt_userspace + opt_jul + opt_log4j + opt_python, true);
+               opt_kernel + opt_userspace + opt_jul + opt_log4j + opt_log4j2 + opt_python, true);
        if (ret) {
                return CMD_ERROR;
        }
index c4e52b78fef879d9edf902bf25e4dc63c50d28af..b0cbf0ca15225d3e71b364a50b4a8feedba3c118 100644 (file)
@@ -27,6 +27,7 @@ static int opt_userspace;
 static int opt_kernel;
 static int opt_jul;
 static int opt_log4j;
+static int opt_log4j2;
 static int opt_python;
 static char *opt_channel;
 static int opt_domain;
@@ -61,6 +62,7 @@ static struct poptOption long_options[] = {
        { "kernel", 'k', POPT_ARG_VAL, &opt_kernel, 1, nullptr, nullptr },
        { "jul", 'j', POPT_ARG_VAL, &opt_jul, 1, nullptr, nullptr },
        { "log4j", 'l', POPT_ARG_VAL, &opt_log4j, 1, nullptr, nullptr },
+       { "log4j2", 0, POPT_ARG_VAL, &opt_log4j2, 1, nullptr, nullptr },
        { "python", 'p', POPT_ARG_VAL, &opt_python, 1, nullptr, nullptr },
        { "userspace", 'u', POPT_ARG_NONE, nullptr, OPT_USERSPACE, nullptr, nullptr },
        { "channel", 'c', POPT_ARG_STRING, &opt_channel, 0, nullptr, nullptr },
@@ -583,6 +585,8 @@ static int list_agent_events()
                domain.type = LTTNG_DOMAIN_JUL;
        } else if (opt_log4j) {
                domain.type = LTTNG_DOMAIN_LOG4J;
+       } else if (opt_log4j2) {
+               domain.type = LTTNG_DOMAIN_LOG4J2;
        } else if (opt_python) {
                domain.type = LTTNG_DOMAIN_PYTHON;
        } else {
@@ -2224,10 +2228,13 @@ static int list_domains(const char *session_name)
                                MSG("  - UST global");
                                break;
                        case LTTNG_DOMAIN_JUL:
-                               MSG("  - JUL (Java Util Logging)");
+                               MSG("  - JUL (java.util.logging)");
                                break;
                        case LTTNG_DOMAIN_LOG4J:
-                               MSG("  - LOG4j (Logging for Java)");
+                               MSG("  - Log4j");
+                               break;
+                       case LTTNG_DOMAIN_LOG4J2:
+                               MSG("  - Log4j2");
                                break;
                        case LTTNG_DOMAIN_PYTHON:
                                MSG("  - Python (logging)");
@@ -2327,6 +2334,8 @@ int cmd_list(int argc, const char **argv)
                domain.type = LTTNG_DOMAIN_JUL;
        } else if (opt_log4j) {
                domain.type = LTTNG_DOMAIN_LOG4J;
+       } else if (opt_log4j2) {
+               domain.type = LTTNG_DOMAIN_LOG4J2;
        } else if (opt_python) {
                domain.type = LTTNG_DOMAIN_PYTHON;
        }
@@ -2337,7 +2346,7 @@ int cmd_list(int argc, const char **argv)
                goto end;
        }
 
-       if (opt_kernel || opt_userspace || opt_jul || opt_log4j || opt_python) {
+       if (opt_kernel || opt_userspace || opt_jul || opt_log4j || opt_log4j2 || opt_python) {
                the_handle = lttng_create_handle(arg_session_name, &domain);
                if (the_handle == nullptr) {
                        ret = CMD_FATAL;
@@ -2346,7 +2355,8 @@ int cmd_list(int argc, const char **argv)
        }
 
        if (arg_session_name == nullptr) {
-               if (!opt_kernel && !opt_userspace && !opt_jul && !opt_log4j && !opt_python) {
+               if (!opt_kernel && !opt_userspace && !opt_jul && !opt_log4j && !opt_log4j2 &&
+                   !opt_python) {
                        ret = list_sessions(nullptr);
                        if (ret) {
                                goto end;
@@ -2375,7 +2385,7 @@ int cmd_list(int argc, const char **argv)
                                goto end;
                        }
                }
-               if (opt_jul || opt_log4j || opt_python) {
+               if (opt_jul || opt_log4j || opt_log4j2 || opt_python) {
                        ret = list_agent_events();
                        if (ret) {
                                goto end;
@@ -2479,10 +2489,13 @@ int cmd_list(int argc, const char **argv)
                                                    "per-user");
                                        break;
                                case LTTNG_DOMAIN_JUL:
-                                       MSG("=== Domain: java.util.logging (JUL) ===\n");
+                                       MSG("=== Domain: JUL (java.util.logging) ===\n");
                                        break;
                                case LTTNG_DOMAIN_LOG4J:
-                                       MSG("=== Domain: log4j ===\n");
+                                       MSG("=== Domain: Log4j ===\n");
+                                       break;
+                               case LTTNG_DOMAIN_LOG4J2:
+                                       MSG("=== Domain: Log4j2 ===\n");
                                        break;
                                case LTTNG_DOMAIN_PYTHON:
                                        MSG("=== Domain: Python logging ===\n");
@@ -2513,6 +2526,7 @@ int cmd_list(int argc, const char **argv)
 
                                if (domains[i].type == LTTNG_DOMAIN_JUL ||
                                    domains[i].type == LTTNG_DOMAIN_LOG4J ||
+                                   domains[i].type == LTTNG_DOMAIN_LOG4J2 ||
                                    domains[i].type == LTTNG_DOMAIN_PYTHON) {
                                        ret = list_session_agent_events();
                                        if (ret) {
index 0cedb26421e976d48c2d5ad271056c97b155d4a4..db905bc4f34ac8ae4083c63d128d1c35eb18db7a 100644 (file)
@@ -135,6 +135,9 @@ static const char *get_pretty_loglevel_name(enum lttng_event_rule_type event_rul
        case LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING:
                name = loglevel_log4j_value_to_name(loglevel);
                break;
+       case LTTNG_EVENT_RULE_TYPE_LOG4J2_LOGGING:
+               name = loglevel_log4j2_value_to_name(loglevel);
+               break;
        case LTTNG_EVENT_RULE_TYPE_JUL_LOGGING:
                name = loglevel_jul_value_to_name(loglevel);
                break;
@@ -274,6 +277,12 @@ static void print_event_rule_logging(const struct lttng_event_rule *event_rule)
                logging_get_log_level_rule = lttng_event_rule_log4j_logging_get_log_level_rule;
                type_str = "log4j";
                break;
+       case LTTNG_EVENT_RULE_TYPE_LOG4J2_LOGGING:
+               logging_get_name_pattern = lttng_event_rule_log4j2_logging_get_name_pattern;
+               logging_get_filter = lttng_event_rule_log4j2_logging_get_filter;
+               logging_get_log_level_rule = lttng_event_rule_log4j2_logging_get_log_level_rule;
+               type_str = "log4j2";
+               break;
        case LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING:
                logging_get_name_pattern = lttng_event_rule_python_logging_get_name_pattern;
                logging_get_filter = lttng_event_rule_python_logging_get_filter;
@@ -513,6 +522,7 @@ static void print_event_rule(const struct lttng_event_rule *event_rule)
                break;
        case LTTNG_EVENT_RULE_TYPE_JUL_LOGGING:
        case LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING:
+       case LTTNG_EVENT_RULE_TYPE_LOG4J2_LOGGING:
        case LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING:
                print_event_rule_logging(event_rule);
                break;
index d266baa44c3f67cacaa83ce617a52196e4077d4e..de19ffed3538c8e1653b1a4478117246c60e24cb 100644 (file)
@@ -77,6 +77,25 @@ static const struct loglevel_name_value loglevel_log4j_values[] = {
        { .name = "LOG4J_ALL", .value = LTTNG_LOGLEVEL_LOG4J_ALL },
 };
 
+static const struct loglevel_name_value loglevel_log4j2_values[] = {
+       { .name = "OFF", .value = LTTNG_LOGLEVEL_LOG4J2_OFF },
+       { .name = "LOG4J2_OFF", .value = LTTNG_LOGLEVEL_LOG4J2_OFF },
+       { .name = "FATAL", .value = LTTNG_LOGLEVEL_LOG4J2_FATAL },
+       { .name = "LOG4J2_FATAL", .value = LTTNG_LOGLEVEL_LOG4J2_FATAL },
+       { .name = "ERROR", .value = LTTNG_LOGLEVEL_LOG4J2_ERROR },
+       { .name = "LOG4J2_ERROR", .value = LTTNG_LOGLEVEL_LOG4J2_ERROR },
+       { .name = "WARN", .value = LTTNG_LOGLEVEL_LOG4J2_WARN },
+       { .name = "LOG4J2_WARN", .value = LTTNG_LOGLEVEL_LOG4J2_WARN },
+       { .name = "INFO", .value = LTTNG_LOGLEVEL_LOG4J2_INFO },
+       { .name = "LOG4J2_INFO", .value = LTTNG_LOGLEVEL_LOG4J2_INFO },
+       { .name = "DEBUG", .value = LTTNG_LOGLEVEL_LOG4J2_DEBUG },
+       { .name = "LOG4J2_DEBUG", .value = LTTNG_LOGLEVEL_LOG4J2_DEBUG },
+       { .name = "TRACE", .value = LTTNG_LOGLEVEL_LOG4J2_TRACE },
+       { .name = "LOG4J2_TRACE", .value = LTTNG_LOGLEVEL_LOG4J2_TRACE },
+       { .name = "ALL", .value = LTTNG_LOGLEVEL_LOG4J2_ALL },
+       { .name = "LOG4J2_ALL", .value = LTTNG_LOGLEVEL_LOG4J2_ALL },
+};
+
 static const struct loglevel_name_value loglevel_jul_values[] = {
        { .name = "OFF", .value = LTTNG_LOGLEVEL_JUL_OFF },
        { .name = "JUL_OFF", .value = LTTNG_LOGLEVEL_JUL_OFF },
@@ -261,6 +280,36 @@ bool loglevel_log4j_parse_range_string(const char *str,
        return ret;
 }
 
+int loglevel_log4j2_name_to_value(const char *name, enum lttng_loglevel_log4j2 *loglevel)
+{
+       int ret = lookup_value_from_name(
+               loglevel_log4j2_values, ARRAY_SIZE(loglevel_log4j2_values), name);
+
+       if (ret >= 0) {
+               *loglevel = (typeof(*loglevel)) ret;
+               ret = 0;
+       }
+
+       return ret;
+}
+
+bool loglevel_log4j2_parse_range_string(const char *str,
+                                       enum lttng_loglevel_log4j2 *min,
+                                       enum lttng_loglevel_log4j2 *max)
+{
+       int min_int, max_int;
+       bool ret = loglevel_parse_range_string_common(str,
+                                                     loglevel_log4j2_values,
+                                                     ARRAY_SIZE(loglevel_log4j2_values),
+                                                     &min_int,
+                                                     &max_int);
+
+       *min = (lttng_loglevel_log4j2) min_int;
+       *max = (lttng_loglevel_log4j2) max_int;
+
+       return ret;
+}
+
 int loglevel_jul_name_to_value(const char *name, enum lttng_loglevel_jul *loglevel)
 {
        int ret =
@@ -347,6 +396,12 @@ const char *loglevel_log4j_value_to_name(int loglevel)
                loglevel_log4j_values, ARRAY_SIZE(loglevel_log4j_values), loglevel);
 }
 
+const char *loglevel_log4j2_value_to_name(int loglevel)
+{
+       return lookup_name_from_value(
+               loglevel_log4j2_values, ARRAY_SIZE(loglevel_log4j2_values), loglevel);
+}
+
 const char *loglevel_jul_value_to_name(int loglevel)
 {
        return lookup_name_from_value(
index 76c5ce021e2a26759ba8dfd3415ef9b40ac91fe1..0989ee60f88e1fffeda65287a743b1462c828674 100644 (file)
@@ -24,6 +24,12 @@ bool loglevel_log4j_parse_range_string(const char *str,
                                       enum lttng_loglevel_log4j *min,
                                       enum lttng_loglevel_log4j *max);
 
+int loglevel_log4j2_name_to_value(const char *name, enum lttng_loglevel_log4j2 *loglevel);
+
+bool loglevel_log4j2_parse_range_string(const char *str,
+                                       enum lttng_loglevel_log4j2 *min,
+                                       enum lttng_loglevel_log4j2 *max);
+
 int loglevel_jul_name_to_value(const char *name, enum lttng_loglevel_jul *loglevel);
 
 bool loglevel_jul_parse_range_string(const char *str,
@@ -40,6 +46,8 @@ const char *loglevel_value_to_name(int loglevel);
 
 const char *loglevel_log4j_value_to_name(int loglevel);
 
+const char *loglevel_log4j2_value_to_name(int loglevel);
+
 const char *loglevel_jul_value_to_name(int loglevel);
 
 const char *loglevel_python_value_to_name(int loglevel);
index 6622d1aa8805dd54099cef6eaa5d1fe6d544b9fb..7831ae65a4f695befc4a5448cafe435cf6220e3d 100644 (file)
@@ -423,7 +423,7 @@ int print_missing_or_multiple_domains(unsigned int domain_count, bool include_ag
 
        if (domain_count == 0) {
                ERR("Please specify a domain (--kernel/--userspace%s).",
-                   include_agent_domains ? "/--jul/--log4j/--python" : "");
+                   include_agent_domains ? "/--jul/--log4j/--log4j2/--python" : "");
                ret = -1;
        } else if (domain_count > 1) {
                ERR("Only one domain must be specified.");
index 68ab02f048f2c9fd7d8b33893f5391938ced36e5..2516a5042bf4dccdf4e1263652580b1addc8e824 100644 (file)
@@ -84,6 +84,7 @@ libcommon_lgpl_la_SOURCES = \
        event-rule/kernel-tracepoint.cpp \
        event-rule/user-tracepoint.cpp \
        event-rule/log4j-logging.cpp \
+       event-rule/log4j2-logging.cpp \
        event-rule/jul-logging.cpp \
        event-rule/python-logging.cpp \
        exception.cpp exception.hpp \
index 91012f475cc97fc7fea324fbd4198c9adce7ffa3..64f00859c6305c6e16892894f106557a50a50a14 100644 (file)
@@ -822,6 +822,7 @@ lttng_condition_event_rule_matches_append_capture_descriptor(struct lttng_condit
        case LTTNG_EVENT_RULE_TYPE_KERNEL_TRACEPOINT:
        case LTTNG_EVENT_RULE_TYPE_JUL_LOGGING:
        case LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING:
+       case LTTNG_EVENT_RULE_TYPE_LOG4J2_LOGGING:
        case LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING:
        case LTTNG_EVENT_RULE_TYPE_KERNEL_SYSCALL:
                /* Supported. */
index f56b4bd0d3cfd1902c8e89d4b70e473c308a207b..d0b41dbbc69a3b36d80e19e28040e787e17b8442 100644 (file)
@@ -105,6 +105,7 @@ LTTNG_EXPORT extern const char *const config_domain_type_kernel;
 LTTNG_EXPORT extern const char *const config_domain_type_ust;
 LTTNG_EXPORT extern const char *const config_domain_type_jul;
 LTTNG_EXPORT extern const char *const config_domain_type_log4j;
+LTTNG_EXPORT extern const char *const config_domain_type_log4j2;
 LTTNG_EXPORT extern const char *const config_domain_type_python;
 
 LTTNG_EXPORT extern const char *const config_buffer_type_per_pid;
index 9af61fa93fb349f037b1e07c5039587c61944729..6dddbe41e7e4a06193add51d1c7e21166764526d 100644 (file)
@@ -164,6 +164,7 @@ const char *const config_domain_type_kernel = "KERNEL";
 const char *const config_domain_type_ust = "UST";
 const char *const config_domain_type_jul = "JUL";
 const char *const config_domain_type_log4j = "LOG4J";
+const char *const config_domain_type_log4j2 = "LOG4J2";
 const char *const config_domain_type_python = "PYTHON";
 
 const char *const config_buffer_type_per_pid = "PER_PID";
@@ -723,6 +724,8 @@ static int get_domain_type(xmlChar *domain)
                ret = LTTNG_DOMAIN_JUL;
        } else if (!strcmp((char *) domain, config_domain_type_log4j)) {
                ret = LTTNG_DOMAIN_LOG4J;
+       } else if (!strcmp((char *) domain, config_domain_type_log4j2)) {
+               ret = LTTNG_DOMAIN_LOG4J2;
        } else if (!strcmp((char *) domain, config_domain_type_python)) {
                ret = LTTNG_DOMAIN_PYTHON;
        } else {
@@ -1609,6 +1612,9 @@ static int process_event_node(xmlNodePtr event_node,
        case LTTNG_DOMAIN_LOG4J:
                event->loglevel = LTTNG_LOGLEVEL_LOG4J_ALL;
                break;
+       case LTTNG_DOMAIN_LOG4J2:
+               event->loglevel = LTTNG_LOGLEVEL_LOG4J2_ALL;
+               break;
        case LTTNG_DOMAIN_PYTHON:
                event->loglevel = LTTNG_LOGLEVEL_PYTHON_DEBUG;
                break;
@@ -2821,6 +2827,7 @@ static int process_domain_node(xmlNodePtr domain_node, const char *session_name)
                switch (domain.type) {
                case LTTNG_DOMAIN_JUL:
                case LTTNG_DOMAIN_LOG4J:
+               case LTTNG_DOMAIN_LOG4J2:
                case LTTNG_DOMAIN_PYTHON:
                        domain.type = LTTNG_DOMAIN_UST;
                default:
@@ -3102,6 +3109,7 @@ static int process_session_node(xmlNodePtr session_node,
        struct lttng_domain *ust_domain = nullptr;
        struct lttng_domain *jul_domain = nullptr;
        struct lttng_domain *log4j_domain = nullptr;
+       struct lttng_domain *log4j2_domain = nullptr;
        struct lttng_domain *python_domain = nullptr;
 
        for (node = xmlFirstElementChild(session_node); node; node = xmlNextElementSibling(node)) {
@@ -3257,6 +3265,13 @@ static int process_session_node(xmlNodePtr session_node,
                        }
                        log4j_domain = domain;
                        break;
+               case LTTNG_DOMAIN_LOG4J2:
+                       if (log4j2_domain) {
+                               /* Same domain seen twice, invalid! */
+                               goto domain_init_error;
+                       }
+                       log4j2_domain = domain;
+                       break;
                case LTTNG_DOMAIN_PYTHON:
                        if (python_domain) {
                                /* Same domain seen twice, invalid! */
@@ -3358,6 +3373,7 @@ error:
        free(ust_domain);
        free(jul_domain);
        free(log4j_domain);
+       free(log4j2_domain);
        free(python_domain);
        xmlFree(name);
        xmlFree(shm_path);
index 149c483ec668cb7912dc6e5aa47b31244db5efc8..2be3648cc5421d5d514c39f2f7a15d0a54681586 100644 (file)
 #define DEFAULT_LOG4J_EVENT_COMPONENT "lttng_log4j"
 #define DEFAULT_LOG4J_EVENT_NAME      DEFAULT_LOG4J_EVENT_COMPONENT ":*"
 
+/* Default log4j2 domain channel name. */
+#define DEFAULT_LOG4J2_CHANNEL_NAME "lttng_log4j2_channel"
+/* Default log4j tracepoint name. This is a wildcard for the log4j2 domain. */
+#define DEFAULT_LOG4J2_EVENT_COMPONENT "lttng_log4j2"
+#define DEFAULT_LOG4J2_EVENT_NAME      DEFAULT_LOG4J2_EVENT_COMPONENT ":*"
+
 /* Default Python domain channel name. */
 #define DEFAULT_PYTHON_CHANNEL_NAME "lttng_python_channel"
 /* Default Python tracepoint name. This is a wildcard for the python domain. */
index 7b331d0491e45a294b537b1f1e38beb19c03463d..0ae57d9d0995287161a1e7c830f22f4e94bbe3d8 100644 (file)
@@ -21,6 +21,8 @@ const char *lttng_domain_type_str(enum lttng_domain_type domain_type)
                return "java.util.logging (JUL)";
        case LTTNG_DOMAIN_LOG4J:
                return "log4j";
+       case LTTNG_DOMAIN_LOG4J2:
+               return "log4j2";
        case LTTNG_DOMAIN_PYTHON:
                return "Python logging";
        default:
index 197d4b011d4c63ab829679c0253f6634059395a2..220a99a233d4a159794ad6b7953437312968e781 100644 (file)
@@ -21,6 +21,7 @@
 #include <lttng/event-rule/kernel-tracepoint-internal.hpp>
 #include <lttng/event-rule/kernel-uprobe-internal.hpp>
 #include <lttng/event-rule/log4j-logging-internal.hpp>
+#include <lttng/event-rule/log4j2-logging-internal.hpp>
 #include <lttng/event-rule/python-logging-internal.hpp>
 #include <lttng/event-rule/user-tracepoint-internal.hpp>
 
@@ -45,6 +46,9 @@ enum lttng_domain_type lttng_event_rule_get_domain_type(const struct lttng_event
        case LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING:
                domain_type = LTTNG_DOMAIN_LOG4J;
                break;
+       case LTTNG_EVENT_RULE_TYPE_LOG4J2_LOGGING:
+               domain_type = LTTNG_DOMAIN_LOG4J2;
+               break;
        case LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING:
                domain_type = LTTNG_DOMAIN_PYTHON;
                break;
@@ -190,6 +194,9 @@ ssize_t lttng_event_rule_create_from_payload(struct lttng_payload_view *view,
        case LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING:
                create_from_payload = lttng_event_rule_log4j_logging_create_from_payload;
                break;
+       case LTTNG_EVENT_RULE_TYPE_LOG4J2_LOGGING:
+               create_from_payload = lttng_event_rule_log4j2_logging_create_from_payload;
+               break;
        case LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING:
                create_from_payload = lttng_event_rule_python_logging_create_from_payload;
                break;
@@ -288,6 +295,7 @@ bool lttng_event_rule_targets_agent_domain(const struct lttng_event_rule *rule)
        switch (type) {
        case LTTNG_DOMAIN_JUL:
        case LTTNG_DOMAIN_LOG4J:
+       case LTTNG_DOMAIN_LOG4J2:
        case LTTNG_DOMAIN_PYTHON:
                targets_agent_domain = true;
                break;
@@ -321,6 +329,8 @@ const char *lttng_event_rule_type_str(enum lttng_event_rule_type type)
                return "jul logging";
        case LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING:
                return "log4j logging";
+       case LTTNG_EVENT_RULE_TYPE_LOG4J2_LOGGING:
+               return "log4j2 logging";
        case LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING:
                return "python logging";
 
index 97876cd35ef782690435316dd1b35f45bdecfc18..289349ca671b95a2ff5b14a49bf6b5186c4d8d63 100644 (file)
@@ -231,7 +231,7 @@ static int generate_agent_filter(const struct lttng_event_rule *rule, char **_ag
                case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS:
                        llr_status = lttng_log_level_rule_at_least_as_severe_as_get_level(
                                log_level_rule, &level);
-                       op = ">=";
+                       op = LTTNG_JUL_EVENT_RULE_AT_LEAST_AS_SEVERE_AS_OP;
                        break;
                default:
                        abort();
@@ -810,8 +810,8 @@ end:
 static bool log_level_rule_valid(const struct lttng_log_level_rule *rule __attribute__((unused)))
 {
        /*
-        * For both JUL and LOG4J custom log level are possible and can
-        * span the entire int32 range.
+        * JUL custom log levels are possible and can span the entire int32
+        * range.
         */
        return true;
 }
index ba440b979e1685082558baa73e20660bcc2cc7cc..dc0c9f2df097219aa95968a208693c1158722e8b 100644 (file)
@@ -231,7 +231,7 @@ static int generate_agent_filter(const struct lttng_event_rule *rule, char **_ag
                case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS:
                        llr_status = lttng_log_level_rule_at_least_as_severe_as_get_level(
                                log_level_rule, &level);
-                       op = ">=";
+                       op = LTTNG_LOG4J_EVENT_RULE_AT_LEAST_AS_SEVERE_AS_OP;
                        break;
                default:
                        abort();
@@ -809,8 +809,8 @@ end:
 static bool log_level_rule_valid(const struct lttng_log_level_rule *rule __attribute__((unused)))
 {
        /*
-        * For both LOG4J custom log level are possible and can
-        * span the entire int32 range.
+        * LOG4J custom log levels are possible and can span the entire int32
+        * range.
         */
        return true;
 }
diff --git a/src/common/event-rule/log4j2-logging.cpp b/src/common/event-rule/log4j2-logging.cpp
new file mode 100644 (file)
index 0000000..8849639
--- /dev/null
@@ -0,0 +1,874 @@
+/*
+ * Copyright (C) 2024 Michael Jeanson <mjeanson@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#include <common/credentials.hpp>
+#include <common/error.hpp>
+#include <common/hashtable/hashtable.hpp>
+#include <common/hashtable/utils.hpp>
+#include <common/macros.hpp>
+#include <common/mi-lttng.hpp>
+#include <common/optional.hpp>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
+#include <common/runas.hpp>
+#include <common/string-utils/string-utils.hpp>
+
+#include <lttng/event-rule/event-rule-internal.hpp>
+#include <lttng/event-rule/log4j2-logging-internal.hpp>
+#include <lttng/event.h>
+#include <lttng/log-level-rule.h>
+
+#define IS_LOG4J2_LOGGING_EVENT_RULE(rule) \
+       (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_LOG4J2_LOGGING)
+
+static void lttng_event_rule_log4j2_logging_destroy(struct lttng_event_rule *rule)
+{
+       struct lttng_event_rule_log4j2_logging *log4j2_logging;
+
+       if (rule == nullptr) {
+               return;
+       }
+
+       log4j2_logging = lttng::utils::container_of(rule, &lttng_event_rule_log4j2_logging::parent);
+
+       lttng_log_level_rule_destroy(log4j2_logging->log_level_rule);
+       free(log4j2_logging->pattern);
+       free(log4j2_logging->filter_expression);
+       free(log4j2_logging->internal_filter.filter);
+       free(log4j2_logging->internal_filter.bytecode);
+       free(log4j2_logging);
+}
+
+static bool lttng_event_rule_log4j2_logging_validate(const struct lttng_event_rule *rule)
+{
+       bool valid = false;
+       struct lttng_event_rule_log4j2_logging *log4j2_logging;
+
+       if (!rule) {
+               goto end;
+       }
+
+       log4j2_logging = lttng::utils::container_of(rule, &lttng_event_rule_log4j2_logging::parent);
+
+       /* Required field. */
+       if (!log4j2_logging->pattern) {
+               ERR("Invalid log4j2_logging event rule: a pattern must be set.");
+               goto end;
+       }
+
+       valid = true;
+end:
+       return valid;
+}
+
+static int lttng_event_rule_log4j2_logging_serialize(const struct lttng_event_rule *rule,
+                                                    struct lttng_payload *payload)
+{
+       int ret;
+       size_t pattern_len, filter_expression_len, header_offset;
+       size_t size_before_log_level_rule;
+       struct lttng_event_rule_log4j2_logging *log4j2_logging;
+       struct lttng_event_rule_log4j2_logging_comm log4j2_logging_comm;
+       struct lttng_event_rule_log4j2_logging_comm *header;
+
+       if (!rule || !IS_LOG4J2_LOGGING_EVENT_RULE(rule)) {
+               ret = -1;
+               goto end;
+       }
+
+       header_offset = payload->buffer.size;
+
+       DBG("Serializing log4j2_logging event rule.");
+       log4j2_logging = lttng::utils::container_of(rule, &lttng_event_rule_log4j2_logging::parent);
+
+       pattern_len = strlen(log4j2_logging->pattern) + 1;
+
+       if (log4j2_logging->filter_expression != nullptr) {
+               filter_expression_len = strlen(log4j2_logging->filter_expression) + 1;
+       } else {
+               filter_expression_len = 0;
+       }
+
+       log4j2_logging_comm.pattern_len = pattern_len;
+       log4j2_logging_comm.filter_expression_len = filter_expression_len;
+
+       ret = lttng_dynamic_buffer_append(
+               &payload->buffer, &log4j2_logging_comm, sizeof(log4j2_logging_comm));
+       if (ret) {
+               goto end;
+       }
+
+       ret = lttng_dynamic_buffer_append(&payload->buffer, log4j2_logging->pattern, pattern_len);
+       if (ret) {
+               goto end;
+       }
+
+       ret = lttng_dynamic_buffer_append(
+               &payload->buffer, log4j2_logging->filter_expression, filter_expression_len);
+       if (ret) {
+               goto end;
+       }
+
+       size_before_log_level_rule = payload->buffer.size;
+
+       ret = lttng_log_level_rule_serialize(log4j2_logging->log_level_rule, payload);
+       if (ret < 0) {
+               goto end;
+       }
+
+       header = (typeof(header)) ((char *) payload->buffer.data + header_offset);
+       header->log_level_rule_len = payload->buffer.size - size_before_log_level_rule;
+
+end:
+       return ret;
+}
+
+static bool lttng_event_rule_log4j2_logging_is_equal(const struct lttng_event_rule *_a,
+                                                    const struct lttng_event_rule *_b)
+{
+       bool is_equal = false;
+       struct lttng_event_rule_log4j2_logging *a, *b;
+
+       a = lttng::utils::container_of(_a, &lttng_event_rule_log4j2_logging::parent);
+       b = lttng::utils::container_of(_b, &lttng_event_rule_log4j2_logging::parent);
+
+       /* Quick checks. */
+
+       if (!!a->filter_expression != !!b->filter_expression) {
+               goto end;
+       }
+
+       /* Long check. */
+       LTTNG_ASSERT(a->pattern);
+       LTTNG_ASSERT(b->pattern);
+       if (strcmp(a->pattern, b->pattern) != 0) {
+               goto end;
+       }
+
+       if (a->filter_expression && b->filter_expression) {
+               if (strcmp(a->filter_expression, b->filter_expression) != 0) {
+                       goto end;
+               }
+       } else if (!!a->filter_expression != !!b->filter_expression) {
+               /* One is set; not the other. */
+               goto end;
+       }
+
+       if (!lttng_log_level_rule_is_equal(a->log_level_rule, b->log_level_rule)) {
+               goto end;
+       }
+
+       is_equal = true;
+end:
+       return is_equal;
+}
+
+/*
+ * On success ret is 0;
+ *
+ * On error ret is negative.
+ *
+ * An event with NO loglevel and the name is * will return NULL.
+ */
+static int generate_agent_filter(const struct lttng_event_rule *rule, char **_agent_filter)
+{
+       int err;
+       int ret = 0;
+       char *agent_filter = nullptr;
+       const char *pattern;
+       const char *filter;
+       const struct lttng_log_level_rule *log_level_rule = nullptr;
+       enum lttng_event_rule_status status;
+
+       LTTNG_ASSERT(rule);
+       LTTNG_ASSERT(_agent_filter);
+
+       status = lttng_event_rule_log4j2_logging_get_name_pattern(rule, &pattern);
+       if (status != LTTNG_EVENT_RULE_STATUS_OK) {
+               ret = -1;
+               goto end;
+       }
+
+       status = lttng_event_rule_log4j2_logging_get_filter(rule, &filter);
+       if (status == LTTNG_EVENT_RULE_STATUS_UNSET) {
+               filter = nullptr;
+       } else if (status != LTTNG_EVENT_RULE_STATUS_OK) {
+               ret = -1;
+               goto end;
+       }
+
+       /* Don't add filter for the '*' event. */
+       if (strcmp(pattern, "*") != 0) {
+               if (filter) {
+                       err = asprintf(
+                               &agent_filter, "(%s) && (logger_name == \"%s\")", filter, pattern);
+               } else {
+                       err = asprintf(&agent_filter, "logger_name == \"%s\"", pattern);
+               }
+
+               if (err < 0) {
+                       PERROR("Failed to format agent filter string");
+                       ret = -1;
+                       goto end;
+               }
+       }
+
+       status = lttng_event_rule_log4j2_logging_get_log_level_rule(rule, &log_level_rule);
+       if (status == LTTNG_EVENT_RULE_STATUS_OK) {
+               enum lttng_log_level_rule_status llr_status;
+               const char *op;
+               int level;
+
+               switch (lttng_log_level_rule_get_type(log_level_rule)) {
+               case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY:
+                       llr_status = lttng_log_level_rule_exactly_get_level(log_level_rule, &level);
+                       op = "==";
+                       break;
+               case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS:
+                       llr_status = lttng_log_level_rule_at_least_as_severe_as_get_level(
+                               log_level_rule, &level);
+                       op = LTTNG_LOG4J2_EVENT_RULE_AT_LEAST_AS_SEVERE_AS_OP;
+                       break;
+               default:
+                       abort();
+               }
+
+               if (llr_status != LTTNG_LOG_LEVEL_RULE_STATUS_OK) {
+                       ret = -1;
+                       goto end;
+               }
+
+               if (filter || agent_filter) {
+                       char *new_filter;
+
+                       err = asprintf(&new_filter,
+                                      "(%s) && (int_loglevel %s %d)",
+                                      agent_filter ? agent_filter : filter,
+                                      op,
+                                      level);
+                       if (agent_filter) {
+                               free(agent_filter);
+                       }
+                       agent_filter = new_filter;
+               } else {
+                       err = asprintf(&agent_filter, "int_loglevel %s %d", op, level);
+               }
+
+               if (err < 0) {
+                       PERROR("Failed to format agent filter string");
+                       ret = -1;
+                       goto end;
+               }
+       }
+
+       *_agent_filter = agent_filter;
+       agent_filter = nullptr;
+
+end:
+       free(agent_filter);
+       return ret;
+}
+
+static enum lttng_error_code
+lttng_event_rule_log4j2_logging_generate_filter_bytecode(struct lttng_event_rule *rule,
+                                                        const struct lttng_credentials *creds)
+{
+       int ret;
+       enum lttng_error_code ret_code;
+       struct lttng_event_rule_log4j2_logging *log4j2_logging;
+       enum lttng_event_rule_status status;
+       const char *filter;
+       struct lttng_bytecode *bytecode = nullptr;
+       char *agent_filter;
+
+       LTTNG_ASSERT(rule);
+
+       log4j2_logging = lttng::utils::container_of(rule, &lttng_event_rule_log4j2_logging::parent);
+
+       status = lttng_event_rule_log4j2_logging_get_filter(rule, &filter);
+       if (status == LTTNG_EVENT_RULE_STATUS_UNSET) {
+               filter = nullptr;
+       } else if (status != LTTNG_EVENT_RULE_STATUS_OK) {
+               ret_code = LTTNG_ERR_FILTER_INVAL;
+               goto end;
+       }
+
+       if (filter && filter[0] == '\0') {
+               ret_code = LTTNG_ERR_FILTER_INVAL;
+               goto error;
+       }
+
+       ret = generate_agent_filter(rule, &agent_filter);
+       if (ret) {
+               ret_code = LTTNG_ERR_FILTER_INVAL;
+               goto error;
+       }
+
+       log4j2_logging->internal_filter.filter = agent_filter;
+
+       if (log4j2_logging->internal_filter.filter == nullptr) {
+               ret_code = LTTNG_OK;
+               goto end;
+       }
+
+       ret = run_as_generate_filter_bytecode(
+               log4j2_logging->internal_filter.filter, creds, &bytecode);
+       if (ret) {
+               ret_code = LTTNG_ERR_FILTER_INVAL;
+               goto end;
+       }
+
+       log4j2_logging->internal_filter.bytecode = bytecode;
+       bytecode = nullptr;
+       ret_code = LTTNG_OK;
+
+error:
+end:
+       free(bytecode);
+       return ret_code;
+}
+
+static const char *
+lttng_event_rule_log4j2_logging_get_internal_filter(const struct lttng_event_rule *rule)
+{
+       struct lttng_event_rule_log4j2_logging *log4j2_logging;
+
+       LTTNG_ASSERT(rule);
+       log4j2_logging = lttng::utils::container_of(rule, &lttng_event_rule_log4j2_logging::parent);
+       return log4j2_logging->internal_filter.filter;
+}
+
+static const struct lttng_bytecode *
+lttng_event_rule_log4j2_logging_get_internal_filter_bytecode(const struct lttng_event_rule *rule)
+{
+       struct lttng_event_rule_log4j2_logging *log4j2_logging;
+
+       LTTNG_ASSERT(rule);
+       log4j2_logging = lttng::utils::container_of(rule, &lttng_event_rule_log4j2_logging::parent);
+       return log4j2_logging->internal_filter.bytecode;
+}
+
+static enum lttng_event_rule_generate_exclusions_status
+lttng_event_rule_log4j2_logging_generate_exclusions(const struct lttng_event_rule *rule
+                                                   __attribute__((unused)),
+                                                   struct lttng_event_exclusion **_exclusions)
+{
+       /* Unsupported. */
+       *_exclusions = nullptr;
+       return LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE;
+}
+
+static unsigned long lttng_event_rule_log4j2_logging_hash(const struct lttng_event_rule *rule)
+{
+       unsigned long hash;
+       struct lttng_event_rule_log4j2_logging *tp_rule =
+               lttng::utils::container_of(rule, &lttng_event_rule_log4j2_logging::parent);
+
+       hash = hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_LOG4J2_LOGGING, lttng_ht_seed);
+       hash ^= hash_key_str(tp_rule->pattern, lttng_ht_seed);
+
+       if (tp_rule->filter_expression) {
+               hash ^= hash_key_str(tp_rule->filter_expression, lttng_ht_seed);
+       }
+
+       if (tp_rule->log_level_rule) {
+               hash ^= lttng_log_level_rule_hash(tp_rule->log_level_rule);
+       }
+
+       return hash;
+}
+
+static struct lttng_event *
+lttng_event_rule_log4j2_logging_generate_lttng_event(const struct lttng_event_rule *rule)
+{
+       int ret;
+       const struct lttng_event_rule_log4j2_logging *log4j2_logging;
+       struct lttng_event *local_event = nullptr;
+       struct lttng_event *event = nullptr;
+       enum lttng_loglevel_type loglevel_type;
+       int loglevel_value = 0;
+       enum lttng_event_rule_status status;
+       const struct lttng_log_level_rule *log_level_rule;
+
+       log4j2_logging = lttng::utils::container_of(rule, &lttng_event_rule_log4j2_logging::parent);
+
+       local_event = zmalloc<lttng_event>();
+       if (!local_event) {
+               goto error;
+       }
+
+       local_event->type = LTTNG_EVENT_TRACEPOINT;
+       ret = lttng_strncpy(local_event->name, log4j2_logging->pattern, sizeof(local_event->name));
+       if (ret) {
+               ERR("Truncation occurred when copying event rule pattern to `lttng_event` structure: pattern = '%s'",
+                   log4j2_logging->pattern);
+               goto error;
+       }
+
+       /* Map the log level rule to an equivalent lttng_loglevel. */
+       status = lttng_event_rule_log4j2_logging_get_log_level_rule(rule, &log_level_rule);
+       if (status == LTTNG_EVENT_RULE_STATUS_UNSET) {
+               loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL;
+               loglevel_value = LTTNG_LOGLEVEL_LOG4J2_ALL;
+       } else if (status == LTTNG_EVENT_RULE_STATUS_OK) {
+               enum lttng_log_level_rule_status llr_status;
+
+               switch (lttng_log_level_rule_get_type(log_level_rule)) {
+               case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY:
+                       llr_status = lttng_log_level_rule_exactly_get_level(log_level_rule,
+                                                                           &loglevel_value);
+                       loglevel_type = LTTNG_EVENT_LOGLEVEL_SINGLE;
+                       break;
+               case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS:
+                       llr_status = lttng_log_level_rule_at_least_as_severe_as_get_level(
+                               log_level_rule, &loglevel_value);
+                       loglevel_type = LTTNG_EVENT_LOGLEVEL_RANGE;
+                       break;
+               default:
+                       abort();
+                       break;
+               }
+
+               if (llr_status != LTTNG_LOG_LEVEL_RULE_STATUS_OK) {
+                       goto error;
+               }
+       } else {
+               goto error;
+       }
+
+       local_event->loglevel_type = loglevel_type;
+       local_event->loglevel = loglevel_value;
+
+       event = local_event;
+       local_event = nullptr;
+error:
+       free(local_event);
+       return event;
+}
+
+static enum lttng_error_code
+lttng_event_rule_log4j2_logging_mi_serialize(const struct lttng_event_rule *rule,
+                                            struct mi_writer *writer)
+{
+       int ret;
+       enum lttng_error_code ret_code;
+       enum lttng_event_rule_status status;
+       const char *filter = nullptr;
+       const char *name_pattern = nullptr;
+       const struct lttng_log_level_rule *log_level_rule = nullptr;
+
+       LTTNG_ASSERT(rule);
+       LTTNG_ASSERT(writer);
+       LTTNG_ASSERT(IS_LOG4J2_LOGGING_EVENT_RULE(rule));
+
+       status = lttng_event_rule_log4j2_logging_get_name_pattern(rule, &name_pattern);
+       LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
+       LTTNG_ASSERT(name_pattern);
+
+       status = lttng_event_rule_log4j2_logging_get_filter(rule, &filter);
+       LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK ||
+                    status == LTTNG_EVENT_RULE_STATUS_UNSET);
+
+       status = lttng_event_rule_log4j2_logging_get_log_level_rule(rule, &log_level_rule);
+       LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK ||
+                    status == LTTNG_EVENT_RULE_STATUS_UNSET);
+
+       /* Open event rule log4j2 logging element. */
+       ret = mi_lttng_writer_open_element(writer, mi_lttng_element_event_rule_log4j2_logging);
+       if (ret) {
+               goto mi_error;
+       }
+
+       /* Name pattern. */
+       ret = mi_lttng_writer_write_element_string(
+               writer, mi_lttng_element_event_rule_name_pattern, name_pattern);
+       if (ret) {
+               goto mi_error;
+       }
+
+       /* Filter expression. */
+       if (filter != nullptr) {
+               ret = mi_lttng_writer_write_element_string(
+                       writer, mi_lttng_element_event_rule_filter_expression, filter);
+               if (ret) {
+                       goto mi_error;
+               }
+       }
+
+       /* Log level rule. */
+       if (log_level_rule) {
+               ret_code = lttng_log_level_rule_mi_serialize(log_level_rule, writer);
+               if (ret_code != LTTNG_OK) {
+                       goto end;
+               }
+       }
+
+       /* Close event rule log4j2 logging element. */
+       ret = mi_lttng_writer_close_element(writer);
+       if (ret) {
+               goto mi_error;
+       }
+
+       ret_code = LTTNG_OK;
+       goto end;
+
+mi_error:
+       ret_code = LTTNG_ERR_MI_IO_FAIL;
+end:
+       return ret_code;
+}
+
+struct lttng_event_rule *lttng_event_rule_log4j2_logging_create(void)
+{
+       struct lttng_event_rule *rule = nullptr;
+       struct lttng_event_rule_log4j2_logging *tp_rule;
+       enum lttng_event_rule_status status;
+
+       tp_rule = zmalloc<lttng_event_rule_log4j2_logging>();
+       if (!tp_rule) {
+               goto end;
+       }
+
+       rule = &tp_rule->parent;
+       lttng_event_rule_init(&tp_rule->parent, LTTNG_EVENT_RULE_TYPE_LOG4J2_LOGGING);
+       tp_rule->parent.validate = lttng_event_rule_log4j2_logging_validate;
+       tp_rule->parent.serialize = lttng_event_rule_log4j2_logging_serialize;
+       tp_rule->parent.equal = lttng_event_rule_log4j2_logging_is_equal;
+       tp_rule->parent.destroy = lttng_event_rule_log4j2_logging_destroy;
+       tp_rule->parent.generate_filter_bytecode =
+               lttng_event_rule_log4j2_logging_generate_filter_bytecode;
+       tp_rule->parent.get_filter = lttng_event_rule_log4j2_logging_get_internal_filter;
+       tp_rule->parent.get_filter_bytecode =
+               lttng_event_rule_log4j2_logging_get_internal_filter_bytecode;
+       tp_rule->parent.generate_exclusions = lttng_event_rule_log4j2_logging_generate_exclusions;
+       tp_rule->parent.hash = lttng_event_rule_log4j2_logging_hash;
+       tp_rule->parent.generate_lttng_event = lttng_event_rule_log4j2_logging_generate_lttng_event;
+       tp_rule->parent.mi_serialize = lttng_event_rule_log4j2_logging_mi_serialize;
+
+       tp_rule->log_level_rule = nullptr;
+
+       /* Default pattern is '*'. */
+       status = lttng_event_rule_log4j2_logging_set_name_pattern(rule, "*");
+       if (status != LTTNG_EVENT_RULE_STATUS_OK) {
+               lttng_event_rule_destroy(rule);
+               rule = nullptr;
+       }
+
+end:
+       return rule;
+}
+
+ssize_t lttng_event_rule_log4j2_logging_create_from_payload(struct lttng_payload_view *view,
+                                                           struct lttng_event_rule **_event_rule)
+{
+       ssize_t ret, offset = 0;
+       enum lttng_event_rule_status status;
+       const struct lttng_event_rule_log4j2_logging_comm *log4j2_logging_comm;
+       const char *pattern;
+       const char *filter_expression = nullptr;
+       struct lttng_buffer_view current_buffer_view;
+       struct lttng_event_rule *rule = nullptr;
+       struct lttng_log_level_rule *log_level_rule = nullptr;
+
+       if (!_event_rule) {
+               ret = -1;
+               goto end;
+       }
+
+       current_buffer_view =
+               lttng_buffer_view_from_view(&view->buffer, offset, sizeof(*log4j2_logging_comm));
+       if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
+               ERR("Failed to initialize from malformed event rule log4j2_logging: buffer too short to contain header.");
+               ret = -1;
+               goto end;
+       }
+
+       log4j2_logging_comm = (typeof(log4j2_logging_comm)) current_buffer_view.data;
+
+       rule = lttng_event_rule_log4j2_logging_create();
+       if (!rule) {
+               ERR("Failed to create event rule log4j2_logging.");
+               ret = -1;
+               goto end;
+       }
+
+       /* Skip to payload. */
+       offset += current_buffer_view.size;
+
+       /* Map the pattern. */
+       current_buffer_view = lttng_buffer_view_from_view(
+               &view->buffer, offset, log4j2_logging_comm->pattern_len);
+
+       if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
+               ret = -1;
+               goto end;
+       }
+
+       pattern = current_buffer_view.data;
+       if (!lttng_buffer_view_contains_string(
+                   &current_buffer_view, pattern, log4j2_logging_comm->pattern_len)) {
+               ret = -1;
+               goto end;
+       }
+
+       /* Skip after the pattern. */
+       offset += log4j2_logging_comm->pattern_len;
+
+       if (!log4j2_logging_comm->filter_expression_len) {
+               goto skip_filter_expression;
+       }
+
+       /* Map the filter_expression. */
+       current_buffer_view = lttng_buffer_view_from_view(
+               &view->buffer, offset, log4j2_logging_comm->filter_expression_len);
+       if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
+               ret = -1;
+               goto end;
+       }
+
+       filter_expression = current_buffer_view.data;
+       if (!lttng_buffer_view_contains_string(&current_buffer_view,
+                                              filter_expression,
+                                              log4j2_logging_comm->filter_expression_len)) {
+               ret = -1;
+               goto end;
+       }
+
+       /* Skip after the pattern. */
+       offset += log4j2_logging_comm->filter_expression_len;
+
+skip_filter_expression:
+       if (!log4j2_logging_comm->log_level_rule_len) {
+               goto skip_log_level_rule;
+       }
+
+       {
+               /* Map the log level rule. */
+               struct lttng_payload_view current_payload_view = lttng_payload_view_from_view(
+                       view, offset, log4j2_logging_comm->log_level_rule_len);
+
+               ret = lttng_log_level_rule_create_from_payload(&current_payload_view,
+                                                              &log_level_rule);
+               if (ret < 0) {
+                       ret = -1;
+                       goto end;
+               }
+
+               LTTNG_ASSERT(ret == log4j2_logging_comm->log_level_rule_len);
+       }
+
+       /* Skip after the log level rule. */
+       offset += log4j2_logging_comm->log_level_rule_len;
+
+skip_log_level_rule:
+
+       status = lttng_event_rule_log4j2_logging_set_name_pattern(rule, pattern);
+       if (status != LTTNG_EVENT_RULE_STATUS_OK) {
+               ERR("Failed to set event rule log4j2_logging pattern.");
+               ret = -1;
+               goto end;
+       }
+
+       if (filter_expression) {
+               status = lttng_event_rule_log4j2_logging_set_filter(rule, filter_expression);
+               if (status != LTTNG_EVENT_RULE_STATUS_OK) {
+                       ERR("Failed to set event rule log4j2_logging pattern.");
+                       ret = -1;
+                       goto end;
+               }
+       }
+
+       if (log_level_rule) {
+               status = lttng_event_rule_log4j2_logging_set_log_level_rule(rule, log_level_rule);
+               if (status != LTTNG_EVENT_RULE_STATUS_OK) {
+                       ERR("Failed to set event rule log4j2_logging log level rule.");
+                       ret = -1;
+                       goto end;
+               }
+       }
+
+       *_event_rule = rule;
+       rule = nullptr;
+       ret = offset;
+end:
+       lttng_log_level_rule_destroy(log_level_rule);
+       lttng_event_rule_destroy(rule);
+       return ret;
+}
+
+enum lttng_event_rule_status
+lttng_event_rule_log4j2_logging_set_name_pattern(struct lttng_event_rule *rule, const char *pattern)
+{
+       char *pattern_copy = nullptr;
+       struct lttng_event_rule_log4j2_logging *log4j2_logging;
+       enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
+
+       if (!rule || !IS_LOG4J2_LOGGING_EVENT_RULE(rule) || !pattern || strlen(pattern) == 0) {
+               status = LTTNG_EVENT_RULE_STATUS_INVALID;
+               goto end;
+       }
+
+       log4j2_logging = lttng::utils::container_of(rule, &lttng_event_rule_log4j2_logging::parent);
+       pattern_copy = strdup(pattern);
+       if (!pattern_copy) {
+               status = LTTNG_EVENT_RULE_STATUS_ERROR;
+               goto end;
+       }
+
+       /* Normalize the pattern. */
+       strutils_normalize_star_glob_pattern(pattern_copy);
+
+       free(log4j2_logging->pattern);
+
+       log4j2_logging->pattern = pattern_copy;
+       pattern_copy = nullptr;
+end:
+       return status;
+}
+
+enum lttng_event_rule_status
+lttng_event_rule_log4j2_logging_get_name_pattern(const struct lttng_event_rule *rule,
+                                                const char **pattern)
+{
+       struct lttng_event_rule_log4j2_logging *log4j2_logging;
+       enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
+
+       if (!rule || !IS_LOG4J2_LOGGING_EVENT_RULE(rule) || !pattern) {
+               status = LTTNG_EVENT_RULE_STATUS_INVALID;
+               goto end;
+       }
+
+       log4j2_logging = lttng::utils::container_of(rule, &lttng_event_rule_log4j2_logging::parent);
+       if (!log4j2_logging->pattern) {
+               status = LTTNG_EVENT_RULE_STATUS_UNSET;
+               goto end;
+       }
+
+       *pattern = log4j2_logging->pattern;
+end:
+       return status;
+}
+
+enum lttng_event_rule_status
+lttng_event_rule_log4j2_logging_set_filter(struct lttng_event_rule *rule, const char *expression)
+{
+       char *expression_copy = nullptr;
+       struct lttng_event_rule_log4j2_logging *log4j2_logging;
+       enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
+
+       if (!rule || !IS_LOG4J2_LOGGING_EVENT_RULE(rule) || !expression ||
+           strlen(expression) == 0) {
+               status = LTTNG_EVENT_RULE_STATUS_INVALID;
+               goto end;
+       }
+
+       log4j2_logging = lttng::utils::container_of(rule, &lttng_event_rule_log4j2_logging::parent);
+       expression_copy = strdup(expression);
+       if (!expression_copy) {
+               PERROR("Failed to copy filter expression");
+               status = LTTNG_EVENT_RULE_STATUS_ERROR;
+               goto end;
+       }
+
+       if (log4j2_logging->filter_expression) {
+               free(log4j2_logging->filter_expression);
+       }
+
+       log4j2_logging->filter_expression = expression_copy;
+       expression_copy = nullptr;
+end:
+       return status;
+}
+
+enum lttng_event_rule_status
+lttng_event_rule_log4j2_logging_get_filter(const struct lttng_event_rule *rule,
+                                          const char **expression)
+{
+       struct lttng_event_rule_log4j2_logging *log4j2_logging;
+       enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
+
+       if (!rule || !IS_LOG4J2_LOGGING_EVENT_RULE(rule) || !expression) {
+               status = LTTNG_EVENT_RULE_STATUS_INVALID;
+               goto end;
+       }
+
+       log4j2_logging = lttng::utils::container_of(rule, &lttng_event_rule_log4j2_logging::parent);
+       if (!log4j2_logging->filter_expression) {
+               status = LTTNG_EVENT_RULE_STATUS_UNSET;
+               goto end;
+       }
+
+       *expression = log4j2_logging->filter_expression;
+end:
+       return status;
+}
+
+static bool log_level_rule_valid(const struct lttng_log_level_rule *rule)
+{
+       /*
+        * LOG4J2 custom log levels are possible and can range from 0 to
+        * int32_max.
+        */
+       return (rule->level >= 0);
+}
+
+enum lttng_event_rule_status lttng_event_rule_log4j2_logging_set_log_level_rule(
+       struct lttng_event_rule *rule, const struct lttng_log_level_rule *log_level_rule)
+{
+       struct lttng_event_rule_log4j2_logging *log4j2_logging;
+       enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
+       struct lttng_log_level_rule *copy = nullptr;
+
+       if (!rule || !IS_LOG4J2_LOGGING_EVENT_RULE(rule)) {
+               status = LTTNG_EVENT_RULE_STATUS_INVALID;
+               goto end;
+       }
+
+       log4j2_logging = lttng::utils::container_of(rule, &lttng_event_rule_log4j2_logging::parent);
+
+       if (!log_level_rule_valid(log_level_rule)) {
+               status = LTTNG_EVENT_RULE_STATUS_INVALID;
+               goto end;
+       }
+
+       copy = lttng_log_level_rule_copy(log_level_rule);
+       if (copy == nullptr) {
+               status = LTTNG_EVENT_RULE_STATUS_ERROR;
+               goto end;
+       }
+
+       if (log4j2_logging->log_level_rule) {
+               lttng_log_level_rule_destroy(log4j2_logging->log_level_rule);
+       }
+
+       log4j2_logging->log_level_rule = copy;
+
+end:
+       return status;
+}
+
+enum lttng_event_rule_status lttng_event_rule_log4j2_logging_get_log_level_rule(
+       const struct lttng_event_rule *rule, const struct lttng_log_level_rule **log_level_rule)
+{
+       struct lttng_event_rule_log4j2_logging *log4j2_logging;
+       enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
+
+       if (!rule || !IS_LOG4J2_LOGGING_EVENT_RULE(rule) || !log_level_rule) {
+               status = LTTNG_EVENT_RULE_STATUS_INVALID;
+               goto end;
+       }
+
+       log4j2_logging = lttng::utils::container_of(rule, &lttng_event_rule_log4j2_logging::parent);
+       if (log4j2_logging->log_level_rule == nullptr) {
+               status = LTTNG_EVENT_RULE_STATUS_UNSET;
+               goto end;
+       }
+
+       *log_level_rule = log4j2_logging->log_level_rule;
+end:
+       return status;
+}
index 7d68b2e8eb9332efe3b90e4948919ffb4a895d8e..4ebb2574d441533956e68df8c0583d96353941bf 100644 (file)
@@ -170,6 +170,14 @@ SPDX-License-Identifier: MIT
                        <xs:enumeration value="LOG4J_DEBUG" />
                        <xs:enumeration value="LOG4J_TRACE" />
                        <xs:enumeration value="LOG4J_ALL" />
+                       <xs:enumeration value="LOG4J2_OFF" />
+                       <xs:enumeration value="LOG4J2_FATAL" />
+                       <xs:enumeration value="LOG4J2_ERROR" />
+                       <xs:enumeration value="LOG4J2_WARN" />
+                       <xs:enumeration value="LOG4J2_INFO" />
+                       <xs:enumeration value="LOG4J2_DEBUG" />
+                       <xs:enumeration value="LOG4J2_TRACE" />
+                       <xs:enumeration value="LOG4J2_ALL" />
                        <xs:enumeration value="PYTHON_CRITICAL" />
                        <xs:enumeration value="PYTHON_ERROR" />
                        <xs:enumeration value="PYTHON_WARNING" />
@@ -305,6 +313,7 @@ SPDX-License-Identifier: MIT
                        <xs:enumeration value="UST"/>
                        <xs:enumeration value="JUL"/>
                        <xs:enumeration value="LOG4J"/>
+                       <xs:enumeration value="LOG4J2"/>
                        <xs:enumeration value="PYTHON"/>
                </xs:restriction>
        </xs:simpleType>
@@ -1068,6 +1077,7 @@ SPDX-License-Identifier: MIT
        <xs:element name="event_rule_kernel_tracepoint" type="tns:event_rule_kernel_tracepoint_type" substitutionGroup="tns:event_rule_sub_type" />
        <xs:element name="event_rule_kernel_uprobe" type="tns:event_rule_kernel_uprobe_type" substitutionGroup="tns:event_rule_sub_type" />
        <xs:element name="event_rule_log4j_logging" type="tns:event_rule_logging_type" substitutionGroup="tns:event_rule_sub_type" />
+       <xs:element name="event_rule_log4j2_logging" type="tns:event_rule_logging_type" substitutionGroup="tns:event_rule_sub_type" />
        <xs:element name="event_rule_python_logging" type="tns:event_rule_logging_type" substitutionGroup="tns:event_rule_sub_type" />
        <xs:element name="event_rule_user_tracepoint" type="tns:event_rule_user_tracepoint_type" substitutionGroup="tns:event_rule_sub_type" />
 
index d7833fcd5d871d3e5d46d23d77f0f6d5bc34bfa4..c82b3ee984c75b08d9764f0ab0efb263b3e5a983 100644 (file)
@@ -151,6 +151,16 @@ const char *const mi_lttng_loglevel_str_log4j_debug = "LOG4J_DEBUG";
 const char *const mi_lttng_loglevel_str_log4j_trace = "LOG4J_TRACE";
 const char *const mi_lttng_loglevel_str_log4j_all = "LOG4J_ALL";
 
+/* String related to loglevel LOG4J2 */
+const char *const mi_lttng_loglevel_str_log4j2_off = "LOG4J2_OFF";
+const char *const mi_lttng_loglevel_str_log4j2_fatal = "LOG4J2_FATAL";
+const char *const mi_lttng_loglevel_str_log4j2_error = "LOG4J2_ERROR";
+const char *const mi_lttng_loglevel_str_log4j2_warn = "LOG4J2_WARN";
+const char *const mi_lttng_loglevel_str_log4j2_info = "LOG4J2_INFO";
+const char *const mi_lttng_loglevel_str_log4j2_debug = "LOG4J2_DEBUG";
+const char *const mi_lttng_loglevel_str_log4j2_trace = "LOG4J2_TRACE";
+const char *const mi_lttng_loglevel_str_log4j2_all = "LOG4J2_ALL";
+
 /* String related to loglevel Python */
 const char *const mi_lttng_loglevel_str_python_critical = "PYTHON_CRITICAL";
 const char *const mi_lttng_loglevel_str_python_error = "PYTHON_ERROR";
@@ -275,6 +285,7 @@ const char *const mi_lttng_element_event_rule_kernel_syscall = "event_rule_kerne
 const char *const mi_lttng_element_event_rule_kernel_tracepoint = "event_rule_kernel_tracepoint";
 const char *const mi_lttng_element_event_rule_kernel_uprobe = "event_rule_kernel_uprobe";
 const char *const mi_lttng_element_event_rule_log4j_logging = "event_rule_log4j_logging";
+const char *const mi_lttng_element_event_rule_log4j2_logging = "event_rule_log4j2_logging";
 const char *const mi_lttng_element_event_rule_python_logging = "event_rule_python_logging";
 const char *const mi_lttng_element_event_rule_user_tracepoint = "event_rule_user_tracepoint";
 
@@ -432,6 +443,30 @@ const char *mi_lttng_loglevel_string(int value, enum lttng_domain_type domain)
                        return mi_lttng_loglevel_str_unknown;
                }
                break;
+       case LTTNG_DOMAIN_LOG4J2:
+               switch (value) {
+               case -1:
+                       return mi_lttng_element_empty;
+               case LTTNG_LOGLEVEL_LOG4J2_OFF:
+                       return mi_lttng_loglevel_str_log4j2_off;
+               case LTTNG_LOGLEVEL_LOG4J2_FATAL:
+                       return mi_lttng_loglevel_str_log4j2_fatal;
+               case LTTNG_LOGLEVEL_LOG4J2_ERROR:
+                       return mi_lttng_loglevel_str_log4j2_error;
+               case LTTNG_LOGLEVEL_LOG4J2_WARN:
+                       return mi_lttng_loglevel_str_log4j2_warn;
+               case LTTNG_LOGLEVEL_LOG4J2_INFO:
+                       return mi_lttng_loglevel_str_log4j2_info;
+               case LTTNG_LOGLEVEL_LOG4J2_DEBUG:
+                       return mi_lttng_loglevel_str_log4j2_debug;
+               case LTTNG_LOGLEVEL_LOG4J2_TRACE:
+                       return mi_lttng_loglevel_str_log4j2_trace;
+               case LTTNG_LOGLEVEL_LOG4J2_ALL:
+                       return mi_lttng_loglevel_str_log4j2_all;
+               default:
+                       return mi_lttng_loglevel_str_unknown;
+               }
+               break;
        case LTTNG_DOMAIN_JUL:
                switch (value) {
                case -1:
@@ -630,6 +665,8 @@ const char *mi_lttng_domaintype_string(enum lttng_domain_type value)
                return config_domain_type_jul;
        case LTTNG_DOMAIN_LOG4J:
                return config_domain_type_log4j;
+       case LTTNG_DOMAIN_LOG4J2:
+               return config_domain_type_log4j2;
        case LTTNG_DOMAIN_PYTHON:
                return config_domain_type_python;
        default:
index 10a3e13f509afc5a7b72289c85e1d9438210980b..0ab5abc1b878208d8e866e5468ae4f13dfb066bb 100644 (file)
@@ -173,6 +173,16 @@ LTTNG_EXPORT extern const char *const mi_lttng_loglevel_str_log4j_debug;
 LTTNG_EXPORT extern const char *const mi_lttng_loglevel_str_log4j_trace;
 LTTNG_EXPORT extern const char *const mi_lttng_loglevel_str_log4j_all;
 
+/* String related to loglevel Log4j2 */
+extern const char *const mi_lttng_loglevel_str_log4j2_off;
+extern const char *const mi_lttng_loglevel_str_log4j2_fatal;
+extern const char *const mi_lttng_loglevel_str_log4j2_error;
+extern const char *const mi_lttng_loglevel_str_log4j2_warn;
+extern const char *const mi_lttng_loglevel_str_log4j2_info;
+extern const char *const mi_lttng_loglevel_str_log4j2_debug;
+extern const char *const mi_lttng_loglevel_str_log4j2_trace;
+extern const char *const mi_lttng_loglevel_str_log4j2_all;
+
 /* String related to loglevel Python */
 LTTNG_EXPORT extern const char *const mi_lttng_loglevel_str_python_critical;
 LTTNG_EXPORT extern const char *const mi_lttng_loglevel_str_python_error;
@@ -290,6 +300,7 @@ extern const char *const mi_lttng_element_event_rule_kernel_syscall;
 extern const char *const mi_lttng_element_event_rule_kernel_tracepoint;
 extern const char *const mi_lttng_element_event_rule_kernel_uprobe;
 extern const char *const mi_lttng_element_event_rule_log4j_logging;
+extern const char *const mi_lttng_element_event_rule_log4j2_logging;
 extern const char *const mi_lttng_element_event_rule_python_logging;
 extern const char *const mi_lttng_element_event_rule_user_tracepoint;
 
index 986fb2dda175a8df19f3cec1be20264ab92e4052..20e4cfe542acf9696072aacb95156e09cd0f52a2 100644 (file)
@@ -235,6 +235,7 @@ by its signed 32-bit representation when converted to msec.
                <xs:enumeration value="UST"/>
                <xs:enumeration value="JUL"/>
                <xs:enumeration value="LOG4J"/>
+               <xs:enumeration value="LOG4J2"/>
                <xs:enumeration value="PYTHON"/>
        </xs:restriction>
 </xs:simpleType>
index 3bd9efb76cc2c64f895d1205ae4c29b0005fb899..ff1aa823de0ddd995bd41a49c8b87c8098fc60f2 100644 (file)
@@ -4,6 +4,7 @@ config_buffer_type_per_uid
 config_domain_type_jul
 config_domain_type_kernel
 config_domain_type_log4j
+config_domain_type_log4j2
 config_domain_type_python
 config_domain_type_ust
 config_element_address
@@ -293,6 +294,13 @@ lttng_event_rule_log4j_logging_get_name_pattern
 lttng_event_rule_log4j_logging_set_filter
 lttng_event_rule_log4j_logging_set_log_level_rule
 lttng_event_rule_log4j_logging_set_name_pattern
+lttng_event_rule_log4j2_logging_create
+lttng_event_rule_log4j2_logging_get_filter
+lttng_event_rule_log4j2_logging_get_log_level_rule
+lttng_event_rule_log4j2_logging_get_name_pattern
+lttng_event_rule_log4j2_logging_set_filter
+lttng_event_rule_log4j2_logging_set_log_level_rule
+lttng_event_rule_log4j2_logging_set_name_pattern
 lttng_event_rule_python_logging_create
 lttng_event_rule_python_logging_get_filter
 lttng_event_rule_python_logging_get_log_level_rule
index 5057b75eff17abebc3d2d9c9ff2b29e08b078670..c5c04c262870711d573ea64c72e674a9979725c4 100644 (file)
@@ -93,6 +93,7 @@ void lttng_ctl_copy_lttng_domain(struct lttng_domain *dst, struct lttng_domain *
                case LTTNG_DOMAIN_UST:
                case LTTNG_DOMAIN_JUL:
                case LTTNG_DOMAIN_LOG4J:
+               case LTTNG_DOMAIN_LOG4J2:
                case LTTNG_DOMAIN_PYTHON:
                        memcpy(dst, src, sizeof(struct lttng_domain));
                        break;
@@ -1011,12 +1012,14 @@ int lttng_enable_event_with_filter(struct lttng_handle *handle,
  *
  * An event with NO loglevel and the name is * will return NULL.
  */
-static char *set_agent_filter(const char *filter, struct lttng_event *ev)
+static char *
+set_agent_filter(const char *filter, struct lttng_event *ev, struct lttng_domain *domain)
 {
        int err;
        char *agent_filter = nullptr;
 
        LTTNG_ASSERT(ev);
+       LTTNG_ASSERT(domain);
 
        /* Don't add filter for the '*' event. */
        if (strcmp(ev->name, "*") != 0) {
@@ -1032,12 +1035,20 @@ static char *set_agent_filter(const char *filter, struct lttng_event *ev)
                }
        }
 
-       /* Add loglevel filtering if any for the JUL domain. */
+       /* Add loglevel filtering if any for the agent domains. */
        if (ev->loglevel_type != LTTNG_EVENT_LOGLEVEL_ALL) {
                const char *op;
 
                if (ev->loglevel_type == LTTNG_EVENT_LOGLEVEL_RANGE) {
-                       op = ">=";
+                       /*
+                        * Log4j2 is the only agent domain for which more severe
+                        * logging levels have a lower numerical value.
+                        */
+                       if (domain->type == LTTNG_DOMAIN_LOG4J2) {
+                               op = "<=";
+                       } else {
+                               op = ">=";
+                       }
                } else {
                        op = "==";
                }
@@ -1134,18 +1145,20 @@ int lttng_enable_event_with_exclusions(struct lttng_handle *handle,
        /* Parse filter expression. */
        if (filter_expression != nullptr || handle->domain.type == LTTNG_DOMAIN_JUL ||
            handle->domain.type == LTTNG_DOMAIN_LOG4J ||
+           handle->domain.type == LTTNG_DOMAIN_LOG4J2 ||
            handle->domain.type == LTTNG_DOMAIN_PYTHON) {
                if (handle->domain.type == LTTNG_DOMAIN_JUL ||
                    handle->domain.type == LTTNG_DOMAIN_LOG4J ||
+                   handle->domain.type == LTTNG_DOMAIN_LOG4J2 ||
                    handle->domain.type == LTTNG_DOMAIN_PYTHON) {
                        char *agent_filter;
 
                        /* Setup agent filter if needed. */
-                       agent_filter = set_agent_filter(filter_expression, ev);
+                       agent_filter = set_agent_filter(filter_expression, ev, &handle->domain);
                        if (!agent_filter) {
                                if (!filter_expression) {
                                        /*
-                                        * No JUL and no filter, just skip
+                                        * No agent and no filter, just skip
                                         * everything below.
                                         */
                                        goto serialize;
@@ -1317,14 +1330,16 @@ int lttng_disable_event_ext(struct lttng_handle *handle,
        /* Parse filter expression. */
        if (filter_expression != nullptr || handle->domain.type == LTTNG_DOMAIN_JUL ||
            handle->domain.type == LTTNG_DOMAIN_LOG4J ||
+           handle->domain.type == LTTNG_DOMAIN_LOG4J2 ||
            handle->domain.type == LTTNG_DOMAIN_PYTHON) {
                if (handle->domain.type == LTTNG_DOMAIN_JUL ||
                    handle->domain.type == LTTNG_DOMAIN_LOG4J ||
+                   handle->domain.type == LTTNG_DOMAIN_LOG4J2 ||
                    handle->domain.type == LTTNG_DOMAIN_PYTHON) {
                        char *agent_filter;
 
                        /* Setup agent filter if needed. */
-                       agent_filter = set_agent_filter(filter_expression, ev);
+                       agent_filter = set_agent_filter(filter_expression, ev, &handle->domain);
                        if (!agent_filter) {
                                if (!filter_expression) {
                                        /*
This page took 0.063903 seconds and 4 git commands to generate.