Skip to content

feat(node): Add shouldCreateSpanForRequest option #6055

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

Merged
Show file tree
Hide file tree
Changes from 1 commit
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
25 changes: 15 additions & 10 deletions packages/node/src/integrations/http.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getCurrentHub, Hub } from '@sentry/core';
import { EventProcessor, Integration, Span, TracePropagationTargets } from '@sentry/types';
import { EventProcessor, Integration, Span } from '@sentry/types';
import {
dynamicSamplingContextToSentryBaggageHeader,
fill,
Expand Down Expand Up @@ -69,11 +69,7 @@ export class Http implements Integration {

const clientOptions = setupOnceGetCurrentHub().getClient()?.getOptions() as NodeClientOptions | undefined;

const wrappedHandlerMaker = _createWrappedRequestMethodFactory(
this._breadcrumbs,
this._tracing,
clientOptions?.tracePropagationTargets,
);
const wrappedHandlerMaker = _createWrappedRequestMethodFactory(this._breadcrumbs, this._tracing, clientOptions);

// eslint-disable-next-line @typescript-eslint/no-var-requires
const httpModule = require('http');
Expand Down Expand Up @@ -109,20 +105,29 @@ type WrappedRequestMethodFactory = (original: OriginalRequestMethod) => WrappedR
function _createWrappedRequestMethodFactory(
breadcrumbsEnabled: boolean,
tracingEnabled: boolean,
tracePropagationTargets: TracePropagationTargets | undefined,
options: NodeClientOptions | undefined,
): WrappedRequestMethodFactory {
// We're caching results so we dont have to recompute regexp everytime we create a request.
const urlMap: Record<string, boolean> = {};

const shouldCreateSpan = (url: string): boolean => {
if (options?.shouldCreateSpanForRequest === undefined) {
return true;
}

return options.shouldCreateSpanForRequest(url);
};
Copy link
Member

Choose a reason for hiding this comment

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

I think we should cache the results of shouldCreateSpanForRequest. On the browser side, I can't decide if it's worth it, but in node where bundle size isn't a concern but being able to most efficiently handle lots of incoming requests quickly is, I think we definitely should (the same way we're doing with tracePropagationTargets just below).

Copy link
Collaborator Author

@timfish timfish Oct 28, 2022

Choose a reason for hiding this comment

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

Since lru_map is already a dependency for the ContextLines integration, should I use that rather than an alternative that could potentially grow indefinitely?

If we cache the result of shouldCreateSpanForRequest we should probably mention this in the jsdocs/docs since it's not obvious and users may think they can use shouldCreateSpanForRequest to dynamically stop span generation.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I just used a map for now!

Copy link
Member

Choose a reason for hiding this comment

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

Sorry, missed your question. You raise two good points. I think for now a map is simple and hasn't bitten us on the header front, so is unlikely to bite us here, either. If it does, I'm sure someone will let us know! And good point about the docs.


const shouldAttachTraceData = (url: string): boolean => {
if (tracePropagationTargets === undefined) {
if (options?.tracePropagationTargets === undefined) {
return true;
}

if (urlMap[url]) {
return urlMap[url];
}

urlMap[url] = tracePropagationTargets.some(tracePropagationTarget =>
urlMap[url] = options.tracePropagationTargets.some(tracePropagationTarget =>
isMatchingPattern(url, tracePropagationTarget),
);

Expand All @@ -148,7 +153,7 @@ function _createWrappedRequestMethodFactory(

const scope = getCurrentHub().getScope();

if (scope && tracingEnabled) {
if (scope && tracingEnabled && shouldCreateSpan(requestUrl)) {
parentSpan = scope.getSpan();

if (parentSpan) {
Expand Down
6 changes: 6 additions & 0 deletions packages/node/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ export interface BaseNodeOptions {
*/
tracePropagationTargets?: TracePropagationTargets;

/**
* This function will be called before creating a span for a request with the given url.
* Return false if you don't want a span for the given url.
*/
shouldCreateSpanForRequest?(url: string): boolean;

/** Callback that is executed when a fatal global error occurs. */
onFatalError?(error: Error): void;
}
Expand Down