tests/snprintf/prog
tests/benchmark/bench1
tests/benchmark/bench2
+
+# Java JUL library
+*.class
+liblttng-ust-jul.jar
+org_lttng_ust_jul_LTTngUst.h
liblttng-ust-libc-wrapper \
liblttng-ust-cyg-profile \
tools \
- tests \
doc
if BUILD_JNI_INTERFACE
-SUBDIRS += liblttng-ust-java
+SUBDIRS += liblttng-ust-java liblttng-ust-jul
endif
+SUBDIRS += tests
+
#temporarily disabled
# liblttng-ust-malloc
[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])
liblttng-ust-ctl/Makefile
liblttng-ust-fork/Makefile
liblttng-ust-java/Makefile
+ liblttng-ust-jul/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
])
--- /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"
+
+JNIEXPORT void JNICALL Java_org_lttng_ust_LTTngUst_tracepoint(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, jul_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
+if BUILD_JNI_INTERFACE
+
+AM_CPPFLAGS = -I$(top_srcdir)/include
+
+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_LTTngUst.h
+dist_noinst_DATA = $(LTTNG_JUL_SRCDIR)/LTTngUst.java
+liblttng_ust_jul_jni_la_LIBADD = -lc -L$(top_builddir)/liblttng-ust/.libs -llttng-ust
+
+LTTNG_JUL_SRCDIR = $(srcdir)/org/lttng/ust/jul
+LTTNG_JUL_DESTDIR = $(builddir)/org/lttng/ust/jul
+
+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_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
+
+LTTngUst.c: org_lttng_ust_LTTngUst.h
+
+$(LTTNG_JUL_DESTDIR)/LTTngUst.class: $(LTTNG_JUL_SRCDIR)/LTTngUst.java
+ $(JCC)/javac -d "$(builddir)" "$(LTTNG_JUL_SRCDIR)/LTTngUst.java"
+
+$(LTTNG_JUL_DESTDIR)/LTTngAgent.class: $(LTTNG_JUL_SRCDIR)/LTTngAgent.java
+ $(JCC)/javac -d "$(builddir)" "$(LTTNG_JUL_SRCDIR)/LTTngAgent.java"
+
+org_lttng_ust_LTTngUst.h: $(LTTNG_JUL_DESTDIR)/LTTngUst.class
+ $(JCC)/javah org.lttng.ust.jul.LTTngUst
+
+liblttng-ust-jul.jar: $(LTTNG_JUL_DESTDIR)/LTTngUst.class $(LTTNG_JUL_DESTDIR)/LTTngAgent.class
+ $(JCC)/jar cf liblttng-ust-jul.jar \
+ $(LTTNG_JUL_DESTDIR)/*.class
+
+endif
--- /dev/null
+This directory contains the LTTng Java Agent for JUL support.
+
+Configuration examples to build this library:
+
+dependency: openjdk-7-jdk
+ ./configure --with-java-jdk=/usr/lib/jvm/java-7-openjdk --with-jni-interface
+
+On Debian system for instance you can simply use the "default-java" path:
+
+ ./configure --with-java-jdk=/usr/lib/jvm/default-java --with-jni-interface
+
+Note that the OpenJDK 7 is used for development and continuous integration thus
+we directly support that version for this library. However, it has been tested
+with OpenJDK 6 also. Please let us know if other Java version (commercial or
+not) work with this library.
+
+After building, you can use the "liblttng-ust-jul.jar" file in a Java project.
+It requires "liblttng-ust-jul.so" which is installed by the build system when
+doing "make install". Make sure that your Java application can find this shared
+object with the "java.library.path".
+
+In order to enable the agent in your Java application, you simply have to add
+this as early as you can in the runtime process.
+
+import org.lttng.ust.jul.LTTngAgent;
+[...]
+ private static LTTngAgent lttngAgent;
+ [...]
+ lttngAgent = LTTngAgent.getLTTngAgent();
+
+This will initialize automatically the singleton LTTngAgent, it will stall
+your application until the session daemon registration is done. If no session
+daemon is available, the execution will continue and the agent will retry at
+each 3 seconds.
+
+Once registered, it is adds a thread inside your Java application and will be
+able to automatically use every Logger object and map them to the jul_event
+tracepoint of the JNI interface (see LTTngUst.c/.java).
--- /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>
+
+TRACEPOINT_EVENT(lttng_jul, jul_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
+/*
+ * 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.io.IOException;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.util.concurrent.Semaphore;
+import java.util.logging.FileHandler;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.logging.LogManager;
+import java.util.Enumeration;
+
+public class LTTngAgent {
+ private static LTTngLogHandler lttngHandler;
+ private static LogManager logManager;
+ private static LTTngThread lttngThread;
+ private static Thread sessiondTh;
+
+ /* 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 static final String sessiondAddr = "127.0.0.1";
+ private static final int sessiondPort = 5345;
+
+ private static final String rootPortFile = "/var/run/lttng/jul.port";
+ private static final String userPortFile = "/.lttng/jul.port";
+
+ /*
+ * Constructor is private. This is a singleton and a reference should be
+ * acquired using getLTTngAgent().
+ */
+ private LTTngAgent() throws IOException {
+ this.logManager = LogManager.getLogManager();
+ this.lttngHandler = new LTTngLogHandler(this.logManager);
+ 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.lttngHandler);
+ }
+ }
+
+ 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;
+ }
+
+ private String getHomePath() {
+ return System.getProperty("user.home");
+ }
+
+ private int getPortFromFile() throws IOException {
+ int port;
+ int uid = getUID();
+ String path;
+ BufferedReader br;
+
+ /* Check if root or not, it tells where to get the port file. */
+ if (uid == 0) {
+ path = rootPortFile;
+ } else {
+ path = new String(getHomePath() + userPortFile);
+ }
+
+ try {
+ br = new BufferedReader(new FileReader(path));
+ String line = br.readLine();
+ port = Integer.parseInt(line, 10);
+ if (port < 0 || port > 65535) {
+ port = sessiondPort;
+ }
+ br.close();
+ } catch (FileNotFoundException e) {
+ port = sessiondPort;
+ }
+
+ return port;
+ }
+
+ /*
+ * 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;
+ }
+
+ /*
+ * Initialize LTTngAgent. This will attach the log handler to all Logger
+ * returned by the logManager.
+ */
+ private synchronized void init() throws SecurityException, IOException {
+ if (this.initialized) {
+ return;
+ }
+
+ this.lttngThread = new LTTngThread(this.sessiondAddr,
+ getPortFromFile(), this.lttngHandler, this.registerSem);
+ this.sessiondTh = new Thread(lttngThread);
+ this.sessiondTh.start();
+
+ this.initialized = true;
+
+ /* Wait for the registration to end. */
+ try {
+ this.registerSem.acquire();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void dispose() throws IOException {
+ this.lttngThread.dispose();
+
+ /* Make sure there is no more LTTng handler attach to logger(s). */
+ this.removeHandlers();
+
+ try {
+ this.sessiondTh.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.jul;
+
+import java.lang.String;
+import java.util.logging.Handler;
+import java.util.logging.LogRecord;
+import java.util.logging.LogManager;
+
+import org.lttng.ust.jul.LTTngUst;
+
+public class LTTngLogHandler extends Handler {
+ public LogManager logManager;
+
+ public LTTngLogHandler(LogManager logManager) {
+ super();
+
+ this.logManager = logManager;
+
+ /* Initialize LTTng UST tracer. */
+ LTTngUst.init();
+ }
+
+ @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.
+ */
+ LTTngUst.tracepoint(record.getMessage(), record.getLoggerName(),
+ record.getSourceClassName(), record.getSourceMethodName(),
+ record.getMillis(), record.getLevel().intValue(),
+ record.getThreadID());
+ }
+}
--- /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.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;
+
+ 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);
+ 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;
+
+ /** 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, 0, data.length);
+ }
+
+ @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 String execute(LTTngLogHandler handler) {
+ Logger logger;
+
+ if (name == null) {
+ this.code = lttng_jul_ret_code.CODE_INVALID_CMD;
+ return null;
+ }
+
+ /* Wild card to enable ALL logger. */
+ if (name.trim().equals("*")) {
+ 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;
+ }
+
+ logger = handler.logManager.getLogger(loggerName);
+ logger.addHandler(handler);
+ }
+ this.code = lttng_jul_ret_code.CODE_SUCCESS_CMD;
+ return null;
+ }
+
+ this.code = lttng_jul_ret_code.CODE_SUCCESS_CMD;
+ logger = handler.logManager.getLogger(name.trim());
+ if (logger != null) {
+ logger.addHandler(handler);
+ return null;
+ } else {
+ return new String(name);
+ }
+ }
+ }
+
+ 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_jul_ret_code code;
+
+ @Override
+ public void populate(byte[] data) {
+ ByteBuffer buf = ByteBuffer.wrap(data);
+ buf.order(ByteOrder.BIG_ENDIAN);
+ name = new String(data, 0, data.length);
+ }
+
+ @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) {
+ Logger logger;
+
+ if (name == null) {
+ this.code = lttng_jul_ret_code.CODE_INVALID_CMD;
+ return;
+ }
+
+ /* Wild card to disable ALL logger. */
+ if (name.trim().equals("*")) {
+ 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;
+ }
+
+ logger = handler.logManager.getLogger(loggerName);
+ logger.removeHandler(handler);
+ }
+ this.code = lttng_jul_ret_code.CODE_SUCCESS_CMD;
+ return;
+ }
+
+ logger = handler.logManager.getLogger(name.trim());
+ if (logger == null) {
+ this.code = lttng_jul_ret_code.CODE_UNK_LOGGER_NAME;
+ } else {
+ logger.removeHandler(handler);
+ this.code = lttng_jul_ret_code.CODE_SUCCESS_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_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.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.DataInputStream;
+import java.net.*;
+import java.lang.management.ManagementFactory;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
+
+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 final int sessiondPort;
+ private Socket sessiondSock;
+ private boolean quit = false;
+
+ private DataInputStream inFromSessiond;
+ private DataOutputStream outToSessiond;
+
+ private LTTngLogHandler handler;
+
+ private Semaphore registerSem;
+
+ private Timer eventTimer;
+ private List<String> enabledEventList = new ArrayList<String>();
+ /* Timer delay at each 5 seconds. */
+ private final static long timerDelay = 5 * 1000;
+ private static boolean timerInitialized;
+
+ public LTTngTCPSessiondClient(String host, int port, Semaphore sem) {
+ this.sessiondHost = host;
+ this.sessiondPort = port;
+ this.registerSem = sem;
+ this.eventTimer = new Timer();
+ this.timerInitialized = false;
+ }
+
+ private void setupEventTimer() {
+ if (this.timerInitialized) {
+ return;
+ }
+
+ this.eventTimer.scheduleAtFixedRate(new TimerTask() {
+ @Override
+ public void run() {
+ /*
+ * We have to make a copy here since it is possible that the
+ * enabled event list is changed during an iteration on it.
+ */
+ List<String> tmpList = new ArrayList<String>(enabledEventList);
+
+ LTTngSessiondCmd2_4.sessiond_enable_handler enableCmd = new
+ LTTngSessiondCmd2_4.sessiond_enable_handler();
+ for (String strEventName: tmpList) {
+ enableCmd.name = strEventName;
+ if (enableCmd.execute(handler) == null) {
+ enabledEventList.remove(strEventName);
+ }
+ }
+ }
+ }, this.timerDelay, this.timerDelay);
+
+ this.timerInitialized = true;
+ }
+
+ public void init(LTTngLogHandler handler) throws InterruptedException {
+ this.handler = handler;
+
+ for (;;) {
+ if (this.quit) {
+ break;
+ }
+
+ try {
+
+ /*
+ * Connect to the session daemon before anything else.
+ */
+ connectToSessiond();
+
+ /*
+ * Register to the session daemon as the Java component of the
+ * UST application.
+ */
+ registerToSessiond();
+ this.registerSem.release();
+
+ setupEventTimer();
+
+ /*
+ * 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) {
+ this.registerSem.release();
+ System.out.println(uhe);
+ } catch (IOException ioe) {
+ this.registerSem.release();
+ Thread.sleep(3000);
+ } catch (Exception e) {
+ this.registerSem.release();
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public void destroy() {
+ this.quit = true;
+ this.eventTimer.cancel();
+
+ 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_LIST:
+ {
+ LTTngSessiondCmd2_4.sessiond_list_logger listLoggerCmd =
+ new LTTngSessiondCmd2_4.sessiond_list_logger();
+ listLoggerCmd.execute(this.handler);
+ data = listLoggerCmd.getBytes();
+ break;
+ }
+ case CMD_ENABLE:
+ {
+ String event_name;
+ 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);
+ event_name = enableCmd.execute(this.handler);
+ if (event_name != null) {
+ /*
+ * Add the event to the list so it can be enabled if
+ * the logger appears at some point in time.
+ */
+ enabledEventList.add(event_name);
+ }
+ 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 void connectToSessiond() throws Exception {
+ this.sessiondSock = new Socket(this.sessiondHost, this.sessiondPort);
+ this.inFromSessiond = new DataInputStream(
+ sessiondSock.getInputStream());
+ this.outToSessiond = new DataOutputStream(
+ sessiondSock.getOutputStream());
+ }
+
+ private void registerToSessiond() throws Exception {
+ byte data[] = new byte[4];
+ ByteBuffer buf = ByteBuffer.wrap(data);
+ String pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
+
+ 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, int port, LTTngLogHandler handler,
+ Semaphore registerSem) {
+ this.handler = handler;
+ this.sessiondClient = new LTTngTCPSessiondClient(host, port,
+ 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.
+ */
+ public static native void tracepoint(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)
--- /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
+ */
+
+import java.io.IOException;
+import java.util.concurrent.Semaphore;
+import java.util.logging.LogManager;
+
+import org.lttng.ust.jul.*;
+
+public class JULTest {
+ private final static int NUM_TESTS = 5;
+ private static int testCount = 1;
+
+ /* Singleton agent object. */
+ private static LTTngAgent agent;
+ private static LTTngLogHandler handler;
+ private static LTTngTCPSessiondClient client;
+
+ private static Semaphore sem;
+
+ private static void ok(String desc) {
+ System.out.println("ok " + testCount + " - " + desc);
+ testCount++;
+ }
+
+ 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", 5345, sem);
+ assert client != null;
+ ok("TCP client is valid");
+ client.destroy();
+ ok("TCP client destroyed");
+
+ agent = LTTngAgent.getLTTngAgent();
+ assert agent != null;
+ ok("LTTngAgent is valid");
+ agent.dispose();
+ ok("LTTngAgent disposed");
+ }
+
+ public static void main(String args[]) throws Exception {
+ System.out.println("1.." + NUM_TESTS);
+ go();
+ }
+}
--- /dev/null
+if BUILD_JNI_INTERFACE
+
+if HAVE_JAVA_JDK
+JCC=$(JAVA_JDK)/bin/javac
+else
+JCC=javac
+endif
+
+AM_CPPFLAGS = -I$(top_srcdir)/include
+
+EXTRA_DIST = test_jul
+
+JUL_jar_file = "$(srcdir)/../../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