2 * SPDX-License-Identifier: LGPL-2.1-only
4 * Copyright (C) 2015-2022 EfficiOS Inc.
5 * Copyright (C) 2015 Alexandre Montplaisir <alexmonthy@efficios.com>
8 package org
.lttng
.ust
.agent
.log4j2
;
10 import java
.util
.Collection
;
13 import java
.util
.TreeSet
;
15 import org
.apache
.logging
.log4j
.LogManager
;
16 import org
.apache
.logging
.log4j
.core
.Appender
;
17 import org
.apache
.logging
.log4j
.core
.Logger
;
18 import org
.apache
.logging
.log4j
.core
.LoggerContext
;
19 import org
.apache
.logging
.log4j
.core
.impl
.Log4jContextFactory
;
20 import org
.apache
.logging
.log4j
.core
.selector
.ContextSelector
;
21 import org
.apache
.logging
.log4j
.spi
.LoggerContextFactory
;
22 import org
.apache
.logging
.log4j
.status
.StatusLogger
;
23 import org
.lttng
.ust
.agent
.AbstractLttngAgent
;
26 * Agent implementation for Log4j 2.x.
28 class LttngLog4j2Agent
extends AbstractLttngAgent
<LttngLogAppender
> {
30 private static LttngLog4j2Agent log4j2_instance
= null;
31 private static LttngLog4j2Agent log4j1_instance
= null;
33 private LttngLog4j2Agent(Domain domain
) {
37 public static synchronized LttngLog4j2Agent
getLog4j1Instance() {
38 if (log4j1_instance
== null) {
39 log4j1_instance
= new LttngLog4j2Agent(Domain
.LOG4J
);
41 return log4j1_instance
;
44 public static synchronized LttngLog4j2Agent
getLog4j2Instance() {
45 if (log4j2_instance
== null) {
46 log4j2_instance
= new LttngLog4j2Agent(Domain
.LOG4J2
);
48 return log4j2_instance
;
52 public Collection
<String
> listAvailableEvents() {
53 Set
<String
> eventNames
= new TreeSet
<>();
55 LoggerContextFactory contextFactory
= LogManager
.getFactory();
56 if (!(contextFactory
instanceof Log4jContextFactory
)) {
57 /* Using a custom ContextFactory is not supported. */
58 StatusLogger
.getLogger().error("Can't list events with custom ContextFactory");
62 ContextSelector selector
= ((Log4jContextFactory
) contextFactory
).getSelector();
64 for (LoggerContext logContext
: selector
.getLoggerContexts()) {
65 Collection
<?
extends Logger
> loggers
= logContext
.getLoggers();
66 for (Logger logger
: loggers
) {
68 * Check if that logger has at least one LTTng log4j appender attached.
70 if (hasLttngAppenderAttached(logger
)) {
71 eventNames
.add(logger
.getName());
79 * Check if a logger has an LttngLogAppender attached.
81 * @param logger the Logger to check, null returns false
82 * @return true if the logger or its parent has at least one LttngLogAppender attached
84 private static boolean hasLttngAppenderAttached(Logger logger
) {
91 * Check all the appenders associated with the logger and return true if one of
92 * them is an LttngLogAppender.
94 Map
<String
, Appender
> appenders
= logger
.getAppenders();
95 for (Map
.Entry
<String
, Appender
> appender
: appenders
.entrySet()) {
96 if (appender
.getValue() instanceof LttngLogAppender
) {
102 * A parent logger, if any, may be connected to an LTTng handler. In this case,
103 * we will want to include this child logger in the output, since it will be
104 * accessible by LTTng.
106 * Despite the doc, getParent can return null based on the implementation as of
109 * The getParent function is there as a backward compat for 1.x. It is not clear
110 * in which context it should be used. The cost of doing the lookup is minimal
111 * and mimics what was done for the 1.x agent.
113 return hasLttngAppenderAttached(logger
.getParent());