github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/logging/loggers/burrow_format_logger.go (about)

     1  // Copyright Monax Industries Limited
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package loggers
     5  
     6  import (
     7  	"encoding"
     8  	"encoding/json"
     9  	"fmt"
    10  	"sync"
    11  	"time"
    12  
    13  	"github.com/go-kit/kit/log"
    14  	"github.com/hyperledger/burrow/logging/structure"
    15  	"github.com/tmthrgd/go-hex"
    16  )
    17  
    18  // Logger that implements some formatting conventions for burrow and burrow-client
    19  // This is intended for applying consistent value formatting before the final 'output' logger;
    20  // we should avoid prematurely formatting values here if it is useful to let the output logger
    21  // decide how it wants to display values. Ideal candidates for 'early' formatting here are types that
    22  // we control and generic output loggers are unlikely to know about.
    23  type burrowFormatLogger struct {
    24  	sync.Mutex
    25  	logger  log.Logger
    26  	options opt
    27  }
    28  
    29  type opt byte
    30  
    31  func (o opt) enabled(q opt) bool {
    32  	return o&q > 0
    33  }
    34  
    35  const (
    36  	DefaultOptions opt = iota
    37  	StringifyValues
    38  )
    39  
    40  func NewBurrowFormatLogger(logger log.Logger, options ...opt) *burrowFormatLogger {
    41  	bfl := &burrowFormatLogger{logger: logger}
    42  	for _, option := range options {
    43  		bfl.options |= option
    44  	}
    45  	return bfl
    46  }
    47  
    48  var _ log.Logger = &burrowFormatLogger{}
    49  
    50  func (bfl *burrowFormatLogger) Log(keyvals ...interface{}) error {
    51  	if bfl.logger == nil {
    52  		return nil
    53  	}
    54  	keyvals, err := structure.MapKeyValues(keyvals,
    55  		func(key interface{}, value interface{}) (interface{}, interface{}) {
    56  			switch v := value.(type) {
    57  			case string, json.Marshaler, encoding.TextMarshaler:
    58  			case time.Time:
    59  				value = v.Format(time.RFC3339Nano)
    60  			case fmt.Stringer:
    61  				value = v.String()
    62  			case []byte:
    63  				value = hex.EncodeUpperToString(v)
    64  			}
    65  			if bfl.options.enabled(StringifyValues) {
    66  				value = structure.Stringify(value)
    67  			}
    68  			return structure.Stringify(key), value
    69  		})
    70  	if err != nil {
    71  		return err
    72  	}
    73  	bfl.Lock()
    74  	defer bfl.Unlock()
    75  	return bfl.logger.Log(keyvals...)
    76  }