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)</li> 031 * <li>{@link #FATAL}</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}</li> 037 * <li>{@link #ALL} (least specific)</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 = 3077535362528045615L; 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 private final String name; 101 private final int intLevel; 102 private final StandardLevel standardLevel; 103 104 private Level(String name, int intLevel) { 105 if (name == null || name.length() == 0) { 106 throw new IllegalArgumentException("Illegal null Level constant"); 107 } 108 if (intLevel < 0) { 109 throw new IllegalArgumentException("Illegal Level int less than zero."); 110 } 111 this.name = name; 112 this.intLevel = intLevel; 113 this.standardLevel = StandardLevel.getStandardLevel(intLevel); 114 if (levels.putIfAbsent(name, this) != null) { 115 throw new IllegalStateException("Level " + name + " has already been defined."); 116 } 117 } 118 119 public int intLevel() { 120 return this.intLevel; 121 } 122 123 public StandardLevel getStandardLevel() { 124 return standardLevel; 125 } 126 127 /** 128 * Compares this level against the level passed as an argument and returns true if this 129 * level is the same or more specific. 130 * 131 * @param level The level to check. 132 * @return True if the passed Level is more specific or the same as this Level. 133 */ 134 public boolean isAtLeastAsSpecificAs(final Level level) { 135 return this.intLevel <= level.intLevel; 136 } 137 138 /** 139 * Compares this level against the level passed as an argument and returns true if this 140 * level is the same or more specific. 141 * 142 * @param level The level to check. 143 * @return True if the passed Level is more specific or the same as this Level. 144 */ 145 public boolean isAtLeastAsSpecificAs(final int level) { 146 return this.intLevel <= level; 147 } 148 149 /** 150 * Compares the specified Level against this one. 151 * @param level The level to check. 152 * @return True if the passed Level is more specific or the same as this Level. 153 */ 154 public boolean lessOrEqual(final Level level) { 155 return this.intLevel <= level.intLevel; 156 } 157 158 /** 159 * Compares the specified Level against this one. 160 * @param level The level to check. 161 * @return True if the passed Level is more specific or the same as this Level. 162 */ 163 public boolean lessOrEqual(final int level) { 164 return this.intLevel <= level; 165 } 166 167 @Override 168 @SuppressWarnings("CloneDoesntCallSuperClone") 169 public Level clone() throws CloneNotSupportedException { 170 throw new CloneNotSupportedException(); 171 } 172 173 @Override 174 public int compareTo(Level other) { 175 return intLevel < other.intLevel ? -1 : (intLevel > other.intLevel ? 1 : 0); 176 } 177 178 @Override 179 public boolean equals(Object other) { 180 return other instanceof Level && other == this; 181 } 182 183 public Class<Level> getDeclaringClass() { 184 return Level.class; 185 } 186 187 @Override 188 public int hashCode() { 189 return this.name.hashCode(); 190 } 191 192 193 public String name() { 194 return this.name; 195 } 196 197 @Override 198 public String toString() { 199 return this.name; 200 } 201 202 /** 203 * Retrieves an existing Level or creates on if it didn't previously exist. 204 * @param name The name of the level. 205 * @param intValue The integer value for the Level. If the level was previously created this value is ignored. 206 * @return The Level. 207 * @throws java.lang.IllegalArgumentException if the name is null or intValue is less than zero. 208 */ 209 public static Level forName(String name, int intValue) { 210 Level level = levels.get(name); 211 if (level != null) { 212 return level; 213 } 214 try { 215 return new Level(name, intValue); 216 } catch (IllegalStateException ex) { 217 // The level was added by something else so just return that one. 218 return levels.get(name); 219 } 220 } 221 222 /** 223 * Return the Level assoicated with the name or null if the Level cannot be found. 224 * @param name The name of the Level. 225 * @return The Level or null. 226 */ 227 public static Level getLevel(String name) { 228 return levels.get(name); 229 } 230 231 /** 232 * Converts the string passed as argument to a level. If the 233 * conversion fails, then this method returns {@link #DEBUG}. 234 * 235 * @param sArg The name of the desired Level. 236 * @return The Level associated with the String. 237 */ 238 public static Level toLevel(final String sArg) { 239 return toLevel(sArg, Level.DEBUG); 240 } 241 242 /** 243 * Converts the string passed as argument to a level. If the 244 * conversion fails, then this method returns the value of 245 * <code>defaultLevel</code>. 246 * 247 * @param name The name of the desired Level. 248 * @param defaultLevel The Level to use if the String is invalid. 249 * @return The Level associated with the String. 250 */ 251 public static Level toLevel(final String name, final Level defaultLevel) { 252 if (name == null) { 253 return defaultLevel; 254 } 255 Level level = levels.get(name.toUpperCase(Locale.ENGLISH)); 256 return level == null ? defaultLevel : level; 257 } 258 259 /** 260 * Return an array of all the Levels that have been registered. 261 * @return An array of Levels. 262 */ 263 public static Level[] values() { 264 Collection<Level> values = Level.levels.values(); 265 return values.toArray(new Level[values.size()]); 266 } 267 268 /** 269 * Return the Level associated with the name. 270 * @param name The name of the Level to return. 271 * @return The Level. 272 * @throws java.lang.IllegalArgumentException if the Level name is not registered. 273 */ 274 public static Level valueOf(String name) { 275 if (name == null) { 276 throw new IllegalArgumentException("Unknown level constant [" + name + "]."); 277 } 278 name = name.toUpperCase(); 279 if (levels.containsKey(name)) { 280 return levels.get(name); 281 } 282 throw new IllegalArgumentException("Unknown level constant [" + name + "]."); 283 } 284 285 public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) { 286 return Enum.valueOf(enumType, name); 287 } 288 289 // for deserialization 290 protected Object readResolve() { 291 return Level.valueOf(this.name); 292 } 293} 294