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 instance
= null;
32 private LttngLog4j2Agent() {
36 public static synchronized LttngLog4j2Agent
getInstance() {
37 if (instance
== null) {
38 instance
= new LttngLog4j2Agent();
44 public Collection
<String
> listAvailableEvents() {
45 Set
<String
> eventNames
= new TreeSet
<>();
47 LoggerContextFactory contextFactory
= LogManager
.getFactory();
48 if (!(contextFactory
instanceof Log4jContextFactory
)) {
49 /* Using a custom ContextFactory is not supported. */
50 StatusLogger
.getLogger().error("Can't list events with custom ContextFactory");
54 ContextSelector selector
= ((Log4jContextFactory
) contextFactory
).getSelector();
56 for (LoggerContext logContext
: selector
.getLoggerContexts()) {
57 Collection
<?
extends Logger
> loggers
= logContext
.getLoggers();
58 for (Logger logger
: loggers
) {
60 * Check if that logger has at least one LTTng log4j appender attached.
62 if (hasLttngAppenderAttached(logger
)) {
63 eventNames
.add(logger
.getName());
71 * Check if a logger has an LttngLogAppender attached.
73 * @param logger the Logger to check, null returns false
74 * @return true if the logger or its parent has at least one LttngLogAppender attached
76 private static boolean hasLttngAppenderAttached(Logger logger
) {
83 * Check all the appenders associated with the logger and return true if one of
84 * them is an LttngLogAppender.
86 Map
<String
, Appender
> appenders
= logger
.getAppenders();
87 for (Map
.Entry
<String
, Appender
> appender
: appenders
.entrySet()) {
88 if (appender
.getValue() instanceof LttngLogAppender
) {
94 * A parent logger, if any, may be connected to an LTTng handler. In this case,
95 * we will want to include this child logger in the output, since it will be
96 * accessible by LTTng.
98 * Despite the doc, getParent can return null based on the implementation as of
101 * The getParent function is there as a backward compat for 1.x. It is not clear
102 * in which context it should be used. The cost of doing the lookup is minimal
103 * and mimics what was done for the 1.x agent.
105 return hasLttngAppenderAttached(logger
.getParent());