...

Source file src/github.com/go-logr/stdr/stdr.go

Documentation: github.com/go-logr/stdr

     1  /*
     2  Copyright 2019 The logr Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  // Package stdr implements github.com/go-logr/logr.Logger in terms of
    18  // Go's standard log package.
    19  package stdr
    20  
    21  import (
    22  	"log"
    23  	"os"
    24  
    25  	"github.com/go-logr/logr"
    26  	"github.com/go-logr/logr/funcr"
    27  )
    28  
    29  // The global verbosity level.  See SetVerbosity().
    30  var globalVerbosity int
    31  
    32  // SetVerbosity sets the global level against which all info logs will be
    33  // compared.  If this is greater than or equal to the "V" of the logger, the
    34  // message will be logged.  A higher value here means more logs will be written.
    35  // The previous verbosity value is returned.  This is not concurrent-safe -
    36  // callers must be sure to call it from only one goroutine.
    37  func SetVerbosity(v int) int {
    38  	old := globalVerbosity
    39  	globalVerbosity = v
    40  	return old
    41  }
    42  
    43  // New returns a logr.Logger which is implemented by Go's standard log package,
    44  // or something like it.  If std is nil, this will use a default logger
    45  // instead.
    46  //
    47  // Example: stdr.New(log.New(os.Stderr, "", log.LstdFlags|log.Lshortfile)))
    48  func New(std StdLogger) logr.Logger {
    49  	return NewWithOptions(std, Options{})
    50  }
    51  
    52  // NewWithOptions returns a logr.Logger which is implemented by Go's standard
    53  // log package, or something like it.  See New for details.
    54  func NewWithOptions(std StdLogger, opts Options) logr.Logger {
    55  	if std == nil {
    56  		// Go's log.Default() is only available in 1.16 and higher.
    57  		std = log.New(os.Stderr, "", log.LstdFlags)
    58  	}
    59  
    60  	if opts.Depth < 0 {
    61  		opts.Depth = 0
    62  	}
    63  
    64  	fopts := funcr.Options{
    65  		LogCaller: funcr.MessageClass(opts.LogCaller),
    66  	}
    67  
    68  	sl := &logger{
    69  		Formatter: funcr.NewFormatter(fopts),
    70  		std:       std,
    71  	}
    72  
    73  	// For skipping our own logger.Info/Error.
    74  	sl.Formatter.AddCallDepth(1 + opts.Depth)
    75  
    76  	return logr.New(sl)
    77  }
    78  
    79  // Options carries parameters which influence the way logs are generated.
    80  type Options struct {
    81  	// Depth biases the assumed number of call frames to the "true" caller.
    82  	// This is useful when the calling code calls a function which then calls
    83  	// stdr (e.g. a logging shim to another API).  Values less than zero will
    84  	// be treated as zero.
    85  	Depth int
    86  
    87  	// LogCaller tells stdr to add a "caller" key to some or all log lines.
    88  	// Go's log package has options to log this natively, too.
    89  	LogCaller MessageClass
    90  
    91  	// TODO: add an option to log the date/time
    92  }
    93  
    94  // MessageClass indicates which category or categories of messages to consider.
    95  type MessageClass int
    96  
    97  const (
    98  	// None ignores all message classes.
    99  	None MessageClass = iota
   100  	// All considers all message classes.
   101  	All
   102  	// Info only considers info messages.
   103  	Info
   104  	// Error only considers error messages.
   105  	Error
   106  )
   107  
   108  // StdLogger is the subset of the Go stdlib log.Logger API that is needed for
   109  // this adapter.
   110  type StdLogger interface {
   111  	// Output is the same as log.Output and log.Logger.Output.
   112  	Output(calldepth int, logline string) error
   113  }
   114  
   115  type logger struct {
   116  	funcr.Formatter
   117  	std StdLogger
   118  }
   119  
   120  var _ logr.LogSink = &logger{}
   121  var _ logr.CallDepthLogSink = &logger{}
   122  
   123  func (l logger) Enabled(level int) bool {
   124  	return globalVerbosity >= level
   125  }
   126  
   127  func (l logger) Info(level int, msg string, kvList ...interface{}) {
   128  	prefix, args := l.FormatInfo(level, msg, kvList)
   129  	if prefix != "" {
   130  		args = prefix + ": " + args
   131  	}
   132  	_ = l.std.Output(l.Formatter.GetDepth()+1, args)
   133  }
   134  
   135  func (l logger) Error(err error, msg string, kvList ...interface{}) {
   136  	prefix, args := l.FormatError(err, msg, kvList)
   137  	if prefix != "" {
   138  		args = prefix + ": " + args
   139  	}
   140  	_ = l.std.Output(l.Formatter.GetDepth()+1, args)
   141  }
   142  
   143  func (l logger) WithName(name string) logr.LogSink {
   144  	l.Formatter.AddName(name)
   145  	return &l
   146  }
   147  
   148  func (l logger) WithValues(kvList ...interface{}) logr.LogSink {
   149  	l.Formatter.AddValues(kvList)
   150  	return &l
   151  }
   152  
   153  func (l logger) WithCallDepth(depth int) logr.LogSink {
   154  	l.Formatter.AddCallDepth(depth)
   155  	return &l
   156  }
   157  
   158  // Underlier exposes access to the underlying logging implementation.  Since
   159  // callers only have a logr.Logger, they have to know which implementation is
   160  // in use, so this interface is less of an abstraction and more of way to test
   161  // type conversion.
   162  type Underlier interface {
   163  	GetUnderlying() StdLogger
   164  }
   165  
   166  // GetUnderlying returns the StdLogger underneath this logger.  Since StdLogger
   167  // is itself an interface, the result may or may not be a Go log.Logger.
   168  func (l logger) GetUnderlying() StdLogger {
   169  	return l.std
   170  }
   171  

View as plain text