tests/benchmark/bench1
tests/benchmark/bench2
-# Java JUL library
+# Java agent library
*.class
-liblttng-ust-jul.jar
-org_lttng_ust_jul_LTTngUst.h
+liblttng-ust-agent.jar
+classnoinst.stamp
+jni-header.stamp
+jul-jni-header.stamp
+log4j-jni-header.stamp
+org_lttng_ust_agent_jul_LTTngLogHandler.h
+org_lttng_ust_agent_log4j_LTTngLogAppender.h
\ No newline at end of file
endif
if BUILD_JNI_INTERFACE
-SUBDIRS += liblttng-ust-java liblttng-ust-jul
+SUBDIRS += liblttng-ust-java
+endif
+
+if BUILD_JAVA_AGENT
+SUBDIRS += liblttng-ust-java-agent
endif
SUBDIRS += tests doc
AC_DEFINE([LTTNG_UST_HAVE_EFFICIENT_UNALIGNED_ACCESS], [1])
fi
-# Set compile flags to java include files if given
-AC_ARG_WITH([java-jdk],
- [AS_HELP_STRING([--with-java-jdk=DIR],[use the Java JDK in DIR. Ex : $JAVA_HOME.])],
- [JAVA_JDK=$withval],
- [JAVA_JDK=""]
-)
-AM_CONDITIONAL([HAVE_JAVA_JDK], [test $JAVA_JDK], [Java JDK path])
-AC_SUBST([JAVA_JDK])
-
-AS_IF([test $JAVA_JDK],[
- AS_IF([test -d $JAVA_JDK],[
- AC_MSG_RESULT([using Java includes in $JAVA_SDK])
- SUBDIRS=`find $JAVA_JDK/include -type d`
- CPPFLAGS+=" "
- CPPFLAGS+=`for x in $SUBDIRS; do echo -n "-I$x "; done`
- CPPFLAGS+=" "
- ],[
- AC_MSG_ERROR(Unable to find Java include files in $JAVA_JDK)
- ])
-])
-
# Check for JNI header files if requested
AC_ARG_ENABLE([jni-interface],
[AS_HELP_STRING([--enable-jni-interface],[build JNI interface between C and Java. Needs Java include files [default=no]])],
AM_CONDITIONAL([BUILD_JNI_INTERFACE], [test "x$jni_interface" = "xyes"])
+
+AC_ARG_ENABLE([java-agent-jul],
+ [AS_HELP_STRING([--enable-java-agent-jul],[build the LTTng UST Java agent with JUL support [default=no]])],
+ [java_agent_jul=$enableval],
+ [java_agent_jul=no]
+)
+
+AC_ARG_ENABLE([java-agent-log4j],
+ [AS_HELP_STRING([--enable-java-agent-log4j],[build the LTTng UST Java agent with Log4j support [default=no]])],
+ [java_agent_log4j=$enableval],
+ [java_agent_log4j=no]
+)
+
+AC_ARG_ENABLE([java-agent-all],
+ [AS_HELP_STRING([--enable-java-agent-all],[build the LTTng UST Java agent with all supported backends [default=no]])],
+ [java_agent_jul=$enableval
+ java_agent_log4j=$enableval],
+ [:]
+)
+
+
+AM_CONDITIONAL([BUILD_JAVA_AGENT], [test "x$java_agent_jul" = "xyes" || test "x$java_agent_log4j" = "xyes"])
+AM_CONDITIONAL([BUILD_JAVA_AGENT_WITH_JUL], [test "x$java_agent_jul" = "xyes"])
+AM_CONDITIONAL([BUILD_JAVA_AGENT_WITH_LOG4J], [test "x$java_agent_log4j" = "xyes"])
+
+if test "x$jni_interface" = "xyes" || test "x$java_agent_jul" = "xyes" || test "x$java_agent_log4j" = "xyes"; then
+ AX_JAVA_OPTIONS
+ AX_PROG_JAVAC
+ AX_PROG_JAVA
+ AX_PROG_JAR
+
+ AX_JNI_INCLUDE_DIR
+ for JNI_INCLUDE_DIR in $JNI_INCLUDE_DIRS
+ do
+ CPPFLAGS="$CPPFLAGS -I$JNI_INCLUDE_DIR"
+ done
+
+ AX_PROG_JAVAH
+fi
+
+if test "x$java_agent_log4j" = "xyes"; then
+ AX_CHECK_CLASSPATH
+
+ AX_CHECK_CLASS(org.apache.log4j.Logger)
+
+ if test "x$ac_cv_class_org_apache_log4j_Logger" = "xno"; then
+ AC_MSG_ERROR([The UST Java agent support for log4j was requested but the Log4j classes were not found. Please specify the location of the Log4j jar via the Java CLASSPATH e.g: export CLASSPATH="/path/to/log4j.jar"])
+ fi
+fi
+
# sdt.h integration
AC_ARG_WITH([sdt],
[AS_HELP_STRING([--with-sdt],[provide SystemTap integration via sdt.h [default=no]])],
AC_DEFINE_UNQUOTED([LTTNG_SYSTEM_RUNDIR], ["$lttng_system_rundir"],
[LTTng system runtime directory])
-lttnglibjavadir="${libdir}/lttng/java"
-AC_SUBST(lttnglibjavadir)
-
AM_PATH_PYTHON([2.7],BUILD_GEN_TP_EXAMPLES=1,[:])
AM_CONDITIONAL([BUILD_GEN_TP_EXAMPLES], [test $BUILD_GEN_TP_EXAMPLES], [Build examples requiring lttng-gen-tp])
liblttng-ust-fork/Makefile
liblttng-ust-dl/Makefile
liblttng-ust-java/Makefile
- liblttng-ust-jul/Makefile
+ liblttng-ust-java-agent/Makefile
+ liblttng-ust-java-agent/java/Makefile
+ liblttng-ust-java-agent/jni/Makefile
+ liblttng-ust-java-agent/jni/jul/Makefile
+ liblttng-ust-java-agent/jni/log4j/Makefile
liblttng-ust-libc-wrapper/Makefile
liblttng-ust-cyg-profile/Makefile
tools/Makefile
tests/snprintf/Makefile
tests/benchmark/Makefile
tests/utils/Makefile
- tests/java-jul/Makefile
lttng-ust.pc
])
AS_ECHO("LTTng-UST will be built with the following options:")
AS_ECHO()
-AS_ECHO_N("Java support (JNI): ")
+
+AS_ECHO_N("Java agent (JUL support): ")
+AS_IF([test "x$java_agent_jul" = "xyes"], [AS_ECHO("Enabled")], [AS_ECHO("Disabled")])
+
+AS_ECHO_N("Java agent (Log4j support): ")
+AS_IF([test "x$java_agent_log4j" = "xyes"], [AS_ECHO("Enabled")], [AS_ECHO("Disabled")])
+
+AS_ECHO_N("JNI interface (JNI): ")
AS_IF([test "x$jni_interface" = "xyes"], [AS_ECHO("Enabled")], [AS_ECHO("Disabled")])
AS_ECHO_N("sdt.h integration: ")
doc_examples_hello_static_libdir = ${docdir}/examples/hello-static-lib
doc_examples_demo_tracefdir = ${docdir}/examples/demo-tracef
-if BUILD_JNI_INTERFACE
+if BUILD_JAVA_AGENT
doc_examples_java_juldir = ${docdir}/examples/java-jul
dist_doc_examples_java_jul_DATA = java-jul/Makefile \
- java-jul/Hello.java \
- java-jul/run
+ java-jul/Hello.java \
+ java-jul/run
SUBDIRS_JUL = java-jul
endif
done; \
if [ x"$(SUBDIRS_JUL)" != x"" ]; then \
for subdir in $(SUBDIRS_JUL); do \
- (cd $(SUBDIRS_JUL) && $(MAKE) JAVA_CLASSPATH_OVERRIDE="../../../liblttng-ust-jul" JAVA_JARFILE_OVERRIDE="liblttng-ust-jul.jar" $(AM_MAKEFLAGS) all && cd ..) || exit 1; \
+ (cd $(SUBDIRS_JUL) && $(MAKE) JAVA_CLASSPATH_OVERRIDE="../../../liblttng-ust-java-agent/java" JAVA_JARFILE_OVERRIDE="liblttng-ust-agent.jar" $(AM_MAKEFLAGS) all && cd ..) || exit 1; \
done; \
fi;
/*
* That's the import you need being the path in the liblttng-ust-jul Jar file.
*/
-import org.lttng.ust.jul.LTTngAgent;
+import org.lttng.ust.agent.LTTngAgent;
public class Hello
{
#
# Default JUL jar name.
-JARFILE=liblttng-ust-jul.jar
+JARFILE=liblttng-ust-agent.jar
# Check if the top level makefile overrides the JUL Jar file name.
ifneq "$(JAVA_JARFILE_OVERRIDE)" ""
# Check if the top level makefile overrides the JUL classpath.
ifeq "$(JAVA_CLASSPATH_OVERRIDE)" ""
- CLASSPATH=/usr/local/lib/lttng/java/$(JARFILE):/usr/lib/lttng/java/$(JARFILE)
+ CLASSPATH=/usr/local/share/java/$(JARFILE):/usr/share/java/$(JARFILE)
else
CLASSPATH=$(JAVA_CLASSPATH_OVERRIDE)/$(JARFILE)
endif
#
DIR=`dirname $0`
-JARFILE="liblttng-ust-jul.jar"
+JARFILE="liblttng-ust-agent.jar"
cd $DIR
if [ -f "$DIR/.intree" ]; then
- CLASSPATH="../../../liblttng-ust-jul/$JARFILE"
- LIBPATH="../../../liblttng-ust-jul/.libs"
+ CLASSPATH="../../../liblttng-ust-java-agent/java/$JARFILE"
+ LIBPATH="../../../liblttng-ust-java-agent/jni/jul/.libs"
else
- CLASSPATH="/usr/local/lib/lttng/java/$JARFILE:/usr/lib/lttng/java/$JARFILE"
+ CLASSPATH="/usr/local/share/java/$JARFILE:/usr/share/java/$JARFILE"
LIBPATH="/usr/local/lib:/usr/lib"
fi
--- /dev/null
+/*
+ * Copyright (C) 2014 - Christian Babeux <christian.babeux@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+import java.io.IOException;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.BasicConfigurator;
+
+import org.lttng.ust.agent.LTTngAgent;
+
+public class Hello
+{
+ /* Of course :) */
+ private static final int answer = 42;
+
+ static Logger helloLog = Logger.getLogger(Hello.class);
+
+ private static LTTngAgent lttngAgent;
+
+ public static void main(String args[]) throws Exception
+ {
+ BasicConfigurator.configure();
+ lttngAgent = LTTngAgent.getLTTngAgent();
+
+ /*
+ * Gives you time to do some lttng commands before any event is hit.
+ */
+ Thread.sleep(5000);
+
+ /* Trigger a tracing event using the JUL Logger created before. */
+ helloLog.info("Hello World, the answer is " + answer);
+
+ System.out.println("Firing hello delay in 10 seconds...");
+ Thread.sleep(5000);
+ helloLog.info("Hello World delayed...");
+ }
+}
--- /dev/null
+#
+# Copyright (C) 2014 - Christian Babeux <christian.babeux@efficios.com>
+#
+# THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED OR
+# IMPLIED. ANY USE IS AT YOUR OWN RISK.
+#
+# Permission is hereby granted to use or copy this program for any purpose,
+# provided the above notices are retained on all copies. Permission to modify
+# the code and to distribute modified code is granted, provided the above
+# notices are retained, and a notice that the code was modified is included
+# with the above copyright notice.
+#
+# This Makefile is not using automake so that users may see how to build a
+# program with tracepoint provider probes as stand-alone shared objects.
+#
+# This makefile is purposefully kept simple to support GNU and BSD make.
+#
+
+JFLAGS = -g
+
+# Default JUL jar name.
+JARFILE=liblttng-ust-agent.jar
+LOG4J=/usr/share/java/log4j.jar
+
+# Check if the top level makefile overrides the JUL Jar file name.
+ifneq "$(JAVA_JARFILE_OVERRIDE)" ""
+ JARFILE=$(JAVA_JARFILE_OVERRIDE)
+endif
+
+# Check if the top level makefile overrides the JUL classpath.
+ifeq "$(JAVA_CLASSPATH_OVERRIDE)" ""
+ CLASSPATH=/usr/local/share/java/$(JARFILE):/usr/share/java/$(JARFILE):$(LOG4J)
+else
+ CLASSPATH=$(JAVA_CLASSPATH_OVERRIDE)/$(JARFILE):$(LOG4J)
+endif
+
+JC = javac -cp "$(CLASSPATH):."
+.SUFFIXES: .java .class
+.java.class:
+ $(JC) $(JFLAGS) $*.java
+
+CLASSES = Hello.java
+
+all: classes
+
+classes: $(CLASSES:.java=.class)
+
+.PHONY: clean
+clean:
+ $(RM) *.class
--- /dev/null
+#!/bin/bash
+
+#
+# The -cp path should be changed to the lttng ust agent jar file on your system
+# or locally to the project. Same goes for the Java library path in order to
+# find the JNI Log4j library.
+#
+
+DIR=`dirname $0`
+JARFILE="liblttng-ust-agent.jar"
+LOG4J="/usr/local/share/java/log4j.jar:/usr/share/java/log4j.jar"
+
+cd $DIR
+
+if [ -f "$DIR/.intree" ]; then
+ CLASSPATH="../../../liblttng-ust-java-agent/java/$JARFILE:$LOG4J"
+ LIBPATH="../../../liblttng-ust-java-agent/jni/log4j/.libs"
+else
+ CLASSPATH="/usr/local/share/java/$JARFILE:/usr/share/java/$JARFILE:$LOG4J"
+ LIBPATH="/usr/local/lib:/usr/lib"
+fi
+
+java -cp "$CLASSPATH:." Hello
+
+cd -
--- /dev/null
+SUBDIRS = java jni
--- /dev/null
+JAVAROOT = .
+
+jarfile = liblttng-ust-agent.jar
+jarfile_old = liblttng-ust-jul.jar
+jardir = $(datadir)/java
+juljniout = ../jni/jul
+log4jjniout = ../jni/log4j
+pkgpath = org/lttng/ust/agent
+pkgpath_old = org/lttng/ust/jul
+dist_noinst_JAVA = $(pkgpath)/LTTngAgent.java \
+ $(pkgpath)/LTTngSessiondCmd2_6.java \
+ $(pkgpath)/LTTngTCPSessiondClient.java \
+ $(pkgpath)/LogFramework.java \
+ $(pkgpath)/LogFrameworkSkeleton.java \
+ $(pkgpath)/jul/LTTngJUL.java \
+ $(pkgpath)/jul/LTTngLogHandler.java \
+ $(pkgpath_old)/LTTngAgent.java
+
+jar_DATA = $(jarfile) $(jarfile_old)
+
+stamp =
+classes = $(pkgpath)/*.class
+
+if BUILD_JAVA_AGENT_WITH_JUL
+dist_noinst_JAVA += $(pkgpath)/jul/LTTngJUL.java \
+ $(pkgpath)/jul/LTTngLogHandler.java
+stamp += jul-jni-header.stamp
+classes += $(pkgpath)/jul/*.class
+endif
+
+if BUILD_JAVA_AGENT_WITH_LOG4J
+dist_noinst_JAVA += $(pkgpath)/log4j/LTTngLog4j.java \
+ $(pkgpath)/log4j/LTTngLogAppender.java
+stamp += log4j-jni-header.stamp
+classes += $(pkgpath)/log4j/*.class
+endif
+
+$(jarfile): classnoinst.stamp
+ $(JAR) cf $(JARFLAGS) $@ $(classes)
+
+$(jarfile_old): classnoinst.stamp
+ $(JAR) cf $(JARFLAGS) $@ $(pkgpath)/*.class \
+ $(pkgpath)/jul/*.class $(pkgpath_old)/*.class
+
+jul-jni-header.stamp: $(dist_noinst_JAVA)
+ $(JAVAH) -cp $(CLASSPATH):. -d $(juljniout) $(JAVAHFLAGS) org.lttng.ust.agent.jul.LTTngLogHandler && \
+ echo "JUL JNI header generated" > jul-jni-header.stamp
+
+log4j-jni-header.stamp: $(dist_noinst_JAVA)
+ $(JAVAH) -cp $(CLASSPATH):. -d $(log4jjniout) $(JAVAHFLAGS) org.lttng.ust.agent.log4j.LTTngLogAppender && \
+ echo "Log4j JNI header generated" > log4j-jni-header.stamp
+
+all-local: $(stamp)
+
+CLEANFILES = $(jarfile) $(jarfile_old) $(pkgpath)/*.class $(pkgpath_old)/*.class $(pkgpath)/jul/*.class \
+ $(pkgpath)/log4j/*.class jul-jni-header.stamp log4j-jni-header.stamp \
+ $(juljniout)/org_lttng_ust_agent_jul_LTTngLogHandler.h \
+ $(log4jjniout)/org_lttng_ust_agent_log4j_LTTngLogAppender.h
--- /dev/null
+/*
+ * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.lttng.ust.agent;
+
+import org.lttng.ust.agent.jul.LTTngJUL;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import java.util.Enumeration;
+import java.lang.reflect.InvocationTargetException;
+
+import java.util.logging.Logger;
+import java.util.logging.FileHandler;;
+import java.util.logging.SimpleFormatter;
+
+public class LTTngAgent {
+ /* Domains */
+ static enum Domain {
+ JUL(3), LOG4J(4);
+ private int value;
+
+ private Domain(int value) {
+ this.value = value;
+ }
+
+ public int value() {
+ return value;
+ }
+ }
+
+ private static LogFramework julUser;
+ private static LogFramework julRoot;
+ private static LogFramework log4jUser;
+ private static LogFramework log4jRoot;
+
+ /* Sessiond clients */
+ private static LTTngTCPSessiondClient julUserClient;
+ private static LTTngTCPSessiondClient julRootClient;
+ private static LTTngTCPSessiondClient log4jUserClient;
+ private static LTTngTCPSessiondClient log4jRootClient;
+
+ private static Thread sessiondThreadJULUser;
+ private static Thread sessiondThreadJULRoot;
+ private static Thread sessiondThreadLog4jUser;
+ private static Thread sessiondThreadLog4jRoot;
+
+ private boolean useJUL = false;
+ private boolean useLog4j = false;
+
+ /* Singleton agent object */
+ private static LTTngAgent curAgent = null;
+
+ /* Indicate if this object has been initialized. */
+ private static boolean initialized = false;
+
+ private static Semaphore registerSem;
+ private final static int semTimeout = 3; /* Seconds */
+
+ /*
+ * Constructor is private. This is a singleton and a reference should be
+ * acquired using getLTTngAgent().
+ */
+ private LTTngAgent() throws IOException {
+ initAgentJULClasses();
+
+ /* Since Log4j is a 3rd party JAR, we need to check if we can load any of its classes */
+ Boolean log4jLoaded = loadLog4jClasses();
+ if (log4jLoaded) {
+ initAgentLog4jClasses();
+ }
+
+ this.registerSem = new Semaphore(0, true);
+ }
+
+ private Boolean loadLog4jClasses() {
+ Boolean loaded = false;
+ try {
+ ClassLoader loader = ClassLoader.getSystemClassLoader();
+ loader.loadClass("org.apache.log4j.Logger");
+ loaded = true;
+ } catch (ClassNotFoundException e) {
+ /* Log4j classes not found, no need to create the relevant objects */
+ loaded = false;
+ }
+
+ return loaded;
+ }
+
+ private void initAgentJULClasses() {
+ try {
+ ClassLoader loader = ClassLoader.getSystemClassLoader();
+ Class<?> lttngJUL = loader.loadClass("org.lttng.ust.agent.jul.LTTngJUL");
+ this.julUser = (LogFramework)lttngJUL.getDeclaredConstructor(new Class[] {Boolean.class}).newInstance(false);
+ this.julRoot = (LogFramework)lttngJUL.getDeclaredConstructor(new Class[] {Boolean.class}).newInstance(true);
+ this.useJUL = true;
+ } catch (ClassNotFoundException e) {
+ /* LTTng JUL classes not found, no need to create the relevant objects */
+ this.useJUL = false;
+ } catch (InstantiationException e) {
+ this.useJUL = false;
+ } catch (NoSuchMethodException e) {
+ this.useJUL = false;
+ } catch (IllegalAccessException e) {
+ this.useJUL = false;
+ } catch (InvocationTargetException e) {
+ this.useJUL = false;
+ }
+ }
+
+ private void initAgentLog4jClasses() {
+ try {
+ ClassLoader loader = ClassLoader.getSystemClassLoader();
+ Class<?> lttngLog4j = loader.loadClass("org.lttng.ust.agent.log4j.LTTngLog4j");
+ this.log4jUser = (LogFramework)lttngLog4j.getDeclaredConstructor(new Class[] {Boolean.class}).newInstance(false);
+ this.log4jRoot = (LogFramework)lttngLog4j.getDeclaredConstructor(new Class[] {Boolean.class}).newInstance(true);
+ this.useLog4j = true;
+ } catch (ClassNotFoundException e) {
+ /* LTTng Log4j classes not found, no need to create the relevant objects */
+ this.useLog4j = false;
+ } catch (InstantiationException e) {
+ this.useLog4j = false;
+ } catch (NoSuchMethodException e) {
+ this.useLog4j = false;
+ } catch (IllegalAccessException e) {
+ this.useLog4j = false;
+ } catch (InvocationTargetException e) {
+ this.useLog4j = false;
+ }
+ }
+
+ /*
+ * Public getter to acquire a reference to this singleton object.
+ */
+ public static synchronized LTTngAgent getLTTngAgent() throws IOException {
+ if (curAgent == null) {
+ curAgent = new LTTngAgent();
+ curAgent.init();
+ }
+
+ return curAgent;
+ }
+
+ private synchronized void init() throws SecurityException, IOException {
+ if (this.initialized) {
+ return;
+ }
+
+ Integer numJULThreads = 0;
+ Integer numLog4jThreads = 0;
+
+ if (this.useJUL) {
+ numJULThreads = initJULClientThreads();
+ }
+
+ if (this.useLog4j) {
+ numLog4jThreads = initLog4jClientThreads();
+ }
+
+ Integer numThreads = numJULThreads + numLog4jThreads;
+
+ /* Wait for each registration to end. */
+ try {
+ this.registerSem.tryAcquire(numThreads,
+ semTimeout,
+ TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ this.initialized = true;
+ }
+
+ private synchronized Integer initJULClientThreads() {
+ Integer numThreads = 2;
+
+ /* Handle user session daemon if any. */
+ this.julUserClient = new LTTngTCPSessiondClient(Domain.JUL,
+ this.julUser,
+ this.registerSem);
+
+ String userThreadName = "LTTng UST agent JUL user thread";
+ this.sessiondThreadJULUser = new Thread(julUserClient, userThreadName);
+ this.sessiondThreadJULUser.setDaemon(true);
+ this.sessiondThreadJULUser.start();
+
+ /* Handle root session daemon. */
+ this.julRootClient = new LTTngTCPSessiondClient(Domain.JUL,
+ this.julRoot,
+ this.registerSem);
+
+ String rootThreadName = "LTTng UST agent JUL root thread";
+ this.sessiondThreadJULRoot = new Thread(julRootClient, rootThreadName);
+ this.sessiondThreadJULRoot.setDaemon(true);
+ this.sessiondThreadJULRoot.start();
+
+ return numThreads;
+ }
+
+ private synchronized Integer initLog4jClientThreads() {
+ Integer numThreads = 2;
+
+ this.log4jUserClient = new LTTngTCPSessiondClient(Domain.LOG4J,
+ this.log4jUser,
+ this.registerSem);
+
+ String userThreadName = "LTTng UST agent Log4j user thread";
+ this.sessiondThreadLog4jUser = new Thread(log4jUserClient, userThreadName);
+ this.sessiondThreadLog4jUser.setDaemon(true);
+ this.sessiondThreadLog4jUser.start();
+
+ this.log4jRootClient = new LTTngTCPSessiondClient(Domain.LOG4J,
+ this.log4jRoot,
+ this.registerSem);
+
+ String rootThreadName = "LTTng UST agent Log4j root thread";
+ this.sessiondThreadLog4jRoot = new Thread(log4jRootClient,rootThreadName);
+ this.sessiondThreadLog4jRoot.setDaemon(true);
+ this.sessiondThreadLog4jRoot.start();
+
+ return numThreads;
+ }
+
+
+ public void dispose() throws IOException {
+ if (this.useJUL) {
+ this.julUserClient.destroy();
+ this.julRootClient.destroy();
+ this.julUser.reset();
+ this.julRoot.reset();
+ }
+
+ if (this.useLog4j) {
+ this.log4jUserClient.destroy();
+ this.log4jRootClient.destroy();
+ this.log4jUser.reset();
+ this.log4jRoot.reset();
+ }
+
+ try {
+ if (this.useJUL) {
+ this.sessiondThreadJULUser.join();
+ this.sessiondThreadJULRoot.join();
+ }
+
+ if (this.useLog4j) {
+ this.sessiondThreadLog4jUser.join();
+ this.sessiondThreadLog4jRoot.join();
+ }
+
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
+ *
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.lttng.ust.agent;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.lang.Object;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Enumeration;
+import java.util.Iterator;
+
+interface LTTngSessiondCmd2_6 {
+ /**
+ * Maximum name length for a logger name to be send to sessiond.
+ */
+ final static int NAME_MAX = 255;
+
+ /*
+ * Size of a primitive type int in byte. Because you know, Java can't
+ * provide that since it does not makes sense...
+ */
+ final static int INT_SIZE = 4;
+
+ public interface SessiondResponse {
+ /**
+ * Gets a byte array of the command so that it may be streamed
+ *
+ * @return the byte array of the command
+ */
+ public byte[] getBytes();
+ }
+
+ public interface SessiondCommand {
+ /**
+ * Populate the class from a byte array
+ *
+ * @param data
+ * the byte array containing the streamed command
+ */
+ public void populate(byte[] data);
+ }
+
+ public enum lttng_agent_command {
+ /** List logger(s). */
+ CMD_LIST(1),
+ /** Enable logger by name. */
+ CMD_ENABLE(2),
+ /** Disable logger by name. */
+ CMD_DISABLE(3),
+ /** Registration done */
+ CMD_REG_DONE(4);
+
+ private int code;
+
+ private lttng_agent_command(int c) {
+ code = c;
+ }
+
+ public int getCommand() {
+ return code;
+ }
+ }
+
+ enum lttng_agent_ret_code {
+ CODE_SUCCESS_CMD(1),
+ CODE_INVALID_CMD(2),
+ CODE_UNK_LOGGER_NAME(3);
+ private int code;
+
+ private lttng_agent_ret_code(int c) {
+ code = c;
+ }
+
+ public int getCode() {
+ return code;
+ }
+ }
+
+ public class sessiond_hdr implements SessiondCommand {
+ /** ABI size of command header. */
+ public final static int SIZE = 16;
+ /** Payload size in bytes following this header. */
+ public long data_size;
+ /** Command type. */
+ public lttng_agent_command cmd;
+ /** Command version. */
+ public int cmd_version;
+
+ public void populate(byte[] data) {
+ ByteBuffer buf = ByteBuffer.wrap(data);
+ buf.order(ByteOrder.BIG_ENDIAN);
+
+ data_size = buf.getLong();
+ cmd = lttng_agent_command.values()[buf.getInt() - 1];
+ cmd_version = buf.getInt();
+ }
+ }
+
+ public class sessiond_enable_handler implements SessiondResponse, SessiondCommand {
+ private final static int SIZE = 4;
+ public String name;
+ public int lttngLogLevel;
+ public int lttngLogLevelType;
+
+ /** Return status code to the session daemon. */
+ public lttng_agent_ret_code code;
+
+ @Override
+ public void populate(byte[] data) {
+ int data_offset = INT_SIZE * 2;
+
+ ByteBuffer buf = ByteBuffer.wrap(data);
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ lttngLogLevel = buf.getInt();
+ lttngLogLevelType = buf.getInt();
+ name = new String(data, data_offset, data.length - data_offset).trim();
+ }
+
+ @Override
+ public byte[] getBytes() {
+ byte data[] = new byte[SIZE];
+ ByteBuffer buf = ByteBuffer.wrap(data);
+ buf.order(ByteOrder.BIG_ENDIAN);
+ buf.putInt(code.getCode());
+ return data;
+ }
+
+ /**
+ * Execute enable handler action which is to enable the given handler
+ * to the received name.
+ */
+ public void execute(LogFramework log) {
+ if (log.enableLogger(this.name)) {
+ this.code = lttng_agent_ret_code.CODE_SUCCESS_CMD;
+ } else {
+ this.code = lttng_agent_ret_code.CODE_INVALID_CMD;
+ }
+ }
+ }
+
+ public class sessiond_disable_handler implements SessiondResponse, SessiondCommand {
+ private final static int SIZE = 4;
+ public String name;
+
+
+ /** Return status code to the session daemon. */
+ public lttng_agent_ret_code code;
+
+ @Override
+ public void populate(byte[] data) {
+ ByteBuffer buf = ByteBuffer.wrap(data);
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ name = new String(data).trim();
+ }
+
+ @Override
+ public byte[] getBytes() {
+ byte data[] = new byte[SIZE];
+ ByteBuffer buf = ByteBuffer.wrap(data);
+ buf.order(ByteOrder.BIG_ENDIAN);
+ buf.putInt(code.getCode());
+ return data;
+ }
+
+ /**
+ * Execute disable handler action which is to disable the given handler
+ * to the received name.
+ */
+ public void execute(LogFramework log) {
+ if (log.disableLogger(this.name)) {
+ this.code = lttng_agent_ret_code.CODE_SUCCESS_CMD;
+ } else {
+ this.code = lttng_agent_ret_code.CODE_INVALID_CMD;
+ }
+ }
+ }
+
+ public class sessiond_list_logger implements SessiondResponse {
+ private final static int SIZE = 12;
+
+ private int data_size = 0;
+ private int nb_logger = 0;
+
+ List<String> logger_list = new ArrayList<String>();
+
+ /** Return status code to the session daemon. */
+ public lttng_agent_ret_code code;
+
+ @Override
+ public byte[] getBytes() {
+ byte data[] = new byte[SIZE + data_size];
+ ByteBuffer buf = ByteBuffer.wrap(data);
+ buf.order(ByteOrder.BIG_ENDIAN);
+
+ /* Returned code */
+ buf.putInt(code.getCode());
+ buf.putInt(data_size);
+ buf.putInt(nb_logger);
+
+ for (String logger: logger_list) {
+ buf.put(logger.getBytes());
+ /* NULL terminated byte after the logger name. */
+ buf.put((byte) 0x0);
+ }
+ return data;
+ }
+
+ public void execute(LogFramework log) {
+ String loggerName;
+
+ Iterator<String> loggers = log.listLoggers();
+ while (loggers.hasNext()) {
+ loggerName = loggers.next();
+ this.logger_list.add(loggerName);
+ this.nb_logger++;
+ this.data_size += loggerName.length() + 1;
+ }
+
+ this.code = lttng_agent_ret_code.CODE_SUCCESS_CMD;
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.lttng.ust.agent;
+
+import java.util.concurrent.Semaphore;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.lang.Integer;
+import java.io.IOException;
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.DataInputStream;
+import java.io.FileReader;
+import java.io.FileNotFoundException;
+import java.net.*;
+import java.lang.management.ManagementFactory;
+
+class LTTngTCPSessiondClient implements Runnable {
+
+ /* Command header from the session deamon. */
+ private LTTngSessiondCmd2_6.sessiond_hdr headerCmd =
+ new LTTngSessiondCmd2_6.sessiond_hdr();
+
+ private Socket sessiondSock;
+ private volatile boolean quit = false;
+
+ private DataInputStream inFromSessiond;
+ private DataOutputStream outToSessiond;
+
+ private LogFramework log;
+
+ private Semaphore registerSem;
+
+ private static final String sessiondHost = "127.0.0.1";
+ private static final String rootPortFile = "/var/run/lttng/agent.port";
+ private static final String userPortFile = "/.lttng/agent.port";
+
+ private static Integer protocolMajorVersion = 1;
+ private static Integer protocolMinorVersion = 0;
+
+ private LTTngAgent.Domain agentDomain;
+
+ /* Indicate if we've already release the semaphore. */
+ private boolean sem_posted = false;
+
+ public LTTngTCPSessiondClient(LTTngAgent.Domain domain, LogFramework log, Semaphore sem) {
+ this.agentDomain = domain;
+ this.log = log;
+ this.registerSem = sem;
+ }
+
+ /*
+ * Try to release the registerSem if it's not already done.
+ */
+ private void tryReleaseSem()
+ {
+ /* Release semaphore so we unblock the agent. */
+ if (!this.sem_posted) {
+ this.registerSem.release();
+ this.sem_posted = true;
+ }
+ }
+
+ @Override
+ public void run() {
+ for (;;) {
+ if (this.quit) {
+ break;
+ }
+
+ /* Cleanup Agent state before trying to connect or reconnect. */
+ this.log.reset();
+
+ try {
+
+ /*
+ * Connect to the session daemon before anything else.
+ */
+ connectToSessiond();
+
+ /*
+ * Register to the session daemon as the Java component of the
+ * UST application.
+ */
+ registerToSessiond();
+
+ /*
+ * Block on socket receive and wait for command from the
+ * session daemon. This will return if and only if there is a
+ * fatal error or the socket closes.
+ */
+ handleSessiondCmd();
+ } catch (UnknownHostException uhe) {
+ tryReleaseSem();
+ System.out.println(uhe);
+ } catch (IOException ioe) {
+ tryReleaseSem();
+ try {
+ Thread.sleep(3000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ } catch (Exception e) {
+ tryReleaseSem();
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public void destroy() {
+ this.quit = true;
+
+ try {
+ if (this.sessiondSock != null) {
+ this.sessiondSock.close();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /*
+ * Receive header data from the session daemon using the LTTng command
+ * static buffer of the right size.
+ */
+ private void recvHeader() throws Exception {
+ int read_len;
+ byte data[] = new byte[this.headerCmd.SIZE];
+
+ read_len = this.inFromSessiond.read(data, 0, data.length);
+ if (read_len != data.length) {
+ throw new IOException();
+ }
+ this.headerCmd.populate(data);
+ }
+
+ /*
+ * Receive payload from the session daemon. This MUST be done after a
+ * recvHeader() so the header value of a command are known.
+ *
+ * The caller SHOULD use isPayload() before which returns true if a payload
+ * is expected after the header.
+ */
+ private byte[] recvPayload() throws Exception {
+ byte payload[] = new byte[(int) this.headerCmd.data_size];
+
+ /* Failsafe check so we don't waste our time reading 0 bytes. */
+ if (payload.length == 0) {
+ return null;
+ }
+
+ this.inFromSessiond.read(payload, 0, payload.length);
+ return payload;
+ }
+
+ /*
+ * Handle session command from the session daemon.
+ */
+ private void handleSessiondCmd() throws Exception {
+ int ret_code;
+ byte data[] = null;
+
+ while (true) {
+ /* Get header from session daemon. */
+ recvHeader();
+
+ if (headerCmd.data_size > 0) {
+ data = recvPayload();
+ }
+
+ switch (headerCmd.cmd) {
+ case CMD_REG_DONE:
+ {
+ /*
+ * Release semaphore so meaning registration is done and we
+ * can proceed to continue tracing.
+ */
+ tryReleaseSem();
+ /*
+ * We don't send any reply to the registration done command.
+ * This just marks the end of the initial session setup.
+ */
+ continue;
+ }
+ case CMD_LIST:
+ {
+ LTTngSessiondCmd2_6.sessiond_list_logger listLoggerCmd =
+ new LTTngSessiondCmd2_6.sessiond_list_logger();
+ listLoggerCmd.execute(this.log);
+ data = listLoggerCmd.getBytes();
+ break;
+ }
+ case CMD_ENABLE:
+ {
+ LTTngSessiondCmd2_6.sessiond_enable_handler enableCmd =
+ new LTTngSessiondCmd2_6.sessiond_enable_handler();
+ if (data == null) {
+ enableCmd.code = LTTngSessiondCmd2_6.lttng_agent_ret_code.CODE_INVALID_CMD;
+ break;
+ }
+ enableCmd.populate(data);
+ enableCmd.execute(this.log);
+ data = enableCmd.getBytes();
+ break;
+ }
+ case CMD_DISABLE:
+ {
+ LTTngSessiondCmd2_6.sessiond_disable_handler disableCmd =
+ new LTTngSessiondCmd2_6.sessiond_disable_handler();
+ if (data == null) {
+ disableCmd.code = LTTngSessiondCmd2_6.lttng_agent_ret_code.CODE_INVALID_CMD;
+ break;
+ }
+ disableCmd.populate(data);
+ disableCmd.execute(this.log);
+ data = disableCmd.getBytes();
+ break;
+ }
+ default:
+ {
+ data = new byte[4];
+ ByteBuffer buf = ByteBuffer.wrap(data);
+ buf.order(ByteOrder.BIG_ENDIAN);
+ LTTngSessiondCmd2_6.lttng_agent_ret_code code =
+ LTTngSessiondCmd2_6.lttng_agent_ret_code.CODE_INVALID_CMD;
+ break;
+ }
+ }
+
+ /* Send payload to session daemon. */
+ this.outToSessiond.write(data, 0, data.length);
+ this.outToSessiond.flush();
+ }
+ }
+
+ private String getHomePath() {
+ return System.getProperty("user.home");
+ }
+
+ /**
+ * Read port number from file created by the session daemon.
+ *
+ * @return port value if found else 0.
+ */
+ private int getPortFromFile(String path) throws IOException {
+ int port;
+ BufferedReader br;
+
+ try {
+ br = new BufferedReader(new FileReader(path));
+ String line = br.readLine();
+ port = Integer.parseInt(line, 10);
+ if (port < 0 || port > 65535) {
+ /* Invalid value. Ignore. */
+ port = 0;
+ }
+ br.close();
+ } catch (FileNotFoundException e) {
+ /* No port available. */
+ port = 0;
+ }
+
+ return port;
+ }
+
+ private void connectToSessiond() throws Exception {
+ int port;
+
+ if (this.log.isRoot()) {
+ port = getPortFromFile(rootPortFile);
+ if (port == 0) {
+ /* No session daemon available. Stop and retry later. */
+ throw new IOException();
+ }
+ } else {
+ port = getPortFromFile(getHomePath() + userPortFile);
+ if (port == 0) {
+ /* No session daemon available. Stop and retry later. */
+ throw new IOException();
+ }
+ }
+
+ this.sessiondSock = new Socket(this.sessiondHost, port);
+ this.inFromSessiond = new DataInputStream(
+ sessiondSock.getInputStream());
+ this.outToSessiond = new DataOutputStream(
+ sessiondSock.getOutputStream());
+ }
+
+ private void registerToSessiond() throws Exception {
+ byte data[] = new byte[16];
+ ByteBuffer buf = ByteBuffer.wrap(data);
+ String pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
+
+ buf.putInt(this.agentDomain.value());
+ buf.putInt(Integer.parseInt(pid));
+ buf.putInt(this.protocolMajorVersion);
+ buf.putInt(this.protocolMinorVersion);
+ this.outToSessiond.write(data, 0, data.length);
+ this.outToSessiond.flush();
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 - Christian Babeux <christian.babeux@efficios.com>
+ *
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.lttng.ust.agent;
+
+import java.util.Iterator;
+
+interface LogFramework {
+ Boolean enableLogger(String name);
+ Boolean disableLogger(String name);
+ Iterator<String> listLoggers();
+ Boolean isRoot();
+ void reset();
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 - Christian Babeux <christian.babeux@efficios.com>
+ *
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.lttng.ust.agent;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Iterator;
+
+public abstract class LogFrameworkSkeleton implements LogFramework {
+
+ /* A map of event name and reference count */
+ private Map<String, Integer> enabledLoggers;
+
+ public LogFrameworkSkeleton() {
+ this.enabledLoggers = new HashMap<String, Integer>();
+ }
+
+ @Override
+ public Boolean enableLogger(String name) {
+ if (name == null) {
+ return false;
+ }
+
+ if (enabledLoggers.containsKey(name)) {
+ /* Event is already enabled, simply increment its refcount */
+ Integer refcount = enabledLoggers.get(name);
+ refcount++;
+ Integer oldval = enabledLoggers.put(name, refcount);
+ assert (oldval != null);
+ } else {
+ /* Event was not enabled, init refcount to 1 */
+ Integer oldval = enabledLoggers.put(name, 1);
+ assert (oldval == null);
+ }
+
+ return true;
+ }
+
+ @Override
+ public Boolean disableLogger(String name) {
+ if (name == null) {
+ return false;
+ }
+
+ if (!enabledLoggers.containsKey(name)) {
+ /* Event was never enabled, abort */
+ return false;
+ }
+
+ /* Event was previously enabled, simply decrement its refcount */
+ Integer refcount = enabledLoggers.get(name);
+ refcount--;
+ assert (refcount >= 0);
+
+ if (refcount == 0) {
+ /* Event is not used anymore, remove it from the map */
+ Integer oldval = enabledLoggers.remove(name);
+ assert (oldval != null);
+ }
+
+ return true;
+ }
+
+ @Override
+ public abstract Iterator<String> listLoggers();
+
+ @Override
+ public abstract Boolean isRoot();
+
+ @Override
+ public void reset() {
+ enabledLoggers.clear();
+ }
+
+ protected Integer getEventCount() {
+ return enabledLoggers.size();
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 - Christian Babeux <christian.babeux@efficios.com>
+ *
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.lttng.ust.agent.jul;
+
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Vector;
+
+import java.util.logging.LogManager;
+import java.util.logging.Logger;
+
+import org.lttng.ust.agent.LogFrameworkSkeleton;
+
+public class LTTngJUL extends LogFrameworkSkeleton {
+
+ private LTTngLogHandler handler;
+ private Boolean attached;
+
+ public LTTngJUL(Boolean isRoot) {
+ super();
+ this.handler = new LTTngLogHandler(isRoot);
+ this.attached = false;
+ }
+
+ @Override
+ public Boolean enableLogger(String name) {
+ if(!super.enableLogger(name)) {
+ return false;
+ }
+
+ /* The first enable of any event triggers the attachment to the root logger */
+ if (getEventCount() == 1 && !this.attached) {
+ attachToRootLogger();
+ }
+
+ return true;
+ }
+
+ @Override
+ public Boolean disableLogger(String name) {
+ if(!super.disableLogger(name)) {
+ return false;
+ }
+
+ /* Detach from the root logger when the event count reach zero */
+ if (getEventCount() == 0 && this.attached) {
+ detachFromRootLogger();
+ }
+
+ return true;
+ }
+
+ @Override
+ public Iterator<String> listLoggers() {
+ Vector<String> logs = new Vector<String>();
+ for (Enumeration<String> loggers = LogManager.getLogManager().getLoggerNames(); loggers.hasMoreElements(); ) {
+ String name = loggers.nextElement();
+ /* Skip the root logger */
+ if (name.equals("")) {
+ continue;
+ }
+
+ logs.add(name);
+ }
+
+ return logs.iterator();
+ }
+
+ @Override
+ public Boolean isRoot() {
+ return handler.isRoot();
+ }
+
+ @Override
+ public void reset() {
+ super.reset();
+ detachFromRootLogger();
+ }
+
+ private void attachToRootLogger() {
+ if (this.attached) {
+ return;
+ }
+
+ Logger rootLogger = LogManager.getLogManager().getLogger("");
+ rootLogger.addHandler(this.handler);
+ this.attached = true;
+ }
+
+ private void detachFromRootLogger() {
+ if (!this.attached) {
+ return;
+ }
+
+ Logger rootLogger = LogManager.getLogManager().getLogger("");
+ rootLogger.removeHandler(this.handler);
+ this.attached = false;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.lttng.ust.agent.jul;
+
+import java.lang.String;
+
+import java.util.logging.Handler;
+import java.util.logging.LogRecord;
+
+class LTTngLogHandler extends Handler {
+ private Boolean is_root;
+
+ public LTTngLogHandler(Boolean isRoot) {
+ super();
+ this.is_root = isRoot;
+ /* Initialize LTTng UST tracer. */
+ try {
+ System.loadLibrary("lttng-ust-jul-jni"); //$NON-NLS-1$
+ } catch (SecurityException e) {
+ e.printStackTrace();
+ } catch (UnsatisfiedLinkError e) {
+ e.printStackTrace();
+ } catch (NullPointerException e) {
+ /* Should never happen */
+ e.printStackTrace();
+ }
+ }
+
+ public Boolean isRoot() {
+ return this.is_root;
+ }
+
+ @Override
+ public void close() throws SecurityException {}
+
+ @Override
+ public void flush() {}
+
+ @Override
+ public void publish(LogRecord record) {
+ /*
+ * Specific tracepoing designed for JUL events. The source class of the
+ * caller is used for the event name, the raw message is taken, the
+ * loglevel of the record and the thread ID.
+ */
+ if (this.is_root) {
+ tracepointS(record.getMessage(),
+ record.getLoggerName(), record.getSourceClassName(),
+ record.getSourceMethodName(), record.getMillis(),
+ record.getLevel().intValue(), record.getThreadID());
+ } else {
+ tracepointU(record.getMessage(),
+ record.getLoggerName(), record.getSourceClassName(),
+ record.getSourceMethodName(), record.getMillis(),
+ record.getLevel().intValue(), record.getThreadID());
+ }
+ }
+
+ /* Use for a user session daemon. */
+ private native void tracepointU(String msg, String logger_name, String class_name,
+ String method_name, long millis, int log_level, int thread_id);
+
+ /* Use for a root session daemon. */
+ private native void tracepointS(String msg, String logger_name, String class_name,
+ String method_name, long millis, int log_level, int thread_id);
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 - Christian Babeux <christian.babeux@efficios.com>
+ *
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.lttng.ust.agent.log4j;
+
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Vector;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+
+import org.lttng.ust.agent.LogFrameworkSkeleton;
+
+public class LTTngLog4j extends LogFrameworkSkeleton {
+
+ private LTTngLogAppender appender;
+ private Boolean attached;
+
+ public LTTngLog4j(Boolean isRoot) {
+ super();
+ this.appender = new LTTngLogAppender(isRoot);
+ this.attached = false;
+ }
+
+ @Override
+ public Boolean enableLogger(String name) {
+ if(!super.enableLogger(name)) {
+ return false;
+ }
+
+ /* The first enable of any event triggers the attachment to the root logger */
+ if (getEventCount() == 1 && !this.attached) {
+ attachToRootLogger();
+ }
+
+ return true;
+ }
+
+ @Override
+ public Boolean disableLogger(String name) {
+ if(!super.disableLogger(name)) {
+ return false;
+ }
+
+ /* Detach from the root logger when the event counts reach zero */
+ if (getEventCount() == 0 && this.attached) {
+ detachFromRootLogger();
+ }
+
+ return true;
+ }
+
+ @Override
+ public Iterator<String> listLoggers() {
+ Vector<String> logs = new Vector<String>();
+ for (Enumeration loggers = LogManager.getCurrentLoggers(); loggers.hasMoreElements(); ) {
+ Logger logger = (Logger) loggers.nextElement();
+ String name = logger.getName();
+ logs.add(name);
+ }
+
+ return logs.iterator();
+ }
+
+ @Override
+ public Boolean isRoot() {
+ return appender.isRoot();
+ }
+
+ @Override
+ public void reset() {
+ super.reset();
+ detachFromRootLogger();
+ }
+
+ private void attachToRootLogger() {
+ if (this.attached) {
+ return;
+ }
+
+ Logger logger = Logger.getRootLogger();
+ logger.addAppender(this.appender);
+ this.attached = true;
+ }
+
+ private void detachFromRootLogger() {
+ if (!this.attached) {
+ return;
+ }
+
+ Logger logger = Logger.getRootLogger();
+ logger.removeAppender(this.appender);
+ this.attached = false;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 - Christian Babeux <christian.babeux@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.lttng.ust.agent.log4j;
+
+import java.lang.String;
+
+import org.apache.log4j.AppenderSkeleton;
+import org.apache.log4j.spi.LoggingEvent;
+
+class LTTngLogAppender extends AppenderSkeleton {
+ private Boolean is_root;
+
+ public LTTngLogAppender(Boolean isRoot) {
+ super();
+ this.is_root = isRoot;
+ try {
+ System.loadLibrary("lttng-ust-log4j-jni"); //$NON-NLS-1$
+ } catch (SecurityException e) {
+ e.printStackTrace();
+ } catch (UnsatisfiedLinkError e) {
+ e.printStackTrace();
+ } catch (NullPointerException e) {
+ /* Should never happen */
+ e.printStackTrace();
+ }
+ }
+
+ public Boolean isRoot() {
+ return this.is_root;
+ }
+
+ @Override
+ protected void append(LoggingEvent event) {
+ int line;
+
+ /*
+ * The line number returned from LocationInformation is a
+ * string. At least try to convert to a proper int.
+ */
+ try {
+ String lineString = event.getLocationInformation().getLineNumber();
+ line = Integer.parseInt(lineString);
+ } catch (NumberFormatException n) {
+ line = -1;
+ }
+
+ if (this.is_root) {
+ tracepointS(event.getRenderedMessage(),
+ event.getLoggerName(),
+ event.getLocationInformation().getClassName(),
+ event.getLocationInformation().getMethodName(),
+ event.getLocationInformation().getFileName(),
+ line,
+ event.getTimeStamp(),
+ event.getLevel().toInt(),
+ event.getThreadName());
+ } else {
+ tracepointU(event.getRenderedMessage(),
+ event.getLoggerName(),
+ event.getLocationInformation().getClassName(),
+ event.getLocationInformation().getMethodName(),
+ event.getLocationInformation().getFileName(),
+ line,
+ event.getTimeStamp(),
+ event.getLevel().toInt(),
+ event.getThreadName());
+ }
+ }
+
+ @Override
+ public void close() {}
+
+ @Override
+ public boolean requiresLayout() {
+ return false;
+ }
+
+ /* Use for a user session daemon. */
+ private native void tracepointU(String msg,
+ String logger_name,
+ String class_name,
+ String method_name,
+ String file_name,
+ int line_number,
+ long timestamp,
+ int loglevel,
+ String thread_name);
+
+ /* Use for a root session daemon. */
+ private native void tracepointS(String msg,
+ String logger_name,
+ String class_name,
+ String method_name,
+ String file_name,
+ int line_number,
+ long timestamp,
+ int loglevel,
+ String thread_name);
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 - Christian Babeux <christian.babeux@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.lttng.ust.jul;
+
+import java.io.IOException;
+
+public class LTTngAgent {
+
+ /*
+ * !!! WARNING !!!
+ * Please use the LTTngAgent found in the org.lttng.ust.agent package.
+ * This class is DEPRECATED.
+ */
+
+ private static LTTngAgent curAgent = null;
+ private static org.lttng.ust.agent.LTTngAgent realAgent = null;
+
+
+ private LTTngAgent() throws IOException {
+ realAgent = org.lttng.ust.agent.LTTngAgent.getLTTngAgent();
+ }
+
+ public static synchronized LTTngAgent getLTTngAgent() throws IOException {
+ if (curAgent == null) {
+ curAgent = new LTTngAgent();
+ }
+
+ return curAgent;
+ }
+
+ public void dispose() throws IOException {
+ realAgent.dispose();
+ }
+}
--- /dev/null
+SUBDIRS=
+if BUILD_JAVA_AGENT_WITH_JUL
+SUBDIRS += jul
+endif
+
+if BUILD_JAVA_AGENT_WITH_LOG4J
+SUBDIRS += log4j
+endif
--- /dev/null
+AM_CPPFLAGS = -I$(top_srcdir)/include
+
+lib_LTLIBRARIES = liblttng-ust-jul-jni.la
+liblttng_ust_jul_jni_la_SOURCES = lttng_ust_jul.c \
+ lttng_ust_jul.h
+
+nodist_liblttng_ust_jul_jni_la_SOURCES = org_lttng_ust_agent_jul_LTTngLogHandler.h
+
+liblttng_ust_jul_jni_la_LIBADD = -lc -L$(top_builddir)/liblttng-ust/.libs -llttng-ust
--- /dev/null
+/*
+ * Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; only
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "org_lttng_ust_agent_jul_LTTngLogHandler.h"
+
+#define TRACEPOINT_DEFINE
+#define TRACEPOINT_CREATE_PROBES
+#include "lttng_ust_jul.h"
+
+/*
+ * System tracepoint meaning only root agent will fire this.
+ */
+JNIEXPORT void JNICALL Java_org_lttng_ust_agent_jul_LTTngLogHandler_tracepointS(JNIEnv *env,
+ jobject jobj,
+ jstring msg,
+ jstring logger_name,
+ jstring class_name,
+ jstring method_name,
+ jlong millis,
+ jint log_level,
+ jint thread_id)
+{
+ jboolean iscopy;
+ const char *msg_cstr = (*env)->GetStringUTFChars(env, msg, &iscopy);
+ const char *logger_name_cstr = (*env)->GetStringUTFChars(env, logger_name, &iscopy);
+ const char *class_name_cstr = (*env)->GetStringUTFChars(env, class_name, &iscopy);
+ const char *method_name_cstr = (*env)->GetStringUTFChars(env, method_name, &iscopy);
+
+ tracepoint(lttng_jul, sys_event, msg_cstr, logger_name_cstr,
+ class_name_cstr, method_name_cstr, millis, log_level, thread_id);
+
+ (*env)->ReleaseStringUTFChars(env, msg, msg_cstr);
+ (*env)->ReleaseStringUTFChars(env, logger_name, logger_name_cstr);
+ (*env)->ReleaseStringUTFChars(env, class_name, class_name_cstr);
+ (*env)->ReleaseStringUTFChars(env, method_name, method_name_cstr);
+}
+
+/*
+ * User tracepoint meaning only a non root agent will fire this.
+ */
+JNIEXPORT void JNICALL Java_org_lttng_ust_agent_jul_LTTngLogHandler_tracepointU(JNIEnv *env,
+ jobject jobj,
+ jstring msg,
+ jstring logger_name,
+ jstring class_name,
+ jstring method_name,
+ jlong millis,
+ jint log_level,
+ jint thread_id)
+{
+ jboolean iscopy;
+ const char *msg_cstr = (*env)->GetStringUTFChars(env, msg, &iscopy);
+ const char *logger_name_cstr = (*env)->GetStringUTFChars(env, logger_name, &iscopy);
+ const char *class_name_cstr = (*env)->GetStringUTFChars(env, class_name, &iscopy);
+ const char *method_name_cstr = (*env)->GetStringUTFChars(env, method_name, &iscopy);
+
+ tracepoint(lttng_jul, user_event, msg_cstr, logger_name_cstr,
+ class_name_cstr, method_name_cstr, millis, log_level, thread_id);
+
+ (*env)->ReleaseStringUTFChars(env, msg, msg_cstr);
+ (*env)->ReleaseStringUTFChars(env, logger_name, logger_name_cstr);
+ (*env)->ReleaseStringUTFChars(env, class_name, class_name_cstr);
+ (*env)->ReleaseStringUTFChars(env, method_name, method_name_cstr);
+}
--- /dev/null
+#undef TRACEPOINT_PROVIDER
+#define TRACEPOINT_PROVIDER lttng_jul
+
+#if !defined(_TRACEPOINT_LTTNG_UST_JUL_H) || defined(TRACEPOINT_HEADER_MULTI_READ)
+#define _TRACEPOINT_LTTNG_UST_JUL_H
+
+/*
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; version 2.1 of
+ * the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <lttng/tracepoint.h>
+
+/*
+ * Privileged tracepoint meaning that this is only enable and fired by the root
+ * session daemon.
+ */
+TRACEPOINT_EVENT(lttng_jul, sys_event,
+ TP_ARGS(
+ const char *, msg,
+ const char *, logger_name,
+ const char *, class_name,
+ const char *, method_name,
+ long, millis,
+ int, log_level,
+ int, thread_id),
+ TP_FIELDS(
+ ctf_string(msg, msg)
+ ctf_string(logger_name, logger_name)
+ ctf_string(class_name, class_name)
+ ctf_string(method_name, method_name)
+ ctf_integer(long, long_millis, millis)
+ ctf_integer(int, int_loglevel, log_level)
+ ctf_integer(int, int_threadid, thread_id)
+ )
+)
+
+/*
+ * User tracepoint meaning that this is only enable and fired by a non root
+ * session daemon.
+ */
+TRACEPOINT_EVENT(lttng_jul, user_event,
+ TP_ARGS(
+ const char *, msg,
+ const char *, logger_name,
+ const char *, class_name,
+ const char *, method_name,
+ long, millis,
+ int, log_level,
+ int, thread_id),
+ TP_FIELDS(
+ ctf_string(msg, msg)
+ ctf_string(logger_name, logger_name)
+ ctf_string(class_name, class_name)
+ ctf_string(method_name, method_name)
+ ctf_integer(long, long_millis, millis)
+ ctf_integer(int, int_loglevel, log_level)
+ ctf_integer(int, int_threadid, thread_id)
+ )
+)
+
+#endif /* _TRACEPOINT_LTTNG_UST_JUL_H */
+
+#undef TRACEPOINT_INCLUDE
+#define TRACEPOINT_INCLUDE "./lttng_ust_jul.h"
+
+/* This part must be outside protection */
+#include <lttng/tracepoint-event.h>
--- /dev/null
+AM_CPPFLAGS = -I$(top_srcdir)/include
+lib_LTLIBRARIES = liblttng-ust-log4j-jni.la
+liblttng_ust_log4j_jni_la_SOURCES = lttng_ust_log4j.c \
+ lttng_ust_log4j.h
+
+nodist_liblttng_ust_log4j_jni_la_SOURCES = org_lttng_ust_agent_log4j_LTTngLogAppender.h
+
+liblttng_ust_log4j_jni_la_LIBADD = -lc -L$(top_builddir)/liblttng-ust/.libs -llttng-ust
--- /dev/null
+/*
+ * Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; only
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "org_lttng_ust_agent_log4j_LTTngLogAppender.h"
+
+#define TRACEPOINT_DEFINE
+#define TRACEPOINT_CREATE_PROBES
+#include "lttng_ust_log4j.h"
+
+/*
+ * System tracepoint meaning only root agent will fire this.
+ */
+JNIEXPORT void JNICALL Java_org_lttng_ust_agent_log4j_LTTngLogAppender_tracepointS(JNIEnv *env,
+ jobject jobj,
+ jstring msg,
+ jstring logger_name,
+ jstring class_name,
+ jstring method_name,
+ jstring file_name,
+ jint line_number,
+ jlong timestamp,
+ jint loglevel,
+ jstring thread_name)
+{
+ jboolean iscopy;
+ const char *msg_cstr = (*env)->GetStringUTFChars(env, msg, &iscopy);
+ const char *logger_name_cstr = (*env)->GetStringUTFChars(env, logger_name, &iscopy);
+ const char *class_name_cstr = (*env)->GetStringUTFChars(env, class_name, &iscopy);
+ const char *method_name_cstr = (*env)->GetStringUTFChars(env, method_name, &iscopy);
+ const char *file_name_cstr = (*env)->GetStringUTFChars(env, file_name, &iscopy);
+ const char *thread_name_cstr = (*env)->GetStringUTFChars(env, thread_name, &iscopy);
+
+ tracepoint(lttng_log4j, sys_event, msg_cstr, logger_name_cstr,
+ class_name_cstr, method_name_cstr, file_name_cstr,
+ line_number, timestamp, loglevel, thread_name_cstr);
+
+ (*env)->ReleaseStringUTFChars(env, msg, msg_cstr);
+ (*env)->ReleaseStringUTFChars(env, logger_name, logger_name_cstr);
+ (*env)->ReleaseStringUTFChars(env, class_name, class_name_cstr);
+ (*env)->ReleaseStringUTFChars(env, method_name, method_name_cstr);
+ (*env)->ReleaseStringUTFChars(env, file_name, file_name_cstr);
+ (*env)->ReleaseStringUTFChars(env, thread_name, thread_name_cstr);
+}
+
+/*
+ * User tracepoint meaning only a non root agent will fire this.
+ */
+JNIEXPORT void JNICALL Java_org_lttng_ust_agent_log4j_LTTngLogAppender_tracepointU(JNIEnv *env,
+ jobject jobj,
+ jstring msg,
+ jstring logger_name,
+ jstring class_name,
+ jstring method_name,
+ jstring file_name,
+ jint line_number,
+ jlong timestamp,
+ jint loglevel,
+ jstring thread_name)
+{
+ jboolean iscopy;
+ const char *msg_cstr = (*env)->GetStringUTFChars(env, msg, &iscopy);
+ const char *logger_name_cstr = (*env)->GetStringUTFChars(env, logger_name, &iscopy);
+ const char *class_name_cstr = (*env)->GetStringUTFChars(env, class_name, &iscopy);
+ const char *method_name_cstr = (*env)->GetStringUTFChars(env, method_name, &iscopy);
+ const char *file_name_cstr = (*env)->GetStringUTFChars(env, file_name, &iscopy);
+ const char *thread_name_cstr = (*env)->GetStringUTFChars(env, thread_name, &iscopy);
+
+ tracepoint(lttng_log4j, user_event, msg_cstr, logger_name_cstr,
+ class_name_cstr, method_name_cstr, file_name_cstr,
+ line_number, timestamp, loglevel, thread_name_cstr);
+
+ (*env)->ReleaseStringUTFChars(env, msg, msg_cstr);
+ (*env)->ReleaseStringUTFChars(env, logger_name, logger_name_cstr);
+ (*env)->ReleaseStringUTFChars(env, class_name, class_name_cstr);
+ (*env)->ReleaseStringUTFChars(env, method_name, method_name_cstr);
+ (*env)->ReleaseStringUTFChars(env, file_name, file_name_cstr);
+ (*env)->ReleaseStringUTFChars(env, thread_name, thread_name_cstr);
+}
--- /dev/null
+#undef TRACEPOINT_PROVIDER
+#define TRACEPOINT_PROVIDER lttng_log4j
+
+#if !defined(_TRACEPOINT_LTTNG_UST_LOG4J_H) || defined(TRACEPOINT_HEADER_MULTI_READ)
+#define _TRACEPOINT_LTTNG_UST_LOG4J_H
+
+/*
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; version 2.1 of
+ * the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <lttng/tracepoint.h>
+
+/*
+ * Privileged tracepoint meaning that this is only enable and fired by the root
+ * session daemon.
+ */
+TRACEPOINT_EVENT(lttng_log4j, sys_event,
+ TP_ARGS(
+ const char *, msg,
+ const char *, logger_name,
+ const char *, class_name,
+ const char *, method_name,
+ const char *, file_name,
+ int, line_number,
+ long, timestamp,
+ int, log_level,
+ const char *, thread_name),
+ TP_FIELDS(
+ ctf_string(msg, msg)
+ ctf_string(logger_name, logger_name)
+ ctf_string(class_name, class_name)
+ ctf_string(method_name, method_name)
+ ctf_string(filename, file_name)
+ ctf_integer(int, line_number, line_number)
+ ctf_integer(long, timestamp, timestamp)
+ ctf_integer(int, int_loglevel, log_level)
+ ctf_string(thread_name, thread_name)
+ )
+)
+
+/*
+ * User tracepoint meaning that this is only enable and fired by a non root
+ * session daemon.
+ */
+TRACEPOINT_EVENT(lttng_log4j, user_event,
+ TP_ARGS(
+ const char *, msg,
+ const char *, logger_name,
+ const char *, class_name,
+ const char *, method_name,
+ const char *, file_name,
+ int, line_number,
+ long, timestamp,
+ int, log_level,
+ const char *, thread_name),
+ TP_FIELDS(
+ ctf_string(msg, msg)
+ ctf_string(logger_name, logger_name)
+ ctf_string(class_name, class_name)
+ ctf_string(method_name, method_name)
+ ctf_string(filename, file_name)
+ ctf_integer(int, line_number, line_number)
+ ctf_integer(long, timestamp, timestamp)
+ ctf_integer(int, int_loglevel, log_level)
+ ctf_string(thread_name, thread_name)
+ )
+)
+
+#endif /* _TRACEPOINT_LTTNG_UST_LOG4J_H */
+
+#undef TRACEPOINT_INCLUDE
+#define TRACEPOINT_INCLUDE "./lttng_ust_log4j.h"
+
+/* This part must be outside protection */
+#include <lttng/tracepoint-event.h>
+++ /dev/null
-/*
- * Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; only
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "org_lttng_ust_jul_LTTngUst.h"
-
-#define TRACEPOINT_DEFINE
-#define TRACEPOINT_CREATE_PROBES
-#include "lttng_ust_jul.h"
-
-/*
- * System tracepoint meaning only root agent will fire this.
- */
-JNIEXPORT void JNICALL Java_org_lttng_ust_jul_LTTngUst_tracepointS(JNIEnv *env,
- jobject jobj,
- jstring msg,
- jstring logger_name,
- jstring class_name,
- jstring method_name,
- jlong millis,
- jint log_level,
- jint thread_id)
-{
- jboolean iscopy;
- const char *msg_cstr = (*env)->GetStringUTFChars(env, msg, &iscopy);
- const char *logger_name_cstr = (*env)->GetStringUTFChars(env, logger_name, &iscopy);
- const char *class_name_cstr = (*env)->GetStringUTFChars(env, class_name, &iscopy);
- const char *method_name_cstr = (*env)->GetStringUTFChars(env, method_name, &iscopy);
-
- tracepoint(lttng_jul, sys_event, msg_cstr, logger_name_cstr,
- class_name_cstr, method_name_cstr, millis, log_level, thread_id);
-
- (*env)->ReleaseStringUTFChars(env, msg, msg_cstr);
- (*env)->ReleaseStringUTFChars(env, logger_name, logger_name_cstr);
- (*env)->ReleaseStringUTFChars(env, class_name, class_name_cstr);
- (*env)->ReleaseStringUTFChars(env, method_name, method_name_cstr);
-}
-
-/*
- * User tracepoint meaning only a non root agent will fire this.
- */
-JNIEXPORT void JNICALL Java_org_lttng_ust_jul_LTTngUst_tracepointU(JNIEnv *env,
- jobject jobj,
- jstring msg,
- jstring logger_name,
- jstring class_name,
- jstring method_name,
- jlong millis,
- jint log_level,
- jint thread_id)
-{
- jboolean iscopy;
- const char *msg_cstr = (*env)->GetStringUTFChars(env, msg, &iscopy);
- const char *logger_name_cstr = (*env)->GetStringUTFChars(env, logger_name, &iscopy);
- const char *class_name_cstr = (*env)->GetStringUTFChars(env, class_name, &iscopy);
- const char *method_name_cstr = (*env)->GetStringUTFChars(env, method_name, &iscopy);
-
- tracepoint(lttng_jul, user_event, msg_cstr, logger_name_cstr,
- class_name_cstr, method_name_cstr, millis, log_level, thread_id);
-
- (*env)->ReleaseStringUTFChars(env, msg, msg_cstr);
- (*env)->ReleaseStringUTFChars(env, logger_name, logger_name_cstr);
- (*env)->ReleaseStringUTFChars(env, class_name, class_name_cstr);
- (*env)->ReleaseStringUTFChars(env, method_name, method_name_cstr);
-}
+++ /dev/null
-LTTNG_JUL_SRCDIR = $(srcdir)/org/lttng/ust/jul
-LTTNG_JUL_DESTDIR = $(builddir)/org/lttng/ust/jul
-
-if BUILD_JNI_INTERFACE
-
-AM_CPPFLAGS = -I$(top_srcdir)/include -I$(builddir) -I$(top_builddir)/include
-
-BUILT_SOURCES = org_lttng_ust_jul_LTTngUst.h
-lib_LTLIBRARIES = liblttng-ust-jul-jni.la
-liblttng_ust_jul_jni_la_SOURCES = LTTngUst.c lttng_ust_jul.h
-nodist_liblttng_ust_jul_jni_la_SOURCES = org_lttng_ust_jul_LTTngUst.h
-dist_noinst_DATA = $(LTTNG_JUL_SRCDIR)/LTTngUst.java \
- $(LTTNG_JUL_SRCDIR)/LTTngAgent.java \
- $(LTTNG_JUL_SRCDIR)/LTTngEvent.java \
- $(LTTNG_JUL_SRCDIR)/LTTngLogHandler.java \
- $(LTTNG_JUL_SRCDIR)/LTTngSessiondCmd2_4.java \
- $(LTTNG_JUL_SRCDIR)/LTTngTCPSessiondClient.java \
- $(LTTNG_JUL_SRCDIR)/LTTngThread.java
-liblttng_ust_jul_jni_la_LIBADD = -lc -L$(top_builddir)/liblttng-ust/.libs -llttng-ust
-
-lttnglibjava_DATA = liblttng-ust-jul.jar
-
-if HAVE_JAVA_JDK
-JCC=$(JAVA_JDK)/bin
-else
-JCC=javac
-endif
-
-all-local: $(LTTNG_JUL_DESTDIR)/LTTngAgent.class \
- $(LTTNG_JUL_DESTDIR)/LTTngUst.class \
- org_lttng_ust_jul_LTTngUst.h \
- liblttng-ust-jul.jar
-
-clean-local:
- rm -f org_lttng_ust_jul_LTTngUst.h
- rm -f liblttng-ust-jul.jar
- rm -f org/lttng/ust/jul/*.class
-
-%.class: %.java
- $(JCC)/javac -d "$(builddir)" $<
-
-LTTNG_AGENT_FILES = $(LTTNG_JUL_SRCDIR)/LTTngAgent.java \
- $(LTTNG_JUL_SRCDIR)/LTTngLogHandler.java \
- $(LTTNG_JUL_SRCDIR)/LTTngEvent.java \
- $(LTTNG_JUL_SRCDIR)/LTTngSessiondCmd2_4.java \
- $(LTTNG_JUL_SRCDIR)/LTTngTCPSessiondClient.java \
- $(LTTNG_JUL_SRCDIR)/LTTngThread.java
-
-$(LTTNG_JUL_DESTDIR)/LTTngAgent.class: $(LTTNG_AGENT_FILES) \
- $(LTTNG_JUL_DESTDIR)/LTTngUst.class
- $(JCC)/javac -d "$(builddir)" $(LTTNG_AGENT_FILES)
-
-org_lttng_ust_jul_LTTngUst.h: $(LTTNG_JUL_DESTDIR)/LTTngUst.class
- $(JCC)/javah org.lttng.ust.jul.LTTngUst
-
-liblttng-ust-jul.jar: $(LTTNG_JUL_DESTDIR)/LTTngAgent.class
- $(JCC)/jar cf liblttng-ust-jul.jar \
- $(LTTNG_JUL_DESTDIR)/*.class
-
-endif
+++ /dev/null
-#undef TRACEPOINT_PROVIDER
-#define TRACEPOINT_PROVIDER lttng_jul
-
-#if !defined(_TRACEPOINT_LTTNG_UST_JUL_H) || defined(TRACEPOINT_HEADER_MULTI_READ)
-#define _TRACEPOINT_LTTNG_UST_JUL_H
-
-/*
- * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; version 2.1 of
- * the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <lttng/tracepoint.h>
-
-/*
- * Privileged tracepoint meaning that this is only enable and fired by the root
- * session daemon.
- */
-TRACEPOINT_EVENT(lttng_jul, sys_event,
- TP_ARGS(
- const char *, msg,
- const char *, logger_name,
- const char *, class_name,
- const char *, method_name,
- long, millis,
- int, log_level,
- int, thread_id),
- TP_FIELDS(
- ctf_string(msg, msg)
- ctf_string(logger_name, logger_name)
- ctf_string(class_name, class_name)
- ctf_string(method_name, method_name)
- ctf_integer(long, long_millis, millis)
- ctf_integer(int, int_loglevel, log_level)
- ctf_integer(int, int_threadid, thread_id)
- )
-)
-
-/*
- * User tracepoint meaning that this is only enable and fired by a non root
- * session daemon.
- */
-TRACEPOINT_EVENT(lttng_jul, user_event,
- TP_ARGS(
- const char *, msg,
- const char *, logger_name,
- const char *, class_name,
- const char *, method_name,
- long, millis,
- int, log_level,
- int, thread_id),
- TP_FIELDS(
- ctf_string(msg, msg)
- ctf_string(logger_name, logger_name)
- ctf_string(class_name, class_name)
- ctf_string(method_name, method_name)
- ctf_integer(long, long_millis, millis)
- ctf_integer(int, int_loglevel, log_level)
- ctf_integer(int, int_threadid, thread_id)
- )
-)
-
-#endif /* _TRACEPOINT_LTTNG_UST_JUL_H */
-
-#undef TRACEPOINT_INCLUDE
-#define TRACEPOINT_INCLUDE "./lttng_ust_jul.h"
-
-/* This part must be outside protection */
-#include <lttng/tracepoint-event.h>
import java.util.Enumeration;
public class LTTngAgent {
- private static LogManager logManager;
/* Possible that we have to threads handling two sessiond. */
private static LTTngLogHandler lttngHandlerRoot;
*/
private LTTngAgent() throws IOException {
this.logManager = LogManager.getLogManager();
- this.lttngHandlerUser = new LTTngLogHandler(this.logManager);
- this.lttngHandlerRoot = new LTTngLogHandler(this.logManager);
+ this.lttngHandlerUser = new LTTngLogHandler();
+ this.lttngHandlerRoot = new LTTngLogHandler();
this.lttngHandlerRoot.is_root = 1;
this.registerSem = new Semaphore(0, true);
}
- private void removeHandlers() throws SecurityException, IOException {
- String loggerName;
- Logger logger;
-
- Enumeration list = this.logManager.getLoggerNames();
- while (list.hasMoreElements()) {
- loggerName = list.nextElement().toString();
- /* Somehow there is always an empty string at the end. */
- if (loggerName == "") {
- continue;
- }
-
- logger = this.logManager.getLogger(loggerName);
- logger.removeHandler(this.lttngHandlerUser);
- logger.removeHandler(this.lttngHandlerRoot);
- }
- }
-
- private int getUID() throws IOException {
- int uid;
- byte b[] = new byte[4];
- String userName = System.getProperty("user.name");
- String command = "id -u " + userName;
- Process child = Runtime.getRuntime().exec(command);
- InputStream in = child.getInputStream();
-
- in.read(b);
- uid = Integer.parseInt(new String(b).trim(), 10);
- in.close();
-
- return uid;
- }
-
/*
* Public getter to acquire a reference to this singleton object.
*/
}
public void dispose() throws IOException {
- this.lttngThreadUser.dispose();
- if (this.lttngThreadRoot != null) {
- this.lttngThreadRoot.dispose();
- }
+ this.lttngJULThreadUser.dispose();
+ this.lttngJULThreadRoot.dispose();
- /* Make sure there is no more LTTng handler attach to logger(s). */
- this.removeHandlers();
+ /* Remove handlers from the root logger */
+ Logger rootLogger = LogManager.getLogManager().getLogger("");
+ rootLogger.removeHandler(this.lttngHandlerUser);
+ rootLogger.removeHandler(this.lttngHandlerRoot);
try {
this.sessiondThUser.join();
- if (this.sessiondThRoot != null) {
- this.sessiondThRoot.join();
- }
+ this.sessiondThRoot.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
+++ /dev/null
-/*
- * Copyright (C) 2014 - David Goulet <dgoulet@efficios.com>
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License, version 2.1 only,
- * as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-package org.lttng.ust.jul;
-
-import java.lang.String;
-
-import org.lttng.ust.jul.LTTngUst;
-
-class LTTngLogLevel {
- /* This level is a JUL int level value. */
- public int level;
- public int type;
-
- public LTTngLogLevel(int level, int type) {
- this.type = type;
- this.level = level;
- }
-}
-
-public class LTTngEvent {
- /* Name of the event. */
- public String name;
- public LTTngLogLevel logLevel;
-
- public LTTngEvent(String name, int loglevel, int loglevel_type) {
- this.name = name;
- this.logLevel = new LTTngLogLevel(loglevel, loglevel_type);
- }
-}
public int is_root = 0;
public int refcount = 0;
- public LogManager logManager;
-
/* Logger object attached to this handler that can trigger a tracepoint. */
public Map<String, LTTngEvent> enabledEvents =
Collections.synchronizedMap(new HashMap<String, LTTngEvent>());
/* Constructor */
- public LTTngLogHandler(LogManager logManager) {
+ public LTTngLogHandler() {
super();
-
- this.logManager = logManager;
-
/* Initialize LTTng UST tracer. */
LTTngUst.init();
}
+++ /dev/null
-/*
- * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
- *
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License, version 2.1 only,
- * as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-package org.lttng.ust.jul;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.lang.Object;
-import java.util.logging.Logger;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Enumeration;
-
-public interface LTTngSessiondCmd2_4 {
- /**
- * Maximum name length for a logger name to be send to sessiond.
- */
- final static int NAME_MAX = 255;
-
- /*
- * Size of a primitive type int in byte. Because you know, Java can't
- * provide that since it does not makes sense...
- */
- final static int INT_SIZE = 4;
-
- public interface SessiondResponse {
- /**
- * Gets a byte array of the command so that it may be streamed
- *
- * @return the byte array of the command
- */
- public byte[] getBytes();
- }
-
- public interface SessiondCommand {
- /**
- * Populate the class from a byte array
- *
- * @param data
- * the byte array containing the streamed command
- */
- public void populate(byte[] data);
- }
-
- public enum lttng_jul_command {
- /** List logger(s). */
- CMD_LIST(1),
- /** Enable logger by name. */
- CMD_ENABLE(2),
- /** Disable logger by name. */
- CMD_DISABLE(3),
- /** Registration done */
- CMD_REG_DONE(4);
-
- private int code;
-
- private lttng_jul_command(int c) {
- code = c;
- }
-
- public int getCommand() {
- return code;
- }
- }
-
- enum lttng_jul_ret_code {
- CODE_SUCCESS_CMD(1),
- CODE_INVALID_CMD(2),
- CODE_UNK_LOGGER_NAME(3);
- private int code;
-
- private lttng_jul_ret_code(int c) {
- code = c;
- }
-
- public int getCode() {
- return code;
- }
- }
-
- public class sessiond_hdr implements SessiondCommand {
- /** ABI size of command header. */
- public final static int SIZE = 16;
- /** Payload size in bytes following this header. */
- public long data_size;
- /** Command type. */
- public lttng_jul_command cmd;
- /** Command version. */
- public int cmd_version;
-
- public void populate(byte[] data) {
- ByteBuffer buf = ByteBuffer.wrap(data);
- buf.order(ByteOrder.BIG_ENDIAN);
-
- data_size = buf.getLong();
- cmd = lttng_jul_command.values()[buf.getInt() - 1];
- cmd_version = buf.getInt();
- }
- }
-
- public class sessiond_enable_handler implements SessiondResponse, SessiondCommand {
- private final static int SIZE = 4;
- public String name;
- public int lttngLogLevel;
- public int lttngLogLevelType;
-
- /** Return status code to the session daemon. */
- public lttng_jul_ret_code code;
-
- @Override
- public void populate(byte[] data) {
- int data_offset = INT_SIZE * 2;
-
- ByteBuffer buf = ByteBuffer.wrap(data);
- buf.order(ByteOrder.LITTLE_ENDIAN);
- lttngLogLevel = buf.getInt();
- lttngLogLevelType = buf.getInt();
- name = new String(data, data_offset, data.length - data_offset).trim();
- }
-
- @Override
- public byte[] getBytes() {
- byte data[] = new byte[SIZE];
- ByteBuffer buf = ByteBuffer.wrap(data);
- buf.order(ByteOrder.BIG_ENDIAN);
- buf.putInt(code.getCode());
- return data;
- }
-
- /**
- * Execute enable handler action which is to enable the given handler
- * to the received name.
- *
- * @return Event name as a string if the event is NOT found thus was
- * not enabled.
- */
- public void execute(LTTngLogHandler handler) {
- LTTngEvent event;
-
- if (this.name == null) {
- this.code = lttng_jul_ret_code.CODE_INVALID_CMD;
- return;
- }
-
- /* Add event to the enabled events hash map. */
- event = handler.enabledEvents.put(this.name,
- new LTTngEvent(this.name, 0, 0));
- if (event != null) {
- /* The event exists so skip updating the refcount. */
- this.code = lttng_jul_ret_code.CODE_SUCCESS_CMD;
- return;
- }
-
- /*
- * Get the root logger and attach to it if it's the first enable
- * seen by the handler.
- */
- Logger rootLogger = handler.logManager.getLogger("");
-
- handler.refcount++;
- if (handler.refcount == 1) {
- /* Add handler only if it's the first enable. */
- rootLogger.addHandler(handler);
- }
-
- this.code = lttng_jul_ret_code.CODE_SUCCESS_CMD;
- return;
- }
- }
-
- public class sessiond_disable_handler implements SessiondResponse, SessiondCommand {
- private final static int SIZE = 4;
- public String name;
- public int lttngLogLevel;
- public int lttngLogLevelType;
-
- /** Return status code to the session daemon. */
- public lttng_jul_ret_code code;
-
- @Override
- public void populate(byte[] data) {
- ByteBuffer buf = ByteBuffer.wrap(data);
- buf.order(ByteOrder.LITTLE_ENDIAN);
- name = new String(data).trim();
- }
-
- @Override
- public byte[] getBytes() {
- byte data[] = new byte[SIZE];
- ByteBuffer buf = ByteBuffer.wrap(data);
- buf.order(ByteOrder.BIG_ENDIAN);
- buf.putInt(code.getCode());
- return data;
- }
-
- /**
- * Execute disable handler action which is to disable the given handler
- * to the received name.
- */
- public void execute(LTTngLogHandler handler) {
- LTTngEvent event;
-
- if (this.name == null) {
- this.code = lttng_jul_ret_code.CODE_INVALID_CMD;
- return;
- }
-
- /*
- * Try to remove the logger name from the events map and if we
- * can't, just skip the refcount update since the event was never
- * enabled.
- */
- event = handler.enabledEvents.remove(this.name);
- if (event == null) {
- /* The event didn't exists so skip updating the refcount. */
- this.code = lttng_jul_ret_code.CODE_INVALID_CMD;
- return;
- }
-
- Logger rootLogger = handler.logManager.getLogger("");
-
- handler.refcount--;
- if (handler.refcount == 0) {
- rootLogger.removeHandler(handler);
- }
-
- this.code = lttng_jul_ret_code.CODE_SUCCESS_CMD;
- return;
- }
- }
-
- public class sessiond_list_logger implements SessiondResponse {
- private final static int SIZE = 12;
-
- private int data_size = 0;
- private int nb_logger = 0;
-
- List<String> logger_list = new ArrayList<String>();
-
- /** Return status code to the session daemon. */
- public lttng_jul_ret_code code;
-
- @Override
- public byte[] getBytes() {
- byte data[] = new byte[SIZE + data_size];
- ByteBuffer buf = ByteBuffer.wrap(data);
- buf.order(ByteOrder.BIG_ENDIAN);
-
- /* Returned code */
- buf.putInt(code.getCode());
- buf.putInt(data_size);
- buf.putInt(nb_logger);
-
- for (String logger: logger_list) {
- buf.put(logger.getBytes());
- /* NULL terminated byte after the logger name. */
- buf.put((byte) 0x0);
- }
- return data;
- }
-
- /**
- * Execute enable handler action which is to enable the given handler
- * to the received name.
- */
- public void execute(LTTngLogHandler handler) {
- String loggerName;
-
- Enumeration loggers = handler.logManager.getLoggerNames();
- while (loggers.hasMoreElements()) {
- loggerName = loggers.nextElement().toString();
- /* Somehow there is always an empty string at the end. */
- if (loggerName == "") {
- continue;
- }
-
- this.logger_list.add(loggerName);
- this.nb_logger++;
- this.data_size += loggerName.length() + 1;
- }
-
- this.code = lttng_jul_ret_code.CODE_SUCCESS_CMD;
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License, version 2.1 only,
- * as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-package org.lttng.ust.jul;
-
-import java.util.concurrent.Semaphore;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.lang.Integer;
-import java.io.IOException;
-import java.io.BufferedOutputStream;
-import java.io.BufferedReader;
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-import java.io.DataInputStream;
-import java.io.FileReader;
-import java.io.FileNotFoundException;
-import java.net.*;
-import java.lang.management.ManagementFactory;
-import java.util.logging.Logger;
-
-class USTRegisterMsg {
- public static int pid;
-}
-
-public class LTTngTCPSessiondClient {
- /* Command header from the session deamon. */
- private LTTngSessiondCmd2_4.sessiond_hdr headerCmd =
- new LTTngSessiondCmd2_4.sessiond_hdr();
-
- private final String sessiondHost;
- private Socket sessiondSock;
- private boolean quit = false;
-
- private DataInputStream inFromSessiond;
- private DataOutputStream outToSessiond;
-
- private LTTngLogHandler handler;
-
- private Semaphore registerSem;
-
- private static final String rootPortFile = "/var/run/lttng/agent.port";
- private static final String userPortFile = "/.lttng/agent.port";
- /*
- * This is taken from the lttng/domain.h file which is mapped to
- * LTTNG_DOMAIN_JUL value for this agent.
- */
- private static final int agent_domain = 3;
-
- /* Indicate if we've already release the semaphore. */
- private boolean sem_posted = false;
-
- public LTTngTCPSessiondClient(String host, Semaphore sem) {
- this.sessiondHost = host;
- this.registerSem = sem;
- }
-
- /*
- * Try to release the registerSem if it's not already done.
- */
- private void tryReleaseSem()
- {
- /* Release semaphore so we unblock the agent. */
- if (!this.sem_posted) {
- this.registerSem.release();
- this.sem_posted = true;
- }
- }
-
- /*
- * Cleanup Agent state.
- */
- private void cleanupState() {
- if (this.handler != null) {
- this.handler.clear();
- }
- }
-
- public void init(LTTngLogHandler handler) throws InterruptedException {
- this.handler = handler;
-
- for (;;) {
- if (this.quit) {
- break;
- }
-
- /* Cleanup Agent state before trying to connect or reconnect. */
- cleanupState();
-
- try {
-
- /*
- * Connect to the session daemon before anything else.
- */
- connectToSessiond();
-
- /*
- * Register to the session daemon as the Java component of the
- * UST application.
- */
- registerToSessiond();
-
- /*
- * Block on socket receive and wait for command from the
- * session daemon. This will return if and only if there is a
- * fatal error or the socket closes.
- */
- handleSessiondCmd();
- } catch (UnknownHostException uhe) {
- tryReleaseSem();
- System.out.println(uhe);
- } catch (IOException ioe) {
- tryReleaseSem();
- Thread.sleep(3000);
- } catch (Exception e) {
- tryReleaseSem();
- e.printStackTrace();
- }
- }
- }
-
- public void destroy() {
- this.quit = true;
-
- try {
- if (this.sessiondSock != null) {
- this.sessiondSock.close();
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- /*
- * Receive header data from the session daemon using the LTTng command
- * static buffer of the right size.
- */
- private void recvHeader() throws Exception {
- int read_len;
- byte data[] = new byte[this.headerCmd.SIZE];
-
- read_len = this.inFromSessiond.read(data, 0, data.length);
- if (read_len != data.length) {
- throw new IOException();
- }
- this.headerCmd.populate(data);
- }
-
- /*
- * Receive payload from the session daemon. This MUST be done after a
- * recvHeader() so the header value of a command are known.
- *
- * The caller SHOULD use isPayload() before which returns true if a payload
- * is expected after the header.
- */
- private byte[] recvPayload() throws Exception {
- byte payload[] = new byte[(int) this.headerCmd.data_size];
-
- /* Failsafe check so we don't waste our time reading 0 bytes. */
- if (payload.length == 0) {
- return null;
- }
-
- this.inFromSessiond.read(payload, 0, payload.length);
- return payload;
- }
-
- /*
- * Handle session command from the session daemon.
- */
- private void handleSessiondCmd() throws Exception {
- int ret_code;
- byte data[] = null;
-
- while (true) {
- /* Get header from session daemon. */
- recvHeader();
-
- if (headerCmd.data_size > 0) {
- data = recvPayload();
- }
-
- switch (headerCmd.cmd) {
- case CMD_REG_DONE:
- {
- /*
- * Release semaphore so meaning registration is done and we
- * can proceed to continue tracing.
- */
- tryReleaseSem();
- /*
- * We don't send any reply to the registration done command.
- * This just marks the end of the initial session setup.
- */
- continue;
- }
- case CMD_LIST:
- {
- LTTngSessiondCmd2_4.sessiond_list_logger listLoggerCmd =
- new LTTngSessiondCmd2_4.sessiond_list_logger();
- listLoggerCmd.execute(this.handler);
- data = listLoggerCmd.getBytes();
- break;
- }
- case CMD_ENABLE:
- {
- LTTngEvent event;
- LTTngSessiondCmd2_4.sessiond_enable_handler enableCmd =
- new LTTngSessiondCmd2_4.sessiond_enable_handler();
- if (data == null) {
- enableCmd.code = LTTngSessiondCmd2_4.lttng_jul_ret_code.CODE_INVALID_CMD;
- break;
- }
- enableCmd.populate(data);
- enableCmd.execute(this.handler);
- data = enableCmd.getBytes();
- break;
- }
- case CMD_DISABLE:
- {
- LTTngSessiondCmd2_4.sessiond_disable_handler disableCmd =
- new LTTngSessiondCmd2_4.sessiond_disable_handler();
- if (data == null) {
- disableCmd.code = LTTngSessiondCmd2_4.lttng_jul_ret_code.CODE_INVALID_CMD;
- break;
- }
- disableCmd.populate(data);
- disableCmd.execute(this.handler);
- data = disableCmd.getBytes();
- break;
- }
- default:
- {
- data = new byte[4];
- ByteBuffer buf = ByteBuffer.wrap(data);
- buf.order(ByteOrder.BIG_ENDIAN);
- LTTngSessiondCmd2_4.lttng_jul_ret_code code =
- LTTngSessiondCmd2_4.lttng_jul_ret_code.CODE_INVALID_CMD;
- buf.putInt(code.getCode());
- break;
- }
- }
-
- /* Send payload to session daemon. */
- this.outToSessiond.write(data, 0, data.length);
- this.outToSessiond.flush();
- }
- }
-
- private String getHomePath() {
- return System.getProperty("user.home");
- }
-
- /**
- * Read port number from file created by the session daemon.
- *
- * @return port value if found else 0.
- */
- private int getPortFromFile(String path) throws IOException {
- int port;
- BufferedReader br;
-
- try {
- br = new BufferedReader(new FileReader(path));
- String line = br.readLine();
- port = Integer.parseInt(line, 10);
- if (port < 0 || port > 65535) {
- /* Invalid value. Ignore. */
- port = 0;
- }
- br.close();
- } catch (FileNotFoundException e) {
- /* No port available. */
- port = 0;
- }
-
- return port;
- }
-
- private void connectToSessiond() throws Exception {
- int port;
-
- if (this.handler.is_root == 1) {
- port = getPortFromFile(rootPortFile);
- if (port == 0) {
- /* No session daemon available. Stop and retry later. */
- throw new IOException();
- }
- } else {
- port = getPortFromFile(getHomePath() + userPortFile);
- if (port == 0) {
- /* No session daemon available. Stop and retry later. */
- throw new IOException();
- }
- }
-
- this.sessiondSock = new Socket(this.sessiondHost, port);
- this.inFromSessiond = new DataInputStream(
- sessiondSock.getInputStream());
- this.outToSessiond = new DataOutputStream(
- sessiondSock.getOutputStream());
- }
-
- private void registerToSessiond() throws Exception {
- byte data[] = new byte[8];
- ByteBuffer buf = ByteBuffer.wrap(data);
- String pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
-
- buf.putInt(this.agent_domain);
- buf.putInt(Integer.parseInt(pid));
- this.outToSessiond.write(data, 0, data.length);
- this.outToSessiond.flush();
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License, version 2.1 only,
- * as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-package org.lttng.ust.jul;
-
-import java.util.concurrent.Semaphore;
-
-public class LTTngThread implements Runnable {
- private LTTngLogHandler handler;
- private LTTngTCPSessiondClient sessiondClient;
-
- public LTTngThread(String host, LTTngLogHandler handler,
- Semaphore registerSem) {
- this.handler = handler;
- this.sessiondClient = new LTTngTCPSessiondClient(host, registerSem);
- }
-
- @Override
- public void run() {
- try {
- this.sessiondClient.init(this.handler);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- public void dispose() {
- this.sessiondClient.destroy();
- }
-}
+++ /dev/null
-/**
- * Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (C) 2012 Alexandre Montplaisir <alexandre.montplaisir@polymtl.ca>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; only
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-package org.lttng.ust.jul;
-
-/**
- * This class implements the the Java side of the LTTng-UST Java interface.
- *
- * First, make sure you have installed "liblttng-ust-java.so" where the linker
- * can find it. You can then call LTTngUst.init() from your Java program to
- * connect the methods exposed here to the native library.
- *
- * Because of limitations in the probe declaration, all trace events generated
- * by this library will have "lttng_ust_java" for domain, and "<type>_event" for
- * event name in the CTF trace files. The "name" parameter will instead appear
- * as the first element of the event's payload.
- *
- * @author Mathieu Desnoyers
- * @author Alexandre Montplaisir
- * @author David Goulet
- *
- */
-public abstract class LTTngUst {
- /**
- * Initialize the UST tracer. This should always be called first, before any
- * tracepoint* method.
- */
- public static void init() {
- System.loadLibrary("lttng-ust-jul-jni"); //$NON-NLS-1$
- }
-
- /**
- * Insert a tracepoint for JUL event.
- *
- * @param msg
- * Raw message provided by the JUL API.
- * @param logger_name
- * Logger name that trigger this event.
- * @param class_name
- * Name of the class that (allegedly) issued the logging request.
- * @param method_name
- * Name of the method that (allegedly) issued the logging request.
- * @param millis
- * Event time in milliseconds since 1970.
- * @param log_level
- * Log level of the event from JUL.
- * @param thread_id
- * Identifier for the thread where the message originated.
- */
-
- /* Use for a user session daemon. */
- public static native void tracepointU(String msg, String logger_name, String class_name,
- String method_name, long millis, int log_level, int thread_id);
-
- /* Use for a root session daemon. */
- public static native void tracepointS(String msg, String logger_name, String class_name,
- String method_name, long millis, int log_level, int thread_id);
-}
SUBDIRS += hello.cxx
endif
-if BUILD_JNI_INTERFACE
-SUBDIRS += java-jul
-endif
-
SCRIPT_LIST = test_loop run.sh unit_tests
dist_noinst_SCRIPTS = $(SCRIPT_LIST)
}
public static void go() throws IOException {
- handler = new LTTngLogHandler(LogManager.getLogManager());
- assert handler.logManager == LogManager.getLogManager();
- ok("Log handler logManager is valid");
-
client = new LTTngTCPSessiondClient("127.0.0.1", sem);
assert client != null;
ok("TCP client is valid");
+++ /dev/null
-EXTRA_DIST = test_jul JULTest.java
-
-if BUILD_JNI_INTERFACE
-
-if HAVE_JAVA_JDK
-JCC=$(JAVA_JDK)/bin/javac
-else
-JCC=javac
-endif
-
-AM_CPPFLAGS = -I$(top_srcdir)/include
-
-JUL_jar_file = "$(builddir)/../../liblttng-ust-jul/liblttng-ust-jul.jar"
-
-default: all
-
-all: JULTest.class
-
-clean-local:
- rm -f *.class
-
-JULTest.class: JULTest.java
- $(JCC) -cp $(JUL_jar_file) -d "$(builddir)" "$(srcdir)/JULTest.java"
-
-endif
+++ /dev/null
-#!/bin/bash
-
-CURDIR=$(dirname $0)/
-TESTDIR=$CURDIR/..
-TESTCLASS="JULTest"
-
-if [ ! -f "$CURDIR/$TESTCLASS.class" ]; then
- echo "1..0 # Skipped: Java support not build"
- exit 0
-fi
-
-java -ea -cp "$CURDIR:$TESTDIR/../liblttng-ust-jul/liblttng-ust-jul.jar" -Djava.library.path="$TESTDIR/../liblttng-ust-jul/.libs" $TESTCLASS
snprintf/test_snprintf
-java-jul/test_jul