Golog is a logger which support tracing and other custom behaviors out of the box. Blazing fast and simple to use.

Overview

GOLOG

codecov

Golog is an opinionated Go logger with simple APIs and configurable behavior.

Why another logger?

Golog is designed to address mainly two issues:

Reduce the amount of PII (personally identifiable information) data in logs

Golog exposes APIs which does not allow to simply introduce a struct or a map as part of the log fields.

This design pushes the consumers of this library to care about PII data and aim to reduce as much as possible the amount of data which can be logged.

It is possible to extend the logger behavior for handling complex data type by implementing an interface as shown in the "Custom field type" section.

Add tracing and other extra data into the logging behavior

Golog expects to have a context passed down to the logging API.

The context.Context in Go is usually the holder for tracing information and embedding one of the decorators available to the logger plugs this behavior for free in all the places where the logger is used.

Examples

Logger

The Logger interface is implemented by the StdLogger type. It allows you to write log messages.

An example of its usage may look like this:

golog.With(golog.Fields{
   golog.Bool("key name", true),
   golog.Strings("another key name", []string{"one", "two"}),
}).Error(ctx, "log message here")

To override the default logger you can use the SetLogger API as shown here:

// create a new custom logger
logger := golog.New(
   golog.NewBufWriter(
       golog.NewJsonEncoder(golog.DefaultJsonConfig()),
       bufio.NewWriter(os.StdErr),
       golog.DefaultErrorHandler(),
   ),
   golog.NewLevelCheckerOption(golog.WARN), 
   // any other option you may want to pass
)

// set the custom logger as the global one 
golog.SetLogger(logger)

CheckLogger

The CheckLogger interface is implemented by the StdLogger type. It allows you to write log messages allowing to set fields only if the log message will be written.

For example if the min log level set is higher than the one which will be logged, as shown in this example, there will be no extra data allocation as well as having a huge performance improvement::

if checked, ok := golog.CheckDebug(ctx, "This is a message"); ok {
    checked.Log(golog.Fields{
        golog.Bool("key name", true),
        golog.Strings("another key name", []string{"one", "two"}),
    })
}

To override the default check logger you can use the SetCheckLogger API as shown here:

// create a new custom logger
logger := golog.New(
   golog.NewBufWriter(
       golog.NewJsonEncoder(golog.DefaultJsonConfig()),
       bufio.NewWriter(os.StdErr),
       golog.DefaultErrorHandler(),
   ),
   golog.NewLevelCheckerOption(golog.WARN), 
   // any other option you may want to pass
)

// set the custom check logger as the global one 
golog.SetCheckLogger(logger)

Standard Library support

Golog Writer can be used by the go log package as well as output

w := &BufWriter{
    Encoder:         enc,
    Writer:          bufio.NewWriter(buf),
    ErrHandler:      errHandler.Handle,
    DefaultLogLevel: DEBUG, //! This will be the log level used for all the logs by the stdlib logger
}

log.SetOutput(w)
log.Println("your log message here...")

Customization

Golog provides multiple ways to customize behaviors

Decorators

A decorator is a function that gets executed before a log message gets written, allowing to inject only once a recurring logging behavior to modify the log message.

An example may be adding a trace and span ids to the log:

var customTraceDecorator golog.DecoratorFunc = func(e golog.Entry) golog.Entry {
    span := trace.FromContext(e.Context()).SpanContext()

    return e.With(golog.Fields{
        golog.String("span_id", span.SpanID.String()),
        golog.String("trace_id", span.TraceID.String()),
    })
}

var logger golog.Logger = golog.New(
    // other arguments here
    golog.OptionFunc(func(l golog.StdLogger) golog.StdLogger {
        return l.WithDecorator(customTraceDecorator)
    }),
)

Out of the box are provided some decorators for tracing purposes in the opencensus and opentelemetry packages, PRs are welcome to add more behavior.

Checkers

A checker is a function that gets executed before a log message gets decorated, allowing to skip the decoration and the writing of a log entry due to custom logic.

An example may be skipping a log if the context doesn't have a value:

