summaryrefslogtreecommitdiff
path: root/src/mongo/gotools/common/log/tool_logger.go
blob: c93378d796bef12bd966bc8069eb0c86291b2fa8 (plain)
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
// Package log provides a utility to log timestamped messages to an io.Writer.
package log

import (
	"fmt"
	"io"
	"os"
	"sync"
	"time"
)

// Tool Logger verbosity constants
const (
	Always = iota
	Info
	DebugLow
	DebugHigh
)

const (
	ToolTimeFormat = "2006-01-02T15:04:05.000-0700"
)

//// Tool Logger Definition

type ToolLogger struct {
	mutex     *sync.Mutex
	writer    io.Writer
	format    string
	verbosity int
}

type VerbosityLevel interface {
	Level() int
	IsQuiet() bool
}

func (tl *ToolLogger) SetVerbosity(level VerbosityLevel) {
	if level == nil {
		tl.verbosity = 0
		return
	}

	if level.IsQuiet() {
		tl.verbosity = -1
	} else {
		tl.verbosity = level.Level()
	}
}

func (tl *ToolLogger) SetWriter(writer io.Writer) {
	tl.writer = writer
}

func (tl *ToolLogger) SetDateFormat(dateFormat string) {
	tl.format = dateFormat
}

func (tl *ToolLogger) Logvf(minVerb int, format string, a ...interface{}) {
	if minVerb < 0 {
		panic("cannot set a minimum log verbosity that is less than 0")
	}

	if minVerb <= tl.verbosity {
		tl.mutex.Lock()
		defer tl.mutex.Unlock()
		tl.log(fmt.Sprintf(format, a...))
	}
}

func (tl *ToolLogger) Logv(minVerb int, msg string) {
	if minVerb < 0 {
		panic("cannot set a minimum log verbosity that is less than 0")
	}

	if minVerb <= tl.verbosity {
		tl.mutex.Lock()
		defer tl.mutex.Unlock()
		tl.log(msg)
	}
}

func (tl *ToolLogger) log(msg string) {
	fmt.Fprintf(tl.writer, "%v\t%v\n", time.Now().Format(tl.format), msg)
}

func NewToolLogger(verbosity VerbosityLevel) *ToolLogger {
	tl := &ToolLogger{
		mutex:  &sync.Mutex{},
		writer: os.Stderr, // default to stderr
		format: ToolTimeFormat,
	}
	tl.SetVerbosity(verbosity)
	return tl
}

//// Log Writer Interface

// toolLogWriter is an io.Writer wrapping a tool logger. It is a private
// type meant for creation with the ToolLogger.Writer(...) method.
type toolLogWriter struct {
	logger       *ToolLogger
	minVerbosity int
}

func (tlw *toolLogWriter) Write(message []byte) (int, error) {
	tlw.logger.Logv(tlw.minVerbosity, string(message))
	return len(message), nil
}

// Writer returns an io.Writer that writes to the logger with
// the given verbosity
func (tl *ToolLogger) Writer(minVerb int) io.Writer {
	return &toolLogWriter{tl, minVerb}
}

//// Global Logging

var globalToolLogger *ToolLogger

func init() {
	if globalToolLogger == nil {
		// initialize tool logger with verbosity level = 0
		globalToolLogger = NewToolLogger(nil)
	}
}

// IsInVerbosity returns true if the current verbosity level setting is
// greater than or equal to the given level.
func IsInVerbosity(minVerb int) bool {
	return minVerb <= globalToolLogger.verbosity
}

func Logvf(minVerb int, format string, a ...interface{}) {
	globalToolLogger.Logvf(minVerb, format, a...)
}

func Logv(minVerb int, msg string) {
	globalToolLogger.Logv(minVerb, msg)
}

func SetVerbosity(verbosity VerbosityLevel) {
	globalToolLogger.SetVerbosity(verbosity)
}

func SetWriter(writer io.Writer) {
	globalToolLogger.SetWriter(writer)
}

func SetDateFormat(dateFormat string) {
	globalToolLogger.SetDateFormat(dateFormat)
}

func Writer(minVerb int) io.Writer {
	return globalToolLogger.Writer(minVerb)
}