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 that are 042 * more specific to pass through the filter. A special level, {@link #ALL}, is guaranteed to capture all levels when 043 * used in logging configurations. 044 */ 045public final class Level implements Comparable<Level>, Serializable { 046 047 /** 048 * No events will be logged. 049 */ 050 public static final Level OFF; 051 052 /** 053 * A severe error that will prevent the application from continuing. 054 */ 055 public static final Level FATAL; 056 057 /** 058 * An error in the application, possibly recoverable. 059 */ 060 public static final Level ERROR; 061 062 /** 063 * An event that might possible lead to an error. 064 */ 065 public static final Level WARN; 066 067 /** 068 * An event for informational purposes. 069 */ 070 public static final Level INFO; 071 072 /** 073 * A general debugging event. 074 */ 075 public static final Level DEBUG; 076 077 /** 078 * A fine-grained debug message, typically capturing the flow through the application. 079 */ 080 public static final Level TRACE; 081 082 /** 083 * All events should be logged. 084 */ 085 public static final Level ALL; 086 087 /** 088 * @since 2.1 089 */ 090 public static final String CATEGORY = "Level"; 091 092 private static final ConcurrentMap<String, Level> LEVELS = new ConcurrentHashMap<>(); // SUPPRESS CHECKSTYLE 093 094 private static final long serialVersionUID = 1581082L; 095 096 static { 097 OFF = new Level("OFF", StandardLevel.OFF.intLevel()); 098 FATAL = new Level("FATAL", StandardLevel.FATAL.intLevel()); 099 ERROR = new Level("ERROR", StandardLevel.ERROR.intLevel()); 100 WARN = new Level("WARN", StandardLevel.WARN.intLevel()); 101 INFO = new Level("INFO", StandardLevel.INFO.intLevel()); 102 DEBUG = new Level("DEBUG", StandardLevel.DEBUG.intLevel()); 103 TRACE = new Level("TRACE", StandardLevel.TRACE.intLevel()); 104 ALL = new Level("ALL", StandardLevel.ALL.intLevel()); 105 } 106 107 private final String name; 108 private final int intLevel; 109 private final StandardLevel standardLevel; 110 111 private Level(final String name, final int intLevel) { 112 if (name == null || name.isEmpty()) { 113 throw new IllegalArgumentException("Illegal null Level constant"); 114 } 115 if (intLevel < 0) { 116 throw new IllegalArgumentException("Illegal Level int less than zero."); 117 } 118 this.name = name; 119 this.intLevel = intLevel; 120 this.standardLevel = StandardLevel.getStandardLevel(intLevel); 121 if (LEVELS.putIfAbsent(name, this) != null) { 122 throw new IllegalStateException("Level " + name + " has already been defined."); 123 } 124 } 125 126 /** 127 * Gets the integral value of this Level. 128 * 129 * @return the value of this Level. 130 */ 131 public int intLevel() { 132 return this.intLevel; 133 } 134 135 /** 136 * Gets the standard Level values as an enum. 137 * 138 * @return an enum of the standard Levels. 139 */ 140 public StandardLevel getStandardLevel() { 141 return standardLevel; 142 } 143 144 /** 145 * Compares this level against the levels passed as arguments and returns true if this level is in between the given 146 * levels. 147 * 148 * @param minLevel The minimum level to test. 149 * @param maxLevel 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. 160 * 161 * @param level The level to test. 162 * @return True if this level Level is less specific or the same as the given Level. 163 */ 164 public boolean isLessSpecificThan(final Level level) { 165 return this.intLevel >= level.intLevel; 166 } 167 168 /** 169 * Compares this level against the level passed as an argument and returns true if this level is the same or is more 170 * specific. 171 * 172 * @param level The level to test. 173 * @return True if this level Level is more specific or the same as the given Level. 174 */ 175 public boolean isMoreSpecificThan(final Level level) { 176 return this.intLevel <= level.intLevel; 177 } 178 179 @Override 180 @SuppressWarnings("CloneDoesntCallSuperClone") 181 // CHECKSTYLE:OFF 182 public Level clone() throws CloneNotSupportedException { 183 throw new CloneNotSupportedException(); 184 } 185 // CHECKSTYLE:ON 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 * 223 * @param name The name of the level. 224 * @param intValue The integer value for the Level. If the level was previously created this value is ignored. 225 * @return The Level. 226 * @throws java.lang.IllegalArgumentException if the name is null or intValue is less than zero. 227 */ 228 public static Level forName(final String name, final int intValue) { 229 final Level level = LEVELS.get(name); 230 if (level != null) { 231 return level; 232 } 233 try { 234 return new Level(name, intValue); 235 } catch (final IllegalStateException ex) { 236 // The level was added by something else so just return that one. 237 return LEVELS.get(name); 238 } 239 } 240 241 /** 242 * Return the Level associated with the name or null if the Level cannot be found. 243 * 244 * @param name The name of the Level. 245 * @return The Level or null. 246 */ 247 public static Level getLevel(final String name) { 248 return LEVELS.get(name); 249 } 250 251 /** 252 * Converts the string passed as argument to a level. If the conversion fails, then this method returns 253 * {@link #DEBUG}. 254 * 255 * @param sArg The name of the desired Level. 256 * @return The Level associated with the String. 257 */ 258 public static Level toLevel(final String sArg) { 259 return toLevel(sArg, Level.DEBUG); 260 } 261 262 /** 263 * Converts the string passed as argument to a level. If the conversion fails, then this method returns the value of 264 * <code>defaultLevel</code>. 265 * 266 * @param name The name of the desired Level. 267 * @param defaultLevel The Level to use if the String is invalid. 268 * @return The Level associated with the String. 269 */ 270 public static Level toLevel(final String name, final Level defaultLevel) { 271 if (name == null) { 272 return defaultLevel; 273 } 274 final Level level = LEVELS.get(name.toUpperCase(Locale.ENGLISH)); 275 return level == null ? defaultLevel : level; 276 } 277 278 /** 279 * Return an array of all the Levels that have been registered. 280 * 281 * @return An array of Levels. 282 */ 283 public static Level[] values() { 284 final Collection<Level> values = Level.LEVELS.values(); 285 return values.toArray(new Level[values.size()]); 286 } 287 288 /** 289 * Return the Level associated with the name. 290 * 291 * @param name The name of the Level to return. 292 * @return The Level. 293 * @throws java.lang.NullPointerException if the Level name is {@code null}. 294 * @throws java.lang.IllegalArgumentException if the Level name is not registered. 295 */ 296 public static Level valueOf(final String name) { 297 Objects.requireNonNull(name, "No level name given."); 298 final String levelName = name.toUpperCase(Locale.ENGLISH); 299 final Level level = LEVELS.get(levelName); 300 if (level != null) { 301 return level; 302 } 303 throw new IllegalArgumentException("Unknown level constant [" + levelName + "]."); 304 } 305 306 /** 307 * Returns the enum constant of the specified enum type with the specified name. The name must match exactly an 308 * identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.) 309 * 310 * @param enumType the {@code Class} object of the enum type from which to return a constant 311 * @param name the name of the constant to return 312 * @param <T> The enum type whose constant is to be returned 313 * @return the enum constant of the specified enum type with the specified name 314 * @throws java.lang.IllegalArgumentException if the specified enum type has no constant with the specified name, or 315 * the specified class object does not represent an enum type 316 * @throws java.lang.NullPointerException if {@code enumType} or {@code name} are {@code null} 317 * @see java.lang.Enum#valueOf(Class, String) 318 */ 319 public static <T extends Enum<T>> T valueOf(final Class<T> enumType, final String name) { 320 return Enum.valueOf(enumType, name); 321 } 322 323 // for deserialization 324 protected Object readResolve() { 325 return Level.valueOf(this.name); 326 } 327}