Giter Site home page Giter Site logo

golog's Introduction

golog

Syntactic sugar for logging and some other cool stuff.

Implements the Adapter pattern to replace the underlying logger. By default, it uses slog, but you can create any other logger implementation by implementing the next interface:

package golog

import (
	"github.com/danteay/golog/fields"
	"github.com/danteay/golog/levels"
)

type Adapter interface {
    Log(level levels.Level, err error, logFields *fields.Fields, msg string, args ...any)
}

Requirements

  • Go 1.22+

Install

go get github.com/danteay/golog

Basic usage

Default Logger

package main

import (
	"github.com/danteay/golog"
)

func main() {
	logger := golog.New() // Set a default logger using zerolog
	logger.Info("Hello world!")
}

SetLog Fields

package main

import (
	"errors"
	"github.com/danteay/golog"
)

func main() {
	logger := golog.New() // Set a default logger using zerolog

	// Single filed
	logger.Field("key", "value").Info("Hello world!")

	// Multi field
	logger.Fields(map[string]any{"key": "value", "key2": "value2"}).Info("Hello world!")

	// Set error
	logger.Err(errors.New("error")).Info("Hello world!")
}

Configuring Zerolog adapter

Current built-in options

package main

import (
	"os"
	
    "github.com/danteay/golog"
    "github.com/danteay/golog/levels"
    "github.com/danteay/golog/adapters/zerolog"
)

func main() {
	adapter := zerolog.New(
		zerolog.WithLevel(levels.Debug),
		zerolog.Colored(),
	)
	
	logger := golog.New(golog.WithAdapter(adapter))
	
	// regular logging
}
Option Description Default
zerolog.WithLevel Sets the minimum logging level to the zerolog instance. levels.Debug
zerolog.Colored Set configuration to use a colored logging format. This is useful for local environments. false
zerolog.WithWriter Set a specific writer apart from the standard and colored outputs. If this option is used at the same time as the Colored option, it will override to use this new specific writer. null
zerolog.WithLogger Sets a preconfigured zerolog.Logger instance to use it on the adapter. If this option is set, it will omit any other option used to configure the adapter. null

Working with context fields

Context fields is a concept added on this package to store log fields that should be added to every log entry. This is useful when you want to add some fields to every log entry, but you don't want to add them manually every time.

package main

import (
    "github.com/danteay/golog"
)

func main() {
	logger := golog.New()
	logger.SetContextFields(map[string]any{"key": "value"})
	
	logger.Info("Hello world!")
	// Output: {"level":"info","time":"2021-08-22T20:00:00-05:00","message":"Hello world!","key":"value"}
	
	logger.Warn("Hello world!")
	// Output: {"level":"warn","time":"2021-08-22T20:00:00-05:00","message":"Hello world!","key":"value"}
}

If you want to remove the context fields, you can use the FlushContextFields method.

package main

import (
    "github.com/danteay/golog"
)

func main() {
	logger := golog.New()
	logger.SetContextFields(map[string]any{"key": "value"})
	
	logger.Info("Hello world!")
	// Output: {"level":"info","time":"2021-08-22T20:00:00-05:00","message":"Hello world!","key":"value"}
	
	logger.FlushContextFields()
	
	logger.Warn("Hello world!")
	// Output: {"level":"warn","time":"2021-08-22T20:00:00-05:00","message":"Hello world!"}
}

This implementation stores the context field in a default store, so any logger created on this way will share the same context fields.

If you want to create a logger with a different context fields, you should pass configure a context.Context instance with the key golog.ExecutionContextKey and a unique value that refers to the execution of the logger, for exemple a request ID.

package main

import (
	"context"
    "github.com/danteay/golog"
)

func main() {
	logger := golog.New()
	logger.SetContextFields(map[string]any{"key": "value"})
	
	logger.Info("Hello world!")
	// Output: {"level":"info","time":"2021-08-22T20:00:00-05:00","message":"Hello world!","key":"value"}
	
	ctx := context.WithValue(context.Background(), golog.ExecutionContextKey, "request-id")
	custom := golog.New().SetContext(ctx)
	custom.SetContextFields(map[string]any{"key": "custom"})
	
	custom.Warn("Hello world!")
	// Output: {"level":"warn","time":"2021-08-22T20:00:00-05:00","message":"Hello world!","key":"custom"}
}

This implementation allows you to flush the context fields for a specific logger instance, without affecting the other.

package main

import (
	"context"
	"github.com/danteay/golog"
)

func main() {
	logger := golog.New()
	logger.SetContextFields(map[string]any{"key": "value"})

	logger.Info("Hello world!")
	// Output: {"level":"info","time":"2021-08-22T20:00:00-05:00","message":"Hello world!","key":"value"}

	ctx := context.WithValue(context.Background(), golog.ExecutionContextKey, "request-id")
	custom := golog.New().SetContext(ctx)
	custom.SetContextFields(map[string]any{"key": "custom"})

	custom.Warn("Hello world!")
	// Output: {"level":"warn","time":"2021-08-22T20:00:00-05:00","message":"Hello world!","key":"custom"}

	custom.FlushContextFields()

	custom.Warn("Hello world!")
	// Output: {"level":"warn","time":"2021-08-22T20:00:00-05:00","message":"Hello world!"}
	logger.Warn("Hello world!")
	// Output: {"level":"warn","time":"2021-08-22T20:00:00-05:00","message":"Hello world!","key":"value"}
}

And if you want to flush all stored context fields no matter the logger instance, you can use the golog.FlushAllContextFields method.

Caveats

Memory leaks

Using context fields with no control may result on memory leaks. This is because the context fields are stored in a global variable that is not flushed automatically, you should not use context fields if you don't really need them.

If you use context fields with the default store you should not add new fields regularly, you should add them once at the beginning of the execution and flush them at the end of the execution.

If you use context fields with a custom store, you should flush them manually when you don't need them anymore, or when the current execution scope ends.

golog's People

Contributors

danteay avatar dependabot[bot] avatar

Stargazers

 avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.