...

Source file src/k8s.io/klog/v2/klog.go

Documentation: k8s.io/klog/v2

     1  // Go support for leveled logs, analogous to https://code.google.com/p/google-glog/
     2  //
     3  // Copyright 2013 Google Inc. All Rights Reserved.
     4  //
     5  // Licensed under the Apache License, Version 2.0 (the "License");
     6  // you may not use this file except in compliance with the License.
     7  // You may obtain a copy of the License at
     8  //
     9  //     http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing, software
    12  // distributed under the License is distributed on an "AS IS" BASIS,
    13  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  // See the License for the specific language governing permissions and
    15  // limitations under the License.
    16  
    17  // Package klog contains the following functionality:
    18  //
    19  //   - output routing as defined via command line flags ([InitFlags])
    20  //   - log formatting as text, either with a single, unstructured string ([Info], [Infof], etc.)
    21  //     or as a structured log entry with message and key/value pairs ([InfoS], etc.)
    22  //   - management of a go-logr [Logger] ([SetLogger], [Background], [TODO])
    23  //   - helper functions for logging values ([Format]) and managing the state of klog ([CaptureState], [State.Restore])
    24  //   - wrappers for [logr] APIs for contextual logging where the wrappers can
    25  //     be turned into no-ops ([EnableContextualLogging], [NewContext], [FromContext],
    26  //     [LoggerWithValues], [LoggerWithName]); if the ability to turn off
    27  //     contextual logging is not needed, then go-logr can also be used directly
    28  //   - type aliases for go-logr types to simplify imports in code which uses both (e.g. [Logger])
    29  //   - [k8s.io/klog/v2/textlogger]: a logger which uses the same formatting as klog log with
    30  //     simpler output routing; beware that it comes with its own command line flags
    31  //     and does not use the ones from klog
    32  //   - [k8s.io/klog/v2/ktesting]: per-test output in Go unit tests
    33  //   - [k8s.io/klog/v2/klogr]: a deprecated, standalone [logr.Logger] on top of the main klog package;
    34  //     use [Background] instead if klog output routing is needed, [k8s.io/klog/v2/textlogger] if not
    35  //   - [k8s.io/klog/v2/examples]: demos of this functionality
    36  //   - [k8s.io/klog/v2/test]: reusable tests for [logr.Logger] implementations
    37  //
    38  // Basic examples:
    39  //
    40  //	klog.Info("Prepare to repel boarders")
    41  //
    42  //	klog.Fatalf("Initialization failed: %s", err)
    43  //
    44  // See the documentation for the V function for an explanation of these examples:
    45  //
    46  //	if klog.V(2) {
    47  //		klog.Info("Starting transaction...")
    48  //	}
    49  //
    50  //	klog.V(2).Infoln("Processed", nItems, "elements")
    51  //
    52  // Log output is buffered and written periodically using Flush. Programs
    53  // should call Flush before exiting to guarantee all log output is written.
    54  //
    55  // By default, all log statements write to standard error.
    56  // This package provides several flags that modify this behavior.
    57  // As a result, flag.Parse must be called before any logging is done.
    58  //
    59  //		-logtostderr=true
    60  //			Logs are written to standard error instead of to files.
    61  //	             This shortcuts most of the usual output routing:
    62  //	             -alsologtostderr, -stderrthreshold and -log_dir have no
    63  //	             effect and output redirection at runtime with SetOutput is
    64  //	             ignored.
    65  //		-alsologtostderr=false
    66  //			Logs are written to standard error as well as to files.
    67  //		-stderrthreshold=ERROR
    68  //			Log events at or above this severity are logged to standard
    69  //			error as well as to files.
    70  //		-log_dir=""
    71  //			Log files will be written to this directory instead of the
    72  //			default temporary directory.
    73  //
    74  //		Other flags provide aids to debugging.
    75  //
    76  //		-log_backtrace_at=""
    77  //			When set to a file and line number holding a logging statement,
    78  //			such as
    79  //				-log_backtrace_at=gopherflakes.go:234
    80  //			a stack trace will be written to the Info log whenever execution
    81  //			hits that statement. (Unlike with -vmodule, the ".go" must be
    82  //			present.)
    83  //		-v=0
    84  //			Enable V-leveled logging at the specified level.
    85  //		-vmodule=""
    86  //			The syntax of the argument is a comma-separated list of pattern=N,
    87  //			where pattern is a literal file name (minus the ".go" suffix) or
    88  //			"glob" pattern and N is a V level. For instance,
    89  //				-vmodule=gopher*=3
    90  //			sets the V level to 3 in all Go files whose names begin "gopher".
    91  package klog
    92  
    93  import (
    94  	"bufio"
    95  	"bytes"
    96  	"errors"
    97  	"flag"
    98  	"fmt"
    99  	"io"
   100  	stdLog "log"
   101  	"math"
   102  	"os"
   103  	"path/filepath"
   104  	"runtime"
   105  	"strconv"
   106  	"strings"
   107  	"sync"
   108  	"sync/atomic"
   109  	"time"
   110  
   111  	"k8s.io/klog/v2/internal/buffer"
   112  	"k8s.io/klog/v2/internal/clock"
   113  	"k8s.io/klog/v2/internal/dbg"
   114  	"k8s.io/klog/v2/internal/serialize"
   115  	"k8s.io/klog/v2/internal/severity"
   116  )
   117  
   118  // severityValue identifies the sort of log: info, warning etc. It also implements
   119  // the flag.Value interface. The -stderrthreshold flag is of type severity and
   120  // should be modified only through the flag.Value interface. The values match
   121  // the corresponding constants in C++.
   122  type severityValue struct {
   123  	severity.Severity
   124  }
   125  
   126  // get returns the value of the severity.
   127  func (s *severityValue) get() severity.Severity {
   128  	return severity.Severity(atomic.LoadInt32((*int32)(&s.Severity)))
   129  }
   130  
   131  // set sets the value of the severity.
   132  func (s *severityValue) set(val severity.Severity) {
   133  	atomic.StoreInt32((*int32)(&s.Severity), int32(val))
   134  }
   135  
   136  // String is part of the flag.Value interface.
   137  func (s *severityValue) String() string {
   138  	return strconv.FormatInt(int64(s.Severity), 10)
   139  }
   140  
   141  // Get is part of the flag.Getter interface.
   142  func (s *severityValue) Get() interface{} {
   143  	return s.Severity
   144  }
   145  
   146  // Set is part of the flag.Value interface.
   147  func (s *severityValue) Set(value string) error {
   148  	var threshold severity.Severity
   149  	// Is it a known name?
   150  	if v, ok := severity.ByName(value); ok {
   151  		threshold = v
   152  	} else {
   153  		v, err := strconv.ParseInt(value, 10, 32)
   154  		if err != nil {
   155  			return err
   156  		}
   157  		threshold = severity.Severity(v)
   158  	}
   159  	logging.stderrThreshold.set(threshold)
   160  	return nil
   161  }
   162  
   163  // OutputStats tracks the number of output lines and bytes written.
   164  type OutputStats struct {
   165  	lines int64
   166  	bytes int64
   167  }
   168  
   169  // Lines returns the number of lines written.
   170  func (s *OutputStats) Lines() int64 {
   171  	return atomic.LoadInt64(&s.lines)
   172  }
   173  
   174  // Bytes returns the number of bytes written.
   175  func (s *OutputStats) Bytes() int64 {
   176  	return atomic.LoadInt64(&s.bytes)
   177  }
   178  
   179  // Stats tracks the number of lines of output and number of bytes
   180  // per severity level. Values must be read with atomic.LoadInt64.
   181  var Stats struct {
   182  	Info, Warning, Error OutputStats
   183  }
   184  
   185  var severityStats = [severity.NumSeverity]*OutputStats{
   186  	severity.InfoLog:    &Stats.Info,
   187  	severity.WarningLog: &Stats.Warning,
   188  	severity.ErrorLog:   &Stats.Error,
   189  }
   190  
   191  // Level is exported because it appears in the arguments to V and is
   192  // the type of the v flag, which can be set programmatically.
   193  // It's a distinct type because we want to discriminate it from logType.
   194  // Variables of type level are only changed under logging.mu.
   195  // The -v flag is read only with atomic ops, so the state of the logging
   196  // module is consistent.
   197  
   198  // Level is treated as a sync/atomic int32.
   199  
   200  // Level specifies a level of verbosity for V logs. *Level implements
   201  // flag.Value; the -v flag is of type Level and should be modified
   202  // only through the flag.Value interface.
   203  type Level int32
   204  
   205  // get returns the value of the Level.
   206  func (l *Level) get() Level {
   207  	return Level(atomic.LoadInt32((*int32)(l)))
   208  }
   209  
   210  // set sets the value of the Level.
   211  func (l *Level) set(val Level) {
   212  	atomic.StoreInt32((*int32)(l), int32(val))
   213  }
   214  
   215  // String is part of the flag.Value interface.
   216  func (l *Level) String() string {
   217  	return strconv.FormatInt(int64(*l), 10)
   218  }
   219  
   220  // Get is part of the flag.Getter interface.
   221  func (l *Level) Get() interface{} {
   222  	return *l
   223  }
   224  
   225  // Set is part of the flag.Value interface.
   226  func (l *Level) Set(value string) error {
   227  	v, err := strconv.ParseInt(value, 10, 32)
   228  	if err != nil {
   229  		return err
   230  	}
   231  	logging.mu.Lock()
   232  	defer logging.mu.Unlock()
   233  	logging.setVState(Level(v), logging.vmodule.filter, false)
   234  	return nil
   235  }
   236  
   237  // moduleSpec represents the setting of the -vmodule flag.
   238  type moduleSpec struct {
   239  	filter []modulePat
   240  }
   241  
   242  // modulePat contains a filter for the -vmodule flag.
   243  // It holds a verbosity level and a file pattern to match.
   244  type modulePat struct {
   245  	pattern string
   246  	literal bool // The pattern is a literal string
   247  	level   Level
   248  }
   249  
   250  // match reports whether the file matches the pattern. It uses a string
   251  // comparison if the pattern contains no metacharacters.
   252  func (m *modulePat) match(file string) bool {
   253  	if m.literal {
   254  		return file == m.pattern
   255  	}
   256  	match, _ := filepath.Match(m.pattern, file)
   257  	return match
   258  }
   259  
   260  func (m *moduleSpec) String() string {
   261  	// Lock because the type is not atomic. TODO: clean this up.
   262  	logging.mu.Lock()
   263  	defer logging.mu.Unlock()
   264  	return m.serialize()
   265  }
   266  
   267  func (m *moduleSpec) serialize() string {
   268  	var b bytes.Buffer
   269  	for i, f := range m.filter {
   270  		if i > 0 {
   271  			b.WriteRune(',')
   272  		}
   273  		fmt.Fprintf(&b, "%s=%d", f.pattern, f.level)
   274  	}
   275  	return b.String()
   276  }
   277  
   278  // Get is part of the (Go 1.2)  flag.Getter interface. It always returns nil for this flag type since the
   279  // struct is not exported.
   280  func (m *moduleSpec) Get() interface{} {
   281  	return nil
   282  }
   283  
   284  var errVmoduleSyntax = errors.New("syntax error: expect comma-separated list of filename=N")
   285  
   286  // Set will sets module value
   287  // Syntax: -vmodule=recordio=2,file=1,gfs*=3
   288  func (m *moduleSpec) Set(value string) error {
   289  	filter, err := parseModuleSpec(value)
   290  	if err != nil {
   291  		return err
   292  	}
   293  	logging.mu.Lock()
   294  	defer logging.mu.Unlock()
   295  	logging.setVState(logging.verbosity, filter, true)
   296  	return nil
   297  }
   298  
   299  func parseModuleSpec(value string) ([]modulePat, error) {
   300  	var filter []modulePat
   301  	for _, pat := range strings.Split(value, ",") {
   302  		if len(pat) == 0 {
   303  			// Empty strings such as from a trailing comma can be ignored.
   304  			continue
   305  		}
   306  		patLev := strings.Split(pat, "=")
   307  		if len(patLev) != 2 || len(patLev[0]) == 0 || len(patLev[1]) == 0 {
   308  			return nil, errVmoduleSyntax
   309  		}
   310  		pattern := patLev[0]
   311  		v, err := strconv.ParseInt(patLev[1], 10, 32)
   312  		if err != nil {
   313  			return nil, errors.New("syntax error: expect comma-separated list of filename=N")
   314  		}
   315  		if v < 0 {
   316  			return nil, errors.New("negative value for vmodule level")
   317  		}
   318  		if v == 0 {
   319  			continue // Ignore. It's harmless but no point in paying the overhead.
   320  		}
   321  		// TODO: check syntax of filter?
   322  		filter = append(filter, modulePat{pattern, isLiteral(pattern), Level(v)})
   323  	}
   324  	return filter, nil
   325  }
   326  
   327  // isLiteral reports whether the pattern is a literal string, that is, has no metacharacters
   328  // that require filepath.Match to be called to match the pattern.
   329  func isLiteral(pattern string) bool {
   330  	return !strings.ContainsAny(pattern, `\*?[]`)
   331  }
   332  
   333  // traceLocation represents the setting of the -log_backtrace_at flag.
   334  type traceLocation struct {
   335  	file string
   336  	line int
   337  }
   338  
   339  // isSet reports whether the trace location has been specified.
   340  // logging.mu is held.
   341  func (t *traceLocation) isSet() bool {
   342  	return t.line > 0
   343  }
   344  
   345  // match reports whether the specified file and line matches the trace location.
   346  // The argument file name is the full path, not the basename specified in the flag.
   347  // logging.mu is held.
   348  func (t *traceLocation) match(file string, line int) bool {
   349  	if t.line != line {
   350  		return false
   351  	}
   352  	if i := strings.LastIndex(file, "/"); i >= 0 {
   353  		file = file[i+1:]
   354  	}
   355  	return t.file == file
   356  }
   357  
   358  func (t *traceLocation) String() string {
   359  	// Lock because the type is not atomic. TODO: clean this up.
   360  	logging.mu.Lock()
   361  	defer logging.mu.Unlock()
   362  	return fmt.Sprintf("%s:%d", t.file, t.line)
   363  }
   364  
   365  // Get is part of the (Go 1.2) flag.Getter interface. It always returns nil for this flag type since the
   366  // struct is not exported
   367  func (t *traceLocation) Get() interface{} {
   368  	return nil
   369  }
   370  
   371  var errTraceSyntax = errors.New("syntax error: expect file.go:234")
   372  
   373  // Set will sets backtrace value
   374  // Syntax: -log_backtrace_at=gopherflakes.go:234
   375  // Note that unlike vmodule the file extension is included here.
   376  func (t *traceLocation) Set(value string) error {
   377  	if value == "" {
   378  		// Unset.
   379  		logging.mu.Lock()
   380  		defer logging.mu.Unlock()
   381  		t.line = 0
   382  		t.file = ""
   383  		return nil
   384  	}
   385  	fields := strings.Split(value, ":")
   386  	if len(fields) != 2 {
   387  		return errTraceSyntax
   388  	}
   389  	file, line := fields[0], fields[1]
   390  	if !strings.Contains(file, ".") {
   391  		return errTraceSyntax
   392  	}
   393  	v, err := strconv.Atoi(line)
   394  	if err != nil {
   395  		return errTraceSyntax
   396  	}
   397  	if v <= 0 {
   398  		return errors.New("negative or zero value for level")
   399  	}
   400  	logging.mu.Lock()
   401  	defer logging.mu.Unlock()
   402  	t.line = v
   403  	t.file = file
   404  	return nil
   405  }
   406  
   407  var logging loggingT
   408  var commandLine flag.FlagSet
   409  
   410  // init sets up the defaults and creates command line flags.
   411  func init() {
   412  	commandLine.StringVar(&logging.logDir, "log_dir", "", "If non-empty, write log files in this directory (no effect when -logtostderr=true)")
   413  	commandLine.StringVar(&logging.logFile, "log_file", "", "If non-empty, use this log file (no effect when -logtostderr=true)")
   414  	commandLine.Uint64Var(&logging.logFileMaxSizeMB, "log_file_max_size", 1800,
   415  		"Defines the maximum size a log file can grow to (no effect when -logtostderr=true). Unit is megabytes. "+
   416  			"If the value is 0, the maximum file size is unlimited.")
   417  	commandLine.BoolVar(&logging.toStderr, "logtostderr", true, "log to standard error instead of files")
   418  	commandLine.BoolVar(&logging.alsoToStderr, "alsologtostderr", false, "log to standard error as well as files (no effect when -logtostderr=true)")
   419  	logging.setVState(0, nil, false)
   420  	commandLine.Var(&logging.verbosity, "v", "number for the log level verbosity")
   421  	commandLine.BoolVar(&logging.addDirHeader, "add_dir_header", false, "If true, adds the file directory to the header of the log messages")
   422  	commandLine.BoolVar(&logging.skipHeaders, "skip_headers", false, "If true, avoid header prefixes in the log messages")
   423  	commandLine.BoolVar(&logging.oneOutput, "one_output", false, "If true, only write logs to their native severity level (vs also writing to each lower severity level; no effect when -logtostderr=true)")
   424  	commandLine.BoolVar(&logging.skipLogHeaders, "skip_log_headers", false, "If true, avoid headers when opening log files (no effect when -logtostderr=true)")
   425  	logging.stderrThreshold = severityValue{
   426  		Severity: severity.ErrorLog, // Default stderrThreshold is ERROR.
   427  	}
   428  	commandLine.Var(&logging.stderrThreshold, "stderrthreshold", "logs at or above this threshold go to stderr when writing to files and stderr (no effect when -logtostderr=true or -alsologtostderr=true)")
   429  	commandLine.Var(&logging.vmodule, "vmodule", "comma-separated list of pattern=N settings for file-filtered logging")
   430  	commandLine.Var(&logging.traceLocation, "log_backtrace_at", "when logging hits line file:N, emit a stack trace")
   431  
   432  	logging.settings.contextualLoggingEnabled = true
   433  	logging.flushD = newFlushDaemon(logging.lockAndFlushAll, nil)
   434  }
   435  
   436  // InitFlags is for explicitly initializing the flags.
   437  // It may get called repeatedly for different flagsets, but not
   438  // twice for the same one. May get called concurrently
   439  // to other goroutines using klog. However, only some flags
   440  // may get set concurrently (see implementation).
   441  func InitFlags(flagset *flag.FlagSet) {
   442  	if flagset == nil {
   443  		flagset = flag.CommandLine
   444  	}
   445  
   446  	commandLine.VisitAll(func(f *flag.Flag) {
   447  		flagset.Var(f.Value, f.Name, f.Usage)
   448  	})
   449  }
   450  
   451  // Flush flushes all pending log I/O.
   452  func Flush() {
   453  	logging.lockAndFlushAll()
   454  }
   455  
   456  // settings collects global settings.
   457  type settings struct {
   458  	// contextualLoggingEnabled controls whether contextual logging is
   459  	// active. Disabling it may have some small performance benefit.
   460  	contextualLoggingEnabled bool
   461  
   462  	// logger is the global Logger chosen by users of klog, nil if
   463  	// none is available.
   464  	logger *logWriter
   465  
   466  	// loggerOptions contains the options that were supplied for
   467  	// globalLogger.
   468  	loggerOptions loggerOptions
   469  
   470  	// Boolean flags. Not handled atomically because the flag.Value interface
   471  	// does not let us avoid the =true, and that shorthand is necessary for
   472  	// compatibility. TODO: does this matter enough to fix? Seems unlikely.
   473  	toStderr     bool // The -logtostderr flag.
   474  	alsoToStderr bool // The -alsologtostderr flag.
   475  
   476  	// Level flag. Handled atomically.
   477  	stderrThreshold severityValue // The -stderrthreshold flag.
   478  
   479  	// Access to all of the following fields must be protected via a mutex.
   480  
   481  	// file holds writer for each of the log types.
   482  	file [severity.NumSeverity]io.Writer
   483  	// flushInterval is the interval for periodic flushing. If zero,
   484  	// the global default will be used.
   485  	flushInterval time.Duration
   486  
   487  	// filterLength stores the length of the vmodule filter chain. If greater
   488  	// than zero, it means vmodule is enabled. It may be read safely
   489  	// using sync.LoadInt32, but is only modified under mu.
   490  	filterLength int32
   491  	// traceLocation is the state of the -log_backtrace_at flag.
   492  	traceLocation traceLocation
   493  	// These flags are modified only under lock, although verbosity may be fetched
   494  	// safely using atomic.LoadInt32.
   495  	vmodule   moduleSpec // The state of the -vmodule flag.
   496  	verbosity Level      // V logging level, the value of the -v flag/
   497  
   498  	// If non-empty, overrides the choice of directory in which to write logs.
   499  	// See createLogDirs for the full list of possible destinations.
   500  	logDir string
   501  
   502  	// If non-empty, specifies the path of the file to write logs. mutually exclusive
   503  	// with the log_dir option.
   504  	logFile string
   505  
   506  	// When logFile is specified, this limiter makes sure the logFile won't exceeds a certain size. When exceeds, the
   507  	// logFile will be cleaned up. If this value is 0, no size limitation will be applied to logFile.
   508  	logFileMaxSizeMB uint64
   509  
   510  	// If true, do not add the prefix headers, useful when used with SetOutput
   511  	skipHeaders bool
   512  
   513  	// If true, do not add the headers to log files
   514  	skipLogHeaders bool
   515  
   516  	// If true, add the file directory to the header
   517  	addDirHeader bool
   518  
   519  	// If true, messages will not be propagated to lower severity log levels
   520  	oneOutput bool
   521  
   522  	// If set, all output will be filtered through the filter.
   523  	filter LogFilter
   524  }
   525  
   526  // deepCopy creates a copy that doesn't share anything with the original
   527  // instance.
   528  func (s settings) deepCopy() settings {
   529  	// vmodule is a slice and would be shared, so we have copy it.
   530  	filter := make([]modulePat, len(s.vmodule.filter))
   531  	copy(filter, s.vmodule.filter)
   532  	s.vmodule.filter = filter
   533  
   534  	if s.logger != nil {
   535  		logger := *s.logger
   536  		s.logger = &logger
   537  	}
   538  
   539  	return s
   540  }
   541  
   542  // loggingT collects all the global state of the logging setup.
   543  type loggingT struct {
   544  	settings
   545  
   546  	// flushD holds a flushDaemon that frequently flushes log file buffers.
   547  	// Uses its own mutex.
   548  	flushD *flushDaemon
   549  
   550  	// mu protects the remaining elements of this structure and the fields
   551  	// in settingsT which need a mutex lock.
   552  	mu sync.Mutex
   553  
   554  	// pcs is used in V to avoid an allocation when computing the caller's PC.
   555  	pcs [1]uintptr
   556  	// vmap is a cache of the V Level for each V() call site, identified by PC.
   557  	// It is wiped whenever the vmodule flag changes state.
   558  	vmap map[uintptr]Level
   559  }
   560  
   561  // setVState sets a consistent state for V logging.
   562  // l.mu is held.
   563  func (l *loggingT) setVState(verbosity Level, filter []modulePat, setFilter bool) {
   564  	// Turn verbosity off so V will not fire while we are in transition.
   565  	l.verbosity.set(0)
   566  	// Ditto for filter length.
   567  	atomic.StoreInt32(&l.filterLength, 0)
   568  
   569  	// Set the new filters and wipe the pc->Level map if the filter has changed.
   570  	if setFilter {
   571  		l.vmodule.filter = filter
   572  		l.vmap = make(map[uintptr]Level)
   573  	}
   574  
   575  	// Things are consistent now, so enable filtering and verbosity.
   576  	// They are enabled in order opposite to that in V.
   577  	atomic.StoreInt32(&l.filterLength, int32(len(filter)))
   578  	l.verbosity.set(verbosity)
   579  }
   580  
   581  var timeNow = time.Now // Stubbed out for testing.
   582  
   583  // CaptureState gathers information about all current klog settings.
   584  // The result can be used to restore those settings.
   585  func CaptureState() State {
   586  	logging.mu.Lock()
   587  	defer logging.mu.Unlock()
   588  	return &state{
   589  		settings:      logging.settings.deepCopy(),
   590  		flushDRunning: logging.flushD.isRunning(),
   591  		maxSize:       MaxSize,
   592  	}
   593  }
   594  
   595  // State stores a snapshot of klog settings. It gets created with CaptureState
   596  // and can be used to restore the entire state. Modifying individual settings
   597  // is supported via the command line flags.
   598  type State interface {
   599  	// Restore restore the entire state. It may get called more than once.
   600  	Restore()
   601  }
   602  
   603  type state struct {
   604  	settings
   605  
   606  	flushDRunning bool
   607  	maxSize       uint64
   608  }
   609  
   610  func (s *state) Restore() {
   611  	// This needs to be done before mutex locking.
   612  	if s.flushDRunning && !logging.flushD.isRunning() {
   613  		// This is not quite accurate: StartFlushDaemon might
   614  		// have been called with some different interval.
   615  		interval := s.flushInterval
   616  		if interval == 0 {
   617  			interval = flushInterval
   618  		}
   619  		logging.flushD.run(interval)
   620  	} else if !s.flushDRunning && logging.flushD.isRunning() {
   621  		logging.flushD.stop()
   622  	}
   623  
   624  	logging.mu.Lock()
   625  	defer logging.mu.Unlock()
   626  
   627  	logging.settings = s.settings
   628  	logging.setVState(s.verbosity, s.vmodule.filter, true)
   629  	MaxSize = s.maxSize
   630  }
   631  
   632  /*
   633  header formats a log header as defined by the C++ implementation.
   634  It returns a buffer containing the formatted header and the user's file and line number.
   635  The depth specifies how many stack frames above lives the source line to be identified in the log message.
   636  
   637  Log lines have this form:
   638  
   639  	Lmmdd hh:mm:ss.uuuuuu threadid file:line] msg...
   640  
   641  where the fields are defined as follows:
   642  
   643  	L                A single character, representing the log level (eg 'I' for INFO)
   644  	mm               The month (zero padded; ie May is '05')
   645  	dd               The day (zero padded)
   646  	hh:mm:ss.uuuuuu  Time in hours, minutes and fractional seconds
   647  	threadid         The space-padded thread ID as returned by GetTID()
   648  	file             The file name
   649  	line             The line number
   650  	msg              The user-supplied message
   651  */
   652  func (l *loggingT) header(s severity.Severity, depth int) (*buffer.Buffer, string, int) {
   653  	_, file, line, ok := runtime.Caller(3 + depth)
   654  	if !ok {
   655  		file = "???"
   656  		line = 1
   657  	} else {
   658  		if slash := strings.LastIndex(file, "/"); slash >= 0 {
   659  			path := file
   660  			file = path[slash+1:]
   661  			if l.addDirHeader {
   662  				if dirsep := strings.LastIndex(path[:slash], "/"); dirsep >= 0 {
   663  					file = path[dirsep+1:]
   664  				}
   665  			}
   666  		}
   667  	}
   668  	return l.formatHeader(s, file, line, timeNow()), file, line
   669  }
   670  
   671  // formatHeader formats a log header using the provided file name and line number.
   672  func (l *loggingT) formatHeader(s severity.Severity, file string, line int, now time.Time) *buffer.Buffer {
   673  	buf := buffer.GetBuffer()
   674  	if l.skipHeaders {
   675  		return buf
   676  	}
   677  	buf.FormatHeader(s, file, line, now)
   678  	return buf
   679  }
   680  
   681  func (l *loggingT) println(s severity.Severity, logger *logWriter, filter LogFilter, args ...interface{}) {
   682  	l.printlnDepth(s, logger, filter, 1, args...)
   683  }
   684  
   685  func (l *loggingT) printlnDepth(s severity.Severity, logger *logWriter, filter LogFilter, depth int, args ...interface{}) {
   686  	if false {
   687  		_ = fmt.Sprintln(args...) // cause vet to treat this function like fmt.Println
   688  	}
   689  
   690  	buf, file, line := l.header(s, depth)
   691  	// If a logger is set and doesn't support writing a formatted buffer,
   692  	// we clear the generated header as we rely on the backing
   693  	// logger implementation to print headers.
   694  	if logger != nil && logger.writeKlogBuffer == nil {
   695  		buffer.PutBuffer(buf)
   696  		buf = buffer.GetBuffer()
   697  	}
   698  	if filter != nil {
   699  		args = filter.Filter(args)
   700  	}
   701  	fmt.Fprintln(buf, args...)
   702  	l.output(s, logger, buf, depth, file, line, false)
   703  }
   704  
   705  func (l *loggingT) print(s severity.Severity, logger *logWriter, filter LogFilter, args ...interface{}) {
   706  	l.printDepth(s, logger, filter, 1, args...)
   707  }
   708  
   709  func (l *loggingT) printDepth(s severity.Severity, logger *logWriter, filter LogFilter, depth int, args ...interface{}) {
   710  	if false {
   711  		_ = fmt.Sprint(args...) //  // cause vet to treat this function like fmt.Print
   712  	}
   713  
   714  	buf, file, line := l.header(s, depth)
   715  	l.printWithInfos(buf, file, line, s, logger, filter, depth+1, args...)
   716  }
   717  
   718  func (l *loggingT) printWithInfos(buf *buffer.Buffer, file string, line int, s severity.Severity, logger *logWriter, filter LogFilter, depth int, args ...interface{}) {
   719  	// If a logger is set and doesn't support writing a formatted buffer,
   720  	// we clear the generated header as we rely on the backing
   721  	// logger implementation to print headers.
   722  	if logger != nil && logger.writeKlogBuffer == nil {
   723  		buffer.PutBuffer(buf)
   724  		buf = buffer.GetBuffer()
   725  	}
   726  	if filter != nil {
   727  		args = filter.Filter(args)
   728  	}
   729  	fmt.Fprint(buf, args...)
   730  	if buf.Len() == 0 || buf.Bytes()[buf.Len()-1] != '\n' {
   731  		buf.WriteByte('\n')
   732  	}
   733  	l.output(s, logger, buf, depth, file, line, false)
   734  }
   735  
   736  func (l *loggingT) printf(s severity.Severity, logger *logWriter, filter LogFilter, format string, args ...interface{}) {
   737  	l.printfDepth(s, logger, filter, 1, format, args...)
   738  }
   739  
   740  func (l *loggingT) printfDepth(s severity.Severity, logger *logWriter, filter LogFilter, depth int, format string, args ...interface{}) {
   741  	if false {
   742  		_ = fmt.Sprintf(format, args...) // cause vet to treat this function like fmt.Printf
   743  	}
   744  
   745  	buf, file, line := l.header(s, depth)
   746  	// If a logger is set and doesn't support writing a formatted buffer,
   747  	// we clear the generated header as we rely on the backing
   748  	// logger implementation to print headers.
   749  	if logger != nil && logger.writeKlogBuffer == nil {
   750  		buffer.PutBuffer(buf)
   751  		buf = buffer.GetBuffer()
   752  	}
   753  	if filter != nil {
   754  		format, args = filter.FilterF(format, args)
   755  	}
   756  	fmt.Fprintf(buf, format, args...)
   757  	if buf.Bytes()[buf.Len()-1] != '\n' {
   758  		buf.WriteByte('\n')
   759  	}
   760  	l.output(s, logger, buf, depth, file, line, false)
   761  }
   762  
   763  // printWithFileLine behaves like print but uses the provided file and line number.  If
   764  // alsoLogToStderr is true, the log message always appears on standard error; it
   765  // will also appear in the log file unless --logtostderr is set.
   766  func (l *loggingT) printWithFileLine(s severity.Severity, logger *logWriter, filter LogFilter, file string, line int, alsoToStderr bool, args ...interface{}) {
   767  	buf := l.formatHeader(s, file, line, timeNow())
   768  	// If a logger is set and doesn't support writing a formatted buffer,
   769  	// we clear the generated header as we rely on the backing
   770  	// logger implementation to print headers.
   771  	if logger != nil && logger.writeKlogBuffer == nil {
   772  		buffer.PutBuffer(buf)
   773  		buf = buffer.GetBuffer()
   774  	}
   775  	if filter != nil {
   776  		args = filter.Filter(args)
   777  	}
   778  	fmt.Fprint(buf, args...)
   779  	if buf.Bytes()[buf.Len()-1] != '\n' {
   780  		buf.WriteByte('\n')
   781  	}
   782  	l.output(s, logger, buf, 2 /* depth */, file, line, alsoToStderr)
   783  }
   784  
   785  // if logger is specified, will call logger.Error, otherwise output with logging module.
   786  func (l *loggingT) errorS(err error, logger *logWriter, filter LogFilter, depth int, msg string, keysAndValues ...interface{}) {
   787  	if filter != nil {
   788  		msg, keysAndValues = filter.FilterS(msg, keysAndValues)
   789  	}
   790  	if logger != nil {
   791  		logger.WithCallDepth(depth+2).Error(err, msg, keysAndValues...)
   792  		return
   793  	}
   794  	l.printS(err, severity.ErrorLog, depth+1, msg, keysAndValues...)
   795  }
   796  
   797  // if logger is specified, will call logger.Info, otherwise output with logging module.
   798  func (l *loggingT) infoS(logger *logWriter, filter LogFilter, depth int, msg string, keysAndValues ...interface{}) {
   799  	if filter != nil {
   800  		msg, keysAndValues = filter.FilterS(msg, keysAndValues)
   801  	}
   802  	if logger != nil {
   803  		logger.WithCallDepth(depth+2).Info(msg, keysAndValues...)
   804  		return
   805  	}
   806  	l.printS(nil, severity.InfoLog, depth+1, msg, keysAndValues...)
   807  }
   808  
   809  // printS is called from infoS and errorS if logger is not specified.
   810  // set log severity by s
   811  func (l *loggingT) printS(err error, s severity.Severity, depth int, msg string, keysAndValues ...interface{}) {
   812  	// Only create a new buffer if we don't have one cached.
   813  	b := buffer.GetBuffer()
   814  	// The message is always quoted, even if it contains line breaks.
   815  	// If developers want multi-line output, they should use a small, fixed
   816  	// message and put the multi-line output into a value.
   817  	b.WriteString(strconv.Quote(msg))
   818  	if err != nil {
   819  		serialize.KVListFormat(&b.Buffer, "err", err)
   820  	}
   821  	serialize.KVListFormat(&b.Buffer, keysAndValues...)
   822  	l.printDepth(s, nil, nil, depth+1, &b.Buffer)
   823  	// Make the buffer available for reuse.
   824  	buffer.PutBuffer(b)
   825  }
   826  
   827  // SetOutput sets the output destination for all severities
   828  func SetOutput(w io.Writer) {
   829  	logging.mu.Lock()
   830  	defer logging.mu.Unlock()
   831  	for s := severity.FatalLog; s >= severity.InfoLog; s-- {
   832  		logging.file[s] = w
   833  	}
   834  }
   835  
   836  // SetOutputBySeverity sets the output destination for specific severity
   837  func SetOutputBySeverity(name string, w io.Writer) {
   838  	logging.mu.Lock()
   839  	defer logging.mu.Unlock()
   840  	sev, ok := severity.ByName(name)
   841  	if !ok {
   842  		panic(fmt.Sprintf("SetOutputBySeverity(%q): unrecognized severity name", name))
   843  	}
   844  	logging.file[sev] = w
   845  }
   846  
   847  // LogToStderr sets whether to log exclusively to stderr, bypassing outputs
   848  func LogToStderr(stderr bool) {
   849  	logging.mu.Lock()
   850  	defer logging.mu.Unlock()
   851  
   852  	logging.toStderr = stderr
   853  }
   854  
   855  // output writes the data to the log files and releases the buffer.
   856  func (l *loggingT) output(s severity.Severity, logger *logWriter, buf *buffer.Buffer, depth int, file string, line int, alsoToStderr bool) {
   857  	var isLocked = true
   858  	l.mu.Lock()
   859  	defer func() {
   860  		if isLocked {
   861  			// Unlock before returning in case that it wasn't done already.
   862  			l.mu.Unlock()
   863  		}
   864  	}()
   865  
   866  	if l.traceLocation.isSet() {
   867  		if l.traceLocation.match(file, line) {
   868  			buf.Write(dbg.Stacks(false))
   869  		}
   870  	}
   871  	data := buf.Bytes()
   872  	if logger != nil {
   873  		if logger.writeKlogBuffer != nil {
   874  			logger.writeKlogBuffer(data)
   875  		} else {
   876  			if len(data) > 0 && data[len(data)-1] == '\n' {
   877  				data = data[:len(data)-1]
   878  			}
   879  			// TODO: set 'severity' and caller information as structured log info
   880  			// keysAndValues := []interface{}{"severity", severityName[s], "file", file, "line", line}
   881  			if s == severity.ErrorLog {
   882  				logger.WithCallDepth(depth+3).Error(nil, string(data))
   883  			} else {
   884  				logger.WithCallDepth(depth + 3).Info(string(data))
   885  			}
   886  		}
   887  	} else if l.toStderr {
   888  		os.Stderr.Write(data)
   889  	} else {
   890  		if alsoToStderr || l.alsoToStderr || s >= l.stderrThreshold.get() {
   891  			os.Stderr.Write(data)
   892  		}
   893  
   894  		if logging.logFile != "" {
   895  			// Since we are using a single log file, all of the items in l.file array
   896  			// will point to the same file, so just use one of them to write data.
   897  			if l.file[severity.InfoLog] == nil {
   898  				if err := l.createFiles(severity.InfoLog); err != nil {
   899  					os.Stderr.Write(data) // Make sure the message appears somewhere.
   900  					l.exit(err)
   901  				}
   902  			}
   903  			_, _ = l.file[severity.InfoLog].Write(data)
   904  		} else {
   905  			if l.file[s] == nil {
   906  				if err := l.createFiles(s); err != nil {
   907  					os.Stderr.Write(data) // Make sure the message appears somewhere.
   908  					l.exit(err)
   909  				}
   910  			}
   911  
   912  			if l.oneOutput {
   913  				_, _ = l.file[s].Write(data)
   914  			} else {
   915  				switch s {
   916  				case severity.FatalLog:
   917  					_, _ = l.file[severity.FatalLog].Write(data)
   918  					fallthrough
   919  				case severity.ErrorLog:
   920  					_, _ = l.file[severity.ErrorLog].Write(data)
   921  					fallthrough
   922  				case severity.WarningLog:
   923  					_, _ = l.file[severity.WarningLog].Write(data)
   924  					fallthrough
   925  				case severity.InfoLog:
   926  					_, _ = l.file[severity.InfoLog].Write(data)
   927  				}
   928  			}
   929  		}
   930  	}
   931  	if s == severity.FatalLog {
   932  		// If we got here via Exit rather than Fatal, print no stacks.
   933  		if atomic.LoadUint32(&fatalNoStacks) > 0 {
   934  			l.mu.Unlock()
   935  			isLocked = false
   936  			timeoutFlush(ExitFlushTimeout)
   937  			OsExit(1)
   938  		}
   939  		// Dump all goroutine stacks before exiting.
   940  		// First, make sure we see the trace for the current goroutine on standard error.
   941  		// If -logtostderr has been specified, the loop below will do that anyway
   942  		// as the first stack in the full dump.
   943  		if !l.toStderr {
   944  			os.Stderr.Write(dbg.Stacks(false))
   945  		}
   946  
   947  		// Write the stack trace for all goroutines to the files.
   948  		trace := dbg.Stacks(true)
   949  		logExitFunc = func(error) {} // If we get a write error, we'll still exit below.
   950  		for log := severity.FatalLog; log >= severity.InfoLog; log-- {
   951  			if f := l.file[log]; f != nil { // Can be nil if -logtostderr is set.
   952  				_, _ = f.Write(trace)
   953  			}
   954  		}
   955  		l.mu.Unlock()
   956  		isLocked = false
   957  		timeoutFlush(ExitFlushTimeout)
   958  		OsExit(255) // C++ uses -1, which is silly because it's anded with 255 anyway.
   959  	}
   960  	buffer.PutBuffer(buf)
   961  
   962  	if stats := severityStats[s]; stats != nil {
   963  		atomic.AddInt64(&stats.lines, 1)
   964  		atomic.AddInt64(&stats.bytes, int64(len(data)))
   965  	}
   966  }
   967  
   968  // logExitFunc provides a simple mechanism to override the default behavior
   969  // of exiting on error. Used in testing and to guarantee we reach a required exit
   970  // for fatal logs. Instead, exit could be a function rather than a method but that
   971  // would make its use clumsier.
   972  var logExitFunc func(error)
   973  
   974  // exit is called if there is trouble creating or writing log files.
   975  // It flushes the logs and exits the program; there's no point in hanging around.
   976  // l.mu is held.
   977  func (l *loggingT) exit(err error) {
   978  	fmt.Fprintf(os.Stderr, "log: exiting because of error: %s\n", err)
   979  	// If logExitFunc is set, we do that instead of exiting.
   980  	if logExitFunc != nil {
   981  		logExitFunc(err)
   982  		return
   983  	}
   984  	needToSync := l.flushAll()
   985  	l.syncAll(needToSync)
   986  	OsExit(2)
   987  }
   988  
   989  // syncBuffer joins a bufio.Writer to its underlying file, providing access to the
   990  // file's Sync method and providing a wrapper for the Write method that provides log
   991  // file rotation. There are conflicting methods, so the file cannot be embedded.
   992  // l.mu is held for all its methods.
   993  type syncBuffer struct {
   994  	logger *loggingT
   995  	*bufio.Writer
   996  	file     *os.File
   997  	sev      severity.Severity
   998  	nbytes   uint64 // The number of bytes written to this file
   999  	maxbytes uint64 // The max number of bytes this syncBuffer.file can hold before cleaning up.
  1000  }
  1001  
  1002  // CalculateMaxSize returns the real max size in bytes after considering the default max size and the flag options.
  1003  func CalculateMaxSize() uint64 {
  1004  	if logging.logFile != "" {
  1005  		if logging.logFileMaxSizeMB == 0 {
  1006  			// If logFileMaxSizeMB is zero, we don't have limitations on the log size.
  1007  			return math.MaxUint64
  1008  		}
  1009  		// Flag logFileMaxSizeMB is in MB for user convenience.
  1010  		return logging.logFileMaxSizeMB * 1024 * 1024
  1011  	}
  1012  	// If "log_file" flag is not specified, the target file (sb.file) will be cleaned up when reaches a fixed size.
  1013  	return MaxSize
  1014  }
  1015  
  1016  func (sb *syncBuffer) Write(p []byte) (n int, err error) {
  1017  	if sb.nbytes+uint64(len(p)) >= sb.maxbytes {
  1018  		if err := sb.rotateFile(time.Now(), false); err != nil {
  1019  			sb.logger.exit(err)
  1020  		}
  1021  	}
  1022  	n, err = sb.Writer.Write(p)
  1023  	sb.nbytes += uint64(n)
  1024  	if err != nil {
  1025  		sb.logger.exit(err)
  1026  	}
  1027  	return
  1028  }
  1029  
  1030  // rotateFile closes the syncBuffer's file and starts a new one.
  1031  // The startup argument indicates whether this is the initial startup of klog.
  1032  // If startup is true, existing files are opened for appending instead of truncated.
  1033  func (sb *syncBuffer) rotateFile(now time.Time, startup bool) error {
  1034  	if sb.file != nil {
  1035  		sb.Flush()
  1036  		sb.file.Close()
  1037  	}
  1038  	var err error
  1039  	sb.file, _, err = create(severity.Name[sb.sev], now, startup)
  1040  	if err != nil {
  1041  		return err
  1042  	}
  1043  	if startup {
  1044  		fileInfo, err := sb.file.Stat()
  1045  		if err != nil {
  1046  			return fmt.Errorf("file stat could not get fileinfo: %v", err)
  1047  		}
  1048  		// init file size
  1049  		sb.nbytes = uint64(fileInfo.Size())
  1050  	} else {
  1051  		sb.nbytes = 0
  1052  	}
  1053  	sb.Writer = bufio.NewWriterSize(sb.file, bufferSize)
  1054  
  1055  	if sb.logger.skipLogHeaders {
  1056  		return nil
  1057  	}
  1058  
  1059  	// Write header.
  1060  	var buf bytes.Buffer
  1061  	fmt.Fprintf(&buf, "Log file created at: %s\n", now.Format("2006/01/02 15:04:05"))
  1062  	fmt.Fprintf(&buf, "Running on machine: %s\n", host)
  1063  	fmt.Fprintf(&buf, "Binary: Built with %s %s for %s/%s\n", runtime.Compiler, runtime.Version(), runtime.GOOS, runtime.GOARCH)
  1064  	fmt.Fprintf(&buf, "Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg\n")
  1065  	n, err := sb.file.Write(buf.Bytes())
  1066  	sb.nbytes += uint64(n)
  1067  	return err
  1068  }
  1069  
  1070  // bufferSize sizes the buffer associated with each log file. It's large
  1071  // so that log records can accumulate without the logging thread blocking
  1072  // on disk I/O. The flushDaemon will block instead.
  1073  const bufferSize = 256 * 1024
  1074  
  1075  // createFiles creates all the log files for severity from sev down to infoLog.
  1076  // l.mu is held.
  1077  func (l *loggingT) createFiles(sev severity.Severity) error {
  1078  	interval := l.flushInterval
  1079  	if interval == 0 {
  1080  		interval = flushInterval
  1081  	}
  1082  	l.flushD.run(interval)
  1083  	now := time.Now()
  1084  	// Files are created in decreasing severity order, so as soon as we find one
  1085  	// has already been created, we can stop.
  1086  	for s := sev; s >= severity.InfoLog && l.file[s] == nil; s-- {
  1087  		sb := &syncBuffer{
  1088  			logger:   l,
  1089  			sev:      s,
  1090  			maxbytes: CalculateMaxSize(),
  1091  		}
  1092  		if err := sb.rotateFile(now, true); err != nil {
  1093  			return err
  1094  		}
  1095  		l.file[s] = sb
  1096  	}
  1097  	return nil
  1098  }
  1099  
  1100  const flushInterval = 5 * time.Second
  1101  
  1102  // flushDaemon periodically flushes the log file buffers.
  1103  type flushDaemon struct {
  1104  	mu       sync.Mutex
  1105  	clock    clock.Clock
  1106  	flush    func()
  1107  	stopC    chan struct{}
  1108  	stopDone chan struct{}
  1109  }
  1110  
  1111  // newFlushDaemon returns a new flushDaemon. If the passed clock is nil, a
  1112  // clock.RealClock is used.
  1113  func newFlushDaemon(flush func(), tickClock clock.Clock) *flushDaemon {
  1114  	if tickClock == nil {
  1115  		tickClock = clock.RealClock{}
  1116  	}
  1117  	return &flushDaemon{
  1118  		flush: flush,
  1119  		clock: tickClock,
  1120  	}
  1121  }
  1122  
  1123  // run starts a goroutine that periodically calls the daemons flush function.
  1124  // Calling run on an already running daemon will have no effect.
  1125  func (f *flushDaemon) run(interval time.Duration) {
  1126  	f.mu.Lock()
  1127  	defer f.mu.Unlock()
  1128  
  1129  	if f.stopC != nil { // daemon already running
  1130  		return
  1131  	}
  1132  
  1133  	f.stopC = make(chan struct{}, 1)
  1134  	f.stopDone = make(chan struct{}, 1)
  1135  
  1136  	ticker := f.clock.NewTicker(interval)
  1137  	go func() {
  1138  		defer ticker.Stop()
  1139  		defer func() { f.stopDone <- struct{}{} }()
  1140  		for {
  1141  			select {
  1142  			case <-ticker.C():
  1143  				f.flush()
  1144  			case <-f.stopC:
  1145  				f.flush()
  1146  				return
  1147  			}
  1148  		}
  1149  	}()
  1150  }
  1151  
  1152  // stop stops the running flushDaemon and waits until the daemon has shut down.
  1153  // Calling stop on a daemon that isn't running will have no effect.
  1154  func (f *flushDaemon) stop() {
  1155  	f.mu.Lock()
  1156  	defer f.mu.Unlock()
  1157  
  1158  	if f.stopC == nil { // daemon not running
  1159  		return
  1160  	}
  1161  
  1162  	f.stopC <- struct{}{}
  1163  	<-f.stopDone
  1164  
  1165  	f.stopC = nil
  1166  	f.stopDone = nil
  1167  }
  1168  
  1169  // isRunning returns true if the flush daemon is running.
  1170  func (f *flushDaemon) isRunning() bool {
  1171  	f.mu.Lock()
  1172  	defer f.mu.Unlock()
  1173  	return f.stopC != nil
  1174  }
  1175  
  1176  // StopFlushDaemon stops the flush daemon, if running, and flushes once.
  1177  // This prevents klog from leaking goroutines on shutdown. After stopping
  1178  // the daemon, you can still manually flush buffers again by calling Flush().
  1179  func StopFlushDaemon() {
  1180  	logging.flushD.stop()
  1181  }
  1182  
  1183  // StartFlushDaemon ensures that the flush daemon runs with the given delay
  1184  // between flush calls. If it is already running, it gets restarted.
  1185  func StartFlushDaemon(interval time.Duration) {
  1186  	StopFlushDaemon()
  1187  	logging.flushD.run(interval)
  1188  }
  1189  
  1190  // lockAndFlushAll is like flushAll but locks l.mu first.
  1191  func (l *loggingT) lockAndFlushAll() {
  1192  	l.mu.Lock()
  1193  	needToSync := l.flushAll()
  1194  	l.mu.Unlock()
  1195  	// Some environments are slow when syncing and holding the lock might cause contention.
  1196  	l.syncAll(needToSync)
  1197  }
  1198  
  1199  // flushAll flushes all the logs
  1200  // l.mu is held.
  1201  //
  1202  // The result is the number of files which need to be synced and the pointers to them.
  1203  func (l *loggingT) flushAll() fileArray {
  1204  	var needToSync fileArray
  1205  
  1206  	// Flush from fatal down, in case there's trouble flushing.
  1207  	for s := severity.FatalLog; s >= severity.InfoLog; s-- {
  1208  		file := l.file[s]
  1209  		if sb, ok := file.(*syncBuffer); ok && sb.file != nil {
  1210  			_ = sb.Flush() // ignore error
  1211  			needToSync.files[needToSync.num] = sb.file
  1212  			needToSync.num++
  1213  		}
  1214  	}
  1215  	if logging.loggerOptions.flush != nil {
  1216  		logging.loggerOptions.flush()
  1217  	}
  1218  	return needToSync
  1219  }
  1220  
  1221  type fileArray struct {
  1222  	num   int
  1223  	files [severity.NumSeverity]*os.File
  1224  }
  1225  
  1226  // syncAll attempts to "sync" their data to disk.
  1227  func (l *loggingT) syncAll(needToSync fileArray) {
  1228  	// Flush from fatal down, in case there's trouble flushing.
  1229  	for i := 0; i < needToSync.num; i++ {
  1230  		_ = needToSync.files[i].Sync() // ignore error
  1231  	}
  1232  }
  1233  
  1234  // CopyStandardLogTo arranges for messages written to the Go "log" package's
  1235  // default logs to also appear in the Google logs for the named and lower
  1236  // severities.  Subsequent changes to the standard log's default output location
  1237  // or format may break this behavior.
  1238  //
  1239  // Valid names are "INFO", "WARNING", "ERROR", and "FATAL".  If the name is not
  1240  // recognized, CopyStandardLogTo panics.
  1241  func CopyStandardLogTo(name string) {
  1242  	sev, ok := severity.ByName(name)
  1243  	if !ok {
  1244  		panic(fmt.Sprintf("log.CopyStandardLogTo(%q): unrecognized severity name", name))
  1245  	}
  1246  	// Set a log format that captures the user's file and line:
  1247  	//   d.go:23: message
  1248  	stdLog.SetFlags(stdLog.Lshortfile)
  1249  	stdLog.SetOutput(logBridge(sev))
  1250  }
  1251  
  1252  // NewStandardLogger returns a Logger that writes to the klog logs for the
  1253  // named and lower severities.
  1254  //
  1255  // Valid names are "INFO", "WARNING", "ERROR", and "FATAL". If the name is not
  1256  // recognized, NewStandardLogger panics.
  1257  func NewStandardLogger(name string) *stdLog.Logger {
  1258  	sev, ok := severity.ByName(name)
  1259  	if !ok {
  1260  		panic(fmt.Sprintf("klog.NewStandardLogger(%q): unknown severity", name))
  1261  	}
  1262  	return stdLog.New(logBridge(sev), "", stdLog.Lshortfile)
  1263  }
  1264  
  1265  // logBridge provides the Write method that enables CopyStandardLogTo to connect
  1266  // Go's standard logs to the logs provided by this package.
  1267  type logBridge severity.Severity
  1268  
  1269  // Write parses the standard logging line and passes its components to the
  1270  // logger for severity(lb).
  1271  func (lb logBridge) Write(b []byte) (n int, err error) {
  1272  	var (
  1273  		file = "???"
  1274  		line = 1
  1275  		text string
  1276  	)
  1277  	// Split "d.go:23: message" into "d.go", "23", and "message".
  1278  	if parts := bytes.SplitN(b, []byte{':'}, 3); len(parts) != 3 || len(parts[0]) < 1 || len(parts[2]) < 1 {
  1279  		text = fmt.Sprintf("bad log format: %s", b)
  1280  	} else {
  1281  		file = string(parts[0])
  1282  		text = string(parts[2][1:]) // skip leading space
  1283  		line, err = strconv.Atoi(string(parts[1]))
  1284  		if err != nil {
  1285  			text = fmt.Sprintf("bad line number: %s", b)
  1286  			line = 1
  1287  		}
  1288  	}
  1289  	// printWithFileLine with alsoToStderr=true, so standard log messages
  1290  	// always appear on standard error.
  1291  	logging.printWithFileLine(severity.Severity(lb), logging.logger, logging.filter, file, line, true, text)
  1292  	return len(b), nil
  1293  }
  1294  
  1295  // setV computes and remembers the V level for a given PC
  1296  // when vmodule is enabled.
  1297  // File pattern matching takes the basename of the file, stripped
  1298  // of its .go suffix, and uses filepath.Match, which is a little more
  1299  // general than the *? matching used in C++.
  1300  // l.mu is held.
  1301  func (l *loggingT) setV(pc uintptr) Level {
  1302  	fn := runtime.FuncForPC(pc)
  1303  	file, _ := fn.FileLine(pc)
  1304  	// The file is something like /a/b/c/d.go. We want just the d.
  1305  	file = strings.TrimSuffix(file, ".go")
  1306  	if slash := strings.LastIndex(file, "/"); slash >= 0 {
  1307  		file = file[slash+1:]
  1308  	}
  1309  	for _, filter := range l.vmodule.filter {
  1310  		if filter.match(file) {
  1311  			l.vmap[pc] = filter.level
  1312  			return filter.level
  1313  		}
  1314  	}
  1315  	l.vmap[pc] = 0
  1316  	return 0
  1317  }
  1318  
  1319  // Verbose is a boolean type that implements Infof (like Printf) etc.
  1320  // See the documentation of V for more information.
  1321  type Verbose struct {
  1322  	enabled bool
  1323  	logger  *logWriter
  1324  }
  1325  
  1326  func newVerbose(level Level, b bool) Verbose {
  1327  	if logging.logger == nil {
  1328  		return Verbose{b, nil}
  1329  	}
  1330  	v := logging.logger.V(int(level))
  1331  	return Verbose{b, &logWriter{Logger: v, writeKlogBuffer: logging.loggerOptions.writeKlogBuffer}}
  1332  }
  1333  
  1334  // V reports whether verbosity at the call site is at least the requested level.
  1335  // The returned value is a struct of type Verbose, which implements Info, Infoln
  1336  // and Infof. These methods will write to the Info log if called.
  1337  // Thus, one may write either
  1338  //
  1339  //	if klog.V(2).Enabled() { klog.Info("log this") }
  1340  //
  1341  // or
  1342  //
  1343  //	klog.V(2).Info("log this")
  1344  //
  1345  // The second form is shorter but the first is cheaper if logging is off because it does
  1346  // not evaluate its arguments.
  1347  //
  1348  // Whether an individual call to V generates a log record depends on the setting of
  1349  // the -v and -vmodule flags; both are off by default. The V call will log if its level
  1350  // is less than or equal to the value of the -v flag, or alternatively if its level is
  1351  // less than or equal to the value of the -vmodule pattern matching the source file
  1352  // containing the call.
  1353  func V(level Level) Verbose {
  1354  	return VDepth(1, level)
  1355  }
  1356  
  1357  // VDepth is a variant of V that accepts a number of stack frames that will be
  1358  // skipped when checking the -vmodule patterns. VDepth(0) is equivalent to
  1359  // V().
  1360  func VDepth(depth int, level Level) Verbose {
  1361  	// This function tries hard to be cheap unless there's work to do.
  1362  	// The fast path is two atomic loads and compares.
  1363  
  1364  	// Here is a cheap but safe test to see if V logging is enabled globally.
  1365  	if logging.verbosity.get() >= level {
  1366  		return newVerbose(level, true)
  1367  	}
  1368  
  1369  	// It's off globally but vmodule may still be set.
  1370  	// Here is another cheap but safe test to see if vmodule is enabled.
  1371  	if atomic.LoadInt32(&logging.filterLength) > 0 {
  1372  		// Now we need a proper lock to use the logging structure. The pcs field
  1373  		// is shared so we must lock before accessing it. This is fairly expensive,
  1374  		// but if V logging is enabled we're slow anyway.
  1375  		logging.mu.Lock()
  1376  		defer logging.mu.Unlock()
  1377  		if runtime.Callers(2+depth, logging.pcs[:]) == 0 {
  1378  			return newVerbose(level, false)
  1379  		}
  1380  		// runtime.Callers returns "return PCs", but we want
  1381  		// to look up the symbolic information for the call,
  1382  		// so subtract 1 from the PC. runtime.CallersFrames
  1383  		// would be cleaner, but allocates.
  1384  		pc := logging.pcs[0] - 1
  1385  		v, ok := logging.vmap[pc]
  1386  		if !ok {
  1387  			v = logging.setV(pc)
  1388  		}
  1389  		return newVerbose(level, v >= level)
  1390  	}
  1391  	return newVerbose(level, false)
  1392  }
  1393  
  1394  // Enabled will return true if this log level is enabled, guarded by the value
  1395  // of v.
  1396  // See the documentation of V for usage.
  1397  func (v Verbose) Enabled() bool {
  1398  	return v.enabled
  1399  }
  1400  
  1401  // Info is equivalent to the global Info function, guarded by the value of v.
  1402  // See the documentation of V for usage.
  1403  func (v Verbose) Info(args ...interface{}) {
  1404  	if v.enabled {
  1405  		logging.print(severity.InfoLog, v.logger, logging.filter, args...)
  1406  	}
  1407  }
  1408  
  1409  // InfoDepth is equivalent to the global InfoDepth function, guarded by the value of v.
  1410  // See the documentation of V for usage.
  1411  func (v Verbose) InfoDepth(depth int, args ...interface{}) {
  1412  	if v.enabled {
  1413  		logging.printDepth(severity.InfoLog, v.logger, logging.filter, depth, args...)
  1414  	}
  1415  }
  1416  
  1417  // Infoln is equivalent to the global Infoln function, guarded by the value of v.
  1418  // See the documentation of V for usage.
  1419  func (v Verbose) Infoln(args ...interface{}) {
  1420  	if v.enabled {
  1421  		logging.println(severity.InfoLog, v.logger, logging.filter, args...)
  1422  	}
  1423  }
  1424  
  1425  // InfolnDepth is equivalent to the global InfolnDepth function, guarded by the value of v.
  1426  // See the documentation of V for usage.
  1427  func (v Verbose) InfolnDepth(depth int, args ...interface{}) {
  1428  	if v.enabled {
  1429  		logging.printlnDepth(severity.InfoLog, v.logger, logging.filter, depth, args...)
  1430  	}
  1431  }
  1432  
  1433  // Infof is equivalent to the global Infof function, guarded by the value of v.
  1434  // See the documentation of V for usage.
  1435  func (v Verbose) Infof(format string, args ...interface{}) {
  1436  	if v.enabled {
  1437  		logging.printf(severity.InfoLog, v.logger, logging.filter, format, args...)
  1438  	}
  1439  }
  1440  
  1441  // InfofDepth is equivalent to the global InfofDepth function, guarded by the value of v.
  1442  // See the documentation of V for usage.
  1443  func (v Verbose) InfofDepth(depth int, format string, args ...interface{}) {
  1444  	if v.enabled {
  1445  		logging.printfDepth(severity.InfoLog, v.logger, logging.filter, depth, format, args...)
  1446  	}
  1447  }
  1448  
  1449  // InfoS is equivalent to the global InfoS function, guarded by the value of v.
  1450  // See the documentation of V for usage.
  1451  func (v Verbose) InfoS(msg string, keysAndValues ...interface{}) {
  1452  	if v.enabled {
  1453  		logging.infoS(v.logger, logging.filter, 0, msg, keysAndValues...)
  1454  	}
  1455  }
  1456  
  1457  // InfoSDepth acts as InfoS but uses depth to determine which call frame to log.
  1458  // InfoSDepth(0, "msg") is the same as InfoS("msg").
  1459  func InfoSDepth(depth int, msg string, keysAndValues ...interface{}) {
  1460  	logging.infoS(logging.logger, logging.filter, depth, msg, keysAndValues...)
  1461  }
  1462  
  1463  // InfoSDepth is equivalent to the global InfoSDepth function, guarded by the value of v.
  1464  // See the documentation of V for usage.
  1465  func (v Verbose) InfoSDepth(depth int, msg string, keysAndValues ...interface{}) {
  1466  	if v.enabled {
  1467  		logging.infoS(v.logger, logging.filter, depth, msg, keysAndValues...)
  1468  	}
  1469  }
  1470  
  1471  // Deprecated: Use ErrorS instead.
  1472  func (v Verbose) Error(err error, msg string, args ...interface{}) {
  1473  	if v.enabled {
  1474  		logging.errorS(err, v.logger, logging.filter, 0, msg, args...)
  1475  	}
  1476  }
  1477  
  1478  // ErrorS is equivalent to the global Error function, guarded by the value of v.
  1479  // See the documentation of V for usage.
  1480  func (v Verbose) ErrorS(err error, msg string, keysAndValues ...interface{}) {
  1481  	if v.enabled {
  1482  		logging.errorS(err, v.logger, logging.filter, 0, msg, keysAndValues...)
  1483  	}
  1484  }
  1485  
  1486  // Info logs to the INFO log.
  1487  // Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
  1488  func Info(args ...interface{}) {
  1489  	logging.print(severity.InfoLog, logging.logger, logging.filter, args...)
  1490  }
  1491  
  1492  // InfoDepth acts as Info but uses depth to determine which call frame to log.
  1493  // InfoDepth(0, "msg") is the same as Info("msg").
  1494  func InfoDepth(depth int, args ...interface{}) {
  1495  	logging.printDepth(severity.InfoLog, logging.logger, logging.filter, depth, args...)
  1496  }
  1497  
  1498  // Infoln logs to the INFO log.
  1499  // Arguments are handled in the manner of fmt.Println; a newline is always appended.
  1500  func Infoln(args ...interface{}) {
  1501  	logging.println(severity.InfoLog, logging.logger, logging.filter, args...)
  1502  }
  1503  
  1504  // InfolnDepth acts as Infoln but uses depth to determine which call frame to log.
  1505  // InfolnDepth(0, "msg") is the same as Infoln("msg").
  1506  func InfolnDepth(depth int, args ...interface{}) {
  1507  	logging.printlnDepth(severity.InfoLog, logging.logger, logging.filter, depth, args...)
  1508  }
  1509  
  1510  // Infof logs to the INFO log.
  1511  // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
  1512  func Infof(format string, args ...interface{}) {
  1513  	logging.printf(severity.InfoLog, logging.logger, logging.filter, format, args...)
  1514  }
  1515  
  1516  // InfofDepth acts as Infof but uses depth to determine which call frame to log.
  1517  // InfofDepth(0, "msg", args...) is the same as Infof("msg", args...).
  1518  func InfofDepth(depth int, format string, args ...interface{}) {
  1519  	logging.printfDepth(severity.InfoLog, logging.logger, logging.filter, depth, format, args...)
  1520  }
  1521  
  1522  // InfoS structured logs to the INFO log.
  1523  // The msg argument used to add constant description to the log line.
  1524  // The key/value pairs would be join by "=" ; a newline is always appended.
  1525  //
  1526  // Basic examples:
  1527  // >> klog.InfoS("Pod status updated", "pod", "kubedns", "status", "ready")
  1528  // output:
  1529  // >> I1025 00:15:15.525108       1 controller_utils.go:116] "Pod status updated" pod="kubedns" status="ready"
  1530  func InfoS(msg string, keysAndValues ...interface{}) {
  1531  	logging.infoS(logging.logger, logging.filter, 0, msg, keysAndValues...)
  1532  }
  1533  
  1534  // Warning logs to the WARNING and INFO logs.
  1535  // Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
  1536  func Warning(args ...interface{}) {
  1537  	logging.print(severity.WarningLog, logging.logger, logging.filter, args...)
  1538  }
  1539  
  1540  // WarningDepth acts as Warning but uses depth to determine which call frame to log.
  1541  // WarningDepth(0, "msg") is the same as Warning("msg").
  1542  func WarningDepth(depth int, args ...interface{}) {
  1543  	logging.printDepth(severity.WarningLog, logging.logger, logging.filter, depth, args...)
  1544  }
  1545  
  1546  // Warningln logs to the WARNING and INFO logs.
  1547  // Arguments are handled in the manner of fmt.Println; a newline is always appended.
  1548  func Warningln(args ...interface{}) {
  1549  	logging.println(severity.WarningLog, logging.logger, logging.filter, args...)
  1550  }
  1551  
  1552  // WarninglnDepth acts as Warningln but uses depth to determine which call frame to log.
  1553  // WarninglnDepth(0, "msg") is the same as Warningln("msg").
  1554  func WarninglnDepth(depth int, args ...interface{}) {
  1555  	logging.printlnDepth(severity.WarningLog, logging.logger, logging.filter, depth, args...)
  1556  }
  1557  
  1558  // Warningf logs to the WARNING and INFO logs.
  1559  // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
  1560  func Warningf(format string, args ...interface{}) {
  1561  	logging.printf(severity.WarningLog, logging.logger, logging.filter, format, args...)
  1562  }
  1563  
  1564  // WarningfDepth acts as Warningf but uses depth to determine which call frame to log.
  1565  // WarningfDepth(0, "msg", args...) is the same as Warningf("msg", args...).
  1566  func WarningfDepth(depth int, format string, args ...interface{}) {
  1567  	logging.printfDepth(severity.WarningLog, logging.logger, logging.filter, depth, format, args...)
  1568  }
  1569  
  1570  // Error logs to the ERROR, WARNING, and INFO logs.
  1571  // Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
  1572  func Error(args ...interface{}) {
  1573  	logging.print(severity.ErrorLog, logging.logger, logging.filter, args...)
  1574  }
  1575  
  1576  // ErrorDepth acts as Error but uses depth to determine which call frame to log.
  1577  // ErrorDepth(0, "msg") is the same as Error("msg").
  1578  func ErrorDepth(depth int, args ...interface{}) {
  1579  	logging.printDepth(severity.ErrorLog, logging.logger, logging.filter, depth, args...)
  1580  }
  1581  
  1582  // Errorln logs to the ERROR, WARNING, and INFO logs.
  1583  // Arguments are handled in the manner of fmt.Println; a newline is always appended.
  1584  func Errorln(args ...interface{}) {
  1585  	logging.println(severity.ErrorLog, logging.logger, logging.filter, args...)
  1586  }
  1587  
  1588  // ErrorlnDepth acts as Errorln but uses depth to determine which call frame to log.
  1589  // ErrorlnDepth(0, "msg") is the same as Errorln("msg").
  1590  func ErrorlnDepth(depth int, args ...interface{}) {
  1591  	logging.printlnDepth(severity.ErrorLog, logging.logger, logging.filter, depth, args...)
  1592  }
  1593  
  1594  // Errorf logs to the ERROR, WARNING, and INFO logs.
  1595  // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
  1596  func Errorf(format string, args ...interface{}) {
  1597  	logging.printf(severity.ErrorLog, logging.logger, logging.filter, format, args...)
  1598  }
  1599  
  1600  // ErrorfDepth acts as Errorf but uses depth to determine which call frame to log.
  1601  // ErrorfDepth(0, "msg", args...) is the same as Errorf("msg", args...).
  1602  func ErrorfDepth(depth int, format string, args ...interface{}) {
  1603  	logging.printfDepth(severity.ErrorLog, logging.logger, logging.filter, depth, format, args...)
  1604  }
  1605  
  1606  // ErrorS structured logs to the ERROR, WARNING, and INFO logs.
  1607  // the err argument used as "err" field of log line.
  1608  // The msg argument used to add constant description to the log line.
  1609  // The key/value pairs would be join by "=" ; a newline is always appended.
  1610  //
  1611  // Basic examples:
  1612  // >> klog.ErrorS(err, "Failed to update pod status")
  1613  // output:
  1614  // >> E1025 00:15:15.525108       1 controller_utils.go:114] "Failed to update pod status" err="timeout"
  1615  func ErrorS(err error, msg string, keysAndValues ...interface{}) {
  1616  	logging.errorS(err, logging.logger, logging.filter, 0, msg, keysAndValues...)
  1617  }
  1618  
  1619  // ErrorSDepth acts as ErrorS but uses depth to determine which call frame to log.
  1620  // ErrorSDepth(0, "msg") is the same as ErrorS("msg").
  1621  func ErrorSDepth(depth int, err error, msg string, keysAndValues ...interface{}) {
  1622  	logging.errorS(err, logging.logger, logging.filter, depth, msg, keysAndValues...)
  1623  }
  1624  
  1625  // Fatal logs to the FATAL, ERROR, WARNING, and INFO logs,
  1626  // prints stack trace(s), then calls OsExit(255).
  1627  //
  1628  // Stderr only receives a dump of the current goroutine's stack trace. Log files,
  1629  // if there are any, receive a dump of the stack traces in all goroutines.
  1630  //
  1631  // Callers who want more control over handling of fatal events may instead use a
  1632  // combination of different functions:
  1633  //   - some info or error logging function, optionally with a stack trace
  1634  //     value generated by github.com/go-logr/lib/dbg.Backtrace
  1635  //   - Flush to flush pending log data
  1636  //   - panic, os.Exit or returning to the caller with an error
  1637  //
  1638  // Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
  1639  func Fatal(args ...interface{}) {
  1640  	logging.print(severity.FatalLog, logging.logger, logging.filter, args...)
  1641  }
  1642  
  1643  // FatalDepth acts as Fatal but uses depth to determine which call frame to log.
  1644  // FatalDepth(0, "msg") is the same as Fatal("msg").
  1645  func FatalDepth(depth int, args ...interface{}) {
  1646  	logging.printDepth(severity.FatalLog, logging.logger, logging.filter, depth, args...)
  1647  }
  1648  
  1649  // Fatalln logs to the FATAL, ERROR, WARNING, and INFO logs,
  1650  // including a stack trace of all running goroutines, then calls OsExit(255).
  1651  // Arguments are handled in the manner of fmt.Println; a newline is always appended.
  1652  func Fatalln(args ...interface{}) {
  1653  	logging.println(severity.FatalLog, logging.logger, logging.filter, args...)
  1654  }
  1655  
  1656  // FatallnDepth acts as Fatalln but uses depth to determine which call frame to log.
  1657  // FatallnDepth(0, "msg") is the same as Fatalln("msg").
  1658  func FatallnDepth(depth int, args ...interface{}) {
  1659  	logging.printlnDepth(severity.FatalLog, logging.logger, logging.filter, depth, args...)
  1660  }
  1661  
  1662  // Fatalf logs to the FATAL, ERROR, WARNING, and INFO logs,
  1663  // including a stack trace of all running goroutines, then calls OsExit(255).
  1664  // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
  1665  func Fatalf(format string, args ...interface{}) {
  1666  	logging.printf(severity.FatalLog, logging.logger, logging.filter, format, args...)
  1667  }
  1668  
  1669  // FatalfDepth acts as Fatalf but uses depth to determine which call frame to log.
  1670  // FatalfDepth(0, "msg", args...) is the same as Fatalf("msg", args...).
  1671  func FatalfDepth(depth int, format string, args ...interface{}) {
  1672  	logging.printfDepth(severity.FatalLog, logging.logger, logging.filter, depth, format, args...)
  1673  }
  1674  
  1675  // fatalNoStacks is non-zero if we are to exit without dumping goroutine stacks.
  1676  // It allows Exit and relatives to use the Fatal logs.
  1677  var fatalNoStacks uint32
  1678  
  1679  // Exit logs to the FATAL, ERROR, WARNING, and INFO logs, then calls OsExit(1).
  1680  // Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
  1681  func Exit(args ...interface{}) {
  1682  	atomic.StoreUint32(&fatalNoStacks, 1)
  1683  	logging.print(severity.FatalLog, logging.logger, logging.filter, args...)
  1684  }
  1685  
  1686  // ExitDepth acts as Exit but uses depth to determine which call frame to log.
  1687  // ExitDepth(0, "msg") is the same as Exit("msg").
  1688  func ExitDepth(depth int, args ...interface{}) {
  1689  	atomic.StoreUint32(&fatalNoStacks, 1)
  1690  	logging.printDepth(severity.FatalLog, logging.logger, logging.filter, depth, args...)
  1691  }
  1692  
  1693  // Exitln logs to the FATAL, ERROR, WARNING, and INFO logs, then calls OsExit(1).
  1694  func Exitln(args ...interface{}) {
  1695  	atomic.StoreUint32(&fatalNoStacks, 1)
  1696  	logging.println(severity.FatalLog, logging.logger, logging.filter, args...)
  1697  }
  1698  
  1699  // ExitlnDepth acts as Exitln but uses depth to determine which call frame to log.
  1700  // ExitlnDepth(0, "msg") is the same as Exitln("msg").
  1701  func ExitlnDepth(depth int, args ...interface{}) {
  1702  	atomic.StoreUint32(&fatalNoStacks, 1)
  1703  	logging.printlnDepth(severity.FatalLog, logging.logger, logging.filter, depth, args...)
  1704  }
  1705  
  1706  // Exitf logs to the FATAL, ERROR, WARNING, and INFO logs, then calls OsExit(1).
  1707  // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
  1708  func Exitf(format string, args ...interface{}) {
  1709  	atomic.StoreUint32(&fatalNoStacks, 1)
  1710  	logging.printf(severity.FatalLog, logging.logger, logging.filter, format, args...)
  1711  }
  1712  
  1713  // ExitfDepth acts as Exitf but uses depth to determine which call frame to log.
  1714  // ExitfDepth(0, "msg", args...) is the same as Exitf("msg", args...).
  1715  func ExitfDepth(depth int, format string, args ...interface{}) {
  1716  	atomic.StoreUint32(&fatalNoStacks, 1)
  1717  	logging.printfDepth(severity.FatalLog, logging.logger, logging.filter, depth, format, args...)
  1718  }
  1719  
  1720  // LogFilter is a collection of functions that can filter all logging calls,
  1721  // e.g. for sanitization of arguments and prevent accidental leaking of secrets.
  1722  type LogFilter interface {
  1723  	Filter(args []interface{}) []interface{}
  1724  	FilterF(format string, args []interface{}) (string, []interface{})
  1725  	FilterS(msg string, keysAndValues []interface{}) (string, []interface{})
  1726  }
  1727  
  1728  // SetLogFilter installs a filter that is used for all log calls.
  1729  //
  1730  // Modifying the filter is not thread-safe and should be done while no other
  1731  // goroutines invoke log calls, usually during program initialization.
  1732  func SetLogFilter(filter LogFilter) {
  1733  	logging.filter = filter
  1734  }
  1735  

View as plain text