aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/pion/logging/logger.go
blob: 35f650581916b8e92a6fe59593e682572090ae4f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
package logging

import (
	"fmt"
	"io"
	"log"
	"os"
	"strings"
	"sync"
)

// Use this abstraction to ensure thread-safe access to the logger's io.Writer
// (which could change at runtime)
type loggerWriter struct {
	sync.RWMutex
	output io.Writer
}

func (lw *loggerWriter) SetOutput(output io.Writer) {
	lw.Lock()
	defer lw.Unlock()
	lw.output = output
}

func (lw *loggerWriter) Write(data []byte) (int, error) {
	lw.RLock()
	defer lw.RUnlock()
	return lw.output.Write(data)
}

// DefaultLeveledLogger encapsulates functionality for providing logging at
// user-defined levels
type DefaultLeveledLogger struct {
	level  LogLevel
	writer *loggerWriter
	trace  *log.Logger
	debug  *log.Logger
	info   *log.Logger
	warn   *log.Logger
	err    *log.Logger
}

// WithTraceLogger is a chainable configuration function which sets the
// Trace-level logger
func (ll *DefaultLeveledLogger) WithTraceLogger(log *log.Logger) *DefaultLeveledLogger {
	ll.trace = log
	return ll
}

// WithDebugLogger is a chainable configuration function which sets the
// Debug-level logger
func (ll *DefaultLeveledLogger) WithDebugLogger(log *log.Logger) *DefaultLeveledLogger {
	ll.debug = log
	return ll
}

// WithInfoLogger is a chainable configuration function which sets the
// Info-level logger
func (ll *DefaultLeveledLogger) WithInfoLogger(log *log.Logger) *DefaultLeveledLogger {
	ll.info = log
	return ll
}

// WithWarnLogger is a chainable configuration function which sets the
// Warn-level logger
func (ll *DefaultLeveledLogger) WithWarnLogger(log *log.Logger) *DefaultLeveledLogger {
	ll.warn = log
	return ll
}

// WithErrorLogger is a chainable configuration function which sets the
// Error-level logger
func (ll *DefaultLeveledLogger) WithErrorLogger(log *log.Logger) *DefaultLeveledLogger {
	ll.err = log
	return ll
}

// WithOutput is a chainable configuration function which sets the logger's
// logging output to the supplied io.Writer
func (ll *DefaultLeveledLogger) WithOutput(output io.Writer) *DefaultLeveledLogger {
	ll.writer.SetOutput(output)
	return ll
}

func (ll *DefaultLeveledLogger) logf(logger *log.Logger, level LogLevel, format string, args ...interface{}) {
	if ll.level.Get() < level {
		return
	}

	callDepth := 3 // this frame + wrapper func + caller
	msg := fmt.Sprintf(format, args...)
	if err := logger.Output(callDepth, msg); err != nil {
		fmt.Fprintf(os.Stderr, "Unable to log: %s", err)
	}
}

// SetLevel sets the logger's logging level
func (ll *DefaultLeveledLogger) SetLevel(newLevel LogLevel) {
	ll.level.Set(newLevel)
}

// Trace emits the preformatted message if the logger is at or below LogLevelTrace
func (ll *DefaultLeveledLogger) Trace(msg string) {
	ll.logf(ll.trace, LogLevelTrace, msg)
}

// Tracef formats and emits a message if the logger is at or below LogLevelTrace
func (ll *DefaultLeveledLogger) Tracef(format string, args ...interface{}) {
	ll.logf(ll.trace, LogLevelTrace, format, args...)
}

// Debug emits the preformatted message if the logger is at or below LogLevelDebug
func (ll *DefaultLeveledLogger) Debug(msg string) {
	ll.logf(ll.debug, LogLevelDebug, msg)
}

// Debugf formats and emits a message if the logger is at or below LogLevelDebug
func (ll *DefaultLeveledLogger) Debugf(format string, args ...interface{}) {
	ll.logf(ll.debug, LogLevelDebug, format, args...)
}

// Info emits the preformatted message if the logger is at or below LogLevelInfo
func (ll *DefaultLeveledLogger) Info(msg string) {
	ll.logf(ll.info, LogLevelInfo, msg)
}

