Log

A minimal, colorful Go logging library with leveled, structured, human-readable output.

Library
Go
vv1.0.0
3,381stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
67/100Good
Development Activity68
Maintenance56
Community52
Maturity52
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
79/100Good
Architecture80
Code Quality82
Innovation62
Learning Curve90

charmbracelet/log is a minimal Go logging library from Charm that renders leveled, structured log lines in a colorful, human-readable format by default, powered by Lip Gloss for styling. It ships with a small API centered on a global package-level logger plus New/NewWithOptions constructors for scoped loggers that carry their own prefix, key-value fields, caller-reporting, and formatter.

Beyond its default text output, Log includes JSON and Logfmt formatters for machine-readable pipelines, and integrates with the standard library in two directions: it can be used directly as a log/slog handler, and it can be wrapped as a *log.Logger for code (like net/http’s ErrorLog) that only accepts the stdlib logger interface. Sub-loggers created via With() inherit and extend fields without mutating the parent, and a Helper() marker (mirroring testing.TB.Helper()) lets wrapper functions skip themselves when reporting caller locations.

What You Get

  • A global package-level logger (log.Info, log.Debug, etc.) that works with zero setup, plus New/NewWithOptions for independent logger instances
  • Text, JSON, and Logfmt formatters selectable per logger via Options.Formatter or SetFormatter
  • Colorful, styleable text output built on Lip Gloss, with per-level and per-key/value style overrides via DefaultStyles()
  • Sub-loggers via With()/WithPrefix() that carry forward fields and a prefix without touching the parent logger
  • A log/slog handler implementation, so Log can back Go’s standard structured-logging API directly
  • A standard-library adapter (StandardLog()) that returns a *log.Logger, for code that only accepts the stdlib logger interface
  • Caller reporting with configurable short/long formatters, and a Helper() marker to skip wrapper functions when resolving the caller frame

Common Use Cases

  • Drop-in application logging for CLI tools and services that want readable, colorful terminal output during development
  • Backing a log/slog.Logger so application code logs through the standard slog API while Log handles formatting
  • Supplying net/http.Server.ErrorLog (and similar stdlib-only hooks) via the StandardLog() adapter
  • Structured JSON or Logfmt output for production log pipelines, switched on per-logger via Options.Formatter
  • Per-request or per-batch sub-loggers created with With("request_id", id) to carry consistent context through a call chain

Under The Hood

Architecture The library centers on a single Logger struct (logger.go) holding an output writer wrapped in a colorprofile.Writer, a mutex-guarded set of fields (level, prefix, time format, caller settings, formatter, styles), and a reusable bytes.Buffer. All logging calls funnel through Log()/Logf() into a private handle() method that assembles timestamp, level, caller, prefix, message, and key-value pairs into a single kvs slice, then dispatches to one of three formatter methods (textFormatter, jsonFormatter, logfmtFormatter in text.go/json.go/logfmt.go) based on the configured Formatter. With() clones the logger (fresh buffer, mutex, and helpers map) and appends new fields, giving sub-loggers isolated state without touching the parent — a clear, single-responsibility data flow with no hidden global state beyond the optional Default() singleton in pkg.go.

Tech Stack Written in modern Go (go.mod targets a recent Go 1.x toolchain) with a deliberately small dependency set: charm.land/lipgloss/v2 for styling and layout, charmbracelet/colorprofile for terminal color-profile detection and ANSI stripping, go-logfmt/logfmt for the Logfmt encoder, and stretchr/testify as a test-only dependency. No web framework, ORM, or database — this is a pure library meant to be imported, with build/release automation (.goreleaser.yml) handled by Charm’s shared GitHub Actions workflows rather than bespoke CI scripting.

Code Quality The repository carries ten _test.go files covering the logger core, JSON/Logfmt/text formatters, level parsing, context helpers, and both pre- and post-Go-1.21 code paths (logger_121.go / logger_no121.go), using testify for assertions. Linting is enforced via a .golangci.yml with an extensive linter set enabled (gosec, errcheck-adjacent checks, wrapcheck, nilerr, unparam, prealloc, and more) plus gofumpt/goimports formatting, and CI runs build, snapshot, and coverage jobs through Charm’s shared reusable workflows on every push and PR. Error handling favors explicit sentinel errors (ErrMissingValue) and value-vs-error-safe writes rather than panics.

API Design The public surface is intentionally narrow: five level methods with plain and f-suffixed formatting variants, With()/WithPrefix() for scoped loggers, and a handful of SetX methods for runtime configuration — no builder chains or generic type parameters to learn. Getting started requires a single import and zero configuration (the package-level logger just works), while advanced usage (custom styles, formatters, caller offsets, slog/stdlib interop) is opt-in through Options or setters, keeping the common path lightweight and the docs (a single, example-driven README with animated terminal recordings for nearly every feature) unusually approachable for a systems-level Go library.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search