Skip to content

Commit

Permalink
Issue #4830 - Enabling JMX on jetty-slf4j-impl
Browse files Browse the repository at this point in the history
Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
  • Loading branch information
joakime committed Apr 30, 2020
1 parent fa94cc2 commit 67bd321
Show file tree
Hide file tree
Showing 10 changed files with 305 additions and 107 deletions.
2 changes: 2 additions & 0 deletions jetty-slf4j-impl/src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,7 @@

requires transitive org.slf4j;

requires static java.management;

provides SLF4JServiceProvider with JettyLoggingServiceProvider;
}
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ public void log(Marker marker, String fqcn, int levelInt, String message, Object
{
long timestamp = System.currentTimeMillis();
String threadName = Thread.currentThread().getName();
getAppender().emit(this, intToLevel(levelInt), timestamp, threadName, throwable, message, argArray);
getAppender().emit(this, LevelUtils.intToLevel(levelInt), timestamp, threadName, throwable, message, argArray);
}
}

Expand Down Expand Up @@ -636,43 +636,9 @@ private void emit(Level level, String msg, Throwable throwable)
getAppender().emit(this, level, timestamp, threadName, throwable, msg);
}

public static Level intToLevel(int level)
{
if (level >= JettyLogger.OFF)
return Level.ERROR;
if (level >= Level.ERROR.toInt())
return Level.ERROR;
if (level >= Level.WARN.toInt())
return Level.WARN;
if (level >= Level.INFO.toInt())
return Level.INFO;
if (level >= Level.DEBUG.toInt())
return Level.DEBUG;
if (level >= Level.TRACE.toInt())
return Level.TRACE;
return Level.TRACE; // everything else
}

public static String levelToString(int level)
{
if (level >= JettyLogger.OFF)
return "OFF";
if (level >= Level.ERROR.toInt())
return "ERROR";
if (level >= Level.WARN.toInt())
return "WARN";
if (level >= Level.INFO.toInt())
return "INFO";
if (level >= Level.DEBUG.toInt())
return "DEBUG";
if (level >= Level.TRACE.toInt())
return "TRACE";
return "OFF"; // everything else
}

@Override
public String toString()
{
return String.format("%s:%s:LEVEL=%s", JettyLogger.class.getSimpleName(), name, levelToString(level));
return String.format("%s:%s:LEVEL=%s", JettyLogger.class.getSimpleName(), name, LevelUtils.levelToString(level));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import java.util.Locale;
import java.util.Properties;
import java.util.TimeZone;
import java.util.function.Function;

import org.slf4j.event.Level;

Expand Down Expand Up @@ -82,7 +81,7 @@ public boolean getHideStacks(String name)
startName = startName.substring(0, startName.length() - SUFFIX_STACKS.length());
}

Boolean hideStacks = walkParentLoggerNames(startName, (key) ->
Boolean hideStacks = JettyLoggerFactory.walkParentLoggerNames(startName, (key) ->
{
String stacksBool = properties.getProperty(key + SUFFIX_STACKS);
if (stacksBool != null)
Expand Down Expand Up @@ -124,12 +123,12 @@ public int getLevel(String name)
startName = startName.substring(0, startName.length() - SUFFIX_LEVEL.length());
}

Integer level = walkParentLoggerNames(startName, (key) ->
Integer level = JettyLoggerFactory.walkParentLoggerNames(startName, (key) ->
{
String levelStr = properties.getProperty(key + SUFFIX_LEVEL);
if (levelStr != null)
String levelStr1 = properties.getProperty(key + SUFFIX_LEVEL);
if (levelStr1 != null)
{
return getLevelInt(key, levelStr);
return LevelUtils.getLevelInt(key, levelStr1);
}
return null;
});
Expand All @@ -140,7 +139,7 @@ public int getLevel(String name)
String levelStr = properties.getProperty("log" + SUFFIX_LEVEL);
if (levelStr != null)
{
level = getLevelInt("log", levelStr);
level = LevelUtils.getLevelInt("log", levelStr);
}
}

Expand Down Expand Up @@ -193,6 +192,11 @@ public JettyLoggerConfiguration load(ClassLoader loader)
});
}

