- Principles
- Motivation
- Getting started
- Implementations
- Bridges (and their hooks)
- Development
- Contributing
- License
If you want to log something it should be easy, intuitive and straight forward. This should work either for very small applications (just one file) or big applications, too.
You should not care about the implementation, you want just to use it.
If you want to implement a new logger you should not be required to educate your users how to use it.
You just want to write a logger for a user-case. Someone else should take care of the public API.
A logging framework should not be both, by design: API and implementation.
You want to have one API and the possibility to use whatever implementation you want.
Regardless how used or implemented you want that just everything sticks together, and you're not ending up over and over again in writing new wrappers or in worst-case see different styled log messages in the console.
Every library should just work transparently with one logger.
I've tried out many logging frameworks for Golang. They're coming with different promises, like:
-
There are ones which tries to be "blazing fast"; focussing on be fast and non-blocking to be able to log as much log events as possible.
-
Other ones are trying to be as minimalistic as possible. Just using a very few amount of code to work.
-
...
...but overall they're just violating the Principles listed above and we're ending up in just mess.
Slf4g is born out of feeling this pain every day again and be simply annoyed. It is inspired by Simple Logging Facade for Java (SLF4J), which was born out of the same pains; but obviously in Java before. Since SLF4J exists, and it is now broadly used in Java, nobody does experience this issues any longer.
It is very easy to use slf4g (as the naming is promising
-
Import the API to your current project (in best with a Go Modules project)
$ go get -u github.com/echocat/slf4g
-
Select one of the implementation of slf4g and import it too (see Implementations). Example:
$ go get -u github.com/echocat/slf4g/native
ℹ️ If you do not pick one implementation the fallback logger is used. It works, too, but is obviously less powerful and is not customizable. It is comparable with the SDK based logger.
-
Configure your application to use the selected logger implementation:
This should be only done in
main/main.go:package main import ( _ "github.com/echocat/slf4g/native" ) func main() { // do your stuff... }
-
In each package create a logger variable, in best case you create a file named
common.goorpackage.gowhich will contain it:package foo import ( "github.com/echocat/slf4g" ) var logger = log.GetLoggerForCurrentPackage()
-
Now you're ready to go. In every file of this package you can do stuff, like:
package foo func MyFunction() { logger.Info("Hello, world!") if !loaded { logger.With("field", 123). Warn("That's not great.") } if err := doSomething(); err != nil { logger.WithError(err). Error("Doh!") } }
For sure, you're able to simply do stuff like that (although to ensure interoperability this is not recommended):
package foo import ( "github.com/echocat/slf4g" ) func MyFunction() { log.Info("Hello, world!") if !loaded { log.With("field", 123). Warn("That's not great.") } if err := doSomething(); err != nil { log.WithError(err). Error("Doh!") } }
Done. Enjoy!
-
native: Reference implementation of slf4g, best use for most applications.
-
testlog: Ensure that everything which is logged within test by slf4g appears correctly within tests.
-
recording: Will record everything which is logged by slf4g and can then be asserted inside test cases.
There are several bridges available to use slf4g in other frameworks:
- sdk/bridge to implement the Go's SDK log interface.
- sdk/bridge/slog to implement the Go's SDK slog interface.
- github.com/echocat/slf4g-logr to implement github.com/go-logr/logr.
- github.com/echocat/slf4g-logrus to implement github.com/sirupsen/logrus.
- github.com/echocat/slf4g-klog to implement k8s.io/klog/v2.
These are automatically registering itself by simply calling an anonymous import (instead of explicitly importing - see Bridges above), like:
package main
import (
// For hook into SDK's log package
_ "github.com/echocat/slf4g/hooks/sdklog"
// For hook into SDK's log/slog package
_ "github.com/echocat/slf4g/hooks/sdkslog"
// For hook into github.com/sirupsen/logrus
_ "github.com/echocat/slf4g-logrus/logrus2slf4g/hook"
// For hook into Kubernetes' k8s.io/klog/v2
_ "github.com/echocat/slf4g-klog/bridge/hook"
)The development toolchain and common build commands are managed with mise 2026.8.6 or newer. Trust the reviewed project configuration and install the pinned default toolchain once:
mise trust
mise installTasks automatically install additional pinned tools and Go versions when they are needed.
Race-detector tasks require a working C toolchain, such as Xcode Command Line Tools on macOS, GCC on Linux, or MinGW-w64 on Windows.
Use mise tasks to list every available task. The main entry points are:
| Command | Purpose |
|---|---|
mise run build |
Build all Go modules |
mise run format |
Format all Go modules |
mise run test |
Test all Go modules |
mise run test:race |
Test all modules with the race detector |
mise run test:matrix |
Run the supported Go version matrix |
mise run coverage |
Create a coverage profile in each module |
mise run lint |
Run golangci-lint for all modules |
mise run vet |
Run go vet for all modules |
mise run tidy:check |
Verify that all module files are tidy |
mise run actionlint |
Validate GitHub Actions workflows |
mise run vuln |
Scan all modules for known vulnerabilities |
mise run tools:lock |
Refresh tool lockfile metadata |
mise run tools:update |
Update locked tool versions |
mise run check |
Run the standard local quality gate |
mise run check:full |
Also run the Go matrix and vulnerability scans |
Module-specific tasks such as mise run test:native and
mise run lint:eventlog are available for focused work.
Tool version requests are declared in mise.toml; the committed lockfiles pin
the exact versions and checksums used locally and in CI.
The GitHub Actions workflows use the same pinned tools and tasks, including Go
1.18 as the minimum supported version of the root module.
Release preparation and the automated native-module tagging process are documented in RELEASING.md.
slf4g is an open source project by echocat. So if you want to make this project even better, you can contribute to this project on Github by fork us.
If you commit code to this project, you have to accept that this code will be released under the license of this project.
See the LICENSE file.