// Infof formats and emits a message if the logger is at or below LogLevelInfo
func (ll *DefaultLeveledLogger) Infof(format string, args ...interface{}) {
	ll.logf(ll.info, LogLevelInfo, format, args...)
}

// Warn emits the preformatted message if the logger is at or below LogLevelWarn
func (ll *DefaultLeveledLogger) Warn(msg string) {
	ll.logf(ll.warn, LogLevelWarn, msg)
}

// Warnf formats and emits a message if the logger is at or below LogLevelWarn
func (ll *DefaultLeveledLogger) Warnf(format string, args ...interface{}) {
	ll.logf(ll.warn, LogLevelWarn, format, args...)
}

// Error emits the preformatted message if the logger is at or below LogLevelError
func (ll *DefaultLeveledLogger) Error(msg string) {
	ll.logf(ll.err, LogLevelError, msg)
}

// Errorf formats and emits a message if the logger is at or below LogLevelError
func (ll *DefaultLeveledLogger) Errorf(format string, args ...interface{}) {
	ll.logf(ll.err, LogLevelError, format, args...)
}

// NewDefaultLeveledLoggerForScope returns a configured LeveledLogger
func NewDefaultLeveledLoggerForScope(scope string, level LogLevel, writer io.Writer) *DefaultLeveledLogger {
	if writer == nil {
		writer = os.Stdout
	}
	logger := &DefaultLeveledLogger{
		writer: &loggerWriter{output: writer},
		level:  level,
	}
	return logger.
		WithTraceLogger(log.New(logger.writer, fmt.Sprintf("%s TRACE: ", scope), log.Lmicroseconds|log.Lshortfile)).
		WithDebugLogger(log.New(logger.writer, fmt.Sprintf("%s DEBUG: ", scope), log.Lmicroseconds|log.Lshortfile)).
		WithInfoLogger(log.New(logger.writer, fmt.Sprintf("%s INFO: ", scope), log.LstdFlags)).
		WithWarnLogger(log.New(logger.writer, fmt.Sprintf("%s WARNING: ", scope), log.LstdFlags)).
		WithErrorLogger(log.New(logger.writer, fmt.Sprintf("%s ERROR: ", scope), log.LstdFlags))
}

// DefaultLoggerFactory define levels by scopes and creates new DefaultLeveledLogger
type DefaultLoggerFactory struct {
	Writer          io.Writer
	DefaultLogLevel LogLevel
	ScopeLevels     map[string]LogLevel
}

// NewDefaultLoggerFactory creates a new DefaultLoggerFactory
func NewDefaultLoggerFactory() *DefaultLoggerFactory {
	factory := DefaultLoggerFactory{}
	factory.DefaultLogLevel = LogLevelError
	factory.ScopeLevels = make(map[string]LogLevel)
	factory.Writer = os.Stdout

	logLevels := map[string]LogLevel{
		"DISABLE": LogLevelDisabled,
		"ERROR":   LogLevelError,
		"WARN":    LogLevelWarn,
		"INFO":    LogLevelInfo,
		"DEBUG":   LogLevelDebug,
		"TRACE":   LogLevelTrace,
	}

	for name, level := range logLevels {
		env := os.Getenv(fmt.Sprintf("PION_LOG_%s", name))

		if env == "" {
			env = os.Getenv(fmt.Sprintf("PIONS_LOG_%s", name))
		}

		if env == "" {
			continue
		}

		if strings.ToLower(env) == "all" {
			factory.DefaultLogLevel = level
			continue
		}

		scopes := strings.Split(strings.ToLower(env), ",")
		for _, scope := range scopes {
			factory.ScopeLevels[scope] = level
		}
	}

	return &factory
}

// NewLogger returns a configured LeveledLogger for the given , argsscope
func (f *DefaultLoggerFactory) NewLogger(scope string) LeveledLogger {
	logLevel := f.DefaultLogLevel
	if f.ScopeLevels != nil {
		scopeLevel, found := f.ScopeLevels[scope]

		if found {
			logLevel = scopeLevel
		}
	}
	return NewDefaultLeveledLoggerForScope(scope, logLevel, f.Writer)
}