Skip to content

Commit 8bcd136

Browse files
authored
ref(vercel-edge): Replace WinterCGFetch with winterCGFetchIntegration (#10436)
This has not been converted yet.
1 parent 5fd5c5d commit 8bcd136

File tree

5 files changed

+159
-108
lines changed

5 files changed

+159
-108
lines changed

packages/nextjs/src/index.types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export declare function init(
2323
// eslint-disable-next-line deprecation/deprecation
2424
export declare const Integrations: typeof clientSdk.Integrations &
2525
typeof serverSdk.Integrations &
26+
// eslint-disable-next-line deprecation/deprecation
2627
typeof edgeSdk.Integrations;
2728

2829
export declare const linkedErrorsIntegration: typeof clientSdk.linkedErrorsIntegration;

packages/vercel-edge/src/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,12 +99,12 @@ export {
9999
import { Integrations as CoreIntegrations, RequestData } from '@sentry/core';
100100

101101
import { WinterCGFetch } from './integrations/wintercg-fetch';
102+
export { winterCGFetchIntegration } from './integrations/wintercg-fetch';
102103

103-
const INTEGRATIONS = {
104+
/** @deprecated Import the integration function directly, e.g. `inboundFiltersIntegration()` instead of `new Integrations.InboundFilter(). */
105+
export const Integrations = {
104106
// eslint-disable-next-line deprecation/deprecation
105107
...CoreIntegrations,
106108
WinterCGFetch,
107109
RequestData,
108110
};
109-
110-
export { INTEGRATIONS as Integrations };

packages/vercel-edge/src/integrations/wintercg-fetch.ts

Lines changed: 91 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,52 @@
11
import { instrumentFetchRequest } from '@sentry-internal/tracing';
2-
import { addBreadcrumb, getClient, isSentryRequestUrl } from '@sentry/core';
3-
import type { FetchBreadcrumbData, FetchBreadcrumbHint, HandlerDataFetch, Integration, Span } from '@sentry/types';
2+
import {
3+
addBreadcrumb,
4+
convertIntegrationFnToClass,
5+
defineIntegration,
6+
getClient,
7+
isSentryRequestUrl,
8+
} from '@sentry/core';
9+
import type {
10+
Client,
11+
FetchBreadcrumbData,
12+
FetchBreadcrumbHint,
13+
HandlerDataFetch,
14+
Integration,
15+
IntegrationClass,
16+
IntegrationFn,
17+
Span,
18+
} from '@sentry/types';
419
import { LRUMap, addFetchInstrumentationHandler, stringMatchesSomePattern } from '@sentry/utils';
520

21+
const INTEGRATION_NAME = 'WinterCGFetch';
22+
23+
const HAS_CLIENT_MAP = new WeakMap<Client, boolean>();
24+
625
export interface Options {
726
/**
827
* Whether breadcrumbs should be recorded for requests
928
* Defaults to true
1029
*/
1130
breadcrumbs: boolean;
31+
1232
/**
1333
* Function determining whether or not to create spans to track outgoing requests to the given URL.
1434
* By default, spans will be created for all outgoing requests.
1535
*/
1636
shouldCreateSpanForRequest?: (url: string) => boolean;
1737
}
1838

19-
/**
20-
* Creates spans and attaches tracing headers to fetch requests on WinterCG runtimes.
21-
*/
22-
export class WinterCGFetch implements Integration {
23-
/**
24-
* @inheritDoc
25-
*/
26-
public static id: string = 'WinterCGFetch';
27-
28-
/**
29-
* @inheritDoc
30-
*/
31-
public name: string = WinterCGFetch.id;
32-
33-
private readonly _options: Options;
39+
const _winterCGFetch = ((options: Partial<Options> = {}) => {
40+
const breadcrumbs = options.breadcrumbs === undefined ? true : options.breadcrumbs;
41+
const shouldCreateSpanForRequest = options.shouldCreateSpanForRequest;
3442

35-
private readonly _createSpanUrlMap: LRUMap<string, boolean> = new LRUMap(100);
36-
private readonly _headersUrlMap: LRUMap<string, boolean> = new LRUMap(100);
43+
const _createSpanUrlMap = new LRUMap<string, boolean>(100);
44+
const _headersUrlMap = new LRUMap<string, boolean>(100);
3745

38-
public constructor(_options: Partial<Options> = {}) {
39-
this._options = {
40-
breadcrumbs: _options.breadcrumbs === undefined ? true : _options.breadcrumbs,
41-
shouldCreateSpanForRequest: _options.shouldCreateSpanForRequest,
42-
};
43-
}
44-
45-
/**
46-
* @inheritDoc
47-
*/
48-
public setupOnce(): void {
49-
const spans: Record<string, Span> = {};
50-
51-
addFetchInstrumentationHandler(handlerData => {
52-
if (!getClient()?.getIntegrationByName?.('WinterCGFetch')) {
53-
return;
54-
}
55-
56-
if (isSentryRequestUrl(handlerData.fetchData.url, getClient())) {
57-
return;
58-
}
59-
60-
instrumentFetchRequest(
61-
handlerData,
62-
this._shouldCreateSpan.bind(this),
63-
this._shouldAttachTraceData.bind(this),
64-
spans,
65-
'auto.http.wintercg_fetch',
66-
);
67-
68-
if (this._options.breadcrumbs) {
69-
createBreadcrumb(handlerData);
70-
}
71-
});
72-
}
46+
const spans: Record<string, Span> = {};
7347

7448
/** Decides whether to attach trace data to the outgoing fetch request */
75-
private _shouldAttachTraceData(url: string): boolean {
49+
function _shouldAttachTraceData(url: string): boolean {
7650
const client = getClient();
7751

7852
if (!client) {
@@ -85,32 +59,86 @@ export class WinterCGFetch implements Integration {
8559
return true;
8660
}
8761

88-
const cachedDecision = this._headersUrlMap.get(url);
62+
const cachedDecision = _headersUrlMap.get(url);
8963
if (cachedDecision !== undefined) {
9064
return cachedDecision;
9165
}
9266

9367
const decision = stringMatchesSomePattern(url, clientOptions.tracePropagationTargets);
94-
this._headersUrlMap.set(url, decision);
68+
_headersUrlMap.set(url, decision);
9569
return decision;
9670
}
9771

9872
/** Helper that wraps shouldCreateSpanForRequest option */
99-
private _shouldCreateSpan(url: string): boolean {
100-
if (this._options.shouldCreateSpanForRequest === undefined) {
73+
function _shouldCreateSpan(url: string): boolean {
74+
if (shouldCreateSpanForRequest === undefined) {
10175
return true;
10276
}
10377

104-
const cachedDecision = this._createSpanUrlMap.get(url);
78+
const cachedDecision = _createSpanUrlMap.get(url);
10579
if (cachedDecision !== undefined) {
10680
return cachedDecision;
10781
}
10882

109-
const decision = this._options.shouldCreateSpanForRequest(url);
110-
this._createSpanUrlMap.set(url, decision);
83+
const decision = shouldCreateSpanForRequest(url);
84+
_createSpanUrlMap.set(url, decision);
11185
return decision;
11286
}
113-
}
87+
88+
return {
89+
name: INTEGRATION_NAME,
90+
// TODO v8: Remove this again
91+
// eslint-disable-next-line @typescript-eslint/no-empty-function
92+
setupOnce() {
93+
addFetchInstrumentationHandler(handlerData => {
94+
const client = getClient();
95+
if (!client || !HAS_CLIENT_MAP.get(client)) {
96+
return;
97+
}
98+
99+
if (isSentryRequestUrl(handlerData.fetchData.url, client)) {
100+
return;
101+
}
102+
103+
instrumentFetchRequest(
104+
handlerData,
105+
_shouldCreateSpan,
106+
_shouldAttachTraceData,
107+
spans,
108+
'auto.http.wintercg_fetch',
109+
);
110+
111+
if (breadcrumbs) {
112+
createBreadcrumb(handlerData);
113+
}
114+
});
115+
},
116+
setup(client) {
117+
HAS_CLIENT_MAP.set(client, true);
118+
},
119+
};
120+
}) satisfies IntegrationFn;
121+
122+
export const winterCGFetchIntegration = defineIntegration(_winterCGFetch);
123+
124+
/**
125+
* Creates spans and attaches tracing headers to fetch requests on WinterCG runtimes.
126+
*
127+
* @deprecated Use `winterCGFetchIntegration()` instead.
128+
*/
129+
// eslint-disable-next-line deprecation/deprecation
130+
export const WinterCGFetch = convertIntegrationFnToClass(
131+
INTEGRATION_NAME,
132+
winterCGFetchIntegration,
133+
) as IntegrationClass<Integration & { setupOnce: () => void }> & {
134+
new (options?: {
135+
breadcrumbs: boolean;
136+
shouldCreateSpanForRequest?: (url: string) => boolean;
137+
}): Integration;
138+
};
139+
140+
// eslint-disable-next-line deprecation/deprecation
141+
export type WinterCGFetch = typeof WinterCGFetch;
114142

115143
function createBreadcrumb(handlerData: HandlerDataFetch): void {
116144
const { startTimestamp, endTimestamp } = handlerData;

packages/vercel-edge/src/sdk.ts

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
import {
2-
FunctionToString,
3-
InboundFilters,
4-
LinkedErrors,
5-
RequestData,
2+
functionToStringIntegration,
63
getIntegrationsToSetup,
4+
inboundFiltersIntegration,
75
initAndBind,
6+
linkedErrorsIntegration,
7+
requestDataIntegration,
88
} from '@sentry/core';
99
import type { Integration, Options } from '@sentry/types';
1010
import { GLOBAL_OBJ, createStackParser, nodeStackLineParser, stackParserFromStackParserOptions } from '@sentry/utils';
1111

1212
import { setAsyncLocalStorageAsyncContextStrategy } from './async';
1313
import { VercelEdgeClient } from './client';
14-
import { WinterCGFetch } from './integrations/wintercg-fetch';
14+
import { winterCGFetchIntegration } from './integrations/wintercg-fetch';
1515
import { makeEdgeTransport } from './transports';
1616
import type { VercelEdgeClientOptions, VercelEdgeOptions } from './types';
1717
import { getVercelEnv } from './utils/vercel';
@@ -24,21 +24,18 @@ const nodeStackParser = createStackParser(nodeStackLineParser());
2424

2525
/** @deprecated Use `getDefaultIntegrations(options)` instead. */
2626
export const defaultIntegrations = [
27-
/* eslint-disable deprecation/deprecation */
28-
new InboundFilters(),
29-
new FunctionToString(),
30-
new LinkedErrors(),
31-
/* eslint-enable deprecation/deprecation */
32-
new WinterCGFetch(),
27+
inboundFiltersIntegration(),
28+
functionToStringIntegration(),
29+
linkedErrorsIntegration(),
30+
winterCGFetchIntegration(),
3331
];
3432

3533
/** Get the default integrations for the browser SDK. */
3634
export function getDefaultIntegrations(options: Options): Integration[] {
3735
return [
3836
// eslint-disable-next-line deprecation/deprecation
3937
...defaultIntegrations,
40-
// eslint-disable-next-line deprecation/deprecation
41-
...(options.sendDefaultPii ? [new RequestData()] : []),
38+
...(options.sendDefaultPii ? [requestDataIntegration()] : []),
4239
];
4340
}
4441

0 commit comments

Comments
 (0)