Skip to content

feat(consola): Enhance Consola integration to extract first-param object as searchable attributes - #19534

Merged
s1gr1d merged 8 commits into
developfrom
sig/consola-obj-keys
Mar 2, 2026
Merged

feat(consola): Enhance Consola integration to extract first-param object as searchable attributes#19534
s1gr1d merged 8 commits into
developfrom
sig/consola-obj-keys

Conversation

@s1gr1d

@s1gr1ds1gr1d commented Feb 26, 2026

Copy link
Copy Markdown
Member

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

// Object-firstconsola.log({userId: 123,action: "login"},"User logged in");// → message: "User logged in", attributes: { userId: 123, action: "login" }// With extra parametersconsola.log({userId: 123},"User action",requestId,timestamp);// → message: "User action", userId: 123, sentry.message.parameter.0: requestId, sentry.message.parameter.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: { data: 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

@s1gr1ds1gr1d changed the title Sig/consola obj keysfeat(consola): Enhance Consola integration to extract first-param object as searchable attributesFeb 26, 2026
@s1gr1d
s1gr1dforce-pushed the sig/consola-obj-keys branch from c71c835 to fcfd91cCompareFebruary 26, 2026 13:51
/**
* Extracts structured attributes from console arguments. If the first argument is a plain object, its properties are extracted as attributes.
*/
function defaultExtractAttributes(

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a function that could be theoretically added by users (as a future feature). That's why this function is extra from the processExtractedAttributes. In theory, it could just be one function.

@github-actions

github-actionsBot commented Feb 26, 2026

Copy link
Copy Markdown
Contributor

size-limit report 📦

PathSize% ChangeChange
@sentry/browser25.63 kB--
@sentry/browser - with treeshaking flags24.13 kB--
@sentry/browser (incl. Tracing)42.43 kB--
@sentry/browser (incl. Tracing, Profiling)47.09 kB--
@sentry/browser (incl. Tracing, Replay)81.25 kB--
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags70.87 kB--
@sentry/browser (incl. Tracing, Replay with Canvas)85.94 kB--
@sentry/browser (incl. Tracing, Replay, Feedback)98.21 kB--
@sentry/browser (incl. Feedback)42.44 kB--
@sentry/browser (incl. sendFeedback)30.29 kB--
@sentry/browser (incl. FeedbackAsync)35.35 kB--
@sentry/browser (incl. Metrics)26.8 kB--
@sentry/browser (incl. Logs)26.94 kB--
@sentry/browser (incl. Metrics & Logs)27.61 kB--
@sentry/react27.38 kB--
@sentry/react (incl. Tracing)44.77 kB--
@sentry/vue30.08 kB--
@sentry/vue (incl. Tracing)44.3 kB--
@sentry/svelte25.66 kB--
CDN Bundle28.17 kB--
CDN Bundle (incl. Tracing)43.26 kB--
CDN Bundle (incl. Logs, Metrics)29.01 kB--
CDN Bundle (incl. Tracing, Logs, Metrics)44.1 kB--
CDN Bundle (incl. Replay, Logs, Metrics)68.09 kB--
CDN Bundle (incl. Tracing, Replay)80.14 kB--
CDN Bundle (incl. Tracing, Replay, Logs, Metrics)81 kB--
CDN Bundle (incl. Tracing, Replay, Feedback)85.65 kB--
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics)86.53 kB--
CDN Bundle - uncompressed82.35 kB--
CDN Bundle (incl. Tracing) - uncompressed128.07 kB--
CDN Bundle (incl. Logs, Metrics) - uncompressed85.19 kB--
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed130.9 kB--
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed208.85 kB--
CDN Bundle (incl. Tracing, Replay) - uncompressed244.95 kB--
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed247.77 kB--
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed257.86 kB--
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed260.67 kB--
@sentry/nextjs (client)47.18 kB--
@sentry/sveltekit (client)42.89 kB--
@sentry/node-core52.24 kB+0.02%+9 B 🔺
@sentry/node174.69 kB+0.01%+4 B 🔺
@sentry/node - without tracing97.39 kB+0.02%+11 B 🔺
@sentry/aws-serverless113.19 kB+0.01%+6 B 🔺

View base workflow run

@github-actions

github-actionsBot commented Feb 26, 2026

Copy link
Copy Markdown
Contributor

node-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.

ScenarioRequests/s% of BaselinePrev. Requests/sChange %
GET Baseline8,713-9,045-4%
GET With Sentry1,54018%1,613-5%
GET With Sentry (error only)5,86867%6,044-3%
POST Baseline1,166-1,188-2%
POST With Sentry56148%561-
POST With Sentry (error only)1,03389%1,036-0%
MYSQL Baseline3,108-3,190-3%
MYSQL With Sentry33611%356-6%
MYSQL With Sentry (error only)2,58283%2,615-1%

View base workflow run

Comment threadpackages/core/src/integrations/consola.ts

@chargomechargome left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

Comment threadpackages/core/src/integrations/consola.ts
/**
* Result of extracting structured attributes from console arguments.
*/
export interface ExtractAttributesResult {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

l: I would not export this as long as the functions stays internal.

@s1gr1d
s1gr1dforce-pushed the sig/consola-obj-keys branch from fcfd91c to 282b963CompareFebruary 27, 2026 09:20

@cursorcursorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Comment threadpackages/core/src/integrations/consola.ts
@s1gr1d
s1gr1d enabled auto-merge (squash) March 2, 2026 10:08
@s1gr1d
s1gr1d merged commit 0dcdd58 into developMar 2, 2026
437 of 439 checks passed
@s1gr1d
s1gr1d deleted the sig/consola-obj-keys branch March 2, 2026 12:29
s1gr1d added a commit that referenced this pull request Jun 9, 2026
…gration` (#21385)
Aligns the console integration so object-first logs are structured,
matching the consola integration behavior. If the first argument is an
object, the keys are added as log attributes.
Reference PR (consola):
#19534
The universal principle is this:
```
IF first_argument is plain_object:
attributes ← first_argument keys/values
message ← second_argument (if string) OR empty
remaining_args → sentry.message.parameter.{0, 1, 2...}
ELSE:
message ← formatted(all_args)
args[1:] → sentry.message.parameter.{0, 1, 2...}
```
### Example Snippet
```js
console.warn({ component: 'PaymentService', retryCount: 3 }, 500, 'TIMEOUT');
console.info(
{ userId: 42, action: 'purchase' },
'Console [OBJ-FIRST+PARAMS]: Checkout complete',
testOrder.orderId,
testOrder.total,
);
```
#### Before
<img width="1434" height="662" alt="image"
src="https://github.com/user-attachments/assets/19f310dd-d417-48fd-acb3-7695e28417b7"
/>
#### After
<img width="1425" height="665" alt="image"
src="https://github.com/user-attachments/assets/6f722ce3-e698-46fa-ba22-5f1f42304f65"
/>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Consola logging add object as extra data/context

2 participants

@s1gr1d@chargome