public String getString(String key, String defValue)
{
return properties.getProperty(key, defValue);
}

public boolean getBoolean(String key, boolean defValue)
{
String val = properties.getProperty(key, Boolean.toString(defValue));
Expand All @@ -216,36 +220,6 @@ public int getInt(String key, int defValue)
}
}

private Integer getLevelInt(String levelSegment, String levelStr)
{
if (levelStr == null)
{
return null;
}

String levelName = levelStr.trim().toUpperCase(Locale.ENGLISH);
switch (levelName)
{
case "ALL":
return JettyLogger.ALL;
case "TRACE":
return Level.TRACE.toInt();
case "DEBUG":
return Level.DEBUG.toInt();
case "INFO":
return Level.INFO.toInt();
case "WARN":
return Level.WARN.toInt();
case "ERROR":
return Level.ERROR.toInt();
case "OFF":
return JettyLogger.OFF;
default:
System.err.println("Unknown JettyLogger/Slf4J Level [" + levelSegment + "]=[" + levelName + "], expecting only [ALL, TRACE, DEBUG, INFO, WARN, ERROR, OFF] as values.");
return null;
}
}

private URL getResource(ClassLoader loader, String resourceName)
{
if (loader == null)
Expand Down Expand Up @@ -303,30 +277,4 @@ private Properties readProperties(ClassLoader loader, String resourceName)
}
return null;
}

