...

Source file src/go.uber.org/zap/zapcore/level.go

Documentation: go.uber.org/zap/zapcore

     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 zapcore
    22  
    23  import (
    24  	"bytes"
    25  	"errors"
    26  	"fmt"
    27  )
    28  
    29  var errUnmarshalNilLevel = errors.New("can't unmarshal a nil *Level")
    30  
    31  // A Level is a logging priority. Higher levels are more important.
    32  type Level int8
    33  
    34  const (
    35  	// DebugLevel logs are typically voluminous, and are usually disabled in
    36  	// production.
    37  	DebugLevel Level = iota - 1
    38  	// InfoLevel is the default logging priority.
    39  	InfoLevel
    40  	// WarnLevel logs are more important than Info, but don't need individual
    41  	// human review.
    42  	WarnLevel
    43  	// ErrorLevel logs are high-priority. If an application is running smoothly,
    44  	// it shouldn't generate any error-level logs.
    45  	ErrorLevel
    46  	// DPanicLevel logs are particularly important errors. In development the
    47  	// logger panics after writing the message.
    48  	DPanicLevel
    49  	// PanicLevel logs a message, then panics.
    50  	PanicLevel
    51  	// FatalLevel logs a message, then calls os.Exit(1).
    52  	FatalLevel
    53  
    54  	_minLevel = DebugLevel
    55  	_maxLevel = FatalLevel
    56  
    57  	// InvalidLevel is an invalid value for Level.
    58  	//
    59  	// Core implementations may panic if they see messages of this level.
    60  	InvalidLevel = _maxLevel + 1
    61  )
    62  
    63  // ParseLevel parses a level based on the lower-case or all-caps ASCII
    64  // representation of the log level. If the provided ASCII representation is
    65  // invalid an error is returned.
    66  //
    67  // This is particularly useful when dealing with text input to configure log
    68  // levels.
    69  func ParseLevel(text string) (Level, error) {
    70  	var level Level
    71  	err := level.UnmarshalText([]byte(text))
    72  	return level, err
    73  }
    74  
    75  type leveledEnabler interface {
    76  	LevelEnabler
    77  
    78  	Level() Level
    79  }
    80  
    81  // LevelOf reports the minimum enabled log level for the given LevelEnabler
    82  // from Zap's supported log levels, or [InvalidLevel] if none of them are
    83  // enabled.
    84  //
    85  // A LevelEnabler may implement a 'Level() Level' method to override the
    86  // behavior of this function.
    87  //
    88  //	func (c *core) Level() Level {
    89  //		return c.currentLevel
    90  //	}
    91  //
    92  // It is recommended that [Core] implementations that wrap other cores use
    93  // LevelOf to retrieve the level of the wrapped core. For example,
    94  //
    95  //	func (c *coreWrapper) Level() Level {
    96  //		return zapcore.LevelOf(c.wrappedCore)
    97  //	}
    98  func LevelOf(enab LevelEnabler) Level {
    99  	if lvler, ok := enab.(leveledEnabler); ok {
   100  		return lvler.Level()
   101  	}
   102  
   103  	for lvl := _minLevel; lvl <= _maxLevel; lvl++ {
   104  		if enab.Enabled(lvl) {
   105  			return lvl
   106  		}
   107  	}
   108  
   109  	return InvalidLevel
   110  }
   111  
   112  // String returns a lower-case ASCII representation of the log level.
   113  func (l Level) String() string {
   114  	switch l {
   115  	case DebugLevel:
   116  		return "debug"
   117  	case InfoLevel:
   118  		return "info"
   119  	case WarnLevel:
   120  		return "warn"
   121  	case ErrorLevel:
   122  		return "error"
   123  	case DPanicLevel:
   124  		return "dpanic"
   125  	case PanicLevel:
   126  		return "panic"
   127  	case FatalLevel:
   128  		return "fatal"
   129  	default:
   130  		return fmt.Sprintf("Level(%d)", l)
   131  	}
   132  }
   133  
   134  // CapitalString returns an all-caps ASCII representation of the log level.
   135  func (l Level) CapitalString() string {
   136  	// Printing levels in all-caps is common enough that we should export this
   137  	// functionality.
   138  	switch l {
   139  	case DebugLevel:
   140  		return "DEBUG"
   141  	case InfoLevel:
   142  		return "INFO"
   143  	case WarnLevel:
   144  		return "WARN"
   145  	case ErrorLevel:
   146  		return "ERROR"
   147  	case DPanicLevel:
   148  		return "DPANIC"
   149  	case PanicLevel:
   150  		return "PANIC"
   151  	case FatalLevel:
   152  		return "FATAL"
   153  	default:
   154  		return fmt.Sprintf("LEVEL(%d)", l)
   155  	}
   156  }
   157  
   158  // MarshalText marshals the Level to text. Note that the text representation
   159  // drops the -Level suffix (see example).
   160  func (l Level) MarshalText() ([]byte, error) {
   161  	return []byte(l.String()), nil
   162  }
   163  
   164  // UnmarshalText unmarshals text to a level. Like MarshalText, UnmarshalText
   165  // expects the text representation of a Level to drop the -Level suffix (see
   166  // example).
   167  //
   168  // In particular, this makes it easy to configure logging levels using YAML,
   169  // TOML, or JSON files.
   170  func (l *Level) UnmarshalText(text []byte) error {
   171  	if l == nil {
   172  		return errUnmarshalNilLevel
   173  	}
   174  	if !l.unmarshalText(text) && !l.unmarshalText(bytes.ToLower(text)) {
   175  		return fmt.Errorf("unrecognized level: %q", text)
   176  	}
   177  	return nil
   178  }
   179  
   180  func (l *Level) unmarshalText(text []byte) bool {
   181  	switch string(text) {
   182  	case "debug", "DEBUG":
   183  		*l = DebugLevel
   184  	case "info", "INFO", "": // make the zero value useful
   185  		*l = InfoLevel
   186  	case "warn", "WARN":
   187  		*l = WarnLevel
   188  	case "error", "ERROR":
   189  		*l = ErrorLevel
   190  	case "dpanic", "DPANIC":
   191  		*l = DPanicLevel
   192  	case "panic", "PANIC":
   193  		*l = PanicLevel
   194  	case "fatal", "FATAL":
   195  		*l = FatalLevel
   196  	default:
   197  		return false
   198  	}
   199  	return true
   200  }
   201  
   202  // Set sets the level for the flag.Value interface.
   203  func (l *Level) Set(s string) error {
   204  	return l.UnmarshalText([]byte(s))
   205  }
   206  
   207  // Get gets the level for the flag.Getter interface.
   208  func (l *Level) Get() interface{} {
   209  	return *l
   210  }
   211  
   212  // Enabled returns true if the given level is at or above this level.
   213  func (l Level) Enabled(lvl Level) bool {
   214  	return lvl >= l
   215  }
   216  
   217  // LevelEnabler decides whether a given logging level is enabled when logging a
   218  // message.
   219  //
   220  // Enablers are intended to be used to implement deterministic filters;
   221  // concerns like sampling are better implemented as a Core.
   222  //
   223  // Each concrete Level value implements a static LevelEnabler which returns
   224  // true for itself and all higher logging levels. For example WarnLevel.Enabled()
   225  // will return true for WarnLevel, ErrorLevel, DPanicLevel, PanicLevel, and
   226  // FatalLevel, but return false for InfoLevel and DebugLevel.
   227  type LevelEnabler interface {
   228  	Enabled(Level) bool
   229  }
   230  

View as plain text