Configuration
Default Logger
The package-level functions (Info(), Warn(), etc.) use the Default logger which writes to os.Stdout at LevelInfo.
// Full configuration
clog.Configure(&clog.Config{
Verbose: true, // enables debug level + timestamps
Output: clog.Stderr(clog.ColorAuto), // custom output
Styles: customStyles, // custom visual styles
})
// Toggle verbose mode
clog.SetVerbose(true)
Output
Each Logger writes to an *Output, which bundles an io.Writer with its terminal capabilities (TTY detection, width, color profile):
// Standard constructors
out := clog.Stdout(clog.ColorAuto) // os.Stdout with auto-detection
out := clog.Stderr(clog.ColorAlways) // os.Stderr with forced colors
out := clog.NewOutput(w, clog.ColorNever) // arbitrary writer, colors disabled
out := clog.TestOutput(&buf) // shorthand for NewOutput(w, ColorNever)
Output methods:
| Method | Description |
|---|---|
Writer() | Returns the underlying io.Writer |
IsTTY() | True if the writer is connected to a terminal |
ColorsDisabled() | True if colors are suppressed for this output |
Width() | Terminal width (0 for non-TTY, lazily cached) |
RefreshWidth() | Re-detect terminal width on next Width() call |
Custom Logger
logger := clog.New(clog.Stderr(clog.ColorAuto))
logger.SetLevel(clog.LevelDebug)
logger.SetReportTimestamp(true)
logger.SetTimeFormat("15:04:05.000")
logger.SetFieldTimeFormat(time.Kitchen) // format for .Time() fields (default: time.RFC3339)
logger.SetTimeLocation(time.UTC) // timezone for timestamps (default: time.Local)
logger.SetFieldStyleLevel(clog.LevelTrace) // min level for field value styling (default: clog.LevelInfo)
logger.SetNonTTYLevel(clog.LevelWarn) // suppress below Warn on non-TTY writers
logger.SetHandler(myHandler)
For simple cases where you just need a writer with default color detection:
logger := clog.NewWriter(os.Stderr) // equivalent to New(NewOutput(os.Stderr, ColorAuto))
Field Formats
Field formatting (durations, elapsed timers, percentages, numbers, hyperlinks, quantity units) is configured per-logger via the FieldFormats struct. Start from DefaultFieldFormats(), set the fields you want, and apply with SetFieldFormats - configuration is per-Logger, so two loggers can format fields differently:
f := clog.DefaultFieldFormats()
f.PercentPrecision = 1 // "75.0%" instead of "75%"
f.ElapsedGradientMax = 30 * time.Second // enable the elapsed gradient
f.HyperlinkLineFormat = "vscode" // preset name, expanded on SetFieldFormats
logger.SetFieldFormats(f)
// Or configure the package-level Default logger:
clog.SetFieldFormats(f)
// Read back the current configuration:
current := logger.FieldFormats()
SetFieldFormats has replace-all semantics (like SetParts): the struct you pass replaces the logger’s entire field-format configuration, so always start from DefaultFieldFormats() (or logger.FieldFormats()) rather than a zero value.
To change a single option without the read-modify-write dance, each field has a per-field convenience setter that preserves the rest of the snapshot - e.g. logger.SetPercentPrecision(1), logger.SetElapsedGradientMax(30*time.Second), logger.SetHyperlinkFileFormat("vscode") (presets are expanded and pushed to the output automatically). These also exist as package-level functions for the Default logger (clog.SetPercentPrecision(1), etc.).
SetTimeGradientMax(max) is a shorthand that sets both DurationGradientMax and ElapsedGradientMax at once, since duration and elapsed fields usually share a gradient ceiling.
| Field | Type | Default | Description |
|---|---|---|---|
DurationFormat | func(time.Duration) string | nil (built-in) | Custom formatter for Duration fields (also used for elapsed when ElapsedFormat is nil) |
DurationGradientMax | time.Duration | 0 (disabled) | Max duration for the Duration field gradient |
DurationMinimum | time.Duration | time.Second | Hide duration fields below this duration (0 shows all values) |
DurationPrecision | int | 0 | Decimal places for duration display (0 = 3s, 1 = 3.2s) |
DurationRound | time.Duration | time.Second | Rounding granularity for duration values (0 disables rounding) |
ElapsedFormat | func(time.Duration) string | nil (built-in) | Custom formatter for elapsed fields (takes priority over DurationFormat) |
ElapsedGradientMax | time.Duration | 0 (disabled) | Max duration for the elapsed gradient |
ElapsedMinimum | time.Duration | time.Second | Hide elapsed fields below this duration (0 shows all values) |
ElapsedPrecision | int | 0 | Decimal places for elapsed display (0 = 3s, 1 = 3.2s) |
ElapsedRound | time.Duration | time.Second | Rounding granularity for elapsed values (0 disables rounding) |
HyperlinkEnabled | bool | true | Enable/disable all hyperlink rendering |
HyperlinkColumnFormat | string | "" | URL format for file+line+column hyperlinks |
HyperlinkDirFormat | string | "" | URL format for directory hyperlinks |
HyperlinkFileFormat | string | "" | URL format for file-only hyperlinks |
HyperlinkLineFormat | string | "" | URL format for file+line hyperlinks |
HyperlinkPathFormat | string | "" | Generic fallback URL format for any path |
PercentFormat | func(float64) string | nil (built-in) | Custom formatter for Percent fields (receives the display value, already scaled to 0–100) |
PercentMaximum | float64 | 0 (= 1.0) | Percent input maximum (0 means 1.0 = fractions 0–1; set 100 for 0–100 input) |
PercentPrecision | int | 0 | Decimal places for Percent display (0 = 75%, 1 = 75.0%) |
PercentReverseGradient | bool | false | Reverse the percent gradient (green=0%, red=100%) |
NumberFormat | NumberFormat | NumberPlain | How integers and both halves of fractions render (plain, grouped, compact) |
FractionFormat | *NumberFormat | nil (inherit) | Overrides NumberFormat for fraction fields only (nil inherits NumberFormat) |
NumberGroupSeparator | string | "," | Digit-group separator for NumberGrouped (e.g. 1,234,567) |
NumberCompactMinimum | int64 | 1000 | Smallest magnitude NumberCompact abbreviates; values below it use the fallback |
NumberCompactFallback | NumberFormat | NumberGrouped | How NumberCompact renders sub-minimum values (NumberGrouped or NumberPlain) |
QuantityUnitsIgnoreCase | bool | true | Case-insensitive quantity unit matching |
Hyperlink format fields accept either a full format string with {path}/{line}/{column} placeholders, or a named preset (e.g. "vscode"), which is expanded when SetFieldFormats is called. See Hyperlinks for details.
Number formatting
By default numbers render verbatim (1234567, 1234567/9999999). Three modes control how integer fields and both halves of a Fraction are rendered:
NumberPlain- verbatim, e.g.1234567(the default).NumberGrouped- locale-style digit grouping, e.g.1,234,567. The separator is configurable.NumberCompact- abbreviated with K/M/B/T suffixes, e.g.1.2M. Values belowNumberCompactMinimum(default1000) render withNumberCompactFallback(grouped by default), so a series reads9,999→10K→11Krather than jumping straight from plain to abbreviated. SetNumberCompactFallback = NumberPlainto keep small values verbatim (9999).
Convenience setters avoid the read-modify-write dance for the common cases:
logger.SetNumberFormat(clog.NumberGrouped) // applies to ints AND fractions
logger.SetNumberGroupSeparator(" ") // "1 234 567"
logger.SetFractionFormat(clog.NumberCompact) // fractions only; ints keep NumberFormat
logger.SetNumberCompactMinimum(10_000) // only abbreviate at >= 10,000
To combine grouping and abbreviation - grouped digits for small values, K/M/B/T suffixes for large ones - select NumberCompact and raise the minimum:
logger.SetNumberFormat(clog.NumberCompact)
logger.SetNumberCompactMinimum(10_000) // 9,999 -> 10K -> 11K -> 1.2M
SetNumberFormat is the global knob; SetFractionFormat overrides it for fractions and falls back to it when unset. A single field can override both via fraction.WithFormat:
clog.Info("progress").
Fraction("done", 1234567, 9999999, fraction.WithFormat(clog.NumberCompact)).
Send() // done=1.2M/10M
The separator is not locale-aware - pick the one that suits your output (",", ".", " ", "_").
Utility Functions
clog.GetLevel() // returns the current level of the Default logger
clog.IsVerbose() // true if level is Debug or Trace
clog.IsTerminal() // true if Default output is a terminal
clog.ColorsDisabled() // true if colors are disabled on the Default logger
clog.SetOutput(out) // change the output (accepts *Output)
clog.SetOutputWriter(w) // change the output writer (with ColorAuto)
clog.SetExitCode(2) // set default Fatal exit code (default: 1)
clog.SetExitFunc(fn) // override os.Exit for Fatal (useful in tests)
logger.Output() // returns the Logger's *Output
Environment Variables
All env vars follow the pattern {PREFIX}_{SUFFIX}. The default prefix is CLOG.
| Suffix | Default env var |
|---|---|
LOG_LEVEL | CLOG_LOG_LEVEL |
HYPERLINK_FORMAT | CLOG_HYPERLINK_FORMAT |
HYPERLINK_PATH_FORMAT | CLOG_HYPERLINK_PATH_FORMAT |
HYPERLINK_FILE_FORMAT | CLOG_HYPERLINK_FILE_FORMAT |
HYPERLINK_DIR_FORMAT | CLOG_HYPERLINK_DIR_FORMAT |
HYPERLINK_LINE_FORMAT | CLOG_HYPERLINK_LINE_FORMAT |
HYPERLINK_COLUMN_FORMAT | CLOG_HYPERLINK_COLUMN_FORMAT |
CLOG_LOG_LEVEL=debug ./some-app # enables debug logging + timestamps
CLOG_LOG_LEVEL=warn ./some-app # suppresses info messages
Custom Env Prefix
Use SetEnvPrefix to whitelabel the env var names for your application. The custom prefix is checked first, with CLOG_ as a fallback.
clog.SetEnvPrefix("MYAPP")
// Now checks MYAPP_LOG_LEVEL first, then CLOG_LOG_LEVEL
// Now checks MYAPP_HYPERLINK_PATH_FORMAT first, then CLOG_HYPERLINK_PATH_FORMAT
// etc.
This means CLOG_LOG_LEVEL=debug always works as a universal escape hatch, even when the application uses a custom prefix.
NO_COLOR is never prefixed - it follows the no-color.org standard independently.