Skip to content

🍲 Deeply configurable logging library for Go with no configuration required to start

License

Notifications You must be signed in to change notification settings

mishankov/logman

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

59 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Logman

Coverage Status CI Go Report Card


logo

Deeply configurable logging library for Go with no configuration required to start

Installation

go get -u github.com/mishankov/logman

Usage

Default logger

For basic log output to stdout, the default logger can be used:

package main

import "github.com/mishankov/logman/loggers"

func main() {
	logger := loggers.NewDefaultLogger()
	logger.Info("Hello, world!")
}

Output:

[2009-11-10 23:00:00 GMT+0000] [main.main:7] [Info] - Hello, world!

Available logging functions

Default functions

package main

import (
	"github.com/mishankov/logman"
	"github.com/mishankov/logman/loggers"
)

func main() {
	logger := loggers.NewDefaultLogger()

	logger.Debug("Hello,", "world!")
	logger.Info("Hello,", "world!")
	logger.Warn("Hello,", "world!")
	logger.Error("Hello,", "world!")
	logger.Fatal("Hello,", "world!")

	logger.Log(logman.Info, "Hello,", "world!")
}

Output:

[2009-11-10 23:00:00 GMT+0000] [main.main:11] [Debug] - Hello, world!
[2009-11-10 23:00:00 GMT+0000] [main.main:12] [Info] - Hello, world!    
[2009-11-10 23:00:00 GMT+0000] [main.main:13] [Warn] - Hello, world!    
[2009-11-10 23:00:00 GMT+0000] [main.main:14] [Error] - Hello, world!   
[2009-11-10 23:00:00 GMT+0000] [main.main:15] [Fatal] - Hello, world!   
[2009-11-10 23:00:00 GMT+0000] [main.main:17] [Info] - Hello, world!

Functions with string formatting

package main

import (
	"github.com/mishankov/logman"
	"github.com/mishankov/logman/loggers"
)

func main() {
	logger := loggers.NewDefaultLogger()

	logger.Debugf("Hello, %s!", "world")
	logger.Infof("Hello, %s!", "world")
	logger.Warnf("Hello, %s!", "world")
	logger.Errorf("Hello, %s!", "world")
	logger.Fatalf("Hello, %s!", "world")

	logger.Logf(logman.Info, "Hello, %s!", "world")
}

Output:

[2009-11-10 23:00:00 GMT+0000] [main.main:11] [Debug] - Hello, world!
[2009-11-10 23:00:00 GMT+0000] [main.main:12] [Info] - Hello, world!
[2009-11-10 23:00:00 GMT+0000] [main.main:13] [Warn] - Hello, world!
[2009-11-10 23:00:00 GMT+0000] [main.main:14] [Error] - Hello, world!
[2009-11-10 23:00:00 GMT+0000] [main.main:15] [Fatal] - Hello, world!
[2009-11-10 23:00:00 GMT+0000] [main.main:17] [Info] - Hello, world!

Structured logging

Structured logging functions allow to add key-value pairs to messages

package main

import (
	"github.com/mishankov/logman"
	"github.com/mishankov/logman/loggers"
)

func main() {
	logger := loggers.NewDefaultLogger()

	logger.Debugs("Hello, world!", "key1", "value", "key2", 1234)
	logger.Infos("Hello, world!", "key1", "value", "key2", 1234)
	logger.Warns("Hello, world!", "key1", "value", "key2", 1234)
	logger.Errors("Hello, world!", "key1", "value", "key2", 1234)
	logger.Fatals("Hello, world!", "key1", "value", "key2", 1234)

	logger.Logs(logman.Info, "Hello, world!", "key1", "value", "key2", 1234)
}

Output:

[2009-11-10 23:00:00 GMT+0000] [main.main:11] [Debug] - Hello, world! key1=value key2=1234
[2009-11-10 23:00:00 GMT+0000] [main.main:12] [Info] - Hello, world! key1=value key2=1234
[2009-11-10 23:00:00 GMT+0000] [main.main:13] [Warn] - Hello, world! key1=value key2=1234
[2009-11-10 23:00:00 GMT+0000] [main.main:14] [Error] - Hello, world! key1=value key2=1234
[2009-11-10 23:00:00 GMT+0000] [main.main:15] [Fatal] - Hello, world! key1=value key2=1234
[2009-11-10 23:00:00 GMT+0000] [main.main:17] [Info] - Hello, world! key1=value key2=1234

