blob: 155b208bd3c824b9a1b85b33f98c4cd2fad65e5c [file] [log] [blame]
William Kurkianea869482019-04-09 15:16:11 -04001// 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
21package zap
22
23import (
Abhay Kumara61c5222025-11-10 07:32:50 +000024 "sync/atomic"
25
26 "go.uber.org/zap/internal"
William Kurkianea869482019-04-09 15:16:11 -040027 "go.uber.org/zap/zapcore"
28)
29
30const (
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.
57type LevelEnablerFunc func(zapcore.Level) bool
58
59// Enabled calls the wrapped function.
60func (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.
71type AtomicLevel struct {
72 l *atomic.Int32
73}
74
Abhay Kumara61c5222025-11-10 07:32:50 +000075var _ internal.LeveledEnabler = AtomicLevel{}
76
William Kurkianea869482019-04-09 15:16:11 -040077// NewAtomicLevel creates an AtomicLevel with InfoLevel and above logging
78// enabled.
79func NewAtomicLevel() AtomicLevel {
Abhay Kumara61c5222025-11-10 07:32:50 +000080 lvl := AtomicLevel{l: new(atomic.Int32)}
81 lvl.l.Store(int32(InfoLevel))
82 return lvl
William Kurkianea869482019-04-09 15:16:11 -040083}
84
85// NewAtomicLevelAt is a convenience function that creates an AtomicLevel
86// and then calls SetLevel with the given level.
87func NewAtomicLevelAt(l zapcore.Level) AtomicLevel {
88 a := NewAtomicLevel()
89 a.SetLevel(l)
90 return a
91}
92
Abhay Kumara61c5222025-11-10 07:32:50 +000093// 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.
99func 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
William Kurkianea869482019-04-09 15:16:11 -0400110// Enabled implements the zapcore.LevelEnabler interface, which allows the
111// AtomicLevel to be used in place of traditional static levels.
112func (lvl AtomicLevel) Enabled(l zapcore.Level) bool {
113 return lvl.Level().Enabled(l)
114}
115
116// Level returns the minimum enabled log level.
117func (lvl AtomicLevel) Level() zapcore.Level {
118 return zapcore.Level(int8(lvl.l.Load()))
119}
120
121// SetLevel alters the logging level.
122func (lvl AtomicLevel) SetLevel(l zapcore.Level) {
123 lvl.l.Store(int32(l))
124}
125
126// String returns the string representation of the underlying Level.
127func (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").
134func (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").
151func (lvl AtomicLevel) MarshalText() (text []byte, err error) {
152 return lvl.Level().MarshalText()
153}