Uh oh!
There was an error while loading. Please reload this page.
feat(core): Create template attributes in consoleLoggingIntegration - #17703
Conversation
consoleLoggingIntegrationnode-overhead report 🧳Note: This is a synthetic benchmark with a minimal express app and does not necessarily reflect the real-world performance impact in an application.
|
Lms24
left a comment
There was a problem hiding this comment.
Can see how this is useful. Sounds like a good change to me!
| }); | ||
| return attributes; | ||
| } |
There was a problem hiding this comment.
Bug: Console Template Attributes Formatting Issues
The createConsoleTemplateAttributes function has two issues. The sentry.message.template attribute includes an unintended trailing space when no followingArgs are present. Additionally, sentry.message.parameter attributes are stored as raw values instead of structured objects with value/type, and null/undefined values are not converted to their expected string representations.
Uh oh!
There was an error while loading. Please reload this page.
…ect as searchable attributes (#19534) Aligns the Consola integration so object-first logs are structured and fallback logs get template + parameters. ## Universal principle - **Object-first** (first argument is a plain object): object keys become log attributes, second argument (if string) is the message, remaining arguments → sentry.message.parameter.{0, 1, 2, ...}. - **Fallback** (first argument is not an object): message = formatted(all args), args[1:] → sentry.message.template and sentry.message.parameter.{0, 1, 2, ...} (same as console integration). ## Consola-specific behavior - **Consola-merged**: For `consola.log({ message: "x", userId, action })` Consola passes `args: ["x"]` and spreads the rest on the log object. We detect this (single string in args + extra keys on logObj) and treat it as one logical object: message = `args[0]`, attributes = extra keys. - **Object-first** now applies to any plain object as first arg (including objects with message or args keys), so e.g. `consola.log.raw({ message: "raw-hello" })` produces attributes from the object and an empty message. - **Fallback** uses the same template/parameter pattern as the console integration (no extraction of objects into top-level attributes; all post-first args go into the formatted message and `sentry.message.parameter.*`). ## Example ```ts // Object-first consola.log({ userId: 123, action: "login" }, "User logged in"); // → message: "User logged in", attributes: { userId: 123, action: "login" } // With extra parameters consola.log({ userId: 123 }, "User action", requestId, timestamp); // → message: "User action", userId: 123, sentry.message.parameter.0: requestId, .1: timestamp // Fallback (non-object first) consola.log("Legacy log", { data: 1 }, 123); // → message: "Legacy log {\"data\":1} 123", sentry.message.template: "Legacy log {} {}", sentry.message.parameter.0/1 ``` Console String substitutions are not added as a template attribute because parsing is too complicated on the client-side (see here: #17703) Closes#18593
ref #16737
Right now if users use
console.loglike so:The console logging integration will emit a log with log message
"here is my log statement".Some users would like it if we automatically paramaterized this into a template, given there are separate arguments being sent into the logging statement. So the above log statement would generate
{ "sentry.message.template": "here {} {} {} {}", "sentry.message.parameter.0": "is", "sentry.message.parameter.1": "my", "sentry.message.parameter.2": "log", "sentry.message.parameter.3": "statement", }This paramaterization is what this PR does, which provides a much better user experience.
One edge case that we need to watch out for is console substitution patterns like
%s,%d,%i,%f,%o,%O,%c. Read more about this in the MDN docs. When encountering a console substitution pattern in the string, we elect to not generate string templates, as parsing the string to evaluate it gets too complicated client side.