var customCtxValueChecker golog.Checker = golog.CheckerFunc(func(e golog.Entry) bool {
    if _, ok := e.Context().Value("key").(string); !ok {
        return false
    }

    return true
})

var logger golog.Logger = golog.New(
    // other arguments here
    golog.OptionFunc(func(l golog.StdLogger) golog.StdLogger {
        return l.WithChecker(customCtxValueChecker)
    }),
)

Out of the box are provided some checkers for skipping log with level lower than an expected one.

Example usage:

var logger golog.Logger = golog.New(
    // other arguments here
    golog.NewLevelCheckerOption(golog.INFO),
)

Custom field type

Logging complex data structure is not intentionally supported out of the box, Golog expects you to implement a FieldMapper interface.

An example may be something like this:

// The complex data structure to log
type User struct {
	ID              string
	Email           string
	Password        string
	ReferenceCode   string
}

// The FieldMapper interface method to create fields out of the complex data structure
func (u User) ToFields() golog.Fields {
    return golog.Fields{
        golog.String("user_id", u.ID),
        golog.String("reference_code", u.ReferenceCode),
    }
}

//...

var u User{...} 
golog.With(golog.Mapper("user", u)).Debug(ctx, "...")

And its usage would look like this

// Example API usage
golog.With(NewUserFields(u)).Error("an error occurred")

Writers

Based on your need you may want to use different entry writers.

Golog provide you those implementations:

BufWriter

It is the standard implementation, and it can be created in this way:

w := golog.NewBufWriter(
    golog.NewJsonEncoder(golog.DefaultJsonConfig()),
    bufio.NewWriter(os.Stdout),
    golog.DefaultErrorHandler(),
    golog.INFO,
)

LeveledWriter

This implementation provides you a way to use a different writer based on the log level, with a default writer used in case there is not an override defined for a log level

var stdOutWriter golog.Writer 
var stdErrWriter golog.Writer 

w := NewLeveledWriter(
    stdOutWriter,
    golog.DefaultMuxWriterOptionFunc(golog.ERROR, stdErrWriter),
    golog.DefaultMuxWriterOptionFunc(golog.FATAL, stdErrWriter),
)

MultiWriter

This implementation simply writes an across multiple writers concurrently

var w1 golog.Writer
var w2 golog.Writer
var w3 golog.Writer
w := golog.NewMultiWriter(w1, w2, w3)

Testing utilities

The golog/test package provide a mock generated using gomock for helping developers to test the logger.

HTTP utilities

The golog/http utility package provide a simple and customizable API for adding some logging behavior on an HTTP server.

// ...
import (
    "net/http"
    
	"github.com/damianopetrungaro/golog"
    httplog "github.com/damianopetrungaro/golog/http"
)

// ...
var h http.Handler // the handler you want to decorate
var logger golog.Logger // your logger
httplog.NewHandler(h, logger, httplog.DefaultLogHandle()) // returns your decorated handler

Performances

Golog is a really fast logging solution, with a low number of allocations as well as crazy performances.

Benchmarks comparing it to logrus and zap

goos: darwin
goarch: amd64
pkg: github.com/damianopetrungaro/golog/benchmarks/logger
cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
BenchmarkLogger/golog-12                 1380526               836.7 ns/op          2842 B/op         27 allocs/op
BenchmarkLogger/zap-12                   1271785               947.1 ns/op          2836 B/op         20 allocs/op
BenchmarkLogger/logrus-12                 361929              3151 ns/op            6166 B/op         69 allocs/op
BenchmarkLogger/golog.Check-12          55652446                18.82 ns/op           64 B/op          1 allocs/op
BenchmarkLogger/zap.Check-12            1000000000               0.8118 ns/op          0 B/op          0 allocs/op
PASS
ok      github.com/damianopetrungaro/golog/benchmarks/logger    8.476s

Considering the nature of the logger and the design it has, the performances are really high.

In the future there may be a support for an even faster and zero allocations version of the logger, but the APIs exposed won't be matching the current one and there will be a different interface provided for that purpose.

More updated benchmarks can be found on this page

