Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/charmbracelet/log
A minimal, colorful Go logging library 🪵
https://github.com/charmbracelet/log
golang logging
Last synced: 20 days ago
JSON representation
A minimal, colorful Go logging library 🪵
- Host: GitHub
- URL: https://github.com/charmbracelet/log
- Owner: charmbracelet
- License: mit
- Created: 2022-12-02T18:04:11.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2024-09-12T14:52:23.000Z (about 2 months ago)
- Last Synced: 2024-10-02T01:07:32.151Z (about 1 month ago)
- Topics: golang, logging
- Language: Go
- Homepage:
- Size: 537 KB
- Stars: 2,325
- Watchers: 12
- Forks: 66
- Open Issues: 15
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Codeowners: .github/CODEOWNERS
Awesome Lists containing this project
- awesomeLibrary - log - A minimal, colorful Go logging library 🪵 (语言资源库 / go)
- my-awesome - charmbracelet/log - 10 star:2.4k fork:0.1k A minimal, colorful Go logging library 🪵 (Go)
README
# Log
A minimal and colorful Go logging library. 🪵
It provides a leveled structured human readable logger with a small API. Unlike
[standard `log`][stdlog], the Charm logger provides customizable colorful human
readable logging with batteries included.- Uses [Lip Gloss][lipgloss] to style and colorize the output.
- Colorful, human readable format.
- Ability to customize the time stamp format.
- Skips caller frames and marks function as helpers.
- Leveled logging.
- Text, JSON, and Logfmt formatters.
- Store and retrieve logger in and from context.
- Slog handler.
- Standard log adapter.## Usage
Use `go get` to download the dependency.
```bash
go get github.com/charmbracelet/log@latest
```Then, `import` it in your Go files:
```go
import "github.com/charmbracelet/log"
```The Charm logger comes with a global package-wise logger with timestamps turned
on, and the logging level set to `info`.```go
log.Debug("Cookie 🍪") // won't print anything
log.Info("Hello World!")
```
All logging levels accept optional key/value pairs to be printed along with a
message.```go
err := fmt.Errorf("too much sugar")
log.Error("failed to bake cookies", "err", err)
```
You can use `log.Print()` to print messages without a level prefix.
```go
log.Print("Baking 101")
// 2023/01/04 10:04:06 Baking 101
```### New loggers
Use `New()` to create new loggers.
```go
logger := log.New(os.Stderr)
if butter {
logger.Warn("chewy!", "butter", true)
}
```
### Levels
Log offers multiple levels to filter your logs on. Available levels are:
```go
log.DebugLevel
log.InfoLevel
log.WarnLevel
log.ErrorLevel
log.FatalLevel
```Use `log.SetLevel()` to set the log level. You can also create a new logger with
a specific log level using `log.Options{Level: }`.Use the corresponding function to log a message:
```go
err := errors.New("Baking error 101")
log.Debug(err)
log.Info(err)
log.Warn(err)
log.Error(err)
log.Fatal(err) // this calls os.Exit(1)
log.Print(err) // prints regardless of log level
```Or use the formatter variant:
```go
format := "%s %d"
log.Debugf(format, "chocolate", 10)
log.Warnf(format, "adding more", 5)
log.Errorf(format, "increasing temp", 420)
log.Fatalf(format, "too hot!", 500) // this calls os.Exit(1)
log.Printf(format, "baking cookies") // prints regardless of log level// Use these in conjunction with `With(...)` to add more context
log.With("err", err).Errorf("unable to start %s", "oven")
```### Structured
All the functions above take a message and key-value pairs of anything. The
message can also be of type any.```go
ingredients := []string{"flour", "butter", "sugar", "chocolate"}
log.Debug("Available ingredients", "ingredients", ingredients)
// DEBUG Available ingredients ingredients="[flour butter sugar chocolate]"
```### Options
You can customize the logger with options. Use `log.NewWithOptions()` and
`log.Options{}` to customize your new logger.```go
logger := log.NewWithOptions(os.Stderr, log.Options{
ReportCaller: true,
ReportTimestamp: true,
TimeFormat: time.Kitchen,
Prefix: "Baking 🍪 ",
})
logger.Info("Starting oven!", "degree", 375)
time.Sleep(10 * time.Minute)
logger.Info("Finished baking")
```
You can also use logger setters to customize the logger.
```go
logger := log.New(os.Stderr)
logger.SetReportTimestamp(false)
logger.SetReportCaller(false)
logger.SetLevel(log.DebugLevel)
```Use `log.SetFormatter()` or `log.Options{Formatter: }` to change the output
format. Available options are:- `log.TextFormatter` (_default_)
- `log.JSONFormatter`
- `log.LogfmtFormatter`> **Note** styling only affects the `TextFormatter`. Styling is disabled if the
> output is not a TTY.For a list of available options, refer to [options.go](./options.go).
### Styles
You can customize the logger styles using [Lipgloss][lipgloss]. The styles are
defined at a global level in [styles.go](./styles.go).```go
// Override the default error level style.
styles := log.DefaultStyles()
styles.Levels[log.ErrorLevel] = lipgloss.NewStyle().
SetString("ERROR!!").
Padding(0, 1, 0, 1).
Background(lipgloss.Color("204")).
Foreground(lipgloss.Color("0"))
// Add a custom style for key `err`
styles.Keys["err"] = lipgloss.NewStyle().Foreground(lipgloss.Color("204"))
styles.Values["err"] = lipgloss.NewStyle().Bold(true)
logger := log.New(os.Stderr)
logger.SetStyles(styles)
logger.Error("Whoops!", "err", "kitchen on fire")
```
### Sub-logger
Create sub-loggers with their specific fields.
```go
logger := log.NewWithOptions(os.Stderr, log.Options{
Prefix: "Baking 🍪 "
})
batch2 := logger.With("batch", 2, "chocolateChips", true)
batch2.Debug("Preparing batch 2...")
batch2.Debug("Adding chocolate chips")
```
### Format Messages
You can use `fmt.Sprintf()` to format messages.
```go
for item := 1; i <= 100; i++ {
log.Info(fmt.Sprintf("Baking %d/100...", item))
}
```
Or arguments:
```go
for temp := 375; temp <= 400; temp++ {
log.Info("Increasing temperature", "degree", fmt.Sprintf("%d°F", temp))
}
```
### Helper Functions
Skip caller frames in helper functions. Similar to what you can do with
`testing.TB().Helper()`.```go
func startOven(degree int) {
log.Helper()
log.Info("Starting oven", "degree", degree)
}log.SetReportCaller(true)
startOven(400) // INFO Starting oven degree=400
```
This will use the _caller_ function (`startOven`) line number instead of the
logging function (`log.Info`) to report the source location.### Slog Handler
You can use Log as an [`log/slog`](https://pkg.go.dev/log/slog) handler. Just
pass a logger instance to Slog and you're good to go.```go
handler := log.New(os.Stderr)
logger := slog.New(handler)
logger.Error("meow?")
```### Standard Log Adapter
Some Go libraries, especially the ones in the standard library, will only accept
the [standard logger][stdlog] interface. For instance, the HTTP Server from
`net/http` will only take a `*log.Logger` for its `ErrorLog` field.For this, you can use the standard log adapter, which simply wraps the logger in
a `*log.Logger` interface.```go
logger := log.NewWithOptions(os.Stderr, log.Options{Prefix: "http"})
stdlog := logger.StandardLog(log.StandardLogOptions{
ForceLevel: log.ErrorLevel,
})
s := &http.Server{
Addr: ":8080",
Handler: handler,
ErrorLog: stdlog,
}
stdlog.Printf("Failed to make bake request, %s", fmt.Errorf("temperature is too low"))
// ERROR http: Failed to make bake request, temperature is too low
```## Gum
Log integrates with [Gum][gum] to log messages to output. Use `gum log [flags]
[message]` to handle logging in your shell scripts. See
[charmbracelet/gum](https://github.com/charmbracelet/gum#log) for more
information.[gum]: https://github.com/charmbracelet/gum
[lipgloss]: https://github.com/charmbracelet/lipgloss
[stdlog]: https://pkg.go.dev/log## License
[MIT](https://github.com/charmbracelet/log/raw/master/LICENSE)
---
Part of [Charm](https://charm.sh).
Charm热爱开源 • Charm loves open source • نحنُ نحب المصادر المفتوحة