Skip to content
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import * as Sentry from '@sentry/node';
import { loggingTransport } from '@sentry-internal/node-integration-tests';
import { consola } from 'consola';

Sentry.init({
dsn: 'https://[email protected]/1337',
release: '1.0.0',
environment: 'test',
enableLogs: true,
transport: loggingTransport,
});

async function run(): Promise<void> {
consola.level = 5;

const sentryReporter = Sentry.createConsolaReporter();
consola.addReporter(sentryReporter);

// Object context extraction - objects should become searchable attributes
consola.info('User logged in', { userId: 123, sessionId: 'abc-123' });

// Multiple objects - properties should be merged
consola.warn('Payment processed', { orderId: 456 }, { amount: 99.99, currency: 'USD' });

// Mixed primitives and objects
consola.error('Error occurred', 'in payment module', { errorCode: 'E001', retryable: true });

// Arrays (should be stored as context attributes)
consola.debug('Processing items', [1, 2, 3, 4, 5]);

// Nested objects
consola.info('Complex data', { user: { id: 789, name: 'Jane' }, metadata: { source: 'api' } });

// Deep nesting to test normalizeDepth (should be normalized at depth 3 - default)
consola.info('Deep object', {
level1: {
level2: {
level3: {
level4: { level5: 'should be normalized' },
},
},
},
simpleKey: 'simple value',
});

await Sentry.flush();
}

// eslint-disable-next-line @typescript-eslint/no-floating-promises
void run();
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import * as Sentry from '@sentry/node';
import { loggingTransport } from '@sentry-internal/node-integration-tests';
import { consola } from 'consola';

Sentry.init({
dsn: 'https://[email protected]/1337',
release: '1.0.0',
environment: 'test',
enableLogs: true,
transport: loggingTransport,
});

async function run(): Promise<void> {
consola.level = 5;

const sentryReporter = Sentry.createConsolaReporter();
consola.addReporter(sentryReporter);

// Test Date objects are preserved
consola.info('Current time:', new Date('2023-01-01T00:00:00.000Z'));

// Test Error objects are preserved
consola.error('Error occurred:', new Error('Test error'));

// Test RegExp objects are preserved
consola.info('Pattern:', /test/gi);

// Test Map and Set objects are preserved
consola.info('Collections:', new Map([['key', 'value']]), new Set([1, 2, 3]));

// Test mixed: plain object + special object
consola.info('Mixed data', { userId: 123 }, new Date('2023-06-15T12:00:00.000Z'));

await Sentry.flush();
}

// eslint-disable-next-line @typescript-eslint/no-floating-promises
void run();

