1 // Copyright (c) 2016 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package zap 22 23 import ( 24 "sync/atomic" 25 26 "go.uber.org/zap/internal" 27 "go.uber.org/zap/zapcore" 28 ) 29 30 const ( 31 // DebugLevel logs are typically voluminous, and are usually disabled in 32 // production. 33 DebugLevel = zapcore.DebugLevel 34 // InfoLevel is the default logging priority. 35 InfoLevel = zapcore.InfoLevel 36 // WarnLevel logs are more important than Info, but don't need individual 37 // human review. 38 WarnLevel = zapcore.WarnLevel 39 // ErrorLevel logs are high-priority. If an application is running smoothly, 40 // it shouldn't generate any error-level logs. 41 ErrorLevel = zapcore.ErrorLevel 42 // DPanicLevel logs are particularly important errors. In development the 43 // logger panics after writing the message. 44 DPanicLevel = zapcore.DPanicLevel 45 // PanicLevel logs a message, then panics. 46 PanicLevel = zapcore.PanicLevel 47 // FatalLevel logs a message, then calls os.Exit(1). 48 FatalLevel = zapcore.FatalLevel 49 ) 50 51 // LevelEnablerFunc is a convenient way to implement zapcore.LevelEnabler with 52 // an anonymous function. 53 // 54 // It's particularly useful when splitting log output between different 55 // outputs (e.g., standard error and standard out). For sample code, see the 56 // package-level AdvancedConfiguration example. 57 type LevelEnablerFunc func(zapcore.Level) bool 58 59 // Enabled calls the wrapped function. 60 func (f LevelEnablerFunc) Enabled(lvl zapcore.Level) bool { return f(lvl) } 61 62 // An AtomicLevel is an atomically changeable, dynamic logging level. It lets 63 // you safely change the log level of a tree of loggers (the root logger and 64 // any children created by adding context) at runtime. 65 // 66 // The AtomicLevel itself is an http.Handler that serves a JSON endpoint to 67 // alter its level. 68 // 69 // AtomicLevels must be created with the NewAtomicLevel constructor to allocate 70 // their internal atomic pointer. 71 type AtomicLevel struct { 72 l *atomic.Int32 73 } 74 75 var _ internal.LeveledEnabler = AtomicLevel{} 76 77 // NewAtomicLevel creates an AtomicLevel with InfoLevel and above logging 78 // enabled. 79 func NewAtomicLevel() AtomicLevel { 80 lvl := AtomicLevel{l: new(atomic.Int32)} 81 lvl.l.Store(int32(InfoLevel)) 82 return lvl 83 } 84 85 // NewAtomicLevelAt is a convenience function that creates an AtomicLevel 86 // and then calls SetLevel with the given level. 87 func NewAtomicLevelAt(l zapcore.Level) AtomicLevel { 88 a := NewAtomicLevel() 89 a.SetLevel(l) 90 return a 91 } 92 93 // ParseAtomicLevel parses an AtomicLevel based on a lowercase or all-caps ASCII 94 // representation of the log level. If the provided ASCII representation is 95 // invalid an error is returned. 96 // 97 // This is particularly useful when dealing with text input to configure log 98 // levels. 99 func ParseAtomicLevel(text string) (AtomicLevel, error) { 100 a := NewAtomicLevel() 101 l, err := zapcore.ParseLevel(text) 102 if err != nil { 103 return a, err 104 } 105 106 a.SetLevel(l) 107 return a, nil 108 } 109 110 // Enabled implements the zapcore.LevelEnabler interface, which allows the 111 // AtomicLevel to be used in place of traditional static levels. 112 func (lvl AtomicLevel) Enabled(l zapcore.Level) bool { 113 return lvl.Level().Enabled(l) 114 } 115 116 // Level returns the minimum enabled log level. 117 func (lvl AtomicLevel) Level() zapcore.Level { 118 return zapcore.Level(int8(lvl.l.Load())) 119 } 120 121 // SetLevel alters the logging level. 122 func (lvl AtomicLevel) SetLevel(l zapcore.Level) { 123 lvl.l.Store(int32(l)) 124 } 125 126 // String returns the string representation of the underlying Level. 127 func (lvl AtomicLevel) String() string { 128 return lvl.Level().String() 129 } 130 131 // UnmarshalText unmarshals the text to an AtomicLevel. It uses the same text 132 // representations as the static zapcore.Levels ("debug", "info", "warn", 133 // "error", "dpanic", "panic", and "fatal"). 134 func (lvl *AtomicLevel) UnmarshalText(text []byte) error { 135 if lvl.l == nil { 136 lvl.l = &atomic.Int32{} 137 } 138 139 var l zapcore.Level 140 if err := l.UnmarshalText(text); err != nil { 141 return err 142 } 143 144 lvl.SetLevel(l) 145 return nil 146 } 147 148 // MarshalText marshals the AtomicLevel to a byte slice. It uses the same 149 // text representation as the static zapcore.Levels ("debug", "info", "warn", 150 // "error", "dpanic", "panic", and "fatal"). 151 func (lvl AtomicLevel) MarshalText() (text []byte, err error) { 152 return lvl.Level().MarshalText() 153 } 154