1 package logging
2 3 import (
4 "context"
5 "io"
6 "log"
7 )
8 9 // Classification is the type of the log entry's classification name.
10 type Classification string
11 12 // Set of standard classifications that can be used by clients and middleware
13 const (
14 Warn Classification = "WARN"
15 Debug Classification = "DEBUG"
16 )
17 18 // Logger is an interface for logging entries at certain classifications.
19 type Logger interface {
20 // Logf is expected to support the standard fmt package "verbs".
21 Logf(classification Classification, format string, v ...interface{})
22 }
23 24 // LoggerFunc is a wrapper around a function to satisfy the Logger interface.
25 type LoggerFunc func(classification Classification, format string, v ...interface{})
26 27 // Logf delegates the logging request to the wrapped function.
28 func (f LoggerFunc) Logf(classification Classification, format string, v ...interface{}) {
29 f(classification, format, v...)
30 }
31 32 // ContextLogger is an optional interface a Logger implementation may expose that provides
33 // the ability to create context aware log entries.
34 type ContextLogger interface {
35 WithContext(context.Context) Logger
36 }
37 38 // WithContext will pass the provided context to logger if it implements the ContextLogger interface and return the resulting
39 // logger. Otherwise the logger will be returned as is. As a special case if a nil logger is provided, a Nop logger will
40 // be returned to the caller.
41 func WithContext(ctx context.Context, logger Logger) Logger {
42 if logger == nil {
43 return Nop{}
44 }
45 46 cl, ok := logger.(ContextLogger)
47 if !ok {
48 return logger
49 }
50 51 return cl.WithContext(ctx)
52 }
53 54 // Nop is a Logger implementation that simply does not perform any logging.
55 type Nop struct{}
56 57 // Logf simply returns without performing any action
58 func (n Nop) Logf(Classification, string, ...interface{}) {
59 return
60 }
61 62 // StandardLogger is a Logger implementation that wraps the standard library logger, and delegates logging to it's
63 // Printf method.
64 type StandardLogger struct {
65 Logger *log.Logger
66 }
67 68 // Logf logs the given classification and message to the underlying logger.
69 func (s StandardLogger) Logf(classification Classification, format string, v ...interface{}) {
70 if len(classification) != 0 {
71 format = string(classification) + " " + format
72 }
73 74 s.Logger.Printf(format, v...)
75 }
76 77 // NewStandardLogger returns a new StandardLogger
78 func NewStandardLogger(writer io.Writer) *StandardLogger {
79 return &StandardLogger{
80 Logger: log.New(writer, "SDK ", log.LstdFlags),
81 }
82 }
83