### Install Charmbracelet Log Source: https://github.com/charmbracelet/log/blob/main/README.md Use go get to download the latest version of the library. ```bash go get github.com/charmbracelet/log@latest ``` -------------------------------- ### Complete Log Example Source: https://github.com/charmbracelet/log/blob/main/_autodocs/getting-started.md A comprehensive example demonstrating logger creation, setting options, global logging, request-scoped logging using context, and handling requests with context-aware loggers. ```go package main import ( "context" "os" "time" "charm.land/log/v2" ) func main() { // Create logger logger := log.NewWithOptions(os.Stderr, log.Options{ Level: log.InfoLevel, ReportTimestamp: true, ReportCaller: true, Formatter: log.TextFormatter, }) log.SetDefault(logger) // Global logs log.Info("application started", "version", "1.0.0") // Request-scoped logging ctx := log.WithContext(context.Background(), logger.With("request_id", "req-123")) handleRequest(ctx) } func handleRequest(ctx context.Context) { logger := log.FromContext(ctx) start := time.Now() logger.Info("request received", "endpoint", "/api/users") // Simulate work time.Sleep(100 * time.Millisecond) duration := time.Since(start).Milliseconds() logger.Info("request completed", "status", 200, "duration_ms", duration) } ``` -------------------------------- ### Full Text Formatter Example with Custom Styles Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/formatters.md Demonstrates setting up a logger with the text formatter and applying custom styles for error levels and specific log messages. This example shows how to initialize the logger, set the formatter, define styles, and then log a message. ```go logger := log.New(os.Stderr) logger.SetFormatter(log.TextFormatter) styles := log.DefaultStyles() // Make errors bold and red styles.Levels[log.ErrorLevel] = lipgloss.NewStyle(). SetString("ERROR"). Bold(true). Foreground(lipgloss.Color("196")) logger.SetStyles(styles) logger.Error("operation failed", "code", "TIMEOUT") ``` -------------------------------- ### Logger Configuration Example Source: https://github.com/charmbracelet/log/blob/main/_autodocs/types.md Example of creating logger options with specific settings for log level, timestamp reporting, caller reporting, JSON formatting, and time format. Used with `NewWithOptions`. ```go opts := log.Options{ Level: log.DebugLevel, ReportTimestamp: true, ReportCaller: true, Formatter: log.JSONFormatter, TimeFormat: "2006-01-02T15:04:05Z07:00", } logger := log.NewWithOptions(os.Stderr, opts) ``` -------------------------------- ### Complete Example: Request-Scoped Logger Propagation Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/context.md A full example demonstrating how to create request-scoped loggers using middleware. It shows how to enrich logs with request details and propagate the logger through the request context to handlers and nested functions. ```go package main import ( "context" "fmt" "net/http" "os" "time" "charm.land/log/v2" ) // Create request-scoped logger func withRequestLogger(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Generate request ID requestID := fmt.Sprintf("%d", time.Now().UnixNano()) // Create logger with request-specific fields requestLogger := log.With( "request_id", requestID, "method", r.Method, "path", r.URL.Path, ) // Store in context ctx := log.WithContext(r.Context(), requestLogger) // Pass to next handler next.ServeHTTP(w, r.WithContext(ctx)) }) } // Handler retrieves logger from context func handleUser(w http.ResponseWriter, r *http.Request) { logger := log.FromContext(r.Context()) logger.Info("user endpoint called", "user_id", r.URL.Query().Get("id")) w.WriteHeader(http.StatusOK) } // Nested function also retrieves logger func validateUser(ctx context.Context, userID string) bool { logger := log.FromContext(ctx) logger.Info("validating user", "user_id", userID) return true } func main() { logger := log.NewWithOptions(os.Stderr, log.Options{ ReportTimestamp: true, ReportCaller: true, Level: log.InfoLevel, }) log.SetDefault(logger) mux := http.NewServeMux() mux.HandleFunc("/user", handleUser) handler := withRequestLogger(mux) log.Info("starting server on :8080") http.ListenAndServe(":8080", handler) } ``` -------------------------------- ### Complete slog Example with Charmbracelet Log Source: https://github.com/charmbracelet/log/blob/main/_autodocs/slog-handler.md This example shows how to create a slog logger using a Charmbracelet Log handler. It demonstrates logging at different levels, adding request-scoped attributes, and using WithGroup for namespacing and chaining groups. ```Go package main import ( "context" "log/slog" // Go 1.21+ "os" "charm.land/log/v2" ) func main() { // Create charm logger charmLogger := log.NewWithOptions(os.Stderr, log.Options{ ReportTimestamp: true, Formatter: log.JSONFormatter, Level: log.InfoLevel, }) // Create slog logger using charm logger as handler slogger := slog.New(charmLogger) // Add request-scoped attributes attrs := []slog.Attr{ slog.String("request_id", "req-123"), slog.String("user_id", "user-456"), } requestHandler := charmLogger.WithAttrs(attrs) requestSlogger := slog.New(requestHandler) // Log at different levels slogger.Debug("debug message") // Not logged (level=info) slogger.Info("info message", slog.String("key", "value")) requestSlogger.Info("request info") // Includes request_id and user_id // Use WithGroup for namespacing authHandler := charmLogger.WithGroup("auth") authSlogger := slog.New(authHandler) authSlogger.Info("user logged in", slog.Int("user_id", 123)) // Chained groups dbHandler := charmLogger.WithGroup("service").WithGroup("db") dbSlogger := slog.New(dbHandler) dbSlogger.Info("query executed") // prefix=service.db } ``` -------------------------------- ### Logger Handle Method Example Source: https://github.com/charmbracelet/log/blob/main/_autodocs/slog-handler.md Shows how slog automatically calls the Handle method for log records. This example configures the logger with JSON formatting and timestamps. ```go logger := log.NewWithOptions(os.Stderr, log.Options{ ReportTimestamp: true, Formatter: log.JSONFormatter, }) slogger := slog.New(logger) // slog automatically calls Handle for each log slogger.InfoContext(ctx, "user login", slog.Int("user_id", 123), slog.String("ip", "192.168.1.1"), ) // Output: {"time":"...","level":"info","msg":"user login","user_id":123,"ip":"192.168.1.1"} ``` -------------------------------- ### Dynamic Logger Configuration Example Source: https://github.com/charmbracelet/log/blob/main/_autodocs/configuration.md Demonstrates how to dynamically change logger settings after creation, such as log level, timestamp reporting, caller reporting, and formatter. ```go logger := log.New(os.Stderr) logger.SetLevel(log.DebugLevel) logger.SetReportTimestamp(true) logger.SetReportCaller(true) logger.SetFormatter(log.JSONFormatter) ``` -------------------------------- ### Set Color Profile (v1) Source: https://github.com/charmbracelet/log/blob/main/UPGRADE_GUIDE_V2.md Example of setting the color profile using termenv in Log v1. This needs to be updated for v2. ```go import ( "github.com/charmbracelet/log" "github.com/muesli/termenv" ) logger := log.New(os.Stderr) logger.SetColorProfile(termenv.TrueColor) ``` -------------------------------- ### Logger With Method Example Source: https://github.com/charmbracelet/log/blob/main/_autodocs/README.md Demonstrates how to use the `With` method to add key-value pairs to a logger instance. The new logger inherits these fields for subsequent log entries. ```go requestLogger := logger.With("request_id", "abc123") requestLogger.Info("handling request") // Both fields attached ``` -------------------------------- ### Text Formatter Styling Example Source: https://github.com/charmbracelet/log/blob/main/_autodocs/configuration.md Shows how to customize the appearance of log output using `TextFormatter` by modifying styles for timestamps, values, and log levels. ```go styles := log.DefaultStyles() // Customize timestamp style styles.Timestamp = lipgloss.NewStyle().Faint(true).Foreground(lipgloss.Color("240")) // Per-key value styling styles.Values["error"] = lipgloss.NewStyle().Foreground(lipgloss.Color("196")).Bold(true) // Per-level styling styles.Levels[log.ErrorLevel] = lipgloss.NewStyle(). Bold(true). Foreground(lipgloss.Color("196")) logger.SetStyles(styles) ``` -------------------------------- ### Basic Logging with Charmbracelet/Log Source: https://github.com/charmbracelet/log/blob/main/_autodocs/INDEX.md Use this for simple, unadorned log messages with key-value pairs. No special setup is required beyond importing the package. ```go log.Info("message", "key", "value") ``` -------------------------------- ### Integrate charm/log with slog using Context Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/context.md This example demonstrates how to create a charm logger, wrap it as an slog handler, store it in context, and then retrieve and use both loggers from the context. ```go package main import ( "context" "log/slog" "os" "charm.land/log/v2" ) func main() { // Create charm logger and wrap as slog handler charmLogger := log.New(os.Stderr) slogger := slog.New(charmLogger) // Store in context ctx := log.WithContext(context.Background(), charmLogger) // Retrieve and use both ways logger := log.FromContext(ctx) logger.Info("charm log message") slogger.InfoContext(ctx, "slog message") } ``` -------------------------------- ### Custom Caller Formatter Example Source: https://github.com/charmbracelet/log/blob/main/_autodocs/types.md Demonstrates how to create and set a custom caller formatter for the logger. This allows for flexible formatting of source location information. ```go // Custom caller formatter customFormatter := func(file string, line int, fn string) string { return fmt.Sprintf("[%s:%d in %s]", filepath.Base(file), line, fn) } logger.SetCallerFormatter(customFormatter) ``` -------------------------------- ### Update Custom Styles (v1) Source: https://github.com/charmbracelet/log/blob/main/UPGRADE_GUIDE_V2.md Example of customizing log styles using Lip Gloss v1. Update Lip Gloss import for v2. ```go import ( "github.com/charmbracelet/lipgloss" "github.com/charmbracelet/log" ) styles := log.DefaultStyles() styles.Levels[log.ErrorLevel] = lipgloss.NewStyle(). Background(lipgloss.Color("204")) ``` -------------------------------- ### Correct Usage of ParseLevel Source: https://github.com/charmbracelet/log/blob/main/_autodocs/errors.md Provides examples of correct and incorrect calls to ParseLevel, highlighting valid log level strings. ```go // āŒ Incorrect level, err := log.ParseLevel("verbose") // āœ… Correct level, _ := log.ParseLevel("debug") level, _ := log.ParseLevel("info") level, _ := log.ParseLevel("warn") level, _ := log.ParseLevel("error") level, _ := log.ParseLevel("fatal") ``` -------------------------------- ### Set Color Profile (v2) Source: https://github.com/charmbracelet/log/blob/main/UPGRADE_GUIDE_V2.md Example of setting the color profile using colorprofile in Log v2. Replace termenv constants with colorprofile equivalents. ```go import ( "charm.land/log/v2" "github.com/charmbracelet/colorprofile" ) logger := log.New(os.Stderr) logger.SetColorProfile(colorprofile.TrueColor) ``` -------------------------------- ### Update Dependencies with go get Source: https://github.com/charmbracelet/log/blob/main/UPGRADE_GUIDE_V2.md Run these commands to update your go.mod file to use Log v2 and tidy up dependencies. ```bash go get charm.land/log/v2@latest go mod tidy ``` -------------------------------- ### Update Custom Styles (v2) Source: https://github.com/charmbracelet/log/blob/main/UPGRADE_GUIDE_V2.md Example of customizing log styles using Lip Gloss v2. Ensure Lip Gloss is imported from charm.land/lipgloss/v2. ```go import ( "charm.land/lipgloss/v2" "charm.land/log/v2" ) styles := log.DefaultStyles() styles.Levels[log.ErrorLevel] = lipgloss.NewStyle(). Background(lipgloss.Color("204")) ``` -------------------------------- ### Force Standard Log Output to Warnings Source: https://github.com/charmbracelet/log/blob/main/_autodocs/types.md Example of creating a standard logger that forces all output to be warnings, regardless of the original message level. ```go // Force all standard log output to be warnings stdlog := logger.StandardLog(log.StandardLogOptions{ ForceLevel: log.WarnLevel, }) ``` -------------------------------- ### Implement slog.LogValuer Interface Source: https://github.com/charmbracelet/log/blob/main/_autodocs/slog-handler.md Example of creating a custom type that implements the slog.LogValuer interface for structured logging of custom data. ```go type User struct { ID int Name string } func (u User) LogValue() slog.Value { return slog.GroupValue( slog.Int("id", u.ID), slog.String("name", u.Name), ) } slogger.Info("user", slog.Any("user", user)) ``` -------------------------------- ### Get Logger Prefix Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/logger.md Retrieves the current prefix string that is prepended to log messages. ```go logger.GetPrefix() ``` -------------------------------- ### Auto-detect Log Level from Prefix Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/standard-log.md Example demonstrating how the StandardLog adapter automatically detects log levels based on message prefixes like 'INFO' or 'ERROR' when no specific level is forced. Messages without recognized prefixes default to InfoLevel. ```go logger := log.New(os.Stderr) stdlog := logger.StandardLog() stdlog.Print("INFO starting application") // Logged at InfoLevel stdlog.Print("ERROR connection failed") // Logged at ErrorLevel stdlog.Print("general message") // Logged at InfoLevel (default) ``` -------------------------------- ### Example Struct Type Definition Source: https://github.com/charmbracelet/log/blob/main/_autodocs/README.md Demonstrates the standard Go struct format used for defining types within the log library. This includes fields with their respective types. ```go type ExampleType struct { Field1 Type1 Field2 Type2 } ``` -------------------------------- ### Custom Logger Options Source: https://github.com/charmbracelet/log/blob/main/README.md Create a new logger with custom options such as `ReportCaller`, `ReportTimestamp`, `TimeFormat`, and `Prefix`. The example demonstrates setting these options and logging messages. ```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") ``` -------------------------------- ### Structured Logging with Predictable Prefixes Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/standard-log.md Integrate with libraries that log messages with predictable prefixes. This example shows how to add base fields to your logger, which will be included in the output of logs from such libraries. ```go logger := log.With("service", "api", "version", "1.0.0") stdlog := logger.StandardLog() // Library logs: "ERROR failed to connect" // Output includes base fields: service=api version=1.0.0 ``` -------------------------------- ### Request Logging Pattern in Go Source: https://github.com/charmbracelet/log/blob/main/_autodocs/getting-started.md Log request details like ID, method, and path at the start and completion of a request using `log.With` for context. ```go func handleUser(w http.ResponseWriter, r *http.Request) { logger := log.With( "request_id", r.Header.Get("X-Request-ID"), "method", r.Method, "path", r.URL.Path, ) logger.Info("request started") // ... handle request ... logger.Info("request completed", "status", 200) } ``` -------------------------------- ### Logger Enabled Method Example Source: https://github.com/charmbracelet/log/blob/main/_autodocs/slog-handler.md Demonstrates how the Enabled method controls logging based on level. Set the logger's minimum level to WarnLevel to observe Debug and Info messages being skipped. ```go logger := log.New(os.Stderr) logger.SetLevel(log.WarnLevel) slogger := slog.New(logger) slogger.Debug("skipped") // Enabled() returns false, Debug not logged slogger.Info("skipped") // Enabled() returns false, Info not logged slogger.Warn("logged") // Enabled() returns true, Warn logged ``` -------------------------------- ### Force All Messages to a Specific Level Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/standard-log.md Example showing how to use `StandardLogOptions.ForceLevel` to ensure all messages logged through the adapter are assigned a specific level, regardless of their content or prefixes. ```go logger := log.New(os.Stderr) stdlog := logger.StandardLog(log.StandardLogOptions{ ForceLevel: log.WarnLevel, }) stdlog.Print("any message") // All logged at WarnLevel ``` -------------------------------- ### LogfmtFormatter Example Usage Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/formatters.md Demonstrates how to use the LogfmtFormatter with timestamp reporting and logging various fields. The output will be in the logfmt format, with string values containing spaces automatically quoted. ```go logger := log.New(os.Stderr) logger.SetFormatter(log.LogfmtFormatter) logger.SetReportTimestamp(true) logger.Info("request processed", "method", "POST", "status", 200, "duration_ms", 45, ) // Output: // time=2023/06/15T14:30:45 level=info msg="request processed" method=POST status=200 duration_ms=45 ``` -------------------------------- ### Get Standard Library Logger Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/package-functions.md Obtain a standard library `log.Logger` that routes its output through the default charmbracelet logger. Optional configurations can be provided. ```go stdLogger := log.StandardLog() stdLogger.Print("message") // Routes through charm log ``` -------------------------------- ### Use Package-Level StandardLog Function Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/standard-log.md The package-level StandardLog function provides a convenient way to get a standard logger that operates on the default logger instance. ```go stdlog := log.StandardLog() // Uses Default() logger ``` -------------------------------- ### Set Custom Styles for Logger Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/logger.md Applies custom styles to the logger's text formatter. Ensure styles are initialized, for example, using DefaultStyles(). ```go customStyles := log.DefaultStyles() // Customize styles logger.SetStyles(customStyles) ``` -------------------------------- ### Bind StandardLog to Logger Instance Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/standard-log.md Use the StandardLog method on a logger instance to get a standard logger. This logger will include any fields already bound to the parent logger. ```go baseLogger := log.New(os.Stderr) requestLogger := baseLogger.With("request_id", "123") // Each can produce a standard logger baseStdLog := baseLogger.StandardLog() requestStdLog := requestLogger.StandardLog() // requestStdLog includes the "request_id" field in all its output ``` -------------------------------- ### Get Default Log Styles Source: https://github.com/charmbracelet/log/blob/main/_autodocs/types.md Retrieves the default styles for text formatting, which include pre-defined colors for each log level. These styles can be modified to customize the appearance further. ```go func DefaultStyles() *Styles ``` -------------------------------- ### JSONFormatter Example Log Output Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/formatters.md Example of structured JSON output generated by JSONFormatter for different log levels and messages. ```json {"time":"2023/06/15 14:30:45","level":"debug","msg":"event","user_id":123,"action":"login"} {"time":"2023/06/15 14:30:46","level":"info","msg":"event","action":"logout"} {"time":"2023/06/15 14:30:47","level":"warn","msg":"connection slow","timeout_ms":5000} {"time":"2023/06/15 14:30:48","level":"error","msg":"error occurred","err":"connection refused"} ``` -------------------------------- ### Performance Profiling with slog Source: https://github.com/charmbracelet/log/blob/main/_autodocs/slog-handler.md Demonstrates how to log the duration of an operation and other relevant metrics using slog. ```go start := time.Now() result := operation() duration := time.Since(start) slogger.Info("operation completed", slog.Duration("elapsed", duration), slog.Int("items", len(result)), slog.Bool("success", len(result) > 0), ) ``` -------------------------------- ### Creating a New Logger Instance Source: https://github.com/charmbracelet/log/blob/main/README.md Instantiate a new logger with a specific output writer (e.g., os.Stderr) and log a warning message with key/value pairs. ```go logger := log.New(os.Stderr) if butter { logger.Warn("chewy!", "butter", true) } ``` -------------------------------- ### Get Current Log Level Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/logger.md Retrieves the current minimum log level that is being output by the logger. ```go currentLevel := logger.GetLevel() ``` -------------------------------- ### Structured Error Logging Source: https://github.com/charmbracelet/log/blob/main/_autodocs/slog-handler.md Example of logging errors with additional context using slog attributes for better debugging. ```go if err != nil { slogger.Error("operation failed", slog.String("operation", "save"), slog.String("error", err.Error()), slog.String("user_id", userID), ) } ``` -------------------------------- ### Set Time Transformation Function Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/package-functions.md Sets a custom function to transform timestamps before they are logged. For example, to use UTC time. ```go log.SetTimeFunction(log.NowUTC) ``` -------------------------------- ### Create Loggers Source: https://github.com/charmbracelet/log/blob/main/_autodocs/README.md Instantiate a new logger instance. Use `NewWithOptions` for custom configurations. ```go logger := log.New(os.Stderr) logger := log.NewWithOptions(os.Stderr, log.Options{...}) ``` -------------------------------- ### Create Logger with Options Source: https://github.com/charmbracelet/log/blob/main/_autodocs/getting-started.md Configure a new logger with specific options like log level, timestamp reporting, caller reporting, and formatter. ```go logger := log.NewWithOptions(os.Stderr, log.Options{ Level: log.DebugLevel, ReportTimestamp: true, ReportCaller: true, Formatter: log.JSONFormatter, }) logger.Debug("debug message", "status", "running") ``` -------------------------------- ### SetTimeFunction Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/package-functions.md Sets the time transformation function on the default logger. This function is called to get the current time for log entries. ```APIDOC ## SetTimeFunction ### Description Sets the time transformation function on the default logger. ### Method Signature ```go func SetTimeFunction(f TimeFunction) ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body * **f** (TimeFunction) - Required - The function to transform timestamps. For example, `log.NowUTC`. ### Request Example ```go log.SetTimeFunction(log.NowUTC) ``` ### Response None ``` -------------------------------- ### Basic Logging with Default Logger Source: https://github.com/charmbracelet/log/blob/main/README.md Demonstrates using the default package-wise logger for Info and Debug level messages. Debug messages are not shown by default. ```go log.Debug("Cookie šŸŖ") // won't print anything log.Info("Hello World!") ``` -------------------------------- ### Complete Integration with http.Server Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/standard-log.md Demonstrates creating a charm logger and obtaining a standard library logger from it. This standard logger can then be used with `http.Server` to ensure all server errors are logged using the configured charm logger. ```go package main import ( "net/http" "os" "charm.land/log/v2" ) func main() { // Create charm logger logger := log.NewWithOptions(os.Stderr, log.Options{ Level: log.InfoLevel, ReportTimestamp: true, ReportCaller: true, Formatter: log.JSONFormatter, }) // Get standard library logger stdlog := logger.StandardLog() // HTTP server errors go through charm logger server := &http.Server{ Addr: ":8080", ErrorLog: stdlog, } // Middleware can use stdlog too // All output respects charm logger configuration logger.Info("http server started") server.ListenAndServe() } ``` -------------------------------- ### Get Default Logger Instance Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/package-functions.md Returns the default global logger instance. It is created on the first call with timestamp reporting enabled. ```go logger := log.Default() logger.Info("using default logger") ``` -------------------------------- ### Import Charm Log Source: https://github.com/charmbracelet/log/blob/main/_autodocs/INDEX.md Import the charm log library for use in your Go project. ```go import "charm.land/log/v2" ``` -------------------------------- ### Configuring Log Format and Prefix Source: https://github.com/charmbracelet/log/blob/main/_autodocs/getting-started.md Customize the log output format and set a global prefix for all log messages. This helps in standardizing log appearance and identifying the application context. ```go logger.SetFormatter(log.JSONFormatter) // Format logger.SetPrefix("app") // Prefix ``` -------------------------------- ### Configure Logger with Options Source: https://github.com/charmbracelet/log/blob/main/_autodocs/INDEX.md Create a new logger instance with custom options, such as reporting timestamps and using JSON formatting. Requires `os` package. ```go logger := log.NewWithOptions(os.Stderr, log.Options{ ReportTimestamp: true, Formatter: log.JSONFormatter, }) ``` -------------------------------- ### Initialize and Set LogfmtFormatter Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/formatters.md This snippet shows how to initialize a logger and set the LogfmtFormatter for outputting logs in the logfmt format. ```go logger := log.New(os.Stderr) logger.SetFormatter(log.LogfmtFormatter) ``` -------------------------------- ### Good vs. Avoided Logging Calls Source: https://github.com/charmbracelet/log/blob/main/_autodocs/errors.md Demonstrates the correct way to pass key-value pairs to logging functions, ensuring an even number of arguments. ```go // āœ… Good logger.Info("event", "type", "login", "user_id", 123, "timestamp", time.Now()) // āŒ Avoid logger.Info("event", "type", "login", "user_id") // Missing value for user_id ``` -------------------------------- ### Logging with Key/Value Pairs Source: https://github.com/charmbracelet/log/blob/main/README.md Shows how to log error messages with additional key/value pairs for context. This is useful for providing details about the error. ```go err := fmt.Errorf("too much sugar") log.Error("failed to bake cookies", "err", err) ``` -------------------------------- ### Update Log Import Path (v1) Source: https://github.com/charmbracelet/log/blob/main/UPGRADE_GUIDE_V2.md This is the import path for Log v1. Update this to the v2 path. ```go import "github.com/charmbracelet/log" ``` -------------------------------- ### Set Initial Fields for Logger Source: https://github.com/charmbracelet/log/blob/main/_autodocs/configuration.md Provide initial key-value pairs that will be included in all log messages from this logger. Fields are provided as alternating key-value pairs. ```go logger := log.NewWithOptions(os.Stderr, log.Options{ Fields: []any{"app", "myapp", "version", "1.0.0"}, }) logger.Info("started") // Output includes app=myapp version=1.0.0 // Add more fields with With() requestLogger := logger.With("request_id", "abc123") ``` -------------------------------- ### New Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/package-functions.md Creates a new logger with default options writing to the given output. ```APIDOC ## New ### Description Creates a new logger with default options writing to the given output. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | w | `io.Writer` | Yes | — | Output destination for logs | ### Return `*Logger` — Newly created logger ### Example ```go logger := log.New(os.Stderr) logger.Info("hello") ``` ``` -------------------------------- ### Configure StandardLog Adapter Source: https://github.com/charmbracelet/log/blob/main/_autodocs/configuration.md Adapts the logger to work with Go's standard library log package. Use detection mode by default or force all messages to a specific level. ```go type StandardLogOptions struct { ForceLevel Level } ``` ```go // Auto-detect levels from message prefix stdlog := logger.StandardLog() ``` ```go // Force all messages to error level stdlog := logger.StandardLog(log.StandardLogOptions{ ForceLevel: log.ErrorLevel, }) ``` -------------------------------- ### Use JSON Formatter with slog Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/formatters.md Shows how to integrate the log library with Go's standard `slog` package by setting the formatter to `log.JSONFormatter` and then creating an `slog.Logger` from the log library's logger. ```go logger := log.New(os.Stderr) logger.SetFormatter(log.JSONFormatter) slogger := slog.New(logger) slogger.Info("message", "key", "value") // JSON output ``` -------------------------------- ### Manually Access Logger from Context Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/context.md Demonstrates advanced usage by directly accessing the logger from the context using `ContextKey`. It is recommended to use the provided helper functions like `FromContext` for cleaner code. ```go // You can manually access using ContextKey if needed logger := ctx.Value(log.ContextKey).(*Logger) // But prefer the helper functions instead: logger := log.FromContext(ctx) ``` -------------------------------- ### Create and Retrieve Logger from Context Source: https://github.com/charmbracelet/log/blob/main/_autodocs/configuration.md Use `log.WithContext` to add a logger to a Go context and `log.FromContext` to retrieve it within handlers or middleware. `log.FromContext` returns the logger from the context or the default logger if none is found. ```go // Create context with logger ctx := log.WithContext(context.Background(), myLogger) // In handler or middleware, retrieve logger func handleRequest(ctx context.Context) { logger := log.FromContext(ctx) // Returns myLogger or Default() logger.Info("processing request") } ``` -------------------------------- ### Wrap Logger in Context with WithContext Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/context.md Use `WithContext` to store a logger in a Go context. This is typically done when initializing request handling or starting new goroutines to ensure the logger is available downstream. The function returns a new context with the logger attached. ```go func WithContext(ctx context.Context, logger *Logger) context.Context ``` ```go logger := log.New(os.Stderr) ctx := log.WithContext(context.Background(), logger) // Pass ctx through handlers handleRequest(ctx) ``` -------------------------------- ### Configuring Log Level and Output Source: https://github.com/charmbracelet/log/blob/main/_autodocs/getting-started.md Set the minimum logging level and specify the output destination for log messages. This allows control over verbosity and where logs are sent. ```go logger.SetLevel(log.DebugLevel) // Minimum level logger.SetOutput(os.Stdout) // Destination ``` -------------------------------- ### Basic Logging Operations Source: https://github.com/charmbracelet/log/blob/main/_autodocs/README.md Perform logging at different levels. `Fatal` will exit the application. ```go log.Debug("message") log.Info("message", "key", "value") log.Warn("message") log.Error("message", "err", err) log.Fatal("message") // Exits ``` -------------------------------- ### Import slog for Go 1.20 Source: https://github.com/charmbracelet/log/blob/main/_autodocs/slog-handler.md For Go versions prior to 1.21, import the experimental slog package from golang.org/x/exp. ```go // Uses experimental slog from golang.org/x/exp import "golang.org/x/exp/slog" ``` -------------------------------- ### Log Levels Source: https://github.com/charmbracelet/log/blob/main/README.md Available log levels include Debug, Info, Warn, Error, and Fatal. Use `log.SetLevel()` to configure the global log level or `log.Options{Level: }` when creating a new logger. ```go log.DebugLevel log.InfoLevel log.WarnLevel log.ErrorLevel log.FatalLevel ``` -------------------------------- ### Create Custom Logger Source: https://github.com/charmbracelet/log/blob/main/_autodocs/getting-started.md Instantiate a new logger that writes to a specified output, such as os.Stderr. ```go logger := log.New(os.Stderr) logger.Info("message", "key", "value") ``` -------------------------------- ### NewWithOptions Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/package-functions.md Creates a new logger with custom options. ```APIDOC ## NewWithOptions ### Description Creates a new logger with custom options. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | w | `io.Writer` | Yes | — | Output destination | | o | `Options` | Yes | — | Logger configuration options | ### Return `*Logger` — Newly created logger ### Example ```go logger := log.NewWithOptions(os.Stderr, log.Options{ Level: log.DebugLevel, ReportTimestamp: true, ReportCaller: true, Formatter: log.JSONFormatter, }) ``` ``` -------------------------------- ### Choose Formatter for Use Case Source: https://github.com/charmbracelet/log/blob/main/_autodocs/getting-started.md Select the appropriate formatter based on your logging needs. TextFormatter is suitable for development, JSONFormatter for production aggregation, and LogfmtFormatter for Unix tools integration. ```go // āœ… Development logger.SetFormatter(log.TextFormatter) // āœ… Production with aggregation logger.SetFormatter(log.JSONFormatter) // āœ… Unix tools integration logger.SetFormatter(log.LogfmtFormatter) ``` -------------------------------- ### Set Color Profile with colorprofile Source: https://github.com/charmbracelet/log/blob/main/UPGRADE_GUIDE_V2.md Manually set the color profile using constants from the 'colorprofile' package if logs display incorrectly. In most cases, automatic detection by Log v2 is sufficient. ```go import "github.com/charmbracelet/colorprofile" // Explicitly set if needed logger.SetColorProfile(colorprofile.TrueColor) // or ANSI256, ANSI, etc. ``` -------------------------------- ### Map slog Levels to Charm Log Levels Source: https://github.com/charmbracelet/log/blob/main/_autodocs/slog-handler.md Demonstrates the direct mapping between slog's predefined log levels and charm log levels. ```go slog.LevelDebug → log.DebugLevel slog.LevelInfo → log.InfoLevel slog.LevelWarn → log.WarnLevel slog.LevelError → log.ErrorLevel ``` -------------------------------- ### Performance Monitoring with Logging in Go Source: https://github.com/charmbracelet/log/blob/main/_autodocs/getting-started.md Measure and log the duration of expensive operations along with other relevant metrics like result size. ```go start := time.Now() result := expensiveOperation() logger.Info("operation completed", "duration_ms", time.Since(start).Milliseconds(), "result_size", len(result), ) ``` -------------------------------- ### Create Logger with Prefix Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/logger.md Returns a new logger instance with a specified string prefix prepended to all log messages. Useful for distinguishing logs from different modules or components. ```go moduleLogger := logger.WithPrefix("auth") moduleLogger.Info("login successful") // Logs with "prefix=auth" ``` -------------------------------- ### Create New Logger with Custom Options Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/package-functions.md Creates a new logger instance with custom configuration options, including log level, timestamp reporting, caller reporting, and formatter. This allows for fine-grained control over logger behavior. ```go logger := log.NewWithOptions(os.Stderr, log.Options{ Level: log.DebugLevel, ReportTimestamp: true, ReportCaller: true, Formatter: log.JSONFormatter, }) ``` -------------------------------- ### Create New Logger with Default Options Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/package-functions.md Creates a new logger instance with default options, writing logs to the specified output writer. Useful for creating isolated loggers. ```go logger := log.New(os.Stderr) logger.Info("hello") ``` -------------------------------- ### Formatted Logging Source: https://github.com/charmbracelet/log/blob/main/README.md Use formatter variants like `Debugf`, `Warnf`, `Errorf`, `Fatalf` for formatted log messages. `log.Fatalf` calls `os.Exit(1)`. `log.Printf` logs regardless of the set level. These can be combined with `With(...)` for context. ```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") ``` -------------------------------- ### Update Log Import Path (v2) Source: https://github.com/charmbracelet/log/blob/main/UPGRADE_GUIDE_V2.md This is the new import path for Log v2. Replace the v1 import with this. ```go import "charm.land/log/v2" ``` -------------------------------- ### Sync go.mod and go.sum with go mod tidy Source: https://github.com/charmbracelet/log/blob/main/UPGRADE_GUIDE_V2.md Run 'go mod tidy' to synchronize your go.mod and go.sum files if you encounter module path declaration issues. ```bash go mod tidy ``` -------------------------------- ### WithPrefix Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/logger.md Returns a new logger instance with a prefix applied to all subsequent log messages. ```APIDOC ## WithPrefix ### Description Returns a new logger with a prefix applied. ### Method Signature ```go func (l *Logger) WithPrefix(prefix string) *Logger ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters Table | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | prefix | `string` | Yes | Prefix to prepend to logs | ### Request Example ```go moduleLogger := logger.WithPrefix("auth") moduleLogger.Info("login successful") // Logs with "prefix=auth" ``` ### Response #### Success Response (`*Logger`) A new logger instance with the specified prefix set. ``` -------------------------------- ### Configure Logger Prefix Source: https://github.com/charmbracelet/log/blob/main/_autodocs/configuration.md Use the Prefix option to prepend a string to all log messages, aiding in context identification. The prefix can be modified dynamically using SetPrefix. ```go logger := log.NewWithOptions(os.Stderr, log.Options{ Prefix: "myapp", }) logger.Info("started") // Output includes "prefix=myapp" // Or set dynamically logger.SetPrefix("auth") ``` -------------------------------- ### Derive Loggers for Context Source: https://github.com/charmbracelet/log/blob/main/_autodocs/errors.md Demonstrates how to create a new logger with pre-defined fields, such as a request ID. This is useful for adding context to logs within specific scopes, like request handling. ```go // Request-scoped logger with built-in fields requestLogger := logger.With("request_id", requestID) requestLogger.Info("handling request") // request_id automatically included ``` -------------------------------- ### Logger Creation Options Struct Source: https://github.com/charmbracelet/log/blob/main/_autodocs/configuration.md The Options struct defines all configuration parameters for creating a logger with NewWithOptions. It allows customization of timestamps, levels, prefixes, caller information, and formatting. ```go type Options struct { TimeFunction TimeFunction TimeFormat string Level Level Prefix string ReportTimestamp bool ReportCaller bool CallerFormatter CallerFormatter CallerOffset int Fields []any Formatter Formatter } ``` -------------------------------- ### Using log.WithContext and log.FromContext Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/context.md Demonstrates how to store a charm logger in a context and retrieve it later. This is useful for passing loggers down through function call chains without explicit parameter passing. ```APIDOC ## Functions ### WithContext #### Description Stores a `log.Logger` in a `context.Context`. #### Parameters - **ctx** (context.Context) - The parent context. - **logger** (*log.Logger) - The logger to store in the context. #### Returns - context.Context - The new context with the logger. ### FromContext #### Description Retrieves a `log.Logger` from a `context.Context`. #### Parameters - **ctx** (context.Context) - The context to retrieve the logger from. #### Returns - *log.Logger - The logger retrieved from the context. If no logger is found, it returns a default logger. ### ContextKey #### Description Returns the key used to store and retrieve the logger from the context. #### Returns - any - The context key. ``` -------------------------------- ### Format Log Messages with Sprintf Source: https://github.com/charmbracelet/log/blob/main/README.md Use fmt.Sprintf to format log messages with dynamic content. This is useful for creating detailed log entries. ```go for item := 1; i <= 100; i++ { log.Info(fmt.Sprintf("Baking %d/100...", item)) } ``` ```go for temp := 375; temp <= 400; temp++ { log.Info("Increasing temperature", "degree", fmt.Sprintf("%d°F", temp)) } ``` -------------------------------- ### Import slog for Go 1.21+ Source: https://github.com/charmbracelet/log/blob/main/_autodocs/slog-handler.md Use this import for Go 1.21 and later to leverage the standard library's slog package. ```go // Uses standard library slog import "log/slog" ``` -------------------------------- ### Integrating with slog (Go 1.21+) Source: https://github.com/charmbracelet/log/blob/main/_autodocs/INDEX.md Use this snippet to integrate charmbracelet/log with Go's standard `slog` package when using Go 1.21 or later. This allows you to leverage `slog`'s API while using the charmbracelet logger as the handler. ```go logger := log.New(os.Stderr) slogger := slog.New(logger) slogger.Info("message", "key", "value") ``` -------------------------------- ### Update Lip Gloss Imports to v2 Source: https://github.com/charmbracelet/log/blob/main/UPGRADE_GUIDE_V2.md Update your Lip Gloss imports to v2 to resolve 'lipgloss.Style' type mismatches. ```go // Before import "github.com/charmbracelet/lipgloss" // After import "charm.land/lipgloss/v2" ``` -------------------------------- ### Info Log with Context Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/logger.md Logs a message at the info level, suitable for general application events and status updates. ```go logger.Info("application started", "version", "1.0.0", "port", 8080) ``` -------------------------------- ### Create Default Logger Source: https://github.com/charmbracelet/log/blob/main/_autodocs/getting-started.md Use the global default logger which outputs to os.Stderr with timestamp reporting enabled. ```go package main import ( "fmt" "os" "charm.land/log/v2" ) func main() { log.Info("hello", "name", "world") } ``` -------------------------------- ### Integrate with Standard Log Source: https://github.com/charmbracelet/log/blob/main/_autodocs/README.md Route output from Go's standard `log` package through the charm logger. This allows using standard logging calls while benefiting from charm logger's features. ```go stdlog := logger.StandardLog() stdlog.Print("message") // Routes through charm logger ``` -------------------------------- ### Use TextFormatter Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/formatters.md Sets the logger to use TextFormatter for human-readable colored output. Customizes styles for message formatting. ```go logger := log.New(os.Stderr) logger.SetFormatter(log.TextFormatter) // Customize styles styles := log.DefaultStyles() styles.Message = lipgloss.NewStyle().Bold(true) logger.SetStyles(styles) ``` -------------------------------- ### StandardLogOptions Struct Definition Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/standard-log.md Defines the configuration options for the StandardLog adapter. The `ForceLevel` field allows overriding automatic level detection. ```go type StandardLogOptions struct { ForceLevel Level } ``` -------------------------------- ### Formatted Logging with Sprintf-style Source: https://github.com/charmbracelet/log/blob/main/_autodocs/getting-started.md Use Sprintf-style format strings for dynamic log messages. This is useful for including variable data like user IDs or error details. ```go logger.Infof("user %d logged in from %s", userID, ipAddress) logger.Errorf("failed to save record: %v", err) ``` -------------------------------- ### Retrieve Logger from Context with FromContext Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/context.md Use `FromContext` to extract a logger that was previously stored in a context. If no logger is found in the context, it safely returns the default package logger. This function never panics and always returns a valid logger. ```go func FromContext(ctx context.Context) *Logger ``` ```go // Context with custom logger ctx := log.WithContext(context.Background(), customLogger) logger := log.FromContext(ctx) // Returns customLogger // Context without custom logger emptyCtx := context.Background() logger := log.FromContext(emptyCtx) // Returns Default() ``` -------------------------------- ### Minimal Log Message Source: https://github.com/charmbracelet/log/blob/main/_autodocs/INDEX.md Log a simple informational message with the default logger. ```go log.Info("message") ``` -------------------------------- ### WithContext Source: https://github.com/charmbracelet/log/blob/main/_autodocs/types.md Stores a logger in the given context. Returns a new context with the logger attached. ```APIDOC ## WithContext ### Description Stores a logger in the given context. ### Method func WithContext(ctx context.Context, logger *Logger) context.Context ### Parameters #### Path Parameters - **ctx** (context.Context) - Required - The context to wrap - **logger** (*Logger) - Required - The logger to store ### Response #### Success Response - **context.Context** - A new context with the logger attached ### Request Example ```go ctx := log.WithContext(context.Background(), logger) ``` ``` -------------------------------- ### Adapt Middleware for Standard Library Logging Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/standard-log.md Adapt middleware that only supports standard library logging by creating a Charmbracelet logger instance configured for standard log output. This allows you to pass the adapter to components expecting an `*log.Logger`. ```go func setupHTTPServer(baseLogger *log.Logger) { stdlog := baseLogger.StandardLog(log.StandardLogOptions{ ForceLevel: log.InfoLevel, }) // Pass to middleware httpServer := &http.Server{ Addr: ":8080", ErrorLog: stdlog, // http.Server ErrorLog } } ``` -------------------------------- ### Handling ErrMissingValue in Logging Source: https://github.com/charmbracelet/log/blob/main/_autodocs/errors.md Demonstrates how an odd number of key-value arguments leads to an implicit 'missing value' entry. Correct usage with an even number of arguments is also shown. ```go logger := log.New(os.Stderr) // This will add an extra "missing value" entry to output logger.Info("message", "key1", "value1", "key2") // Output includes: key1=value1 key2= (with error indicator) // Correct usage - even number of args logger.Info("message", "key1", "value1", "key2", "value2") ``` -------------------------------- ### Setting Text Output Format Source: https://github.com/charmbracelet/log/blob/main/_autodocs/getting-started.md Configure the logger to use the default text formatter for human-readable, colored output. This is suitable for development and debugging. ```go logger.SetFormatter(log.TextFormatter) // Output: 2023/06/15 14:30:45 INFO event user_id=123 ``` -------------------------------- ### Log Attributes with slog Source: https://github.com/charmbracelet/log/blob/main/_autodocs/slog-handler.md Shows how to pass attributes to the slog logger, which are then extracted and passed to the charm logger. ```go slogger.Info("message", slog.String("user", "alice"), slog.Int("count", 42), slog.Duration("elapsed", time.Second), ) // All attributes included in structured output ``` -------------------------------- ### FromContext Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/context.md Retrieves a logger from a context. Extracts a logger previously stored with `WithContext()`. If no logger is found, returns the default package logger (obtained via `Default()`). ```APIDOC ## FromContext ### Description Retrieves a logger from a context. ### Signature ```go func FromContext(ctx context.Context) *Logger ``` ### Parameters #### Path Parameters - **ctx** (`context.Context`) - Required - Context containing or derived from a context with stored logger ### Return `*Logger` - The logger from the context, or `Default()` if not found ### Behavior: - If context contains a logger stored with `WithContext()` → returns that logger - If context doesn't contain a logger → returns `Default()` - Always returns a non-nil logger (never panics) ### Example: ```go // Context with custom logger ctx := log.WithContext(context.Background(), customLogger) logger := log.FromContext(ctx) // Returns customLogger // Context without custom logger emptyCtx := context.Background() logger := log.FromContext(emptyCtx) // Returns Default() ``` ### Common pattern - option to pass down context: ```go func process(ctx context.Context, item interface{}) error { logger := log.FromContext(ctx) logger.Info("processing item", "item", item) // Pass context to sub-calls return subprocess(ctx, item) } ``` ``` -------------------------------- ### HTTP Middleware for Context Logging Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/context.md This HTTP middleware demonstrates a common pattern for injecting a context-aware logger into requests. It creates a logger with request-specific information and attaches it to the request's context before passing it to the next handler. ```go func loggingMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { logger := log.With("request_id", requestID(r)) ctx := log.WithContext(r.Context(), logger) next.ServeHTTP(w, r.WithContext(ctx)) }) } ``` -------------------------------- ### WithContext Source: https://github.com/charmbracelet/log/blob/main/_autodocs/api-reference/context.md Wraps a logger in a context for propagation. Stores the provided logger in the context using a package-internal context key. The logger can later be retrieved with `FromContext()`. ```APIDOC ## WithContext ### Description Wraps a logger in a context for propagation. ### Signature ```go func WithContext(ctx context.Context, logger *Logger) context.Context ``` ### Parameters #### Path Parameters - **ctx** (`context.Context`) - Required - Base context to wrap (typically from incoming request or `context.Background()`) - **logger** (`*Logger`) - Required - Logger instance to store in context ### Return `context.Context` - New context with the logger attached ### Example ```go logger := log.New(os.Stderr) ctx := log.WithContext(context.Background(), logger) // Pass ctx through handlers handleRequest(ctx) ``` ### Common patterns: HTTP middleware: ```go func loggingMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { logger := log.With("request_id", requestID(r)) ctx := log.WithContext(r.Context(), logger) next.ServeHTTP(w, r.WithContext(ctx)) }) } ``` Request handler: ```go func handleRequest(w http.ResponseWriter, r *http.Request) { logger := log.FromContext(r.Context()) logger.Info("handling request", "path", r.URL.Path) } ``` ```