-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
feat(core): Add ignoreSpans
option
#17078
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
base: develop
Are you sure you want to change the base?
Changes from all commits
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 | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -10,6 +10,11 @@ import type { StackLineParser, StackParser } from './stacktrace'; | |||||||||||||||||
import type { TracePropagationTargets } from './tracing'; | ||||||||||||||||||
import type { BaseTransportOptions, Transport } from './transport'; | ||||||||||||||||||
|
||||||||||||||||||
interface IgnoreSpanFilter { | ||||||||||||||||||
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. m: I think we can type this a bit smarter, right? Currently, this allows users to pass in an empty object but we could type it in a way so that at least one prop is required
Suggested change
we should probably still check that this is also enforced when we apply the option (which we do already) |
||||||||||||||||||
name?: string | RegExp; | ||||||||||||||||||
op?: string | RegExp; | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
export interface ClientOptions<TO extends BaseTransportOptions = BaseTransportOptions> { | ||||||||||||||||||
/** | ||||||||||||||||||
* Enable debug functionality in the SDK itself. If `debug` is set to `true` the SDK will attempt | ||||||||||||||||||
|
@@ -208,6 +213,13 @@ export interface ClientOptions<TO extends BaseTransportOptions = BaseTransportOp | |||||||||||||||||
*/ | ||||||||||||||||||
ignoreTransactions?: Array<string | RegExp>; | ||||||||||||||||||
|
||||||||||||||||||
/** | ||||||||||||||||||
* A list of span names or patterns to ignore. | ||||||||||||||||||
* | ||||||||||||||||||
* @default [] | ||||||||||||||||||
*/ | ||||||||||||||||||
ignoreSpans?: (string | RegExp | IgnoreSpanFilter)[]; | ||||||||||||||||||
|
||||||||||||||||||
/** | ||||||||||||||||||
* A URL to an envelope tunnel endpoint. An envelope tunnel is an HTTP endpoint | ||||||||||||||||||
* that accepts Sentry envelopes for forwarding. This can be used to force data | ||||||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,67 @@ | ||||||||||||||||||||||||||||||
import type { ClientOptions } from '../types-hoist/options'; | ||||||||||||||||||||||||||||||
import type { SpanJSON } from '../types-hoist/span'; | ||||||||||||||||||||||||||||||
import { isMatchingPattern, stringMatchesSomePattern } from './string'; | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||||||
* Check if a span should be ignored based on the ignoreSpans configuration. | ||||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||||
export function shouldIgnoreSpan( | ||||||||||||||||||||||||||||||
span: Pick<SpanJSON, 'description' | 'op'>, | ||||||||||||||||||||||||||||||
ignoreSpans: ClientOptions['ignoreSpans'], | ||||||||||||||||||||||||||||||
): boolean { | ||||||||||||||||||||||||||||||
if (!ignoreSpans?.length) { | ||||||||||||||||||||||||||||||
return false; | ||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
if (!span.description) { | ||||||||||||||||||||||||||||||
return false; | ||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||
Comment on lines
+16
to
+18
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: I can't think of an actual example right now but theoretically, shouldn't we still match on the op of a span without a description? |
||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
// First we check the simple string/regex patterns - if the name matches any of them, we ignore the span | ||||||||||||||||||||||||||||||
const simplePatterns = ignoreSpans.filter(isStringOrRegExp); | ||||||||||||||||||||||||||||||
if (simplePatterns.length && stringMatchesSomePattern(span.description, simplePatterns)) { | ||||||||||||||||||||||||||||||
return true; | ||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
// Then we check the more complex patterns, where both parts must match | ||||||||||||||||||||||||||||||
for (const pattern of ignoreSpans) { | ||||||||||||||||||||||||||||||
// Have already checked for simple patterns, so we can skip these | ||||||||||||||||||||||||||||||
if (isStringOrRegExp(pattern) || (!pattern.name && !pattern.op)) { | ||||||||||||||||||||||||||||||
continue; | ||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||
Comment on lines
+21
to
+31
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: I think performance-wise, it makes more sense to handle everything in one for loop here, no? If users didn't pass simple patterns or none of them matched, we'd iterate twice over the ignoreSpans array. Also avoids calling |
||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
const nameMatches = pattern.name ? isMatchingPattern(span.description, pattern.name) : true; | ||||||||||||||||||||||||||||||
const opMatches = pattern.op ? span.op && isMatchingPattern(span.op, pattern.op) : true; | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
if (nameMatches && opMatches) { | ||||||||||||||||||||||||||||||
return true; | ||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||
Comment on lines
+33
to
+38
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. this is pretty clever, took me a minute to understand :D
Suggested change
|
||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
return false; | ||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||||||
* Takes a list of spans, and a span that was dropped, and re-parents the child spans of the dropped span to the parent of the dropped span, if possible. | ||||||||||||||||||||||||||||||
* This mutates the spans array in place! | ||||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||||
export function reparentChildSpans(spans: SpanJSON[], dropSpan: SpanJSON): void { | ||||||||||||||||||||||||||||||
const droppedSpanParentId = dropSpan.parent_span_id; | ||||||||||||||||||||||||||||||
const droppedSpanId = dropSpan.span_id; | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
// This should generally not happen, as we do not apply this on root spans | ||||||||||||||||||||||||||||||
// but to be safe, we just bail in this case | ||||||||||||||||||||||||||||||
if (!droppedSpanParentId) { | ||||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
for (const span of spans) { | ||||||||||||||||||||||||||||||
if (span.parent_span_id === droppedSpanId) { | ||||||||||||||||||||||||||||||
span.parent_span_id = droppedSpanParentId; | ||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
function isStringOrRegExp(value: unknown): value is string | RegExp { | ||||||||||||||||||||||||||||||
return typeof value === 'string' || value instanceof RegExp; | ||||||||||||||||||||||||||||||
} |
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.
l: This should save a bit of performance overhead in case the passed array is empty