level.go raw

   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