-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
feat(core): Apply scope attributes to logs #18184
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Lms24
wants to merge
19
commits into
develop
Choose a base branch
from
lms/feat-core-logs-apply-scope-attributes
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+714
−429
Open
Changes from 18 commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
848a44d
feat(core): Apply scope attributes to logs
Lms24 3741fa2
wip
Lms24 4fef1b6
adjust after scope attribute changes
Lms24 54e0b9a
add browser integration test
Lms24 c71e1c1
adjust browser integration test
Lms24 d81eb3b
add node integration test
Lms24 5388d82
remove accidental code
Lms24 ee851a4
test optimizations
Lms24 0ccf278
only serilialize primitive scope attributes
Lms24 ab276bd
fallback logic only in log attributes
Lms24 e21944b
unify `attributeValueToTypedAttributeValue` with optional fallback logic
Lms24 cea78ba
adjust tests
Lms24 e540350
more tests
Lms24 8bf89f7
100% coverage <3
Lms24 9a02e95
fix tests, adjust jsdoc
Lms24 cd8f346
further jsdoc adjustments
Lms24 9813fa2
lint
Lms24 18e52c6
use Object.fromEntries instead of reduce
Lms24 9aba62a
of course, lint complains
Lms24 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
11 changes: 6 additions & 5 deletions
11
dev-packages/browser-integration-tests/suites/public-api/logger/integration/test.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
33 changes: 33 additions & 0 deletions
33
dev-packages/browser-integration-tests/suites/public-api/logger/scopeAttributes/subject.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| // only log attribute | ||
| Sentry.logger.info('log_before_any_scope', { log_attr: 'log_attr_1' }); | ||
|
|
||
| Sentry.getGlobalScope().setAttributes({ global_scope_attr: true }); | ||
|
|
||
| // this attribute will not be sent for now | ||
| Sentry.getGlobalScope().setAttribute('array_attr', [1, 2, 3]); | ||
|
|
||
| // 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(); |
98 changes: 98 additions & 0 deletions
98
dev-packages/browser-integration-tests/suites/public-api/logger/scopeAttributes/test.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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, | ||
| testingCdnBundle, | ||
| } from '../../../../utils/helpers'; | ||
|
|
||
| sentryTest('captures logs with scope attributes', async ({ getLocalTestUrl, page }) => { | ||
| sentryTest.skip(testingCdnBundle()); | ||
|
|
||
| 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' }, | ||
| }, | ||
| }, | ||
| ], | ||
| }, | ||
| ]); | ||
| }); |
11 changes: 6 additions & 5 deletions
11
dev-packages/browser-integration-tests/suites/public-api/logger/simple/test.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
49 changes: 49 additions & 0 deletions
49
dev-packages/node-integration-tests/suites/public-api/logger/scenario.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| import * as Sentry from '@sentry/node'; | ||
| import { loggingTransport } from '@sentry-internal/node-integration-tests'; | ||
|
|
||
| Sentry.init({ | ||
| dsn: 'https://[email protected]/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); | ||
|
|
||
| // this attribute will not be sent for now | ||
| Sentry.getGlobalScope().setAttributes({ array_attr: [1, 2, 3] }); | ||
|
|
||
| // 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
109
dev-packages/node-integration-tests/suites/public-api/logger/test.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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('logs', () => { | ||
| afterAll(() => { | ||
| cleanupChildProcesses(); | ||
| }); | ||
|
|
||
| test('captures logs with scope and log attributes', async () => { | ||
| 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(); | ||
| }); | ||
| }); | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Node integration test uses partial matching for attributes (Bugbot Rules)
Flagging per review rules: The test uses
toMatchObject(viaassertSentryLogContainer) which is a relaxed assertion. The test scenario setsarray_attr: [1, 2, 3]on the global scope, which should NOT appear in logs (since non-primitive scope attributes are discarded). However, the test only verifies that expected attributes are present, not thatarray_attris absent. If a regression caused non-primitive scope attributes to leak into logs, this test would not catch it. The browser integration test correctly usestoEqualfor exact matching.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fair point if true