Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
Expand Up @@ -166,7 +166,7 @@ sentryTest('should capture console object calls', async ({ getLocalTestUrl, page
'sentry.message.template': { value: 'Mixed: {} {} {} {}', type: 'string' },
'sentry.message.parameter.0': { value: 'prefix', type: 'string' },
'sentry.message.parameter.1': { value: '{"obj":true}', type: 'string' },
'sentry.message.parameter.2': { value: '[4,5,6]', type: 'string' },
'sentry.message.parameter.2': { value: [4, 5, 6], type: 'integer[]' },
'sentry.message.parameter.3': { value: 'suffix', type: 'string' },
},
},
Expand Down Expand Up @@ -235,7 +235,7 @@ sentryTest('should capture console object calls', async ({ getLocalTestUrl, page
'sentry.message.template': { value: 'hello {} {} {}', type: 'string' },
'sentry.message.parameter.0': { value: true, type: 'boolean' },
'sentry.message.parameter.1': { value: 'null', type: 'string' },
'sentry.message.parameter.2': { value: '', type: 'string' },
'sentry.message.parameter.2': { value: 'undefined', type: 'string' },
},
},
],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// only log attribute
Sentry.logger.info('log_before_any_scope', { log_attr: 'log_attr_1' });

Sentry.getGlobalScope().setAttributes({ global_scope_attr: true });

// global scope, log attribute
Sentry.logger.info('log_after_global_scope', { log_attr: 'log_attr_2' });

Sentry.withIsolationScope(isolationScope => {
isolationScope.setAttribute('isolation_scope_1_attr', { value: 100, unit: 'millisecond' });

// global scope, isolation scope, log attribute
Sentry.logger.info('log_with_isolation_scope', { log_attr: 'log_attr_3' });

Sentry.withScope(scope => {
scope.setAttributes({ scope_attr: { value: 200, unit: 'millisecond' } });

// global scope, isolation scope, current scope attribute, log attribute
Sentry.logger.info('log_with_scope', { log_attr: 'log_attr_4' });
});

Sentry.withScope(scope2 => {
scope2.setAttribute('scope_2_attr', { value: 300, unit: 'millisecond' });

// global scope, isolation scope, current scope attribute, log attribute
Sentry.logger.info('log_with_scope_2', { log_attr: 'log_attr_5' });
});
});

Sentry.flush();
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { expect } from '@playwright/test';
import type { LogEnvelope } from '@sentry/core';
import { sentryTest } from '../../../../utils/fixtures';
import { getFirstSentryEnvelopeRequest, properFullEnvelopeRequestParser } from '../../../../utils/helpers';

sentryTest('captures logs with scope attributes', async ({ getLocalTestUrl, page }) => {
const bundle = process.env.PW_BUNDLE || '';
// Only run this for npm package exports
if (bundle.startsWith('bundle') || bundle.startsWith('loader')) {
sentryTest.skip();
}

const url = await getLocalTestUrl({ testDir: __dirname });

const event = await getFirstSentryEnvelopeRequest<LogEnvelope>(page, url, properFullEnvelopeRequestParser);
const envelopeItems = event[1];

expect(envelopeItems[0]).toEqual([
{
type: 'log',
item_count: 5,
content_type: 'application/vnd.sentry.items.log+json',
},
{
items: [
{
timestamp: expect.any(Number),
level: 'info',
body: 'log_before_any_scope',
severity_number: 9,
trace_id: expect.any(String),
attributes: {
'sentry.sdk.name': { value: 'sentry.javascript.browser', type: 'string' },
'sentry.sdk.version': { value: expect.any(String), type: 'string' },
log_attr: { value: 'log_attr_1', type: 'string' },
},
},
{
timestamp: expect.any(Number),
level: 'info',
body: 'log_after_global_scope',
severity_number: 9,
trace_id: expect.any(String),
attributes: {
'sentry.sdk.name': { value: 'sentry.javascript.browser', type: 'string' },
'sentry.sdk.version': { value: expect.any(String), type: 'string' },
global_scope_attr: { value: true, type: 'boolean' },
log_attr: { value: 'log_attr_2', type: 'string' },
},
},
{
timestamp: expect.any(Number),
level: 'info',
body: 'log_with_isolation_scope',
severity_number: 9,
trace_id: expect.any(String),
attributes: {
'sentry.sdk.name': { value: 'sentry.javascript.browser', type: 'string' },
'sentry.sdk.version': { value: expect.any(String), type: 'string' },
global_scope_attr: { value: true, type: 'boolean' },
isolation_scope_1_attr: { value: 100, unit: 'millisecond', type: 'integer' },
log_attr: { value: 'log_attr_3', type: 'string' },
},
},
{
timestamp: expect.any(Number),
level: 'info',
body: 'log_with_scope',
severity_number: 9,
trace_id: expect.any(String),
attributes: {
'sentry.sdk.name': { value: 'sentry.javascript.browser', type: 'string' },
'sentry.sdk.version': { value: expect.any(String), type: 'string' },
global_scope_attr: { value: true, type: 'boolean' },
isolation_scope_1_attr: { value: 100, unit: 'millisecond', type: 'integer' },
scope_attr: { value: 200, unit: 'millisecond', type: 'integer' },
log_attr: { value: 'log_attr_4', type: 'string' },
},
},
{
timestamp: expect.any(Number),
level: 'info',
body: 'log_with_scope_2',
severity_number: 9,
trace_id: expect.any(String),
attributes: {
'sentry.sdk.name': { value: 'sentry.javascript.browser', type: 'string' },
'sentry.sdk.version': { value: expect.any(String), type: 'string' },
global_scope_attr: { value: true, type: 'boolean' },
isolation_scope_1_attr: { value: 100, unit: 'millisecond', type: 'integer' },
scope_2_attr: { value: 300, unit: 'millisecond', type: 'integer' },
log_attr: { value: 'log_attr_5', type: 'string' },
},
},
],
},
]);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import * as Sentry from '@sentry/node';
import { loggingTransport } from '@sentry-internal/node-integration-tests';

Sentry.init({
dsn: 'https://public@dsn.ingest.sentry.io/1337',
release: '1.0.0',
environment: 'test',
enableLogs: true,
transport: loggingTransport,
});

async function run(): Promise<void> {
// only log attribute
Sentry.logger.info('log_before_any_scope', { log_attr: 'log_attr_1' });

Sentry.getGlobalScope().setAttribute('global_scope_attr', true);

// global scope, log attribute
Sentry.logger.info('log_after_global_scope', { log_attr: 'log_attr_2' });

Sentry.withIsolationScope(isolationScope => {
isolationScope.setAttribute('isolation_scope_1_attr', { value: 100, unit: 'millisecond' });

// global scope, isolation scope, log attribute
Sentry.logger.info('log_with_isolation_scope', { log_attr: 'log_attr_3' });

Sentry.withScope(scope => {
scope.setAttribute('scope_attr', { value: 200, unit: 'millisecond' });

// global scope, isolation scope, current scope attribute, log attribute
Sentry.logger.info('log_with_scope', { log_attr: 'log_attr_4' });
});

Sentry.withScope(scope2 => {
scope2.setAttribute('scope_2_attr', { value: 300, unit: 'millisecond' });

// global scope, isolation scope, current scope attribute, log attribute
Sentry.logger.info('log_with_scope_2', { log_attr: 'log_attr_5' });
});
});

await Sentry.flush();
}

// eslint-disable-next-line @typescript-eslint/no-floating-promises
run();
109 changes: 109 additions & 0 deletions dev-packages/node-integration-tests/suites/public-api/logger/test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import type { SerializedLog } from '@sentry/core';
import { afterAll, describe, expect, test } from 'vitest';
import { cleanupChildProcesses, createRunner } from '../../../utils/runner';

const commonAttributes: SerializedLog['attributes'] = {
'sentry.environment': {
type: 'string',
value: 'test',
},
'sentry.release': {
type: 'string',
value: '1.0.0',
},
'sentry.sdk.name': {
type: 'string',
value: 'sentry.javascript.node',
},
'sentry.sdk.version': {
type: 'string',
value: expect.any(String),
},
'server.address': {
type: 'string',
value: expect.any(String),
},
};

describe('metrics', () => {
afterAll(() => {
cleanupChildProcesses();
});

test('should capture all metric types', async () => {

Check failure on line 33 in dev-packages/node-integration-tests/suites/public-api/logger/test.ts

View workflow job for this annotation

GitHub Actions / Node (24) (TS 3.8) Integration Tests

suites/public-api/logger/test.ts > metrics > should capture all metric types

Error: Test timed out in 15000ms. If this is a long-running test, pass a timeout value as the last argument or configure it globally with "testTimeout". ❯ suites/public-api/logger/test.ts:33:3
const runner = createRunner(__dirname, 'scenario.ts')
.expect({
log: {
items: [
{
timestamp: expect.any(Number),
level: 'info',
body: 'log_before_any_scope',
severity_number: 9,
trace_id: expect.any(String),
attributes: {
...commonAttributes,
log_attr: { value: 'log_attr_1', type: 'string' },
},
},
{
timestamp: expect.any(Number),
level: 'info',
body: 'log_after_global_scope',
severity_number: 9,
trace_id: expect.any(String),
attributes: {
...commonAttributes,
global_scope_attr: { value: true, type: 'boolean' },
log_attr: { value: 'log_attr_2', type: 'string' },
},
},
{
timestamp: expect.any(Number),
level: 'info',
body: 'log_with_isolation_scope',
severity_number: 9,
trace_id: expect.any(String),
attributes: {
...commonAttributes,
global_scope_attr: { value: true, type: 'boolean' },
isolation_scope_1_attr: { value: 100, unit: 'millisecond', type: 'integer' },
log_attr: { value: 'log_attr_3', type: 'string' },
},
},
{
timestamp: expect.any(Number),
level: 'info',
body: 'log_with_scope',
severity_number: 9,
trace_id: expect.any(String),
attributes: {
...commonAttributes,
global_scope_attr: { value: true, type: 'boolean' },
isolation_scope_1_attr: { value: 100, unit: 'millisecond', type: 'integer' },
scope_attr: { value: 200, unit: 'millisecond', type: 'integer' },
log_attr: { value: 'log_attr_4', type: 'string' },
},
},
{
timestamp: expect.any(Number),
level: 'info',
body: 'log_with_scope_2',
severity_number: 9,
trace_id: expect.any(String),
attributes: {
...commonAttributes,
global_scope_attr: { value: true, type: 'boolean' },
isolation_scope_1_attr: { value: 100, unit: 'millisecond', type: 'integer' },
scope_2_attr: { value: 300, unit: 'millisecond', type: 'integer' },
log_attr: { value: 'log_attr_5', type: 'string' },
},
},
],
},
})
.start();

await runner.completed();
});
});
2 changes: 1 addition & 1 deletion packages/core/src/attributes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export type RawAttributes<T> = T & ValidatedAttributes<T>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type RawAttribute<T> = T extends { value: any } | { unit: any } ? AttributeObject : T;

export type Attributes = Record<string, TypedAttributeValue>;
export type TypedAttributes = Record<string, TypedAttributeValue>;

export type AttributeValueType = string | number | boolean | Array<string> | Array<number> | Array<boolean>;

Expand Down
Loading
Loading