Note

Golog doesn't hande key deduplication.

Meaning that

golog.With(golog.Fields{
    golog.String("hello", "world"),
    golog.String("hello", "another world"),
}).Info(ctx, "no deduplication")

will print

{
  "level": "INFO",
  "message": "no deduplication",
  "hello": "world",
  "hello": "another world"
}
Issues
  • feat(sentry): use Hub from Entry's context when possible

    feat(sentry): use Hub from Entry's context when possible

    If the golog.Entry's context contains a sentry Hub, use it. If it doesn't, fallback to the hub configured for the Writer. If no hub were specified for the Writer, use the sentry.CurrentHub().

    Users should keep in mind that using a hub concurrently is not supported by sentry.

    I also took the chance to do some minor cleanup in the Writer struct and adding some comments.

    Closes #54.

    opened by Pitasi 3
  • sentry: take Hub from context or fallback to the global one

    sentry: take Hub from context or fallback to the global one

    Hi @damianopetrungaro, thank you for golog :)

    I'm trying to log errors to Sentry, and saw that you already provide a Sentry Writer. The only problem I see with it is that it must be initialized with a sentry.Hub, while in reality I think it should use the Hub contained in the context if any (see for example the Sentry http middleware usage, it's also worth pointing out that the Hub struct is not concurrent safe for writing, that's why it's cloned when not found in the context).

    I can open a PR if you want me to 😃

    opened by Pitasi 8
  • feat: support any type in encoder

    feat: support any type in encoder

    I am not convinced this project should support any type.

    Performances for this use case may be a good selling point since the implementation designed is more efficient than other loggers around.

    New benchmarks supporting any:

    goos: darwin
    goarch: amd64
    pkg: github.com/damianopetrungaro/golog/benchmarks/logger
    cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
    BenchmarkLogger/golog-12                   72630             16335 ns/op           17348 B/op        128 allocs/op
    BenchmarkLogger/zap-12                     58617             20173 ns/op           28346 B/op        125 allocs/op
    BenchmarkLogger/logrus-12                  66474             18344 ns/op           13882 B/op        172 allocs/op
    BenchmarkLogger/golog.Check-12          53974438                22.63 ns/op           64 B/op          1 allocs/op
    BenchmarkLogger/zap.Check-12            1000000000               0.8838 ns/op          0 B/op          0 allocs/op
    PASS
    ok      github.com/damianopetrungaro/golog/benchmarks/logger    6.494s
    
    opened by damianopetrungaro 1
