From 67bd321bfcf62a32deb658fd7619245e774606fa Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Thu, 30 Apr 2020 14:51:42 -0500 Subject: [PATCH 01/10] Issue #4830 - Enabling JMX on jetty-slf4j-impl Signed-off-by: Joakim Erdfelt --- .../src/main/java/module-info.java | 2 + .../eclipse/jetty/logging/JettyLogger.java | 38 +------- .../logging/JettyLoggerConfiguration.java | 74 +++------------ .../jetty/logging/JettyLoggerFactory.java | 77 ++++++++++++++-- .../logging/JettyLoggerFactoryMBean.java | 31 +++++++ .../jetty/logging/JettyLoggingJmx.java | 50 +++++++++++ .../logging/JettyLoggingServiceProvider.java | 2 + .../org/eclipse/jetty/logging/LevelUtils.java | 90 +++++++++++++++++++ .../jetty/logging/JettyLoggerTest.java | 2 +- .../eclipse/jetty/logging/JmxExperiment.java | 46 ++++++++++ 10 files changed, 305 insertions(+), 107 deletions(-) create mode 100644 jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactoryMBean.java create mode 100644 jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggingJmx.java create mode 100644 jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/LevelUtils.java create mode 100644 jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JmxExperiment.java diff --git a/jetty-slf4j-impl/src/main/java/module-info.java b/jetty-slf4j-impl/src/main/java/module-info.java index 0bfb99cd437..3cfbbf20391 100644 --- a/jetty-slf4j-impl/src/main/java/module-info.java +++ b/jetty-slf4j-impl/src/main/java/module-info.java @@ -25,5 +25,7 @@ module org.eclipse.jetty.logging requires transitive org.slf4j; + requires static java.management; + provides SLF4JServiceProvider with JettyLoggingServiceProvider; } diff --git a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLogger.java b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLogger.java index 90e1a639b5b..54ab43069e8 100644 --- a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLogger.java +++ b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLogger.java @@ -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)); } } diff --git a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerConfiguration.java b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerConfiguration.java index 2864430fee2..547e54e82f3 100644 --- a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerConfiguration.java +++ b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerConfiguration.java @@ -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 walkParentLoggerNames(String startName, Function 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; - } } diff --git a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactory.java b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactory.java index 83d39cf71c1..f607ada4790 100644 --- a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactory.java +++ b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactory.java @@ -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 loggerMap; + private final ConcurrentMap 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 walkParentLoggerNames(String startName, Function 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); + } + } } diff --git a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactoryMBean.java b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactoryMBean.java new file mode 100644 index 00000000000..59c2da9f0a2 --- /dev/null +++ b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactoryMBean.java @@ -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); +} diff --git a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggingJmx.java b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggingJmx.java new file mode 100644 index 00000000000..f7aeac3a80e --- /dev/null +++ b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggingJmx.java @@ -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); + } + } +} diff --git a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggingServiceProvider.java b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggingServiceProvider.java index 01ad473162a..61e7ec47f40 100644 --- a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggingServiceProvider.java +++ b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggingServiceProvider.java @@ -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() diff --git a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/LevelUtils.java b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/LevelUtils.java new file mode 100644 index 00000000000..e78abf4817b --- /dev/null +++ b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/LevelUtils.java @@ -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 + } +} diff --git a/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JettyLoggerTest.java b/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JettyLoggerTest.java index 86b6fd6db8d..58b0c660573 100644 --- a/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JettyLoggerTest.java +++ b/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JettyLoggerTest.java @@ -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())); } } diff --git a/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JmxExperiment.java b/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JmxExperiment.java new file mode 100644 index 00000000000..26e12297d23 --- /dev/null +++ b/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JmxExperiment.java @@ -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(); + } + } +} From c144358f421a774ab1f34fbae1a173ea453baa60 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Fri, 1 May 2020 08:34:13 -0500 Subject: [PATCH 02/10] Issue #4830 - Adding jmx entries for logging-jetty module Signed-off-by: Joakim Erdfelt --- .../modules/logging/jetty/resources/jetty-logging.properties | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/jetty-home/src/main/resources/modules/logging/jetty/resources/jetty-logging.properties b/jetty-home/src/main/resources/modules/logging/jetty/resources/jetty-logging.properties index d0fdf6c5bd5..a9c6aeb60ab 100644 --- a/jetty-home/src/main/resources/modules/logging/jetty/resources/jetty-logging.properties +++ b/jetty-home/src/main/resources/modules/logging/jetty/resources/jetty-logging.properties @@ -4,5 +4,9 @@ org.eclipse.jetty.LEVEL=INFO #com.example.LEVEL=INFO ## Configure a level for specific logger #com.example.MyComponent.LEVEL=INFO +## Enable JMX management of Jetty Logging +# org.eclipse.jetty.logging.jmx=true +## Configure JMX Context Name +# org.eclipse.jetty.logging.jmx.contextName=JettyServer ## Hide stacks traces in an arbitrary logger tree #com.example.STACKS=false From d2399205ff7d7820c6757d0f9f4acec9bea79412 Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Sun, 3 May 2020 10:06:41 +0200 Subject: [PATCH 03/10] Issue #4830 - Add JMX to new Jetty 10 jetty-slf4j-impl. Alternative implementation that adds JMX support for jetty-slf4j-impl. This version modifies MBeanContainer to be aware of @MXBean annotations and *MBean and *MXBean interfaces, so it does not require a dependency on jetty-jmx nor on java.management. Signed-off-by: Simone Bordet --- examples/embedded/pom.xml | 2 +- .../eclipse/jetty/embedded/Http2Server.java | 3 + .../jetty/resources/jetty-logging.properties | 4 +- .../org/eclipse/jetty/jmx/MBeanContainer.java | 55 ++++++- jetty-slf4j-impl/pom.xml | 31 +++- .../src/main/java/module-info.java | 2 - .../eclipse/jetty/logging/JettyLogger.java | 74 +++++++++- .../logging/JettyLoggerConfiguration.java | 52 ++----- .../jetty/logging/JettyLoggerFactory.java | 134 ++++-------------- .../logging/JettyLoggerFactoryMBean.java | 3 +- .../jetty/logging/JettyLoggingJmx.java | 50 ------- .../logging/JettyLoggingServiceProvider.java | 2 - .../org/eclipse/jetty/logging/LevelUtils.java | 73 +++------- .../org/eclipse/jetty/logging/JMXTest.java | 74 ++++++++++ .../jetty/logging/JettyLoggerTest.java | 6 +- .../eclipse/jetty/logging/JmxExperiment.java | 46 ------ 16 files changed, 289 insertions(+), 322 deletions(-) delete mode 100644 jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggingJmx.java create mode 100644 jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JMXTest.java delete mode 100644 jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JmxExperiment.java diff --git a/examples/embedded/pom.xml b/examples/embedded/pom.xml index 22bc490c200..558be37b6e6 100644 --- a/examples/embedded/pom.xml +++ b/examples/embedded/pom.xml @@ -22,7 +22,7 @@ org.eclipse.jetty jetty-slf4j-impl - test + runtime org.eclipse.jetty diff --git a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/Http2Server.java b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/Http2Server.java index 22dfd38702a..c18551268d1 100644 --- a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/Http2Server.java +++ b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/Http2Server.java @@ -61,6 +61,7 @@ import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.servlets.PushCacheFilter; import org.eclipse.jetty.util.resource.PathResource; import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.slf4j.LoggerFactory; public class Http2Server { @@ -74,6 +75,8 @@ public class Http2Server ManagementFactory.getPlatformMBeanServer()); server.addBean(mbContainer); + server.addBean(LoggerFactory.getILoggerFactory()); + ServletContextHandler context = new ServletContextHandler(server, "/", ServletContextHandler.SESSIONS); Path docroot = Paths.get("src/main/resources/docroot"); if (!Files.exists(docroot)) diff --git a/jetty-home/src/main/resources/modules/logging/jetty/resources/jetty-logging.properties b/jetty-home/src/main/resources/modules/logging/jetty/resources/jetty-logging.properties index a9c6aeb60ab..fba91898dc4 100644 --- a/jetty-home/src/main/resources/modules/logging/jetty/resources/jetty-logging.properties +++ b/jetty-home/src/main/resources/modules/logging/jetty/resources/jetty-logging.properties @@ -4,9 +4,7 @@ org.eclipse.jetty.LEVEL=INFO #com.example.LEVEL=INFO ## Configure a level for specific logger #com.example.MyComponent.LEVEL=INFO -## Enable JMX management of Jetty Logging -# org.eclipse.jetty.logging.jmx=true ## Configure JMX Context Name -# org.eclipse.jetty.logging.jmx.contextName=JettyServer +# org.eclipse.jetty.logging.jmx.context=JettyServer ## Hide stacks traces in an arbitrary logger tree #com.example.STACKS=false diff --git a/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MBeanContainer.java b/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MBeanContainer.java index f8db4c44bd2..b6ed4b2a90c 100644 --- a/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MBeanContainer.java +++ b/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MBeanContainer.java @@ -30,10 +30,12 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; +import javax.management.DynamicMBean; import javax.management.InstanceNotFoundException; import javax.management.MBeanInfo; import javax.management.MBeanRegistrationException; import javax.management.MBeanServer; +import javax.management.MXBean; import javax.management.ObjectName; import javax.management.modelmbean.ModelMBean; @@ -60,7 +62,7 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable, De private final MBeanServer _mbeanServer; private final boolean _useCacheForOtherClassLoaders; - private final ConcurrentMap _metaData = new ConcurrentHashMap<>(); + private final ConcurrentMap, MetaData> _metaData = new ConcurrentHashMap<>(); private final ConcurrentMap _beans = new ConcurrentHashMap<>(); private final ConcurrentMap _mbeans = new ConcurrentHashMap<>(); private String _domain = null; @@ -151,7 +153,26 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable, De { if (o == null) return null; - Object mbean = findMetaData(container, o.getClass()).newInstance(o); + if (o instanceof DynamicMBean) + return o; + Class klass = o.getClass(); + while (klass != Object.class) + { + MXBean mxbean = klass.getAnnotation(MXBean.class); + if (mxbean != null && mxbean.value()) + return o; + String mbeanName = klass.getName() + "MBean"; + String mxbeanName = klass.getName() + "MXBean"; + Class[] interfaces = klass.getInterfaces(); + for (Class type : interfaces) + { + String name = type.getName(); + if (name.equals(mbeanName) || name.equals(mxbeanName)) + return o; + } + klass = klass.getSuperclass(); + } + Object mbean = findMetaData(container, klass).newInstance(o); if (mbean instanceof ObjectMBean) ((ObjectMBean)mbean).setMBeanContainer(container); if (LOG.isDebugEnabled()) @@ -338,7 +359,9 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable, De StringBuilder buf = new StringBuilder(); - String context = (mbean instanceof ObjectMBean) ? makeName(((ObjectMBean)mbean).getObjectContextBasis()) : null; + String context = (mbean instanceof ObjectMBean) + ? makeName(((ObjectMBean)mbean).getObjectContextBasis()) + : makeName(reflectContextBasis(mbean)); if (context == null && parentObjectName != null) context = parentObjectName.getKeyProperty("context"); @@ -347,7 +370,9 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable, De buf.append("type=").append(type); - String name = (mbean instanceof ObjectMBean) ? makeName(((ObjectMBean)mbean).getObjectNameBasis()) : context; + String name = (mbean instanceof ObjectMBean) + ? makeName(((ObjectMBean)mbean).getObjectNameBasis()) + : makeName(reflectNameBasis(mbean)); if (name != null && name.length() > 1) buf.append(",").append("name=").append(name); @@ -394,6 +419,28 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable, De } } + private String reflectContextBasis(Object mbean) + { + return reflectBasis(mbean, "jmxContext"); + } + + private String reflectNameBasis(Object mbean) + { + return reflectBasis(mbean, "jmxName"); + } + + private String reflectBasis(Object mbean, String methodName) + { + try + { + return (String)mbean.getClass().getMethod(methodName).invoke(mbean); + } + catch (Throwable x) + { + return null; + } + } + /** * @param basis name to strip of special characters. * @return normalized name diff --git a/jetty-slf4j-impl/pom.xml b/jetty-slf4j-impl/pom.xml index be399ee79a2..61d8e2fb1ce 100644 --- a/jetty-slf4j-impl/pom.xml +++ b/jetty-slf4j-impl/pom.xml @@ -4,16 +4,35 @@ jetty-project 10.0.0-SNAPSHOT + 4.0.0 jetty-slf4j-impl Jetty :: Slf4j Implementation Slf4j Logging Implementation based on Jetty's older StdErrLog - http://www.eclipse.org/jetty + ${project.groupId}.logging + + + maven-compiler-plugin + + + --add-modules + java.management + + + + + maven-surefire-plugin + + + @{argLine} ${jetty.surefire.argLine} --add-reads org.eclipse.jetty.logging=java.management + + + org.apache.felix maven-bundle-plugin @@ -29,15 +48,17 @@ + + + org.slf4j + slf4j-api + + org.eclipse.jetty.toolchain jetty-test-helper test - - org.slf4j - slf4j-api - diff --git a/jetty-slf4j-impl/src/main/java/module-info.java b/jetty-slf4j-impl/src/main/java/module-info.java index 3cfbbf20391..0bfb99cd437 100644 --- a/jetty-slf4j-impl/src/main/java/module-info.java +++ b/jetty-slf4j-impl/src/main/java/module-info.java @@ -25,7 +25,5 @@ module org.eclipse.jetty.logging requires transitive org.slf4j; - requires static java.management; - provides SLF4JServiceProvider with JettyLoggingServiceProvider; } diff --git a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLogger.java b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLogger.java index 54ab43069e8..e7eaff98155 100644 --- a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLogger.java +++ b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLogger.java @@ -32,18 +32,18 @@ public class JettyLogger implements LocationAwareLogger, Logger /** * The Level to set if you want this logger to be "OFF" */ - public static final int OFF = 999; + static final int OFF = 999; /** * The Level to set if you want this logger to show all events from all levels. */ - public static final int ALL = -1; + static final int ALL = Level.TRACE.toInt(); private final JettyLoggerFactory factory; private final String name; private final String condensedName; private final JettyAppender appender; private int level; - private boolean hideStacks = false; + private boolean hideStacks; public JettyLogger(JettyLoggerFactory factory, String name, JettyAppender appender) { @@ -54,12 +54,72 @@ public class JettyLogger implements LocationAwareLogger, Logger { this.factory = factory; this.name = name; - this.condensedName = JettyLoggerFactory.condensePackageString(name); + this.condensedName = condensePackageString(name); this.appender = appender; this.level = level; this.hideStacks = hideStacks; } + /** + * Condenses a classname by stripping down the package name to just the first character of each package name + * segment.Configured + * + *
+     * Examples:
+     * "org.eclipse.jetty.test.FooTest"           = "oejt.FooTest"
+     * "org.eclipse.jetty.server.logging.LogTest" = "orjsl.LogTest"
+     * 
+ * + * @param classname the fully qualified class name + * @return the condensed name + */ + private static String condensePackageString(String classname) + { + if (classname == null || classname.isEmpty()) + return ""; + + int rawLen = classname.length(); + StringBuilder dense = new StringBuilder(rawLen); + boolean foundStart = false; + boolean hasPackage = false; + int startIdx = -1; + int endIdx = -1; + for (int i = 0; i < rawLen; i++) + { + char c = classname.charAt(i); + if (!foundStart) + { + foundStart = Character.isJavaIdentifierStart(c); + if (foundStart) + { + if (startIdx >= 0) + { + dense.append(classname.charAt(startIdx)); + hasPackage = true; + } + startIdx = i; + } + } + + if (foundStart) + { + if (Character.isJavaIdentifierPart(c)) + endIdx = i; + else + foundStart = false; + } + } + // append remaining from startIdx + if ((startIdx >= 0) && (endIdx >= startIdx)) + { + if (hasPackage) + dense.append('.'); + dense.append(classname, startIdx, endIdx + 1); + } + + return dense.toString(); + } + @Override public void debug(String msg) { @@ -285,7 +345,7 @@ public class JettyLogger implements LocationAwareLogger, Logger this.level = lvlInt; // apply setLevel to children too. - factory.walkChildLoggers(this.getName(), (logger) -> logger.setLevel(lvlInt)); + factory.walkChildrenLoggers(this.getName(), (logger) -> logger.setLevel(lvlInt)); } @Override @@ -402,7 +462,7 @@ public class JettyLogger implements LocationAwareLogger, Logger this.hideStacks = hideStacks; // apply setHideStacks to children too. - factory.walkChildLoggers(this.getName(), (logger) -> logger.setHideStacks(hideStacks)); + factory.walkChildrenLoggers(this.getName(), (logger) -> logger.setHideStacks(hideStacks)); } @Override @@ -639,6 +699,6 @@ public class JettyLogger implements LocationAwareLogger, Logger @Override public String toString() { - return String.format("%s:%s:LEVEL=%s", JettyLogger.class.getSimpleName(), name, LevelUtils.levelToString(level)); + return String.format("%s:%s:LEVEL=%s", JettyLogger.class.getSimpleName(), name, LevelUtils.intToLevel(level)); } } diff --git a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerConfiguration.java b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerConfiguration.java index 547e54e82f3..ba00a0abadf 100644 --- a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerConfiguration.java +++ b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerConfiguration.java @@ -77,29 +77,22 @@ public class JettyLoggerConfiguration // strip ".STACKS" suffix (if present) if (startName.endsWith(SUFFIX_STACKS)) - { startName = startName.substring(0, startName.length() - SUFFIX_STACKS.length()); - } - Boolean hideStacks = JettyLoggerFactory.walkParentLoggerNames(startName, (key) -> + Boolean hideStacks = JettyLoggerFactory.walkParentLoggerNames(startName, key -> { String stacksBool = properties.getProperty(key + SUFFIX_STACKS); if (stacksBool != null) - { return Boolean.parseBoolean(stacksBool); - } return null; }); - if (hideStacks != null) - return hideStacks; - - return DEFAULT_HIDE_STACKS; + return hideStacks != null ? hideStacks : DEFAULT_HIDE_STACKS; } /** - * Get the Logging Level for the provided log name. Using the FQCN first, then each package segment from longest to - * shortest. + *

Returns the Logging Level for the provided log name.

+ *

Uses the FQCN first, then each package segment from longest to shortest.

* * @param name the name to get log for * @return the logging level int @@ -111,42 +104,30 @@ public class JettyLoggerConfiguration String startName = name != null ? name : ""; - // strip trailing dot + // Strip trailing dot. while (startName.endsWith(".")) { startName = startName.substring(0, startName.length() - 1); } - // strip ".LEVEL" suffix (if present) + // Strip ".LEVEL" suffix (if present). if (startName.endsWith(SUFFIX_LEVEL)) - { startName = startName.substring(0, startName.length() - SUFFIX_LEVEL.length()); - } - Integer level = JettyLoggerFactory.walkParentLoggerNames(startName, (key) -> + Integer level = JettyLoggerFactory.walkParentLoggerNames(startName, key -> { - String levelStr1 = properties.getProperty(key + SUFFIX_LEVEL); - if (levelStr1 != null) - { - return LevelUtils.getLevelInt(key, levelStr1); - } - return null; + String levelStr = properties.getProperty(key + SUFFIX_LEVEL); + return LevelUtils.getLevelInt(levelStr); }); if (level == null) { - // try legacy root logging config + // Try legacy root logging config. String levelStr = properties.getProperty("log" + SUFFIX_LEVEL); - if (levelStr != null) - { - level = LevelUtils.getLevelInt("log", levelStr); - } + level = LevelUtils.getLevelInt(levelStr); } - if (level != null) - return level; - - return DEFAULT_LEVEL; + return level != null ? level : DEFAULT_LEVEL; } public TimeZone getTimeZone(String key) @@ -154,7 +135,6 @@ public class JettyLoggerConfiguration String zoneIdStr = properties.getProperty(key); if (zoneIdStr == null) return null; - return TimeZone.getTimeZone(zoneIdStr); } @@ -207,9 +187,7 @@ public class JettyLoggerConfiguration { String val = properties.getProperty(key, Integer.toString(defValue)); if (val == null) - { return defValue; - } try { return Integer.parseInt(val); @@ -223,13 +201,9 @@ public class JettyLoggerConfiguration private URL getResource(ClassLoader loader, String resourceName) { if (loader == null) - { return ClassLoader.getSystemResource(resourceName); - } else - { return loader.getResource(resourceName); - } } /** @@ -260,9 +234,7 @@ public class JettyLoggerConfiguration { URL propsUrl = getResource(loader, resourceName); if (propsUrl == null) - { return null; - } try (InputStream in = propsUrl.openStream()) { diff --git a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactory.java b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactory.java index f607ada4790..e313cbe83b5 100644 --- a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactory.java +++ b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactory.java @@ -19,6 +19,7 @@ package org.eclipse.jetty.logging; import java.util.Objects; +import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.function.Consumer; @@ -46,6 +47,13 @@ public class JettyLoggerFactory implements ILoggerFactory, JettyLoggerFactoryMBe rootLogger.setLevel(configuration.getLevel(Logger.ROOT_LOGGER_NAME)); } + @SuppressWarnings("unused") + public String jmxContext() + { + // Used to build the ObjectName. + return configuration.getString("org.eclipse.jetty.logging.jmx.context", null); + } + /** * Get a {@link JettyLogger} instance, creating if not yet existing. * @@ -55,10 +63,7 @@ public class JettyLoggerFactory implements ILoggerFactory, JettyLoggerFactoryMBe public JettyLogger getJettyLogger(String name) { if (name.equals(Logger.ROOT_LOGGER_NAME)) - { return getRootLogger(); - } - return loggerMap.computeIfAbsent(name, this::createLogger); } @@ -74,118 +79,45 @@ public class JettyLoggerFactory implements ILoggerFactory, JettyLoggerFactoryMBe return getJettyLogger(name); } - protected void walkChildLoggers(String parentName, Consumer childConsumer) + void walkChildrenLoggers(String parentName, Consumer childConsumer) { String prefix = parentName; if (parentName.length() > 0 && !prefix.endsWith(".")) - { prefix += "."; - } for (JettyLogger logger : loggerMap.values()) { + // Skip self. if (logger.getName().equals(parentName)) - { - // skip self continue; - } - // is child, and is not itself + // It is a child, and is not itself. if (logger.getName().startsWith(prefix)) - { childConsumer.accept(logger); - } } } - public JettyLogger getRootLogger() + JettyLogger getRootLogger() { return rootLogger; } private JettyLogger createLogger(String name) { - // or is that handled by slf4j itself? JettyAppender appender = rootLogger.getAppender(); int level = this.configuration.getLevel(name); boolean hideStacks = this.configuration.getHideStacks(name); return new JettyLogger(this, name, appender, level, hideStacks); } - /** - * Condenses a classname by stripping down the package name to just the first character of each package name - * segment.Configured - * - *
-     * Examples:
-     * "org.eclipse.jetty.test.FooTest"           = "oejt.FooTest"
-     * "org.eclipse.jetty.server.logging.LogTest" = "orjsl.LogTest"
-     * 
- * - * @param classname the fully qualified class name - * @return the condensed name - */ - protected static String condensePackageString(String classname) + static T walkParentLoggerNames(String startName, Function nameFunction) { - if (classname == null || classname.isEmpty()) - { - return ""; - } - - int rawLen = classname.length(); - StringBuilder dense = new StringBuilder(rawLen); - boolean foundStart = false; - boolean hasPackage = false; - int startIdx = -1; - int endIdx = -1; - for (int i = 0; i < rawLen; i++) - { - char c = classname.charAt(i); - if (!foundStart) - { - foundStart = Character.isJavaIdentifierStart(c); - if (foundStart) - { - if (startIdx >= 0) - { - dense.append(classname.charAt(startIdx)); - hasPackage = true; - } - startIdx = i; - } - } - - if (foundStart) - { - if (!Character.isJavaIdentifierPart(c)) - { - foundStart = false; - } - else - { - endIdx = i; - } - } - } - // append remaining from startIdx - if ((startIdx >= 0) && (endIdx >= startIdx)) - { - if (hasPackage) - { - dense.append('.'); - } - dense.append(classname, startIdx, endIdx + 1); - } - - return dense.toString(); - } - - public static T walkParentLoggerNames(String startName, Function nameFunction) - { - String nameSegment = startName; + if (startName == null) + return null; // Checking with FQCN first, then each package segment from longest to shortest. - while ((nameSegment != null) && (nameSegment.length() > 0)) + String nameSegment = startName; + while (nameSegment.length() > 0) { T ret = nameFunction.apply(nameSegment); if (ret != null) @@ -194,22 +126,18 @@ public class JettyLoggerFactory implements ILoggerFactory, JettyLoggerFactoryMBe // Trim and try again. int idx = nameSegment.lastIndexOf('.'); if (idx >= 0) - { nameSegment = nameSegment.substring(0, idx); - } else - { - nameSegment = null; - } + break; } - return null; } @Override public String[] getLoggerNames() { - return loggerMap.keySet().toArray(new String[0]); + TreeSet names = new TreeSet<>(loggerMap.keySet()); + return names.toArray(new String[0]); } @Override @@ -221,25 +149,23 @@ public class JettyLoggerFactory implements ILoggerFactory, JettyLoggerFactoryMBe @Override public String getLoggerLevel(String loggerName) { - return walkParentLoggerNames(loggerName, (key) -> + return walkParentLoggerNames(loggerName, key -> { JettyLogger logger = loggerMap.get(key); - if (key != null) - { - return LevelUtils.levelToString(logger.getLevel()); - } + if (logger != null) + return LevelUtils.intToLevel(logger.getLevel()).toString(); return null; }); } @Override - public void setLoggerLevel(String loggerName, String levelName) + public boolean setLoggerLevel(String loggerName, String levelName) { - Integer levelInt = LevelUtils.getLevelInt(loggerName, levelName); - if (levelInt != null) - { - JettyLogger jettyLogger = getJettyLogger(loggerName); - jettyLogger.setLevel(levelInt); - } + Integer levelInt = LevelUtils.getLevelInt(levelName); + if (levelInt == null) + return false; + JettyLogger jettyLogger = getJettyLogger(loggerName); + jettyLogger.setLevel(levelInt); + return true; } } diff --git a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactoryMBean.java b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactoryMBean.java index 59c2da9f0a2..304410df716 100644 --- a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactoryMBean.java +++ b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactoryMBean.java @@ -18,14 +18,13 @@ package org.eclipse.jetty.logging; -@SuppressWarnings("unused") public interface JettyLoggerFactoryMBean { int getLoggerCount(); String[] getLoggerNames(); - void setLoggerLevel(String loggerName, String levelName); + boolean setLoggerLevel(String loggerName, String levelName); String getLoggerLevel(String loggerName); } diff --git a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggingJmx.java b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggingJmx.java deleted file mode 100644 index f7aeac3a80e..00000000000 --- a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggingJmx.java +++ /dev/null @@ -1,50 +0,0 @@ -// -// ======================================================================== -// 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); - } - } -} diff --git a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggingServiceProvider.java b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggingServiceProvider.java index 61e7ec47f40..01ad473162a 100644 --- a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggingServiceProvider.java +++ b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggingServiceProvider.java @@ -45,8 +45,6 @@ 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() diff --git a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/LevelUtils.java b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/LevelUtils.java index e78abf4817b..9f4cbfbac2a 100644 --- a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/LevelUtils.java +++ b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/LevelUtils.java @@ -24,67 +24,34 @@ import org.slf4j.event.Level; public class LevelUtils { - public static Integer getLevelInt(String loggerName, String levelStr) + public static Integer getLevelInt(String levelStr) { - if (levelStr == null) + try + { + if (levelStr == null) + return null; + String levelName = levelStr.trim().toUpperCase(Locale.ENGLISH); + if ("ALL".equals(levelName)) + return Level.TRACE.toInt(); + return Level.valueOf(levelName).toInt(); + } + catch (Throwable x) { 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) + try + { + if (level < JettyLogger.ALL) + return Level.TRACE; + return Level.intToLevel(level); + } + catch (Throwable x) + { 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 + } } } diff --git a/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JMXTest.java b/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JMXTest.java new file mode 100644 index 00000000000..70d6dbda114 --- /dev/null +++ b/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JMXTest.java @@ -0,0 +1,74 @@ +// +// ======================================================================== +// 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 java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; +import java.util.Properties; +import javax.management.JMX; +import javax.management.MBeanServer; +import javax.management.ObjectName; + +import org.junit.jupiter.api.Test; +import org.slf4j.event.Level; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class JMXTest +{ + @Test + public void testJMX() throws Exception + { + MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer(); + + Properties props = new Properties(); + JettyLoggerConfiguration config = new JettyLoggerConfiguration(props); + JettyLoggerFactory loggerFactory = new JettyLoggerFactory(config); + + ObjectName objectName = ObjectName.getInstance("org.eclipse.jetty.logging", "type", JettyLoggerFactory.class.getSimpleName().toLowerCase(Locale.ENGLISH)); + mbeanServer.registerMBean(loggerFactory, objectName); + + JettyLoggerFactoryMBean mbean = JMX.newMBeanProxy(mbeanServer, objectName, JettyLoggerFactoryMBean.class); + + // Only the root logger. + assertEquals(1, mbean.getLoggerCount()); + + JettyLogger child = loggerFactory.getJettyLogger("org.eclipse.jetty.logging"); + JettyLogger parent = loggerFactory.getJettyLogger("org.eclipse.jetty"); + assertEquals(3, mbean.getLoggerCount()); + + // Names are sorted. + List expected = new ArrayList<>(Arrays.asList(JettyLogger.ROOT_LOGGER_NAME, parent.getName(), child.getName())); + expected.sort(String::compareTo); + String[] loggerNames = mbean.getLoggerNames(); + assertEquals(expected, Arrays.asList(loggerNames)); + + // Setting the parent level should propagate to the children. + parent.setLevel(Level.DEBUG); + assertEquals(Level.intToLevel(parent.getLevel()).toString(), mbean.getLoggerLevel(child.getName())); + + // Setting the level via JMX affects the logger. + assertTrue(mbean.setLoggerLevel(child.getName(), "INFO")); + assertEquals(Level.INFO.toInt(), child.getLevel()); + } +} diff --git a/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JettyLoggerTest.java b/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JettyLoggerTest.java index 58b0c660573..857afc19788 100644 --- a/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JettyLoggerTest.java +++ b/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JettyLoggerTest.java @@ -526,7 +526,7 @@ public class JettyLoggerTest assertThat("Logger.toString", log.toString(), is("JettyLogger:xxx:LEVEL=ERROR")); log.setLevel(JettyLogger.OFF); - assertThat("Logger.toString", log.toString(), is("JettyLogger:xxx:LEVEL=OFF")); + assertThat("Logger.toString", log.toString(), is("JettyLogger:xxx:LEVEL=ERROR")); } @Test @@ -556,7 +556,7 @@ public class JettyLoggerTest assertLevel(log, Level.DEBUG); // as stomped // Restore configured - factory.walkChildLoggers(root.getName(), (logger) -> + factory.walkChildrenLoggers(root.getName(), (logger) -> { int configuredLevel = config.getLevel(logger.getName()); logger.setLevel(configuredLevel); @@ -609,6 +609,6 @@ public class JettyLoggerTest private void assertLevel(JettyLogger log, Level expectedLevel) { assertThat("Log[" + log.getName() + "].level", - LevelUtils.levelToString(log.getLevel()), is(expectedLevel.toString())); + LevelUtils.intToLevel(log.getLevel()), is(expectedLevel)); } } diff --git a/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JmxExperiment.java b/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JmxExperiment.java deleted file mode 100644 index 26e12297d23..00000000000 --- a/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JmxExperiment.java +++ /dev/null @@ -1,46 +0,0 @@ -// -// ======================================================================== -// 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(); - } - } -} From f98e2f8e140a86aa469830bb2c8327ca7bcc6c82 Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Sun, 3 May 2020 21:40:27 +0200 Subject: [PATCH 04/10] Issue #4830 - Add JMX to new Jetty 10 jetty-slf4j-impl. Updates after review. Fixed test failures. Signed-off-by: Simone Bordet --- .../src/main/java/org/eclipse/jetty/jmx/MBeanContainer.java | 2 +- .../java/org/eclipse/jetty/logging/JettyLoggerFactory.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MBeanContainer.java b/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MBeanContainer.java index b6ed4b2a90c..39564ac64c0 100644 --- a/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MBeanContainer.java +++ b/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MBeanContainer.java @@ -172,7 +172,7 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable, De } klass = klass.getSuperclass(); } - Object mbean = findMetaData(container, klass).newInstance(o); + Object mbean = findMetaData(container, o.getClass()).newInstance(o); if (mbean instanceof ObjectMBean) ((ObjectMBean)mbean).setMBeanContainer(container); if (LOG.isDebugEnabled()) diff --git a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactory.java b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactory.java index e313cbe83b5..849d2812e9b 100644 --- a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactory.java +++ b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactory.java @@ -130,7 +130,8 @@ public class JettyLoggerFactory implements ILoggerFactory, JettyLoggerFactoryMBe else break; } - return null; + + return nameFunction.apply(Logger.ROOT_LOGGER_NAME); } @Override From 1c4f05d2d8a6f6b02c7033576569525e88463759 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Fri, 8 May 2020 12:34:12 -0500 Subject: [PATCH 05/10] Issue #4830 - Cleaning up Level handling with JettyLevel enum Signed-off-by: Joakim Erdfelt --- .../org/eclipse/jetty/logging/JettyLevel.java | 114 ++++++++++++++++++ .../eclipse/jetty/logging/JettyLogger.java | 44 +++---- .../logging/JettyLoggerConfiguration.java | 19 +-- .../jetty/logging/JettyLoggerFactory.java | 16 ++- .../org/eclipse/jetty/logging/LevelUtils.java | 57 --------- .../org/eclipse/jetty/logging/JMXTest.java | 7 +- .../logging/JettyLoggerConfigurationTest.java | 81 ++++++------- .../jetty/logging/JettyLoggerTest.java | 92 +++++++------- .../jetty/xml/XmlConfigurationTest.java | 3 +- 9 files changed, 244 insertions(+), 189 deletions(-) create mode 100644 jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLevel.java delete mode 100644 jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/LevelUtils.java diff --git a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLevel.java b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLevel.java new file mode 100644 index 00000000000..038ca466a99 --- /dev/null +++ b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLevel.java @@ -0,0 +1,114 @@ +// +// ======================================================================== +// 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 enum JettyLevel +{ + // Intentionally sorted incrementally by level int + ALL(Level.TRACE.toInt() - 10), + TRACE(Level.TRACE), + DEBUG(Level.DEBUG), + INFO(Level.INFO), + WARN(Level.WARN), + ERROR(Level.ERROR), + OFF(Level.ERROR.toInt() + 1); + + private final Level level; + private final int levelInt; + + JettyLevel(Level level) + { + this.level = level; + this.levelInt = level.toInt(); + } + + JettyLevel(int i) + { + this.level = null; + this.levelInt = i; + } + + public static JettyLevel fromLevel(Level slf4jLevel) + { + for (JettyLevel level : JettyLevel.values()) + { + if (slf4jLevel.toInt() == level.levelInt) + return level; + } + return OFF; + } + + public int toInt() + { + return levelInt; + } + + public Level toLevel() + { + return level; + } + + /** + * Tests that a provided level is included by the level value of this level. + * + * @param testLevel the level to test against. + * @return true if includes this includes the test level. + */ + public boolean includes(JettyLevel testLevel) + { + return (this.levelInt <= testLevel.levelInt); + } + + @Override + public String toString() + { + return name(); + } + + public static JettyLevel intToLevel(int levelInt) + { + for (JettyLevel level : JettyLevel.values()) + { + if (levelInt <= level.levelInt) + return level; + } + return OFF; + } + + public static JettyLevel strToLevel(String levelStr) + { + if (levelStr == null) + { + return null; + } + + String levelName = levelStr.trim().toUpperCase(Locale.ENGLISH); + for (JettyLevel level : JettyLevel.values()) + { + if (level.name().equals(levelName)) + return level; + } + + return null; + } +} diff --git a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLogger.java b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLogger.java index e7eaff98155..7367a215911 100644 --- a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLogger.java +++ b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLogger.java @@ -18,8 +18,6 @@ package org.eclipse.jetty.logging; -import java.util.Objects; - import org.slf4j.Logger; import org.slf4j.Marker; import org.slf4j.event.Level; @@ -29,28 +27,19 @@ import org.slf4j.spi.LocationAwareLogger; public class JettyLogger implements LocationAwareLogger, Logger { - /** - * The Level to set if you want this logger to be "OFF" - */ - static final int OFF = 999; - /** - * The Level to set if you want this logger to show all events from all levels. - */ - static final int ALL = Level.TRACE.toInt(); - private final JettyLoggerFactory factory; private final String name; private final String condensedName; private final JettyAppender appender; - private int level; + private JettyLevel level; private boolean hideStacks; public JettyLogger(JettyLoggerFactory factory, String name, JettyAppender appender) { - this(factory, name, appender, Level.INFO.toInt(), false); + this(factory, name, appender, JettyLevel.INFO, false); } - public JettyLogger(JettyLoggerFactory factory, String name, JettyAppender appender, int level, boolean hideStacks) + public JettyLogger(JettyLoggerFactory factory, String name, JettyAppender appender, JettyLevel level, boolean hideStacks) { this.factory = factory; this.name = name; @@ -303,11 +292,11 @@ public class JettyLogger implements LocationAwareLogger, Logger @Override public void log(Marker marker, String fqcn, int levelInt, String message, Object[] argArray, Throwable throwable) { - if (this.level <= levelInt) + if (this.level.toInt() <= levelInt) { long timestamp = System.currentTimeMillis(); String threadName = Thread.currentThread().getName(); - getAppender().emit(this, LevelUtils.intToLevel(levelInt), timestamp, threadName, throwable, message, argArray); + getAppender().emit(this, JettyLevel.intToLevel(levelInt).toLevel(), timestamp, threadName, throwable, message, argArray); } } @@ -329,23 +318,22 @@ public class JettyLogger implements LocationAwareLogger, Logger return condensedName; } - public int getLevel() + public JettyLevel getLevel() { return level; } public void setLevel(Level level) { - Objects.requireNonNull(level, "Level"); - setLevel(level.toInt()); + setLevel(JettyLevel.fromLevel(level)); } - public void setLevel(int lvlInt) + public void setLevel(JettyLevel level) { - this.level = lvlInt; + this.level = level; // apply setLevel to children too. - factory.walkChildrenLoggers(this.getName(), (logger) -> logger.setLevel(lvlInt)); + factory.walkChildrenLoggers(this.getName(), (logger) -> logger.setLevel(level)); } @Override @@ -443,13 +431,13 @@ public class JettyLogger implements LocationAwareLogger, Logger @Override public boolean isDebugEnabled() { - return level <= Level.DEBUG.toInt(); + return level.includes(JettyLevel.DEBUG); } @Override public boolean isErrorEnabled() { - return level <= Level.ERROR.toInt(); + return level.includes(JettyLevel.ERROR); } public boolean isHideStacks() @@ -468,19 +456,19 @@ public class JettyLogger implements LocationAwareLogger, Logger @Override public boolean isInfoEnabled() { - return level <= Level.INFO.toInt(); + return level.includes(JettyLevel.INFO); } @Override public boolean isTraceEnabled() { - return level <= Level.TRACE.toInt(); + return level.includes(JettyLevel.TRACE); } @Override public boolean isWarnEnabled() { - return level <= Level.WARN.toInt(); + return level.includes(JettyLevel.WARN); } @Override @@ -699,6 +687,6 @@ public class JettyLogger implements LocationAwareLogger, Logger @Override public String toString() { - return String.format("%s:%s:LEVEL=%s", JettyLogger.class.getSimpleName(), name, LevelUtils.intToLevel(level)); + return String.format("%s:%s:LEVEL=%s", JettyLogger.class.getSimpleName(), name, level.name()); } } diff --git a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerConfiguration.java b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerConfiguration.java index ba00a0abadf..4096ab4f70e 100644 --- a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerConfiguration.java +++ b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerConfiguration.java @@ -27,8 +27,6 @@ import java.util.Locale; import java.util.Properties; import java.util.TimeZone; -import org.slf4j.event.Level; - /** * JettyLogger specific configuration: *
    @@ -38,7 +36,7 @@ import org.slf4j.event.Level; */ public class JettyLoggerConfiguration { - private static final int DEFAULT_LEVEL = Level.INFO.toInt(); + private static final JettyLevel DEFAULT_LEVEL = JettyLevel.INFO; private static final boolean DEFAULT_HIDE_STACKS = false; private static final String SUFFIX_LEVEL = ".LEVEL"; private static final String SUFFIX_STACKS = ".STACKS"; @@ -97,7 +95,7 @@ public class JettyLoggerConfiguration * @param name the name to get log for * @return the logging level int */ - public int getLevel(String name) + public JettyLevel getLevel(String name) { if (properties.isEmpty()) return DEFAULT_LEVEL; @@ -114,17 +112,24 @@ public class JettyLoggerConfiguration if (startName.endsWith(SUFFIX_LEVEL)) startName = startName.substring(0, startName.length() - SUFFIX_LEVEL.length()); - Integer level = JettyLoggerFactory.walkParentLoggerNames(startName, key -> + JettyLevel level = JettyLoggerFactory.walkParentLoggerNames(startName, key -> { String levelStr = properties.getProperty(key + SUFFIX_LEVEL); - return LevelUtils.getLevelInt(levelStr); + return JettyLevel.strToLevel(levelStr); }); + if (level == null) + { + // Try slf4j root logging config. + String levelStr = properties.getProperty(JettyLogger.ROOT_LOGGER_NAME + SUFFIX_LEVEL); + level = JettyLevel.strToLevel(levelStr); + } + if (level == null) { // Try legacy root logging config. String levelStr = properties.getProperty("log" + SUFFIX_LEVEL); - level = LevelUtils.getLevelInt(levelStr); + level = JettyLevel.strToLevel(levelStr); } return level != null ? level : DEFAULT_LEVEL; diff --git a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactory.java b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactory.java index 849d2812e9b..fd97bd771b5 100644 --- a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactory.java +++ b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactory.java @@ -24,6 +24,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.function.Consumer; import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; import org.slf4j.ILoggerFactory; import org.slf4j.Logger; @@ -105,7 +107,7 @@ public class JettyLoggerFactory implements ILoggerFactory, JettyLoggerFactoryMBe private JettyLogger createLogger(String name) { JettyAppender appender = rootLogger.getAppender(); - int level = this.configuration.getLevel(name); + JettyLevel level = this.configuration.getLevel(name); boolean hideStacks = this.configuration.getHideStacks(name); return new JettyLogger(this, name, appender, level, hideStacks); } @@ -154,7 +156,7 @@ public class JettyLoggerFactory implements ILoggerFactory, JettyLoggerFactoryMBe { JettyLogger logger = loggerMap.get(key); if (logger != null) - return LevelUtils.intToLevel(logger.getLevel()).toString(); + return logger.getLevel().toString(); return null; }); } @@ -162,11 +164,15 @@ public class JettyLoggerFactory implements ILoggerFactory, JettyLoggerFactoryMBe @Override public boolean setLoggerLevel(String loggerName, String levelName) { - Integer levelInt = LevelUtils.getLevelInt(levelName); - if (levelInt == null) + JettyLevel level = JettyLevel.strToLevel(levelName); + if (level == null) + { + System.err.printf("Unknown JettyLogger/Slf4J Level [%s]=[%s], expecting only [%s] as values.", + loggerName, levelName, Stream.of(JettyLevel.values()).map(JettyLevel::toString).collect(Collectors.joining(", "))); return false; + } JettyLogger jettyLogger = getJettyLogger(loggerName); - jettyLogger.setLevel(levelInt); + jettyLogger.setLevel(level); return true; } } diff --git a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/LevelUtils.java b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/LevelUtils.java deleted file mode 100644 index 9f4cbfbac2a..00000000000 --- a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/LevelUtils.java +++ /dev/null @@ -1,57 +0,0 @@ -// -// ======================================================================== -// 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 levelStr) - { - try - { - if (levelStr == null) - return null; - String levelName = levelStr.trim().toUpperCase(Locale.ENGLISH); - if ("ALL".equals(levelName)) - return Level.TRACE.toInt(); - return Level.valueOf(levelName).toInt(); - } - catch (Throwable x) - { - return null; - } - } - - public static Level intToLevel(int level) - { - try - { - if (level < JettyLogger.ALL) - return Level.TRACE; - return Level.intToLevel(level); - } - catch (Throwable x) - { - return Level.ERROR; - } - } -} diff --git a/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JMXTest.java b/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JMXTest.java index 70d6dbda114..6719982f81c 100644 --- a/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JMXTest.java +++ b/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JMXTest.java @@ -29,7 +29,6 @@ import javax.management.MBeanServer; import javax.management.ObjectName; import org.junit.jupiter.api.Test; -import org.slf4j.event.Level; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -64,11 +63,11 @@ public class JMXTest assertEquals(expected, Arrays.asList(loggerNames)); // Setting the parent level should propagate to the children. - parent.setLevel(Level.DEBUG); - assertEquals(Level.intToLevel(parent.getLevel()).toString(), mbean.getLoggerLevel(child.getName())); + parent.setLevel(JettyLevel.DEBUG); + assertEquals(parent.getLevel().toString(), mbean.getLoggerLevel(child.getName())); // Setting the level via JMX affects the logger. assertTrue(mbean.setLoggerLevel(child.getName(), "INFO")); - assertEquals(Level.INFO.toInt(), child.getLevel()); + assertEquals(JettyLevel.INFO, child.getLevel()); } } diff --git a/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JettyLoggerConfigurationTest.java b/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JettyLoggerConfigurationTest.java index bc3982c0c64..14def8a813c 100644 --- a/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JettyLoggerConfigurationTest.java +++ b/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JettyLoggerConfigurationTest.java @@ -21,7 +21,6 @@ package org.eclipse.jetty.logging; import java.util.Properties; import org.junit.jupiter.api.Test; -import org.slf4j.event.Level; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -46,8 +45,8 @@ public class JettyLoggerConfigurationTest assertFalse(appender.isCondensedNames()); assertEquals(appender.getThreadPadding(), 10); - int level = config.getLevel("com.mortbay"); - assertEquals(Level.WARN.toInt(), level); + JettyLevel level = config.getLevel("com.mortbay"); + assertEquals(JettyLevel.WARN, level); boolean stacks = config.getHideStacks("com.mortbay.Foo"); assertFalse(stacks); @@ -59,8 +58,8 @@ public class JettyLoggerConfigurationTest Properties props = new Properties(); props.setProperty("com.mortbay.LEVEL", "WARN"); JettyLoggerConfiguration config = new JettyLoggerConfiguration(props); - int level = config.getLevel("com.mortbay"); - assertEquals(Level.WARN.toInt(), level); + JettyLevel level = config.getLevel("com.mortbay"); + assertEquals(JettyLevel.WARN, level); } @Test @@ -70,8 +69,8 @@ public class JettyLoggerConfigurationTest props.setProperty("com.mortbay.LEVEL", "WARN"); JettyLoggerConfiguration config = new JettyLoggerConfiguration(props); // extra trailing dot "." - int level = config.getLevel("com.mortbay."); - assertEquals(Level.WARN.toInt(), level); + JettyLevel level = config.getLevel("com.mortbay."); + assertEquals(JettyLevel.WARN, level); } @Test @@ -81,8 +80,8 @@ public class JettyLoggerConfigurationTest props.setProperty("com.mortbay.LEVEL", "WARN"); JettyLoggerConfiguration config = new JettyLoggerConfiguration(props); // asking for name with ".LEVEL" - int level = config.getLevel("com.mortbay.Bar.LEVEL"); - assertEquals(Level.WARN.toInt(), level); + JettyLevel level = config.getLevel("com.mortbay.Bar.LEVEL"); + assertEquals(JettyLevel.WARN, level); } @Test @@ -91,8 +90,8 @@ public class JettyLoggerConfigurationTest Properties props = new Properties(); props.setProperty("com.mortbay.LEVEL", "WARN"); JettyLoggerConfiguration config = new JettyLoggerConfiguration(props); - int level = config.getLevel("com.mortbay.Foo"); - assertEquals(Level.WARN.toInt(), level); + JettyLevel level = config.getLevel("com.mortbay.Foo"); + assertEquals(JettyLevel.WARN, level); } @Test @@ -102,8 +101,8 @@ public class JettyLoggerConfigurationTest props.setProperty("com.mortbay.LEVEL", "WARN"); JettyLoggerConfiguration config = new JettyLoggerConfiguration(props); // asking for name that isn't configured, returns default value - int level = config.getLevel("org.eclipse.jetty"); - assertEquals(Level.INFO.toInt(), level); + JettyLevel level = config.getLevel("org.eclipse.jetty"); + assertEquals(JettyLevel.INFO, level); } @Test @@ -168,7 +167,7 @@ public class JettyLoggerConfigurationTest JettyLoggerConfiguration config = new JettyLoggerConfiguration(props); // Default Level (because of bad level value) - assertEquals(Level.WARN.toInt(), config.getLevel("org.eclipse.jetty.bad")); + assertEquals(JettyLevel.WARN, config.getLevel("org.eclipse.jetty.bad")); } @Test @@ -180,9 +179,9 @@ public class JettyLoggerConfigurationTest JettyLoggerConfiguration config = new JettyLoggerConfiguration(props); // Default Level - assertEquals(Level.WARN.toInt(), config.getLevel("org.eclipse.jetty")); + assertEquals(JettyLevel.WARN, config.getLevel("org.eclipse.jetty")); // Specific Level - assertEquals(Level.INFO.toInt(), config.getLevel("org.eclipse.jetty.util")); + assertEquals(JettyLevel.INFO, config.getLevel("org.eclipse.jetty.util")); } @Test @@ -193,11 +192,11 @@ public class JettyLoggerConfigurationTest JettyLoggerConfiguration config = new JettyLoggerConfiguration(props); // Default Levels - assertEquals(Level.DEBUG.toInt(), config.getLevel(null)); - assertEquals(Level.DEBUG.toInt(), config.getLevel("")); - assertEquals(Level.DEBUG.toInt(), config.getLevel("org.eclipse.jetty")); + assertEquals(JettyLevel.DEBUG, config.getLevel(null)); + assertEquals(JettyLevel.DEBUG, config.getLevel("")); + assertEquals(JettyLevel.DEBUG, config.getLevel("org.eclipse.jetty")); String name = JettyLoggerConfigurationTest.class.getName(); - assertEquals(Level.DEBUG.toInt(), config.getLevel(name), "Default Logging Level - " + name + " name"); + assertEquals(JettyLevel.DEBUG, config.getLevel(name), "Default Logging Level - " + name + " name"); } @Test @@ -209,12 +208,12 @@ public class JettyLoggerConfigurationTest JettyLoggerConfiguration config = new JettyLoggerConfiguration(props); // Default Levels - assertEquals(Level.INFO.toInt(), config.getLevel(null)); - assertEquals(Level.INFO.toInt(), config.getLevel("")); - assertEquals(Level.INFO.toInt(), config.getLevel("org.eclipse.jetty")); + assertEquals(JettyLevel.INFO, config.getLevel(null)); + assertEquals(JettyLevel.INFO, config.getLevel("")); + assertEquals(JettyLevel.INFO, config.getLevel("org.eclipse.jetty")); // Specified Level - assertEquals(JettyLogger.ALL, config.getLevel(name)); + assertEquals(JettyLevel.ALL, config.getLevel(name)); } @Test @@ -225,16 +224,16 @@ public class JettyLoggerConfigurationTest JettyLoggerConfiguration config = new JettyLoggerConfiguration(props); // Default Levels - assertEquals(Level.INFO.toInt(), config.getLevel(null)); - assertEquals(Level.INFO.toInt(), config.getLevel("")); - assertEquals(Level.INFO.toInt(), config.getLevel("org.eclipse.jetty")); - assertEquals(Level.INFO.toInt(), config.getLevel("org.eclipse.jetty.server.BogusObject")); - assertEquals(Level.INFO.toInt(), config.getLevel(JettyLoggerConfigurationTest.class.getName())); + assertEquals(JettyLevel.INFO, config.getLevel(null)); + assertEquals(JettyLevel.INFO, config.getLevel("")); + assertEquals(JettyLevel.INFO, config.getLevel("org.eclipse.jetty")); + assertEquals(JettyLevel.INFO, config.getLevel("org.eclipse.jetty.server.BogusObject")); + assertEquals(JettyLevel.INFO, config.getLevel(JettyLoggerConfigurationTest.class.getName())); // Configured Level - assertEquals(Level.DEBUG.toInt(), config.getLevel("org.eclipse.jetty.util.Bogus")); - assertEquals(Level.DEBUG.toInt(), config.getLevel("org.eclipse.jetty.util")); - assertEquals(Level.DEBUG.toInt(), config.getLevel("org.eclipse.jetty.util.resource.PathResource")); + assertEquals(JettyLevel.DEBUG, config.getLevel("org.eclipse.jetty.util.Bogus")); + assertEquals(JettyLevel.DEBUG, config.getLevel("org.eclipse.jetty.util")); + assertEquals(JettyLevel.DEBUG, config.getLevel("org.eclipse.jetty.util.resource.PathResource")); } @Test @@ -248,17 +247,17 @@ public class JettyLoggerConfigurationTest JettyLoggerConfiguration config = new JettyLoggerConfiguration(props); // Default Levels - assertEquals(Level.DEBUG.toInt(), config.getLevel(null)); - assertEquals(Level.DEBUG.toInt(), config.getLevel("")); - assertEquals(Level.DEBUG.toInt(), config.getLevel("org.eclipse.jetty")); - assertEquals(Level.DEBUG.toInt(), config.getLevel("org.eclipse.jetty.server.BogusObject")); - assertEquals(Level.DEBUG.toInt(), config.getLevel(JettyLoggerConfigurationTest.class.getName())); + assertEquals(JettyLevel.DEBUG, config.getLevel(null)); + assertEquals(JettyLevel.DEBUG, config.getLevel("")); + assertEquals(JettyLevel.DEBUG, config.getLevel("org.eclipse.jetty")); + assertEquals(JettyLevel.DEBUG, config.getLevel("org.eclipse.jetty.server.BogusObject")); + assertEquals(JettyLevel.DEBUG, config.getLevel(JettyLoggerConfigurationTest.class.getName())); // Configured Level - assertEquals(Level.WARN.toInt(), config.getLevel("org.eclipse.jetty.util.MagicUtil")); - assertEquals(Level.WARN.toInt(), config.getLevel("org.eclipse.jetty.util")); - assertEquals(Level.WARN.toInt(), config.getLevel("org.eclipse.jetty.util.resource.PathResource")); + assertEquals(JettyLevel.WARN, config.getLevel("org.eclipse.jetty.util.MagicUtil")); + assertEquals(JettyLevel.WARN, config.getLevel("org.eclipse.jetty.util")); + assertEquals(JettyLevel.WARN, config.getLevel("org.eclipse.jetty.util.resource.PathResource")); - assertEquals(JettyLogger.ALL, config.getLevel("org.eclipse.jetty.util.ConcurrentHashMap")); + assertEquals(JettyLevel.ALL, config.getLevel("org.eclipse.jetty.util.ConcurrentHashMap")); } } diff --git a/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JettyLoggerTest.java b/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JettyLoggerTest.java index 857afc19788..02a0167f45c 100644 --- a/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JettyLoggerTest.java +++ b/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JettyLoggerTest.java @@ -91,11 +91,11 @@ public class JettyLoggerTest JettyLogger log = factory.getJettyLogger("xxx"); - log.setLevel(Level.DEBUG); + log.setLevel(JettyLevel.DEBUG); log.debug("testing {} {}", "test", "debug"); log.info("testing {} {}", "test", "info"); log.warn("testing {} {}", "test", "warn"); - log.setLevel(Level.INFO); + log.setLevel(JettyLevel.INFO); log.debug("YOU SHOULD NOT SEE THIS!"); output.assertContains("DEBUG:xxx:tname: testing test debug"); @@ -177,7 +177,7 @@ public class JettyLoggerTest appender.setStream(output); JettyLogger log = factory.getJettyLogger(JettyLoggerTest.class.getName()); - log.setLevel(Level.DEBUG); + log.setLevel(JettyLevel.DEBUG); String nullMsg = null; try (StacklessLogging ignored = new StacklessLogging(log)) @@ -234,11 +234,11 @@ public class JettyLoggerTest log.warn("See Me"); // Set to debug level - log.setLevel(Level.DEBUG); + log.setLevel(JettyLevel.DEBUG); log.warn("Hear Me"); // Set to warn level - log.setLevel(Level.WARN); + log.setLevel(JettyLevel.WARN); log.warn("Cheer Me"); log.warn("", new Throwable("out of focus")); @@ -279,18 +279,18 @@ public class JettyLoggerTest log.info("I will not buy"); // Level Debug - log.setLevel(Level.DEBUG); + log.setLevel(JettyLevel.DEBUG); log.info("this record"); // Level All - log.setLevel(Level.TRACE); + log.setLevel(JettyLevel.TRACE); log.info("it is scratched."); log.info("", new Throwable("out of focus")); log.info("shot issue", new Throwable("scene lost")); // Level Warn - log.setLevel(Level.WARN); + log.setLevel(JettyLevel.WARN); log.info("sorry?"); log.info("", new Throwable("on editing room floor")); @@ -326,7 +326,7 @@ public class JettyLoggerTest JettyLogger log = factory.getJettyLogger(JettyLoggerTest.class.getName()); try (StacklessLogging ignored = new StacklessLogging(log)) { - log.setLevel(Level.ERROR); + log.setLevel(JettyLevel.ERROR); // Various logging events log.debug("Squelch"); @@ -359,7 +359,7 @@ public class JettyLoggerTest try (StacklessLogging ignored = new StacklessLogging(log)) { - log.setLevel(JettyLogger.OFF); + log.setLevel(JettyLevel.OFF); // Various logging events log.debug("Squelch"); @@ -399,18 +399,18 @@ public class JettyLoggerTest log.debug("", new Throwable("on editing room floor")); // Level Debug - log.setLevel(Level.DEBUG); + log.setLevel(JettyLevel.DEBUG); log.debug("my hovercraft is"); log.debug("", new Throwable("out of focus")); log.debug("shot issue", new Throwable("scene lost")); // Level All - log.setLevel(Level.TRACE); + log.setLevel(JettyLevel.TRACE); log.debug("full of eels."); // Level Warn - log.setLevel(Level.WARN); + log.setLevel(JettyLevel.WARN); log.debug("what?"); // Validate Output @@ -444,22 +444,22 @@ public class JettyLoggerTest try (StacklessLogging ignored = new StacklessLogging(log)) { - log.setLevel(Level.TRACE); + log.setLevel(JettyLevel.TRACE); assertThat("log.level(trace).isDebugEnabled", log.isDebugEnabled(), is(true)); - log.setLevel(Level.DEBUG); + log.setLevel(JettyLevel.DEBUG); assertThat("log.level(debug).isDebugEnabled", log.isDebugEnabled(), is(true)); - log.setLevel(Level.INFO); + log.setLevel(JettyLevel.INFO); assertThat("log.level(info).isDebugEnabled", log.isDebugEnabled(), is(false)); - log.setLevel(Level.WARN); + log.setLevel(JettyLevel.WARN); assertThat("log.level(warn).isDebugEnabled", log.isDebugEnabled(), is(false)); - log.setLevel(Level.ERROR); + log.setLevel(JettyLevel.ERROR); assertThat("log.level(error).isDebugEnabled", log.isDebugEnabled(), is(false)); - log.setLevel(JettyLogger.OFF); + log.setLevel(JettyLevel.OFF); assertThat("log.level(null).isDebugEnabled", log.isDebugEnabled(), is(false)); } } @@ -478,23 +478,23 @@ public class JettyLoggerTest try (StacklessLogging ignored = new StacklessLogging(log)) { - log.setLevel(Level.TRACE); - assertThat("log.level(trace).getLevel()", log.getLevel(), is(Level.TRACE.toInt())); + log.setLevel(JettyLevel.TRACE); + assertThat("log.level(trace).getLevel()", log.getLevel(), is(JettyLevel.TRACE)); - log.setLevel(Level.DEBUG); - assertThat("log.level(debug).getLevel()", log.getLevel(), is(Level.DEBUG.toInt())); + log.setLevel(JettyLevel.DEBUG); + assertThat("log.level(debug).getLevel()", log.getLevel(), is(JettyLevel.DEBUG)); - log.setLevel(Level.INFO); - assertThat("log.level(info).getLevel()", log.getLevel(), is(Level.INFO.toInt())); + log.setLevel(JettyLevel.INFO); + assertThat("log.level(info).getLevel()", log.getLevel(), is(JettyLevel.INFO)); - log.setLevel(Level.WARN); - assertThat("log.level(warn).getLevel()", log.getLevel(), is(Level.WARN.toInt())); + log.setLevel(JettyLevel.WARN); + assertThat("log.level(warn).getLevel()", log.getLevel(), is(JettyLevel.WARN)); - log.setLevel(Level.ERROR); - assertThat("log.level(error).getLevel()", log.getLevel(), is(Level.ERROR.toInt())); + log.setLevel(JettyLevel.ERROR); + assertThat("log.level(error).getLevel()", log.getLevel(), is(JettyLevel.ERROR)); - log.setLevel(888); - assertThat("log.level(888).getLevel()", log.getLevel(), is(888)); + log.setLevel(JettyLevel.OFF); + assertThat("log.level(off).getLevel()", log.getLevel(), is(JettyLevel.OFF)); } } @@ -510,23 +510,23 @@ public class JettyLoggerTest JettyLogger log = factory.getJettyLogger("xxx"); - log.setLevel(Level.TRACE); + log.setLevel(JettyLevel.TRACE); assertThat("Logger.toString", log.toString(), is("JettyLogger:xxx:LEVEL=TRACE")); - log.setLevel(Level.DEBUG); + log.setLevel(JettyLevel.DEBUG); assertThat("Logger.toString", log.toString(), is("JettyLogger:xxx:LEVEL=DEBUG")); - log.setLevel(Level.INFO); + log.setLevel(JettyLevel.INFO); assertThat("Logger.toString", log.toString(), is("JettyLogger:xxx:LEVEL=INFO")); - log.setLevel(Level.WARN); + log.setLevel(JettyLevel.WARN); assertThat("Logger.toString", log.toString(), is("JettyLogger:xxx:LEVEL=WARN")); - log.setLevel(Level.ERROR); + log.setLevel(JettyLevel.ERROR); assertThat("Logger.toString", log.toString(), is("JettyLogger:xxx:LEVEL=ERROR")); - log.setLevel(JettyLogger.OFF); - assertThat("Logger.toString", log.toString(), is("JettyLogger:xxx:LEVEL=ERROR")); + log.setLevel(JettyLevel.OFF); + assertThat("Logger.toString", log.toString(), is("JettyLogger:xxx:LEVEL=OFF")); } @Test @@ -544,25 +544,25 @@ public class JettyLoggerTest appender.setStream(output); JettyLogger root = factory.getJettyLogger(""); - assertLevel(root, Level.INFO); // default + assertLevel(root, JettyLevel.INFO); // default JettyLogger log = factory.getJettyLogger("org.eclipse.jetty.util.Foo"); assertThat("Log.isDebugEnabled()", log.isDebugEnabled(), is(false)); - assertLevel(log, Level.WARN); // as configured + assertLevel(log, JettyLevel.WARN); // as configured // Boot stomp it all to debug - root.setLevel(Level.DEBUG); + root.setLevel(JettyLevel.DEBUG); assertThat("Log.isDebugEnabled()", log.isDebugEnabled(), is(true)); - assertLevel(log, Level.DEBUG); // as stomped + assertLevel(log, JettyLevel.DEBUG); // as stomped // Restore configured factory.walkChildrenLoggers(root.getName(), (logger) -> { - int configuredLevel = config.getLevel(logger.getName()); + JettyLevel configuredLevel = config.getLevel(logger.getName()); logger.setLevel(configuredLevel); }); assertThat("Log.isDebugEnabled()", log.isDebugEnabled(), is(false)); - assertLevel(log, Level.WARN); // as configured + assertLevel(log, JettyLevel.WARN); // as configured } @Test @@ -606,9 +606,9 @@ public class JettyLoggerTest output.assertContains("\t|\t|java.lang.Exception: branch0"); } - private void assertLevel(JettyLogger log, Level expectedLevel) + private void assertLevel(JettyLogger log, JettyLevel expectedLevel) { assertThat("Log[" + log.getName() + "].level", - LevelUtils.intToLevel(log.getLevel()), is(expectedLevel)); + log.getLevel(), is(expectedLevel)); } } diff --git a/jetty-xml/src/test/java/org/eclipse/jetty/xml/XmlConfigurationTest.java b/jetty-xml/src/test/java/org/eclipse/jetty/xml/XmlConfigurationTest.java index 8838a0797dd..823aeba8b8d 100644 --- a/jetty-xml/src/test/java/org/eclipse/jetty/xml/XmlConfigurationTest.java +++ b/jetty-xml/src/test/java/org/eclipse/jetty/xml/XmlConfigurationTest.java @@ -36,6 +36,7 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; +import org.eclipse.jetty.logging.JettyLevel; import org.eclipse.jetty.logging.JettyLogger; import org.eclipse.jetty.logging.StdErrAppender; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; @@ -1595,7 +1596,7 @@ public class XmlConfigurationTest JettyLogger jettyLogger = (JettyLogger)slf4jLogger; StdErrAppender appender = (StdErrAppender)jettyLogger.getAppender(); PrintStream oldStream = appender.getStream(); - int oldLevel = jettyLogger.getLevel(); + JettyLevel oldLevel = jettyLogger.getLevel(); try { // capture events From 1c2c3892f17c12db2a59411b467d803303a7e9f7 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Fri, 8 May 2020 12:42:57 -0500 Subject: [PATCH 06/10] Issue #4830 - Ensuring we have Logger ROOT configuration ability Signed-off-by: Joakim Erdfelt --- .../jetty/logging/JettyLoggerConfigurationTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JettyLoggerConfigurationTest.java b/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JettyLoggerConfigurationTest.java index 14def8a813c..cdbdd5ebede 100644 --- a/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JettyLoggerConfigurationTest.java +++ b/jetty-slf4j-impl/src/test/java/org/eclipse/jetty/logging/JettyLoggerConfigurationTest.java @@ -162,7 +162,7 @@ public class JettyLoggerConfigurationTest public void testGetLoggingLevelBad() { Properties props = new Properties(); - props.setProperty("log.LEVEL", "WARN"); + props.setProperty("ROOT.LEVEL", "WARN"); props.setProperty("org.eclipse.jetty.bad.LEVEL", "EXPECTED_BAD_LEVEL"); JettyLoggerConfiguration config = new JettyLoggerConfiguration(props); @@ -174,7 +174,7 @@ public class JettyLoggerConfigurationTest public void testGetLoggingLevelLowercase() { Properties props = new Properties(); - props.setProperty("log.LEVEL", "warn"); + props.setProperty("ROOT.LEVEL", "warn"); props.setProperty("org.eclipse.jetty.util.LEVEL", "info"); JettyLoggerConfiguration config = new JettyLoggerConfiguration(props); @@ -188,7 +188,7 @@ public class JettyLoggerConfigurationTest public void testGetLoggingLevelRoot() { Properties props = new Properties(); - props.setProperty("log.LEVEL", "DEBUG"); + props.setProperty("ROOT.LEVEL", "DEBUG"); JettyLoggerConfiguration config = new JettyLoggerConfiguration(props); // Default Levels @@ -240,7 +240,7 @@ public class JettyLoggerConfigurationTest public void testGetLoggingLevelMixedLevels() { Properties props = new Properties(); - props.setProperty("log.LEVEL", "DEBUG"); + props.setProperty("ROOT.LEVEL", "DEBUG"); props.setProperty("org.eclipse.jetty.util.LEVEL", "WARN"); props.setProperty("org.eclipse.jetty.util.ConcurrentHashMap.LEVEL", "ALL"); From 69e1d119fe3b26e8371d98b1419a987d802c96db Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Fri, 8 May 2020 12:48:46 -0500 Subject: [PATCH 07/10] Issue #4830 - Improved notification of configuration mistakes on level names Signed-off-by: Joakim Erdfelt --- .../logging/JettyLoggerConfiguration.java | 21 ++++++++++++++++--- .../jetty/logging/JettyLoggerFactory.java | 6 +----- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerConfiguration.java b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerConfiguration.java index 4096ab4f70e..2f4662aeb34 100644 --- a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerConfiguration.java +++ b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerConfiguration.java @@ -26,6 +26,8 @@ import java.security.PrivilegedAction; import java.util.Locale; import java.util.Properties; import java.util.TimeZone; +import java.util.stream.Collectors; +import java.util.stream.Stream; /** * JettyLogger specific configuration: @@ -115,26 +117,39 @@ public class JettyLoggerConfiguration JettyLevel level = JettyLoggerFactory.walkParentLoggerNames(startName, key -> { String levelStr = properties.getProperty(key + SUFFIX_LEVEL); - return JettyLevel.strToLevel(levelStr); + return toJettyLevel(key, levelStr); }); if (level == null) { // Try slf4j root logging config. String levelStr = properties.getProperty(JettyLogger.ROOT_LOGGER_NAME + SUFFIX_LEVEL); - level = JettyLevel.strToLevel(levelStr); + level = toJettyLevel(JettyLogger.ROOT_LOGGER_NAME, levelStr); } if (level == null) { // Try legacy root logging config. String levelStr = properties.getProperty("log" + SUFFIX_LEVEL); - level = JettyLevel.strToLevel(levelStr); + level = toJettyLevel("log", levelStr); } return level != null ? level : DEFAULT_LEVEL; } + protected static JettyLevel toJettyLevel(String loggerName, String levelStr) + { + if (levelStr == null) + return null; + JettyLevel level = JettyLevel.strToLevel(levelStr); + if (level == null) + { + System.err.printf("Unknown JettyLogger/Slf4J Level [%s]=[%s], expecting only [%s] as values.", + loggerName, levelStr, Stream.of(JettyLevel.values()).map(JettyLevel::toString).collect(Collectors.joining(", "))); + } + return level; + } + public TimeZone getTimeZone(String key) { String zoneIdStr = properties.getProperty(key); diff --git a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactory.java b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactory.java index fd97bd771b5..389a25dbfd3 100644 --- a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactory.java +++ b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactory.java @@ -24,8 +24,6 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.function.Consumer; import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; import org.slf4j.ILoggerFactory; import org.slf4j.Logger; @@ -164,11 +162,9 @@ public class JettyLoggerFactory implements ILoggerFactory, JettyLoggerFactoryMBe @Override public boolean setLoggerLevel(String loggerName, String levelName) { - JettyLevel level = JettyLevel.strToLevel(levelName); + JettyLevel level = JettyLoggerConfiguration.toJettyLevel(loggerName, levelName); if (level == null) { - System.err.printf("Unknown JettyLogger/Slf4J Level [%s]=[%s], expecting only [%s] as values.", - loggerName, levelName, Stream.of(JettyLevel.values()).map(JettyLevel::toString).collect(Collectors.joining(", "))); return false; } JettyLogger jettyLogger = getJettyLogger(loggerName); From d6d994db5c7a82c03b47270d62681d25dd841ede Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Fri, 8 May 2020 22:03:03 +0200 Subject: [PATCH 08/10] Issue #4830 - Add JMX to new Jetty 10 jetty-slf4j-impl. Updates after review. Signed-off-by: Simone Bordet --- .../eclipse/jetty/logging/JettyLogger.java | 227 +++++++++--------- .../logging/JettyLoggerConfiguration.java | 2 +- .../jetty/logging/JettyLoggerFactory.java | 2 +- .../jetty/xml/XmlConfigurationTest.java | 3 +- 4 files changed, 114 insertions(+), 120 deletions(-) diff --git a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLogger.java b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLogger.java index 7367a215911..08c65e7a7a0 100644 --- a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLogger.java +++ b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLogger.java @@ -109,6 +109,48 @@ public class JettyLogger implements LocationAwareLogger, Logger return dense.toString(); } + public JettyAppender getAppender() + { + return appender; + } + + String getCondensedName() + { + return condensedName; + } + + public JettyLevel getLevel() + { + return level; + } + + public void setLevel(JettyLevel level) + { + this.level = level; + + // apply setLevel to children too. + factory.walkChildrenLoggers(this.getName(), (logger) -> logger.setLevel(level)); + } + + @Override + public String getName() + { + return name; + } + + public boolean isHideStacks() + { + return hideStacks; + } + + public void setHideStacks(boolean hideStacks) + { + this.hideStacks = hideStacks; + + // apply setHideStacks to children too. + factory.walkChildrenLoggers(this.getName(), (logger) -> logger.setHideStacks(hideStacks)); + } + @Override public void debug(String msg) { @@ -154,12 +196,6 @@ public class JettyLogger implements LocationAwareLogger, Logger } } - @Override - public boolean isDebugEnabled(Marker marker) - { - return isDebugEnabled(); - } - @Override public void debug(Marker marker, String msg) { @@ -195,6 +231,18 @@ public class JettyLogger implements LocationAwareLogger, Logger debug(msg, t); } + @Override + public boolean isDebugEnabled() + { + return level.includes(JettyLevel.DEBUG); + } + + @Override + public boolean isDebugEnabled(Marker marker) + { + return isDebugEnabled(); + } + @Override public void error(String msg) { @@ -240,12 +288,6 @@ public class JettyLogger implements LocationAwareLogger, Logger } } - @Override - public boolean isErrorEnabled(Marker marker) - { - return isErrorEnabled(); - } - @Override public void error(Marker marker, String msg) { @@ -281,65 +323,16 @@ public class JettyLogger implements LocationAwareLogger, Logger error(msg, t); } - public JettyAppender getAppender() - { - return appender; - } - - /** - * Entry point for {@link LocationAwareLogger} - */ @Override - public void log(Marker marker, String fqcn, int levelInt, String message, Object[] argArray, Throwable throwable) + public boolean isErrorEnabled() { - if (this.level.toInt() <= levelInt) - { - long timestamp = System.currentTimeMillis(); - String threadName = Thread.currentThread().getName(); - getAppender().emit(this, JettyLevel.intToLevel(levelInt).toLevel(), timestamp, threadName, throwable, message, argArray); - } - } - - /** - * Dynamic (via Reflection) entry point for {@link SubstituteLogger} usage. - * - * @param event the logging event - */ - @SuppressWarnings("unused") - public void log(LoggingEvent event) - { - // TODO: do we want to support org.sfl4j.Marker? - // TODO: do we want to support org.sfl4j.even.KeyValuePair? - getAppender().emit(this, event.getLevel(), event.getTimeStamp(), event.getThreadName(), event.getThrowable(), event.getMessage(), event.getArgumentArray()); - } - - public String getCondensedName() - { - return condensedName; - } - - public JettyLevel getLevel() - { - return level; - } - - public void setLevel(Level level) - { - setLevel(JettyLevel.fromLevel(level)); - } - - public void setLevel(JettyLevel level) - { - this.level = level; - - // apply setLevel to children too. - factory.walkChildrenLoggers(this.getName(), (logger) -> logger.setLevel(level)); + return level.includes(JettyLevel.ERROR); } @Override - public String getName() + public boolean isErrorEnabled(Marker marker) { - return name; + return isErrorEnabled(); } @Override @@ -387,12 +380,6 @@ public class JettyLogger implements LocationAwareLogger, Logger } } - @Override - public boolean isInfoEnabled(Marker marker) - { - return isInfoEnabled(); - } - @Override public void info(Marker marker, String msg) { @@ -428,31 +415,6 @@ public class JettyLogger implements LocationAwareLogger, Logger info(msg, t); } - @Override - public boolean isDebugEnabled() - { - return level.includes(JettyLevel.DEBUG); - } - - @Override - public boolean isErrorEnabled() - { - return level.includes(JettyLevel.ERROR); - } - - public boolean isHideStacks() - { - return hideStacks; - } - - public void setHideStacks(boolean hideStacks) - { - this.hideStacks = hideStacks; - - // apply setHideStacks to children too. - factory.walkChildrenLoggers(this.getName(), (logger) -> logger.setHideStacks(hideStacks)); - } - @Override public boolean isInfoEnabled() { @@ -460,15 +422,9 @@ public class JettyLogger implements LocationAwareLogger, Logger } @Override - public boolean isTraceEnabled() + public boolean isInfoEnabled(Marker marker) { - return level.includes(JettyLevel.TRACE); - } - - @Override - public boolean isWarnEnabled() - { - return level.includes(JettyLevel.WARN); + return isInfoEnabled(); } @Override @@ -516,12 +472,6 @@ public class JettyLogger implements LocationAwareLogger, Logger } } - @Override - public boolean isTraceEnabled(Marker marker) - { - return isTraceEnabled(); - } - @Override public void trace(Marker marker, String msg) { @@ -557,6 +507,18 @@ public class JettyLogger implements LocationAwareLogger, Logger trace(msg, t); } + @Override + public boolean isTraceEnabled() + { + return level.includes(JettyLevel.TRACE); + } + + @Override + public boolean isTraceEnabled(Marker marker) + { + return isTraceEnabled(); + } + @Override public void warn(String msg) { @@ -602,12 +564,6 @@ public class JettyLogger implements LocationAwareLogger, Logger } } - @Override - public boolean isWarnEnabled(Marker marker) - { - return isWarnEnabled(); - } - @Override public void warn(Marker marker, String msg) { @@ -643,6 +599,18 @@ public class JettyLogger implements LocationAwareLogger, Logger warn(msg, t); } + @Override + public boolean isWarnEnabled() + { + return level.includes(JettyLevel.WARN); + } + + @Override + public boolean isWarnEnabled(Marker marker) + { + return isWarnEnabled(); + } + private void emit(Level level, String msg) { long timestamp = System.currentTimeMillis(); @@ -684,6 +652,33 @@ public class JettyLogger implements LocationAwareLogger, Logger getAppender().emit(this, level, timestamp, threadName, throwable, msg); } + /** + * Entry point for {@link LocationAwareLogger} + */ + @Override + public void log(Marker marker, String fqcn, int levelInt, String message, Object[] argArray, Throwable throwable) + { + if (this.level.toInt() <= levelInt) + { + long timestamp = System.currentTimeMillis(); + String threadName = Thread.currentThread().getName(); + getAppender().emit(this, JettyLevel.intToLevel(levelInt).toLevel(), timestamp, threadName, throwable, message, argArray); + } + } + + /** + * Dynamic (via Reflection) entry point for {@link SubstituteLogger} usage. + * + * @param event the logging event + */ + @SuppressWarnings("unused") + public void log(LoggingEvent event) + { + // TODO: do we want to support org.sfl4j.Marker? + // TODO: do we want to support org.sfl4j.even.KeyValuePair? + getAppender().emit(this, event.getLevel(), event.getTimeStamp(), event.getThreadName(), event.getThrowable(), event.getMessage(), event.getArgumentArray()); + } + @Override public String toString() { diff --git a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerConfiguration.java b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerConfiguration.java index 2f4662aeb34..1f9f28b985d 100644 --- a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerConfiguration.java +++ b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerConfiguration.java @@ -145,7 +145,7 @@ public class JettyLoggerConfiguration if (level == null) { System.err.printf("Unknown JettyLogger/Slf4J Level [%s]=[%s], expecting only [%s] as values.", - loggerName, levelStr, Stream.of(JettyLevel.values()).map(JettyLevel::toString).collect(Collectors.joining(", "))); + loggerName, levelStr, Stream.of(JettyLevel.values()).map(JettyLevel::name).collect(Collectors.joining(", "))); } return level; } diff --git a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactory.java b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactory.java index 389a25dbfd3..aa0bda76539 100644 --- a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactory.java +++ b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerFactory.java @@ -154,7 +154,7 @@ public class JettyLoggerFactory implements ILoggerFactory, JettyLoggerFactoryMBe { JettyLogger logger = loggerMap.get(key); if (logger != null) - return logger.getLevel().toString(); + return logger.getLevel().name(); return null; }); } diff --git a/jetty-xml/src/test/java/org/eclipse/jetty/xml/XmlConfigurationTest.java b/jetty-xml/src/test/java/org/eclipse/jetty/xml/XmlConfigurationTest.java index 823aeba8b8d..6cd7e3fb95a 100644 --- a/jetty-xml/src/test/java/org/eclipse/jetty/xml/XmlConfigurationTest.java +++ b/jetty-xml/src/test/java/org/eclipse/jetty/xml/XmlConfigurationTest.java @@ -55,7 +55,6 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.slf4j.event.Level; import org.xml.sax.SAXException; import static java.nio.charset.StandardCharsets.UTF_8; @@ -1602,7 +1601,7 @@ public class XmlConfigurationTest // capture events appender.setStream(new PrintStream(logBytes, true)); // make sure we are seeing WARN level events - jettyLogger.setLevel(Level.WARN); + jettyLogger.setLevel(JettyLevel.WARN); action.run(); } From 41f6e3df5127c3ac01efa8202b3465b2cfa0be88 Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Fri, 8 May 2020 22:16:24 +0200 Subject: [PATCH 09/10] Issue #4830 - Add JMX to new Jetty 10 jetty-slf4j-impl. Updates after review, take 2. Signed-off-by: Simone Bordet --- .../eclipse/jetty/logging/JettyLoggerConfiguration.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerConfiguration.java b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerConfiguration.java index 1f9f28b985d..27097b2bd2f 100644 --- a/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerConfiguration.java +++ b/jetty-slf4j-impl/src/main/java/org/eclipse/jetty/logging/JettyLoggerConfiguration.java @@ -23,11 +23,10 @@ import java.io.InputStream; import java.net.URL; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.Arrays; import java.util.Locale; import java.util.Properties; import java.util.TimeZone; -import java.util.stream.Collectors; -import java.util.stream.Stream; /** * JettyLogger specific configuration: @@ -137,15 +136,15 @@ public class JettyLoggerConfiguration return level != null ? level : DEFAULT_LEVEL; } - protected static JettyLevel toJettyLevel(String loggerName, String levelStr) + static JettyLevel toJettyLevel(String loggerName, String levelStr) { if (levelStr == null) return null; JettyLevel level = JettyLevel.strToLevel(levelStr); if (level == null) { - System.err.printf("Unknown JettyLogger/Slf4J Level [%s]=[%s], expecting only [%s] as values.", - loggerName, levelStr, Stream.of(JettyLevel.values()).map(JettyLevel::name).collect(Collectors.joining(", "))); + System.err.printf("Unknown JettyLogger/SLF4J Level [%s]=[%s], expecting only %s as values.%n", + loggerName, levelStr, Arrays.toString(JettyLevel.values())); } return level; } From 3215e11b3fe118652f181f6e4df2fb2c43aba7de Mon Sep 17 00:00:00 2001 From: Olivier Lamy Date: Tue, 19 May 2020 16:28:53 +1000 Subject: [PATCH 10/10] Issue #4887 update documentation org.apache.aries.spifly.dynamic.bundle version 1.2.4 --- .../src/main/asciidoc/development/frameworks/osgi.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jetty-documentation/src/main/asciidoc/development/frameworks/osgi.adoc b/jetty-documentation/src/main/asciidoc/development/frameworks/osgi.adoc index 9f72bf7398c..e7059fdef4e 100644 --- a/jetty-documentation/src/main/asciidoc/development/frameworks/osgi.adoc +++ b/jetty-documentation/src/main/asciidoc/development/frameworks/osgi.adoc @@ -55,7 +55,7 @@ You *must also install the Apache Aries SPI Fly bundles* as many parts of Jetty [cols=",,",options="header",] |======================================================================= |Jar |Bundle Symbolic Name |Location -|org.apache.aries.spifly:org.apache.aries.spifly.dynamic.bundle-1.2.jar |org.apache.aries.spifly.dynamic.bundle +|org.apache.aries.spifly:org.apache.aries.spifly.dynamic.bundle-1.2.4.jar |org.apache.aries.spifly.dynamic.bundle |https://repo1.maven.org/maven2/org/apache/aries/spifly/org.apache.aries.spifly.dynamic.bundle/[Maven central] |=======================================================================