Add LOG4J2 domain to the Log4j 2.x agent
[lttng-ust.git] / src / lib / lttng-ust-java-agent / java / lttng-ust-agent-log4j2 / org / lttng / ust / agent / log4j2 / LttngLogAppender.java
CommitLineData
464c4756
MJ
1/*
2 * SPDX-License-Identifier: LGPL-2.1-only
3 *
4 * Copyright (C) 2015-2022 EfficiOS Inc.
5 * Copyright (C) 2015 Alexandre Montplaisir <alexmonthy@efficios.com>
6 * Copyright (C) 2014 Christian Babeux <christian.babeux@efficios.com>
7 */
8
9package org.lttng.ust.agent.log4j2;
10
11import java.io.IOException;
12import java.util.Collection;
13import java.util.Map;
14import java.util.Map.Entry;
15import java.util.concurrent.TimeUnit;
16import java.util.concurrent.atomic.AtomicLong;
17
18import org.apache.logging.log4j.core.Appender;
19import org.apache.logging.log4j.core.Core;
20import org.apache.logging.log4j.core.Filter;
21import org.apache.logging.log4j.core.LogEvent;
22import org.apache.logging.log4j.core.appender.AbstractAppender;
23import org.apache.logging.log4j.core.config.Property;
24import org.apache.logging.log4j.core.config.plugins.Plugin;
25import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
26import org.apache.logging.log4j.core.config.plugins.PluginElement;
27import org.apache.logging.log4j.core.config.plugins.PluginFactory;
8063c7b0 28import org.apache.logging.log4j.message.Message;
37d351b8 29import org.lttng.ust.agent.ILttngAgent.Domain;
464c4756
MJ
30import org.lttng.ust.agent.ILttngHandler;
31import org.lttng.ust.agent.context.ContextInfoSerializer;
32
33/**
34 * LTTng-UST Log4j 2.x log handler.
35 *
36 * Applications can attach this appender to their
37 * {@link org.apache.log4j.Logger} to have it generate UST events from logging
38 * events received through the logger.
39 *
40 * It sends its events to UST via the JNI library "liblttng-ust-log4j-jni.so".
41 * Make sure this library is available before using this appender.
42 *
43 */
44@Plugin(name = LttngLogAppender.PLUGIN_NAME, category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE, printObject = false)
45public final class LttngLogAppender extends AbstractAppender implements ILttngHandler {
46
47 /**
48 * The name of the appender in the configuration.
49 */
50 public static final String PLUGIN_NAME = "Lttng";
51
52 private static final String SHARED_OBJECT_NAME = "lttng-ust-log4j-jni";
53
54 /**
55 * Number of events logged (really sent through JNI) by this handler
56 */
57 private final AtomicLong eventCount = new AtomicLong(0);
58
59 private final LttngLog4j2Agent agent;
60
61 /**
62 * Constructor
63 *
64 * @param name The name of the Appender.
37d351b8 65 * @param domain The LTTng-UST agent domain 'LOG4J' / 'LOG4J2'.
464c4756 66 * @param filter The Filter or null.
37d351b8
MJ
67 * @param ignoreExceptions If {@code "true"} exceptions encountered when
68 * appending events are logged; otherwise they are
464c4756
MJ
69 * propagated to the caller.
70 *
37d351b8
MJ
71 * @throws IOException This handler requires the
72 * lttng-ust-log4j-jni.so native library,
73 * through which it will send the trace events.
74 * This exception is thrown if this library
75 * cannot be found.
76 * @throws IllegalArgumentException If the provided domain is unsupported.
77 * @throws SecurityException We will forward any SecurityExcepion that
78 * may be thrown when trying to load the JNI
79 * library.
464c4756 80 */
37d351b8
MJ
81 protected LttngLogAppender(String name, LttngLog4j2Agent.Domain domain, Filter filter, boolean ignoreExceptions)
82 throws IOException, IllegalArgumentException, SecurityException {
464c4756
MJ
83
84 super(name, filter, null, ignoreExceptions, Property.EMPTY_ARRAY);
85
86 /* Initialize LTTng UST tracer. */
87 try {
88 System.loadLibrary(SHARED_OBJECT_NAME); // $NON-NLS-1$
89 } catch (UnsatisfiedLinkError e) {
90 throw new IOException(e);
91 }
92
93 /* Register to the relevant agent. */
37d351b8 94 if (domain == LttngLog4j2Agent.Domain.LOG4J) {
495b8381
MJ
95 agent = LttngLog4j2Agent.getLog4j1Instance();
96 } else if (domain == LttngLog4j2Agent.Domain.LOG4J2) {
97 agent = LttngLog4j2Agent.getLog4j2Instance();
37d351b8
MJ
98 } else {
99 throw new IllegalArgumentException("Unsupported domain '" + domain + "'");
100 }
101
464c4756
MJ
102 agent.registerHandler(this);
103 }
104
105 /**
106 * Create an LttngLogAppender.
107 *
108 * @param name The name of the Appender, null returns null.
37d351b8 109 * @param domain The LTTng-UST agent domain 'LOG4J' / 'LOG4J2'.
464c4756
MJ
110 * @param ignoreExceptions If {@code "true"} (default) exceptions encountered
111 * when appending events are logged; otherwise they are
112 * propagated to the caller.
113 * @param filter The Filter or null.
114 *
37d351b8
MJ
115 * @return A new LttngLogAppender, null if the name was null or the domain is
116 * null or invalid.
464c4756
MJ
117 */
118 @PluginFactory
119 public static LttngLogAppender createAppender(@PluginAttribute("name") String name,
37d351b8
MJ
120 @PluginAttribute("domain") String domain, @PluginAttribute("ignoreExceptions") Boolean ignoreExceptions,
121 @PluginElement("Filters") Filter filter) {
464c4756
MJ
122
123 if (name == null) {
124 LOGGER.error("No name provided for LttngLogAppender");
125 return null;
126 }
127
37d351b8
MJ
128 if (domain == null) {
129 LOGGER.error("No domain provided for LttngLogAppender");
130 return null;
131 }
132
464c4756
MJ
133 if (ignoreExceptions == null) {
134 ignoreExceptions = true;
135 }
136
37d351b8
MJ
137 /* Parse the domain string */
138 LttngLog4j2Agent.Domain parsedDomain;
139 try {
140 parsedDomain = LttngLog4j2Agent.Domain.valueOf(domain.toUpperCase());
141 } catch (IllegalArgumentException e) {
142 LOGGER.error("Invalid domain '{}' for LttngLogAppender", domain);
143 return null;
144 }
145
146 /* Create the appender and handle the possible failures. */
147 LttngLogAppender newAppender;
148 try {
149 newAppender = new LttngLogAppender(name, parsedDomain, filter, ignoreExceptions);
150 } catch (IllegalArgumentException e) {
151 LOGGER.error("Invalid domain '{}' for LttngLogAppender", parsedDomain);
152 newAppender = null;
153 } catch (SecurityException e) {
154 LOGGER.error("Security error trying to load '{}' JNI library for LttngLogAppender", SHARED_OBJECT_NAME);
155 newAppender = null;
156 } catch (IOException e) {
157 LOGGER.error("Failed to load '{}' JNI library for LttngLogAppender", SHARED_OBJECT_NAME);
158 newAppender = null;
159 }
160
161 return newAppender;
464c4756
MJ
162 }
163
164 @Override
165 public synchronized void close() {
166 agent.unregisterHandler(this);
167 }
168
169 @Override
170 public void stop() {
171 close();
172 super.stop();
173
174 getStatusLogger().debug("Appender Lttng stopped");
175 }
176
177 @Override
178 public boolean stop(final long timeout, final TimeUnit timeUnit) {
179 close();
180 boolean status = super.stop(timeout, timeUnit);
181
182 getStatusLogger().debug("Appender Lttng stopped with status " + status);
183
184 return status;
185 }
186
187 /**
188 * Get the number of events logged by this handler so far. This means the number
189 * of events actually sent through JNI to UST.
190 *
191 * @return The number of events logged so far
192 */
193 @Override
194 public long getEventCount() {
195 return eventCount.get();
196 }
197
198 @Override
199 public void append(LogEvent event) {
200 /*
201 * Check if the current message should be logged, according to the UST session
202 * settings.
203 */
8063c7b0
MJ
204 String loggername = event.getLoggerName();
205 if (loggername == null || !agent.isEventEnabled(loggername)) {
464c4756
MJ
206 return;
207 }
208
8063c7b0
MJ
209 /*
210 * Default value if the Message is null.
211 */
212 String message = "";
213
214 Message eventMessage = event.getMessage();
215 if (eventMessage != null) {
216 message = eventMessage.getFormattedMessage();
217 }
218
464c4756
MJ
219 /*
220 * Default values if the StackTraceElement is null.
221 */
222 String classname = "";
223 String methodname = "";
224 String filename = "";
225 int line = -1;
226
227 StackTraceElement ste = event.getSource();
228 if (ste != null) {
229 classname = ste.getClassName();
230 methodname = ste.getMethodName();
231 filename = ste.getFileName();
232 line = ste.getLineNumber();
233 }
234
235 /* Retrieve all the requested context information we can find. */
236 Collection<Entry<String, Map<String, Integer>>> enabledContexts = agent.getEnabledAppContexts();
237 ContextInfoSerializer.SerializedContexts contextInfo = ContextInfoSerializer
238 .queryAndSerializeRequestedContexts(enabledContexts);
239
240 eventCount.incrementAndGet();
241
8063c7b0
MJ
242 LttngLog4j2Api.tracepointWithContext(message, loggername, classname, methodname, filename, line,
243 event.getTimeMillis(), event.getLevel().intLevel(), event.getThreadName(),
495b8381 244 contextInfo.getEntriesArray(), contextInfo.getStringsArray(), agent.getDomain() == Domain.LOG4J);
464c4756
MJ
245 }
246}
This page took 0.032696 seconds and 4 git commands to generate.