001/* 002 * Copyright 2023 the original author or authors. 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package de.cuioss.test.juli; 017 018import static de.cuioss.tools.string.MoreStrings.isEmpty; 019import static java.util.Objects.requireNonNull; 020 021import java.util.EnumSet; 022import java.util.logging.Level; 023import java.util.logging.Logger; 024 025import lombok.AccessLevel; 026import lombok.Getter; 027import lombok.RequiredArgsConstructor; 028 029/** 030 * Defines the log-levels with implicit mapping to JUL log level according to: 031 * <a href= 032 * "https://www.slf4j.org/apidocs/org/slf4j/bridge/SLF4JBridgeHandler.html">SLF4JBridgeHandler</a> 033 * 034 * @author Oliver Wolff 035 * 036 */ 037@RequiredArgsConstructor(access = AccessLevel.PRIVATE) 038public enum TestLogLevel { 039 040 /** Trace Level, maps to {@link Level#FINER}. */ 041 TRACE(Level.FINER), 042 /** Debug Level, maps to {@link Level#FINE}. */ 043 DEBUG(Level.FINE), 044 /** Info Level, maps to {@link Level#INFO}. */ 045 INFO(Level.INFO), 046 /** Warn Level, maps to {@link Level#WARNING}. */ 047 WARN(Level.WARNING), 048 /** Error Level, maps to {@link Level#SEVERE}. */ 049 ERROR(Level.SEVERE); 050 051 @Getter 052 private final Level juliLevel; 053 054 /** 055 * 056 * @param logger to be checked, must not be null 057 * @return {@code true} if the log-level is enabled on the logger, false 058 * otherwise 059 */ 060 boolean isEnabled(Logger logger) { 061 return logger.isLoggable(getJuliLevel()); 062 } 063 064 /** 065 * Convenient method for setting the root-logger-level in the context of the 066 * current {@link TestLogLevel} 067 * 068 * @return the {@link TestLogLevel} itself in order to us is in a fluent way 069 */ 070 public TestLogLevel setAsRootLevel() { 071 return addLogger(""); 072 } 073 074 /** 075 * Convenient method for setting a Log-Level in the context of the current 076 * {@link TestLogLevel} 077 * 078 * @param className if it is {@code null} it will set the root-logger for the 079 * actual Log-Level 080 * @return the {@link TestLogLevel} itself in order to us is in a fluent way 081 */ 082 public TestLogLevel addLogger(Class<?> className) { 083 if (null == className) { 084 return addLogger(""); 085 } 086 return addLogger(className.getName()); 087 } 088 089 /** 090 * Convenient method for setting a Log-Level in context of the current 091 * {@link TestLogLevel} 092 * 093 * @param loggerName if it is {@code null} or empty it will set the root-logger 094 * for the actual Log-Level 095 * @return the {@link TestLogLevel} itself in order to us is in a fluent way 096 */ 097 public TestLogLevel addLogger(String loggerName) { 098 TestLoggerFactory.addLogger(this, loggerName); 099 return this; 100 } 101 102 /** 103 * @param level to be parsed, must not be null 104 * @return the mapped level or {@link TestLogLevel#INFO} if the level can not be 105 * mapped 106 */ 107 public static TestLogLevel parse(Level level) { 108 requireNonNull(level); 109 for (TestLogLevel testLogLevel : TestLogLevel.values()) { 110 if (testLogLevel.juliLevel.equals(level)) { 111 return testLogLevel; 112 } 113 } 114 return TestLogLevel.INFO; 115 } 116 117 /** 118 * Factory method for deriving a {@link TestLogLevel} from a given String. 119 * 120 * @param levelAsAString The String representation of the desired 121 * {@link TestLogLevel} 122 * @param defaultLevel must not be null 123 * @return the desired {@link TestLogLevel} if levelAsAString is null or empty 124 * or is not a defined {@link TestLogLevel} the method will return the 125 * given defaultLevel 126 */ 127 static TestLogLevel getLevelOrDefault(final String levelAsAString, final TestLogLevel defaultLevel) { 128 requireNonNull(defaultLevel); 129 if (isEmpty(levelAsAString)) { 130 return defaultLevel; 131 } 132 try { 133 return TestLogLevel.valueOf(levelAsAString.toUpperCase()); 134 } catch (IllegalArgumentException e) { 135 var message = "Unable to determine logger, expected one of %s, but was %s" 136 .formatted(EnumSet.allOf(TestLogLevel.class), levelAsAString); 137 Logger.getLogger(TestLogLevel.class.getName()).log(Level.FINE, message, e); 138 return defaultLevel; 139 } 140 } 141}