glog.go 27 KB

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