github.com/newrelic/go-agent@v3.26.0+incompatible/internal/logger/logger.go (about) 1 // Copyright 2020 New Relic Corporation. All rights reserved. 2 // SPDX-License-Identifier: Apache-2.0 3 4 package logger 5 6 import ( 7 "encoding/json" 8 "fmt" 9 "io" 10 "log" 11 "os" 12 ) 13 14 // Logger matches newrelic.Logger to allow implementations to be passed to 15 // internal packages. 16 type Logger interface { 17 Error(msg string, context map[string]interface{}) 18 Warn(msg string, context map[string]interface{}) 19 Info(msg string, context map[string]interface{}) 20 Debug(msg string, context map[string]interface{}) 21 DebugEnabled() bool 22 } 23 24 // ShimLogger implements Logger and does nothing. 25 type ShimLogger struct { 26 // IsDebugEnabled is useful as it allows DebugEnabled code paths to be 27 // tested. 28 IsDebugEnabled bool 29 } 30 31 // Error allows ShimLogger to implement Logger. 32 func (s ShimLogger) Error(string, map[string]interface{}) {} 33 34 // Warn allows ShimLogger to implement Logger. 35 func (s ShimLogger) Warn(string, map[string]interface{}) {} 36 37 // Info allows ShimLogger to implement Logger. 38 func (s ShimLogger) Info(string, map[string]interface{}) {} 39 40 // Debug allows ShimLogger to implement Logger. 41 func (s ShimLogger) Debug(string, map[string]interface{}) {} 42 43 // DebugEnabled allows ShimLogger to implement Logger. 44 func (s ShimLogger) DebugEnabled() bool { return s.IsDebugEnabled } 45 46 type logFile struct { 47 l *log.Logger 48 doDebug bool 49 } 50 51 // New creates a basic Logger. 52 func New(w io.Writer, doDebug bool) Logger { 53 return &logFile{ 54 l: log.New(w, logPid, logFlags), 55 doDebug: doDebug, 56 } 57 } 58 59 const logFlags = log.Ldate | log.Ltime | log.Lmicroseconds 60 61 var ( 62 logPid = fmt.Sprintf("(%d) ", os.Getpid()) 63 ) 64 65 func (f *logFile) fire(level, msg string, ctx map[string]interface{}) { 66 js, err := json.Marshal(struct { 67 Level string `json:"level"` 68 Event string `json:"msg"` 69 Context map[string]interface{} `json:"context"` 70 }{ 71 level, 72 msg, 73 ctx, 74 }) 75 if nil == err { 76 f.l.Print(string(js)) 77 } else { 78 f.l.Printf("unable to marshal log entry: %v", err) 79 } 80 } 81 82 func (f *logFile) Error(msg string, ctx map[string]interface{}) { 83 f.fire("error", msg, ctx) 84 } 85 func (f *logFile) Warn(msg string, ctx map[string]interface{}) { 86 f.fire("warn", msg, ctx) 87 } 88 func (f *logFile) Info(msg string, ctx map[string]interface{}) { 89 f.fire("info", msg, ctx) 90 } 91 func (f *logFile) Debug(msg string, ctx map[string]interface{}) { 92 if f.doDebug { 93 f.fire("debug", msg, ctx) 94 } 95 } 96 func (f *logFile) DebugEnabled() bool { return f.doDebug }