// Copyright (c) 2016 Uber Technologies, Inc.1//2// Permission is hereby granted, free of charge, to any person obtaining a copy3// of this software and associated documentation files (the "Software"), to deal4// in the Software without restriction, including without limitation the rights5// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell6// copies of the Software, and to permit persons to whom the Software is7// furnished to do so, subject to the following conditions:8//9// The above copyright notice and this permission notice shall be included in10// all copies or substantial portions of the Software.11//12// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR13// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,14// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE15// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER16// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,17// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN18// THE SOFTWARE.1920package zap2122import (23"sync/atomic"2425"go.uber.org/zap/internal"26"go.uber.org/zap/zapcore"27)2829const (30// DebugLevel logs are typically voluminous, and are usually disabled in31// production.32DebugLevel = zapcore.DebugLevel33// InfoLevel is the default logging priority.34InfoLevel = zapcore.InfoLevel35// WarnLevel logs are more important than Info, but don't need individual36// human review.37WarnLevel = zapcore.WarnLevel38// ErrorLevel logs are high-priority. If an application is running smoothly,39// it shouldn't generate any error-level logs.40ErrorLevel = zapcore.ErrorLevel41// DPanicLevel logs are particularly important errors. In development the42// logger panics after writing the message.43DPanicLevel = zapcore.DPanicLevel44// PanicLevel logs a message, then panics.45PanicLevel = zapcore.PanicLevel46// FatalLevel logs a message, then calls os.Exit(1).47FatalLevel = zapcore.FatalLevel48)4950// LevelEnablerFunc is a convenient way to implement zapcore.LevelEnabler with51// an anonymous function.52//53// It's particularly useful when splitting log output between different54// outputs (e.g., standard error and standard out). For sample code, see the55// package-level AdvancedConfiguration example.56type LevelEnablerFunc func(zapcore.Level) bool5758// Enabled calls the wrapped function.59func (f LevelEnablerFunc) Enabled(lvl zapcore.Level) bool { return f(lvl) }6061// An AtomicLevel is an atomically changeable, dynamic logging level. It lets62// you safely change the log level of a tree of loggers (the root logger and63// any children created by adding context) at runtime.64//65// The AtomicLevel itself is an http.Handler that serves a JSON endpoint to66// alter its level.67//68// AtomicLevels must be created with the NewAtomicLevel constructor to allocate69// their internal atomic pointer.70type AtomicLevel struct {71l *atomic.Int3272}7374var _ internal.LeveledEnabler = AtomicLevel{}7576// NewAtomicLevel creates an AtomicLevel with InfoLevel and above logging77// enabled.78func NewAtomicLevel() AtomicLevel {79lvl := AtomicLevel{l: new(atomic.Int32)}80lvl.l.Store(int32(InfoLevel))81return lvl82}8384// NewAtomicLevelAt is a convenience function that creates an AtomicLevel85// and then calls SetLevel with the given level.86func NewAtomicLevelAt(l zapcore.Level) AtomicLevel {87a := NewAtomicLevel()88a.SetLevel(l)89return a90}9192// ParseAtomicLevel parses an AtomicLevel based on a lowercase or all-caps ASCII93// representation of the log level. If the provided ASCII representation is94// invalid an error is returned.95//96// This is particularly useful when dealing with text input to configure log97// levels.98func ParseAtomicLevel(text string) (AtomicLevel, error) {99a := NewAtomicLevel()100l, err := zapcore.ParseLevel(text)101if err != nil {102return a, err103}104105a.SetLevel(l)106return a, nil107}108109// Enabled implements the zapcore.LevelEnabler interface, which allows the110// AtomicLevel to be used in place of traditional static levels.111func (lvl AtomicLevel) Enabled(l zapcore.Level) bool {112return lvl.Level().Enabled(l)113}114115// Level returns the minimum enabled log level.116func (lvl AtomicLevel) Level() zapcore.Level {117return zapcore.Level(int8(lvl.l.Load()))118}119120// SetLevel alters the logging level.121func (lvl AtomicLevel) SetLevel(l zapcore.Level) {122lvl.l.Store(int32(l))123}124125// String returns the string representation of the underlying Level.126func (lvl AtomicLevel) String() string {127return lvl.Level().String()128}129130// UnmarshalText unmarshals the text to an AtomicLevel. It uses the same text131// representations as the static zapcore.Levels ("debug", "info", "warn",132// "error", "dpanic", "panic", and "fatal").133func (lvl *AtomicLevel) UnmarshalText(text []byte) error {134if lvl.l == nil {135lvl.l = &atomic.Int32{}136}137138var l zapcore.Level139if err := l.UnmarshalText(text); err != nil {140return err141}142143lvl.SetLevel(l)144return nil145}146147// MarshalText marshals the AtomicLevel to a byte slice. It uses the same148// text representation as the static zapcore.Levels ("debug", "info", "warn",149// "error", "dpanic", "panic", and "fatal").150func (lvl AtomicLevel) MarshalText() (text []byte, err error) {151return lvl.Level().MarshalText()152}153154155