242 changes: 241 additions & 1 deletion dev-packages/node-integration-tests/suites/consola/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ describe('consola integration', () => {
{
timestamp: expect.any(Number),
level: 'info',
body: 'Message with args: hello 123 {"key":"value"} [1,2,3]',
body: 'Message with args: hello 123',
severity_number: expect.any(Number),
trace_id: expect.any(String),
attributes: {
Expand All @@ -291,6 +291,7 @@ describe('consola integration', () => {
'server.address': { value: expect.any(String), type: 'string' },
'consola.type': { value: 'info', type: 'string' },
'consola.level': { value: 3, type: 'integer' },
key: { value: 'value', type: 'string' },
Copy link

Choose a reason for hiding this comment

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

Test missing assertion for array attribute extraction (Bugbot Rules)

Per the review rules: "Check that tests actually test the newly added behaviour. When checking on sent payloads by the SDK, ensure that the newly added data is asserted thoroughly." The test subject at subject-args.ts line 24 includes an array [1, 2, 3] in the args, which per the new feature should be stored as consola.args.0. However, the test's expected attributes at lines 285-295 only assert key: 'value' but not the consola.args.0 attribute for the array, leaving the array extraction behavior unverified in this test case.

Fix in Cursor Fix in Web

},
},
{
Expand Down Expand Up @@ -491,4 +492,243 @@ describe('consola integration', () => {

await runner.completed();
});

test('should extract objects as searchable context attributes', async () => {
const runner = createRunner(__dirname, 'subject-object-context.ts')
.expect({
log: {
items: [
{
timestamp: expect.any(Number),
level: 'info',
body: 'User logged in',
severity_number: expect.any(Number),
trace_id: expect.any(String),
attributes: {
'sentry.origin': { value: 'auto.log.consola', type: 'string' },
'sentry.release': { value: '1.0.0', type: 'string' },
'sentry.environment': { value: 'test', type: 'string' },
'sentry.sdk.name': { value: 'sentry.javascript.node', type: 'string' },
'sentry.sdk.version': { value: expect.any(String), type: 'string' },
'server.address': { value: expect.any(String), type: 'string' },
'consola.type': { value: 'info', type: 'string' },
'consola.level': { value: 3, type: 'integer' },
userId: { value: 123, type: 'integer' },
sessionId: { value: 'abc-123', type: 'string' },
},
},
{
timestamp: expect.any(Number),
level: 'warn',
body: 'Payment processed',
severity_number: expect.any(Number),
trace_id: expect.any(String),
attributes: {
'sentry.origin': { value: 'auto.log.consola', type: 'string' },
'sentry.release': { value: '1.0.0', type: 'string' },
'sentry.environment': { value: 'test', type: 'string' },
'sentry.sdk.name': { value: 'sentry.javascript.node', type: 'string' },
'sentry.sdk.version': { value: expect.any(String), type: 'string' },
'server.address': { value: expect.any(String), type: 'string' },
'consola.type': { value: 'warn', type: 'string' },
'consola.level': { value: 1, type: 'integer' },
orderId: { value: 456, type: 'integer' },
amount: { value: 99.99, type: 'double' },
currency: { value: 'USD', type: 'string' },
},
},
{
timestamp: expect.any(Number),
level: 'error',
body: 'Error occurred in payment module',
severity_number: expect.any(Number),
trace_id: expect.any(String),
attributes: {
'sentry.origin': { value: 'auto.log.consola', type: 'string' },
'sentry.release': { value: '1.0.0', type: 'string' },
'sentry.environment': { value: 'test', type: 'string' },
'sentry.sdk.name': { value: 'sentry.javascript.node', type: 'string' },
'sentry.sdk.version': { value: expect.any(String), type: 'string' },
'server.address': { value: expect.any(String), type: 'string' },
'consola.type': { value: 'error', type: 'string' },
'consola.level': { value: 0, type: 'integer' },
errorCode: { value: 'E001', type: 'string' },
retryable: { value: true, type: 'boolean' },
},
},
{
timestamp: expect.any(Number),
level: 'debug',
body: 'Processing items',
severity_number: expect.any(Number),
trace_id: expect.any(String),
attributes: {
'sentry.origin': { value: 'auto.log.consola', type: 'string' },
'sentry.release': { value: '1.0.0', type: 'string' },
'sentry.environment': { value: 'test', type: 'string' },
'sentry.sdk.name': { value: 'sentry.javascript.node', type: 'string' },
'sentry.sdk.version': { value: expect.any(String), type: 'string' },
'server.address': { value: expect.any(String), type: 'string' },
'consola.type': { value: 'debug', type: 'string' },
'consola.level': { value: 4, type: 'integer' },
'consola.args.0': { value: '[1,2,3,4,5]', type: 'string' },
},
},
{
timestamp: expect.any(Number),
level: 'info',
body: 'Complex data',
severity_number: expect.any(Number),
trace_id: expect.any(String),
attributes: {
'sentry.origin': { value: 'auto.log.consola', type: 'string' },
'sentry.release': { value: '1.0.0', type: 'string' },
'sentry.environment': { value: 'test', type: 'string' },
'sentry.sdk.name': { value: 'sentry.javascript.node', type: 'string' },
'sentry.sdk.version': { value: expect.any(String), type: 'string' },
'server.address': { value: expect.any(String), type: 'string' },
'consola.type': { value: 'info', type: 'string' },
'consola.level': { value: 3, type: 'integer' },
user: { value: '{"id":789,"name":"Jane"}', type: 'string' },
metadata: { value: '{"source":"api"}', type: 'string' },
},
},
{
timestamp: expect.any(Number),
level: 'info',
body: 'Deep object',
severity_number: expect.any(Number),
trace_id: expect.any(String),
attributes: {
'sentry.origin': { value: 'auto.log.consola', type: 'string' },
'sentry.release': { value: '1.0.0', type: 'string' },
'sentry.environment': { value: 'test', type: 'string' },
'sentry.sdk.name': { value: 'sentry.javascript.node', type: 'string' },
'sentry.sdk.version': { value: expect.any(String), type: 'string' },
'server.address': { value: expect.any(String), type: 'string' },
'consola.type': { value: 'info', type: 'string' },
'consola.level': { value: 3, type: 'integer' },
// Nested objects are extracted and normalized respecting normalizeDepth setting
level1: { value: '{"level2":{"level3":{"level4":"[Object]"}}}', type: 'string' },
simpleKey: { value: 'simple value', type: 'string' },
},
},
],
},
})
.start();

await runner.completed();
});

test('should preserve special objects (Date, Error, RegExp, Map, Set) as context attributes', async () => {
const runner = createRunner(__dirname, 'subject-special-objects.ts')
.expect({
log: {
items: [
{
timestamp: expect.any(Number),
level: 'info',
body: 'Current time:',
severity_number: expect.any(Number),
trace_id: expect.any(String),
attributes: {
'sentry.origin': { value: 'auto.log.consola', type: 'string' },
'sentry.release': { value: '1.0.0', type: 'string' },
'sentry.environment': { value: 'test', type: 'string' },
'sentry.sdk.name': { value: 'sentry.javascript.node', type: 'string' },
'sentry.sdk.version': { value: expect.any(String), type: 'string' },
'server.address': { value: expect.any(String), type: 'string' },
'consola.type': { value: 'info', type: 'string' },
'consola.level': { value: 3, type: 'integer' },
// Date objects serialize with extra quotes
'consola.args.0': { value: '"2023-01-01T00:00:00.000Z"', type: 'string' },
},
},
{
timestamp: expect.any(Number),
level: 'error',
body: 'Error occurred:',
severity_number: expect.any(Number),
trace_id: expect.any(String),
attributes: {
'sentry.origin': { value: 'auto.log.consola', type: 'string' },
'sentry.release': { value: '1.0.0', type: 'string' },
'sentry.environment': { value: 'test', type: 'string' },
'sentry.sdk.name': { value: 'sentry.javascript.node', type: 'string' },
'sentry.sdk.version': { value: expect.any(String), type: 'string' },
'server.address': { value: expect.any(String), type: 'string' },
'consola.type': { value: 'error', type: 'string' },
'consola.level': { value: 0, type: 'integer' },
// Error objects serialize as empty object (properties are non-enumerable)
'consola.args.0': { value: '{}', type: 'string' },
},
},
{
timestamp: expect.any(Number),
level: 'info',
body: 'Pattern:',
severity_number: expect.any(Number),
trace_id: expect.any(String),
attributes: {
'sentry.origin': { value: 'auto.log.consola', type: 'string' },
'sentry.release': { value: '1.0.0', type: 'string' },
'sentry.environment': { value: 'test', type: 'string' },
'sentry.sdk.name': { value: 'sentry.javascript.node', type: 'string' },
'sentry.sdk.version': { value: expect.any(String), type: 'string' },
'server.address': { value: expect.any(String), type: 'string' },
'consola.type': { value: 'info', type: 'string' },
'consola.level': { value: 3, type: 'integer' },
// RegExp objects serialize as empty object
'consola.args.0': { value: '{}', type: 'string' },
},
},
{
timestamp: expect.any(Number),
level: 'info',
body: 'Collections:',
severity_number: expect.any(Number),
trace_id: expect.any(String),
attributes: {
'sentry.origin': { value: 'auto.log.consola', type: 'string' },
'sentry.release': { value: '1.0.0', type: 'string' },
'sentry.environment': { value: 'test', type: 'string' },
'sentry.sdk.name': { value: 'sentry.javascript.node', type: 'string' },
'sentry.sdk.version': { value: expect.any(String), type: 'string' },
'server.address': { value: expect.any(String), type: 'string' },
'consola.type': { value: 'info', type: 'string' },
'consola.level': { value: 3, type: 'integer' },
// Map converted to object, Set converted to array
'consola.args.0': { value: '{"key":"value"}', type: 'string' },
'consola.args.1': { value: '[1,2,3]', type: 'string' },
},
},
{
timestamp: expect.any(Number),
level: 'info',
body: 'Mixed data',
severity_number: expect.any(Number),
trace_id: expect.any(String),
attributes: {
'sentry.origin': { value: 'auto.log.consola', type: 'string' },
'sentry.release': { value: '1.0.0', type: 'string' },
'sentry.environment': { value: 'test', type: 'string' },
'sentry.sdk.name': { value: 'sentry.javascript.node', type: 'string' },
'sentry.sdk.version': { value: expect.any(String), type: 'string' },
'server.address': { value: expect.any(String), type: 'string' },
'consola.type': { value: 'info', type: 'string' },
'consola.level': { value: 3, type: 'integer' },
// Plain object properties are extracted
userId: { value: 123, type: 'integer' },
// Date is preserved in context
'consola.args.0': { value: '"2023-06-15T12:00:00.000Z"', type: 'string' },
},
},
],
},
})
.start();

await runner.completed();
});
});
Loading
Loading