- Go 100%
| append.go | ||
| append_examples_test.go | ||
| append_test.go | ||
| calltrace.go | ||
| chainid.go | ||
| corelogger.go | ||
| corelogger_log_test.go | ||
| default.go | ||
| demostrate.go | ||
| doc.go | ||
| errors.go | ||
| field.go | ||
| flags.go | ||
| formattedlogger.go | ||
| formattedlogger_alertf_test.go | ||
| formattedlogger_debugf_test.go | ||
| formattedlogger_errorf_test.go | ||
| formattedlogger_highlightf_test.go | ||
| formattedlogger_informf_test.go | ||
| formattedlogger_tracef_test.go | ||
| formattedlogger_warnf_test.go | ||
| go.mod | ||
| go.sum | ||
| leveledlogger.go | ||
| leveledlogger_alert.go | ||
| leveledlogger_begin.go | ||
| leveledlogger_debug.go | ||
| leveledlogger_end.go | ||
| leveledlogger_error.go | ||
| leveledlogger_fatal.go | ||
| leveledlogger_highlight.go | ||
| leveledlogger_inform.go | ||
| leveledlogger_mute.go | ||
| leveledlogger_panic.go | ||
| leveledlogger_trace.go | ||
| leveledlogger_unmute.go | ||
| leveledlogger_warn.go | ||
| leveledlogger_with.go | ||
| levels.go | ||
| LICENSE | ||
| logger.go | ||
| magickeys.go | ||
| mutedlogger.go | ||
| README.md | ||
| trouble.go | ||
go-log
Package log provides human-friendly, structured and formatted logging that supports timing function execution, and execution tracing, for the Go programming language.
Online Documention
Online documentation, which includes examples, can be found at: http://godoc.org/codeberg.org/reiver/go-log
Example Log
Logs are meant to be legible to humans and easy to read!
By default, package log outputs logs that are human-friendly logs — while, at the same time, being machine-legible. For example:
[INFORM]
: Hello world!
_chain-id: 20251206_050128_3odqb2afk61we
_when: 2025-12-06 06:04:58.508307767 -0800 PST m=+0.008210703
_call-trace: main.webserver():main.go:82, main.main():main.go:28, runtime.main():proc.go:285, runtime.goexit():asm_amd64.s:1693
Note that there is also a color mode for the log output, to make it even more human-friendly.
(By default, the logs generated by package log are multi-line logs.
A machine can split a log file / log stream into separate logs by looking for "\n\n".)
Easy to Read Logs
This logger is opinionated —
Logs are meant to be legible to humans and easy to read!
It should be easy for a human-being to read the logs outputted from an application without any (necessary) post-processing.
For example, this — JSON on a single line — (that some software outputs as logs) is NOT (in general) human-legible:
{"L":"INFORM","_chain-id":"20251206_050128_3odqb2afk61we","_when":"2025-12-06 06:04:58.508307767 -0800 PST m=+0.008210703","msg":"Hello world!","_call-trace":"main.webserver():main.go:82, main.main():main.go:28, runtime.main():proc.go:285, runtime.goexit():asm_amd64.s:1693"}
However, the following is much more human-legible and easier to read:
[INFORM]
: Hello world!
_chain-id: 20251206_050128_3odqb2afk61we
_when: 2025-12-06 06:04:58.508307767 -0800 PST m=+0.008210703
_call-trace: main.webserver():main.go:82, main.main():main.go:28, runtime.main():proc.go:285, runtime.goexit():asm_amd64.s:1693
Log Levels
The log-levels supported by package log are:
| name | shared by | level | flag | description | example |
|---|---|---|---|---|---|
| alert | fatal, panic | 1 | v |
meant for the most severe problems — something that needs immediate attention | logger.Alertf("WTF?!?!, the database isn't there: %w", err) |
| highlight | 2 | vv |
meant for important information that should be paid attention to now | logger.Highlightf("HTTP server at: http://localhost:8080") |
|
| error | 3 | vvv |
meant for errors that matter but don't necessarily need immediate attention | logger.Errorf("API call returned an error: %w") |
|
| inform | 4 | vvvv |
meant for information that matters but doesn't necessarily need immediate attention | logger.Informf("web-server initialized") |
|
| warn | 5 | vvvvv |
meant for warnings | logger.Warnf(field.String("", "incorrect password")) |
|
| debug | begin, end | 6 | vvvvvv |
meant for debugging mode | logger.Debug(field.Int("length", len(parameters))) |
| trace | 7 | vvvvvvv |
meant for the most fine-grained level of information (ex: data dumps) | logger.Trace(field.Any("http-request", request)) |
History
This logger was first created in the year 2015 — in either September or October — and has gone through a number of changes since then.
Also, originally, this Go package was named flog (formatted logger), but was later renamed to log.
Although this logger's git repo is currently hosted at https://codeberg.org/reiver/go-log, it was previously at https://github.com/reiver/go-log, and before that was at https://github.com/reiver/go-flog.
Basic Usage
Basic usage of this logger looks like this:
logger := log.Logger(os.Stdout)
Once you have the logger, you can do things such as:
logger.Debug(stringly.String("msg", "Hello world!"))
logger.Debugf("Hello %s!", name)
logger.Inform(stringly.Uint("count", count))
logger.Informf("count = %d!", count)
Deployment Environment
Of course in a real application system you should (probably) create a different kind of logger for each deployment environment.
Even though the PrettyWritingRouter is great for a development deployment environment (i.e., "DEV") it is probably not appropriate for a production deployment environment (i.e., "PROD").
For example:
var logger log.Logger
switch deploymentEnvironment {
case "DEV":
router := log.NewPrettyWritingRouter(os.Stdout)
logger = log.New(router)
case "PROD":
verboseRouter = log.NewDiscardingRouter()
if isVerboseMode {
verboseRouter = NewCustomVerboseRouter()
}
panicDetectionRouter := log.NewFilteringRouter(NewCustomerPanicRecordingRouter(), filterOnlyPanicsFunc)
errorDetectionRouter := log.NewFilteringRouter(NewCustomerPanicRecordingRouter(), filterOnlyErrorsFunc)
router := NewFanoutRouter(verboseRouter, panicDetectionRouter, errorDetectionRouter)
logger = log.New(router)
}
Chain-ID
The _chain-id is used to link multiple logs together.
Every time you call logger.Begin() a new chain-id is created.
You might, for example, write code similar to the following:
func DoSomething(name string) {
log := logger.Begin()
defer log.End()
// ...
log.Debugf("name = %q", name)
// ...
}
And then, that would generate 3 logs all with the same chain-id, that are similar to the following:
[BEGIN]
_chain-id: 20251206_061341_2c1q343hs06qf
_when: 2025-12-06 06:13:41.088370269 -0800 PST m=+0.000520925
_call-trace: main.DoSomething():main.go:268, main.main():main.go:20, runtime.main():proc.go:285, runtime.goexit():asm_amd64.s:1693
[DEBUG]
: name = "Joe Blow"
_chain-id: 20251206_061341_2c1q343hs06qf
_when: 2025-12-06 06:13:41.08850844 -0800 PST m=+0.000659140
_call-trace: main.DoSomething():main.go:274, main.main():main.go:20, runtime.main():proc.go:285, runtime.goexit():asm_amd64.s:1693
[END]
_chain-id: 20251206_061341_2c1q343hs06qf
_when: 2025-12-06 06:13:41.088661061 -0800 PST m=+0.000811717
_call-trace: main.DoSomething():main.go:278, main.main():main.go:20, runtime.main():proc.go:285, runtime.goexit():asm_amd64.s:1693
_δt: 330.258µs
Parent-ID
The _parent-id is the _chain-id of the parent logger.
Import
To import package log use import code like the following:
import "codeberg.org/reiver/go-log"
Installation
To install package log do the following:
GOPROXY=direct go get codeberg.org/reiver/go-log
Author
Package log was written by Charles Iliya Krempeaux