private <T> T walkParentLoggerNames(String startName, Function<String, T> nameFunction)
{
String nameSegment = startName;

// Checking with FQCN first, then each package segment from longest to shortest.
while ((nameSegment != null) && (nameSegment.length() > 0))
{
T ret = nameFunction.apply(nameSegment);
if (ret != null)
return ret;

// Trim and try again.
int idx = nameSegment.lastIndexOf('.');
if (idx >= 0)
{
nameSegment = nameSegment.substring(0, idx);
}
else
{
nameSegment = null;
}
}

return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,16 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Consumer;
import java.util.function.Function;

import org.slf4j.ILoggerFactory;
import org.slf4j.Logger;

public class JettyLoggerFactory implements ILoggerFactory
public class JettyLoggerFactory implements ILoggerFactory, JettyLoggerFactoryMBean
{
private static final String ROOT_LOGGER_NAME = "";
private final JettyLoggerConfiguration configuration;
private final JettyLogger rootLogger;
private ConcurrentMap<String, JettyLogger> loggerMap;
private final ConcurrentMap<String, JettyLogger> loggerMap;

public JettyLoggerFactory(JettyLoggerConfiguration config)
{
Expand All @@ -41,9 +41,9 @@ public JettyLoggerFactory(JettyLoggerConfiguration config)

StdErrAppender appender = new StdErrAppender(configuration);

rootLogger = new JettyLogger(this, ROOT_LOGGER_NAME, appender);
loggerMap.put(ROOT_LOGGER_NAME, rootLogger);
rootLogger.setLevel(configuration.getLevel(ROOT_LOGGER_NAME));
rootLogger = new JettyLogger(this, Logger.ROOT_LOGGER_NAME, appender);
loggerMap.put(Logger.ROOT_LOGGER_NAME, rootLogger);
rootLogger.setLevel(configuration.getLevel(Logger.ROOT_LOGGER_NAME));
}

/**
Expand All @@ -54,7 +54,7 @@ public JettyLoggerFactory(JettyLoggerConfiguration config)
*/
public JettyLogger getJettyLogger(String name)
{
if (name.equals(ROOT_LOGGER_NAME))
if (name.equals(Logger.ROOT_LOGGER_NAME))
{
return getRootLogger();
}
Expand Down Expand Up @@ -179,4 +179,67 @@ protected static String condensePackageString(String classname)

return dense.toString();
}

public static <T> T walkParentLoggerNames(String startName, Function<String, T> nameFunction)
{
String nameSegment = startName;

// Checking with FQCN first, then each package segment from longest to shortest.
while ((nameSegment != null) && (nameSegment.length() > 0))
{
T ret = nameFunction.apply(nameSegment);
if (ret != null)
return ret;

// Trim and try again.
int idx = nameSegment.lastIndexOf('.');
if (idx >= 0)
{
nameSegment = nameSegment.substring(0, idx);
}
else
{
nameSegment = null;
}
}

return null;
}

@Override
public String[] getLoggerNames()
{
return loggerMap.keySet().toArray(new String[0]);
}

@Override
public int getLoggerCount()
{
return loggerMap.size();
}

@Override
public String getLoggerLevel(String loggerName)
{
return walkParentLoggerNames(loggerName, (key) ->
{
JettyLogger logger = loggerMap.get(key);
if (key != null)
{
return LevelUtils.levelToString(logger.getLevel());
}
return null;
});
}

@Override
public void setLoggerLevel(String loggerName, String levelName)
{
Integer levelInt = LevelUtils.getLevelInt(loggerName, levelName);
if (levelInt != null)
{
JettyLogger jettyLogger = getJettyLogger(loggerName);
jettyLogger.setLevel(levelInt);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// ========================================================================
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under
// the terms of the Eclipse Public License 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0
//
// This Source Code may also be made available under the following
// Secondary Licenses when the conditions for such availability set
// forth in the Eclipse Public License, v. 2.0 are satisfied:
// the Apache License v2.0 which is available at
// https://www.apache.org/licenses/LICENSE-2.0
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//

package org.eclipse.jetty.logging;

@SuppressWarnings("unused")
public interface JettyLoggerFactoryMBean
{
int getLoggerCount();

String[] getLoggerNames();

void setLoggerLevel(String loggerName, String levelName);

String getLoggerLevel(String loggerName);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//
// ========================================================================
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under
// the terms of the Eclipse Public License 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0
//
// This Source Code may also be made available under the following
// Secondary Licenses when the conditions for such availability set
// forth in the Eclipse Public License, v. 2.0 are satisfied:
// the Apache License v2.0 which is available at
// https://www.apache.org/licenses/LICENSE-2.0
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//

package org.eclipse.jetty.logging;

import java.lang.management.ManagementFactory;
import javax.management.MBeanServer;
import javax.management.ObjectName;

public class JettyLoggingJmx
{
public static void initialize(JettyLoggerConfiguration config, JettyLoggerFactory loggerFactory)
{
if (!config.getBoolean("org.eclipse.jetty.logging.jmx", false))
{
loggerFactory.getJettyLogger(JettyLoggingJmx.class.getName()).debug("JMX not enabled");
return;
}

try
{
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
String contextName = config.getString("org.eclipse.jetty.logging.jmx.contextName", "default");

ObjectName objName = new ObjectName(JettyLoggerFactory.class.getName() + ":name=" + contextName);
mbs.registerMBean(loggerFactory, objName);
}
catch (Throwable cause)
{
JettyLogger logger = loggerFactory.getJettyLogger(JettyLoggingJmx.class.getName());
logger.warn("java.management not available.");
logger.debug("java.management is not available", cause);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ public void initialize()
loggerFactory = new JettyLoggerFactory(config);
markerFactory = new BasicMarkerFactory();
mdcAdapter = new NOPMDCAdapter(); // TODO: Provide Jetty Implementation?

JettyLoggingJmx.initialize(config, loggerFactory);
}

public JettyLoggerFactory getJettyLoggerFactory()
Expand Down
Loading

0 comments on commit 67bd321

Please sign in to comment.