...

Source file src/github.com/golang/glog/glog.go

Documentation: github.com/golang/glog

     1  // Go support for leveled logs, analogous to https://github.com/google/glog.
     2  //
     3  // Copyright 2023 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 glog implements logging analogous to the Google-internal C++ INFO/ERROR/V setup.
    18  // It provides functions that have a name matched by regex:
    19  //
    20  //	(Info|Warning|Error|Fatal)(Context)?(Depth)?(f)?
    21  //
    22  // If Context is present, function takes context.Context argument. The
    23  // context is used to pass through the Trace Context to log sinks that can make use
    24  // of it.
    25  // It is recommended to use the context variant of the functions over the non-context
    26  // variants if a context is available to make sure the Trace Contexts are present
    27  // in logs.
    28  //
    29  // If Depth is present, this function calls log from a different depth in the call stack.
    30  // This enables a callee to emit logs that use the callsite information of its caller
    31  // or any other callers in the stack. When depth == 0, the original callee's line
    32  // information is emitted. When depth > 0, depth frames are skipped in the call stack
    33  // and the final frame is treated like the original callee to Info.
    34  //
    35  // If 'f' is present, function formats according to a format specifier.
    36  //
    37  // This package also provides V-style logging controlled by the -v and -vmodule=file=2 flags.
    38  //
    39  // Basic examples:
    40  //
    41  //	glog.Info("Prepare to repel boarders")
    42  //
    43  //	glog.Fatalf("Initialization failed: %s", err)
    44  //
    45  // See the documentation for the V function for an explanation of these examples:
    46  //
    47  //	if glog.V(2) {
    48  //		glog.Info("Starting transaction...")
    49  //	}
    50  //
    51  //	glog.V(2).Infoln("Processed", nItems, "elements")
    52  //
    53  // Log output is buffered and written periodically using Flush. Programs
    54  // should call Flush before exiting to guarantee all log output is written.
    55  //
    56  // By default, all log statements write to files in a temporary directory.
    57  // This package provides several flags that modify this behavior.
    58  // As a result, flag.Parse must be called before any logging is done.
    59  //
    60  //	-logtostderr=false
    61  //		Logs are written to standard error instead of to files.
    62  //	-alsologtostderr=false
    63  //		Logs are written to standard error as well as to files.
    64  //	-stderrthreshold=ERROR
    65  //		Log events at or above this severity are logged to standard
    66  //		error as well as to files.
    67  //	-log_dir=""
    68  //		Log files will be written to this directory instead of the
    69  //		default temporary directory.
    70  //
    71  // Other flags provide aids to debugging.
    72  //
    73  //	-log_backtrace_at=""
    74  //		A comma-separated list of file and line numbers holding a logging
    75  //		statement, such as
    76  //			-log_backtrace_at=gopherflakes.go:234
    77  //		A stack trace will be written to the Info log whenever execution
    78  //		hits one of these statements. (Unlike with -vmodule, the ".go"
    79  //		must bepresent.)
    80  //	-v=0
    81  //		Enable V-leveled logging at the specified level.
    82  //	-vmodule=""
    83  //		The syntax of the argument is a comma-separated list of pattern=N,
    84  //		where pattern is a literal file name (minus the ".go" suffix) or
    85  //		"glob" pattern and N is a V level. For instance,
    86  //			-vmodule=gopher*=3
    87  //		sets the V level to 3 in all Go files whose names begin with "gopher",
    88  //		and
    89  //			-vmodule=/path/to/glog/glog_test=1
    90  //		sets the V level to 1 in the Go file /path/to/glog/glog_test.go.
    91  //		If a glob pattern contains a slash, it is matched against the full path,
    92  //		and the file name. Otherwise, the pattern is
    93  //		matched only against the file's basename.  When both -vmodule and -v
    94  //		are specified, the -vmodule values take precedence for the specified
    95  //		modules.
    96  package glog
    97  
    98  // This file contains the parts of the log package that are shared among all
    99  // implementations (file, envelope, and appengine).
   100  
   101  import (
   102  	"bytes"
   103  	"context"
   104  	"errors"
   105  	"fmt"
   106  	stdLog "log"
   107  	"os"
   108  	"reflect"
   109  	"runtime"
   110  	"runtime/pprof"
   111  	"strconv"
   112  	"sync"
   113  	"sync/atomic"
   114  	"time"
   115  
   116  	"github.com/golang/glog/internal/logsink"
   117  	"github.com/golang/glog/internal/stackdump"
   118  )
   119  
   120  var timeNow = time.Now // Stubbed out for testing.
   121  
   122  // MaxSize is the maximum size of a log file in bytes.
   123  var MaxSize uint64 = 1024 * 1024 * 1800
   124  
   125  // ErrNoLog is the error we return if no log file has yet been created
   126  // for the specified log type.
   127  var ErrNoLog = errors.New("log file not yet created")
   128  
   129  // OutputStats tracks the number of output lines and bytes written.
   130  type OutputStats struct {
   131  	lines int64
   132  	bytes int64
   133  }
   134  
   135  // Lines returns the number of lines written.
   136  func (s *OutputStats) Lines() int64 {
   137  	return atomic.LoadInt64(&s.lines)
   138  }
   139  
   140  // Bytes returns the number of bytes written.
   141  func (s *OutputStats) Bytes() int64 {
   142  	return atomic.LoadInt64(&s.bytes)
   143  }
   144  
   145  // Stats tracks the number of lines of output and number of bytes
   146  // per severity level. Values must be read with atomic.LoadInt64.
   147  var Stats struct {
   148  	Info, Warning, Error OutputStats
   149  }
   150  
   151  var severityStats = [...]*OutputStats{
   152  	logsink.Info:    &Stats.Info,
   153  	logsink.Warning: &Stats.Warning,
   154  	logsink.Error:   &Stats.Error,
   155  	logsink.Fatal:   nil,
   156  }
   157  
   158  // Level specifies a level of verbosity for V logs.  The -v flag is of type
   159  // Level and should be modified only through the flag.Value interface.
   160  type Level int32
   161  
   162  var metaPool sync.Pool // Pool of *logsink.Meta.
   163  
   164  // metaPoolGet returns a *logsink.Meta from metaPool as both an interface and a
   165  // pointer, allocating a new one if necessary.  (Returning the interface value
   166  // directly avoids an allocation if there was an existing pointer in the pool.)
   167  func metaPoolGet() (any, *logsink.Meta) {
   168  	if metai := metaPool.Get(); metai != nil {
   169  		return metai, metai.(*logsink.Meta)
   170  	}
   171  	meta := new(logsink.Meta)
   172  	return meta, meta
   173  }
   174  
   175  type stack bool
   176  
   177  const (
   178  	noStack   = stack(false)
   179  	withStack = stack(true)
   180  )
   181  
   182  func appendBacktrace(depth int, format string, args []any) (string, []any) {
   183  	// Capture a backtrace as a stackdump.Stack (both text and PC slice).
   184  	// Structured log sinks can extract the backtrace in whichever format they
   185  	// prefer (PCs or text), and Text sinks will include it as just another part
   186  	// of the log message.
   187  	//
   188  	// Use depth instead of depth+1 so that the backtrace always includes the
   189  	// log function itself - otherwise the reason for the trace appearing in the
   190  	// log may not be obvious to the reader.
   191  	dump := stackdump.Caller(depth)
   192  
   193  	// Add an arg and an entry in the format string for the stack dump.
   194  	//
   195  	// Copy the "args" slice to avoid a rare but serious aliasing bug
   196  	// (corrupting the caller's slice if they passed it to a non-Fatal call
   197  	// using "...").
   198  	format = format + "\n\n%v\n"
   199  	args = append(append([]any(nil), args...), dump)
   200  
   201  	return format, args
   202  }
   203  
   204  // logf acts as ctxlogf, but doesn't expect a context.
   205  func logf(depth int, severity logsink.Severity, verbose bool, stack stack, format string, args ...any) {
   206  	ctxlogf(nil, depth+1, severity, verbose, stack, format, args...)
   207  }
   208  
   209  // ctxlogf writes a log message for a log function call (or log function wrapper)
   210  // at the given depth in the current goroutine's stack.
   211  func ctxlogf(ctx context.Context, depth int, severity logsink.Severity, verbose bool, stack stack, format string, args ...any) {
   212  	now := timeNow()
   213  	_, file, line, ok := runtime.Caller(depth + 1)
   214  	if !ok {
   215  		file = "???"
   216  		line = 1
   217  	}
   218  
   219  	if stack == withStack || backtraceAt(file, line) {
   220  		format, args = appendBacktrace(depth+1, format, args)
   221  	}
   222  
   223  	metai, meta := metaPoolGet()
   224  	*meta = logsink.Meta{
   225  		Context:  ctx,
   226  		Time:     now,
   227  		File:     file,
   228  		Line:     line,
   229  		Depth:    depth + 1,
   230  		Severity: severity,
   231  		Verbose:  verbose,
   232  		Thread:   int64(pid),
   233  	}
   234  	sinkf(meta, format, args...)
   235  	// Clear pointer fields so they can be garbage collected early.
   236  	meta.Context = nil
   237  	meta.Stack = nil
   238  	metaPool.Put(metai)
   239  }
   240  
   241  func sinkf(meta *logsink.Meta, format string, args ...any) {
   242  	meta.Depth++
   243  	n, err := logsink.Printf(meta, format, args...)
   244  	if stats := severityStats[meta.Severity]; stats != nil {
   245  		atomic.AddInt64(&stats.lines, 1)
   246  		atomic.AddInt64(&stats.bytes, int64(n))
   247  	}
   248  
   249  	if err != nil {
   250  		logsink.Printf(meta, "glog: exiting because of error: %s", err)
   251  		sinks.file.Flush()
   252  		os.Exit(2)
   253  	}
   254  }
   255  
   256  // CopyStandardLogTo arranges for messages written to the Go "log" package's
   257  // default logs to also appear in the Google logs for the named and lower
   258  // severities.  Subsequent changes to the standard log's default output location
   259  // or format may break this behavior.
   260  //
   261  // Valid names are "INFO", "WARNING", "ERROR", and "FATAL".  If the name is not
   262  // recognized, CopyStandardLogTo panics.
   263  func CopyStandardLogTo(name string) {
   264  	sev, err := logsink.ParseSeverity(name)
   265  	if err != nil {
   266  		panic(fmt.Sprintf("log.CopyStandardLogTo(%q): %v", name, err))
   267  	}
   268  	// Set a log format that captures the user's file and line:
   269  	//   d.go:23: message
   270  	stdLog.SetFlags(stdLog.Lshortfile)
   271  	stdLog.SetOutput(logBridge(sev))
   272  }
   273  
   274  // NewStandardLogger returns a Logger that writes to the Google logs for the
   275  // named and lower severities.
   276  //
   277  // Valid names are "INFO", "WARNING", "ERROR", and "FATAL". If the name is not
   278  // recognized, NewStandardLogger panics.
   279  func NewStandardLogger(name string) *stdLog.Logger {
   280  	sev, err := logsink.ParseSeverity(name)
   281  	if err != nil {
   282  		panic(fmt.Sprintf("log.NewStandardLogger(%q): %v", name, err))
   283  	}
   284  	return stdLog.New(logBridge(sev), "", stdLog.Lshortfile)
   285  }
   286  
   287  // logBridge provides the Write method that enables CopyStandardLogTo to connect
   288  // Go's standard logs to the logs provided by this package.
   289  type logBridge logsink.Severity
   290  
   291  // Write parses the standard logging line and passes its components to the
   292  // logger for severity(lb).
   293  func (lb logBridge) Write(b []byte) (n int, err error) {
   294  	var (
   295  		file = "???"
   296  		line = 1
   297  		text string
   298  	)
   299  	// Split "d.go:23: message" into "d.go", "23", and "message".
   300  	if parts := bytes.SplitN(b, []byte{':'}, 3); len(parts) != 3 || len(parts[0]) < 1 || len(parts[2]) < 1 {
   301  		text = fmt.Sprintf("bad log format: %s", b)
   302  	} else {
   303  		file = string(parts[0])
   304  		text = string(parts[2][1:]) // skip leading space
   305  		line, err = strconv.Atoi(string(parts[1]))
   306  		if err != nil {
   307  			text = fmt.Sprintf("bad line number: %s", b)
   308  			line = 1
   309  		}
   310  	}
   311  
   312  	// The depth below hard-codes details of how stdlog gets here.  The alternative would be to walk
   313  	// up the stack looking for src/log/log.go but that seems like it would be
   314  	// unfortunately slow.
   315  	const stdLogDepth = 4
   316  
   317  	metai, meta := metaPoolGet()
   318  	*meta = logsink.Meta{
   319  		Time:     timeNow(),
   320  		File:     file,
   321  		Line:     line,
   322  		Depth:    stdLogDepth,
   323  		Severity: logsink.Severity(lb),
   324  		Thread:   int64(pid),
   325  	}
   326  
   327  	format := "%s"
   328  	args := []any{text}
   329  	if backtraceAt(file, line) {
   330  		format, args = appendBacktrace(meta.Depth, format, args)
   331  	}
   332  
   333  	sinkf(meta, format, args...)
   334  	metaPool.Put(metai)
   335  
   336  	return len(b), nil
   337  }
   338  
   339  // defaultFormat returns a fmt.Printf format specifier that formats its
   340  // arguments as if they were passed to fmt.Print.
   341  func defaultFormat(args []any) string {
   342  	n := len(args)
   343  	switch n {
   344  	case 0:
   345  		return ""
   346  	case 1:
   347  		return "%v"
   348  	}
   349  
   350  	b := make([]byte, 0, n*3-1)
   351  	wasString := true // Suppress leading space.
   352  	for _, arg := range args {
   353  		isString := arg != nil && reflect.TypeOf(arg).Kind() == reflect.String
   354  		if wasString || isString {
   355  			b = append(b, "%v"...)
   356  		} else {
   357  			b = append(b, " %v"...)
   358  		}
   359  		wasString = isString
   360  	}
   361  	return string(b)
   362  }
   363  
   364  // lnFormat returns a fmt.Printf format specifier that formats its arguments
   365  // as if they were passed to fmt.Println.
   366  func lnFormat(args []any) string {
   367  	if len(args) == 0 {
   368  		return "\n"
   369  	}
   370  
   371  	b := make([]byte, 0, len(args)*3)
   372  	for range args {
   373  		b = append(b, "%v "...)
   374  	}
   375  	b[len(b)-1] = '\n' // Replace the last space with a newline.
   376  	return string(b)
   377  }
   378  
   379  // Verbose is a boolean type that implements Infof (like Printf) etc.
   380  // See the documentation of V for more information.
   381  type Verbose bool
   382  
   383  // V reports whether verbosity at the call site is at least the requested level.
   384  // The returned value is a boolean of type Verbose, which implements Info, Infoln
   385  // and Infof. These methods will write to the Info log if called.
   386  // Thus, one may write either
   387  //
   388  //	if glog.V(2) { glog.Info("log this") }
   389  //
   390  // or
   391  //
   392  //	glog.V(2).Info("log this")
   393  //
   394  // The second form is shorter but the first is cheaper if logging is off because it does
   395  // not evaluate its arguments.
   396  //
   397  // Whether an individual call to V generates a log record depends on the setting of
   398  // the -v and --vmodule flags; both are off by default. If the level in the call to
   399  // V is at most the value of -v, or of -vmodule for the source file containing the
   400  // call, the V call will log.
   401  func V(level Level) Verbose {
   402  	return VDepth(1, level)
   403  }
   404  
   405  // VDepth acts as V but uses depth to determine which call frame to check vmodule for.
   406  // VDepth(0, level) is the same as V(level).
   407  func VDepth(depth int, level Level) Verbose {
   408  	return Verbose(verboseEnabled(depth+1, level))
   409  }
   410  
   411  // Info is equivalent to the global Info function, guarded by the value of v.
   412  // See the documentation of V for usage.
   413  func (v Verbose) Info(args ...any) {
   414  	v.InfoDepth(1, args...)
   415  }
   416  
   417  // InfoDepth is equivalent to the global InfoDepth function, guarded by the value of v.
   418  // See the documentation of V for usage.
   419  func (v Verbose) InfoDepth(depth int, args ...any) {
   420  	if v {
   421  		logf(depth+1, logsink.Info, true, noStack, defaultFormat(args), args...)
   422  	}
   423  }
   424  
   425  // InfoDepthf is equivalent to the global InfoDepthf function, guarded by the value of v.
   426  // See the documentation of V for usage.
   427  func (v Verbose) InfoDepthf(depth int, format string, args ...any) {
   428  	if v {
   429  		logf(depth+1, logsink.Info, true, noStack, format, args...)
   430  	}
   431  }
   432  
   433  // Infoln is equivalent to the global Infoln function, guarded by the value of v.
   434  // See the documentation of V for usage.
   435  func (v Verbose) Infoln(args ...any) {
   436  	if v {
   437  		logf(1, logsink.Info, true, noStack, lnFormat(args), args...)
   438  	}
   439  }
   440  
   441  // Infof is equivalent to the global Infof function, guarded by the value of v.
   442  // See the documentation of V for usage.
   443  func (v Verbose) Infof(format string, args ...any) {
   444  	if v {
   445  		logf(1, logsink.Info, true, noStack, format, args...)
   446  	}
   447  }
   448  
   449  // InfoContext is equivalent to the global InfoContext function, guarded by the value of v.
   450  // See the documentation of V for usage.
   451  func (v Verbose) InfoContext(ctx context.Context, args ...any) {
   452  	v.InfoContextDepth(ctx, 1, args...)
   453  }
   454  
   455  // InfoContextf is equivalent to the global InfoContextf function, guarded by the value of v.
   456  // See the documentation of V for usage.
   457  func (v Verbose) InfoContextf(ctx context.Context, format string, args ...any) {
   458  	if v {
   459  		ctxlogf(ctx, 1, logsink.Info, true, noStack, format, args...)
   460  	}
   461  }
   462  
   463  // InfoContextDepth is equivalent to the global InfoContextDepth function, guarded by the value of v.
   464  // See the documentation of V for usage.
   465  func (v Verbose) InfoContextDepth(ctx context.Context, depth int, args ...any) {
   466  	if v {
   467  		ctxlogf(ctx, depth+1, logsink.Info, true, noStack, defaultFormat(args), args...)
   468  	}
   469  }
   470  
   471  // InfoContextDepthf is equivalent to the global InfoContextDepthf function, guarded by the value of v.
   472  // See the documentation of V for usage.
   473  func (v Verbose) InfoContextDepthf(ctx context.Context, depth int, format string, args ...any) {
   474  	if v {
   475  		ctxlogf(ctx, depth+1, logsink.Info, true, noStack, format, args...)
   476  	}
   477  }
   478  
   479  // Info logs to the INFO log.
   480  // Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
   481  func Info(args ...any) {
   482  	InfoDepth(1, args...)
   483  }
   484  
   485  // InfoDepth calls Info from a different depth in the call stack.
   486  // This enables a callee to emit logs that use the callsite information of its caller
   487  // or any other callers in the stack. When depth == 0, the original callee's line
   488  // information is emitted. When depth > 0, depth frames are skipped in the call stack
   489  // and the final frame is treated like the original callee to Info.
   490  func InfoDepth(depth int, args ...any) {
   491  	logf(depth+1, logsink.Info, false, noStack, defaultFormat(args), args...)
   492  }
   493  
   494  // InfoDepthf acts as InfoDepth but with format string.
   495  func InfoDepthf(depth int, format string, args ...any) {
   496  	logf(depth+1, logsink.Info, false, noStack, format, args...)
   497  }
   498  
   499  // Infoln logs to the INFO log.
   500  // Arguments are handled in the manner of fmt.Println; a newline is appended if missing.
   501  func Infoln(args ...any) {
   502  	logf(1, logsink.Info, false, noStack, lnFormat(args), args...)
   503  }
   504  
   505  // Infof logs to the INFO log.
   506  // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
   507  func Infof(format string, args ...any) {
   508  	logf(1, logsink.Info, false, noStack, format, args...)
   509  }
   510  
   511  // InfoContext is like [Info], but with an extra [context.Context] parameter. The
   512  // context is used to pass the Trace Context to log sinks.
   513  func InfoContext(ctx context.Context, args ...any) {
   514  	InfoContextDepth(ctx, 1, args...)
   515  }
   516  
   517  // InfoContextf is like [Infof], but with an extra [context.Context] parameter. The
   518  // context is used to pass the Trace Context to log sinks.
   519  func InfoContextf(ctx context.Context, format string, args ...any) {
   520  	ctxlogf(ctx, 1, logsink.Info, false, noStack, format, args...)
   521  }
   522  
   523  // InfoContextDepth is like [InfoDepth], but with an extra [context.Context] parameter. The
   524  // context is used to pass the Trace Context to log sinks.
   525  func InfoContextDepth(ctx context.Context, depth int, args ...any) {
   526  	ctxlogf(ctx, depth+1, logsink.Info, false, noStack, defaultFormat(args), args...)
   527  }
   528  
   529  // InfoContextDepthf is like [InfoDepthf], but with an extra [context.Context] parameter. The
   530  // context is used to pass the Trace Context to log sinks.
   531  func InfoContextDepthf(ctx context.Context, depth int, format string, args ...any) {
   532  	ctxlogf(ctx, depth+1, logsink.Info, false, noStack, format, args...)
   533  }
   534  
   535  // Warning logs to the WARNING and INFO logs.
   536  // Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
   537  func Warning(args ...any) {
   538  	WarningDepth(1, args...)
   539  }
   540  
   541  // WarningDepth acts as Warning but uses depth to determine which call frame to log.
   542  // WarningDepth(0, "msg") is the same as Warning("msg").
   543  func WarningDepth(depth int, args ...any) {
   544  	logf(depth+1, logsink.Warning, false, noStack, defaultFormat(args), args...)
   545  }
   546  
   547  // WarningDepthf acts as Warningf but uses depth to determine which call frame to log.
   548  // WarningDepthf(0, "msg") is the same as Warningf("msg").
   549  func WarningDepthf(depth int, format string, args ...any) {
   550  	logf(depth+1, logsink.Warning, false, noStack, format, args...)
   551  }
   552  
   553  // Warningln logs to the WARNING and INFO logs.
   554  // Arguments are handled in the manner of fmt.Println; a newline is appended if missing.
   555  func Warningln(args ...any) {
   556  	logf(1, logsink.Warning, false, noStack, lnFormat(args), args...)
   557  }
   558  
   559  // Warningf logs to the WARNING and INFO logs.
   560  // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
   561  func Warningf(format string, args ...any) {
   562  	logf(1, logsink.Warning, false, noStack, format, args...)
   563  }
   564  
   565  // WarningContext is like [Warning], but with an extra [context.Context] parameter. The
   566  // context is used to pass the Trace Context to log sinks.
   567  func WarningContext(ctx context.Context, args ...any) {
   568  	WarningContextDepth(ctx, 1, args...)
   569  }
   570  
   571  // WarningContextf is like [Warningf], but with an extra [context.Context] parameter. The
   572  // context is used to pass the Trace Context to log sinks.
   573  func WarningContextf(ctx context.Context, format string, args ...any) {
   574  	ctxlogf(ctx, 1, logsink.Warning, false, noStack, format, args...)
   575  }
   576  
   577  // WarningContextDepth is like [WarningDepth], but with an extra [context.Context] parameter. The
   578  // context is used to pass the Trace Context to log sinks.
   579  func WarningContextDepth(ctx context.Context, depth int, args ...any) {
   580  	ctxlogf(ctx, depth+1, logsink.Warning, false, noStack, defaultFormat(args), args...)
   581  }
   582  
   583  // WarningContextDepthf is like [WarningDepthf], but with an extra [context.Context] parameter. The
   584  // context is used to pass the Trace Context to log sinks.
   585  func WarningContextDepthf(ctx context.Context, depth int, format string, args ...any) {
   586  	ctxlogf(ctx, depth+1, logsink.Warning, false, noStack, format, args...)
   587  }
   588  
   589  // Error logs to the ERROR, WARNING, and INFO logs.
   590  // Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
   591  func Error(args ...any) {
   592  	ErrorDepth(1, args...)
   593  }
   594  
   595  // ErrorDepth acts as Error but uses depth to determine which call frame to log.
   596  // ErrorDepth(0, "msg") is the same as Error("msg").
   597  func ErrorDepth(depth int, args ...any) {
   598  	logf(depth+1, logsink.Error, false, noStack, defaultFormat(args), args...)
   599  }
   600  
   601  // ErrorDepthf acts as Errorf but uses depth to determine which call frame to log.
   602  // ErrorDepthf(0, "msg") is the same as Errorf("msg").
   603  func ErrorDepthf(depth int, format string, args ...any) {
   604  	logf(depth+1, logsink.Error, false, noStack, format, args...)
   605  }
   606  
   607  // Errorln logs to the ERROR, WARNING, and INFO logs.
   608  // Arguments are handled in the manner of fmt.Println; a newline is appended if missing.
   609  func Errorln(args ...any) {
   610  	logf(1, logsink.Error, false, noStack, lnFormat(args), args...)
   611  }
   612  
   613  // Errorf logs to the ERROR, WARNING, and INFO logs.
   614  // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
   615  func Errorf(format string, args ...any) {
   616  	logf(1, logsink.Error, false, noStack, format, args...)
   617  }
   618  
   619  // ErrorContext is like [Error], but with an extra [context.Context] parameter. The
   620  // context is used to pass the Trace Context to log sinks.
   621  func ErrorContext(ctx context.Context, args ...any) {
   622  	ErrorContextDepth(ctx, 1, args...)
   623  }
   624  
   625  // ErrorContextf is like [Errorf], but with an extra [context.Context] parameter. The
   626  // context is used to pass the Trace Context to log sinks.
   627  func ErrorContextf(ctx context.Context, format string, args ...any) {
   628  	ctxlogf(ctx, 1, logsink.Error, false, noStack, format, args...)
   629  }
   630  
   631  // ErrorContextDepth is like [ErrorDepth], but with an extra [context.Context] parameter. The
   632  // context is used to pass the Trace Context to log sinks.
   633  func ErrorContextDepth(ctx context.Context, depth int, args ...any) {
   634  	ctxlogf(ctx, depth+1, logsink.Error, false, noStack, defaultFormat(args), args...)
   635  }
   636  
   637  // ErrorContextDepthf is like [ErrorDepthf], but with an extra [context.Context] parameter. The
   638  // context is used to pass the Trace Context to log sinks.
   639  func ErrorContextDepthf(ctx context.Context, depth int, format string, args ...any) {
   640  	ctxlogf(ctx, depth+1, logsink.Error, false, noStack, format, args...)
   641  }
   642  
   643  func ctxfatalf(ctx context.Context, depth int, format string, args ...any) {
   644  	ctxlogf(ctx, depth+1, logsink.Fatal, false, withStack, format, args...)
   645  	sinks.file.Flush()
   646  
   647  	err := abortProcess() // Should not return.
   648  
   649  	// Failed to abort the process using signals.  Dump a stack trace and exit.
   650  	Errorf("abortProcess returned unexpectedly: %v", err)
   651  	sinks.file.Flush()
   652  	pprof.Lookup("goroutine").WriteTo(os.Stderr, 1)
   653  	os.Exit(2) // Exit with the same code as the default SIGABRT handler.
   654  }
   655  
   656  func fatalf(depth int, format string, args ...any) {
   657  	ctxfatalf(nil, depth+1, format, args...)
   658  }
   659  
   660  // Fatal logs to the FATAL, ERROR, WARNING, and INFO logs,
   661  // including a stack trace of all running goroutines, then calls os.Exit(2).
   662  // Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
   663  func Fatal(args ...any) {
   664  	FatalDepth(1, args...)
   665  }
   666  
   667  // FatalDepth acts as Fatal but uses depth to determine which call frame to log.
   668  // FatalDepth(0, "msg") is the same as Fatal("msg").
   669  func FatalDepth(depth int, args ...any) {
   670  	fatalf(depth+1, defaultFormat(args), args...)
   671  }
   672  
   673  // FatalDepthf acts as Fatalf but uses depth to determine which call frame to log.
   674  // FatalDepthf(0, "msg") is the same as Fatalf("msg").
   675  func FatalDepthf(depth int, format string, args ...any) {
   676  	fatalf(depth+1, format, args...)
   677  }
   678  
   679  // Fatalln logs to the FATAL, ERROR, WARNING, and INFO logs,
   680  // including a stack trace of all running goroutines, then calls os.Exit(2).
   681  // Arguments are handled in the manner of fmt.Println; a newline is appended if missing.
   682  func Fatalln(args ...any) {
   683  	fatalf(1, lnFormat(args), args...)
   684  }
   685  
   686  // Fatalf logs to the FATAL, ERROR, WARNING, and INFO logs,
   687  // including a stack trace of all running goroutines, then calls os.Exit(2).
   688  // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
   689  func Fatalf(format string, args ...any) {
   690  	fatalf(1, format, args...)
   691  }
   692  
   693  // FatalContext is like [Fatal], but with an extra [context.Context] parameter. The
   694  // context is used to pass the Trace Context to log sinks.
   695  func FatalContext(ctx context.Context, args ...any) {
   696  	FatalContextDepth(ctx, 1, args...)
   697  }
   698  
   699  // FatalContextf is like [Fatalf], but with an extra [context.Context] parameter. The
   700  // context is used to pass the Trace Context to log sinks.
   701  func FatalContextf(ctx context.Context, format string, args ...any) {
   702  	ctxfatalf(ctx, 1, format, args...)
   703  }
   704  
   705  // FatalContextDepth is like [FatalDepth], but with an extra [context.Context] parameter. The
   706  // context is used to pass the Trace Context to log sinks.
   707  func FatalContextDepth(ctx context.Context, depth int, args ...any) {
   708  	ctxfatalf(ctx, depth+1, defaultFormat(args), args...)
   709  }
   710  
   711  // FatalContextDepthf is like [FatalDepthf], but with an extra [context.Context] parameter.
   712  func FatalContextDepthf(ctx context.Context, depth int, format string, args ...any) {
   713  	ctxfatalf(ctx, depth+1, format, args...)
   714  }
   715  
   716  func ctxexitf(ctx context.Context, depth int, format string, args ...any) {
   717  	ctxlogf(ctx, depth+1, logsink.Fatal, false, noStack, format, args...)
   718  	sinks.file.Flush()
   719  	os.Exit(1)
   720  }
   721  
   722  func exitf(depth int, format string, args ...any) {
   723  	ctxexitf(nil, depth+1, format, args...)
   724  }
   725  
   726  // Exit logs to the FATAL, ERROR, WARNING, and INFO logs, then calls os.Exit(1).
   727  // Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
   728  func Exit(args ...any) {
   729  	ExitDepth(1, args...)
   730  }
   731  
   732  // ExitDepth acts as Exit but uses depth to determine which call frame to log.
   733  // ExitDepth(0, "msg") is the same as Exit("msg").
   734  func ExitDepth(depth int, args ...any) {
   735  	exitf(depth+1, defaultFormat(args), args...)
   736  }
   737  
   738  // ExitDepthf acts as Exitf but uses depth to determine which call frame to log.
   739  // ExitDepthf(0, "msg") is the same as Exitf("msg").
   740  func ExitDepthf(depth int, format string, args ...any) {
   741  	exitf(depth+1, format, args...)
   742  }
   743  
   744  // Exitln logs to the FATAL, ERROR, WARNING, and INFO logs, then calls os.Exit(1).
   745  func Exitln(args ...any) {
   746  	exitf(1, lnFormat(args), args...)
   747  }
   748  
   749  // Exitf logs to the FATAL, ERROR, WARNING, and INFO logs, then calls os.Exit(1).
   750  // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
   751  func Exitf(format string, args ...any) {
   752  	exitf(1, format, args...)
   753  }
   754  
   755  // ExitContext is like [Exit], but with an extra [context.Context] parameter. The
   756  // context is used to pass the Trace Context to log sinks.
   757  func ExitContext(ctx context.Context, args ...any) {
   758  	ExitContextDepth(ctx, 1, args...)
   759  }
   760  
   761  // ExitContextf is like [Exitf], but with an extra [context.Context] parameter. The
   762  // context is used to pass the Trace Context to log sinks.
   763  func ExitContextf(ctx context.Context, format string, args ...any) {
   764  	ctxexitf(ctx, 1, format, args...)
   765  }
   766  
   767  // ExitContextDepth is like [ExitDepth], but with an extra [context.Context] parameter. The
   768  // context is used to pass the Trace Context to log sinks.
   769  func ExitContextDepth(ctx context.Context, depth int, args ...any) {
   770  	ctxexitf(ctx, depth+1, defaultFormat(args), args...)
   771  }
   772  
   773  // ExitContextDepthf is like [ExitDepthf], but with an extra [context.Context] parameter. The
   774  // context is used to pass the Trace Context to log sinks.
   775  func ExitContextDepthf(ctx context.Context, depth int, format string, args ...any) {
   776  	ctxexitf(ctx, depth+1, format, args...)
   777  }
   778  

View as plain text