001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache license, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the license for the specific language governing permissions and 015 * limitations under the license. 016 */ 017package org.apache.logging.log4j; 018 019import java.io.Serializable; 020import java.util.Collection; 021import java.util.Locale; 022import java.util.Objects; 023import java.util.concurrent.ConcurrentHashMap; 024import java.util.concurrent.ConcurrentMap; 025 026import org.apache.logging.log4j.spi.StandardLevel; 027 028/** 029 * Levels used for identifying the severity of an event. Levels are organized from most specific to least: 030 * <ul> 031 * <li>{@link #OFF} (most specific, no logging)</li> 032 * <li>{@link #FATAL} (most specific, little data)</li> 033 * <li>{@link #ERROR}</li> 034 * <li>{@link #WARN}</li> 035 * <li>{@link #INFO}</li> 036 * <li>{@link #DEBUG}</li> 037 * <li>{@link #TRACE} (least specific, a lot of data)</li> 038 * <li>{@link #ALL} (least specific, all data)</li> 039 * </ul> 040 * 041 * Typically, configuring a level in a filter or on a logger will cause logging events of that level and those 042 * that are more specific to pass through the filter. 043 * A special level, {@link #ALL}, is guaranteed to capture all levels when used in logging configurations. 044 */ 045public final class Level implements Comparable<Level>, Serializable { 046 047 private static final long serialVersionUID = 1581082L; 048 private static final ConcurrentMap<String, Level> levels = new ConcurrentHashMap<>(); 049 050 /** 051 * No events will be logged. 052 */ 053 public static final Level OFF; 054 055 /** 056 * A severe error that will prevent the application from continuing. 057 */ 058 public static final Level FATAL; 059 060 /** 061 * An error in the application, possibly recoverable. 062 */ 063 public static final Level ERROR; 064 065 /** 066 * An event that might possible lead to an error. 067 */ 068 public static final Level WARN; 069 070 /** 071 * An event for informational purposes. 072 */ 073 public static final Level INFO; 074 075 /** 076 * A general debugging event. 077 */ 078 public static final Level DEBUG; 079 080 /** 081 * A fine-grained debug message, typically capturing the flow through the application. 082 */ 083 public static final Level TRACE; 084 085 /** 086 * All events should be logged. 087 */ 088 public static final Level ALL; 089 090 static { 091 OFF = new Level("OFF", StandardLevel.OFF.intLevel()); 092 FATAL = new Level("FATAL", StandardLevel.FATAL.intLevel()); 093 ERROR = new Level("ERROR", StandardLevel.ERROR.intLevel()); 094 WARN = new Level("WARN", StandardLevel.WARN.intLevel()); 095 INFO = new Level("INFO", StandardLevel.INFO.intLevel()); 096 DEBUG = new Level("DEBUG", StandardLevel.DEBUG.intLevel()); 097 TRACE = new Level("TRACE", StandardLevel.TRACE.intLevel()); 098 ALL = new Level("ALL", StandardLevel.ALL.intLevel()); 099 } 100 101 /** 102 * @since 2.1 103 */ 104 public static final String CATEGORY = "Level"; 105 106 private final String name; 107 private final int intLevel; 108 private final StandardLevel standardLevel; 109 110 private Level(final String name, final int intLevel) { 111 if (name == null || name.isEmpty()) { 112 throw new IllegalArgumentException("Illegal null Level constant"); 113 } 114 if (intLevel < 0) { 115 throw new IllegalArgumentException("Illegal Level int less than zero."); 116 } 117 this.name = name; 118 this.intLevel = intLevel; 119 this.standardLevel = StandardLevel.getStandardLevel(intLevel); 120 if (levels.putIfAbsent(name, this) != null) { 121 throw new IllegalStateException("Level " + name + " has already been defined."); 122 } 123 } 124 125 /** 126 * Gets the integral value of this Level. 127 * 128 * @return the value of this Level. 129 */ 130 public int intLevel() { 131 return this.intLevel; 132 } 133 134 /** 135 * Gets the standard Level values as an enum. 136 * 137 * @return an enum of the standard Levels. 138 */ 139 public StandardLevel getStandardLevel() { 140 return standardLevel; 141 } 142 143 /** 144 * Compares this level against the levels passed as arguments and returns true if this level is in between the given levels. 145 * 146 * @param minLevel 147 * The minimum level to test. 148 * @param maxLevel 149 * The maximum level to test. 150 * @return True true if this level is in between the given levels 151 * @since 2.4 152 */ 153 public boolean isInRange(final Level minLevel, final Level maxLevel) { 154 return this.intLevel >= minLevel.intLevel && this.intLevel <= maxLevel.intLevel; 155 } 156 157 /** 158 * Compares this level against the level passed as an argument and returns true if this level is the same or is less 159 * specific.T 160 * 161 * @param level 162 * The level to test. 163 * @return True if this level Level is less specific or the same as the given Level. 164 */ 165 public boolean isLessSpecificThan(final Level level) { 166 return this.intLevel >= level.intLevel; 167 } 168 169 /** 170 * Compares this level against the level passed as an argument and returns true if this level is the same or is more 171 * specific. 172 * 173 * @param level 174 * The level to test. 175 * @return True if this level Level is more specific or the same as the given Level. 176 */ 177 public boolean isMoreSpecificThan(final Level level) { 178 return this.intLevel <= level.intLevel; 179 } 180 181 @Override 182 @SuppressWarnings("CloneDoesntCallSuperClone") 183 public Level clone() throws CloneNotSupportedException { 184 throw new CloneNotSupportedException(); 185 } 186 187 @Override 188 public int compareTo(final Level other) { 189 return intLevel < other.intLevel ? -1 : (intLevel > other.intLevel ? 1 : 0); 190 } 191 192 @Override 193 public boolean equals(final Object other) { 194 return other instanceof Level && other == this; 195 } 196 197 public Class<Level> getDeclaringClass() { 198 return Level.class; 199 } 200 201 @Override 202 public int hashCode() { 203 return this.name.hashCode(); 204 } 205 206 /** 207 * Gets the symbolic name of this Level. Equivalent to calling {@link #toString()}. 208 * 209 * @return the name of this Level. 210 */ 211 public String name() { 212 return this.name; 213 } 214 215 @Override 216 public String toString() { 217 return this.name; 218 } 219 220 /** 221 * Retrieves an existing Level or creates on if it didn't previously exist. 222 * @param name The name of the level. 223 * @param intValue The integer value for the Level. If the level was previously created this value is ignored. 224 * @return The Level. 225 * @throws java.lang.IllegalArgumentException if the name is null or intValue is less than zero. 226 */ 227 public static Level forName(final String name, final int intValue) { 228 final Level level = levels.get(name); 229 if (level != null) { 230 return level; 231 } 232 try { 233 return new Level(name, intValue); 234 } catch (final IllegalStateException ex) { 235 // The level was added by something else so just return that one. 236 return levels.get(name); 237 } 238 } 239 240 /** 241 * Return the Level associated with the name or null if the Level cannot be found. 242 * @param name The name of the Level. 243 * @return The Level or null. 244 */ 245 public static Level getLevel(final String name) { 246 return levels.get(name); 247 } 248 249 /** 250 * Converts the string passed as argument to a level. If the 251 * conversion fails, then this method returns {@link #DEBUG}. 252 * 253 * @param sArg The name of the desired Level. 254 * @return The Level associated with the String. 255 */ 256 public static Level toLevel(final String sArg) { 257 return toLevel(sArg, Level.DEBUG); 258 } 259 260 /** 261 * Converts the string passed as argument to a level. If the 262 * conversion fails, then this method returns the value of 263 * <code>defaultLevel</code>. 264 * 265 * @param name The name of the desired Level. 266 * @param defaultLevel The Level to use if the String is invalid. 267 * @return The Level associated with the String. 268 */ 269 public static Level toLevel(final String name, final Level defaultLevel) { 270 if (name == null) { 271 return defaultLevel; 272 } 273 final Level level = levels.get(name.toUpperCase(Locale.ENGLISH)); 274 return level == null ? defaultLevel : level; 275 } 276 277 /** 278 * Return an array of all the Levels that have been registered. 279 * @return An array of Levels. 280 */ 281 public static Level[] values() { 282 final Collection<Level> values = Level.levels.values(); 283 return values.toArray(new Level[values.size()]); 284 } 285 286 /** 287 * Return the Level associated with the name. 288 * @param name The name of the Level to return. 289 * @return The Level. 290 * @throws java.lang.NullPointerException if the Level name is {@code null}. 291 * @throws java.lang.IllegalArgumentException if the Level name is not registered. 292 */ 293 public static Level valueOf(final String name) { 294 Objects.requireNonNull(name, "No level name given."); 295 final String levelName = name.toUpperCase(Locale.ENGLISH); 296 final Level level = levels.get(levelName); 297 if (level != null) { 298 return level; 299 } 300 throw new IllegalArgumentException("Unknown level constant [" + levelName + "]."); 301 } 302 303 /** 304 * Returns the enum constant of the specified enum type with the specified name. The name must match exactly an 305 * identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.) 306 * 307 * @param enumType the {@code Class} object of the enum type from which to return a constant 308 * @param name the name of the constant to return 309 * @param <T> The enum type whose constant is to be returned 310 * @return the enum constant of the specified enum type with the specified name 311 * @throws java.lang.IllegalArgumentException if the specified enum type has no constant with the specified name, 312 * or the specified class object does not represent an enum type 313 * @throws java.lang.NullPointerException if {@code enumType} or {@code name} are {@code null} 314 * @see java.lang.Enum#valueOf(Class, String) 315 */ 316 public static <T extends Enum<T>> T valueOf(final Class<T> enumType, final String name) { 317 return Enum.valueOf(enumType, name); 318 } 319 320 // for deserialization 321 protected Object readResolve() { 322 return Level.valueOf(this.name); 323 } 324} 325