Skip to content

Commit d0aa570

Browse files
committed
Merge branch 'develop' into feat/add-devcontainer
* develop: ref: Add external contributor to CHANGELOG.md (getsentry#13500) test: Avoid race conditions with symlinks (getsentry#13498) fix(node): Suppress tracing for transport request execution rather than transport creation (getsentry#13491) ci: Ensure cache save happens after install step (getsentry#13497) test: Increase timeout for redis-cache test & docker-compose (getsentry#13499) Fix config example in README.md for Nuxt (getsentry#13496)
2 parents e989e5c + 6479e88 commit d0aa570

File tree

13 files changed

+122
-130
lines changed

13 files changed

+122
-130
lines changed

.github/actions/install-playwright/action.yml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,6 @@ runs:
2121
~/.cache/ms-playwright
2222
key: playwright-${{ runner.os }}-${{ steps.playwright-version.outputs.version }}
2323

24-
# Only store cache on develop branch
25-
- name: Store cached playwright binaries
26-
uses: actions/cache/save@v4
27-
if: github.event_name == 'push' && github.ref == 'refs/heads/develop'
28-
with:
29-
path: |
30-
~/.cache/ms-playwright
31-
key: playwright-${{ runner.os }}-${{ steps.playwright-version.outputs.version }}
32-
3324
# We always install all browsers, if uncached
3425
- name: Install Playwright dependencies (uncached)
3526
run: npx playwright install chromium webkit firefox --with-deps
@@ -40,3 +31,12 @@ runs:
4031
run: npx playwright install-deps ${{ inputs.browsers || 'chromium webkit firefox' }}
4132
if: steps.playwright-cache.outputs.cache-hit == 'true'
4233
shell: bash
34+
35+
# Only store cache on develop branch
36+
- name: Store cached playwright binaries
37+
uses: actions/cache/save@v4
38+
if: github.event_name == 'push' && github.ref == 'refs/heads/develop'
39+
with:
40+
path: |
41+
~/.cache/ms-playwright
42+
key: playwright-${{ runner.os }}-${{ steps.playwright-version.outputs.version }}

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
- "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott
1212

13+
Work in this release was contributed by @leopoldkristjansson. Thank you for your contribution!
14+
1315
## 8.27.0
1416

1517
### Important Changes

dev-packages/browser-integration-tests/utils/generatePlugin.ts

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { Package } from '@sentry/types';
44
import HtmlWebpackPlugin, { createHtmlTagObject } from 'html-webpack-plugin';
55
import type { Compiler } from 'webpack';
66

7-
import { addStaticAsset, addStaticAssetSymlink } from './staticAssets';
7+
import { addStaticAsset, symlinkAsset } from './staticAssets';
88

99
const LOADER_TEMPLATE = fs.readFileSync(path.join(__dirname, '../fixtures/loader.js'), 'utf-8');
1010
const PACKAGES_DIR = path.join(__dirname, '..', '..', '..', 'packages');
@@ -214,7 +214,10 @@ class SentryScenarioGenerationPlugin {
214214
src: 'cdn.bundle.js',
215215
});
216216

217-
addStaticAssetSymlink(this.localOutPath, path.resolve(PACKAGES_DIR, bundleName, bundlePath), 'cdn.bundle.js');
217+
symlinkAsset(
218+
path.resolve(PACKAGES_DIR, bundleName, bundlePath),
219+
path.join(this.localOutPath, 'cdn.bundle.js'),
220+
);
218221

