Charm Log

repository·main·Indexed 25 days ago

https://github.com/charmbracelet/log

A minimal, colorful, and structured Go logging library designed for human-readable terminal output. It features built-in styling via Lip Gloss, multiple formatters (Text, JSON, Logfmt), and seamless integration with slog and context. The library provides a leveled logging system (Debug, Info, Warn, Error, Fatal), smart caller tracking with Helper() support, and the ability to create sub-loggers with fixed key-value pairs.

Tokens
6.2K
Snippets
18
Records
50
Agent score
80%

What's inside charmbracelet/log

  1. Overview of the Charm Log library

    main

    Charm Log is a minimal and colorful Go logging library designed for human-readable, structured logging. It provides a leveled logging system with several key features:

    • Colorful Output: Uses Lip Gloss to style and colorize logs.
    • Human Readable: Optimized for terminal visibility.
    • Customizable: Supports custom timestamp formats and multiple output formats including Text, JSON, and Logfmt.
    • Context Support: Ability to store and retrieve loggers from context.Context.
    • Integrations: Includes an slog handler and a standard log adapter.
    • Smart Caller Tracking: Automatically skips caller frames and marks functions as helpers to ensure accurate log locations.
  2. Upgrade from Log v1 to v2

    main

    Upgrading to Log v2 primarily involves updating import paths and dependencies. The API remains largely the same, but there are breaking changes regarding color profiles and style types.

    Quick Start Steps:

    1. Update import paths from github.com/charmbracelet/log to charm.land/log/v2.
    2. Update dependencies using go get.
    3. Fix type references if you use custom styles (Lip Gloss v2) or manual color profiles (colorprofile).
    go get charm.land/log/v2@latest
    go mod tidy
  3. Use the global logger

    main

    The package provides a global logger with timestamps enabled and the logging level set to info by default. You can use it directly without instantiation.

    All logging levels accept optional key/value pairs to be printed along with a message. Use log.Print() to print messages without a level prefix.

    import "github.com/charmbracelet/log"
    
    log.Debug("Cookie 🍪") // won't print anything
    log.Info("Hello World!")
    
    err := fmt.Errorf("too much sugar")
    log.Error("failed to bake cookies", "err", err)
    
    log.Print("Baking 101")
    // 2023/01/04 10:04:06 Baking 101
  4. Update Log v1 import paths to v2

    main

    The import path for the Log library has changed to use the Charm vanity domain. You must replace all instances of the old path with the new v2 path.

    Old path (v1): github.com/charmbracelet/log
    New path (v2): charm.land/log/v2

    # Find all files that need updating
    grep -r "github.com/charmbracelet/log" .
  5. Customize loggers with `log.Options`

    main

    Use log.NewWithOptions(io.Writer, log.Options{}) to configure a logger.

    Available log.Options fields include:

    • ReportCaller: boolean to report the source file/line.
    • ReportTimestamp: boolean to include timestamps.
    • TimeFormat: time.TimeFormat for timestamp styling.
    • Prefix: string to add a prefix to all logs.
    • Formatter: choose between log.TextFormatter (default), log.JSONFormatter, or log.LogfmtFormatter.
    • Level: set the minimum logging level.

    You can also use setter methods on an existing logger instance, such as logger.SetReportTimestamp(false), logger.SetReportCaller(false), or logger.SetLevel(log.DebugLevel).

    logger := log.NewWithOptions(os.Stderr, log.Options{
        ReportCaller: true,
        ReportTimestamp: true,
        TimeFormat: time.Kitchen,
        Prefix: "Baking 🍪 ",
    })
    logger.Info("Starting oven!", "degree", 375)
  6. Troubleshoot Log v2 upgrade issues

    main

    Common issues encountered during the v2 upgrade:

    • "cannot find package github.com/charmbracelet/log": You missed updating an import path. Use grep -r "github.com/charmbracelet/log" . to find them.
    • "cannot use termenv.Profile as colorprofile.Profile": Replace termenv imports and constants with github.com/charmbracelet/colorprofile.
    • "lipgloss.Style type mismatch": Update your Lip Gloss imports from github.com/charmbracelet/lipgloss to charm.land/lipgloss/v2.
    • "module declares its path as charm.land/log/v2 but was required as github.com/charmbracelet/log": Run go mod tidy. If it persists, run go clean -modcache followed by go mod tidy.
  7. Migrate SetColorProfile to colorprofile in v2

    main

    In Log v2, the SetColorProfile method no longer accepts termenv.Profile. It now requires colorprofile.Profile from the github.com/charmbracelet/colorprofile package.

    Mapping of constants:

    • termenv.TrueColor $\rightarrow$ colorprofile.TrueColor
    • termenv.ANSI256 $\rightarrow$ colorprofile.ANSI256
    • termenv.ANSI $\rightarrow$ colorprofile.ANSI
    • termenv.Ascii $\rightarrow$ colorprofile.Ascii
    • termenv.NoTTY $\rightarrow$ colorprofile.NoTTY
    import (
        "charm.land/log/v2"
        "github.com/charmbracelet/colorprofile"
    )
    
    logger := log.New(os.Stderr)
    logger.SetColorProfile(colorprofile.TrueColor)
  8. Update custom Styles to use Lip Gloss v2

    main

    If you customize the Styles struct in Log v2, all style fields now use charm.land/lipgloss/v2.Style instead of the v1 version. You must update your Lip Gloss imports to use the v2 vanity domain.

    Affected fields in Styles struct:

    • Caller, Key, Keys, Levels, Message, Prefix, Separator, Timestamp, Value, Values.
    import (
        "charm.land/lipgloss/v2"
        "charm.land/log/v2"
    )
    
    styles := log.DefaultStyles()
    styles.Levels[log.ErrorLevel] = lipgloss.NewStyle().
        Background(lipgloss.Color("204"))
  9. Structured logging with key/value pairs

    main

    All logging functions accept a message (which can be of type any) followed by optional key/value pairs of any type.

    ingredients := []string{"flour", "butter", "sugar", "chocolate"}
    log.Debug("Available ingredients", "ingredients", ingredients)
    // DEBUG Available ingredients ingredients="[flour butter sugar chocolate]"