While reading packages/logfire-api/src/formatter.ts I noticed nested template fields like {a.b} don't traverse into the attribute value. In getField (the loop around line 65) every path segment after the first is looked up in the top-level record instead of the object being walked, so one of two things happens:
import * as logfire from 'logfire'
// 1. falls back to the raw template
logfire.info('hello {user.name}', { user: { name: 'Alice' } })
// message: "hello {user.name}" plus a "Formatting error: The field user.name is not defined." warning
// 2. silently renders an unrelated attribute when a top-level key shares the trailing segment name
logfire.info('value is {a.b}', { a: { b: 'nested' }, b: 'top' })
// message: "value is top"
Expected (matching Python Logfire, which resolves dotted fields into the value): "hello Alice" and "value is nested". Reproduced on current main. The second case is the nasty one since there's no warning, just a wrong value in the message. Bracket syntax like {a[0]} also doesn't resolve, but that looks more like a missing feature than a wrong result, so I left it alone.
I took a stab at a fix on my fork: https://github.com/ayaangazali/logfire-js/tree/nested-template-fields (built with Claude Code's help, went through the diff myself). It walks the path segments into the value, keeps literal dotted keys like http.method winning over traversal so existing OTel-style attribute names don't change behavior, and adds a formatter.test.ts covering the cases above plus a changeset. pnpm run check is green. happy to open a PR if the approach looks right, or totally fine if it's easier to handle on your end. still learning this codebase, would love any pointers :)
While reading
packages/logfire-api/src/formatter.tsI noticed nested template fields like{a.b}don't traverse into the attribute value. IngetField(the loop around line 65) every path segment after the first is looked up in the top-levelrecordinstead of the object being walked, so one of two things happens:Expected (matching Python Logfire, which resolves dotted fields into the value): "hello Alice" and "value is nested". Reproduced on current main. The second case is the nasty one since there's no warning, just a wrong value in the message. Bracket syntax like
{a[0]}also doesn't resolve, but that looks more like a missing feature than a wrong result, so I left it alone.I took a stab at a fix on my fork: https://github.com/ayaangazali/logfire-js/tree/nested-template-fields (built with Claude Code's help, went through the diff myself). It walks the path segments into the value, keeps literal dotted keys like
http.methodwinning over traversal so existing OTel-style attribute names don't change behavior, and adds a formatter.test.ts covering the cases above plus a changeset.pnpm run checkis green. happy to open a PR if the approach looks right, or totally fine if it's easier to handle on your end. still learning this codebase, would love any pointers :)