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 }