Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Styles

Customise the visual appearance using lipgloss styles:

Styled output

clog.SetStyles(&style.Config{
  // Customise level colors
  Levels: style.LevelMap{
    clog.LevelError: new(
      lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("9")), // bright red
    ),
  },
  // Customise field key appearance
  KeyDefault: new(
    lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("12")), // bright blue
  ),
})

SetStyles merges non-zero fields into the existing configuration - only the fields you set are changed, all others keep their current values.

Value Coloring

Values are styled with a three-tier priority system:

  1. Key styles - style all values of a specific field key
  2. Value styles - style values matching a typed key (bool true != string "true")
  3. Type styles - style values by their Go type
clog.SetStyles(&style.Config{
  // 1. Key styles: all values of the "status" field are green
  Keys: style.Map{
    "status": new(lipgloss.NewStyle().Foreground(lipgloss.Color("2"))),
  },
  // 2. Value styles: typed key matches (bool `true` != string "true")
  Values: style.ValueMap{
    "PASS": new(lipgloss.NewStyle().Foreground(lipgloss.Color("2"))),
    "FAIL": new(lipgloss.NewStyle().Foreground(lipgloss.Color("1"))),
  },
  // 3. Type styles
  FieldString: new(lipgloss.NewStyle().Foreground(lipgloss.Color("15"))),
  FieldNumber: new(lipgloss.NewStyle().Foreground(lipgloss.Color("5"))),
  FieldError:  new(lipgloss.NewStyle().Foreground(lipgloss.Color("1"))),
})

Styles Reference

FieldTypeAliasDefault
BacktickStyleterracotta
BacktickModestyle.BacktickModestyle.BacktickStrip
DurationGradient[]style.ColorStopgreen → yellow → red
DurationGradientModestyle.GradientModestyle.GradientFade
DurationThresholdsmap[string][]ThresholdThresholdMap{}
DurationUnitsmap[string]StyleStyleMap{}
ElapsedGradient[]style.ColorStopgreen → yellow → red
ElapsedGradientModestyle.GradientModestyle.GradientFade
FieldDurationNumberStylemagenta
FieldDurationUnitStylemagenta faint
FieldElapsedNumberStylenil (→ DurationNumber)
FieldElapsedUnitStylenil (→ DurationUnit)
FieldErrorStylered
FieldFractionSeparatorStylenil (→ value color, faint)
FieldNumberStylemagenta
FieldPercentStylenil
FieldQuantityNumberStylemagenta
FieldQuantityUnitStylemagenta faint
FieldQuote*QuoteStylenil (→ value’s style)
FieldStringStylewhite
FieldTimeStylemagenta
KeyDefaultStyleblue
Keysmap[string]StyleStyleMap{}
Levelsmap[Level]StyleLevelStyleMapper-level bold colors
Messagesmap[Level]StyleLevelStyleMapstyle.DefaultMessages()
PercentGradient[]style.ColorStopred → yellow → green
QuantityThresholdsmap[string][]ThresholdThresholdMap{}
QuantityUnitsmap[string]StyleStyleMap{}
SeparatorStylefaint
Symbolsmap[Level]StyleLevelStyleMap{}
TimestampStylefaint
Valuesmap[any]StyleValueStyleMapstyle.DefaultValues()

Syntax Highlighting

Per-token styles for the Printer. Each has a Default*() constructor with Dracula-inspired colors. Set to nil to disable highlighting for that format.

FieldTypeDefault
HCL*style.HCLstyle.DefaultHCL()
JSON*style.JSONstyle.DefaultJSON()
TOML*style.TOMLstyle.DefaultTOML()
YAML*style.YAMLstyle.DefaultYAML()

See Printer for per-format token style tables.

Field Descriptions