Releases(v1.9.2)
  • v1.9.2(Jun 30, 2022)

  • v1.9.1(Jun 10, 2022)

  • v1.9.0(Jun 9, 2022)

  • v1.8.0(May 20, 2022)

  • v1.7.2(May 20, 2022)

  • v1.7.1(May 20, 2022)

  • v1.7.0(May 19, 2022)

  • v1.6.0(May 14, 2022)

  • v1.5.1(May 13, 2022)

  • v1.5.0(May 4, 2022)

  • v1.4.0(May 3, 2022)

  • v1.3.0(May 3, 2022)

  • v1.2.0(May 3, 2022)

  • v1.1.0(May 2, 2022)

  • v1.0.0(May 2, 2022)

  • v0.6.0(May 2, 2022)

  • v0.5.0(May 2, 2022)

  • v0.3.0(Apr 28, 2022)

    What's Changed

    • feat: add mux writer by @damianopetrungaro in https://github.com/damianopetrungaro/golog/pull/23
    • ci: add codecov by @damianopetrungaro in https://github.com/damianopetrungaro/golog/pull/24
    • test: cover exported functions by @damianopetrungaro in https://github.com/damianopetrungaro/golog/pull/25
    • fix: encoders handle errors as strings by @damianopetrungaro in https://github.com/damianopetrungaro/golog/pull/26

    Full Changelog: https://github.com/damianopetrungaro/golog/compare/v0.2.2...v0.3.0

    Source code(tar.gz)
    Source code(zip)
  • v0.2.2(Apr 27, 2022)

    What's Changed

    • test: fix test for multiple environment by @damianopetrungaro in https://github.com/damianopetrungaro/golog/pull/20
    • feat: add support for text encoder by @damianopetrungaro in https://github.com/damianopetrungaro/golog/pull/21

    Full Changelog: https://github.com/damianopetrungaro/golog/compare/v0.2.1...v0.2.2

    Source code(tar.gz)
    Source code(zip)
  • v0.2.1(Apr 27, 2022)

    What's Changed

    • chore: update benchmark result by @damianopetrungaro in https://github.com/damianopetrungaro/golog/pull/18
    • feat: support stack trace decorator by @damianopetrungaro in https://github.com/damianopetrungaro/golog/pull/19

    Full Changelog: https://github.com/damianopetrungaro/golog/compare/v0.2.0...v0.2.1

    Source code(tar.gz)
    Source code(zip)
  • v0.2.0(Apr 26, 2022)

    What's Changed

    • fix: add new line after each entry by @damianopetrungaro in https://github.com/damianopetrungaro/golog/pull/16
    • feat!: drop fields from entry from the json encoder by @damianopetrungaro in https://github.com/damianopetrungaro/golog/pull/17

    Full Changelog: https://github.com/damianopetrungaro/golog/compare/v0.1.0...v0.2.0

    Source code(tar.gz)
    Source code(zip)
  • v0.1.0(Apr 26, 2022)

    What's Changed

    • feat!: add support for stdlib log package by @damianopetrungaro in https://github.com/damianopetrungaro/golog/pull/15

    Full Changelog: https://github.com/damianopetrungaro/golog/compare/v0.0.1...v0.1.0

    Source code(tar.gz)
    Source code(zip)
  • v0.0.1(Apr 25, 2022)

    What's Changed

    • ci: add github action by @damianopetrungaro in https://github.com/damianopetrungaro/golog/pull/1
    • feat: add log level by @damianopetrungaro in https://github.com/damianopetrungaro/golog/pull/2
    • chore: add level comment by @damianopetrungaro in https://github.com/damianopetrungaro/golog/pull/3
    • feat: add entry by @damianopetrungaro in https://github.com/damianopetrungaro/golog/pull/4
    • feat: add logger by @damianopetrungaro in https://github.com/damianopetrungaro/golog/pull/5
    • chore: add readme by @damianopetrungaro in https://github.com/damianopetrungaro/golog/pull/6
    • feat: add tracing pkgs by @damianopetrungaro in https://github.com/damianopetrungaro/golog/pull/7
    • fix: return logger value when enriching it with new fields by @damianopetrungaro in https://github.com/damianopetrungaro/golog/pull/8
    • chore: add benchmarks for the writer by @damianopetrungaro in https://github.com/damianopetrungaro/golog/pull/9
    • feat: add base logger by @damianopetrungaro in https://github.com/damianopetrungaro/golog/pull/10
    • feat checked logger and json encoder by @damianopetrungaro in https://github.com/damianopetrungaro/golog/pull/11
    • Add checker by @damianopetrungaro in https://github.com/damianopetrungaro/golog/pull/12
    • chore: remove deocator from logger benchmark by @damianopetrungaro in https://github.com/damianopetrungaro/golog/pull/13
    • Add doc and minor API improvements by @damianopetrungaro in https://github.com/damianopetrungaro/golog/pull/14

    New Contributors

    • @damianopetrungaro made their first contribution in https://github.com/damianopetrungaro/golog/pull/1

    Full Changelog: https://github.com/damianopetrungaro/golog/commits/v0.0.1

    Source code(tar.gz)
    Source code(zip)
Owner
Damiano Petrungaro
Philosopher ego-less coder and community enthusiast, DDD lover. Creating applications in Golang & PHP since 2015.
Damiano Petrungaro
Logger - Simple logger without written with std pkg

Go-Logger Simple usage is: package main

MaskedTrench 2 Jan 2, 2022
Simple logger for Go programs. Allows custom formats for messages.

go-logger A simple go logger for easy logging in your programs. Allows setting custom format for messages. Preview Install go get github.com/apsdehal/

