// Copyright (c) 2016 Uber Technologies, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. package zapcore import ( "bytes" "errors" "fmt" ) var errUnmarshalNilLevel = errors.New("can't unmarshal a nil *Level") // A Level is a logging priority. Higher levels are more important. type Level int8 const ( // DebugLevel logs are typically voluminous, and are usually disabled in // production. DebugLevel Level = iota - 1 // InfoLevel is the default logging priority. InfoLevel // WarnLevel logs are more important than Info, but don't need individual // human review. WarnLevel // ErrorLevel logs are high-priority. If an application is running smoothly, // it shouldn't generate any error-level logs. ErrorLevel // DPanicLevel logs are particularly important errors. In development the // logger panics after writing the message. DPanicLevel // PanicLevel logs a message, then panics. PanicLevel // FatalLevel logs a message, then calls os.Exit(1). FatalLevel _minLevel = DebugLevel _maxLevel = FatalLevel ) // String returns a lower-case ASCII representation of the log level. func (l Level) String() string { switch l { case DebugLevel: return "debug" case InfoLevel: return "info" case WarnLevel: return "warn" case ErrorLevel: return "error" case DPanicLevel: return "dpanic" case PanicLevel: return "panic" case FatalLevel: return "fatal" default: return fmt.Sprintf("Level(%d)", l) } } // CapitalString returns an all-caps ASCII representation of the log level. func (l Level) CapitalString() string { // Printing levels in all-caps is common enough that we should export this // functionality. switch l { case DebugLevel: return "DEBUG" case InfoLevel: return "INFO" case WarnLevel: return "WARN" case ErrorLevel: return "ERROR" case DPanicLevel: return "DPANIC" case PanicLevel: return "PANIC" case FatalLevel: return "FATAL" default: return fmt.Sprintf("LEVEL(%d)", l) } } // MarshalText marshals the Level to text. Note that the text representation // drops the -Level suffix (see example). func (l Level) MarshalText() ([]byte, error) { return []byte(l.String()), nil } // UnmarshalText unmarshals text to a level. Like MarshalText, UnmarshalText // expects the text representation of a Level to drop the -Level suffix (see // example). // // In particular, this makes it easy to configure logging levels using YAML, // TOML, or JSON files. func (l *Level) UnmarshalText(text []byte) error { if l == nil { return errUnmarshalNilLevel } if !l.unmarshalText(text) && !l.unmarshalText(bytes.ToLower(text)) { return fmt.Errorf("unrecognized level: %q", text) } return nil } func (l *Level) unmarshalText(text []byte) bool { switch string(text) { case "debug", "DEBUG": *l = DebugLevel case "info", "INFO", "": // make the zero value useful *l = InfoLevel case "warn", "WARN": *l = WarnLevel case "error", "ERROR": *l = ErrorLevel case "dpanic", "DPANIC": *l = DPanicLevel case "panic", "PANIC": *l = PanicLevel case "fatal", "FATAL": *l = FatalLevel default: return false } return true } // Set sets the level for the flag.Value interface. func (l *Level) Set(s string) error { return l.UnmarshalText([]byte(s)) } // Get gets the level for the flag.Getter interface. func (l *Level) Get() interface{} { return *l } // Enabled returns true if the given level is at or above this level. func (l Level) Enabled(lvl Level) bool { return lvl >= l } // LevelEnabler decides whether a given logging level is enabled when logging a // message. // // Enablers are intended to be used to implement deterministic filters; // concerns like sampling are better implemented as a Core. // // Each concrete Level value implements a static LevelEnabler which returns // true for itself and all higher logging levels. For example WarnLevel.Enabled() // will return true for WarnLevel, ErrorLevel, DPanicLevel, PanicLevel, and // FatalLevel, but return false for InfoLevel and DebugLevel. type LevelEnabler interface { Enabled(Level) bool }