1// Copyright 2015 The Prometheus Authors
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14// Package log implements logging via logrus.
15//
16// Deprecated: This package has been replaced with github.com/prometheus/common/promlog.
17
18package log
19
20import (
21	"fmt"
22	"io"
23	"io/ioutil"
24	"log"
25	"net/url"
26	"os"
27	"runtime"
28	"strconv"
29	"strings"
30
31	"github.com/sirupsen/logrus"
32	"gopkg.in/alecthomas/kingpin.v2"
33)
34
35// setSyslogFormatter is nil if the target architecture does not support syslog.
36var setSyslogFormatter func(logger, string, string) error
37
38// setEventlogFormatter is nil if the target OS does not support Eventlog (i.e., is not Windows).
39var setEventlogFormatter func(logger, string, bool) error
40
41func setJSONFormatter() {
42	origLogger.Formatter = &logrus.JSONFormatter{}
43}
44
45type loggerSettings struct {
46	level  string
47	format string
48}
49
50func (s *loggerSettings) apply(ctx *kingpin.ParseContext) error {
51	err := baseLogger.SetLevel(s.level)
52	if err != nil {
53		return err
54	}
55	err = baseLogger.SetFormat(s.format)
56	return err
57}
58
59// AddFlags adds the flags used by this package to the Kingpin application.
60// To use the default Kingpin application, call AddFlags(kingpin.CommandLine)
61func AddFlags(a *kingpin.Application) {
62	s := loggerSettings{}
63	a.Flag("log.level", "Only log messages with the given severity or above. Valid levels: [debug, info, warn, error, fatal]").
64		Default(origLogger.Level.String()).
65		StringVar(&s.level)
66	defaultFormat := url.URL{Scheme: "logger", Opaque: "stderr"}
67	a.Flag("log.format", `Set the log target and format. Example: "logger:syslog?appname=bob&local=7" or "logger:stdout?json=true"`).
68		Default(defaultFormat.String()).
69		StringVar(&s.format)
70	a.Action(s.apply)
71}
72
73// Logger is the interface for loggers used in the Prometheus components.
74type Logger interface {
75	Debug(...interface{})
76	Debugln(...interface{})
77	Debugf(string, ...interface{})
78
79	Info(...interface{})
80	Infoln(...interface{})
81	Infof(string, ...interface{})
82
83	Warn(...interface{})
84	Warnln(...interface{})
85	Warnf(string, ...interface{})
86
87	Error(...interface{})
88	Errorln(...interface{})
89	Errorf(string, ...interface{})
90
91	Fatal(...interface{})
92	Fatalln(...interface{})
93	Fatalf(string, ...interface{})
94
95	With(key string, value interface{}) Logger
96
97	SetFormat(string) error
98	SetLevel(string) error
99}
100
101type logger struct {
102	entry *logrus.Entry
103}
104
105func (l logger) With(key string, value interface{}) Logger {
106	return logger{l.entry.WithField(key, value)}
107}
108
109// Debug logs a message at level Debug on the standard logger.
110func (l logger) Debug(args ...interface{}) {
111	l.sourced().Debug(args...)
112}
113
114// Debug logs a message at level Debug on the standard logger.
115func (l logger) Debugln(args ...interface{}) {
116	l.sourced().Debugln(args...)
117}
118
119// Debugf logs a message at level Debug on the standard logger.
120func (l logger) Debugf(format string, args ...interface{}) {
121	l.sourced().Debugf(format, args...)
122}
123
124// Info logs a message at level Info on the standard logger.
125func (l logger) Info(args ...interface{}) {
126	l.sourced().Info(args...)
127}
128
129// Info logs a message at level Info on the standard logger.
130func (l logger) Infoln(args ...interface{}) {
131	l.sourced().Infoln(args...)
132}
133
134// Infof logs a message at level Info on the standard logger.
135func (l logger) Infof(format string, args ...interface{}) {
136	l.sourced().Infof(format, args...)
137}
138
139// Warn logs a message at level Warn on the standard logger.
140func (l logger) Warn(args ...interface{}) {
141	l.sourced().Warn(args...)
142}
143
144// Warn logs a message at level Warn on the standard logger.
145func (l logger) Warnln(args ...interface{}) {
146	l.sourced().Warnln(args...)
147}
148
149// Warnf logs a message at level Warn on the standard logger.
150func (l logger) Warnf(format string, args ...interface{}) {
151	l.sourced().Warnf(format, args...)
152}
153
154// Error logs a message at level Error on the standard logger.
155func (l logger) Error(args ...interface{}) {
156	l.sourced().Error(args...)
157}
158
159// Error logs a message at level Error on the standard logger.
160func (l logger) Errorln(args ...interface{}) {
161	l.sourced().Errorln(args...)
162}
163
164// Errorf logs a message at level Error on the standard logger.
165func (l logger) Errorf(format string, args ...interface{}) {
166	l.sourced().Errorf(format, args...)
167}
168
169// Fatal logs a message at level Fatal on the standard logger.
170func (l logger) Fatal(args ...interface{}) {
171	l.sourced().Fatal(args...)
172}
173
174// Fatal logs a message at level Fatal on the standard logger.
175func (l logger) Fatalln(args ...interface{}) {
176	l.sourced().Fatalln(args...)
177}
178
179// Fatalf logs a message at level Fatal on the standard logger.
180func (l logger) Fatalf(format string, args ...interface{}) {
181	l.sourced().Fatalf(format, args...)
182}
183
184func (l logger) SetLevel(level string) error {
185	lvl, err := logrus.ParseLevel(level)
186	if err != nil {
187		return err
188	}
189
190	l.entry.Logger.Level = lvl
191	return nil
192}
193
194func (l logger) SetFormat(format string) error {
195	u, err := url.Parse(format)
196	if err != nil {
197		return err
198	}
199	if u.Scheme != "logger" {
200		return fmt.Errorf("invalid scheme %s", u.Scheme)
201	}
202	jsonq := u.Query().Get("json")
203	if jsonq == "true" {
204		setJSONFormatter()
205	}
206
207	switch u.Opaque {
208	case "syslog":
209		if setSyslogFormatter == nil {
210			return fmt.Errorf("system does not support syslog")
211		}
212		appname := u.Query().Get("appname")
213		facility := u.Query().Get("local")
214		return setSyslogFormatter(l, appname, facility)
215	case "eventlog":
216		if setEventlogFormatter == nil {
217			return fmt.Errorf("system does not support eventlog")
218		}
219		name := u.Query().Get("name")
220		debugAsInfo := false
221		debugAsInfoRaw := u.Query().Get("debugAsInfo")
222		if parsedDebugAsInfo, err := strconv.ParseBool(debugAsInfoRaw); err == nil {
223			debugAsInfo = parsedDebugAsInfo
224		}
225		return setEventlogFormatter(l, name, debugAsInfo)
226	case "stdout":
227		l.entry.Logger.Out = os.Stdout
228	case "stderr":
229		l.entry.Logger.Out = os.Stderr
230	default:
231		return fmt.Errorf("unsupported logger %q", u.Opaque)
232	}
233	return nil
234}
235
236// sourced adds a source field to the logger that contains
237// the file name and line where the logging happened.
238func (l logger) sourced() *logrus.Entry {
239	_, file, line, ok := runtime.Caller(2)
240	if !ok {
241		file = "<???>"
242		line = 1
243	} else {
244		slash := strings.LastIndex(file, "/")
245		file = file[slash+1:]
246	}
247	return l.entry.WithField("source", fmt.Sprintf("%s:%d", file, line))
248}
249
250var origLogger = logrus.New()
251var baseLogger = logger{entry: logrus.NewEntry(origLogger)}
252
253// Base returns the default Logger logging to
254func Base() Logger {
255	return baseLogger
256}
257
258// NewLogger returns a new Logger logging to out.
259func NewLogger(w io.Writer) Logger {
260	l := logrus.New()
261	l.Out = w
262	return logger{entry: logrus.NewEntry(l)}
263}
264
265// NewNopLogger returns a logger that discards all log messages.
266func NewNopLogger() Logger {
267	l := logrus.New()
268	l.Out = ioutil.Discard
269	return logger{entry: logrus.NewEntry(l)}
270}
271
272// With adds a field to the logger.
273func With(key string, value interface{}) Logger {
274	return baseLogger.With(key, value)
275}
276
277// Debug logs a message at level Debug on the standard logger.
278func Debug(args ...interface{}) {
279	baseLogger.sourced().Debug(args...)
280}
281
282// Debugln logs a message at level Debug on the standard logger.
283func Debugln(args ...interface{}) {
284	baseLogger.sourced().Debugln(args...)
285}
286
287// Debugf logs a message at level Debug on the standard logger.
288func Debugf(format string, args ...interface{}) {
289	baseLogger.sourced().Debugf(format, args...)
290}
291
292// Info logs a message at level Info on the standard logger.
293func Info(args ...interface{}) {
294	baseLogger.sourced().Info(args...)
295}
296
297// Infoln logs a message at level Info on the standard logger.
298func Infoln(args ...interface{}) {
299	baseLogger.sourced().Infoln(args...)
300}
301
302// Infof logs a message at level Info on the standard logger.
303func Infof(format string, args ...interface{}) {
304	baseLogger.sourced().Infof(format, args...)
305}
306
307// Warn logs a message at level Warn on the standard logger.
308func Warn(args ...interface{}) {
309	baseLogger.sourced().Warn(args...)
310}
311
312// Warnln logs a message at level Warn on the standard logger.
313func Warnln(args ...interface{}) {
314	baseLogger.sourced().Warnln(args...)
315}
316
317// Warnf logs a message at level Warn on the standard logger.
318func Warnf(format string, args ...interface{}) {
319	baseLogger.sourced().Warnf(format, args...)
320}
321
322// Error logs a message at level Error on the standard logger.
323func Error(args ...interface{}) {
324	baseLogger.sourced().Error(args...)
325}
326
327// Errorln logs a message at level Error on the standard logger.
328func Errorln(args ...interface{}) {
329	baseLogger.sourced().Errorln(args...)
330}
331
332// Errorf logs a message at level Error on the standard logger.
333func Errorf(format string, args ...interface{}) {
334	baseLogger.sourced().Errorf(format, args...)
335}
336
337// Fatal logs a message at level Fatal on the standard logger.
338func Fatal(args ...interface{}) {
339	baseLogger.sourced().Fatal(args...)
340}
341
342// Fatalln logs a message at level Fatal on the standard logger.
343func Fatalln(args ...interface{}) {
344	baseLogger.sourced().Fatalln(args...)
345}
346
347// Fatalf logs a message at level Fatal on the standard logger.
348func Fatalf(format string, args ...interface{}) {
349	baseLogger.sourced().Fatalf(format, args...)
350}
351
352// AddHook adds hook to Prometheus' original logger.
353func AddHook(hook logrus.Hook) {
354	origLogger.Hooks.Add(hook)
355}
356
357type errorLogWriter struct{}
358
359func (errorLogWriter) Write(b []byte) (int, error) {
360	baseLogger.sourced().Error(string(b))
361	return len(b), nil
362}
363
364// NewErrorLogger returns a log.Logger that is meant to be used
365// in the ErrorLog field of an http.Server to log HTTP server errors.
366func NewErrorLogger() *log.Logger {
367	return log.New(&errorLogWriter{}, "", 0)
368}
369