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