A library that provides structured and formatted logging for the Go programming language.
Find a file
2026-03-25 02:17:45 -07:00
append.go change code change and refactor 2025-12-07 13:24:51 -08:00
append_examples_test.go change code change and refactor 2025-12-07 13:24:51 -08:00
append_test.go change code change and refactor 2025-12-07 13:24:51 -08:00
calltrace.go restored call-trace 2025-12-05 15:11:07 -08:00
chainid.go change code change and refactor 2025-12-07 13:24:51 -08:00
corelogger.go changed some ansi color escape codes 2025-12-10 06:04:00 -08:00
corelogger_log_test.go big code change and refactor 2025-12-07 16:46:03 -08:00
default.go flags 2025-12-09 20:20:17 -08:00
demostrate.go demostrate 2025-12-10 06:56:03 -08:00
doc.go docs 2025-12-10 06:41:59 -08:00
errors.go erorr 2026-03-25 01:56:51 -07:00
field.go .Log and docs 2025-12-07 14:45:32 -08:00
flags.go erorr 2026-03-25 01:56:51 -07:00
formattedlogger.go wrapped errors 2025-12-10 10:02:37 -08:00
formattedlogger_alertf_test.go big code change and refactor 2025-12-07 18:30:57 -08:00
formattedlogger_debugf_test.go big code change and refactor 2025-12-07 18:30:57 -08:00
formattedlogger_errorf_test.go big code change and refactor 2025-12-07 18:30:57 -08:00
formattedlogger_highlightf_test.go big code change and refactor 2025-12-07 18:30:57 -08:00
formattedlogger_informf_test.go big code change and refactor 2025-12-07 18:30:57 -08:00
formattedlogger_tracef_test.go big code change and refactor 2025-12-07 18:30:57 -08:00
formattedlogger_warnf_test.go big code change and refactor 2025-12-07 18:30:57 -08:00
go.mod erorr 2026-03-25 01:56:51 -07:00
go.sum erorr 2026-03-25 01:56:51 -07:00
leveledlogger.go make flags work again 2026-03-25 02:17:45 -07:00
leveledlogger_alert.go wrapped errors 2025-12-10 10:08:23 -08:00
leveledlogger_begin.go constants 2025-12-07 22:25:50 -08:00
leveledlogger_debug.go constants 2025-12-07 22:25:50 -08:00
leveledlogger_end.go constants 2025-12-07 22:25:50 -08:00
leveledlogger_error.go wrapped errors 2025-12-10 10:08:23 -08:00
leveledlogger_fatal.go constants 2025-12-07 22:25:50 -08:00
leveledlogger_highlight.go constants 2025-12-07 22:25:50 -08:00
leveledlogger_inform.go correction 2025-12-09 20:23:49 -08:00
leveledlogger_mute.go big code change and refactor 2025-12-07 16:46:03 -08:00
leveledlogger_panic.go constants 2025-12-07 22:25:50 -08:00
leveledlogger_trace.go constants 2025-12-07 22:25:50 -08:00
leveledlogger_unmute.go big code change and refactor 2025-12-07 16:46:03 -08:00
leveledlogger_warn.go constants 2025-12-07 22:25:50 -08:00
leveledlogger_with.go big code change and refactor 2025-12-07 18:30:57 -08:00
levels.go change code change and refactor 2025-12-07 13:24:51 -08:00
LICENSE changelog.ca -> reiver.link 2025-12-07 19:42:39 -08:00
logger.go wrapped errors 2025-12-10 10:02:37 -08:00
magickeys.go docs 2025-12-07 16:08:00 -08:00
mutedlogger.go correction 2025-12-07 20:11:25 -08:00
README.md docs 2025-12-09 15:49:24 -08:00
trouble.go dealing with a nil error case 2025-12-10 06:32:14 -08:00

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

GoDoc

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