LTTNG_LOGLEVEL_DEBUG = 14,
};
+/*
+ * Available loglevels for the JUL domain. Those are an exact map from the
+ * class java.util.logging.Level.
+ */
+enum lttng_loglevel_jul {
+ LTTNG_LOGLEVEL_JUL_OFF = INT32_MAX,
+ LTTNG_LOGLEVEL_JUL_SEVERE = 1000,
+ LTTNG_LOGLEVEL_JUL_WARNING = 900,
+ LTTNG_LOGLEVEL_JUL_INFO = 800,
+ LTTNG_LOGLEVEL_JUL_CONFIG = 700,
+ LTTNG_LOGLEVEL_JUL_FINE = 500,
+ LTTNG_LOGLEVEL_JUL_FINER = 400,
+ LTTNG_LOGLEVEL_JUL_FINEST = 300,
+ LTTNG_LOGLEVEL_JUL_ALL = INT32_MIN,
+};
+
/*
* LTTng consumer mode
*/
/* The wild card * means that everything should be enabled. */
if (strncmp(event->name, "*", 1) == 0 && strlen(event->name) == 1) {
- ret = event_jul_enable_all(usess);
+ ret = event_jul_enable_all(usess, event);
} else {
ret = event_jul_enable(usess, event);
}
}
case LTTNG_DOMAIN_JUL:
{
- struct lttng_event uevent;
+ struct lttng_event uevent, event;
struct lttng_domain tmp_dom;
struct ltt_ust_session *usess = session->ust_session;
goto error;
}
- ret = event_jul_enable_all(usess);
+ event.loglevel = LTTNG_LOGLEVEL_JUL_ALL;
+ event.loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL;
+ strncpy(event.name, "*", sizeof(event.name));
+ event.name[sizeof(event.name) - 1] = '\0';
+
+ ret = event_jul_enable_all(usess, &event);
if (ret != LTTNG_OK) {
goto error;
}
*
* Return LTTNG_OK on success or else a LTTNG_ERR* code.
*/
-int event_jul_enable_all(struct ltt_ust_session *usess)
+int event_jul_enable_all(struct ltt_ust_session *usess,
+ struct lttng_event *event)
{
int ret;
struct jul_event *jevent;
- struct lttng_event event;
struct lttng_ht_iter iter;
assert(usess);
DBG("Event JUL enabling ALL events for session %" PRIu64, usess->id);
- /* Create the * wildcard event name for the Java agent. */
- memset(event.name, 0, sizeof(event.name));
- strncpy(event.name, "*", sizeof(event.name));
- event.name[sizeof(event.name) - 1] = '\0';
-
/* Enable event on JUL application through TCP socket. */
- ret = event_jul_enable(usess, &event);
+ ret = event_jul_enable(usess, event);
if (ret != LTTNG_OK) {
goto error;
}
assert(usess);
assert(event);
- DBG("Event JUL enabling %s for session %" PRIu64, event->name, usess->id);
+ DBG("Event JUL enabling %s for session %" PRIu64 " with loglevel type %d "
+ "and loglevel %d", event->name, usess->id, event->loglevel_type,
+ event->loglevel);
jevent = jul_find_by_name(event->name, &usess->domain_jul);
if (!jevent) {
ret = LTTNG_ERR_NOMEM;
goto error;
}
+ jevent->loglevel = event->loglevel;
+ jevent->loglevel_type = event->loglevel_type;
created = 1;
}
struct ltt_ust_channel *uchan);
int event_jul_enable(struct ltt_ust_session *usess, struct lttng_event *event);
-int event_jul_enable_all(struct ltt_ust_session *usess);
+int event_jul_enable_all(struct ltt_ust_session *usess,
+ struct lttng_event *event);
int event_jul_disable(struct ltt_ust_session *usess, char *event_name);
int event_jul_disable_all(struct ltt_ust_session *usess);
goto error_io;
}
+ msg.loglevel = event->loglevel;
+ msg.loglevel_type = event->loglevel_type;
strncpy(msg.name, event->name, sizeof(msg.name));
ret = send_payload(app->sock, &msg, sizeof(msg));
if (ret < 0) {
* the JUL API.
*/
char name[LTTNG_SYMBOL_NAME_LEN];
+ enum lttng_loglevel_jul loglevel;
+ enum lttng_loglevel_type loglevel_type;
/*
* Tells if the event is enabled or not on the JUL Agent.
*/
#define _GNU_SOURCE
+#include <assert.h>
#include <popt.h>
#include <stdio.h>
#include <stdlib.h>
fprintf(ofp, " TRACE_DEBUG_LINE = 13\n");
fprintf(ofp, " TRACE_DEBUG = 14\n");
fprintf(ofp, " (shortcuts such as \"system\" are allowed)\n");
+ fprintf(ofp, "\n");
+ fprintf(ofp, " Available JUL domain loglevels:\n");
+ fprintf(ofp, " JUL_OFF = INT32_MAX\n");
+ fprintf(ofp, " JUL_SEVERE = %d\n", LTTNG_LOGLEVEL_JUL_SEVERE);
+ fprintf(ofp, " JUL_WARNING = %d\n", LTTNG_LOGLEVEL_JUL_WARNING);
+ fprintf(ofp, " JUL_INFO = %d\n", LTTNG_LOGLEVEL_JUL_INFO);
+ fprintf(ofp, " JUL_CONFIG = %d\n", LTTNG_LOGLEVEL_JUL_CONFIG);
+ fprintf(ofp, " JUL_FINE = %d\n", LTTNG_LOGLEVEL_JUL_FINE);
+ fprintf(ofp, " JUL_FINER = %d\n", LTTNG_LOGLEVEL_JUL_FINER);
+ fprintf(ofp, " JUL_FINEST = %d\n", LTTNG_LOGLEVEL_JUL_FINEST);
+ fprintf(ofp, " JUL_ALL = INT32_MIN\n");
+ fprintf(ofp, " (shortcuts such as \"severe\" are allowed)\n");
+ fprintf(ofp, "\n");
fprintf(ofp, " -f, --filter \'expression\'\n");
fprintf(ofp, " Filter expression on event fields and context.\n");
fprintf(ofp, " Event recording depends on evaluation.\n");
return ret;
}
+/*
+ * Maps JUL loglevel from string to value
+ */
+static int loglevel_jul_str_to_value(const char *inputstr)
+{
+ int i = 0;
+ char str[LTTNG_SYMBOL_NAME_LEN];
+
+ /*
+ * Loop up to LTTNG_SYMBOL_NAME_LEN minus one because the NULL bytes is
+ * added at the end of the loop so a the upper bound we avoid the overflow.
+ */
+ while (i < (LTTNG_SYMBOL_NAME_LEN - 1) && inputstr[i] != '\0') {
+ str[i] = toupper(inputstr[i]);
+ i++;
+ }
+ str[i] = '\0';
+
+ if (!strcmp(str, "JUL_OFF") || !strcmp(str, "OFF")) {
+ return LTTNG_LOGLEVEL_JUL_OFF;
+ } else if (!strcmp(str, "JUL_SEVERE") || !strcmp(str, "SEVERE")) {
+ return LTTNG_LOGLEVEL_JUL_SEVERE;
+ } else if (!strcmp(str, "JUL_WARNING") || !strcmp(str, "WARNING")) {
+ return LTTNG_LOGLEVEL_JUL_WARNING;
+ } else if (!strcmp(str, "JUL_INFO") || !strcmp(str, "INFO")) {
+ return LTTNG_LOGLEVEL_JUL_INFO;
+ } else if (!strcmp(str, "JUL_CONFIG") || !strcmp(str, "CONFIG")) {
+ return LTTNG_LOGLEVEL_JUL_CONFIG;
+ } else if (!strcmp(str, "JUL_FINE") || !strcmp(str, "FINE")) {
+ return LTTNG_LOGLEVEL_JUL_FINE;
+ } else if (!strcmp(str, "JUL_FINER") || !strcmp(str, "FINER")) {
+ return LTTNG_LOGLEVEL_JUL_FINER;
+ } else if (!strcmp(str, "JUL_FINEST") || !strcmp(str, "FINEST")) {
+ return LTTNG_LOGLEVEL_JUL_FINEST;
+ } else if (!strcmp(str, "JUL_ALL") || !strcmp(str, "ALL")) {
+ return LTTNG_LOGLEVEL_JUL_ALL;
+ } else {
+ return -1;
+ }
+}
+
/*
* Maps loglevel from string to value
*/
strcpy(ev.name, "*");
ev.loglevel_type = opt_loglevel_type;
if (opt_loglevel) {
- ev.loglevel = loglevel_str_to_value(opt_loglevel);
+ assert(opt_userspace || opt_jul);
+ if (opt_userspace) {
+ ev.loglevel = loglevel_str_to_value(opt_loglevel);
+ } else if (opt_jul) {
+ ev.loglevel = loglevel_jul_str_to_value(opt_loglevel);
+ }
if (ev.loglevel == -1) {
ERR("Unknown loglevel %s", opt_loglevel);
ret = -LTTNG_ERR_INVALID;
goto error;
}
} else {
- ev.loglevel = -1;
+ assert(opt_userspace || opt_jul);
+ if (opt_userspace) {
+ ev.loglevel = -1;
+ } else if (opt_jul) {
+ ev.loglevel = LTTNG_LOGLEVEL_JUL_ALL;
+ }
}
}
ret = CMD_UNSUPPORTED;
goto error;
}
+
+ ev.loglevel_type = opt_loglevel_type;
+ if (opt_loglevel) {
+ ev.loglevel = loglevel_jul_str_to_value(opt_loglevel);
+ if (ev.loglevel == -1) {
+ ERR("Unknown loglevel %s", opt_loglevel);
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+ } else {
+ ev.loglevel = LTTNG_LOGLEVEL_JUL_ALL;
+ }
ev.type = LTTNG_EVENT_TRACEPOINT;
strncpy(ev.name, event_name, LTTNG_SYMBOL_NAME_LEN);
ev.name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
* Enable event command payload.
*/
struct lttcomm_jul_enable {
+ uint32_t loglevel;
+ uint32_t loglevel_type;
char name[LTTNG_SYMBOL_NAME_LEN];
} LTTNG_PACKED;
TRACE_PATH=$(mktemp -d)
-NUM_TESTS=16
+NUM_TESTS=37
source $TESTDIR/utils/utils.sh
stop_lttng_tracing $SESSION_NAME
destroy_lttng_session $SESSION_NAME
+
+ # Validate test. Expecting all events.
+ trace_matches $EVENT_NAME $(($NR_ITER - 1)) $TRACE_PATH
+ if [ $? -ne 0 ]; then
+ return $?
+ fi
}
function test_jul_after_start ()
stop_lttng_tracing $SESSION_NAME
destroy_lttng_session $SESSION_NAME
+
+ # Validate test. Expecting all events.
+ trace_matches $EVENT_NAME $(($NR_ITER - 1)) $TRACE_PATH
+ if [ $? -ne 0 ]; then
+ return $?
+ fi
+}
+
+function test_jul_loglevel ()
+{
+ diag "Test JUL application with loglevel"
+
+ create_lttng_session $SESSION_NAME $TRACE_PATH
+ enable_jul_lttng_event_loglevel $SESSION_NAME $EVENT_NAME "JUL_INFO"
+ start_lttng_tracing $SESSION_NAME
+
+ # Run 5 times with a 1 second delay
+ run_app
+
+ wait_apps
+
+ stop_lttng_tracing $SESSION_NAME
+ destroy_lttng_session $SESSION_NAME
+
+ # Validate test. Expecting all events.
+ trace_matches $EVENT_NAME $(($NR_ITER - 1)) $TRACE_PATH
+ if [ $? -ne 0 ]; then
+ return $?
+ fi
+
+ diag "Test JUL applications with lower loglevel"
+
+ create_lttng_session $SESSION_NAME $TRACE_PATH
+ enable_jul_lttng_event_loglevel $SESSION_NAME $EVENT_NAME "JUL_SEVERE"
+ start_lttng_tracing $SESSION_NAME
+
+ # Run 5 times with a 1 second delay
+ run_app
+
+ wait_apps
+
+ stop_lttng_tracing $SESSION_NAME
+ destroy_lttng_session $SESSION_NAME
+
+ # Validate test. Expecting 0 events.
+ trace_matches $EVENT_NAME 0 $TRACE_PATH
+ if [ $? -ne 0 ]; then
+ return $?
+ fi
+
+ diag "Test JUL applications with higher loglevel"
+
+ create_lttng_session $SESSION_NAME $TRACE_PATH
+ enable_jul_lttng_event_loglevel $SESSION_NAME $EVENT_NAME "JUL_FINER"
+ start_lttng_tracing $SESSION_NAME
+
+ # Run 5 times with a 1 second delay
+ run_app
+
+ wait_apps
+
+ stop_lttng_tracing $SESSION_NAME
+ destroy_lttng_session $SESSION_NAME
+
+ # Validate test. Expecting all events.
+ trace_matches $EVENT_NAME $(($NR_ITER - 1)) $TRACE_PATH
+ return $?
}
plan_tests $NUM_TESTS
start_lttng_sessiond
tests=(
+ test_jul_loglevel
test_jul_before_start
test_jul_after_start
)
for fct_test in ${tests[@]};
do
${fct_test}
-
- # Validate test
- validate_trace $EVENT_NAME $TRACE_PATH
- if [ $? -eq 0 ]; then
- # Only delete if successful
- rm -rf $TRACE_PATH
- else
- break
+ if [ $? -ne 0 ]; then
+ break;
fi
+ rm -rf $TRACE_PATH
done
stop_lttng_sessiond
ok $? "Enable JUL event $event_name for session $sess_name"
}
+function enable_jul_lttng_event_loglevel()
+{
+ sess_name=$1
+ event_name="$2"
+ loglevel=$3
+ channel_name=$4
+
+ if [ -z $channel_name ]; then
+ # default channel if none specified
+ chan=""
+ else
+ chan="-c $channel_name"
+ fi
+
+ $TESTDIR/../src/bin/lttng/$LTTNG_BIN enable-event --loglevel $loglevel "$event_name" $chan -s $sess_name -j >/dev/null 2>&1
+ ok $? "Enable JUL event $event_name for session $sess_name with loglevel $loglevel"
+}
+
function enable_ust_lttng_event_filter()
{
sess_name="$1"