55// This code may be copied and pasted into your microservice
66// and modified to your liking. Put it in a package called
77// log. A little copying is better than a little dependency.
8- //
98package log
109
1110import (
1211 "encoding/json"
1312 "fmt"
1413 "io"
1514 "os"
15+ "regexp"
16+ "sync"
1617 "time"
1718)
1819
1920// Line allows a log line to be embedded somewhere
2021type Line = line
2122
23+ type LevelInt int
24+
25+ type LogConfig struct {
26+ MinLevel LevelInt
27+ RegexPassthrough []string
28+ RegexEnabled bool
29+ DebugOn bool
30+ UpdatedAt time.Time
31+ }
32+
33+ const (
34+ LevelDebug LevelInt = iota + 1
35+ LevelInfo
36+ LevelWarn
37+ LevelError
38+ LevelFatal
39+ )
40+
2241var (
2342 // Service name (can be set in main or elsewhere)
2443 Service = os .Getenv ("SVC" )
@@ -34,18 +53,27 @@ var (
3453
3554 // Default is the level used when calling Printf and Fatalf
3655 Default = Info
56+
57+ Config = LogConfig {
58+ MinLevel : LevelDebug ,
59+ RegexPassthrough : []string {},
60+ RegexEnabled : false ,
61+ DebugOn : false ,
62+ UpdatedAt : time.Time {},
63+ }
64+ compiledRegex = []* regexp.Regexp {}
65+ setMutex = sync.Mutex {}
3766)
3867
3968var (
4069 // Info, Warn, and so forth are commonly encountered log "levels".
41- Info = line {Level : "info" }
42- Warn = line {Level : "warn" }
43- Error = line {Level : "error" }
44- Fatal = line {Level : "fatal" }
45-
46- // Debug is a special level, it is only printed if DebugOn is true
47- Debug = line {Level : "debug" }
48- DebugOn = false
70+ Info = line {Level : "info" , LevelInt : LevelInfo }
71+ Warn = line {Level : "warn" , LevelInt : LevelWarn }
72+ Error = line {Level : "error" , LevelInt : LevelError }
73+ Fatal = line {Level : "fatal" , LevelInt : LevelFatal }
74+
75+ // Debug is a special level, it is only printed if Config.DebugOn is true
76+ Debug = line {Level : "debug" , LevelInt : LevelDebug }
4977)
5078
5179var stderr = io .Writer (os .Stderr )
@@ -65,8 +93,9 @@ func SetOutput(w io.Writer) (old io.Writer) {
6593type line struct {
6694 fn func (line ) line
6795 fields
68- Level string
69- msg string
96+ Level string
97+ LevelInt LevelInt
98+ msg string
7099}
71100
72101// Printf attaches the formatted message to line and outputs
@@ -81,8 +110,13 @@ type line struct {
81110//
82111// Prefer log.Error.F() to log.Error.Printf() unless using Add
83112func (l line ) Printf (f string , v ... interface {}) {
84- if l .Level == Debug .Level && ! DebugOn {
85- return
113+ checkDebug := l .Level == Debug .Level && ! Config .DebugOn
114+ checkMinLevel := l .LevelInt < Config .MinLevel
115+ if checkDebug || checkMinLevel {
116+ // check to see if message matches any regex to allow message to be printed
117+ if ! RegexPassthrough (f , v ... ) {
118+ return
119+ }
86120 }
87121 fmt .Fprintln (stderr , l .Msg (f , v ... ).String ())
88122 if l .Level == "fatal" {
@@ -224,8 +258,8 @@ type trapme string
224258// not affected. Trap calls os.Exit(1) if the panic occured from these
225259// functions.
226260//
227- // func main(){
228- // defer log.Trap()
261+ // func main(){
262+ // defer log.Trap()
229263//
230264// }
231265func Trap () {
@@ -245,3 +279,33 @@ func zero(v interface{}) bool {
245279 }
246280 return len (t ) == 0
247281}
282+
283+ func SetLogConfig (config LogConfig ) error {
284+ setMutex .Lock ()
285+ defer setMutex .Unlock ()
286+ Config = config
287+ // compile the regexes
288+ for _ , exp := range config .RegexPassthrough {
289+ reg , err := regexp .Compile (exp )
290+ if err != nil {
291+ return err
292+ }
293+ compiledRegex = append (compiledRegex , reg )
294+ }
295+ return nil
296+ }
297+
298+ func RegexPassthrough (f string , v ... interface {}) bool {
299+ if ! Config .RegexEnabled {
300+ return false
301+ }
302+ setMutex .Lock ()
303+ defer setMutex .Unlock ()
304+ msg := fmt .Sprintf (f , v ... )
305+ for _ , reg := range compiledRegex {
306+ if reg .MatchString (msg ) {
307+ return true
308+ }
309+ }
310+ return false
311+ }
0 commit comments