219222
if (useLoader) {
220223
const loaderConfig = LOADER_CONFIGS[bundleKey];
@@ -245,14 +248,13 @@ class SentryScenarioGenerationPlugin {
245248
const fileName = `${integration}.bundle.js`;
246249

247250
// We add the files, but not a script tag - they are lazy-loaded
248-
addStaticAssetSymlink(
249-
this.localOutPath,
251+
symlinkAsset(
250252
path.resolve(
251253
PACKAGES_DIR,
252254
'feedback',
253255
BUNDLE_PATHS['feedback']?.[integrationBundleKey]?.replace('[INTEGRATION_NAME]', integration) || '',
254256
),
255-
fileName,
257+
path.join(this.localOutPath, fileName),
256258
);
257259
});
258260
}
@@ -262,26 +264,23 @@ class SentryScenarioGenerationPlugin {
262264
if (baseIntegrationFileName) {
263265
this.requiredIntegrations.forEach(integration => {
264266
const fileName = `${integration}.bundle.js`;
265-
addStaticAssetSymlink(
266-
this.localOutPath,
267+
symlinkAsset(
267268
path.resolve(
268269
PACKAGES_DIR,
269270
'browser',
270271
baseIntegrationFileName.replace('[INTEGRATION_NAME]', integration),
271272
),
272-
fileName,
273+
path.join(this.localOutPath, fileName),
273274
);
274275

275276
if (integration === 'feedback') {
276-
addStaticAssetSymlink(
277-
this.localOutPath,
277+
symlinkAsset(
278278
path.resolve(PACKAGES_DIR, 'feedback', 'build/bundles/feedback-modal.js'),
279-
'feedback-modal.bundle.js',
279+
path.join(this.localOutPath, 'feedback-modal.bundle.js'),
280280
);
281-
addStaticAssetSymlink(
282-
this.localOutPath,
281+
symlinkAsset(
283282
path.resolve(PACKAGES_DIR, 'feedback', 'build/bundles/feedback-screenshot.js'),
284-
'feedback-screenshot.bundle.js',
283+
path.join(this.localOutPath, 'feedback-screenshot.bundle.js'),
285284
);
286285
}
287286

@@ -295,10 +294,9 @@ class SentryScenarioGenerationPlugin {
295294

296295
const baseWasmFileName = BUNDLE_PATHS['wasm']?.[integrationBundleKey];
297296
if (this.requiresWASMIntegration && baseWasmFileName) {
298-
addStaticAssetSymlink(
299-
this.localOutPath,
297+
symlinkAsset(
300298
path.resolve(PACKAGES_DIR, 'wasm', baseWasmFileName),
301-
'wasm.bundle.js',
299+
path.join(this.localOutPath, 'wasm.bundle.js'),
302300
);
303301

304302
const wasmObject = createHtmlTagObject('script', {

dev-packages/browser-integration-tests/utils/staticAssets.ts

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,11 @@ export function addStaticAsset(localOutPath: string, fileName: string, cb: () =>
2222
symlinkAsset(newPath, path.join(localOutPath, fileName));
2323
}
2424

25-
export function addStaticAssetSymlink(localOutPath: string, originalPath: string, fileName: string): void {
26-
const newPath = path.join(STATIC_DIR, fileName);
27-
28-
// Only copy files once
29-
if (!fs.existsSync(newPath)) {
30-
fs.symlinkSync(originalPath, newPath);
31-
}
32-
33-
symlinkAsset(newPath, path.join(localOutPath, fileName));
34-
}
35-
36-
function symlinkAsset(originalPath: string, targetPath: string): void {
25+
export function symlinkAsset(originalPath: string, targetPath: string): void {
3726
try {
38-
fs.unlinkSync(targetPath);
27+
fs.linkSync(originalPath, targetPath);
3928
} catch {
40-
// ignore errors here
29+
// ignore errors here, probably means the file already exists
30+
// Since we always build into a new directory for each test, we can safely ignore this
4131
}
42-
43-
fs.linkSync(originalPath, targetPath);
4432
}

dev-packages/node-integration-tests/suites/tracing/redis-cache/test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { cleanupChildProcesses, createRunner } from '../../../utils/runner';
22

33
// When running docker compose, we need a larger timeout, as this takes some time...
4-
jest.setTimeout(75000);
4+
jest.setTimeout(90000);
55

66
describe('redis cache auto instrumentation', () => {
77
afterAll(() => {

dev-packages/node-integration-tests/utils/runner.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ async function runDockerCompose(options: DockerOptions): Promise<VoidFunction> {
124124
const timeout = setTimeout(() => {
125125
close();
126126
reject(new Error('Timed out waiting for docker-compose'));
127-
}, 60_000);
127+
}, 75_000);
128128

129129
function newData(data: Buffer): void {
130130
const text = data.toString('utf8');

packages/browser/src/transports/fetch.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export function makeFetchTransport(
4747
}
4848

4949
try {
50+
// TODO: This may need a `suppresTracing` call in the future when we switch the browser SDK to OTEL
5051
return nativeFetch(options.url, requestOptions).then(response => {
5152
pendingBodySize -= requestSize;
5253
pendingCount--;

packages/cloudflare/src/transport.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { createTransport } from '@sentry/core';
1+
import { createTransport, suppressTracing } from '@sentry/core';
22
import type { BaseTransportOptions, Transport, TransportMakeRequestResponse, TransportRequest } from '@sentry/types';
33
import { SentryError } from '@sentry/utils';
44

@@ -89,14 +89,16 @@ export function makeCloudflareTransport(options: CloudflareTransportOptions): Tr
8989
...options.fetchOptions,
9090
};
9191

92-
return fetch(options.url, requestOptions).then(response => {
93-
return {
94-
statusCode: response.status,
95-
headers: {
96-
'x-sentry-rate-limits': response.headers.get('X-Sentry-Rate-Limits'),
97-
'retry-after': response.headers.get('Retry-After'),
98-
},
99-
};
92+
return suppressTracing(() => {
93+
return fetch(options.url, requestOptions).then(response => {
94+
return {
95+
statusCode: response.status,
96+
headers: {
97+
'x-sentry-rate-limits': response.headers.get('X-Sentry-Rate-Limits'),
98+
'retry-after': response.headers.get('Retry-After'),
99+
},
100+
};
101+
});
100102
});
101103
}
102104

packages/deno/src/transports/index.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { createTransport } from '@sentry/core';
1+
import { createTransport, suppressTracing } from '@sentry/core';
22
import type { BaseTransportOptions, Transport, TransportMakeRequestResponse, TransportRequest } from '@sentry/types';
33
import { consoleSandbox, logger, rejectedSyncPromise } from '@sentry/utils';
44

@@ -37,14 +37,16 @@ export function makeFetchTransport(options: DenoTransportOptions): Transport {
3737
};
3838

3939
try {
40-
return fetch(options.url, requestOptions).then(response => {
41-
return {
42-
statusCode: response.status,
43-
headers: {
44-
'x-sentry-rate-limits': response.headers.get('X-Sentry-Rate-Limits'),
45-
'retry-after': response.headers.get('Retry-After'),
46-
},
47-
};
40+
return suppressTracing(() => {
41+
return fetch(options.url, requestOptions).then(response => {
42+
return {
43+
statusCode: response.status,
44+
headers: {
45+
'x-sentry-rate-limits': response.headers.get('X-Sentry-Rate-Limits'),
46+
'retry-after': response.headers.get('Retry-After'),
47+
},
48+
};
49+
});
4850
});
4951
} catch (e) {
5052
return rejectedSyncPromise(e);

packages/node/src/integrations/http.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
99
getCapturedScopesOnSpan,
1010
getCurrentScope,
1111
getIsolationScope,
12-
isSentryRequestUrl,
1312
setCapturedScopesOnSpan,
1413
} from '@sentry/core';
1514
import { getClient } from '@sentry/opentelemetry';
@@ -102,10 +101,6 @@ export const instrumentHttp = Object.assign(
102101
return false;
103102
}
104103

105-
if (isSentryRequestUrl(url, getClient())) {
106-
return true;
107-
}
108-
109104
const _ignoreOutgoingRequests = _httpOptions.ignoreOutgoingRequests;
110105
if (_ignoreOutgoingRequests && _ignoreOutgoingRequests(url, request)) {
111106
return true;

packages/node/src/transports/http.ts

Lines changed: 55 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,8 @@ export function makeNodeTransport(options: NodeTransportOptions): Transport {
7979
? (new HttpsProxyAgent(proxy) as http.Agent)
8080
: new nativeHttpModule.Agent({ keepAlive, maxSockets: 30, timeout: 2000 });
8181

82-
// This ensures we do not generate any spans in OpenTelemetry for the transport
83-
return suppressTracing(() => {
84-
const requestExecutor = createRequestExecutor(options, options.httpModule ?? nativeHttpModule, agent);
85-
return createTransport(options, requestExecutor);
86-
});
82+
const requestExecutor = createRequestExecutor(options, options.httpModule ?? nativeHttpModule, agent);
83+
return createTransport(options, requestExecutor);
8784
}
8885

8986
/**
@@ -122,54 +119,59 @@ function createRequestExecutor(
122119
const { hostname, pathname, port, protocol, search } = new URL(options.url);
123120
return function makeRequest(request: TransportRequest): Promise<TransportMakeRequestResponse> {
124121
return new Promise((resolve, reject) => {
125-
let body = streamFromBody(request.body);
126-
127-
const headers: Record<string, string> = { ...options.headers };
128-
129-
if (request.body.length > GZIP_THRESHOLD) {
130-
headers['content-encoding'] = 'gzip';
131-
body = body.pipe(createGzip());
132-
}
133-
134-
const req = httpModule.request(
135-
{
136-
method: 'POST',
137-
agent,
138-
headers,
139-
hostname,
140-
path: `${pathname}${search}`,
141-
port,
142-
protocol,
143-
ca: options.caCerts,
144-
},
145-
res => {
146-
res.on('data', () => {
147-
// Drain socket
148-
});
149-
150-
res.on('end', () => {
151-
// Drain socket
152-
});
153-
154-
res.setEncoding('utf8');
155-
156-
// "Key-value pairs of header names and values. Header names are lower-cased."
157-
// https://nodejs.org/api/http.html#http_message_headers
158-
const retryAfterHeader = res.headers['retry-after'] ?? null;
159-
const rateLimitsHeader = res.headers['x-sentry-rate-limits'] ?? null;
160-
161-
resolve({
162-
statusCode: res.statusCode,
163-
headers: {
164-
'retry-after': retryAfterHeader,
165-
'x-sentry-rate-limits': Array.isArray(rateLimitsHeader) ? rateLimitsHeader[0] || null : rateLimitsHeader,
166-
},
167-
});
168-
},
169-
);
170-
171-
req.on('error', reject);
172-
body.pipe(req);
122+
// This ensures we do not generate any spans in OpenTelemetry for the transport
123+
suppressTracing(() => {
124+
let body = streamFromBody(request.body);
125+
126+
const headers: Record<string, string> = { ...options.headers };
127+
128+
if (request.body.length > GZIP_THRESHOLD) {
129+
headers['content-encoding'] = 'gzip';
130+
body = body.pipe(createGzip());
131+
}
132+
133+
const req = httpModule.request(
134+
{
135+
method: 'POST',
136+
agent,
137+
headers,
138+
hostname,
139+
path: `${pathname}${search}`,
140+
port,
141+
protocol,
142+
ca: options.caCerts,
143+
},
144+
res => {
145+
res.on('data', () => {
146+
// Drain socket
147+
});
148+
149+
res.on('end', () => {
150+
// Drain socket
151+
});
152+
153+
res.setEncoding('utf8');
154+
155+
// "Key-value pairs of header names and values. Header names are lower-cased."
156+
// https://nodejs.org/api/http.html#http_message_headers
157+
const retryAfterHeader = res.headers['retry-after'] ?? null;
158+
const rateLimitsHeader = res.headers['x-sentry-rate-limits'] ?? null;
159+
160+
resolve({
161+
statusCode: res.statusCode,
162+
headers: {
163+
'retry-after': retryAfterHeader,
164+
'x-sentry-rate-limits': Array.isArray(rateLimitsHeader)
165+
? rateLimitsHeader[0] || null
166+
: rateLimitsHeader,
167+
},
168+
});
169+
},
170+
);
171+
172+
req.on('error', reject);
173+
body.pipe(req);
174+
});
173175
});
174176
};
175177
}

packages/nuxt/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ Add a `sentry.client.config.(js|ts)` file to the root of your project:
9696
import * as Sentry from '@sentry/nuxt';
9797

9898
Sentry.init({
99-
dsn: env.DSN,
99+
dsn: process.env.DSN,
100100
});
101101
```
102102

0 commit comments

Comments
 (0)