Amanpreet Singh 276 Jun 14, 2022
Blazing fast, structured, leveled logging in Go.

⚡ zap Blazing fast, structured, leveled logging in Go. Installation go get -u go.uber.org/zap Note that zap only supports the two most recent minor ve

Uber Go 16.2k Jun 30, 2022
Blazing fast syslog parser

A parser for Syslog messages and transports. Blazing fast Syslog parsers By @leodido. To wrap up, this package provides: a RFC5424-compliant parser an

InfluxData 418 Jun 27, 2022
Convenient Logger interface and std logger wrapper

Convenient logger interface and wrapper around std logger Interface type Logger interface { Error(err error) Debugf(format string, args ...interface

Denis Mitrofanov 1 Nov 28, 2021
Logger - A thin wrapper of uber-go/zap logger for personal project

a thin wraper of uber-go/zap logger for personal project 0. thanks uber-go/zap B

tsingson 1 Jun 16, 2022
Dead simple, super fast, zero allocation and modular logger for Golang

Onelog Onelog is a dead simple but very efficient JSON logger. It is one of the fastest JSON logger out there. Also, it is one of the logger with the

Francois Parquet 399 Jun 16, 2022
A feature-rich and easy to use logger for golang

A feature-rich and easy to use logger for golang ?? Install ?? Common Logs lumber.Success() lumber.Info() lumber.Debug() lumber.Warning()

Matthew Gleich 49 May 26, 2022
A flexible process data collection, metrics, monitoring, instrumentation, and tracing client library for Go

Package monkit is a flexible code instrumenting and data collection library. See documentation at https://godoc.org/gopkg.in/spacemonkeygo/monkit.v3 S

Space Monkey Go 463 Apr 15, 2022
CNCF Jaeger, a Distributed Tracing Platform

Jaeger - a Distributed Tracing System Jaeger, inspired by Dapper and OpenZipkin, is a distributed tracing platform created by Uber Technologies and do

Jaeger - Distributed Tracing Platform 16k Jun 29, 2022
Tool for generating OpenTelemetry tracing decorators.

tracegen Tool for generating OpenTelemetry tracing decorators. Installation go get -u github.com/KazanExpress/tracegen/cmd/... Usage tracegen generate

Marketplace Technologies 5 Apr 7, 2022
🪵 A dead simple, pretty, and feature-rich logger for golang

?? lumber ?? A dead simple, pretty, and feature-rich logger for golang ?? Install ?? Logging Functions lumber.Success() lumber.Info() lumber.Debug() l

Matt Gleich 49 May 26, 2022
A simple and super power logger for golang

The most powerfull and faster logger for golang powered by DC ?? What is this? W

Teo 7 Jan 23, 2022
Simple Yet Powerful Logger

sypl sypl provides a Simple Yet Powerful Logger built on top of the Golang sypl. A sypl logger can have many Outputs, and each Output is responsible f

Sauce Labs 9 Apr 28, 2022
simple concurrent logger

XMUS-LOGGER pure golang logger compatible with golang io standards. USAGE : logOptions := logger.LoggerOptions{ LogLevel: 6, // read more about lo

amupxm [amir hossein mokarrami far] 5 Sep 19, 2021
A simple logger API.

flog a simple logger API for Go program that save logs into a file. NOTE: This package is provided "as is" with no guarantee. Use it at your own risk

Iss Meftah 3 May 14, 2022
A simple Go JSON logger.

logger A simple JSON logger for Go. It uses a context.Context to store values which will then be logged along with each message. It is possible to rec

Shawn Milochik 1 Dec 20, 2021
A Simple logger for golang

go-logger Installation go get github.com/mo-taufiq/go-logger Quickstart package main import ( gologger "github.com/mo-taufiq/go-logger" ) func main

Moh Taufiqur Rohman 1 Jan 15, 2022
Simple Proof of Concept REST event logger.

REST Event Logger PoC I am working on this project intermittently. I have set myself a time limit of ~3hrs which includes the time to acquire and adap

Saad Ur Rahman 0 Feb 10, 2022