Configuration
Rendering is controlled by a single LoggableEncodingConfig (logging4s.core.config). A default given is provided;
override it once, application-wide:
import logging4s.core.config.*
given LoggableEncodingConfig =
LoggableEncodingConfig(
keyNameStyle = KeyNameStyle.CamelCase,
plainValuesStyle = PlainValuesStyle.Logfmt
)| Field | Default | Effect |
|---|---|---|
jsonTupleAsArray |
true |
tuple/Ior JSON: true → [1,"a"], false → {"int":1,"string":"a"} |
mapAsObject |
true |
Map JSON: true → {"a":1}, false → [["a",1]] (the 3.x shape) |
keyNameStyle |
SnakeCase |
applied to every key: AsIs / SnakeCase / KebabCase / CamelCase / PascalCase |
plainTupleStyle |
AsScala |
tuple plain form: (1, a) / [1, a] / 1, a / {1, a} |
plainValuesStyle |
Arrow |
value-list join: Arrow k -> (v), Logfmt k=v, Colon k: v, CurlyMap {k=v}, … |
includeSourcePosition |
true |
attach the call site as a source field ("OrderService.scala:42", the file name only) |
includeValuesInMessage |
true |
append the values to the message text; false keeps the message as bare static text and renders only the structured form — each value is then rendered once rather than twice, the sensible setting for a pipeline that reads only the JSON |
omitAbsentValues |
false |
true drops an absent value (None, Some(None), Unit, kyo Absent) instead of rendering null — both a top-level value and a field of a derived product. Absence is decided without rendering the value |
sumTypeDiscriminator |
None |
Some("type") makes a derived sum type's JSON lead with the variant name: {"type":"Card",…} |
keyNameStyle and plainValuesStyle are applied by the backend at aggregation time; jsonTupleAsArray,
plainTupleStyle and mapAsObject are baked into compound Loggables when they are summoned. A single top-level
given covers both.
Default keys: scalars key by type name (Loggable[Int] → int, UUID → uuid), and a derived case class by its
decapitalized name (User → user). The standard library types key by what they are:
| Types | Key |
|---|---|
Instant, java.util.Date, LocalTime and the date-time types |
time |
LocalDate |
date |
Year, YearMonth, MonthDay, Month, DayOfWeek, Period |
year, year_month, month_day, month, day_of_week, period |
ZoneId, ZoneOffset |
zone |
java.time.Duration, FiniteDuration, Duration |
time_ms — an infinite or undefined Duration renders null |
URI, URL, InetAddress, Path, Locale, Currency |
uri, url, ip, path, locale, currency |
Throwable |
error — {"class":…,"message":…}, with its cause chain nested up to five deep |
Try[A] |
error_<key of A> — the value, or the failure as a Throwable |
Collections append a plural suffix (List[Int] → ints) — a naive English one (child → childs), so set a key
where it reads badly. Two values of one type share a key, so two timestamps in one call come out as time and
time_2; give them names. A Map[K, V] keys as <k>_<v>s, which for Map[String, String] is strings — the same as
a List[String] — and a search index that maps one field to both an object and an array rejects the second, so give a
Map its own key.