2 * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
4 * This library is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License, version 2.1 only,
6 * as published by the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, write to the Free Software Foundation,
15 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 package org
.lttng
.ust
.agent
;
20 import org
.lttng
.ust
.agent
.jul
.LTTngJUL
;
22 import java
.io
.IOException
;
23 import java
.io
.InputStream
;
24 import java
.io
.BufferedReader
;
25 import java
.io
.FileReader
;
26 import java
.util
.concurrent
.Semaphore
;
27 import java
.util
.concurrent
.TimeUnit
;
28 import java
.util
.Enumeration
;
29 import java
.lang
.reflect
.InvocationTargetException
;
31 import java
.util
.logging
.Logger
;
32 import java
.util
.logging
.SimpleFormatter
;
34 public class LTTngAgent
{
40 private Domain(int value
) {
49 private static LogFramework julUser
;
50 private static LogFramework julRoot
;
51 private static LogFramework log4jUser
;
52 private static LogFramework log4jRoot
;
54 /* Sessiond clients */
55 private static LTTngTCPSessiondClient julUserClient
;
56 private static LTTngTCPSessiondClient julRootClient
;
57 private static LTTngTCPSessiondClient log4jUserClient
;
58 private static LTTngTCPSessiondClient log4jRootClient
;
60 private static Thread sessiondThreadJULUser
;
61 private static Thread sessiondThreadJULRoot
;
62 private static Thread sessiondThreadLog4jUser
;
63 private static Thread sessiondThreadLog4jRoot
;
65 private boolean useJUL
= false;
66 private boolean useLog4j
= false;
68 /* Singleton agent object */
69 private static LTTngAgent curAgent
= null;
71 /* Indicate if this object has been initialized. */
72 private static boolean initialized
= false;
74 private static Semaphore registerSem
;
75 private final static int semTimeout
= 3; /* Seconds */
78 * Constructor is private. This is a singleton and a reference should be
79 * acquired using getLTTngAgent().
81 private LTTngAgent() throws IOException
{
82 initAgentJULClasses();
84 /* Since Log4j is a 3rd party JAR, we need to check if we can load any of its classes */
85 Boolean log4jLoaded
= loadLog4jClasses();
87 initAgentLog4jClasses();
90 this.registerSem
= new Semaphore(0, true);
93 private Boolean
loadLog4jClasses() {
97 logging
= loadClass("org.apache.log4j.spi.LoggingEvent");
98 } catch (ClassNotFoundException e
) {
99 /* Log4j classes not found, no need to create the relevant objects */
104 * Detect capabilities of the log4j library. We only
105 * support log4j >= 1.2.15. The getTimeStamp() method
106 * was introduced in log4j 1.2.15, so verify that it
109 * We can't rely on the getPackage().getImplementationVersion()
110 * call that would retrieves information from the manifest file
111 * found in the JAR since the manifest file shipped
112 * from upstream is known to be broken in several
113 * versions of the library.
116 * https://issues.apache.org/bugzilla/show_bug.cgi?id=44370
120 logging
.getDeclaredMethod("getTimeStamp");
121 } catch (NoSuchMethodException e
) {
123 } catch (NullPointerException e
) {
124 /* Should never happen */
126 } catch (SecurityException e
) {
133 private Class
<?
> loadClass(String className
) throws ClassNotFoundException
{
135 Class
<?
> loadedClass
;
138 /* Try to load class using the current thread's context class loader */
139 loader
= Thread
.currentThread().getContextClassLoader();
140 loadedClass
= loader
.loadClass(className
);
141 } catch (ClassNotFoundException e
) {
142 /* Loading failed, try using the system class loader */
143 loader
= ClassLoader
.getSystemClassLoader();
144 loadedClass
= loader
.loadClass(className
);
150 private void initAgentJULClasses() {
152 Class
<?
> lttngJUL
= loadClass("org.lttng.ust.agent.jul.LTTngJUL");
153 this.julUser
= (LogFramework
)lttngJUL
.getDeclaredConstructor(new Class
[] {Boolean
.class}).newInstance(false);
154 this.julRoot
= (LogFramework
)lttngJUL
.getDeclaredConstructor(new Class
[] {Boolean
.class}).newInstance(true);
156 } catch (ClassNotFoundException e
) {
157 /* LTTng JUL classes not found, no need to create the relevant objects */
159 } catch (InstantiationException e
) {
161 } catch (NoSuchMethodException e
) {
163 } catch (IllegalAccessException e
) {
165 } catch (InvocationTargetException e
) {
170 private void initAgentLog4jClasses() {
172 Class
<?
> lttngLog4j
= loadClass("org.lttng.ust.agent.log4j.LTTngLog4j");
173 this.log4jUser
= (LogFramework
)lttngLog4j
.getDeclaredConstructor(new Class
[] {Boolean
.class}).newInstance(false);
174 this.log4jRoot
= (LogFramework
)lttngLog4j
.getDeclaredConstructor(new Class
[] {Boolean
.class}).newInstance(true);
175 this.useLog4j
= true;
176 } catch (ClassNotFoundException e
) {
177 /* LTTng Log4j classes not found, no need to create the relevant objects */
178 this.useLog4j
= false;
179 } catch (InstantiationException e
) {
180 this.useLog4j
= false;
181 } catch (NoSuchMethodException e
) {
182 this.useLog4j
= false;
183 } catch (IllegalAccessException e
) {
184 this.useLog4j
= false;
185 } catch (InvocationTargetException e
) {
186 this.useLog4j
= false;
191 * Public getter to acquire a reference to this singleton object.
193 public static synchronized LTTngAgent
getLTTngAgent() throws IOException
{
194 if (curAgent
== null) {
195 curAgent
= new LTTngAgent();
202 private synchronized void init() throws SecurityException
, IOException
{
203 if (this.initialized
) {
207 Integer numJULThreads
= 0;
208 Integer numLog4jThreads
= 0;
211 numJULThreads
= initJULClientThreads();
215 numLog4jThreads
= initLog4jClientThreads();
218 Integer numThreads
= numJULThreads
+ numLog4jThreads
;
220 /* Wait for each registration to end. */
222 this.registerSem
.tryAcquire(numThreads
,
225 } catch (InterruptedException e
) {
229 this.initialized
= true;
232 private synchronized Integer
initJULClientThreads() {
233 Integer numThreads
= 2;
235 /* Handle user session daemon if any. */
236 this.julUserClient
= new LTTngTCPSessiondClient(Domain
.JUL
,
240 String userThreadName
= "LTTng UST agent JUL user thread";
241 this.sessiondThreadJULUser
= new Thread(julUserClient
, userThreadName
);
242 this.sessiondThreadJULUser
.setDaemon(true);
243 this.sessiondThreadJULUser
.start();
245 /* Handle root session daemon. */
246 this.julRootClient
= new LTTngTCPSessiondClient(Domain
.JUL
,
250 String rootThreadName
= "LTTng UST agent JUL root thread";
251 this.sessiondThreadJULRoot
= new Thread(julRootClient
, rootThreadName
);
252 this.sessiondThreadJULRoot
.setDaemon(true);
253 this.sessiondThreadJULRoot
.start();
258 private synchronized Integer
initLog4jClientThreads() {
259 Integer numThreads
= 2;
261 this.log4jUserClient
= new LTTngTCPSessiondClient(Domain
.LOG4J
,
265 String userThreadName
= "LTTng UST agent Log4j user thread";
266 this.sessiondThreadLog4jUser
= new Thread(log4jUserClient
, userThreadName
);
267 this.sessiondThreadLog4jUser
.setDaemon(true);
268 this.sessiondThreadLog4jUser
.start();
270 this.log4jRootClient
= new LTTngTCPSessiondClient(Domain
.LOG4J
,
274 String rootThreadName
= "LTTng UST agent Log4j root thread";
275 this.sessiondThreadLog4jRoot
= new Thread(log4jRootClient
,rootThreadName
);
276 this.sessiondThreadLog4jRoot
.setDaemon(true);
277 this.sessiondThreadLog4jRoot
.start();
283 public void dispose() throws IOException
{
285 this.julUserClient
.destroy();
286 this.julRootClient
.destroy();
287 this.julUser
.reset();
288 this.julRoot
.reset();
292 this.log4jUserClient
.destroy();
293 this.log4jRootClient
.destroy();
294 this.log4jUser
.reset();
295 this.log4jRoot
.reset();
300 this.sessiondThreadJULUser
.join();
301 this.sessiondThreadJULRoot
.join();
305 this.sessiondThreadLog4jUser
.join();
306 this.sessiondThreadLog4jRoot
.join();
309 } catch (InterruptedException e
) {