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

styles := clog.DefaultStyles()

// Customise level colours
styles.Levels[clog.ErrorLevel] = new(
  lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("9")), // bright red
)

// Customise field key appearance
styles.KeyDefault = new(
  lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("12")), // bright blue
)

clog.SetStyles(styles)

Value Colouring

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
styles := clog.DefaultStyles()

// 1. Key styles: all values of the "status" field are green
styles.Keys["status"] = new(lipgloss.NewStyle().
  Foreground(lipgloss.Color("2"))) // green

// 2. Value styles: typed key matches (bool `true` != string "true")
styles.Values["PASS"] = new(
  lipgloss.NewStyle().
  Foreground(lipgloss.Color("2")), // green
)

styles.Values["FAIL"] = new(lipgloss.NewStyle().
  Foreground(lipgloss.Color("1")), // red
)

// 3. Type styles: string values -> white, numeric values -> magenta, errors -> red by default
styles.FieldString = new(lipgloss.NewStyle().Foreground(lipgloss.Color("15")))
styles.FieldNumber = new(lipgloss.NewStyle().Foreground(lipgloss.Color("5")))
styles.FieldError  = new(lipgloss.NewStyle().Foreground(lipgloss.Color("1")))
styles.FieldString = nil  // set to nil to disable
styles.FieldNumber = nil  // set to nil to disable

clog.SetStyles(styles)

Styles Reference

FieldTypeAliasDefault
DurationThresholdsmap[string][]ThresholdThresholdMap{}
DurationUnitsmap[string]StyleStyleMap{}
FieldDurationNumberStylemagenta
FieldDurationUnitStylemagenta faint
FieldElapsedNumberStylenil (→ DurationNumber)
FieldElapsedUnitStylenil (→ DurationUnit)
FieldErrorStylered
FieldJSON*JSONStylesDefaultJSONStyles()
FieldNumberStylemagenta
FieldPercentStylenil
FieldQuantityNumberStylemagenta
FieldQuantityUnitStylemagenta faint
FieldStringStylewhite
FieldTimeStylemagenta
KeyDefaultStyleblue
Keysmap[string]StyleStyleMap{}
Levelsmap[Level]StyleLevelStyleMapper-level bold colours
Messagesmap[Level]StyleLevelStyleMapDefaultMessageStyles()
Prefixesmap[Level]StyleLevelStyleMap{}
PercentGradient[]ColorStopred → yellow → green
QuantityThresholdsmap[string][]ThresholdThresholdMap{}
QuantityUnitsmap[string]StyleStyleMap{}
SeparatorStylefaint
TimestampStylefaint
Valuesmap[any]StyleValueStyleMapDefaultValueStyles()
FieldDescription
DurationThresholdsDuration unit -> magnitude-based style thresholds
DurationUnitsDuration unit string -> style override
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
FieldJSONPer-token styles for JSON syntax highlighting; nil disables highlighting
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
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
PrefixesPer-level prefix style
PercentGradientGradient colour stops for Percent fields
QuantityThresholdsQuantity unit -> magnitude-based style thresholds
QuantityUnitsQuantity unit string -> style override
SeparatorStyle for the separator between key and value
TimestampStyle for the timestamp prefix, 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)
SetElapsedFormatFuncfunc(time.Duration) stringnilCustom format function for Elapsed fields
SetElapsedMinimumtime.Durationtime.SecondMinimum duration for Elapsed fields to be displayed
SetElapsedPrecisionint0Decimal places for Elapsed display (0 = “3s”, 1 = “3.2s”)
SetElapsedRoundtime.Durationtime.SecondRounding granularity for Elapsed values (0 to disable)
SetFieldSortSortSortNoneSort order: SortNone, SortAscending, SortDescending
SetPercentFormatFuncfunc(float64) stringnilCustom format function for Percent fields
SetPercentReverseGradientboolfalseReverse the percent gradient (green=0%, red=100%) for this logger
SetPercentPrecisionint0Decimal places for Percent display (0 = “75%”, 1 = “75.0%”)
SetQuantityUnitsIgnoreCasebooltrueCase-insensitive quantity unit matching
SetSeparatorTextstring"="Key/value separator string

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"] = clog.Thresholds{
  {Value: 5000, Style: clog.ThresholdStyle{Number: redStyle, Unit: redStyle}},
  {Value: 1000, Style: clog.ThresholdStyle{Number: yellowStyle, Unit: yellowStyle}},
}

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

Per-Level Message Styles

Style the log message text differently for each level:

styles := clog.DefaultStyles()

styles.Messages[clog.ErrorLevel] = new(
  lipgloss.NewStyle().Foreground(lipgloss.Color("1")), // red
)

styles.Messages[clog.WarnLevel] = new(
  lipgloss.NewStyle().Foreground(lipgloss.Color("3")), // yellow
)

clog.SetStyles(styles)

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

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

Use 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:

// Global: all Percent fields on the Default logger
clog.SetPercentReverseGradient(true)

// Per-logger: all Percent fields on this logger
logger.SetPercentReverseGradient(true)

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

WithPercentReverseGradient() is a PercentOption passed directly to Event.Percent. It toggles the logger-level setting for that field - so if the logger already has the gradient reversed, WithPercentReverseGradient() 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.

Format Hooks

Override the default formatting for Elapsed and Percent fields:

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

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

When set to nil (the default), the built-in formatters are used (formatElapsed with SetElapsedPrecision for elapsed, strconv.FormatFloat with SetPercentPrecision + “%” for percent).

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

Renderer Binding

Styles created with lipgloss.NewStyle() are bound to the global renderer (anchored to os.Stdout). When stdout is piped, that renderer detects Ascii profile and all colours are silently stripped - even for styles meant for stderr.

clog handles this automatically: New, SetStyles, SetOutput, and SetColorMode all call WithRenderer to rebind styles to the logger’s output renderer. Custom styles passed to SetStyles are transparently rebound - no changes needed in user code.

For advanced use, Styles and JSONStyles expose WithRenderer(*lipgloss.Renderer):

styles := clog.DefaultStyles()
styles.WithRenderer(output.Renderer())

Both methods mutate and return the receiver for fluent chaining.