FieldDescription
BacktickStyle for text inside backtick pairs in messages and string field values, nil to disable
BacktickModeBacktick delimiters: BacktickStrip drops them, BacktickKeep keeps them (width-stable)
DurationGradientGradient color stops for Duration fields; active when FieldFormats.DurationGradientMax > 0
DurationGradientModeGradient transition mode: GradientFade (smooth) or GradientStep (discrete)
DurationThresholdsDuration unit -> magnitude-based style thresholds
DurationUnitsDuration unit string -> style override
ElapsedGradientGradient color stops for Elapsed fields; active when FieldFormats.ElapsedGradientMax > 0
ElapsedGradientModeGradient transition mode: GradientFade (smooth) or GradientStep (discrete)
FieldDurationNumberStyle for numeric segments of duration values (e.g. “1” in “1m30s”), nil to disable
FieldDurationUnitStyle for unit segments of duration values (e.g. “m” in “1m30s”), nil to disable
FieldElapsedNumberStyle for numeric segments of elapsed-time values; nil falls back to FieldDurationNumber
FieldElapsedUnitStyle for unit segments of elapsed-time values; nil falls back to FieldDurationUnit
FieldErrorStyle for error field values, nil to disable
FieldFractionSeparatorStyle for the / in fraction values; nil keeps the value’s color and adds the faint attribute
FieldNumberStyle for int/float field values, nil to disable
FieldPercentBase style for Percent fields (foreground overridden by gradient), nil to disable
FieldQuantityNumberStyle for numeric part of quantity values (e.g. “5” in “5km”), nil to disable
FieldQuantityUnitStyle for unit part of quantity values (e.g. “km” in “5km”), nil to disable
FieldQuoteStyle for the quote delimiters around quoted values (set Inherit to keep the value’s color)
FieldStringStyle for string field values, nil to disable
FieldTimeStyle for time.Time field values, nil to disable
KeyDefaultStyle for field key names without a per-key override, nil to disable
KeysField key name -> value style override
LevelsPer-level label style (e.g. “INF”, “ERR”), nil to disable
MessagesPer-level message text style, nil to disable
PercentGradientGradient color stops for Percent fields
QuantityThresholdsQuantity unit -> magnitude-based style thresholds
QuantityUnitsQuantity unit string -> style override
SeparatorStyle for the separator between key and value
SymbolsPer-level symbol style
TimestampStyle for the timestamp, nil to disable
ValuesTyped value -> style (uses Go equality, so bool true != string "true")

Configuration

Behavioural settings are configured via setter methods on Logger (or package-level convenience functions for the Default logger):

SetterTypeDefaultDescription
SetAnimationIntervaltime.Duration67msMinimum refresh interval for all animations (0 = use built-in rates)
SetFieldSortSortSortNoneSort order: SortNone, SortAscending, SortDescending
SetSeparatorTextstring"="Key/value separator string

Field formatting behaviour (gradient maxima, format functions, percent precision, hyperlink formats, etc.) is configured per-logger via the FieldFormats struct - see Field Formats.

Each Threshold pairs a minimum value with style overrides:

type ThresholdStyle struct {
  Number Style // Override for the number segment (nil = keep default).
  Unit   Style // Override for the unit segment (nil = keep default).
}

type Threshold struct {
  Value float64        // Minimum numeric value (inclusive) to trigger this style.
  Style ThresholdStyle // Style overrides for number and unit segments.
}

Thresholds are evaluated in descending order - the first match wins:

styles.QuantityThresholds["ms"] = style.Thresholds{
  {Value: 5000, Style: style.ThresholdStyle{Number: redStyle, Unit: redStyle}},
  {Value: 1000, Style: style.ThresholdStyle{Number: yellowStyle, Unit: yellowStyle}},
}

Value styles only apply at Info level and above by default. Use SetFieldStyleLevel to change the threshold.

Backtick Spans

Text inside a matched pair of backticks - in the message or in string field values - is rendered with the Backtick style. By default the delimiters are dropped (style.BacktickStrip), which shrinks the message by two visible columns per span. For pre-aligned content such as grid-padded table rows, use style.BacktickKeep to render the delimiters as part of the styled span, so the visible width is exactly what was written:

