Log::Fmt(3)

πŸ’– Log::Fmt β€” a little parser and emitter of structured log lines πŸ’–

okay so bestie, welcome to Log::Fmt(3), straight out of the User Contributed Perl Documentation corner of the universe. this is the whole page, no skips, no cuts, we're eating every last crumb πŸ“


✨ VERSION ✨

version 3.013 β€” that's the one, no cap πŸ’…


🌸 OVERVIEW 🌸

so like, this library primarily exists to service Log::Dispatchouli's log_event methods. that's its whole job, its main character arc πŸ‘‘

what it does: it takes an arrayref of key/value pairs and turns it into a string that a human can scan tolerably well, and which a machine can parse about as well. two audiences, one string, it's giving bilingual πŸ’«

and ALSO β€” and this is the fun part β€” it can do that tolerably-okay parsing for you. you don't have to do it yourself. iconic behaviour honestly 🫢


πŸ¦‹ PERL VERSION πŸ¦‹

this library should run on perls released even a long time ago. like, it should work on any version of perl released in the last five years. ancient-perl-friendly, we love her for that ⭐

although it may work on older versions of perl, no guarantee is made that the minimum required version will not be increased. the version may be increased for any reason, and there is no promise that patches will be accepted to lower the minimum required perl.

so basically: don't come for her about the floor moving. it might. it's allowed to. πŸ’€

πŸŽ€ METHODS πŸŽ€

🌈 format_event_string

my $octets = Log::Fmt->format_event_string([
  key1 => $value1,
  key2 => $value2,
]);

note especially, bestie, that if any value to encode is a reference to a reference, then String::Flogger is used to encode the referenced value. that means you can embed, in your logfmt, a JSON dump of a structure by passing a reference to the structure, instead of passing the structure itself. sneaky? no. clever? yes. ate πŸ’…

string values are assumed to be character strings, and will be UTF-8 encoded as part of the formatting process. important. remember it. ✨

🌈 parse_event_string

my $kv_pairs = Log::Fmt->parse_event_string($octets);

given the kind of (byte) string emitted by format_event_string, this method returns a reference to an array of key/value pairs. after being unquoted, value strings will be UTF-8 decoded into character strings. so it undoes the byte-ness for you, so considerate πŸ₯Ί

now listen, this isn't exactly a round trip. not a perfect circle. let's break down why, fr fr:

  • first off, the formatting can change illegal keys by replacing characters with question marks, or replacing empty strings with tildes.
  • secondly, the formatter will expand some values like arrayrefs and hashrefs into multiple keys, but the parser will not recombine those keys into structures.
  • also, there might be other asymmetric conversions.

that said, the string escaping done by the formatter should correctly reverse. so the escaping? trustworthy. the structure stuff? one-directional. iykyk 😌

if the input string is badly formed, hunks that don't appear to be value key/value pairs will be presented as values for the key junk. so you don't lose them, they just get filed under junk. honestly same 🫠

🌈 parse_event_string_as_hash

my $hashref = Log::Fmt->parse_event_string_as_hash($line);

this parses the given line as logfmt, then puts the key/value pairs into a hash and returns a reference to it. cute, tidy, done πŸŽ€

BUT β€” because nothing prevents a single key from appearing more than once, you should use this with the understanding that data could be lost. no guarantee is made of which value will be preserved.

bestie. if your keys repeat, something is getting dropped and nobody will tell you which one. proceed with awareness. 😭

πŸ‘‘ SPECIFICATION πŸ‘‘

πŸ’œ The logfmt text format

although quite a few tools exist for managing logfmt, there is no spec-like document for it. and because you may require multiple implementations, a specification can be helpful. so here it is, we made one, you're welcome 🌸

every logfmt event is a sequence of pairs in the form key=value. pairs are separated by a single space.

event = pair *(WSP pair)
pair  = key "=" value
okchr = %x21 / %x23-3c / %x3e-5b / %x5d-7e ; VCHAR minus \ and " and =
key   = 1*(okchr)
value = key / quoted

quoted = DQUOTE *( escaped / quoted-ok / okchr / eightbit ) DQUOTE
escaped         = escaped-special / escaped-hex
escaped-special = "\\" / "\n" / "\r" / "\t" / ("\" DQUOTE)
escaped-hex     = "\x{" 2HEXDIG "}" ; lowercase forms okay also
quoted-ok       = SP / "="
eightbit        = %x80-ff

when formatting a value, if a value is already a valid key token, use it without further quoting. no extra quotes, she's already valid, let her breathe ✨

πŸ’œ Quoting a Unicode string

it is preferable to build quoted values from a Unicode string, because it's possible to know whether a given codepoint is a non-ASCII unsafe character, like LINE SEPARATOR. safe non-ASCII characters can be directly UTF-8 encoded, rather than quoted with \x{...}. in that way, viewing logfmt events with a standard terminal can show something like:

user.name="JΓΌrgen"

see?? pretty. readable. the vibes are immaculate 🌈

to generate a quoted from a Unicode string, for each codepoint:

  • convert \ to \\
  • convert " to \"
  • convert a newline (U+000A) to \n
  • convert a carriage return (U+000D) to \r
  • convert a character tabulation (U+0009) to \t
  • for any control character (by general category) or vertical newline:
    • encode the character into a UTF-8 bytestring
    • convert each byte in the bytestring into \x{...} form
    • use that sequence of \x{...} codes in place of the replaced character

finally, UTF-8 encode the entire string and wrap it in double qoutes.

yes it says "qoutes". we're keeping it exactly as written. that's the original's typo and we love her, we don't touch her πŸ’–

this Perl implementation assumes that all string values to be encoded are character strings!

🧚 Quoting a bytestring

encoding a Unicode string is preferable, but may not be practical. in those cases when you have only a byte sequence, apply these steps.

for each byte (using ASCII conventions):

  • convert \ to \\
  • convert " to \"
  • convert a newline (%0a) to \n
  • convert a carriage return (%0d) to \r
  • convert a character tabulation (%x09) to \t
  • convert any control character (%x00-1f / %x7f) to the \x{...} form
  • convert any non-ASCII byte (%x80-ff) to the \x{...} form

finally, wrap the string in double quotes.


🫢 AUTHOR 🫢

Ricardo SIGNES <cpan@semiotic.systems> β€” legend behaviour, honestly πŸ‘‘


this software is copyright (c) 2025 by Ricardo SIGNES.

this is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.


and that's the whole page bestie, no notes, no skips, every last flag and codepoint accounted for πŸŽ€

this was Log::Fmt version 3.013, shipped with perl v5.42.0 and dated 2026-01-17 β€” thanks for reading, mwah πŸ’‹βœ¨πŸŒΈ

πŸ“¦ where this page comes from