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
229
230
231
232
233
234
235
|
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package log
/*
Handles the on/off flags for things like log.Info() and log.Warn()
*/
/*
The original log flags:
log.Ldate: The date in the local time zone: YYYY/MM/DD.
log.Ltime: The time in the local time zone: HH:MM:SS.
log.Lmicroseconds: Microsecond resolution: HH:MM:SS.microseconds.
log.Llongfile: Full file name and line number: /a/b/c/d.go:23.
log.Lshortfile: Final file name element and line number: d.go:23.
log.LUTC: If Ldate or Ltime is set, use UTC rather than the local time zone.
log.Lmsgprefix: Move the "prefix" from the beginning of the line to before the message.
log.LstdFlags: Initial values for the standard logger (Ldate | Ltime).
can be set this way:
myLogger.SetFlags(log.Ldate | log.Ltime)
*/
import (
"net/http"
"os"
"sync"
)
var INFO *LogFlag // toggles log.Info()
var VERBOSE *LogFlag // toggles log.Verbose()
var SPEW *LogFlag // toggles log.Spew()
var WARN *LogFlag // toggles log.Warn() (true by default)
var ERROR *LogFlag // toggles log.Warn() (true by default)
var PRINTLN *LogFlag // toggles log.Println() (true by default)
var always *LogFlag
var allon bool = false
// writeMutex protects locks the write process
var flagsMutex sync.Mutex
type LogFlag struct {
b bool
orig bool // used as the Default value. set at the time of Registration()
name string
// TODO: figure out what package is sending the Registration
subsystem string // probably should just be forced to be the package name
short string // string actually printed on each line
desc string
}
var flags []*LogFlag
var daemonMode bool
var captureMode *os.File
var httpMode http.ResponseWriter
func init() {
full := "go.wit.com/log"
short := "log"
// internally used to bypass the possibility that all the flags are off
always = new(LogFlag)
always.b = true
always.orig = true
always.subsystem = full
always.short = short
always.desc = "internal only"
daemonMode = false
INFO = NewFlag("INFO", true, full, short, "Enable log.Info()")
SPEW = NewFlag("SPEW", false, full, short, "Enable log.Spew()")
WARN = NewFlag("WARN", true, full, short, "Enable log.Warn()")
ERROR = NewFlag("ERROR", true, full, short, "Enable log.Error()")
PRINTLN = NewFlag("PRINTLN", true, full, short, "Enable log.Println()")
VERBOSE = NewFlag("VERBOSE", false, full, short, "Enable log.Verbose()")
}
// restores flag to it's default value
func (f *LogFlag) SetDefault() {
if !f.Ok() {
return
}
f.b = f.orig
}
// set all the flags
func SetDefaults() {
flagsMutex.Lock()
defer flagsMutex.Unlock()
for _, f := range flags {
f.SetDefault()
}
}
// simply protects against panic() by making sure it exists.
func (f *LogFlag) Ok() bool {
if f == nil {
return false
}
return true
}
// set all the flags
func SetAll(b bool) {
flagsMutex.Lock()
defer flagsMutex.Unlock()
allon = b
for _, f := range flags {
f.b = b
}
}
// this bypasses all checks and _always_ logs the info to STDOUT
// is this a bad idea? Probably not....
// TODO: returning []*LogFlag is not safe and access must be locked
// but this is only used by the log debugging window at this time
func ShowFlags() []*LogFlag {
flagsMutex.Lock()
defer flagsMutex.Unlock()
for _, f := range flags {
Log(always, "ShowFlags() ", "("+f.subsystem+")", f.name, "=", f.b, ":", f.desc)
}
return flags
}
// TODO, switch to this. maybe.
func ProcessFlags(callback func(*LogFlag)) {
flagsMutex.Lock()
defer flagsMutex.Unlock()
for _, f := range flags {
Log(always, "ProcessFlags() run callback(f) here on", f)
callback(f)
}
}
// probably a better name than Get()
// switch to this
func (f *LogFlag) Bool() bool {
if !f.Ok() {
return false
}
return f.b
}
// returns the value of the flag
func (f *LogFlag) Get() bool {
if !f.Ok() {
return false
}
return f.b
}
/*
func (f *LogFlag) Set(b bool) {
if ! f.Ok() {}
f.b = b
}
*/
// returns the name of the flag
func (f *LogFlag) GetName() string {
if !f.Ok() {
return ""
}
return f.name
}
// returns the subsystem of the flag
func (f *LogFlag) GetSubsystem() string {
if !f.Ok() {
return ""
}
return f.subsystem
}
// returns the description of the flag
func (f *LogFlag) GetDesc() string {
if !f.Ok() {
return ""
}
return f.desc
}
// returns the description of the flag
func (f *LogFlag) GetDefault() bool {
if !f.Ok() {
return false
}
return f.orig
}
// register a variable name from a subsystem
// inspired by Alex Flint
// set the Default value at the time of registration
// this is what the current log.SetFlag() function should become
func NewFlag(name string, b bool, full, short, desc string) *LogFlag {
flagsMutex.Lock()
defer flagsMutex.Unlock()
f := new(LogFlag)
// Log(always, "log.SetFlag() ", full, short, name, b)
if allon {
f.b = true
} else {
f.b = b
}
f.orig = b
f.short = short
f.subsystem = full
f.name = name
f.desc = desc
flags = append(flags, f)
return f
}
func (f *LogFlag) SetBool(b bool) {
/*
if ! f.Ok() {return}
flagsMutex.Lock()
defer flagsMutex.Unlock()
*/
Info("Set() ", "("+f.subsystem+")", f.name, "=", f.b, ":", f.desc)
f.b = b
Info("Set() f.b is now", f.b)
}
|