Logging values from context

logman supports logging methods that recieves context.Context as first parameters to log values from it. In default logger it does nothing. Only way to utilize it is to use custom or one of provided formatters (DefaultContextFormatter, JSONContextFormatter) with custom logger (more about it later).

Example:

package main

import (
	"context"
	"fmt"
	"os"

	"github.com/mishankov/logman"
	"github.com/mishankov/logman/formatters"
)

type ContextValueKey string

func (cvk ContextValueKey) String() string {
	return string(cvk)
}

const (
	ContextValueKey1 ContextValueKey = "key1"
	ContextValueKey2 ContextValueKey = "key2"
)

func main() {
	ctx := context.Background()
	ctx = context.WithValue(ctx, ContextValueKey1, "value 1")
	ctx = context.WithValue(ctx, ContextValueKey2, 4)

	logger := logman.NewLogger(os.Stdout, formatters.NewDefaultContextFormatter(formatters.DefaultTimeLayout, []fmt.Stringer{ContextValueKey1, ContextValueKey2}), nil)
	logger.DebugsCtx(ctx, "default logger", "param1", "value1")

	loggerJSON := logman.NewLogger(os.Stdout, formatters.NewJSONContextFormatter(formatters.DefaultTimeLayout, []fmt.Stringer{ContextValueKey1, ContextValueKey2}), nil)
	loggerJSON.DebugsCtx(ctx, "json logger", "param1", "value1")
}

Output:

time="2009-11-10 23:00:00 GMT+0000" level=Debug location=main.main:29 msg="default logger" key1="value 1" key2=4 param1=value1
{"key1":"value 1","key2":4,"level":"Debug","location":"main.main:32","msg":"json logger","param1":"value1","time":"2009-11-10 23:00:00 GMT+0000"}

Custom logger

You can use logman.NewLogger to create a custom logger. For example, this is how to mimic loggers.NewDefaultLogger using logman.NewLogger:

package main

import (
	"os"
	"github.com/mishankov/logman"
	"github.com/mishankov/logman/formatters"
)

func main() {
	logger := logman.NewLogger(os.Stdout, formatters.NewDefaultFormatter(formatters.DefaultFormat, formatters.DefaultTimeLayout), nil)
}

Writers

Writers output logs to some destination. Every writer should implement the io.Writer interface. Logman provides FileWriter:

package main

import "github.com/mishankov/logman/writers"

func main() {
	fw, _ := writers.NewFileWriter("test.log")
}

DefaultLogger uses os.Stdout as writer.

Formatters

Formatters format log messages before they are passed to the writer. Every formatter should implement the logman.Formatter interface. Logman provides DefaultFormatter, JSONFormatter, DefaultContextFormatter and JSONContextFormatter:

package main

import "github.com/mishankov/logman/formatters"

func main() {
	formatter := formatters.NewDefaultFormatter(formatters.DefaultFormat, formatters.DefaultTimeLayout)
	jsonFormatter := formatters.NewJSONFormatter()
}

Filters

Filters filter log messages. Every filter should implement the logman.Filter interface. Logman provides LevelFilter:

package main

import "github.com/mishankov/logman/filters"

func main() {
	filter := filters.NewLevelFilter(logman.Info)
}

Examples

Let's see how to create a custom logger that outputs Error or higher level messages in JSON format to a file:

package main

import (
	"github.com/mishankov/logman"
	"github.com/mishankov/logman/filters"
	"github.com/mishankov/logman/formatters"
	"github.com/mishankov/logman/writers"
)

func main() {
	fw, _ := writers.NewFileWriter("error.log")
	formatter := formatters.NewJSONFormatter()
	filter := filters.NewLevelFilter(logman.Error)
	logger := logman.NewLogger(fw, formatter, filter)

	logger.Error("Hello,", "world!")
	logger.Debug("I am not logged")
}

error.log content:

{"callLocation":"main.main:16","logLevel":"Error","message":"Hello, world!","time":"2009-11-10 23:00:00 GMT+0000"}

Motivation

  • Practice Golang and TDD skills
  • Simple but flexible logging for personal projects

About

🍲 Deeply configurable logging library for Go with no configuration required to start

Topics

Resources

License

Stars

Watchers

Forks

Languages