clog.SetStyles(&style.Config{BacktickMode: style.BacktickKeep})

An unmatched backtick is content, not a delimiter, and is left untouched in both modes. A non-color writer always leaves backticks exactly as written.

Per-Level Message Styles

Style the log message text differently for each level:

clog.SetStyles(&style.Config{
  Messages: style.LevelMap{
    clog.LevelError: new(lipgloss.NewStyle().Foreground(lipgloss.Color("1"))),
    clog.LevelWarn:  new(lipgloss.NewStyle().Foreground(lipgloss.Color("3"))),
  },
})

Use style.DefaultMessages() to get the defaults (unstyled for all levels).

Use style.DefaultValues() to get the default value styles (true=green, false=red, nil=grey, ""=grey).

Use style.DefaultPercentGradient() to get the default red → yellow → green gradient stops used for Percent fields.

Percent Gradient Direction

By default the Percent gradient runs red (0%) → yellow (50%) → green (100%) - useful when a higher value is better (e.g. battery, health score). For metrics where a lower value is better (CPU usage, disk usage, error rate), reverse the gradient:

// Logger-wide: all Percent fields
f := clog.DefaultFieldFormats()
f.PercentReverseGradient = true
clog.SetFieldFormats(f)

// Per-field: just this Percent field, regardless of the logger setting
clog.Info().
  Percent("cpu", 0.92, percent.WithReverseGradient()).
  Percent("battery", 0.85).
  Msg("System status")
// "cpu" renders red at 92%, "battery" renders green at 85%

percent.WithReverseGradient() is a percent.Option passed directly to Event.Percent. It toggles the logger’s PercentReverseGradient setting for that field - so if the gradient is already reversed, percent.WithReverseGradient() flips it back to normal. This makes it easy to mix metrics with different semantics on the same log line regardless of the logger default.

Duration Gradient

Color Duration fields on a gradient that transitions from green (fast) through yellow to red (slow). Set a max duration to enable the gradient - duration values are mapped onto 0→max, clamping at max:

f := clog.DefaultFieldFormats()
f.DurationGradientMax = 20 * time.Second
clog.SetFieldFormats(f)

When active, the gradient overrides FieldDurationNumber / FieldDurationUnit and colors the entire formatted string. When the max is 0 (the default) or DurationGradient stops are nil, the existing number/unit split styling is used.

Use style.DefaultElapsedGradient() to get the default green → yellow → red gradient stops (shared with Elapsed by default).

The DurationGradientMode field controls transition style - see Gradient Mode below.

Override the gradient max, stops, or transition mode for a single Duration field, regardless of the logger’s FieldFormats/style.Config settings, using options from the duration package:

import "github.com/gechr/clog/field/duration"

// Logger default: 20s gradient max
clog.SetDurationGradientMax(20 * time.Second)

clog.Info().
  Duration("latency", d).                                                 // uses the 20s default
  Duration("timeout_check", d2, duration.WithGradientMax(1*time.Second)). // this field maxes out at 1s
  Msg("request handled")

Elapsed Gradient

Color elapsed-time fields on a gradient that transitions from green (fast) through yellow to red (slow). Set a max duration to enable the gradient - elapsed values are mapped onto 0→max, clamping at max:

f := clog.DefaultFieldFormats()
f.ElapsedGradientMax = 30 * time.Second
clog.SetFieldFormats(f)

When active, the gradient overrides FieldElapsedNumber / FieldElapsedUnit and colors the entire formatted string. When the max is 0 (the default) or ElapsedGradient stops are nil, the existing number/unit split styling is used.

Use style.DefaultElapsedGradient() to get the default green → yellow → red gradient stops used for Elapsed fields (same stops as DurationGradient by default).

Per-Field Overrides

Override the gradient max, stops, or transition mode for a single Elapsed field, regardless of the logger’s FieldFormats/style.Config settings, using options from the elapsed package:

import "github.com/gechr/clog/field/elapsed"

// Logger default: 30s gradient max
clog.SetElapsedGradientMax(30 * time.Second)

clog.Info().
  Elapsed("elapsed").                                            // uses the 30s default
  Elapsed("quick_step", elapsed.WithGradientMax(2*time.Second)). // this field maxes out at 2s
  Msg("batch complete")

elapsed.WithGradient(stops...) overrides the color stops, and elapsed.WithGradientMode(mode) overrides fade vs. step transitions, for that field only:

clog.Info().Elapsed("elapsed",
  elapsed.WithGradientMax(5*time.Second),
  elapsed.WithGradient(
    style.ColorStop{Position: 0, Color: colorful.Color{R: 0, G: 1, B: 1}}, // cyan
    style.ColorStop{Position: 1, Color: colorful.Color{R: 1, G: 0, B: 1}}, // magenta
  ),
  elapsed.WithGradientMode(style.GradientStep),
).Msg("render")

elapsed.WithMinimum(d) overrides ElapsedMinimum for that field only - the field is hidden entirely when its duration falls below d, regardless of the logger’s threshold:

clog.SetElapsedMinimum(time.Second) // logger default: hide fields under 1s

clog.Info().
  Elapsed("elapsed").                               // hidden if under 1s
  Elapsed("critical_step", elapsed.WithMinimum(0)). // always shown
  Msg("batch complete")

These options work the same way on animated builders - fx.Builder.Elapsed (see Spinner) accepts the same elapsed.Option values for its auto-updating field.

The duration package mirrors this for Duration fields: duration.WithGradientMax, duration.WithGradient, duration.WithGradientMode (see Duration Gradient above), and duration.WithMinimum, which overrides DurationMinimum for that field only.

Gradient Mode

Both DurationGradientMode and ElapsedGradientMode control how colors transition between stops:

ModeDescription
style.GradientFadeSmooth interpolation between stops (default)
style.GradientStepDiscrete color jumps at stop boundaries

Fade blends smoothly between adjacent color stops using perceptually uniform CIE-LCh interpolation. Step uses the color of the last stop whose position is ≤ the current value - no blending.

clog.SetStyles(&style.Config{ElapsedGradientMode: style.GradientStep})

Custom Stops

clog.SetStyles(&style.Config{
  ElapsedGradient: []style.ColorStop{
    {Position: 0, Color: colorful.Color{R: 0, G: 1, B: 0}}, // green
    {Position: 1, Color: colorful.Color{R: 1, G: 0, B: 0}}, // red
  },
})

Format Hooks

Override the default formatting for Elapsed and Percent fields via FieldFormats:

f := clog.DefaultFieldFormats()

// Custom elapsed format: truncate to whole seconds
f.ElapsedFormat = func(d time.Duration) string {
  return d.Truncate(time.Second).String()
}

// Custom percent format: "75/100" instead of "75%"
f.PercentFormat = func(v float64) string {
  return fmt.Sprintf("%.0f/100", v)
}

clog.SetFieldFormats(f)

When set to nil (the default), the built-in formatters are used (formatElapsed with ElapsedPrecision for elapsed, strconv.FormatFloat with PercentPrecision + “%” for percent). Custom percent format functions receive the display percentage (0–100), not the raw stored value.

Field Sort Order

Control the order fields appear in log output. By default fields preserve insertion order.

// Sort fields alphabetically by key
clog.SetFieldSort(clog.SortAscending)

// Or reverse alphabetical
clog.SetFieldSort(clog.SortDescending)
ConstantDescription
SortNonePreserve insertion order (default)
SortAscendingSort fields by key A→Z
SortDescendingSort fields by key Z→A
clog.Info().
  Str("zoo", "animals").
  Str("alpha", "first").
  Int("count", 42).
  Msg("Sorted")
// SortNone:       INF ℹ️ Sorted zoo=animals alpha=first count=42
// SortAscending:  INF ℹ️ Sorted alpha=first count=42 zoo=animals
// SortDescending: INF ℹ️ Sorted zoo=animals count=42 alpha=first