Issue #4830 - Enabling JMX on jetty-slf4j-impl
Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
This commit is contained in:
parent
fa94cc2f6c
commit
67bd321bfc
|
@ -25,5 +25,7 @@ module org.eclipse.jetty.logging
|
|||
|
||||
requires transitive org.slf4j;
|
||||
|
||||
requires static java.management;
|
||||
|
||||
provides SLF4JServiceProvider with JettyLoggingServiceProvider;
|
||||
}
|
||||
|
|
|
@ -247,7 +247,7 @@ public class JettyLogger implements LocationAwareLogger, Logger
|
|||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -636,43 +636,9 @@ public class JettyLogger implements LocationAwareLogger, Logger
|
|||
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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ import java.security.PrivilegedAction;
|
|||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
import java.util.TimeZone;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.slf4j.event.Level;
|
||||
|
||||
|
@ -82,7 +81,7 @@ public class JettyLoggerConfiguration
|
|||
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)
|
||||
|
@ -124,12 +123,12 @@ public class JettyLoggerConfiguration
|
|||
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;
|
||||
});
|
||||
|
@ -140,7 +139,7 @@ public class JettyLoggerConfiguration
|
|||
String levelStr = properties.getProperty("log" + SUFFIX_LEVEL);
|
||||
if (levelStr != null)
|
||||
{
|
||||
level = getLevelInt("log", levelStr);
|
||||
level = LevelUtils.getLevelInt("log", levelStr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -193,6 +192,11 @@ public class JettyLoggerConfiguration
|
|||
});
|
||||
}
|
||||
|
||||
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));
|
||||
|
@ -216,36 +220,6 @@ public class JettyLoggerConfiguration
|
|||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -303,30 +277,4 @@ public class JettyLoggerConfiguration
|
|||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,16 +22,16 @@ import java.util.Objects;
|
|||
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)
|
||||
{
|
||||
|
@ -41,9 +41,9 @@ public class JettyLoggerFactory implements ILoggerFactory
|
|||
|
||||
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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -54,7 +54,7 @@ public class JettyLoggerFactory implements ILoggerFactory
|
|||
*/
|
||||
public JettyLogger getJettyLogger(String name)
|
||||
{
|
||||
if (name.equals(ROOT_LOGGER_NAME))
|
||||
if (name.equals(Logger.ROOT_LOGGER_NAME))
|
||||
{
|
||||
return getRootLogger();
|
||||
}
|
||||
|
@ -179,4 +179,67 @@ public class JettyLoggerFactory implements ILoggerFactory
|
|||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -45,6 +45,8 @@ public class JettyLoggingServiceProvider implements SLF4JServiceProvider
|
|||
loggerFactory = new JettyLoggerFactory(config);
|
||||
markerFactory = new BasicMarkerFactory();
|
||||
mdcAdapter = new NOPMDCAdapter(); // TODO: Provide Jetty Implementation?
|
||||
|
||||
JettyLoggingJmx.initialize(config, loggerFactory);
|
||||
}
|
||||
|
||||
public JettyLoggerFactory getJettyLoggerFactory()
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// 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.util.Locale;
|
||||
|
||||
import org.slf4j.event.Level;
|
||||
|
||||
public class LevelUtils
|
||||
{
|
||||
public static Integer getLevelInt(String loggerName, 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 [" + loggerName + "]=[" + levelName + "], expecting only [ALL, TRACE, DEBUG, INFO, WARN, ERROR, OFF] as values.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
|
@ -609,6 +609,6 @@ public class JettyLoggerTest
|
|||
private void assertLevel(JettyLogger log, Level expectedLevel)
|
||||
{
|
||||
assertThat("Log[" + log.getName() + "].level",
|
||||
JettyLogger.levelToString(log.getLevel()), is(expectedLevel.toString()));
|
||||
LevelUtils.levelToString(log.getLevel()), is(expectedLevel.toString()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// 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.util.Properties;
|
||||
|
||||
public class JmxExperiment
|
||||
{
|
||||
public static void main(String[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
Properties props = new Properties();
|
||||
props.setProperty("org.eclipse.jetty.logging.jmx", "true");
|
||||
props.setProperty("org.eclipse.jetty.logging.jmx.contextName", "Main");
|
||||
props.setProperty("org.eclipse.jetty.logging.LEVEL", "DEBUG");
|
||||
JettyLoggerConfiguration config = new JettyLoggerConfiguration(props);
|
||||
JettyLoggerFactory loggerFactory = new JettyLoggerFactory(config);
|
||||
|
||||
JettyLoggingJmx.initialize(config, loggerFactory);
|
||||
|
||||
loggerFactory.getJettyLogger(JmxExperiment.class.getName()).info("Waiting for key-press");
|
||||
System.in.read();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue