Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/kataras/golog

A high-performant Logging Foundation for Go Applications. X3 faster than the rest leveled loggers.
https://github.com/kataras/golog

easy-to-use go golang high-performance iris iris-golang log logger logging logs modular stdout

Last synced: 2 days ago
JSON representation

A high-performant Logging Foundation for Go Applications. X3 faster than the rest leveled loggers.

Awesome Lists containing this project

README

        

# ✒️ golog

_golog_ is a zero-dependency simple, fast and easy-to-use level-based logger written in [Go Programming Language](https://go.dev).

![Output from win terminal](screen.png)

[![build status](https://img.shields.io/github/actions/workflow/status/kataras/golog/ci.yml)](https://github.com/kataras/golog/actions) [![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=flat-square)](http://goreportcard.com/report/kataras/golog) [![godocs](https://img.shields.io/badge/online-documentation-0366d6.svg?style=flat-square)](https://pkg.go.dev/github.com/kataras/golog) [![github issues](https://img.shields.io/github/issues/kataras/golog.svg?style=flat-square)](https://github.com/kataras/golog/issues?q=is%3Aopen+is%3Aissue)

## 🚀 Installation

The only requirement is the Go Programming Language[*](https://go.dev/dl).

Go modules

```bash
$ go get github.com/kataras/golog@latest
```

Or edit your project's go.mod file and execute $ go build.

```mod
module your_project_name

go 1.22

require (
github.com/kataras/golog v0.1.12
)
```

> `$ go build`

```bash
$ go get github.com/kataras/golog@latest
```

```go
package main

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

func main() {
// Default Output is `os.Stdout`,
// but you can change it:
// golog.SetOutput(os.Stderr)

// Time Format defaults to: "2006/01/02 15:04"
// you can change it to something else or disable it with:
// golog.SetTimeFormat("")

// Level defaults to "info",
// but you can change it:
golog.SetLevel("debug")

golog.Println("This is a raw message, no levels, no colors.")
golog.Info("This is an info message, with colors (if the output is terminal)")
golog.Warn("This is a warning message")
golog.Error("This is an error message")
golog.Debug("This is a debug message")
golog.Fatal(`Fatal will exit no matter what,
but it will also print the log message if logger's Level is >=FatalLevel`)

// Use any other supported logger through golog, e.g. the new "log/slog":
// golog.Install(slog.Default())
}
```

## Log Levels

| Name | Method | Text | Color |
| ----------|-------------------------|----------|--------------------|
| `"fatal"` | `Fatal, Fatalf` | `[FTAL]` | Red background |
| `"error"` | `Error, Errorf` | `[ERRO]` | Red foreground |
| `"warn"` | `Warn, Warnf, Warningf` | `[WARN]` | Magenta foreground |
| `"info"` | `Info, Infof` | `[INFO]` | Cyan foreground |
| `"debug"` | `Debug, Debugf` | `[DBUG]` | Yellow foreground |

> On debug level the logger will store stacktrace information to the log instance, which is not printed but can be accessed through a `Handler` (see below).

### Helpers

```go
// GetTextForLevel returns the level's (rich) text.
fatalRichText := golog.GetTextForLevel(golog.FatalLevel, true)

// fatalRichText == "\x1b[41m[FTAL]\x1b[0m"
```

```go
// ParseLevel returns a Level based on its string name.
level := golog.ParseLevel("debug")

// level == golog.DebugLevel
```

### Customization

You can customize the log level attributes.

```go
func init() {
// Levels contains a map of the log levels and their attributes.
errorAttrs := golog.Levels[golog.ErrorLevel]

// Change a log level's text.
customColorCode := 156
errorAttrs.SetText("custom text", customColorCode)

// Get (rich) text per log level.
enableColors := true
errorRichText := errorAttrs.Text(enableColors)
}
```

Alternatively, to change a specific text on a known log level, you can just call:

```go
golog.ErrorText("custom text", 156)
```

## Integration

The `golog.Logger` is using common, expected log methods, therefore you can integrate it with ease.

Take for example the [badger](github.com/dgraph-io/badger) database. You want to add a prefix of `[badger]` in your logs when badger wants to print something.

1. Create a child logger with a prefix text using the `Child` function,
2. disable new lines (because they are managed by badger itself) and you are ready to GO:

```go
opts := badger.DefaultOptions("./data")
opts.Logger = golog.Child("[badger]").DisableNewLine()

db, err := badger.Open(opts)
// [...]
```

### Level-based and standard Loggers

You can put `golog` in front of your existing loggers using the [Install](https://pkg.go.dev/github.com/kataras/golog?tab=doc#Logger.Install) method.

Supporte loggers:

- log
- slog
- logrus

Example for `log/slog` standard package:

```go
// Simulate an slog.Logger preparation.
var myLogger = slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelDebug,
}))

func main() {
golog.SetLevel("error")
golog.Install(myLogger)

golog.Error("error message")
}
```

Example for `log` standard package:

```go
// Simulate a log.Logger preparation.
myLogger := log.New(os.Stdout, "", 0)

golog.SetLevel("error")
golog.Install(myLogger)

golog.Error("error message")
```

Example for [sirupsen/logrus](https://github.com/sirupsen/logrus):

```go
// Simulate a logrus logger preparation.
logrus.SetLevel(logrus.InfoLevel)
logrus.SetFormatter(&logrus.JSONFormatter{})

golog.Install(logrus.StandardLogger())

golog.Debug(`this debug message will not be shown,
because the logrus level is InfoLevel`)
golog.Error(`this error message will be visible as JSON,
because of logrus.JSONFormatter`)
```

## Output Format

Any value that completes the [Formatter interface](https://github.com/kataras/golog/blob/master/formatter.go) can be used to write to the (leveled) output writer. By default the `"json"` formatter is available.

### JSON

```go
import "github.com/kataras/golog"

func main() {
golog.SetLevel("debug")
golog.SetFormat("json", " ") // < --

// main.go#29
golog.Debugf("This is a %s with data (debug prints the stacktrace too)", "message", golog.Fields{
"username": "kataras",
})
}
```

**Output**

```json
{
"timestamp": 1591423477,
"level": "debug",
"message": "This is a message with data (debug prints the stacktrace too)",
"fields": {
"username": "kataras"
},
"stacktrace": [
{
"function": "main.main",
"source": "C:/example/main.go:29"
}
]
}
```

### Register custom Formatter

```go
golog.RegisterFormatter(new(myFormatter))
golog.SetFormat("myformat", options...)
```

The `Formatter` interface looks like this:

```go
// Formatter is responsible to print a log to the logger's writer.
type Formatter interface {
// The name of the formatter.
String() string
// Set any options and return a clone,
// generic. See `Logger.SetFormat`.
Options(opts ...interface{}) Formatter
// Writes the "log" to "dest" logger.
Format(dest io.Writer, log *Log) bool
}
```

### Custom Format using `Handler`

The Logger can accept functions to handle (and print) each [Log](https://pkg.go.dev/github.com/kataras/golog?tab=doc#Log) through its [Handle](https://pkg.go.dev/github.com/kataras/golog?tab=doc#Logger.Handle) method. The Handle method accepts a [Handler](https://pkg.go.dev/github.com/kataras/golog?tab=doc#Handler).

```go
type Handler func(value *Log) (handled bool)
```

This method can be used to alter Log's fields based on custom logic or to change the output destination and its **output format**.

**Create a JSON handler**

```go
import "encoding/json"

func jsonOutput(l *golog.Log) bool {
enc := json.NewEncoder(l.Logger.GetLevelOutput(l.Level.String()))
enc.SetIndent("", " ")
err := enc.Encode(l)
return err == nil
}
```

**Register the handler and log something**

```go
import "github.com/kataras/golog"

func main() {
golog.SetLevel("debug")
golog.Handle(jsonOutput)

// main.go#29
golog.Debugf("This is a %s with data (debug prints the stacktrace too)", "message", golog.Fields{
"username": "kataras",
})
}
```

## Examples

* [basic](_examples/basic/main.go)
* [output per level](_examples/level-output/main.go)
* [child](_examples/child/main.go)
* [add new level](_examples/customize-levels/new-level/main.go)
* [change text and color](_examples/customize-levels/text-and-colors/main.go)
* [customize output](_examples/customize-output/main.go)
* [multi output](_examples/multi-output/main.go)
* [scan](_examples/scan/main.go)
* [logurs integration](_examples/integrations/logrus/main.go)
* [log.Logger std integration](_examples/integrations/std/main.go)
* [ngrok integration](_examples/ngrok-logger/main.go) **NEW**
* [postgres integration](https://github.com/kataras/pgx-golog) **NEW**
* [new instance](_examples/instance/main.go)

## 🔥 Benchmarks

| test | times ran (large is better) | ns/op (small is better) | B/op (small is better) | allocs/op (small is better) |
| -----------|--------|-------------|-------------|-------------|
| **BenchmarkGologPrint** | 10000000 | 3749 ns/op | 890 B/op | 28 allocs/op |
| BenchmarkLogrusPrint |   3000000 | 9609 ns/op | 1611 B/op | 64 allocs/op |

Click [here](_benchmarks) for details.

## 👥 Contributing

If you find that something is not working as expected please open an [issue](https://github.com/kataras/golog/issues).