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