-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
feat(core)!: Pass root spans to beforeSendSpan and disallow returning null
#14831
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
Changes from 7 commits
7c3a0bb
eaa6d88
af0c0c5
37534eb
c1a5ea8
bbd3e8c
e5facf3
d625cde
3de5d06
2295f64
de85def
373734d
feae885
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -54,6 +54,7 @@ import { getPossibleEventMessages } from './utils/eventUtils'; | |
| import { parseSampleRate } from './utils/parseSampleRate'; | ||
| import { prepareEvent } from './utils/prepareEvent'; | ||
| import { showSpanDropWarning } from './utils/spanUtils'; | ||
| import { convertSpanJsonToTransactionEvent, convertTransactionEventToSpanJson } from './utils/transactionEvent'; | ||
|
|
||
| const ALREADY_SEEN_ERROR = "Not capturing exception because it's already been captured."; | ||
| const MISSING_RELEASE_FOR_SESSION_ERROR = 'Discarded session because of missing or non-string release'; | ||
|
|
@@ -972,41 +973,57 @@ function processBeforeSend( | |
| hint: EventHint, | ||
| ): PromiseLike<Event | null> | Event | null { | ||
| const { beforeSend, beforeSendTransaction, beforeSendSpan } = options; | ||
| let processedEvent = event; | ||
|
|
||
| if (isErrorEvent(event) && beforeSend) { | ||
| return beforeSend(event, hint); | ||
| if (isErrorEvent(processedEvent) && beforeSend) { | ||
| return beforeSend(processedEvent, hint); | ||
| } | ||
|
|
||
| if (isTransactionEvent(event)) { | ||
| if (event.spans && beforeSendSpan) { | ||
| const processedSpans: SpanJSON[] = []; | ||
| for (const span of event.spans) { | ||
| const processedSpan = beforeSendSpan(span); | ||
| if (processedSpan) { | ||
| processedSpans.push(processedSpan); | ||
| } else { | ||
| showSpanDropWarning(); | ||
| client.recordDroppedEvent('before_send', 'span'); | ||
| if (isTransactionEvent(processedEvent)) { | ||
| if (beforeSendSpan) { | ||
| // process root span | ||
| const processedRootSpanJson = beforeSendSpan(convertTransactionEventToSpanJson(processedEvent)); | ||
| if (!processedRootSpanJson) { | ||
| showSpanDropWarning(); | ||
| } else { | ||
| // update event with processed root span values | ||
| processedEvent = { | ||
| ...event, | ||
| ...convertSpanJsonToTransactionEvent(processedRootSpanJson), | ||
| }; | ||
| } | ||
|
|
||
| // process child spans | ||
| if (processedEvent.spans) { | ||
| const processedSpans: SpanJSON[] = []; | ||
| for (const span of processedEvent.spans) { | ||
| const processedSpan = beforeSendSpan(span); | ||
| if (!processedSpan) { | ||
| showSpanDropWarning(); | ||
| processedSpans.push(span); | ||
| } else { | ||
| processedSpans.push(processedSpan); | ||
| } | ||
| } | ||
| processedEvent.spans = processedSpans; | ||
| } | ||
| event.spans = processedSpans; | ||
| } | ||
|
|
||
| if (beforeSendTransaction) { | ||
| if (event.spans) { | ||
| if (processedEvent.spans) { | ||
| // We store the # of spans before processing in SDK metadata, | ||
| // so we can compare it afterwards to determine how many spans were dropped | ||
| const spanCountBefore = event.spans.length; | ||
| event.sdkProcessingMetadata = { | ||
| const spanCountBefore = processedEvent.spans.length; | ||
| processedEvent.sdkProcessingMetadata = { | ||
| ...event.sdkProcessingMetadata, | ||
| spanCountBeforeProcessing: spanCountBefore, | ||
| }; | ||
| } | ||
| return beforeSendTransaction(event, hint); | ||
| return beforeSendTransaction(processedEvent as TransactionEvent, hint); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. l (not blocking): Is there a way we can get rid of this type cast? No worries if not, just curious since there's the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah somehow no matter what I do, after the processedEvent = merge<TransactionEvent>(
processedEvent,
convertSpanJsonToTransactionEvent(processedRootSpanJson),
); |
||
| } | ||
| } | ||
|
|
||
| return event; | ||
| return processedEvent; | ||
| } | ||
|
|
||
| function isErrorEvent(event: Event): event is ErrorEvent { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| import { SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME, SEMANTIC_ATTRIBUTE_PROFILE_ID } from '../semanticAttributes'; | ||
| import type { SpanJSON, TransactionEvent } from '../types-hoist'; | ||
| import { dropUndefinedKeys } from '../utils-hoist'; | ||
|
|
||
| /** | ||
| * Converts a transaction event to a span JSON object. | ||
| */ | ||
| export function convertTransactionEventToSpanJson(event: TransactionEvent): SpanJSON { | ||
| const { trace_id, parent_span_id, span_id, status, origin, data, op } = event.contexts?.trace ?? {}; | ||
|
|
||
| return dropUndefinedKeys({ | ||
| data: data ?? {}, | ||
| description: event.transaction, | ||
| op, | ||
| parent_span_id, | ||
| span_id: span_id ?? '', | ||
| start_timestamp: event.start_timestamp ?? 0, | ||
| status, | ||
| timestamp: event.timestamp, | ||
| trace_id: trace_id ?? '', | ||
| origin, | ||
| profile_id: data?.[SEMANTIC_ATTRIBUTE_PROFILE_ID] as string | undefined, | ||
| exclusive_time: data?.[SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME] as number | undefined, | ||
| measurements: event.measurements, | ||
| }); | ||
| } | ||
|
|
||
| /** | ||
| * Converts a span JSON object to a transaction event. | ||
| */ | ||
| export function convertSpanJsonToTransactionEvent(span: SpanJSON): TransactionEvent { | ||
| const event: TransactionEvent = { | ||
| type: 'transaction', | ||
| timestamp: span.timestamp, | ||
| start_timestamp: span.start_timestamp, | ||
| transaction: span.description, | ||
| contexts: { | ||
| trace: { | ||
| trace_id: span.trace_id, | ||
| span_id: span.span_id, | ||
| parent_span_id: span.parent_span_id, | ||
| op: span.op, | ||
| status: span.status, | ||
| origin: span.origin, | ||
| data: { | ||
| ...span.data, | ||
| ...(span.profile_id && { [SEMANTIC_ATTRIBUTE_PROFILE_ID]: span.profile_id }), | ||
| ...(span.exclusive_time && { [SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME]: span.exclusive_time }), | ||
| }, | ||
| }, | ||
| }, | ||
| }; | ||
|
|
||
| if (span.measurements) { | ||
| event.measurements = span.measurements; | ||
| } | ||
|
|
||
chargome marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return dropUndefinedKeys(event); | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.