diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 4f06228f3a7e..70535bd06e89 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -1004,6 +1004,15 @@ jobs:
timeout-minutes: 5
run: pnpm test:assert
+ - name: Upload Playwright Traces
+ uses: actions/upload-artifact@v4
+ if: failure()
+ with:
+ name: playwright-traces-job_e2e_playwright_tests-${{ matrix.test-application}}
+ path: dev-packages/e2e-tests/test-applications/${{ matrix.test-application}}/test-results
+ overwrite: true
+ retention-days: 7
+
job_optional_e2e_tests:
name: E2E ${{ matrix.label || matrix.test-application }} Test
# We only run E2E tests for non-fork PRs because the E2E tests require secrets to work and they can't be accessed from forks
diff --git a/.size-limit.js b/.size-limit.js
index d2211d91d5b0..5da293511976 100644
--- a/.size-limit.js
+++ b/.size-limit.js
@@ -10,6 +10,31 @@ module.exports = [
gzip: true,
limit: '24 KB',
},
+ {
+ name: '@sentry/browser - with treeshaking flags',
+ path: 'packages/browser/build/npm/esm/index.js',
+ import: createImport('init'),
+ gzip: true,
+ limit: '24 KB',
+ modifyWebpackConfig: function (config) {
+ const webpack = require('webpack');
+ const TerserPlugin = require('terser-webpack-plugin');
+
+ config.plugins.push(
+ new webpack.DefinePlugin({
+ __SENTRY_DEBUG__: false,
+ __RRWEB_EXCLUDE_SHADOW_DOM__: true,
+ __RRWEB_EXCLUDE_IFRAME__: true,
+ __SENTRY_EXCLUDE_REPLAY_WORKER__: true,
+ }),
+ );
+
+ config.optimization.minimize = true;
+ config.optimization.minimizer = [new TerserPlugin()];
+
+ return config;
+ },
+ },
{
name: '@sentry/browser (incl. Tracing)',
path: 'packages/browser/build/npm/esm/index.js',
@@ -32,6 +57,8 @@ module.exports = [
limit: '68 KB',
modifyWebpackConfig: function (config) {
const webpack = require('webpack');
+ const TerserPlugin = require('terser-webpack-plugin');
+
config.plugins.push(
new webpack.DefinePlugin({
__SENTRY_DEBUG__: false,
@@ -40,6 +67,10 @@ module.exports = [
__SENTRY_EXCLUDE_REPLAY_WORKER__: true,
}),
);
+
+ config.optimization.minimize = true;
+ config.optimization.minimizer = [new TerserPlugin()];
+
return config;
},
},
@@ -222,11 +253,17 @@ module.exports = [
ignore: [...builtinModules, ...nodePrefixedBuiltinModules],
modifyWebpackConfig: function (config) {
const webpack = require('webpack');
+ const TerserPlugin = require('terser-webpack-plugin');
+
config.plugins.push(
new webpack.DefinePlugin({
__SENTRY_TRACING__: false,
}),
);
+
+ config.optimization.minimize = true;
+ config.optimization.minimizer = [new TerserPlugin()];
+
return config;
},
},
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 015c5370a75a..7b0f4361b92b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,57 @@
- "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott
+## 8.29.0
+
+### Important Changes
+
+- **Beta releases of official Solid and SolidStart Sentry SDKs**
+
+This release marks the beta releases of the `@sentry/solid` and `@sentry/solidstart` Sentry SDKs. For details on how to
+use them, check out the
+[Sentry Solid SDK README](https://github.com/getsentry/sentry-javascript/tree/develop/packages/solid) and the
+[Sentry SolidStart SDK README](https://github.com/getsentry/sentry-javascript/tree/develop/packages/solidstart)
+respectively. Please reach out on [GitHub](https://github.com/getsentry/sentry-javascript/issues/new/choose) if you have
+any feedback or concerns.
+
+- **feat(node): Option to only wrap instrumented modules (#13139)**
+
+Adds the SDK option to only wrap ES modules with `import-in-the-middle` that specifically need to be instrumented.
+
+```javascript
+import * as Sentry from '@sentry/node';
+
+Sentry.init({
+ dsn: '__PUBLIC_DSN__',
+ registerEsmLoaderHooks: { onlyHookedModules: true },
+});
+```
+
+- **feat(node): Update OpenTelemetry packages to instrumentation v0.53.0 (#13587)**
+
+All internal OpenTelemetry instrumentation was updated to their latest version. This adds support for Mongoose v7 and v8
+and fixes various bugs related to ESM mode.
+
+### Other Changes
+
+- feat(nextjs): Emit warning when using turbopack (#13566)
+- feat(nextjs): Future-proof Next.js config options overriding (#13586)
+- feat(node): Add `generic-pool` integration (#13465)
+- feat(nuxt): Upload sourcemaps generated by Nitro (#13382)
+- feat(solidstart): Add `browserTracingIntegration` by default (#13561)
+- feat(solidstart): Add `sentrySolidStartVite` plugin to simplify source maps upload (#13493)
+- feat(vue): Only start UI spans if parent is available (#13568)
+- fix(cloudflare): Guard `context.waitUntil` call in request handler (#13549)
+- fix(gatsby): Fix assets path for sourcemaps upload (#13592)
+- fix(nextjs): Use posix paths for sourcemap uploads (#13603)
+- fix(node-fetch): Use stringified origin url (#13581)
+- fix(node): Replace dashes in `generic-pool` span origins with underscores (#13579)
+- fix(replay): Fix types in WebVitalData (#13573)
+- fix(replay): Improve replay web vital types (#13602)
+- fix(utils): Keep logger on carrier (#13570)
+
+Work in this release was contributed by @Zen-cronic. Thank you for your contribution!
+
## 8.28.0
### Important Changes
diff --git a/dev-packages/browser-integration-tests/package.json b/dev-packages/browser-integration-tests/package.json
index 886f91d328fb..d012484a4e0b 100644
--- a/dev-packages/browser-integration-tests/package.json
+++ b/dev-packages/browser-integration-tests/package.json
@@ -48,7 +48,7 @@
"babel-loader": "^8.2.2",
"html-webpack-plugin": "^5.5.0",
"pako": "^2.1.0",
- "webpack": "^5.90.3"
+ "webpack": "^5.94.0"
},
"devDependencies": {
"@types/glob": "8.0.0",
diff --git a/dev-packages/browser-integration-tests/suites/feedback/attachTo/init.js b/dev-packages/browser-integration-tests/suites/feedback/attachTo/init.js
new file mode 100644
index 000000000000..5eb27143fdc7
--- /dev/null
+++ b/dev-packages/browser-integration-tests/suites/feedback/attachTo/init.js
@@ -0,0 +1,17 @@
+import * as Sentry from '@sentry/browser';
+// Import this separately so that generatePlugin can handle it for CDN scenarios
+import { feedbackIntegration } from '@sentry/browser';
+
+const feedback = feedbackIntegration({
+ autoInject: false,
+});
+
+window.Sentry = Sentry;
+window.feedback = feedback;
+
+Sentry.init({
+ dsn: 'https://public@dsn.ingest.sentry.io/1337',
+ integrations: [feedback],
+});
+
+feedback.attachTo('#custom-feedback-buttom');
diff --git a/dev-packages/browser-integration-tests/suites/feedback/attachTo/template.html b/dev-packages/browser-integration-tests/suites/feedback/attachTo/template.html
new file mode 100644
index 000000000000..ae36b0c69c7b
--- /dev/null
+++ b/dev-packages/browser-integration-tests/suites/feedback/attachTo/template.html
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/dev-packages/browser-integration-tests/suites/feedback/attachTo/test.ts b/dev-packages/browser-integration-tests/suites/feedback/attachTo/test.ts
new file mode 100644
index 000000000000..507b08685092
--- /dev/null
+++ b/dev-packages/browser-integration-tests/suites/feedback/attachTo/test.ts
@@ -0,0 +1,82 @@
+import { expect } from '@playwright/test';
+
+import { TEST_HOST, sentryTest } from '../../../utils/fixtures';
+import { envelopeRequestParser, getEnvelopeType, shouldSkipFeedbackTest } from '../../../utils/helpers';
+
+sentryTest('should capture feedback with custom button', async ({ getLocalTestUrl, page }) => {
+ if (shouldSkipFeedbackTest()) {
+ sentryTest.skip();
+ }
+
+ const feedbackRequestPromise = page.waitForResponse(res => {
+ const req = res.request();
+
+ const postData = req.postData();
+ if (!postData) {
+ return false;
+ }
+
+ try {
+ return getEnvelopeType(req) === 'feedback';
+ } catch (err) {
+ return false;
+ }
+ });
+
+ await page.route('https://dsn.ingest.sentry.io/**/*', route => {
+ return route.fulfill({
+ status: 200,
+ contentType: 'application/json',
+ body: JSON.stringify({ id: 'test-id' }),
+ });
+ });
+
+ const url = await getLocalTestUrl({ testDir: __dirname });
+
+ await page.goto(url);
+ await page.locator('#custom-feedback-buttom').click();
+ await page.waitForSelector(':visible:text-is("Report a Bug")');
+
+ expect(await page.locator(':visible:text-is("Report a Bug")').count()).toEqual(1);
+ await page.locator('[name="name"]').fill('Jane Doe');
+ await page.locator('[name="email"]').fill('janedoe@example.org');
+ await page.locator('[name="message"]').fill('my example feedback');
+ await page.locator('[data-sentry-feedback] .btn--primary').click();
+
+ const feedbackEvent = envelopeRequestParser((await feedbackRequestPromise).request());
+ expect(feedbackEvent).toEqual({
+ type: 'feedback',
+ breadcrumbs: expect.any(Array),
+ contexts: {
+ feedback: {
+ contact_email: 'janedoe@example.org',
+ message: 'my example feedback',
+ name: 'Jane Doe',
+ source: 'widget',
+ url: `${TEST_HOST}/index.html`,
+ },
+ trace: {
+ trace_id: expect.stringMatching(/\w{32}/),
+ span_id: expect.stringMatching(/\w{16}/),
+ },
+ },
+ level: 'info',
+ timestamp: expect.any(Number),
+ event_id: expect.stringMatching(/\w{32}/),
+ environment: 'production',
+ tags: {},
+ sdk: {
+ integrations: expect.arrayContaining(['Feedback']),
+ version: expect.any(String),
+ name: 'sentry.javascript.browser',
+ packages: expect.anything(),
+ },
+ request: {
+ url: `${TEST_HOST}/index.html`,
+ headers: {
+ 'User-Agent': expect.stringContaining(''),
+ },
+ },
+ platform: 'javascript',
+ });
+});
diff --git a/dev-packages/browser-integration-tests/suites/feedback/logger/init.js b/dev-packages/browser-integration-tests/suites/feedback/logger/init.js
new file mode 100644
index 000000000000..3251bd6c7a4c
--- /dev/null
+++ b/dev-packages/browser-integration-tests/suites/feedback/logger/init.js
@@ -0,0 +1,19 @@
+import * as Sentry from '@sentry/browser';
+// Import this separately so that generatePlugin can handle it for CDN scenarios
+import { feedbackIntegration } from '@sentry/browser';
+
+const feedback = feedbackIntegration({
+ autoInject: false,
+});
+
+window.Sentry = Sentry;
+window.feedback = feedback;
+
+Sentry.init({
+ dsn: 'https://public@dsn.ingest.sentry.io/1337',
+ debug: true,
+ integrations: [feedback],
+});
+
+// This should log an error!
+feedback.attachTo('#does-not-exist');
diff --git a/dev-packages/browser-integration-tests/suites/feedback/logger/test.ts b/dev-packages/browser-integration-tests/suites/feedback/logger/test.ts
new file mode 100644
index 000000000000..34fadfc2503b
--- /dev/null
+++ b/dev-packages/browser-integration-tests/suites/feedback/logger/test.ts
@@ -0,0 +1,36 @@
+import { expect } from '@playwright/test';
+
+import { sentryTest } from '../../../utils/fixtures';
+import { shouldSkipFeedbackTest } from '../../../utils/helpers';
+
+/**
+ * This test is mostly relevant for ensuring that the logger works in all combinations of CDN bundles.
+ * Even if feedback is included via the CDN, this test ensures that the logger is working correctly.
+ */
+sentryTest('should log error correctly', async ({ getLocalTestUrl, page }) => {
+ // In minified bundles we do not have logger messages, so we skip the test
+ if (shouldSkipFeedbackTest() || (process.env.PW_BUNDLE || '').includes('_min')) {
+ sentryTest.skip();
+ }
+
+ const messages: string[] = [];
+
+ page.on('console', message => {
+ messages.push(message.text());
+ });
+
+ await page.route('https://dsn.ingest.sentry.io/**/*', route => {
+ return route.fulfill({
+ status: 200,
+ contentType: 'application/json',
+ body: JSON.stringify({ id: 'test-id' }),
+ });
+ });
+
+ const url = await getLocalTestUrl({ testDir: __dirname });
+
+ await page.goto(url);
+
+ expect(messages).toContain('Sentry Logger [log]: Integration installed: Feedback');
+ expect(messages).toContain('Sentry Logger [error]: [Feedback] Unable to attach to target element');
+});
diff --git a/dev-packages/browser-integration-tests/suites/integrations/httpContext/init.js b/dev-packages/browser-integration-tests/suites/integrations/httpContext/init.js
new file mode 100644
index 000000000000..984534454ac7
--- /dev/null
+++ b/dev-packages/browser-integration-tests/suites/integrations/httpContext/init.js
@@ -0,0 +1,20 @@
+import * as Sentry from '@sentry/browser';
+
+window.Sentry = Sentry;
+
+const integrations = Sentry.getDefaultIntegrations({}).filter(
+ defaultIntegration => defaultIntegration.name === 'HttpContext',
+);
+
+const client = new Sentry.BrowserClient({
+ dsn: 'https://public@dsn.ingest.sentry.io/1337',
+ transport: Sentry.makeFetchTransport,
+ stackParser: Sentry.defaultStackParser,
+ integrations: integrations,
+});
+
+const scope = new Sentry.Scope();
+scope.setClient(client);
+client.init();
+
+window._sentryScope = scope;
diff --git a/dev-packages/browser-integration-tests/suites/integrations/httpContext/subject.js b/dev-packages/browser-integration-tests/suites/integrations/httpContext/subject.js
new file mode 100644
index 000000000000..62ce205e2ffc
--- /dev/null
+++ b/dev-packages/browser-integration-tests/suites/integrations/httpContext/subject.js
@@ -0,0 +1 @@
+window._sentryScope.captureException(new Error('client init'));
diff --git a/dev-packages/browser-integration-tests/suites/integrations/httpContext/test.ts b/dev-packages/browser-integration-tests/suites/integrations/httpContext/test.ts
new file mode 100644
index 000000000000..02a62142e02b
--- /dev/null
+++ b/dev-packages/browser-integration-tests/suites/integrations/httpContext/test.ts
@@ -0,0 +1,26 @@
+import { expect } from '@playwright/test';
+import type { Event } from '@sentry/types';
+
+import { sentryTest } from '../../../utils/fixtures';
+import { getFirstSentryEnvelopeRequest } from '../../../utils/helpers';
+
+sentryTest('httpContextIntegration captures user-agent and referrer', async ({ getLocalTestPath, page }) => {
+ const url = await getLocalTestPath({ testDir: __dirname });
+
+ const errorEventPromise = getFirstSentryEnvelopeRequest(page);
+
+ // Simulate document.referrer being set to test full functionality of the integration
+ await page.goto(url, { referer: 'https://sentry.io/' });
+
+ const errorEvent = await errorEventPromise;
+
+ expect(errorEvent.exception?.values).toHaveLength(1);
+
+ expect(errorEvent.request).toEqual({
+ headers: {
+ 'User-Agent': expect.any(String),
+ Referer: 'https://sentry.io/',
+ },
+ url: expect.any(String),
+ });
+});
diff --git a/dev-packages/browser-integration-tests/suites/integrations/httpclient/httpClientIntegration/init.js b/dev-packages/browser-integration-tests/suites/integrations/httpclient/httpClientIntegration/init.js
deleted file mode 100644
index 8540ab176c38..000000000000
--- a/dev-packages/browser-integration-tests/suites/integrations/httpclient/httpClientIntegration/init.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import * as Sentry from '@sentry/browser';
-import { httpClientIntegration } from '@sentry/browser';
-
-window.Sentry = Sentry;
-
-Sentry.init({
- dsn: 'https://public@dsn.ingest.sentry.io/1337',
- integrations: [httpClientIntegration()],
- tracesSampleRate: 1,
- sendDefaultPii: true,
-});
diff --git a/dev-packages/browser-integration-tests/suites/integrations/httpclient/httpClientIntegration/subject.js b/dev-packages/browser-integration-tests/suites/integrations/httpclient/httpClientIntegration/subject.js
deleted file mode 100644
index 563b069e66cc..000000000000
--- a/dev-packages/browser-integration-tests/suites/integrations/httpclient/httpClientIntegration/subject.js
+++ /dev/null
@@ -1,8 +0,0 @@
-const xhr = new XMLHttpRequest();
-
-xhr.open('GET', 'http://sentry-test.io/foo', true);
-xhr.withCredentials = true;
-xhr.setRequestHeader('Accept', 'application/json');
-xhr.setRequestHeader('Content-Type', 'application/json');
-xhr.setRequestHeader('Cache', 'no-cache');
-xhr.send();
diff --git a/dev-packages/browser-integration-tests/suites/integrations/httpclient/httpClientIntegration/test.ts b/dev-packages/browser-integration-tests/suites/integrations/httpclient/httpClientIntegration/test.ts
deleted file mode 100644
index f064a8652b48..000000000000
--- a/dev-packages/browser-integration-tests/suites/integrations/httpclient/httpClientIntegration/test.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-import { expect } from '@playwright/test';
-import type { Event } from '@sentry/types';
-
-import { sentryTest } from '../../../../utils/fixtures';
-import { getFirstSentryEnvelopeRequest } from '../../../../utils/helpers';
-
-sentryTest('works with httpClientIntegration', async ({ getLocalTestPath, page }) => {
- const url = await getLocalTestPath({ testDir: __dirname });
-
- await page.route('**/foo', route => {
- return route.fulfill({
- status: 500,
- body: JSON.stringify({
- error: {
- message: 'Internal Server Error',
- },
- }),
- headers: {
- 'Content-Type': 'text/html',
- },
- });
- });
-
- const eventData = await getFirstSentryEnvelopeRequest(page, url);
-
- expect(eventData.exception?.values).toHaveLength(1);
-
- // Not able to get the cookies from the request/response because of Playwright bug
- // https://github.com/microsoft/playwright/issues/11035
- expect(eventData).toMatchObject({
- message: 'HTTP Client Error with status code: 500',
- exception: {
- values: [
- {
- type: 'Error',
- value: 'HTTP Client Error with status code: 500',
- mechanism: {
- type: 'http.client',
- handled: false,
- },
- },
- ],
- },
- request: {
- url: 'http://sentry-test.io/foo',
- method: 'GET',
- headers: {
- accept: 'application/json',
- cache: 'no-cache',
- 'content-type': 'application/json',
- },
- },
- contexts: {
- response: {
- status_code: 500,
- body_size: 45,
- headers: {
- 'content-type': 'text/html',
- 'content-length': '45',
- },
- },
- },
- });
-});
diff --git a/dev-packages/browser-integration-tests/suites/replay/logger/init.js b/dev-packages/browser-integration-tests/suites/replay/logger/init.js
new file mode 100644
index 000000000000..195be16ddad3
--- /dev/null
+++ b/dev-packages/browser-integration-tests/suites/replay/logger/init.js
@@ -0,0 +1,18 @@
+import * as Sentry from '@sentry/browser';
+
+window.Sentry = Sentry;
+window.Replay = Sentry.replayIntegration({
+ flushMinDelay: 200,
+ flushMaxDelay: 200,
+ minReplayDuration: 0,
+});
+
+Sentry.init({
+ dsn: 'https://public@dsn.ingest.sentry.io/1337',
+ sampleRate: 0,
+ replaysSessionSampleRate: 1.0,
+ replaysOnErrorSampleRate: 0.0,
+ debug: true,
+
+ integrations: [window.Replay],
+});
diff --git a/dev-packages/browser-integration-tests/suites/replay/logger/test.ts b/dev-packages/browser-integration-tests/suites/replay/logger/test.ts
new file mode 100644
index 000000000000..fa034a12b003
--- /dev/null
+++ b/dev-packages/browser-integration-tests/suites/replay/logger/test.ts
@@ -0,0 +1,36 @@
+import { expect } from '@playwright/test';
+
+import { sentryTest } from '../../../utils/fixtures';
+import { shouldSkipReplayTest, waitForReplayRequest } from '../../../utils/replayHelpers';
+
+sentryTest('should output logger messages', async ({ getLocalTestPath, page }) => {
+ // In minified bundles we do not have logger messages, so we skip the test
+ if (shouldSkipReplayTest() || (process.env.PW_BUNDLE || '').includes('_min')) {
+ sentryTest.skip();
+ }
+
+ const messages: string[] = [];
+
+ page.on('console', message => {
+ messages.push(message.text());
+ });
+
+ await page.route('https://dsn.ingest.sentry.io/**/*', route => {
+ return route.fulfill({
+ status: 200,
+ contentType: 'application/json',
+ body: JSON.stringify({ id: 'test-id' }),
+ });
+ });
+
+ const reqPromise0 = waitForReplayRequest(page, 0);
+
+ const url = await getLocalTestPath({ testDir: __dirname });
+
+ await Promise.all([page.goto(url), reqPromise0]);
+
+ expect(messages).toContain('Sentry Logger [log]: Integration installed: Replay');
+ expect(messages).toContain('Sentry Logger [info]: [Replay] Creating new session');
+ expect(messages).toContain('Sentry Logger [info]: [Replay] Starting replay in session mode');
+ expect(messages).toContain('Sentry Logger [info]: [Replay] Using compression worker');
+});
diff --git a/dev-packages/browser-integration-tests/utils/generatePlugin.ts b/dev-packages/browser-integration-tests/utils/generatePlugin.ts
index 9189ce63812f..acc583506df4 100644
--- a/dev-packages/browser-integration-tests/utils/generatePlugin.ts
+++ b/dev-packages/browser-integration-tests/utils/generatePlugin.ts
@@ -30,7 +30,6 @@ const useLoader = bundleKey.startsWith('loader');
const IMPORTED_INTEGRATION_CDN_BUNDLE_PATHS: Record = {
httpClientIntegration: 'httpclient',
captureConsoleIntegration: 'captureconsole',
- CaptureConsole: 'captureconsole',
debugIntegration: 'debug',
rewriteFramesIntegration: 'rewriteframes',
contextLinesIntegration: 'contextlines',
diff --git a/dev-packages/bundle-analyzer-scenarios/package.json b/dev-packages/bundle-analyzer-scenarios/package.json
index 6cec8aa83b2f..b1375418e16f 100644
--- a/dev-packages/bundle-analyzer-scenarios/package.json
+++ b/dev-packages/bundle-analyzer-scenarios/package.json
@@ -9,7 +9,7 @@
"private": true,
"dependencies": {
"html-webpack-plugin": "^5.6.0",
- "webpack": "^5.92.1",
+ "webpack": "^5.94.0",
"webpack-bundle-analyzer": "^4.10.2"
},
"scripts": {
diff --git a/dev-packages/e2e-tests/test-applications/node-express-esm-loader/src/instrument.mjs b/dev-packages/e2e-tests/test-applications/node-express-esm-loader/src/instrument.mjs
index 544c773e5e7c..caaf73162ded 100644
--- a/dev-packages/e2e-tests/test-applications/node-express-esm-loader/src/instrument.mjs
+++ b/dev-packages/e2e-tests/test-applications/node-express-esm-loader/src/instrument.mjs
@@ -5,4 +5,5 @@ Sentry.init({
dsn: process.env.E2E_TEST_DSN,
tunnel: `http://localhost:3031/`, // proxy server
tracesSampleRate: 1,
+ registerEsmLoaderHooks: { onlyIncludeInstrumentedModules: true },
});
diff --git a/dev-packages/e2e-tests/test-applications/solidstart/app.config.ts b/dev-packages/e2e-tests/test-applications/solidstart/app.config.ts
index b3c737efe5ba..0b9a5553fb0a 100644
--- a/dev-packages/e2e-tests/test-applications/solidstart/app.config.ts
+++ b/dev-packages/e2e-tests/test-applications/solidstart/app.config.ts
@@ -1,3 +1,8 @@
+import { sentrySolidStartVite } from '@sentry/solidstart';
import { defineConfig } from '@solidjs/start/config';
-export default defineConfig({});
+export default defineConfig({
+ vite: {
+ plugins: [sentrySolidStartVite()],
+ },
+});
diff --git a/dev-packages/e2e-tests/test-applications/solidstart/package.json b/dev-packages/e2e-tests/test-applications/solidstart/package.json
index dfcf8a47402a..e831a14c1f47 100644
--- a/dev-packages/e2e-tests/test-applications/solidstart/package.json
+++ b/dev-packages/e2e-tests/test-applications/solidstart/package.json
@@ -3,14 +3,19 @@
"version": "0.0.0",
"scripts": {
"clean": "pnpx rimraf node_modules pnpm-lock.yaml .vinxi .output",
+ "clean:build": "pnpx rimraf .vinxi .output",
"dev": "NODE_OPTIONS='--import ./src/instrument.server.mjs' vinxi dev",
"build": "vinxi build",
"//": [
"We are using `vinxi dev` to start the server because `vinxi start` is experimental and ",
"doesn't correctly resolve modules for @sentry/solidstart/solidrouter.",
- "This is currently not an issue outside of our repo. See: https://github.com/nksaraf/vinxi/issues/177"
+ "This is currently not an issue outside of our repo. See: https://github.com/nksaraf/vinxi/issues/177",
+ "We run the build command to ensure building succeeds. However, keeping",
+ "build output around slows down the vite dev server when using `@sentry/vite-plugin` so we clear it out",
+ "before actually running the tests.",
+ "Cleaning the build output should be removed once we can use `vinxi start`."
],
- "preview": "HOST=localhost PORT=3030 NODE_OPTIONS='--import ./src/instrument.server.mjs' vinxi dev",
+ "preview": "pnpm clean:build && HOST=localhost PORT=3030 NODE_OPTIONS='--import ./src/instrument.server.mjs' vinxi dev",
"start": "HOST=localhost PORT=3030 NODE_OPTIONS='--import ./src/instrument.server.mjs' vinxi start",
"test:prod": "TEST_ENV=production playwright test",
"test:build": "pnpm install && npx playwright install && pnpm build",
diff --git a/dev-packages/e2e-tests/test-applications/solidstart/src/routes/client-error.tsx b/dev-packages/e2e-tests/test-applications/solidstart/src/routes/client-error.tsx
index e997e4fbb1e3..5e405e8c4e40 100644
--- a/dev-packages/e2e-tests/test-applications/solidstart/src/routes/client-error.tsx
+++ b/dev-packages/e2e-tests/test-applications/solidstart/src/routes/client-error.tsx
@@ -1,75 +1,15 @@
-import * as Sentry from '@sentry/solidstart';
-import type { ParentProps } from 'solid-js';
-import { ErrorBoundary, createSignal, onMount } from 'solid-js';
-
-const SentryErrorBoundary = Sentry.withSentryErrorBoundary(ErrorBoundary);
-
-const [count, setCount] = createSignal(1);
-const [caughtError, setCaughtError] = createSignal(false);
-
export default function ClientErrorPage() {
return (
-
- {caughtError() && (
-
- )}
-
-
-
-
-
-
-
-
-
- );
-}
-
-function Throw(props: { error: string }) {
- onMount(() => {
- throw new Error(props.error);
- });
- return null;
-}
-
-function SampleErrorBoundary(props: ParentProps) {
- return (
- (
-
- Error Boundary Fallback
-
- {error.message}
-
-
-
- )}
- >
- {props.children}
-
+
+
+
);
}
diff --git a/dev-packages/e2e-tests/test-applications/solidstart/src/routes/error-boundary.tsx b/dev-packages/e2e-tests/test-applications/solidstart/src/routes/error-boundary.tsx
new file mode 100644
index 000000000000..b22607667e7e
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/solidstart/src/routes/error-boundary.tsx
@@ -0,0 +1,64 @@
+import * as Sentry from '@sentry/solidstart';
+import type { ParentProps } from 'solid-js';
+import { ErrorBoundary, createSignal, onMount } from 'solid-js';
+
+const SentryErrorBoundary = Sentry.withSentryErrorBoundary(ErrorBoundary);
+
+const [count, setCount] = createSignal(1);
+const [caughtError, setCaughtError] = createSignal(false);
+
+export default function ErrorBoundaryTestPage() {
+ return (
+
+ {caughtError() && (
+
+ )}
+
+
+
+
+
+
+ );
+}
+
+function Throw(props: { error: string }) {
+ onMount(() => {
+ throw new Error(props.error);
+ });
+ return null;
+}
+
+function SampleErrorBoundary(props: ParentProps) {
+ return (
+ (
+
+ Error Boundary Fallback
+
+ {error.message}
+
+
+
+ )}
+ >
+ {props.children}
+
+ );
+}
diff --git a/dev-packages/e2e-tests/test-applications/solidstart/src/routes/index.tsx b/dev-packages/e2e-tests/test-applications/solidstart/src/routes/index.tsx
index eed722cba4e3..9a0b22cc38c6 100644
--- a/dev-packages/e2e-tests/test-applications/solidstart/src/routes/index.tsx
+++ b/dev-packages/e2e-tests/test-applications/solidstart/src/routes/index.tsx
@@ -14,6 +14,9 @@ export default function Home() {
Server error
+
+ Error Boundary
+
User 5
diff --git a/dev-packages/e2e-tests/test-applications/solidstart/tests/errorboundary.test.ts b/dev-packages/e2e-tests/test-applications/solidstart/tests/errorboundary.test.ts
index a4edf3c46236..b709760aab94 100644
--- a/dev-packages/e2e-tests/test-applications/solidstart/tests/errorboundary.test.ts
+++ b/dev-packages/e2e-tests/test-applications/solidstart/tests/errorboundary.test.ts
@@ -10,7 +10,7 @@ test('captures an exception', async ({ page }) => {
);
});
- await page.goto('/client-error');
+ await page.goto('/error-boundary');
await page.locator('#caughtErrorBtn').click();
const errorEvent = await errorEventPromise;
@@ -27,7 +27,7 @@ test('captures an exception', async ({ page }) => {
},
],
},
- transaction: '/client-error',
+ transaction: '/error-boundary',
});
});
@@ -40,7 +40,7 @@ test('captures a second exception after resetting the boundary', async ({ page }
);
});
- await page.goto('/client-error');
+ await page.goto('/error-boundary');
await page.locator('#caughtErrorBtn').click();
const firstErrorEvent = await firstErrorEventPromise;
@@ -57,7 +57,7 @@ test('captures a second exception after resetting the boundary', async ({ page }
},
],
},
- transaction: '/client-error',
+ transaction: '/error-boundary',
});
const secondErrorEventPromise = waitForError('solidstart', errorEvent => {
@@ -85,6 +85,6 @@ test('captures a second exception after resetting the boundary', async ({ page }
},
],
},
- transaction: '/client-error',
+ transaction: '/error-boundary',
});
});
diff --git a/dev-packages/e2e-tests/test-applications/solidstart/tests/errors.client.test.ts b/dev-packages/e2e-tests/test-applications/solidstart/tests/errors.client.test.ts
index 0f5ef61b365a..e2b00786f54c 100644
--- a/dev-packages/e2e-tests/test-applications/solidstart/tests/errors.client.test.ts
+++ b/dev-packages/e2e-tests/test-applications/solidstart/tests/errors.client.test.ts
@@ -4,7 +4,7 @@ import { waitForError } from '@sentry-internal/test-utils';
test.describe('client-side errors', () => {
test('captures error thrown on click', async ({ page }) => {
const errorPromise = waitForError('solidstart', async errorEvent => {
- return errorEvent?.exception?.values?.[0]?.value === 'Error thrown from Solid Start E2E test app';
+ return errorEvent?.exception?.values?.[0]?.value === 'Uncaught error thrown from Solid Start E2E test app';
});
await page.goto(`/client-error`);
@@ -16,9 +16,8 @@ test.describe('client-side errors', () => {
values: [
{
type: 'Error',
- value: 'Error thrown from Solid Start E2E test app',
+ value: 'Uncaught error thrown from Solid Start E2E test app',
mechanism: {
- type: 'instrument',
handled: false,
},
},
diff --git a/dev-packages/node-integration-tests/package.json b/dev-packages/node-integration-tests/package.json
index 9243a1512884..0ac7fdbf0aa2 100644
--- a/dev-packages/node-integration-tests/package.json
+++ b/dev-packages/node-integration-tests/package.json
@@ -44,6 +44,7 @@
"cors": "^2.8.5",
"cron": "^3.1.6",
"express": "^4.17.3",
+ "generic-pool": "^3.9.0",
"graphql": "^16.3.0",
"http-terminator": "^3.2.0",
"ioredis": "^5.4.1",
diff --git a/dev-packages/node-integration-tests/suites/esm/import-in-the-middle/app.mjs b/dev-packages/node-integration-tests/suites/esm/import-in-the-middle/app.mjs
new file mode 100644
index 000000000000..6b20155aea38
--- /dev/null
+++ b/dev-packages/node-integration-tests/suites/esm/import-in-the-middle/app.mjs
@@ -0,0 +1,21 @@
+import { loggingTransport } from '@sentry-internal/node-integration-tests';
+import * as Sentry from '@sentry/node';
+import * as iitm from 'import-in-the-middle';
+
+new iitm.Hook((_, name) => {
+ if (name !== 'http') {
+ throw new Error(`'http' should be the only hooked modules but we just hooked '${name}'`);
+ }
+});
+
+Sentry.init({
+ dsn: 'https://public@dsn.ingest.sentry.io/1337',
+ release: '1.0',
+ autoSessionTracking: false,
+ transport: loggingTransport,
+ registerEsmLoaderHooks: { onlyIncludeInstrumentedModules: true },
+});
+
+await import('./sub-module.mjs');
+await import('http');
+await import('os');
diff --git a/dev-packages/node-integration-tests/suites/esm/import-in-the-middle/sub-module.mjs b/dev-packages/node-integration-tests/suites/esm/import-in-the-middle/sub-module.mjs
new file mode 100644
index 000000000000..9940c57857eb
--- /dev/null
+++ b/dev-packages/node-integration-tests/suites/esm/import-in-the-middle/sub-module.mjs
@@ -0,0 +1,2 @@
+// eslint-disable-next-line no-console
+console.assert(true);
diff --git a/dev-packages/node-integration-tests/suites/esm/import-in-the-middle/test.ts b/dev-packages/node-integration-tests/suites/esm/import-in-the-middle/test.ts
new file mode 100644
index 000000000000..8b9e6e06202f
--- /dev/null
+++ b/dev-packages/node-integration-tests/suites/esm/import-in-the-middle/test.ts
@@ -0,0 +1,12 @@
+import { conditionalTest } from '../../../utils';
+import { cleanupChildProcesses, createRunner } from '../../../utils/runner';
+
+afterAll(() => {
+ cleanupChildProcesses();
+});
+
+conditionalTest({ min: 18 })('import-in-the-middle', () => {
+ test('onlyIncludeInstrumentedModules', done => {
+ createRunner(__dirname, 'app.mjs').ensureNoErrorOutput().start(done);
+ });
+});
diff --git a/dev-packages/node-integration-tests/suites/tracing/genericPool/scenario.js b/dev-packages/node-integration-tests/suites/tracing/genericPool/scenario.js
new file mode 100644
index 000000000000..74d5f73693f5
--- /dev/null
+++ b/dev-packages/node-integration-tests/suites/tracing/genericPool/scenario.js
@@ -0,0 +1,71 @@
+const { loggingTransport } = require('@sentry-internal/node-integration-tests');
+const Sentry = require('@sentry/node');
+
+Sentry.init({
+ dsn: 'https://public@dsn.ingest.sentry.io/1337',
+ release: '1.0',
+ tracesSampleRate: 1.0,
+ transport: loggingTransport,
+});
+
+// Stop the process from exiting before the transaction is sent
+setInterval(() => {}, 1000);
+
+const mysql = require('mysql');
+const genericPool = require('generic-pool');
+
+const factory = {
+ create: function () {
+ return mysql.createConnection({
+ user: 'root',
+ password: 'docker',
+ });
+ },
+ destroy: function (client) {
+ client.end(err => {
+ if (err) {
+ // eslint-disable-next-line no-console
+ console.error('Error while disconnecting MySQL:', err);
+ }
+ });
+ },
+};
+
+const opts = {
+ max: 10,
+ min: 2,
+};
+
+const myPool = genericPool.createPool(factory, opts);
+
+async function run() {
+ await Sentry.startSpan(
+ {
+ op: 'transaction',
+ name: 'Test Transaction',
+ },
+ async () => {
+ try {
+ const client1 = await myPool.acquire();
+ const client2 = await myPool.acquire();
+
+ client1.query('SELECT NOW()', function () {
+ myPool.release(client1);
+ });
+
+ client2.query('SELECT 1 + 1 AS solution', function () {
+ myPool.release(client2);
+ });
+ } catch (err) {
+ // eslint-disable-next-line no-console
+ console.error('Error while pooling MySQL:', err);
+ } finally {
+ await myPool.drain();
+ await myPool.clear();
+ }
+ },
+ );
+}
+
+// eslint-disable-next-line @typescript-eslint/no-floating-promises
+run();
diff --git a/dev-packages/node-integration-tests/suites/tracing/genericPool/test.ts b/dev-packages/node-integration-tests/suites/tracing/genericPool/test.ts
new file mode 100644
index 000000000000..114d3a909188
--- /dev/null
+++ b/dev-packages/node-integration-tests/suites/tracing/genericPool/test.ts
@@ -0,0 +1,34 @@
+import { cleanupChildProcesses, createRunner } from '../../../utils/runner';
+
+describe('genericPool auto instrumentation', () => {
+ afterAll(() => {
+ cleanupChildProcesses();
+ });
+
+ test('should auto-instrument `genericPool` package when calling pool.require()', done => {
+ const EXPECTED_TRANSACTION = {
+ transaction: 'Test Transaction',
+ spans: expect.arrayContaining([
+ expect.objectContaining({
+ description: expect.stringMatching(/^generic-pool\.ac?quire/),
+ origin: 'auto.db.otel.generic_pool',
+ data: {
+ 'sentry.origin': 'auto.db.otel.generic_pool',
+ },
+ status: 'ok',
+ }),
+
+ expect.objectContaining({
+ description: expect.stringMatching(/^generic-pool\.ac?quire/),
+ origin: 'auto.db.otel.generic_pool',
+ data: {
+ 'sentry.origin': 'auto.db.otel.generic_pool',
+ },
+ status: 'ok',
+ }),
+ ]),
+ };
+
+ createRunner(__dirname, 'scenario.js').expect({ transaction: EXPECTED_TRANSACTION }).start(done);
+ });
+});
diff --git a/dev-packages/size-limit-gh-action/.eslintrc.cjs b/dev-packages/size-limit-gh-action/.eslintrc.cjs
index 8c67e0037908..4a92730d3b0b 100644
--- a/dev-packages/size-limit-gh-action/.eslintrc.cjs
+++ b/dev-packages/size-limit-gh-action/.eslintrc.cjs
@@ -7,7 +7,7 @@ module.exports = {
overrides: [
{
- files: ['*.mjs'],
+ files: ['**/*.mjs'],
extends: ['@sentry-internal/sdk/src/base'],
},
],
diff --git a/dev-packages/size-limit-gh-action/index.mjs b/dev-packages/size-limit-gh-action/index.mjs
index 3dbb8aa22127..848802256853 100644
--- a/dev-packages/size-limit-gh-action/index.mjs
+++ b/dev-packages/size-limit-gh-action/index.mjs
@@ -1,4 +1,3 @@
-/* eslint-disable max-lines */
import { promises as fs } from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
@@ -9,13 +8,22 @@ import { exec } from '@actions/exec';
import { context, getOctokit } from '@actions/github';
import * as glob from '@actions/glob';
import * as io from '@actions/io';
-import bytes from 'bytes';
import { markdownTable } from 'markdown-table';
+import { SizeLimitFormatter } from './utils/SizeLimitFormatter.mjs';
+import { getArtifactsForBranchAndWorkflow } from './utils/getArtifactsForBranchAndWorkflow.mjs';
+
const SIZE_LIMIT_HEADING = '## size-limit report 📦 ';
const ARTIFACT_NAME = 'size-limit-action';
const RESULTS_FILE = 'size-limit-results.json';
+function getResultsFilePath() {
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
+ return path.resolve(__dirname, RESULTS_FILE);
+}
+
+const { getInput, setFailed } = core;
+
async function fetchPreviousComment(octokit, repo, pr) {
const { data: commentList } = await octokit.rest.issues.listComments({
...repo,
@@ -26,114 +34,6 @@ async function fetchPreviousComment(octokit, repo, pr) {
return !sizeLimitComment ? null : sizeLimitComment;
}
-class SizeLimit {
- formatBytes(size) {
- return bytes.format(size, { unitSeparator: ' ' });
- }
-
- formatPercentageChange(base = 0, current = 0) {
- if (base === 0) {
- return 'added';
- }
-
- if (current === 0) {
- return 'removed';
- }
-
- const value = ((current - base) / base) * 100;
- const formatted = (Math.sign(value) * Math.ceil(Math.abs(value) * 100)) / 100;
-
- if (value > 0) {
- return `+${formatted}%`;
- }
-
- if (value === 0) {
- return '-';
- }
-
- return `${formatted}%`;
- }
-
- formatChange(base = 0, current = 0) {
- if (base === 0) {
- return 'added';
- }
-
- if (current === 0) {
- return 'removed';
- }
-
- const value = current - base;
- const formatted = this.formatBytes(value);
-
- if (value > 0) {
- return `+${formatted} 🔺`;
- }
-
- if (value === 0) {
- return '-';
- }
-
- return `${formatted} 🔽`;
- }
-
- formatLine(value, change) {
- return `${value} (${change})`;
- }
-
- formatSizeResult(name, base, current) {
- return [
- name,
- this.formatBytes(current.size),
- this.formatPercentageChange(base.size, current.size),
- this.formatChange(base.size, current.size),
- ];
- }
-
- parseResults(output) {
- const results = JSON.parse(output);
-
- return results.reduce((current, result) => {
- return {
- // biome-ignore lint/performance/noAccumulatingSpread:
- ...current,
- [result.name]: {
- name: result.name,
- size: +result.size,
- },
- };
- }, {});
- }
-
- hasSizeChanges(base, current, threshold = 0) {
- const names = [...new Set([...(base ? Object.keys(base) : []), ...Object.keys(current)])];
-
- return !!names.find(name => {
- const baseResult = base?.[name] || EmptyResult;
- const currentResult = current[name] || EmptyResult;
-
- if (baseResult.size === 0 && currentResult.size === 0) {
- return true;
- }
-
- return Math.abs((currentResult.size - baseResult.size) / baseResult.size) * 100 > threshold;
- });
- }
-
- formatResults(base, current) {
- const names = [...new Set([...(base ? Object.keys(base) : []), ...Object.keys(current)])];
- const header = SIZE_RESULTS_HEADER;
- const fields = names.map(name => {
- const baseResult = base?.[name] || EmptyResult;
- const currentResult = current[name] || EmptyResult;
-
- return this.formatSizeResult(name, baseResult, currentResult);
- });
-
- return [header, ...fields];
- }
-}
-
async function execSizeLimit() {
let output = '';
@@ -151,15 +51,8 @@ async function execSizeLimit() {
return { status, output };
}
-const SIZE_RESULTS_HEADER = ['Path', 'Size', '% Change', 'Change'];
-
-const EmptyResult = {
- name: '-',
- size: 0,
-};
-
async function run() {
- const { getInput, setFailed } = core;
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
try {
const { payload, repo } = context;
@@ -174,36 +67,12 @@ async function run() {
}
const octokit = getOctokit(githubToken);
- const limit = new SizeLimit();
- const artifactClient = artifact.create();
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
- const resultsFilePath = path.resolve(__dirname, RESULTS_FILE);
+ const limit = new SizeLimitFormatter();
+ const resultsFilePath = getResultsFilePath();
// If we have no comparison branch, we just run size limit & store the result as artifact
if (!comparisonBranch) {
- let base;
- const { output: baseOutput } = await execSizeLimit();
-
- try {
- base = limit.parseResults(baseOutput);
- } catch (error) {
- core.error('Error parsing size-limit output. The output should be a json.');
- throw error;
- }
-
- try {
- await fs.writeFile(resultsFilePath, JSON.stringify(base), 'utf8');
- } catch (err) {
- core.error(err);
- }
- const globber = await glob.create(resultsFilePath, {
- followSymbolicLinks: false,
- });
- const files = await globber.glob();
-
- await artifactClient.uploadArtifact(ARTIFACT_NAME, files, __dirname);
-
- return;
+ return runSizeLimitOnComparisonBranch();
}
// Else, we run size limit for the current branch, AND fetch it for the comparison branch
@@ -213,12 +82,15 @@ async function run() {
let baseWorkflowRun;
try {
+ const workflowName = `${process.env.GITHUB_WORKFLOW || ''}`;
+ core.startGroup(`getArtifactsForBranchAndWorkflow - workflow:"${workflowName}", branch:"${comparisonBranch}"`);
const artifacts = await getArtifactsForBranchAndWorkflow(octokit, {
...repo,
artifactName: ARTIFACT_NAME,
branch: comparisonBranch,
- workflowName: `${process.env.GITHUB_WORKFLOW || ''}`,
+ workflowName,
});
+ core.endGroup();
if (!artifacts) {
throw new Error('No artifacts found');
@@ -255,9 +127,12 @@ async function run() {
const thresholdNumber = Number(threshold);
- // @ts-ignore
const sizeLimitComment = await fetchPreviousComment(octokit, repo, pr);
+ if (sizeLimitComment) {
+ core.debug('Found existing size limit comment, udpating it instead of creating a new one...');
+ }
+
const shouldComment =
isNaN(thresholdNumber) || limit.hasSizeChanges(base, current, thresholdNumber) || sizeLimitComment;
@@ -269,8 +144,12 @@ async function run() {
'⚠️ **Warning:** Base artifact is not the latest one, because the latest workflow run is not done yet. This may lead to incorrect results. Try to re-run all tests to get up to date results.',
);
}
-
- bodyParts.push(markdownTable(limit.formatResults(base, current)));
+ try {
+ bodyParts.push(markdownTable(limit.formatResults(base, current)));
+ } catch (error) {
+ core.error('Error generating markdown table');
+ core.error(error);
+ }
if (baseWorkflowRun) {
bodyParts.push('');
@@ -298,6 +177,8 @@ async function run() {
"Error updating comment. This can happen for PR's originating from a fork without write permissions.",
);
}
+ } else {
+ core.debug('Skipping comment because there are no changes.');
}
if (status > 0) {
@@ -309,136 +190,29 @@ async function run() {
}
}
-// max pages of workflows to pagination through
-const DEFAULT_MAX_PAGES = 50;
-// max results per page
-const DEFAULT_PAGE_LIMIT = 10;
-
-/**
- * Fetch artifacts from a workflow run from a branch
- *
- * This is a bit hacky since GitHub Actions currently does not directly
- * support downloading artifacts from other workflows
- */
-/**
- * Fetch artifacts from a workflow run from a branch
- *
- * This is a bit hacky since GitHub Actions currently does not directly
- * support downloading artifacts from other workflows
- */
-async function getArtifactsForBranchAndWorkflow(octokit, { owner, repo, workflowName, branch, artifactName }) {
- core.startGroup(`getArtifactsForBranchAndWorkflow - workflow:"${workflowName}", branch:"${branch}"`);
-
- let repositoryWorkflow = null;
+async function runSizeLimitOnComparisonBranch() {
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
+ const resultsFilePath = getResultsFilePath();
- // For debugging
- const allWorkflows = [];
-
- //
- // Find workflow id from `workflowName`
- //
- for await (const response of octokit.paginate.iterator(octokit.rest.actions.listRepoWorkflows, {
- owner,
- repo,
- })) {
- const targetWorkflow = response.data.find(({ name }) => name === workflowName);
+ const limit = new SizeLimitFormatter();
+ const artifactClient = artifact.create();
- allWorkflows.push(...response.data.map(({ name }) => name));
+ const { output: baseOutput } = await execSizeLimit();
- // If not found in responses, continue to search on next page
- if (!targetWorkflow) {
- continue;
- }
-
- repositoryWorkflow = targetWorkflow;
- break;
- }
-
- if (!repositoryWorkflow) {
- core.info(
- `Unable to find workflow with name "${workflowName}" in the repository. Found workflows: ${allWorkflows.join(
- ', ',
- )}`,
- );
- core.endGroup();
- return null;
+ try {
+ const base = limit.parseResults(baseOutput);
+ await fs.writeFile(resultsFilePath, JSON.stringify(base), 'utf8');
+ } catch (error) {
+ core.error('Error parsing size-limit output. The output should be a json.');
+ throw error;
}
- const workflow_id = repositoryWorkflow.id;
-
- let currentPage = 0;
- let latestWorkflowRun = null;
-
- for await (const response of octokit.paginate.iterator(octokit.rest.actions.listWorkflowRuns, {
- owner,
- repo,
- workflow_id,
- branch,
- per_page: DEFAULT_PAGE_LIMIT,
- event: 'push',
- })) {
- if (!response.data.length) {
- core.warning(`Workflow ${workflow_id} not found in branch ${branch}`);
- core.endGroup();
- return null;
- }
-
- // Do not allow downloading artifacts from a fork.
- const filtered = response.data.filter(workflowRun => workflowRun.head_repository.full_name === `${owner}/${repo}`);
-
- // Sort to ensure the latest workflow run is the first
- filtered.sort((a, b) => {
- return new Date(b.created_at).getTime() - new Date(a.created_at).getTime();
- });
-
- // Store the first workflow run, to determine if this is the latest one...
- if (!latestWorkflowRun) {
- latestWorkflowRun = filtered[0];
- }
-
- // Search through workflow artifacts until we find a workflow run w/ artifact name that we are looking for
- for (const workflowRun of filtered) {
- core.info(`Checking artifacts for workflow run: ${workflowRun.html_url}`);
-
- const {
- data: { artifacts },
- } = await octokit.rest.actions.listWorkflowRunArtifacts({
- owner,
- repo,
- run_id: workflowRun.id,
- });
-
- if (!artifacts) {
- core.warning(
- `Unable to fetch artifacts for branch: ${branch}, workflow: ${workflow_id}, workflowRunId: ${workflowRun.id}`,
- );
- } else {
- const foundArtifact = artifacts.find(({ name }) => name === artifactName);
- if (foundArtifact) {
- core.info(`Found suitable artifact: ${foundArtifact.url}`);
- return {
- artifact: foundArtifact,
- workflowRun,
- isLatest: latestWorkflowRun.id === workflowRun.id,
- };
- } else {
- core.info(`No artifact found for ${artifactName}, trying next workflow run...`);
- }
- }
- }
-
- if (currentPage > DEFAULT_MAX_PAGES) {
- core.warning(`Workflow ${workflow_id} not found in branch: ${branch}`);
- core.endGroup();
- return null;
- }
-
- currentPage++;
- }
+ const globber = await glob.create(resultsFilePath, {
+ followSymbolicLinks: false,
+ });
+ const files = await globber.glob();
- core.warning(`Artifact not found: ${artifactName}`);
- core.endGroup();
- return null;
+ await artifactClient.uploadArtifact(ARTIFACT_NAME, files, __dirname);
}
run();
diff --git a/dev-packages/size-limit-gh-action/utils/SizeLimitFormatter.mjs b/dev-packages/size-limit-gh-action/utils/SizeLimitFormatter.mjs
new file mode 100644
index 000000000000..034281b38224
--- /dev/null
+++ b/dev-packages/size-limit-gh-action/utils/SizeLimitFormatter.mjs
@@ -0,0 +1,137 @@
+import * as core from '@actions/core';
+import bytes from 'bytes';
+
+const SIZE_RESULTS_HEADER = ['Path', 'Size', '% Change', 'Change'];
+
+const EmptyResult = {
+ name: '-',
+ size: 0,
+};
+
+export class SizeLimitFormatter {
+ formatBytes(size) {
+ return bytes.format(size, { unitSeparator: ' ' });
+ }
+
+ formatName(name, sizeLimit, passed) {
+ if (passed) {
+ return name;
+ }
+
+ return `⛔️ ${name} (max: ${this.formatBytes(sizeLimit)})`;
+ }
+
+ formatPercentageChange(base = 0, current = 0) {
+ if (base === 0) {
+ return 'added';
+ }
+
+ if (current === 0) {
+ return 'removed';
+ }
+
+ const value = ((current - base) / base) * 100;
+ const formatted = (Math.sign(value) * Math.ceil(Math.abs(value) * 100)) / 100;
+
+ if (value > 0) {
+ return `+${formatted}%`;
+ }
+
+ if (value === 0) {
+ return '-';
+ }
+
+ return `${formatted}%`;
+ }
+
+ formatChange(base = 0, current = 0) {
+ if (base === 0) {
+ return 'added';
+ }
+
+ if (current === 0) {
+ return 'removed';
+ }
+
+ const value = current - base;
+ const formatted = this.formatBytes(value);
+
+ if (value > 0) {
+ return `+${formatted} 🔺`;
+ }
+
+ if (value === 0) {
+ return '-';
+ }
+
+ return `${formatted} 🔽`;
+ }
+
+ formatLine(value, change) {
+ return `${value} (${change})`;
+ }
+
+ formatSizeResult(name, base, current) {
+ if (!current.passed) {
+ core.debug(
+ `Size limit exceeded for ${name} - ${this.formatBytes(current.size)} > ${this.formatBytes(current.sizeLimit)}`,
+ );
+ }
+
+ return [
+ this.formatName(name, current.sizeLimit, current.passed),
+ this.formatBytes(current.size),
+ this.formatPercentageChange(base.size, current.size),
+ this.formatChange(base.size, current.size),
+ ];
+ }
+
+ parseResults(output) {
+ const results = JSON.parse(output);
+
+ return results.reduce((current, result) => {
+ return {
+ // biome-ignore lint/performance/noAccumulatingSpread:
+ ...current,
+ [result.name]: {
+ name: result.name,
+ size: +result.size,
+ sizeLimit: +result.sizeLimit,
+ passed: result.passed || false,
+ },
+ };
+ }, {});
+ }
+
+ hasSizeChanges(base, current, threshold = 0) {
+ if (!base || !current) {
+ return true;
+ }
+
+ const names = [...new Set([...Object.keys(base), ...Object.keys(current)])];
+
+ return names.some(name => {
+ const baseResult = base[name] || EmptyResult;
+ const currentResult = current[name] || EmptyResult;
+
+ if (!baseResult.size || !currentResult.size) {
+ return true;
+ }
+
+ return Math.abs((currentResult.size - baseResult.size) / baseResult.size) * 100 > threshold;
+ });
+ }
+
+ formatResults(base, current) {
+ const names = [...new Set([...(base ? Object.keys(base) : []), ...Object.keys(current)])];
+ const header = SIZE_RESULTS_HEADER;
+ const fields = names.map(name => {
+ const baseResult = base?.[name] || EmptyResult;
+ const currentResult = current[name] || EmptyResult;
+
+ return this.formatSizeResult(name, baseResult, currentResult);
+ });
+
+ return [header, ...fields];
+ }
+}
diff --git a/dev-packages/size-limit-gh-action/utils/getArtifactsForBranchAndWorkflow.mjs b/dev-packages/size-limit-gh-action/utils/getArtifactsForBranchAndWorkflow.mjs
new file mode 100644
index 000000000000..6d512b46afe1
--- /dev/null
+++ b/dev-packages/size-limit-gh-action/utils/getArtifactsForBranchAndWorkflow.mjs
@@ -0,0 +1,128 @@
+import * as core from '@actions/core';
+
+// max pages of workflows to pagination through
+const DEFAULT_MAX_PAGES = 50;
+// max results per page
+const DEFAULT_PAGE_LIMIT = 10;
+
+/**
+ * Fetch artifacts from a workflow run from a branch
+ *
+ * This is a bit hacky since GitHub Actions currently does not directly
+ * support downloading artifacts from other workflows
+ */
+/**
+ * Fetch artifacts from a workflow run from a branch
+ *
+ * This is a bit hacky since GitHub Actions currently does not directly
+ * support downloading artifacts from other workflows
+ */
+export async function getArtifactsForBranchAndWorkflow(octokit, { owner, repo, workflowName, branch, artifactName }) {
+ let repositoryWorkflow = null;
+
+ // For debugging
+ const allWorkflows = [];
+
+ //
+ // Find workflow id from `workflowName`
+ //
+ for await (const response of octokit.paginate.iterator(octokit.rest.actions.listRepoWorkflows, {
+ owner,
+ repo,
+ })) {
+ const targetWorkflow = response.data.find(({ name }) => name === workflowName);
+
+ allWorkflows.push(...response.data.map(({ name }) => name));
+
+ // If not found in responses, continue to search on next page
+ if (!targetWorkflow) {
+ continue;
+ }
+
+ repositoryWorkflow = targetWorkflow;
+ break;
+ }
+
+ if (!repositoryWorkflow) {
+ core.info(
+ `Unable to find workflow with name "${workflowName}" in the repository. Found workflows: ${allWorkflows.join(
+ ', ',
+ )}`,
+ );
+ return null;
+ }
+
+ const workflow_id = repositoryWorkflow.id;
+
+ let currentPage = 0;
+ let latestWorkflowRun = null;
+
+ for await (const response of octokit.paginate.iterator(octokit.rest.actions.listWorkflowRuns, {
+ owner,
+ repo,
+ workflow_id,
+ branch,
+ per_page: DEFAULT_PAGE_LIMIT,
+ event: 'push',
+ })) {
+ if (!response.data.length) {
+ core.warning(`Workflow ${workflow_id} not found in branch ${branch}`);
+ return null;
+ }
+
+ // Do not allow downloading artifacts from a fork.
+ const filtered = response.data.filter(workflowRun => workflowRun.head_repository.full_name === `${owner}/${repo}`);
+
+ // Sort to ensure the latest workflow run is the first
+ filtered.sort((a, b) => {
+ return new Date(b.created_at).getTime() - new Date(a.created_at).getTime();
+ });
+
+ // Store the first workflow run, to determine if this is the latest one...
+ if (!latestWorkflowRun) {
+ latestWorkflowRun = filtered[0];
+ }
+
+ // Search through workflow artifacts until we find a workflow run w/ artifact name that we are looking for
+ for (const workflowRun of filtered) {
+ core.info(`Checking artifacts for workflow run: ${workflowRun.html_url}`);
+
+ const {
+ data: { artifacts },
+ } = await octokit.rest.actions.listWorkflowRunArtifacts({
+ owner,
+ repo,
+ run_id: workflowRun.id,
+ });
+
+ if (!artifacts) {
+ core.warning(
+ `Unable to fetch artifacts for branch: ${branch}, workflow: ${workflow_id}, workflowRunId: ${workflowRun.id}`,
+ );
+ } else {
+ const foundArtifact = artifacts.find(({ name }) => name === artifactName);
+ if (foundArtifact) {
+ core.info(`Found suitable artifact: ${foundArtifact.url}`);
+ return {
+ artifact: foundArtifact,
+ workflowRun,
+ isLatest: latestWorkflowRun.id === workflowRun.id,
+ };
+ } else {
+ core.info(`No artifact found for ${artifactName}, trying next workflow run...`);
+ }
+ }
+ }
+
+ if (currentPage > DEFAULT_MAX_PAGES) {
+ core.warning(`Workflow ${workflow_id} not found in branch: ${branch}`);
+ return null;
+ }
+
+ currentPage++;
+ }
+
+ core.warning(`Artifact not found: ${artifactName}`);
+ core.endGroup();
+ return null;
+}
diff --git a/dev-packages/test-utils/src/playwright-config.ts b/dev-packages/test-utils/src/playwright-config.ts
index da2a10d0b477..d30c8cad4475 100644
--- a/dev-packages/test-utils/src/playwright-config.ts
+++ b/dev-packages/test-utils/src/playwright-config.ts
@@ -46,7 +46,7 @@ export function getPlaywrightConfig(
baseURL: `http://localhost:${appPort}`,
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
- trace: 'on-first-retry',
+ trace: 'retain-on-failure',
},
/* Configure projects for major browsers */
diff --git a/packages/astro/src/index.server.ts b/packages/astro/src/index.server.ts
index 0895eb86e364..747870da3014 100644
--- a/packages/astro/src/index.server.ts
+++ b/packages/astro/src/index.server.ts
@@ -43,6 +43,7 @@ export {
fsIntegration,
functionToStringIntegration,
generateInstrumentOnce,
+ genericPoolIntegration,
getActiveSpan,
getAutoPerformanceIntegrations,
getClient,
diff --git a/packages/aws-serverless/package.json b/packages/aws-serverless/package.json
index fa20bebe24ff..e6acf8e0e2f6 100644
--- a/packages/aws-serverless/package.json
+++ b/packages/aws-serverless/package.json
@@ -64,8 +64,8 @@
"access": "public"
},
"dependencies": {
- "@opentelemetry/instrumentation-aws-lambda": "0.43.0",
- "@opentelemetry/instrumentation-aws-sdk": "0.43.1",
+ "@opentelemetry/instrumentation-aws-lambda": "0.44.0",
+ "@opentelemetry/instrumentation-aws-sdk": "0.44.0",
"@sentry/core": "8.28.0",
"@sentry/node": "8.28.0",
"@sentry/types": "8.28.0",
diff --git a/packages/aws-serverless/src/index.ts b/packages/aws-serverless/src/index.ts
index 27f48c2da0db..f648dba045ec 100644
--- a/packages/aws-serverless/src/index.ts
+++ b/packages/aws-serverless/src/index.ts
@@ -87,6 +87,7 @@ export {
setupConnectErrorHandler,
fastifyIntegration,
fsIntegration,
+ genericPoolIntegration,
graphqlIntegration,
mongoIntegration,
mongooseIntegration,
diff --git a/packages/bun/src/index.ts b/packages/bun/src/index.ts
index d4ca06f85584..1d8b02c33568 100644
--- a/packages/bun/src/index.ts
+++ b/packages/bun/src/index.ts
@@ -108,6 +108,7 @@ export {
setupKoaErrorHandler,
connectIntegration,
setupConnectErrorHandler,
+ genericPoolIntegration,
graphqlIntegration,
mongoIntegration,
mongooseIntegration,
diff --git a/packages/cloudflare/src/request.ts b/packages/cloudflare/src/request.ts
index 560c17afb9e7..7a474c3b27cb 100644
--- a/packages/cloudflare/src/request.ts
+++ b/packages/cloudflare/src/request.ts
@@ -31,7 +31,13 @@ export function wrapRequestHandler(
handler: (...args: unknown[]) => Response | Promise,
): Promise {
return withIsolationScope(async isolationScope => {
- const { options, request, context } = wrapperOptions;
+ const { options, request } = wrapperOptions;
+
+ // In certain situations, the passed context can become undefined.
+ // For example, for Astro while prerendering pages at build time.
+ // see: https://github.com/getsentry/sentry-javascript/issues/13217
+ const context = wrapperOptions.context as ExecutionContext | undefined;
+
const client = init(options);
isolationScope.setClient(client);
@@ -89,7 +95,7 @@ export function wrapRequestHandler(
captureException(e, { mechanism: { handled: false, type: 'cloudflare' } });
throw e;
} finally {
- context.waitUntil(flush(2000));
+ context?.waitUntil(flush(2000));
}
},
);
diff --git a/packages/cloudflare/test/request.test.ts b/packages/cloudflare/test/request.test.ts
index 93764a292ab4..5218e8afe20b 100644
--- a/packages/cloudflare/test/request.test.ts
+++ b/packages/cloudflare/test/request.test.ts
@@ -45,6 +45,15 @@ describe('withSentry', () => {
expect(context.waitUntil).toHaveBeenLastCalledWith(expect.any(Promise));
});
+ test("doesn't error if context is undefined", () => {
+ expect(() =>
+ wrapRequestHandler(
+ { options: MOCK_OPTIONS, request: new Request('https://example.com'), context: undefined as any },
+ () => new Response('test'),
+ ),
+ ).not.toThrow();
+ });
+
test('creates a cloudflare client and sets it on the handler', async () => {
const initAndBindSpy = vi.spyOn(SentryCore, 'initAndBind');
await wrapRequestHandler(
diff --git a/packages/ember/package.json b/packages/ember/package.json
index 2ff37964532e..1bec2d30f9bf 100644
--- a/packages/ember/package.json
+++ b/packages/ember/package.json
@@ -80,7 +80,7 @@
"qunit": "~2.19.2",
"qunit-dom": "~2.0.0",
"sinon": "15.2.0",
- "webpack": "~5.90.3"
+ "webpack": "~5.94.0"
},
"engines": {
"node": ">=14.18"
diff --git a/packages/gatsby/gatsby-node.js b/packages/gatsby/gatsby-node.js
index d60914a03061..de88ee73adc0 100644
--- a/packages/gatsby/gatsby-node.js
+++ b/packages/gatsby/gatsby-node.js
@@ -12,7 +12,7 @@ exports.onCreateWebpackConfig = ({ getConfig, actions }, options) => {
sentryWebpackPlugin({
sourcemaps: {
// Only include files from the build output directory
- assets: ['public'],
+ assets: ['./public/**'],
// Ignore files that aren't users' source code related
ignore: [
'polyfill-*', // related to polyfills
diff --git a/packages/google-cloud-serverless/src/index.ts b/packages/google-cloud-serverless/src/index.ts
index f58305c64f6c..463a0c5c1246 100644
--- a/packages/google-cloud-serverless/src/index.ts
+++ b/packages/google-cloud-serverless/src/index.ts
@@ -87,6 +87,7 @@ export {
connectIntegration,
setupConnectErrorHandler,
fastifyIntegration,
+ genericPoolIntegration,
graphqlIntegration,
mongoIntegration,
mongooseIntegration,
diff --git a/packages/nextjs/package.json b/packages/nextjs/package.json
index 6965ddcf5167..1dacc4435cd4 100644
--- a/packages/nextjs/package.json
+++ b/packages/nextjs/package.json
@@ -68,7 +68,7 @@
"access": "public"
},
"dependencies": {
- "@opentelemetry/instrumentation-http": "0.52.1",
+ "@opentelemetry/instrumentation-http": "0.53.0",
"@opentelemetry/semantic-conventions": "^1.25.1",
"@rollup/plugin-commonjs": "26.0.1",
"@sentry/core": "8.28.0",
@@ -91,7 +91,7 @@
},
"peerDependencies": {
"next": "^13.2.0 || ^14.0 || ^15.0.0-rc.0",
- "webpack": ">= 5.0.0"
+ "webpack": "5.94.0"
},
"peerDependenciesMeta": {
"webpack": {
diff --git a/packages/nextjs/src/config/webpackPluginOptions.ts b/packages/nextjs/src/config/webpackPluginOptions.ts
index 1bca9bff49b6..7b183047896a 100644
--- a/packages/nextjs/src/config/webpackPluginOptions.ts
+++ b/packages/nextjs/src/config/webpackPluginOptions.ts
@@ -11,37 +11,43 @@ export function getWebpackPluginOptions(
buildContext: BuildContext,
sentryBuildOptions: SentryBuildOptions,
): SentryWebpackPluginOptions {
- const { buildId, isServer, config: userNextConfig, dir: projectDir, nextRuntime } = buildContext;
+ const { buildId, isServer, config: userNextConfig, dir, nextRuntime } = buildContext;
const prefixInsert = !isServer ? 'Client' : nextRuntime === 'edge' ? 'Edge' : 'Node.js';
- const distDirAbsPath = path.join(projectDir, (userNextConfig as NextConfigObject).distDir || '.next'); // `.next` is the default directory
+ // We need to convert paths to posix because Glob patterns use `\` to escape
+ // glob characters. This clashes with Windows path separators.
+ // See: https://www.npmjs.com/package/glob
+ const projectDir = dir.replace(/\\/g, '/');
+ // `.next` is the default directory
+ const distDir = (userNextConfig as NextConfigObject).distDir?.replace(/\\/g, '/') ?? '.next';
+ const distDirAbsPath = path.posix.join(projectDir, distDir);
let sourcemapUploadAssets: string[] = [];
const sourcemapUploadIgnore: string[] = [];
if (isServer) {
sourcemapUploadAssets.push(
- path.join(distDirAbsPath, 'server', '**'), // This is normally where Next.js outputs things
- path.join(distDirAbsPath, 'serverless', '**'), // This was the output location for serverless Next.js
+ path.posix.join(distDirAbsPath, 'server', '**'), // This is normally where Next.js outputs things
+ path.posix.join(distDirAbsPath, 'serverless', '**'), // This was the output location for serverless Next.js
);
} else {
if (sentryBuildOptions.widenClientFileUpload) {
- sourcemapUploadAssets.push(path.join(distDirAbsPath, 'static', 'chunks', '**'));
+ sourcemapUploadAssets.push(path.posix.join(distDirAbsPath, 'static', 'chunks', '**'));
} else {
sourcemapUploadAssets.push(
- path.join(distDirAbsPath, 'static', 'chunks', 'pages', '**'),
- path.join(distDirAbsPath, 'static', 'chunks', 'app', '**'),
+ path.posix.join(distDirAbsPath, 'static', 'chunks', 'pages', '**'),
+ path.posix.join(distDirAbsPath, 'static', 'chunks', 'app', '**'),
);
}
// TODO: We should think about uploading these when `widenClientFileUpload` is `true`. They may be useful in some situations.
sourcemapUploadIgnore.push(
- path.join(distDirAbsPath, 'static', 'chunks', 'framework-*'),
- path.join(distDirAbsPath, 'static', 'chunks', 'framework.*'),
- path.join(distDirAbsPath, 'static', 'chunks', 'main-*'),
- path.join(distDirAbsPath, 'static', 'chunks', 'polyfills-*'),
- path.join(distDirAbsPath, 'static', 'chunks', 'webpack-*'),
+ path.posix.join(distDirAbsPath, 'static', 'chunks', 'framework-*'),
+ path.posix.join(distDirAbsPath, 'static', 'chunks', 'framework.*'),
+ path.posix.join(distDirAbsPath, 'static', 'chunks', 'main-*'),
+ path.posix.join(distDirAbsPath, 'static', 'chunks', 'polyfills-*'),
+ path.posix.join(distDirAbsPath, 'static', 'chunks', 'webpack-*'),
);
}
@@ -79,9 +85,9 @@ export function getWebpackPluginOptions(
// We only care to delete client bundle source maps because they would be the ones being served.
// Removing the server source maps crashes Vercel builds for (thus far) unknown reasons:
// https://github.com/getsentry/sentry-javascript/issues/13099
- path.join(distDirAbsPath, 'static', '**', '*.js.map'),
- path.join(distDirAbsPath, 'static', '**', '*.mjs.map'),
- path.join(distDirAbsPath, 'static', '**', '*.cjs.map'),
+ path.posix.join(distDirAbsPath, 'static', '**', '*.js.map'),
+ path.posix.join(distDirAbsPath, 'static', '**', '*.mjs.map'),
+ path.posix.join(distDirAbsPath, 'static', '**', '*.cjs.map'),
]
: undefined,
...sentryBuildOptions.unstable_sentryWebpackPluginOptions?.sourcemaps,
diff --git a/packages/nextjs/src/config/withSentryConfig.ts b/packages/nextjs/src/config/withSentryConfig.ts
index 78df524c88c0..4f5205fecfcb 100644
--- a/packages/nextjs/src/config/withSentryConfig.ts
+++ b/packages/nextjs/src/config/withSentryConfig.ts
@@ -1,3 +1,4 @@
+/* eslint-disable complexity */
import { isThenable, parseSemver } from '@sentry/utils';
import * as fs from 'fs';
@@ -47,6 +48,7 @@ function getFinalConfigObject(
incomingUserNextConfigObject: NextConfigObject,
userSentryOptions: SentryBuildOptions,
): NextConfigObject {
+ // TODO(v9): Remove this check for the Sentry property
if ('sentry' in incomingUserNextConfigObject) {
// eslint-disable-next-line no-console
console.warn(
@@ -71,21 +73,10 @@ function getFinalConfigObject(
}
}
- // We need to enable `instrumentation.ts` for users because we tell them to put their `Sentry.init()` calls inside of it.
- if (incomingUserNextConfigObject.experimental?.instrumentationHook === false) {
- // eslint-disable-next-line no-console
- console.warn(
- '[@sentry/nextjs] You turned off the `instrumentationHook` option. Note that Sentry will not be initialized if you did not set it up inside `instrumentation.ts`.',
- );
- }
- incomingUserNextConfigObject.experimental = {
- instrumentationHook: true,
- ...incomingUserNextConfigObject.experimental,
- };
+ const nextJsVersion = getNextjsVersion();
// Add the `clientTraceMetadata` experimental option based on Next.js version. The option got introduced in Next.js version 15.0.0 (actually 14.3.0-canary.64).
// Adding the option on lower versions will cause Next.js to print nasty warnings we wouldn't confront our users with.
- const nextJsVersion = getNextjsVersion();
if (nextJsVersion) {
const { major, minor } = parseSemver(nextJsVersion);
if (major !== undefined && minor !== undefined && (major >= 15 || (major === 14 && minor >= 3))) {
@@ -99,7 +90,84 @@ function getFinalConfigObject(
} else {
// eslint-disable-next-line no-console
console.log(
- "[@sentry/nextjs] The Sentry SDK was not able to determine your Next.js version. If you are using Next.js 15 or greater, please add `experimental.clientTraceMetadata: ['sentry-trace', 'baggage']` to your Next.js config to enable pageload tracing for App Router.",
+ "[@sentry/nextjs] The Sentry SDK was not able to determine your Next.js version. If you are using Next.js version 15 or greater, please add `experimental.clientTraceMetadata: ['sentry-trace', 'baggage']` to your Next.js config to enable pageload tracing for App Router.",
+ );
+ }
+
+ // From Next.js version (15.0.0-canary.124) onwards, Next.js does no longer require the `experimental.instrumentationHook` option and will
+ // print a warning when it is set, so we need to conditionally provide it for lower versions.
+ if (nextJsVersion) {
+ const { major, minor, patch, prerelease } = parseSemver(nextJsVersion);
+ const isFullySupportedRelease =
+ major !== undefined &&
+ minor !== undefined &&
+ patch !== undefined &&
+ major >= 15 &&
+ ((minor === 0 && patch === 0 && prerelease === undefined) || minor > 0 || patch > 0);
+ const isSupportedV15Rc =
+ major !== undefined &&
+ minor !== undefined &&
+ patch !== undefined &&
+ prerelease !== undefined &&
+ major === 15 &&
+ minor === 0 &&
+ patch === 0 &&
+ prerelease.startsWith('rc.') &&
+ parseInt(prerelease.split('.')[1] || '', 10) > 0;
+ const isSupportedCanary =
+ minor !== undefined &&
+ patch !== undefined &&
+ prerelease !== undefined &&
+ major === 15 &&
+ minor === 0 &&
+ patch === 0 &&
+ prerelease.startsWith('canary.') &&
+ parseInt(prerelease.split('.')[1] || '', 10) >= 124;
+
+ if (!isFullySupportedRelease && !isSupportedV15Rc && !isSupportedCanary) {
+ if (incomingUserNextConfigObject.experimental?.instrumentationHook === false) {
+ // eslint-disable-next-line no-console
+ console.warn(
+ '[@sentry/nextjs] You turned off the `experimental.instrumentationHook` option. Note that Sentry will not be initialized if you did not set it up inside `instrumentation.(js|ts)`.',
+ );
+ }
+ incomingUserNextConfigObject.experimental = {
+ instrumentationHook: true,
+ ...incomingUserNextConfigObject.experimental,
+ };
+ }
+ } else {
+ // If we cannot detect a Next.js version for whatever reason, the sensible default is to set the `experimental.instrumentationHook`, even though it may create a warning.
+ if (
+ incomingUserNextConfigObject.experimental &&
+ 'instrumentationHook' in incomingUserNextConfigObject.experimental
+ ) {
+ if (incomingUserNextConfigObject.experimental.instrumentationHook === false) {
+ // eslint-disable-next-line no-console
+ console.warn(
+ '[@sentry/nextjs] You set `experimental.instrumentationHook` to `false`. If you are using Next.js version 15 or greater, you can remove that option. If you are using Next.js version 14 or lower, you need to set `experimental.instrumentationHook` in your `next.config.(js|mjs)` to `true` for the SDK to be properly initialized in combination with `instrumentation.(js|ts)`.',
+ );
+ }
+ } else {
+ // eslint-disable-next-line no-console
+ console.log(
+ "[@sentry/nextjs] The Sentry SDK was not able to determine your Next.js version. If you are using Next.js version 15 or greater, Next.js will probably show you a warning about the `experimental.instrumentationHook` being set. To silence Next.js' warning, explicitly set the `experimental.instrumentationHook` option in your `next.config.(js|mjs|ts)` to `undefined`. If you are on Next.js version 14 or lower, you can silence this particular warning by explicitly setting the `experimental.instrumentationHook` option in your `next.config.(js|mjs)` to `true`.",
+ );
+ incomingUserNextConfigObject.experimental = {
+ instrumentationHook: true,
+ ...incomingUserNextConfigObject.experimental,
+ };
+ }
+ }
+
+ if (process.env.TURBOPACK && !process.env.SENTRY_SUPPRESS_TURBOPACK_WARNING) {
+ // eslint-disable-next-line no-console
+ console.warn(
+ `[@sentry/nextjs] WARNING: You are using the Sentry SDK with \`next ${
+ process.env.NODE_ENV === 'development' ? 'dev' : 'build'
+ } --turbo\`. The Sentry SDK doesn't yet fully support Turbopack. The SDK will not be loaded in the browser, and serverside instrumentation will be inaccurate or incomplete. ${
+ process.env.NODE_ENV === 'development' ? 'Production builds without `--turbo` will still fully work. ' : ''
+ }If you are just trying out Sentry or attempting to configure the SDK, we recommend temporarily removing the \`--turbo\` flag while you are developing locally. Follow this issue for progress on Sentry + Turbopack: https://github.com/getsentry/sentry-javascript/issues/8105. (You can suppress this warning by setting SENTRY_SUPPRESS_TURBOPACK_WARNING=1 as environment variable)`,
);
}
diff --git a/packages/nextjs/test/config/webpack/webpackPluginOptions.test.ts b/packages/nextjs/test/config/webpack/webpackPluginOptions.test.ts
index 557859b2a7e1..177077d2b5c4 100644
--- a/packages/nextjs/test/config/webpack/webpackPluginOptions.test.ts
+++ b/packages/nextjs/test/config/webpack/webpackPluginOptions.test.ts
@@ -2,6 +2,7 @@ import type { BuildContext, NextConfigObject } from '../../../src/config/types';
import { getWebpackPluginOptions } from '../../../src/config/webpackPluginOptions';
function generateBuildContext(overrides: {
+ dir?: string;
isServer: boolean;
nextjsConfig?: NextConfigObject;
}): BuildContext {
@@ -9,7 +10,7 @@ function generateBuildContext(overrides: {
dev: false, // The plugin is not included in dev mode
isServer: overrides.isServer,
buildId: 'test-build-id',
- dir: '/my/project/dir',
+ dir: overrides.dir ?? '/my/project/dir',
config: overrides.nextjsConfig ?? {},
totalPages: 2,
defaultLoaders: true,
@@ -171,4 +172,23 @@ describe('getWebpackPluginOptions()', () => {
assets: [],
});
});
+
+ it('passes posix paths to the plugin', () => {
+ const buildContext = generateBuildContext({
+ dir: 'C:\\my\\windows\\project\\dir',
+ nextjsConfig: { distDir: '.dist\\v1' },
+ isServer: false,
+ });
+ const generatedPluginOptions = getWebpackPluginOptions(buildContext, { widenClientFileUpload: true });
+ expect(generatedPluginOptions.sourcemaps).toMatchObject({
+ assets: ['C:/my/windows/project/dir/.dist/v1/static/chunks/**'],
+ ignore: [
+ 'C:/my/windows/project/dir/.dist/v1/static/chunks/framework-*',
+ 'C:/my/windows/project/dir/.dist/v1/static/chunks/framework.*',
+ 'C:/my/windows/project/dir/.dist/v1/static/chunks/main-*',
+ 'C:/my/windows/project/dir/.dist/v1/static/chunks/polyfills-*',
+ 'C:/my/windows/project/dir/.dist/v1/static/chunks/webpack-*',
+ ],
+ });
+ });
});
diff --git a/packages/node/package.json b/packages/node/package.json
index f17c37541f63..9a7091ef57fc 100644
--- a/packages/node/package.json
+++ b/packages/node/package.json
@@ -68,27 +68,28 @@
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/context-async-hooks": "^1.25.1",
"@opentelemetry/core": "^1.25.1",
- "@opentelemetry/instrumentation": "^0.52.1",
- "@opentelemetry/instrumentation-connect": "0.38.0",
- "@opentelemetry/instrumentation-express": "0.41.1",
- "@opentelemetry/instrumentation-fastify": "0.38.0",
- "@opentelemetry/instrumentation-fs": "0.14.0",
- "@opentelemetry/instrumentation-graphql": "0.42.0",
- "@opentelemetry/instrumentation-hapi": "0.40.0",
- "@opentelemetry/instrumentation-http": "0.52.1",
- "@opentelemetry/instrumentation-ioredis": "0.42.0",
- "@opentelemetry/instrumentation-koa": "0.42.0",
- "@opentelemetry/instrumentation-mongodb": "0.46.0",
- "@opentelemetry/instrumentation-mongoose": "0.40.0",
- "@opentelemetry/instrumentation-mysql": "0.40.0",
- "@opentelemetry/instrumentation-mysql2": "0.40.0",
- "@opentelemetry/instrumentation-nestjs-core": "0.39.0",
- "@opentelemetry/instrumentation-pg": "0.43.0",
- "@opentelemetry/instrumentation-redis-4": "0.41.0",
+ "@opentelemetry/instrumentation": "^0.53.0",
+ "@opentelemetry/instrumentation-connect": "0.39.0",
+ "@opentelemetry/instrumentation-express": "0.42.0",
+ "@opentelemetry/instrumentation-fastify": "0.39.0",
+ "@opentelemetry/instrumentation-fs": "0.15.0",
+ "@opentelemetry/instrumentation-generic-pool": "0.39.0",
+ "@opentelemetry/instrumentation-graphql": "0.43.0",
+ "@opentelemetry/instrumentation-hapi": "0.41.0",
+ "@opentelemetry/instrumentation-http": "0.53.0",
+ "@opentelemetry/instrumentation-ioredis": "0.43.0",
+ "@opentelemetry/instrumentation-koa": "0.43.0",
+ "@opentelemetry/instrumentation-mongodb": "0.47.0",
+ "@opentelemetry/instrumentation-mongoose": "0.42.0",
+ "@opentelemetry/instrumentation-mysql": "0.41.0",
+ "@opentelemetry/instrumentation-mysql2": "0.41.0",
+ "@opentelemetry/instrumentation-nestjs-core": "0.40.0",
+ "@opentelemetry/instrumentation-pg": "0.44.0",
+ "@opentelemetry/instrumentation-redis-4": "0.42.0",
"@opentelemetry/resources": "^1.25.1",
"@opentelemetry/sdk-trace-base": "^1.25.1",
"@opentelemetry/semantic-conventions": "^1.25.1",
- "@prisma/instrumentation": "5.18.0",
+ "@prisma/instrumentation": "5.19.1",
"@sentry/core": "8.28.0",
"@sentry/opentelemetry": "8.28.0",
"@sentry/types": "8.28.0",
diff --git a/packages/node/src/index.ts b/packages/node/src/index.ts
index 5f4adf315fd5..6ce3c325e3ff 100644
--- a/packages/node/src/index.ts
+++ b/packages/node/src/index.ts
@@ -26,6 +26,7 @@ export { hapiIntegration, setupHapiErrorHandler } from './integrations/tracing/h
export { koaIntegration, setupKoaErrorHandler } from './integrations/tracing/koa';
export { connectIntegration, setupConnectErrorHandler } from './integrations/tracing/connect';
export { spotlightIntegration } from './integrations/spotlight';
+export { genericPoolIntegration } from './integrations/tracing/genericPool';
export { SentryContextManager } from './otel/contextManager';
export { generateInstrumentOnce } from './otel/instrument';
diff --git a/packages/node/src/integrations/node-fetch.ts b/packages/node/src/integrations/node-fetch.ts
index 093b314a6138..fa7a9974135a 100644
--- a/packages/node/src/integrations/node-fetch.ts
+++ b/packages/node/src/integrations/node-fetch.ts
@@ -192,11 +192,11 @@ function getBreadcrumbData(request: FetchRequest): Partial
function getAbsoluteUrl(origin: string, path: string = '/'): string {
const url = `${origin}`;
- if (origin.endsWith('/') && path.startsWith('/')) {
+ if (url.endsWith('/') && path.startsWith('/')) {
return `${url}${path.slice(1)}`;
}
- if (!origin.endsWith('/') && !path.startsWith('/')) {
+ if (!url.endsWith('/') && !path.startsWith('/')) {
return `${url}/${path.slice(1)}`;
}
diff --git a/packages/node/src/integrations/tracing/genericPool.ts b/packages/node/src/integrations/tracing/genericPool.ts
new file mode 100644
index 000000000000..8bc84554071c
--- /dev/null
+++ b/packages/node/src/integrations/tracing/genericPool.ts
@@ -0,0 +1,40 @@
+import { GenericPoolInstrumentation } from '@opentelemetry/instrumentation-generic-pool';
+import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, defineIntegration, spanToJSON } from '@sentry/core';
+import type { IntegrationFn } from '@sentry/types';
+import { generateInstrumentOnce } from '../../otel/instrument';
+
+const INTEGRATION_NAME = 'GenericPool';
+
+export const instrumentGenericPool = generateInstrumentOnce(INTEGRATION_NAME, () => new GenericPoolInstrumentation({}));
+
+const _genericPoolIntegration = (() => {
+ return {
+ name: INTEGRATION_NAME,
+ setupOnce() {
+ instrumentGenericPool();
+ },
+
+ setup(client) {
+ client.on('spanStart', span => {
+ const spanJSON = spanToJSON(span);
+
+ const spanDescription = spanJSON.description;
+
+ // typo in emitted span for version <= 0.38.0 of @opentelemetry/instrumentation-generic-pool
+ const isGenericPoolSpan =
+ spanDescription === 'generic-pool.aquire' || spanDescription === 'generic-pool.acquire';
+
+ if (isGenericPoolSpan) {
+ span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto.db.otel.generic_pool');
+ }
+ });
+ },
+ };
+}) satisfies IntegrationFn;
+
+/**
+ * GenericPool integration
+ *
+ * Capture tracing data for GenericPool.
+ */
+export const genericPoolIntegration = defineIntegration(_genericPoolIntegration);
diff --git a/packages/node/src/integrations/tracing/index.ts b/packages/node/src/integrations/tracing/index.ts
index 886c11683674..46a9f79e4caa 100644
--- a/packages/node/src/integrations/tracing/index.ts
+++ b/packages/node/src/integrations/tracing/index.ts
@@ -4,6 +4,7 @@ import { instrumentHttp } from '../http';
import { connectIntegration, instrumentConnect } from './connect';
import { expressIntegration, instrumentExpress } from './express';
import { fastifyIntegration, instrumentFastify } from './fastify';
+import { genericPoolIntegration, instrumentGenericPool } from './genericPool';
import { graphqlIntegration, instrumentGraphql } from './graphql';
import { hapiIntegration, instrumentHapi } from './hapi';
import { instrumentKoa, koaIntegration } from './koa';
@@ -37,6 +38,7 @@ export function getAutoPerformanceIntegrations(): Integration[] {
hapiIntegration(),
koaIntegration(),
connectIntegration(),
+ genericPoolIntegration(),
];
}
@@ -61,5 +63,6 @@ export function getOpenTelemetryInstrumentationToPreload(): (((options?: any) =>
instrumentHapi,
instrumentGraphql,
instrumentRedis,
+ instrumentGenericPool,
];
}
diff --git a/packages/node/src/sdk/initOtel.ts b/packages/node/src/sdk/initOtel.ts
index 03d8cea76fac..37b94ebc439f 100644
--- a/packages/node/src/sdk/initOtel.ts
+++ b/packages/node/src/sdk/initOtel.ts
@@ -10,6 +10,7 @@ import {
import { SDK_VERSION } from '@sentry/core';
import { SentryPropagator, SentrySampler, SentrySpanProcessor } from '@sentry/opentelemetry';
import { GLOBAL_OBJ, consoleSandbox, logger } from '@sentry/utils';
+import { createAddHookMessageChannel } from 'import-in-the-middle';
import { getOpenTelemetryInstrumentationToPreload } from '../integrations/tracing';
import { SentryContextManager } from '../otel/contextManager';
@@ -31,6 +32,26 @@ export function initOpenTelemetry(client: NodeClient): void {
client.traceProvider = provider;
}
+type ImportInTheMiddleInitData = Pick & {
+ addHookMessagePort?: unknown;
+};
+
+interface RegisterOptions {
+ data?: ImportInTheMiddleInitData;
+ transferList?: unknown[];
+}
+
+function getRegisterOptions(esmHookConfig?: EsmLoaderHookOptions): RegisterOptions {
+ if (esmHookConfig?.onlyIncludeInstrumentedModules) {
+ const { addHookMessagePort } = createAddHookMessageChannel();
+ // If the user supplied include, we need to use that as a starting point or use an empty array to ensure no modules
+ // are wrapped if they are not hooked
+ return { data: { addHookMessagePort, include: esmHookConfig.include || [] }, transferList: [addHookMessagePort] };
+ }
+
+ return { data: esmHookConfig };
+}
+
/** Initialize the ESM loader. */
export function maybeInitializeEsmLoader(esmHookConfig?: EsmLoaderHookOptions): void {
const [nodeMajor = 0, nodeMinor = 0] = process.versions.node.split('.').map(Number);
@@ -44,7 +65,7 @@ export function maybeInitializeEsmLoader(esmHookConfig?: EsmLoaderHookOptions):
if (!GLOBAL_OBJ._sentryEsmLoaderHookRegistered && importMetaUrl) {
try {
// @ts-expect-error register is available in these versions
- moduleModule.register('import-in-the-middle/hook.mjs', importMetaUrl, { data: esmHookConfig });
+ moduleModule.register('import-in-the-middle/hook.mjs', importMetaUrl, getRegisterOptions(esmHookConfig));
GLOBAL_OBJ._sentryEsmLoaderHookRegistered = true;
} catch (error) {
logger.warn('Failed to register ESM hook', error);
diff --git a/packages/node/src/types.ts b/packages/node/src/types.ts
index 9604b31ddb22..aa9873e2da91 100644
--- a/packages/node/src/types.ts
+++ b/packages/node/src/types.ts
@@ -6,7 +6,18 @@ import type { NodeTransportOptions } from './transports';
export interface EsmLoaderHookOptions {
include?: Array;
- exclude?: Array;
+ exclude?: Array /**
+ * When set to `true`, `import-in-the-middle` will only wrap ESM modules that are specifically instrumented by
+ * OpenTelemetry plugins. This is useful to avoid issues where `import-in-the-middle` is not compatible with some of
+ * your dependencies.
+ *
+ * **Note**: This feature will only work if you `Sentry.init()` the SDK before the instrumented modules are loaded.
+ * This can be achieved via the Node `--import` CLI flag or by loading your app via async `import()` after calling
+ * `Sentry.init()`.
+ *
+ * Defaults to `false`.
+ */;
+ onlyIncludeInstrumentedModules?: boolean;
}
export interface BaseNodeOptions {
diff --git a/packages/nuxt/package.json b/packages/nuxt/package.json
index 2aaa9f06dd78..688cac5489af 100644
--- a/packages/nuxt/package.json
+++ b/packages/nuxt/package.json
@@ -47,6 +47,7 @@
"@sentry/core": "8.28.0",
"@sentry/node": "8.28.0",
"@sentry/opentelemetry": "8.28.0",
+ "@sentry/rollup-plugin": "2.22.3",
"@sentry/types": "8.28.0",
"@sentry/utils": "8.28.0",
"@sentry/vite-plugin": "2.22.3",
diff --git a/packages/nuxt/src/vite/sourceMaps.ts b/packages/nuxt/src/vite/sourceMaps.ts
index 3518c45409e0..18eed2cbcfd8 100644
--- a/packages/nuxt/src/vite/sourceMaps.ts
+++ b/packages/nuxt/src/vite/sourceMaps.ts
@@ -1,52 +1,102 @@
import type { Nuxt } from '@nuxt/schema';
-import { sentryVitePlugin } from '@sentry/vite-plugin';
+import { type SentryRollupPluginOptions, sentryRollupPlugin } from '@sentry/rollup-plugin';
+import { type SentryVitePluginOptions, sentryVitePlugin } from '@sentry/vite-plugin';
+import type { NitroConfig } from 'nitropack';
import type { SentryNuxtModuleOptions } from '../common/types';
/**
- * Setup source maps for Sentry inside the Nuxt module during build time.
+ * Setup source maps for Sentry inside the Nuxt module during build time (in Vite for Nuxt and Rollup for Nitro).
*/
export function setupSourceMaps(moduleOptions: SentryNuxtModuleOptions, nuxt: Nuxt): void {
- nuxt.hook('vite:extendConfig', async (viteInlineConfig, _env) => {
- const sourceMapsUploadOptions = moduleOptions.sourceMapsUploadOptions || {};
-
- if ((sourceMapsUploadOptions.enabled ?? true) && viteInlineConfig.mode !== 'development') {
- const sentryPlugin = sentryVitePlugin({
- org: sourceMapsUploadOptions.org ?? process.env.SENTRY_ORG,
- project: sourceMapsUploadOptions.project ?? process.env.SENTRY_PROJECT,
- authToken: sourceMapsUploadOptions.authToken ?? process.env.SENTRY_AUTH_TOKEN,
- telemetry: sourceMapsUploadOptions.telemetry ?? true,
- sourcemaps: {
- assets: sourceMapsUploadOptions.sourcemaps?.assets ?? undefined,
- ignore: sourceMapsUploadOptions.sourcemaps?.ignore ?? undefined,
- filesToDeleteAfterUpload: sourceMapsUploadOptions.sourcemaps?.filesToDeleteAfterUpload ?? undefined,
- },
- _metaOptions: {
- telemetry: {
- metaFramework: 'nuxt',
- },
- },
- debug: moduleOptions.debug ?? false,
- });
+ const sourceMapsUploadOptions = moduleOptions.sourceMapsUploadOptions || {};
+ const sourceMapsEnabled = sourceMapsUploadOptions.enabled ?? true;
+ nuxt.hook('vite:extendConfig', async (viteInlineConfig, _env) => {
+ if (sourceMapsEnabled && viteInlineConfig.mode !== 'development') {
+ // Add Sentry plugin
viteInlineConfig.plugins = viteInlineConfig.plugins || [];
- viteInlineConfig.plugins.push(sentryPlugin);
-
- const sourceMapsPreviouslyEnabled = viteInlineConfig.build?.sourcemap;
-
- if (moduleOptions.debug && !sourceMapsPreviouslyEnabled) {
- // eslint-disable-next-line no-console
- console.log('[Sentry]: Enabled source maps generation in the Vite build options.');
- if (!moduleOptions.sourceMapsUploadOptions?.sourcemaps?.filesToDeleteAfterUpload) {
- // eslint-disable-next-line no-console
- console.warn(
- `[Sentry] We recommend setting the \`sourceMapsUploadOptions.sourcemaps.filesToDeleteAfterUpload\` option to clean up source maps after uploading.
-[Sentry] Otherwise, source maps might be deployed to production, depending on your configuration`,
- );
- }
- }
+ viteInlineConfig.plugins.push(sentryVitePlugin(getPluginOptions(moduleOptions)));
+ // Enable source maps
viteInlineConfig.build = viteInlineConfig.build || {};
viteInlineConfig.build.sourcemap = true;
+
+ logDebugInfo(moduleOptions, viteInlineConfig.build?.sourcemap);
+ }
+ });
+
+ nuxt.hook('nitro:config', (nitroConfig: NitroConfig) => {
+ if (sourceMapsEnabled && !nitroConfig.dev) {
+ if (!nitroConfig.rollupConfig) {
+ nitroConfig.rollupConfig = {};
+ }
+
+ if (nitroConfig.rollupConfig.plugins === null || nitroConfig.rollupConfig.plugins === undefined) {
+ nitroConfig.rollupConfig.plugins = [];
+ } else if (!Array.isArray(nitroConfig.rollupConfig.plugins)) {
+ // `rollupConfig.plugins` can be a single plugin, so we want to put it into an array so that we can push our own plugin
+ nitroConfig.rollupConfig.plugins = [nitroConfig.rollupConfig.plugins];
+ }
+
+ // Add Sentry plugin
+ nitroConfig.rollupConfig.plugins.push(sentryRollupPlugin(getPluginOptions(moduleOptions, true)));
+
+ // Enable source maps
+ nitroConfig.rollupConfig.output = nitroConfig?.rollupConfig?.output || {};
+ nitroConfig.rollupConfig.output.sourcemap = true;
+ nitroConfig.rollupConfig.output.sourcemapExcludeSources = false; // Adding "sourcesContent" to the source map (Nitro sets this eto `true`)
+
+ logDebugInfo(moduleOptions, nitroConfig.rollupConfig.output?.sourcemap);
}
});
}
+
+/**
+ * Normalizes the beginning of a path from e.g. ../../../ to ./
+ */
+function normalizePath(path: string): string {
+ return path.replace(/^(\.\.\/)+/, './');
+}
+
+function getPluginOptions(
+ moduleOptions: SentryNuxtModuleOptions,
+ isNitro = false,
+): SentryVitePluginOptions | SentryRollupPluginOptions {
+ const sourceMapsUploadOptions = moduleOptions.sourceMapsUploadOptions || {};
+
+ return {
+ org: sourceMapsUploadOptions.org ?? process.env.SENTRY_ORG,
+ project: sourceMapsUploadOptions.project ?? process.env.SENTRY_PROJECT,
+ authToken: sourceMapsUploadOptions.authToken ?? process.env.SENTRY_AUTH_TOKEN,
+ telemetry: sourceMapsUploadOptions.telemetry ?? true,
+ sourcemaps: {
+ assets:
+ sourceMapsUploadOptions.sourcemaps?.assets ?? isNitro ? ['./.output/server/**/*'] : ['./.output/public/**/*'],
+ ignore: sourceMapsUploadOptions.sourcemaps?.ignore ?? undefined,
+ filesToDeleteAfterUpload: sourceMapsUploadOptions.sourcemaps?.filesToDeleteAfterUpload ?? undefined,
+ rewriteSources: (source: string) => normalizePath(source),
+ },
+ _metaOptions: {
+ telemetry: {
+ metaFramework: 'nuxt',
+ },
+ },
+ debug: moduleOptions.debug ?? false,
+ };
+}
+
+function logDebugInfo(moduleOptions: SentryNuxtModuleOptions, sourceMapsPreviouslyEnabled: boolean): void {
+ if (moduleOptions.debug && !sourceMapsPreviouslyEnabled) {
+ // eslint-disable-next-line no-console
+ console.log('[Sentry]: Enabled source maps generation in the Vite build options.');
+
+ const sourceMapsUploadOptions = moduleOptions.sourceMapsUploadOptions || {};
+
+ if (!sourceMapsUploadOptions.sourcemaps?.filesToDeleteAfterUpload) {
+ // eslint-disable-next-line no-console
+ console.warn(
+ '[Sentry] We recommend setting the `sourceMapsUploadOptions.sourcemaps.filesToDeleteAfterUpload` option to clean up source maps after uploading. Otherwise, source maps might be deployed to production, depending on your configuration',
+ );
+ }
+ }
+}
diff --git a/packages/remix/package.json b/packages/remix/package.json
index 286926c79f1d..9b86fd631ff8 100644
--- a/packages/remix/package.json
+++ b/packages/remix/package.json
@@ -52,7 +52,7 @@
"access": "public"
},
"dependencies": {
- "@opentelemetry/instrumentation-http": "0.52.1",
+ "@opentelemetry/instrumentation-http": "0.53.0",
"@remix-run/router": "1.x",
"@sentry/cli": "^2.33.0",
"@sentry/core": "8.28.0",
diff --git a/packages/remix/src/index.server.ts b/packages/remix/src/index.server.ts
index 7ab6efb15827..457dcb9f8685 100644
--- a/packages/remix/src/index.server.ts
+++ b/packages/remix/src/index.server.ts
@@ -47,6 +47,7 @@ export {
flush,
functionToStringIntegration,
generateInstrumentOnce,
+ genericPoolIntegration,
getActiveSpan,
getAutoPerformanceIntegrations,
getClient,
diff --git a/packages/replay-internal/src/types/performance.ts b/packages/replay-internal/src/types/performance.ts
index 7a60e51684f3..f598581c93ab 100644
--- a/packages/replay-internal/src/types/performance.ts
+++ b/packages/replay-internal/src/types/performance.ts
@@ -114,7 +114,7 @@ export interface WebVitalData {
/**
* The layout shifts of a CLS metric
*/
- attributions?: { value: number; sources?: number[] }[];
+ attributions?: { value: number; nodeIds: number[] | undefined }[];
}
/**
diff --git a/packages/replay-internal/src/util/createPerformanceEntries.ts b/packages/replay-internal/src/util/createPerformanceEntries.ts
index 830f878dc8ea..c28e69caee00 100644
--- a/packages/replay-internal/src/util/createPerformanceEntries.ts
+++ b/packages/replay-internal/src/util/createPerformanceEntries.ts
@@ -58,11 +58,6 @@ interface LayoutShiftAttribution {
currentRect: DOMRectReadOnly;
}
-interface Attribution {
- value: number;
- nodeIds?: number[];
-}
-
/**
* Handler creater for web vitals
*/
@@ -198,7 +193,7 @@ export function getLargestContentfulPaint(metric: Metric): ReplayPerformanceEntr
return getWebVital(metric, 'largest-contentful-paint', node);
}
-function isLayoutShift(entry: PerformanceEntry | LayoutShift): entry is LayoutShift {
+function isLayoutShift(entry: PerformanceEntry): entry is LayoutShift {
return (entry as LayoutShift).sources !== undefined;
}
@@ -206,7 +201,7 @@ function isLayoutShift(entry: PerformanceEntry | LayoutShift): entry is LayoutSh
* Add a CLS event to the replay based on a CLS metric.
*/
export function getCumulativeLayoutShift(metric: Metric): ReplayPerformanceEntry {
- const layoutShifts: Attribution[] = [];
+ const layoutShifts: WebVitalData['attributions'] = [];
const nodes: Node[] = [];
for (const entry of metric.entries) {
if (isLayoutShift(entry)) {
@@ -220,9 +215,10 @@ export function getCumulativeLayoutShift(metric: Metric): ReplayPerformanceEntry
}
}
}
- layoutShifts.push({ value: entry.value, nodeIds });
+ layoutShifts.push({ value: entry.value, nodeIds: nodeIds.length ? nodeIds : undefined });
}
}
+
return getWebVital(metric, 'cumulative-layout-shift', nodes, layoutShifts);
}
@@ -251,14 +247,14 @@ function getWebVital(
metric: Metric,
name: string,
nodes: Node[] | undefined,
- attributions?: Attribution[],
+ attributions?: WebVitalData['attributions'],
): ReplayPerformanceEntry {
const value = metric.value;
const rating = metric.rating;
const end = getAbsoluteTime(value);
- const data: ReplayPerformanceEntry = {
+ return {
type: 'web-vital',
name,
start: end,
@@ -271,6 +267,4 @@ function getWebVital(
attributions,
},
};
-
- return data;
}
diff --git a/packages/solid/README.md b/packages/solid/README.md
index 06012bb34be8..e5ddd2186c02 100644
--- a/packages/solid/README.md
+++ b/packages/solid/README.md
@@ -4,16 +4,16 @@
-# Official Sentry SDK for Solid (EXPERIMENTAL)
+# Official Sentry SDK for Solid
[](https://www.npmjs.com/package/@sentry/solid)
[](https://www.npmjs.com/package/@sentry/solid)
[](https://www.npmjs.com/package/@sentry/solid)
-This SDK is considered ⚠️ **experimental and in an alpha state**. It may experience breaking changes. Please reach out
-on [GitHub](https://github.com/getsentry/sentry-javascript/issues/new/choose) if you have any feedback or concerns. This
-SDK currently only supports [Solid](https://www.solidjs.com/) and is not yet officially compatible with
-[Solid Start](https://start.solidjs.com/).
+This SDK is in **Beta**. The API is stable but updates may include minor changes in behavior. Please reach out on
+[GitHub](https://github.com/getsentry/sentry-javascript/issues/new/choose) if you have any feedback or concerns. This
+SDK is for [Solid](https://www.solidjs.com/). If you're using [SolidStart](https://start.solidjs.com/) see our
+[SolidStart SDK here](https://github.com/getsentry/sentry-javascript/tree/develop/packages/solidstart).
# Solid Router
diff --git a/packages/solidstart/.eslintrc.js b/packages/solidstart/.eslintrc.js
index c1f55c94aadf..d567b12530d0 100644
--- a/packages/solidstart/.eslintrc.js
+++ b/packages/solidstart/.eslintrc.js
@@ -14,6 +14,7 @@ module.exports = {
files: ['src/vite/**', 'src/server/**'],
rules: {
'@sentry-internal/sdk/no-optional-chaining': 'off',
+ '@sentry-internal/sdk/no-nullish-coalescing': 'off',
},
},
],
diff --git a/packages/solidstart/README.md b/packages/solidstart/README.md
index 0b25a3a37e3e..ceda55838e8d 100644
--- a/packages/solidstart/README.md
+++ b/packages/solidstart/README.md
@@ -4,15 +4,15 @@
-# Official Sentry SDK for Solid Start (EXPERIMENTAL)
+# Official Sentry SDK for SolidStart
[](https://www.npmjs.com/package/@sentry/solidstart)
[](https://www.npmjs.com/package/@sentry/solidstart)
[](https://www.npmjs.com/package/@sentry/solidstart)
-This SDK is considered ⚠️ **experimental and in an alpha state**. It may experience breaking changes. Please reach out
-on [GitHub](https://github.com/getsentry/sentry-javascript/issues/new/choose) if you have any feedback or concerns. This
-SDK is for [Solid Start](https://start.solidjs.com/). If you're using [Solid](https://www.solidjs.com/) see our
+This SDK is in **Beta**. The API is stable but updates may include minor changes in behavior. Please reach out on
+[GitHub](https://github.com/getsentry/sentry-javascript/issues/new/choose) if you have any feedback or concerns. This
+SDK is for [SolidStart](https://start.solidjs.com/). If you're using [Solid](https://www.solidjs.com/) see our
[Solid SDK here](https://github.com/getsentry/sentry-javascript/tree/develop/packages/solid).
## Links
@@ -22,7 +22,7 @@ SDK is for [Solid Start](https://start.solidjs.com/). If you're using [Solid](ht
## General
This package is a wrapper around `@sentry/node` for the server and `@sentry/solid` for the client side, with added
-functionality related to Solid Start.
+functionality related to SolidStart.
## Manual Setup
@@ -30,7 +30,7 @@ If the setup through the wizard doesn't work for you, you can also set up the SD
### 1. Prerequesits & Installation
-Install the Sentry Solid Start SDK:
+Install the Sentry SolidStart SDK:
```bash
# Using npm
@@ -157,58 +157,34 @@ render(
);
```
-# Sourcemaps and Releases
+## Uploading Source Maps
-To generate and upload source maps of your Solid Start app use our Vite bundler plugin.
-
-1. Install the Sentry Vite plugin
-
-```bash
-# Using npm
-npm install @sentry/vite-plugin --save-dev
-
-# Using yarn
-yarn add @sentry/vite-plugin --dev
-```
-
-2. Configure the vite plugin
-
-To upload source maps you have to configure an auth token. Auth tokens can be passed to the plugin explicitly with the
-`authToken` option, with a `SENTRY_AUTH_TOKEN` environment variable, or with an `.env.sentry-build-plugin` file in the
-working directory when building your project. We recommend you add the auth token to your CI/CD environment as an
-environment variable.
+To upload source maps, add the `sentrySolidStartVite` plugin from `@sentry/solidstart` to your `app.config.ts` and
+configure an auth token. Auth tokens can be passed to the plugin explicitly with the `authToken` option, with a
+`SENTRY_AUTH_TOKEN` environment variable, or with an `.env.sentry-build-plugin` file in the working directory when
+building your project. We recommend you add the auth token to your CI/CD environment as an environment variable.
Learn more about configuring the plugin in our
[Sentry Vite Plugin documentation](https://www.npmjs.com/package/@sentry/vite-plugin).
-```bash
-// .env.sentry-build-plugin
-SENTRY_AUTH_TOKEN=
-SENTRY_ORG=
-SENTRY_PROJECT=
-```
-
-3. Finally, add the plugin to your `app.config.ts` file.
-
-```javascript
+```typescript
+// app.config.ts
import { defineConfig } from '@solidjs/start/config';
-import { sentryVitePlugin } from '@sentry/vite-plugin';
+import { sentrySolidStartVite } from '@sentry/solidstart';
export default defineConfig({
- // rest of your config
// ...
vite: {
- build: {
- sourcemap: true,
- },
plugins: [
- sentryVitePlugin({
+ sentrySolidStartVite({
org: process.env.SENTRY_ORG,
project: process.env.SENTRY_PROJECT,
authToken: process.env.SENTRY_AUTH_TOKEN,
+ debug: true,
}),
],
},
+ // ...
});
```
diff --git a/packages/solidstart/src/client/sdk.ts b/packages/solidstart/src/client/sdk.ts
index f44a2134ce50..8b1b6f7f39d5 100644
--- a/packages/solidstart/src/client/sdk.ts
+++ b/packages/solidstart/src/client/sdk.ts
@@ -1,13 +1,21 @@
import { applySdkMetadata } from '@sentry/core';
import type { BrowserOptions } from '@sentry/solid';
-import { init as initSolidSDK } from '@sentry/solid';
-import type { Client } from '@sentry/types';
+import {
+ browserTracingIntegration,
+ getDefaultIntegrations as getDefaultSolidIntegrations,
+ init as initSolidSDK,
+} from '@sentry/solid';
+import type { Client, Integration } from '@sentry/types';
+
+// Treeshakable guard to remove all code related to tracing
+declare const __SENTRY_TRACING__: boolean;
/**
* Initializes the client side of the Solid Start SDK.
*/
export function init(options: BrowserOptions): Client | undefined {
const opts = {
+ defaultIntegrations: getDefaultIntegrations(options),
...options,
};
@@ -15,3 +23,20 @@ export function init(options: BrowserOptions): Client | undefined {
return initSolidSDK(opts);
}
+
+function getDefaultIntegrations(options: BrowserOptions): Integration[] {
+ const integrations = getDefaultSolidIntegrations(options);
+
+ // This evaluates to true unless __SENTRY_TRACING__ is text-replaced with "false",
+ // in which case everything inside will get tree-shaken away
+ if (typeof __SENTRY_TRACING__ === 'undefined' || __SENTRY_TRACING__) {
+ // We add the default BrowserTracingIntegration here always.
+ // We can do this, even if `solidRouterBrowserTracingIntegration` is
+ // supplied as integration in `init` by users because it will win
+ // over the default integration by virtue of having the same
+ // `BrowserTracing` integration name and being added later.
+ integrations.push(browserTracingIntegration());
+ }
+
+ return integrations;
+}
diff --git a/packages/solidstart/src/index.server.ts b/packages/solidstart/src/index.server.ts
index 0ce5251aa327..d675a1c72820 100644
--- a/packages/solidstart/src/index.server.ts
+++ b/packages/solidstart/src/index.server.ts
@@ -1 +1,2 @@
export * from './server';
+export * from './vite';
diff --git a/packages/solidstart/src/index.types.ts b/packages/solidstart/src/index.types.ts
index 89eaa14662e3..51adf848775a 100644
--- a/packages/solidstart/src/index.types.ts
+++ b/packages/solidstart/src/index.types.ts
@@ -3,6 +3,7 @@
// exports in this file - which we do below.
export * from './client';
export * from './server';
+export * from './vite';
import type { Integration, Options, StackParser } from '@sentry/types';
diff --git a/packages/solidstart/src/server/index.ts b/packages/solidstart/src/server/index.ts
index c3499a82459a..995f58d057e3 100644
--- a/packages/solidstart/src/server/index.ts
+++ b/packages/solidstart/src/server/index.ts
@@ -38,6 +38,7 @@ export {
flush,
functionToStringIntegration,
generateInstrumentOnce,
+ genericPoolIntegration,
getActiveSpan,
getAutoPerformanceIntegrations,
getClient,
diff --git a/packages/solidstart/src/vite/index.ts b/packages/solidstart/src/vite/index.ts
new file mode 100644
index 000000000000..464bbd604fbe
--- /dev/null
+++ b/packages/solidstart/src/vite/index.ts
@@ -0,0 +1 @@
+export * from './sentrySolidStartVite';
diff --git a/packages/solidstart/src/vite/sentrySolidStartVite.ts b/packages/solidstart/src/vite/sentrySolidStartVite.ts
new file mode 100644
index 000000000000..59435f919071
--- /dev/null
+++ b/packages/solidstart/src/vite/sentrySolidStartVite.ts
@@ -0,0 +1,18 @@
+import type { Plugin } from 'vite';
+import { makeSourceMapsVitePlugin } from './sourceMaps';
+import type { SentrySolidStartPluginOptions } from './types';
+
+/**
+ * Various Sentry vite plugins to be used for SolidStart.
+ */
+export const sentrySolidStartVite = (options: SentrySolidStartPluginOptions = {}): Plugin[] => {
+ const sentryPlugins: Plugin[] = [];
+
+ if (process.env.NODE_ENV !== 'development') {
+ if (options.sourceMapsUploadOptions?.enabled ?? true) {
+ sentryPlugins.push(...makeSourceMapsVitePlugin(options));
+ }
+ }
+
+ return sentryPlugins;
+};
diff --git a/packages/solidstart/src/vite/sourceMaps.ts b/packages/solidstart/src/vite/sourceMaps.ts
new file mode 100644
index 000000000000..548038515e79
--- /dev/null
+++ b/packages/solidstart/src/vite/sourceMaps.ts
@@ -0,0 +1,58 @@
+import { sentryVitePlugin } from '@sentry/vite-plugin';
+import type { Plugin } from 'vite';
+import type { SentrySolidStartPluginOptions } from './types';
+
+/**
+ * A Sentry plugin for SolidStart to enable source maps and use
+ * @sentry/vite-plugin to automatically upload source maps to Sentry.
+ * @param {SourceMapsOptions} options
+ */
+export function makeSourceMapsVitePlugin(options: SentrySolidStartPluginOptions): Plugin[] {
+ const { authToken, debug, org, project, sourceMapsUploadOptions } = options;
+ return [
+ {
+ name: 'sentry-solidstart-source-maps',
+ apply: 'build',
+ enforce: 'post',
+ config(config) {
+ const sourceMapsPreviouslyNotEnabled = !config.build?.sourcemap;
+ if (debug && sourceMapsPreviouslyNotEnabled) {
+ // eslint-disable-next-line no-console
+ console.log('[Sentry SolidStart Plugin] Enabling source map generation');
+ if (!sourceMapsUploadOptions?.filesToDeleteAfterUpload) {
+ // eslint-disable-next-line no-console
+ console.warn(
+ `[Sentry SolidStart PLugin] We recommend setting the \`sourceMapsUploadOptions.filesToDeleteAfterUpload\` option to clean up source maps after uploading.
+[Sentry SolidStart Plugin] Otherwise, source maps might be deployed to production, depending on your configuration`,
+ );
+ }
+ }
+ return {
+ ...config,
+ build: {
+ ...config.build,
+ sourcemap: true,
+ },
+ };
+ },
+ },
+ ...sentryVitePlugin({
+ authToken: authToken ?? process.env.SENTRY_AUTH_TOKEN,
+ bundleSizeOptimizations: options.bundleSizeOptimizations,
+ debug: debug ?? false,
+ org: org ?? process.env.SENTRY_ORG,
+ project: project ?? process.env.SENTRY_PROJECT,
+ sourcemaps: {
+ filesToDeleteAfterUpload: sourceMapsUploadOptions?.filesToDeleteAfterUpload ?? undefined,
+ ...sourceMapsUploadOptions?.unstable_sentryVitePluginOptions?.sourcemaps,
+ },
+ telemetry: sourceMapsUploadOptions?.telemetry ?? true,
+ _metaOptions: {
+ telemetry: {
+ metaFramework: 'solidstart',
+ },
+ },
+ ...sourceMapsUploadOptions?.unstable_sentryVitePluginOptions,
+ }),
+ ];
+}
diff --git a/packages/solidstart/src/vite/types.ts b/packages/solidstart/src/vite/types.ts
new file mode 100644
index 000000000000..4a64e4856b5d
--- /dev/null
+++ b/packages/solidstart/src/vite/types.ts
@@ -0,0 +1,128 @@
+import type { SentryVitePluginOptions } from '@sentry/vite-plugin';
+
+type SourceMapsOptions = {
+ /**
+ * If this flag is `true`, and an auth token is detected, the Sentry SDK will
+ * automatically generate and upload source maps to Sentry during a production build.
+ *
+ * @default true
+ */
+ enabled?: boolean;
+
+ /**
+ * If this flag is `true`, the Sentry plugin will collect some telemetry data and send it to Sentry.
+ * It will not collect any sensitive or user-specific data.
+ *
+ * @default true
+ */
+ telemetry?: boolean;
+
+ /**
+ * A glob or an array of globs that specifies the build artifacts that should be deleted after the artifact
+ * upload to Sentry has been completed.
+ *
+ * @default [] - By default no files are deleted.
+ *
+ * The globbing patterns follow the implementation of the glob package. (https://www.npmjs.com/package/glob)
+ */
+ filesToDeleteAfterUpload?: string | Array;
+
+ /**
+ * Options to further customize the Sentry Vite Plugin (@sentry/vite-plugin) behavior directly.
+ * Options specified in this object take precedence over the options specified in
+ * the `sourcemaps` and `release` objects.
+ *
+ * @see https://www.npmjs.com/package/@sentry/vite-plugin/v/2.22.2#options which lists all available options.
+ *
+ * Warning: Options within this object are subject to change at any time.
+ * We DO NOT guarantee semantic versioning for these options, meaning breaking
+ * changes can occur at any time within a major SDK version.
+ *
+ * Furthermore, some options are untested with SvelteKit specifically. Use with caution.
+ */
+ unstable_sentryVitePluginOptions?: Partial;
+};
+
+type BundleSizeOptimizationOptions = {
+ /**
+ * If set to `true`, the plugin will attempt to tree-shake (remove) any debugging code within the Sentry SDK.
+ * Note that the success of this depends on tree shaking being enabled in your build tooling.
+ *
+ * Setting this option to `true` will disable features like the SDK's `debug` option.
+ */
+ excludeDebugStatements?: boolean;
+
+ /**
+ * If set to true, the plugin will try to tree-shake tracing statements out.
+ * Note that the success of this depends on tree shaking generally being enabled in your build.
+ * Attention: DO NOT enable this when you're using any performance monitoring-related SDK features (e.g. Sentry.startSpan()).
+ */
+ excludeTracing?: boolean;
+
+ /**
+ * If set to `true`, the plugin will attempt to tree-shake (remove) code related to the Sentry SDK's Session Replay Shadow DOM recording functionality.
+ * Note that the success of this depends on tree shaking being enabled in your build tooling.
+ *
+ * This option is safe to be used when you do not want to capture any Shadow DOM activity via Sentry Session Replay.
+ */
+ excludeReplayShadowDom?: boolean;
+
+ /**
+ * If set to `true`, the plugin will attempt to tree-shake (remove) code related to the Sentry SDK's Session Replay `iframe` recording functionality.
+ * Note that the success of this depends on tree shaking being enabled in your build tooling.
+ *
+ * You can safely do this when you do not want to capture any `iframe` activity via Sentry Session Replay.
+ */
+ excludeReplayIframe?: boolean;
+
+ /**
+ * If set to `true`, the plugin will attempt to tree-shake (remove) code related to the Sentry SDK's Session Replay's Compression Web Worker.
+ * Note that the success of this depends on tree shaking being enabled in your build tooling.
+ *
+ * **Notice:** You should only do use this option if you manually host a compression worker and configure it in your Sentry Session Replay integration config via the `workerUrl` option.
+ */
+ excludeReplayWorker?: boolean;
+};
+
+/**
+ * Build options for the Sentry module. These options are used during build-time by the Sentry SDK.
+ */
+export type SentrySolidStartPluginOptions = {
+ /**
+ * The auth token to use when uploading source maps to Sentry.
+ *
+ * Instead of specifying this option, you can also set the `SENTRY_AUTH_TOKEN` environment variable.
+ *
+ * To create an auth token, follow this guide:
+ * @see https://docs.sentry.io/product/accounts/auth-tokens/#organization-auth-tokens
+ */
+ authToken?: string;
+
+ /**
+ * The organization slug of your Sentry organization.
+ * Instead of specifying this option, you can also set the `SENTRY_ORG` environment variable.
+ */
+ org?: string;
+
+ /**
+ * The project slug of your Sentry project.
+ * Instead of specifying this option, you can also set the `SENTRY_PROJECT` environment variable.
+ */
+ project?: string;
+
+ /**
+ * Options for the Sentry Vite plugin to customize the source maps upload process.
+ */
+ sourceMapsUploadOptions?: SourceMapsOptions;
+
+ /**
+ * Options for the Sentry Vite plugin to customize bundle size optimizations.
+ */
+ bundleSizeOptimizations?: BundleSizeOptimizationOptions;
+
+ /**
+ * Enable debug functionality of the SDK during build-time.
+ * Enabling this will give you, for example logs about source maps.
+ */
+ debug?: boolean;
+};
diff --git a/packages/solidstart/test/client/sdk.test.ts b/packages/solidstart/test/client/sdk.test.ts
index 886bb29b515d..b242e03ceb70 100644
--- a/packages/solidstart/test/client/sdk.test.ts
+++ b/packages/solidstart/test/client/sdk.test.ts
@@ -3,6 +3,7 @@ import * as SentrySolid from '@sentry/solid';
import { vi } from 'vitest';
import { init as solidStartInit } from '../../src/client';
+import { solidRouterBrowserTracingIntegration } from '../../src/client/solidrouter';
const browserInit = vi.spyOn(SentrySolid, 'init');
@@ -34,3 +35,47 @@ describe('Initialize Solid Start SDK', () => {
expect(browserInit).toHaveBeenLastCalledWith(expect.objectContaining(expectedMetadata));
});
});
+
+describe('browserTracingIntegration', () => {
+ it('adds the `browserTracingIntegration` when `__SENTRY_TRACING__` is not set', () => {
+ const client = solidStartInit({
+ dsn: 'https://public@dsn.ingest.sentry.io/1337',
+ });
+
+ const browserTracingIntegration = client
+ ?.getOptions()
+ .integrations.find(integration => integration.name === 'BrowserTracing');
+ expect(browserTracingIntegration).toBeDefined();
+ expect(browserTracingIntegration!.isDefaultInstance).toEqual(true);
+ });
+
+ it("doesn't add the `browserTracingIntegration` if `__SENTRY_TRACING__` is false", () => {
+ // @ts-expect-error Test setup for build-time flag
+ globalThis.__SENTRY_TRACING__ = false;
+
+ const client = solidStartInit({
+ dsn: 'https://public@dsn.ingest.sentry.io/1337',
+ });
+
+ const browserTracingIntegration = client
+ ?.getOptions()
+ .integrations.find(integration => integration.name === 'BrowserTracing');
+ expect(browserTracingIntegration).toBeUndefined();
+
+ // @ts-expect-error Test setup for build-time flag
+ delete globalThis.__SENTRY_TRACING__;
+ });
+
+ it("doesn't add the default `browserTracingIntegration` if `solidBrowserTracingIntegration` was already passed in", () => {
+ const client = solidStartInit({
+ integrations: [solidRouterBrowserTracingIntegration()],
+ dsn: 'https://public@dsn.ingest.sentry.io/1337',
+ });
+
+ const browserTracingIntegration = client
+ ?.getOptions()
+ .integrations.find(integration => integration.name === 'BrowserTracing');
+ expect(browserTracingIntegration).toBeDefined();
+ expect(browserTracingIntegration!.isDefaultInstance).toBeUndefined();
+ });
+});
diff --git a/packages/solidstart/test/server/withServerActionInstrumentation.test.ts b/packages/solidstart/test/server/withServerActionInstrumentation.test.ts
index 9a5b1e0c2b51..7e1686e2ccb1 100644
--- a/packages/solidstart/test/server/withServerActionInstrumentation.test.ts
+++ b/packages/solidstart/test/server/withServerActionInstrumentation.test.ts
@@ -10,7 +10,6 @@ import {
spanToJSON,
} from '@sentry/node';
import { NodeClient } from '@sentry/node';
-import { solidRouterBrowserTracingIntegration } from '@sentry/solidstart/solidrouter';
import { redirect } from '@solidjs/router';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
@@ -98,7 +97,6 @@ describe('withServerActionInstrumentation', () => {
setCurrentClient(client);
client.on('spanStart', span => spanStartMock(spanToJSON(span)));
- client.addIntegration(solidRouterBrowserTracingIntegration());
await serverActionGetPrefecture();
expect(spanStartMock).toHaveBeenCalledWith(
diff --git a/packages/solidstart/test/vite/sentrySolidStartVite.test.ts b/packages/solidstart/test/vite/sentrySolidStartVite.test.ts
new file mode 100644
index 000000000000..d3f905313859
--- /dev/null
+++ b/packages/solidstart/test/vite/sentrySolidStartVite.test.ts
@@ -0,0 +1,50 @@
+import type { Plugin } from 'vite';
+import { describe, expect, it, vi } from 'vitest';
+import { sentrySolidStartVite } from '../../src/vite/sentrySolidStartVite';
+
+vi.spyOn(console, 'log').mockImplementation(() => {
+ /* noop */
+});
+vi.spyOn(console, 'warn').mockImplementation(() => {
+ /* noop */
+});
+
+function getSentrySolidStartVitePlugins(options?: Parameters[0]): Plugin[] {
+ return sentrySolidStartVite({
+ project: 'project',
+ org: 'org',
+ authToken: 'token',
+ ...options,
+ });
+}
+
+describe('sentrySolidStartVite()', () => {
+ it('returns an array of vite plugins', () => {
+ const plugins = getSentrySolidStartVitePlugins();
+ const names = plugins.map(plugin => plugin.name);
+ expect(names).toEqual([
+ 'sentry-solidstart-source-maps',
+ 'sentry-telemetry-plugin',
+ 'sentry-vite-release-injection-plugin',
+ 'sentry-debug-id-upload-plugin',
+ 'sentry-vite-debug-id-injection-plugin',
+ 'sentry-vite-debug-id-upload-plugin',
+ 'sentry-file-deletion-plugin',
+ ]);
+ });
+
+ it("returns an empty array if source maps upload isn't enabled", () => {
+ const plugins = getSentrySolidStartVitePlugins({ sourceMapsUploadOptions: { enabled: false } });
+ expect(plugins).toHaveLength(0);
+ });
+
+ it('returns an empty array if `NODE_ENV` is development', async () => {
+ const previousEnv = process.env.NODE_ENV;
+ process.env.NODE_ENV = 'development';
+
+ const plugins = getSentrySolidStartVitePlugins({ sourceMapsUploadOptions: { enabled: true } });
+ expect(plugins).toHaveLength(0);
+
+ process.env.NODE_ENV = previousEnv;
+ });
+});
diff --git a/packages/solidstart/test/vite/sourceMaps.test.ts b/packages/solidstart/test/vite/sourceMaps.test.ts
new file mode 100644
index 000000000000..e7d6c1bd598d
--- /dev/null
+++ b/packages/solidstart/test/vite/sourceMaps.test.ts
@@ -0,0 +1,96 @@
+import type { SentryVitePluginOptions } from '@sentry/vite-plugin';
+import { beforeEach, describe, expect, it, vi } from 'vitest';
+import { makeSourceMapsVitePlugin } from '../../src/vite/sourceMaps';
+
+const mockedSentryVitePlugin = {
+ name: 'sentry-vite-debug-id-upload-plugin',
+ writeBundle: vi.fn(),
+};
+
+const sentryVitePluginSpy = vi.fn((_options: SentryVitePluginOptions) => [mockedSentryVitePlugin]);
+
+vi.mock('@sentry/vite-plugin', async () => {
+ const original = (await vi.importActual('@sentry/vite-plugin')) as any;
+
+ return {
+ ...original,
+ sentryVitePlugin: (options: SentryVitePluginOptions) => sentryVitePluginSpy(options),
+ };
+});
+
+beforeEach(() => {
+ vi.clearAllMocks();
+});
+
+describe('makeSourceMapsVitePlugin()', () => {
+ it('returns a plugin to set `sourcemaps` to `true`', () => {
+ const [sourceMapsConfigPlugin, sentryVitePlugin] = makeSourceMapsVitePlugin({});
+
+ expect(sourceMapsConfigPlugin?.name).toEqual('sentry-solidstart-source-maps');
+ expect(sourceMapsConfigPlugin?.apply).toEqual('build');
+ expect(sourceMapsConfigPlugin?.enforce).toEqual('post');
+ expect(sourceMapsConfigPlugin?.config).toEqual(expect.any(Function));
+
+ expect(sentryVitePlugin).toEqual(mockedSentryVitePlugin);
+ });
+
+ it('passes user-specified vite plugin options to vite plugin plugin', () => {
+ makeSourceMapsVitePlugin({
+ org: 'my-org',
+ authToken: 'my-token',
+ sourceMapsUploadOptions: {
+ filesToDeleteAfterUpload: ['baz/*.js'],
+ },
+ bundleSizeOptimizations: {
+ excludeTracing: true,
+ },
+ });
+
+ expect(sentryVitePluginSpy).toHaveBeenCalledWith(
+ expect.objectContaining({
+ org: 'my-org',
+ authToken: 'my-token',
+ sourcemaps: {
+ filesToDeleteAfterUpload: ['baz/*.js'],
+ },
+ bundleSizeOptimizations: {
+ excludeTracing: true,
+ },
+ }),
+ );
+ });
+
+ it('should override options with unstable_sentryVitePluginOptions', () => {
+ makeSourceMapsVitePlugin({
+ org: 'my-org',
+ authToken: 'my-token',
+ bundleSizeOptimizations: {
+ excludeTracing: true,
+ },
+ sourceMapsUploadOptions: {
+ unstable_sentryVitePluginOptions: {
+ org: 'unstable-org',
+ sourcemaps: {
+ assets: ['unstable/*.js'],
+ },
+ bundleSizeOptimizations: {
+ excludeTracing: false,
+ },
+ },
+ },
+ });
+
+ expect(sentryVitePluginSpy).toHaveBeenCalledWith(
+ expect.objectContaining({
+ org: 'unstable-org',
+ authToken: 'my-token',
+ bundleSizeOptimizations: {
+ excludeTracing: false,
+ },
+ sourcemaps: {
+ assets: ['unstable/*.js'],
+ },
+ }),
+ );
+ });
+});
diff --git a/packages/sveltekit/src/server/index.ts b/packages/sveltekit/src/server/index.ts
index 32dd6627d7a6..d57ec35bd7cc 100644
--- a/packages/sveltekit/src/server/index.ts
+++ b/packages/sveltekit/src/server/index.ts
@@ -37,6 +37,7 @@ export {
fastifyIntegration,
flush,
functionToStringIntegration,
+ genericPoolIntegration,
generateInstrumentOnce,
getActiveSpan,
getAutoPerformanceIntegrations,
diff --git a/packages/utils/src/logger.ts b/packages/utils/src/logger.ts
index e996d87202b2..533b59fd5882 100644
--- a/packages/utils/src/logger.ts
+++ b/packages/utils/src/logger.ts
@@ -1,7 +1,7 @@
import type { ConsoleLevel } from '@sentry/types';
import { DEBUG_BUILD } from './debug-build';
-import { GLOBAL_OBJ } from './worldwide';
+import { GLOBAL_OBJ, getGlobalSingleton } from './worldwide';
/** Prefix for logging strings */
const PREFIX = 'Sentry Logger ';
@@ -97,4 +97,8 @@ function makeLogger(): Logger {
return logger as Logger;
}
-export const logger = makeLogger();
+/**
+ * This is a logger singleton which either logs things or no-ops if logging is not enabled.
+ * The logger is a singleton on the carrier, to ensure that a consistent logger is used throughout the SDK.
+ */
+export const logger = getGlobalSingleton('logger', makeLogger);
diff --git a/packages/utils/src/worldwide.ts b/packages/utils/src/worldwide.ts
index e323f12034a2..2a1ca7b958d8 100644
--- a/packages/utils/src/worldwide.ts
+++ b/packages/utils/src/worldwide.ts
@@ -15,6 +15,7 @@
import type { Client, MetricsAggregator, Scope } from '@sentry/types';
import type { SdkSource } from './env';
+import type { logger } from './logger';
import { SDK_VERSION } from './version';
interface SentryCarrier {
@@ -25,6 +26,7 @@ interface SentryCarrier {
defaultIsolationScope?: Scope;
defaultCurrentScope?: Scope;
globalMetricsAggregators?: WeakMap | undefined;
+ logger?: typeof logger;
/** Overwrites TextEncoder used in `@sentry/utils`, need for `react-native@0.73` and older */
encodePolyfill?: (input: string) => Uint8Array;
diff --git a/packages/vue/src/tracing.ts b/packages/vue/src/tracing.ts
index 70f662559adf..135b7fa8c9cc 100644
--- a/packages/vue/src/tracing.ts
+++ b/packages/vue/src/tracing.ts
@@ -114,6 +114,8 @@ export const createTracingMixins = (options: TracingOptions): Mixins => {
attributes: {
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.vue',
},
+ // UI spans should only be created if there is an active root span (transaction)
+ onlyIfParent: true,
});
}
} else {
diff --git a/yarn.lock b/yarn.lock
index 6f2432d7054a..246bb480abd9 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7004,6 +7004,13 @@
dependencies:
"@opentelemetry/api" "^1.0.0"
+"@opentelemetry/api-logs@0.53.0":
+ version "0.53.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/api-logs/-/api-logs-0.53.0.tgz#c478cbd8120ec2547b64edfa03a552cfe42170be"
+ integrity sha512-8HArjKx+RaAI8uEIgcORbZIPklyh1YLjPSBus8hjRmvLi6DeFzgOcdZ7KwPabKj8mXF8dX0hyfAyGfycz0DbFw==
+ dependencies:
+ "@opentelemetry/api" "^1.0.0"
+
"@opentelemetry/api@^0.12.0":
version "0.12.0"
resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-0.12.0.tgz#0359c3926e8f16fdcd8c78f196bd1e9fc4e66777"
@@ -7047,6 +7054,13 @@
dependencies:
"@opentelemetry/semantic-conventions" "1.25.1"
+"@opentelemetry/core@1.26.0":
+ version "1.26.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.26.0.tgz#7d84265aaa850ed0ca5813f97d831155be42b328"
+ integrity sha512-1iKxXXE8415Cdv0yjG3G6hQnB5eVEsJce3QaawX8SjDn0mAS0ZM8fAbZZJD4ajvhC15cePvosSCut404KrIIvQ==
+ dependencies:
+ "@opentelemetry/semantic-conventions" "1.27.0"
+
"@opentelemetry/core@^0.12.0":
version "0.12.0"
resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-0.12.0.tgz#a888badc9a408fa1f13976a574e69d14be32488e"
@@ -7056,178 +7070,185 @@
"@opentelemetry/context-base" "^0.12.0"
semver "^7.1.3"
-"@opentelemetry/instrumentation-aws-lambda@0.43.0":
- version "0.43.0"
- resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-aws-lambda/-/instrumentation-aws-lambda-0.43.0.tgz#6a96d582627873bb34d197655b7b69792f0f8da3"
- integrity sha512-pSxcWlsE/pCWQRIw92sV2C+LmKXelYkjkA7C5s39iPUi4pZ2lA1nIiw+1R/y2pDEhUHcaKkNyljQr3cx9ZpVlQ==
+"@opentelemetry/instrumentation-aws-lambda@0.44.0":
+ version "0.44.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-aws-lambda/-/instrumentation-aws-lambda-0.44.0.tgz#9b82bd6cc86f572be837578b29ef6bf242eb1a39"
+ integrity sha512-6vmr7FJIuopZzsQjEQTp4xWtF6kBp7DhD7pPIN8FN0dKUKyuVraABIpgWjMfelaUPy4rTYUGkYqPluhG0wx8Dw==
dependencies:
- "@opentelemetry/instrumentation" "^0.52.0"
+ "@opentelemetry/instrumentation" "^0.53.0"
"@opentelemetry/propagator-aws-xray" "^1.3.1"
"@opentelemetry/resources" "^1.8.0"
- "@opentelemetry/semantic-conventions" "^1.22.0"
- "@types/aws-lambda" "8.10.122"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
+ "@types/aws-lambda" "8.10.143"
-"@opentelemetry/instrumentation-aws-sdk@0.43.1":
- version "0.43.1"
- resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-aws-sdk/-/instrumentation-aws-sdk-0.43.1.tgz#b7cb8601061d57a9290cad8c499bda135ba3ba2c"
- integrity sha512-qLT2cCniJ5W+6PFzKbksnoIQuq9pS83nmgaExfUwXVvlwi0ILc50dea0tWBHZMkdIDa/zZdcuFrJ7+fUcSnRow==
+"@opentelemetry/instrumentation-aws-sdk@0.44.0":
+ version "0.44.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-aws-sdk/-/instrumentation-aws-sdk-0.44.0.tgz#f1a2d8c186d37fae42954921bbdcc3555aac331c"
+ integrity sha512-HIWFg4TDQsayceiikOnruMmyQ0SZYW6WiR+wknWwWVLHC3lHTCpAnqzp5V42ckArOdlwHZu2Jvq2GMSM4Myx3w==
dependencies:
"@opentelemetry/core" "^1.8.0"
- "@opentelemetry/instrumentation" "^0.52.0"
- "@opentelemetry/propagation-utils" "^0.30.10"
- "@opentelemetry/semantic-conventions" "^1.22.0"
+ "@opentelemetry/instrumentation" "^0.53.0"
+ "@opentelemetry/propagation-utils" "^0.30.11"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
-"@opentelemetry/instrumentation-connect@0.38.0":
- version "0.38.0"
- resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.38.0.tgz#1f4aa27894eac2538fb3c8fce7b1be92cae0217e"
- integrity sha512-2/nRnx3pjYEmdPIaBwtgtSviTKHWnDZN3R+TkRUnhIVrvBKVcq+I5B2rtd6mr6Fe9cHlZ9Ojcuh7pkNh/xdWWg==
+"@opentelemetry/instrumentation-connect@0.39.0":
+ version "0.39.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.39.0.tgz#32bdbaac464cba061c95df6c850ee81efdd86f8b"
+ integrity sha512-pGBiKevLq7NNglMgqzmeKczF4XQMTOUOTkK8afRHMZMnrK3fcETyTH7lVaSozwiOM3Ws+SuEmXZT7DYrrhxGlg==
dependencies:
"@opentelemetry/core" "^1.8.0"
- "@opentelemetry/instrumentation" "^0.52.0"
- "@opentelemetry/semantic-conventions" "^1.22.0"
+ "@opentelemetry/instrumentation" "^0.53.0"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
"@types/connect" "3.4.36"
-"@opentelemetry/instrumentation-express@0.41.1":
- version "0.41.1"
- resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-express/-/instrumentation-express-0.41.1.tgz#658561df6ffbae86f5ad33e8d7ef2abb7b4967fc"
- integrity sha512-uRx0V3LPGzjn2bxAnV8eUsDT82vT7NTwI0ezEuPMBOTOsnPpGhWdhcdNdhH80sM4TrWrOfXm9HGEdfWE3TRIww==
+"@opentelemetry/instrumentation-express@0.42.0":
+ version "0.42.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-express/-/instrumentation-express-0.42.0.tgz#279f195aa66baee2b98623a16666c6229c8e7564"
+ integrity sha512-YNcy7ZfGnLsVEqGXQPT+S0G1AE46N21ORY7i7yUQyfhGAL4RBjnZUqefMI0NwqIl6nGbr1IpF0rZGoN8Q7x12Q==
dependencies:
"@opentelemetry/core" "^1.8.0"
- "@opentelemetry/instrumentation" "^0.52.0"
- "@opentelemetry/semantic-conventions" "^1.22.0"
+ "@opentelemetry/instrumentation" "^0.53.0"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
-"@opentelemetry/instrumentation-fastify@0.38.0":
- version "0.38.0"
- resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-fastify/-/instrumentation-fastify-0.38.0.tgz#0cb02ee1156197075e8a90e4fd18a6b6c94221ba"
- integrity sha512-HBVLpTSYpkQZ87/Df3N0gAw7VzYZV3n28THIBrJWfuqw3Or7UqdhnjeuMIPQ04BKk3aZc0cWn2naSQObbh5vXw==
+"@opentelemetry/instrumentation-fastify@0.39.0":
+ version "0.39.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-fastify/-/instrumentation-fastify-0.39.0.tgz#96a040e4944daf77c53a8fe5a128bc3b2568e4aa"
+ integrity sha512-SS9uSlKcsWZabhBp2szErkeuuBDgxOUlllwkS92dVaWRnMmwysPhcEgHKB8rUe3BHg/GnZC1eo1hbTZv4YhfoA==
dependencies:
"@opentelemetry/core" "^1.8.0"
- "@opentelemetry/instrumentation" "^0.52.0"
- "@opentelemetry/semantic-conventions" "^1.22.0"
+ "@opentelemetry/instrumentation" "^0.53.0"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
-"@opentelemetry/instrumentation-fs@0.14.0":
- version "0.14.0"
- resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.14.0.tgz#19f1cb38a8c2d05f3b96af67f1c8d43f0af2829b"
- integrity sha512-pVc8P5AgliC1DphyyBUgsxXlm2XaPH4BpYvt7rAZDMIqUpRk8gs19SioABtKqqxvFzg5jPtgJfJsdxq0Y+maLw==
+"@opentelemetry/instrumentation-fs@0.15.0":
+ version "0.15.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.15.0.tgz#41658507860f39fee5209bca961cea8d24ca2a83"
+ integrity sha512-JWVKdNLpu1skqZQA//jKOcKdJC66TWKqa2FUFq70rKohvaSq47pmXlnabNO+B/BvLfmidfiaN35XakT5RyMl2Q==
dependencies:
"@opentelemetry/core" "^1.8.0"
- "@opentelemetry/instrumentation" "^0.52.0"
+ "@opentelemetry/instrumentation" "^0.53.0"
-"@opentelemetry/instrumentation-graphql@0.42.0":
- version "0.42.0"
- resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.42.0.tgz#588a18c39e3b3f655bc09243566172ab0b638d35"
- integrity sha512-N8SOwoKL9KQSX7z3gOaw5UaTeVQcfDO1c21csVHnmnmGUoqsXbArK2B8VuwPWcv6/BC/i3io+xTo7QGRZ/z28Q==
+"@opentelemetry/instrumentation-generic-pool@0.39.0":
+ version "0.39.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.39.0.tgz#2b9af16ad82d5cbe67125c0125753cecd162a728"
+ integrity sha512-y4v8Y+tSfRB3NNBvHjbjrn7rX/7sdARG7FuK6zR8PGb28CTa0kHpEGCJqvL9L8xkTNvTXo+lM36ajFGUaK1aNw==
dependencies:
- "@opentelemetry/instrumentation" "^0.52.0"
+ "@opentelemetry/instrumentation" "^0.53.0"
-"@opentelemetry/instrumentation-hapi@0.40.0":
- version "0.40.0"
- resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.40.0.tgz#ae11190f0f57cdb4dc8d792cb8bca61e5343684c"
- integrity sha512-8U/w7Ifumtd2bSN1OLaSwAAFhb9FyqWUki3lMMB0ds+1+HdSxYBe9aspEJEgvxAqOkrQnVniAPTEGf1pGM7SOw==
+"@opentelemetry/instrumentation-graphql@0.43.0":
+ version "0.43.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.43.0.tgz#71bb94ea775c70dbd388c739b397ec1418f3f170"
+ integrity sha512-aI3YMmC2McGd8KW5du1a2gBA0iOMOGLqg4s9YjzwbjFwjlmMNFSK1P3AIg374GWg823RPUGfVTIgZ/juk9CVOA==
+ dependencies:
+ "@opentelemetry/instrumentation" "^0.53.0"
+
+"@opentelemetry/instrumentation-hapi@0.41.0":
+ version "0.41.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.41.0.tgz#de8711907256d8fae1b5faf71fc825cef4a7ddbb"
+ integrity sha512-jKDrxPNXDByPlYcMdZjNPYCvw0SQJjN+B1A+QH+sx+sAHsKSAf9hwFiJSrI6C4XdOls43V/f/fkp9ITkHhKFbQ==
dependencies:
"@opentelemetry/core" "^1.8.0"
- "@opentelemetry/instrumentation" "^0.52.0"
- "@opentelemetry/semantic-conventions" "^1.22.0"
+ "@opentelemetry/instrumentation" "^0.53.0"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
-"@opentelemetry/instrumentation-http@0.52.1":
- version "0.52.1"
- resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-http/-/instrumentation-http-0.52.1.tgz#12061501601838d1c912f9c29bdd40a13a7e44cf"
- integrity sha512-dG/aevWhaP+7OLv4BQQSEKMJv8GyeOp3Wxl31NHqE8xo9/fYMfEljiZphUHIfyg4gnZ9swMyWjfOQs5GUQe54Q==
+"@opentelemetry/instrumentation-http@0.53.0":
+ version "0.53.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-http/-/instrumentation-http-0.53.0.tgz#0d806adf1b3aba036bc46e16162e3c0dbb8a6b60"
+ integrity sha512-H74ErMeDuZfj7KgYCTOFGWF5W9AfaPnqLQQxeFq85+D29wwV2yqHbz2IKLYpkOh7EI6QwDEl7rZCIxjJLyc/CQ==
dependencies:
- "@opentelemetry/core" "1.25.1"
- "@opentelemetry/instrumentation" "0.52.1"
- "@opentelemetry/semantic-conventions" "1.25.1"
+ "@opentelemetry/core" "1.26.0"
+ "@opentelemetry/instrumentation" "0.53.0"
+ "@opentelemetry/semantic-conventions" "1.27.0"
semver "^7.5.2"
-"@opentelemetry/instrumentation-ioredis@0.42.0":
- version "0.42.0"
- resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.42.0.tgz#0f488ffc68af3caa474e2f67861759075170729c"
- integrity sha512-P11H168EKvBB9TUSasNDOGJCSkpT44XgoM6d3gRIWAa9ghLpYhl0uRkS8//MqPzcJVHr3h3RmfXIpiYLjyIZTw==
+"@opentelemetry/instrumentation-ioredis@0.43.0":
+ version "0.43.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.43.0.tgz#dbadabaeefc4cb47c406f878444f1bcac774fa89"
+ integrity sha512-i3Dke/LdhZbiUAEImmRG3i7Dimm/BD7t8pDDzwepSvIQ6s2X6FPia7561gw+64w+nx0+G9X14D7rEfaMEmmjig==
dependencies:
- "@opentelemetry/instrumentation" "^0.52.0"
+ "@opentelemetry/instrumentation" "^0.53.0"
"@opentelemetry/redis-common" "^0.36.2"
- "@opentelemetry/semantic-conventions" "^1.23.0"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
-"@opentelemetry/instrumentation-koa@0.42.0":
- version "0.42.0"
- resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.42.0.tgz#1c180f3605448c2e57a4ba073b69ffba7b2970b3"
- integrity sha512-H1BEmnMhho8o8HuNRq5zEI4+SIHDIglNB7BPKohZyWG4fWNuR7yM4GTlR01Syq21vODAS7z5omblScJD/eZdKw==
+"@opentelemetry/instrumentation-koa@0.43.0":
+ version "0.43.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.43.0.tgz#963fd192a1b5f6cbae5dabf4ec82e3105cbb23b1"
+ integrity sha512-lDAhSnmoTIN6ELKmLJBplXzT/Jqs5jGZehuG22EdSMaTwgjMpxMDI1YtlKEhiWPWkrz5LUsd0aOO0ZRc9vn3AQ==
dependencies:
"@opentelemetry/core" "^1.8.0"
- "@opentelemetry/instrumentation" "^0.52.0"
- "@opentelemetry/semantic-conventions" "^1.22.0"
+ "@opentelemetry/instrumentation" "^0.53.0"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
-"@opentelemetry/instrumentation-mongodb@0.46.0":
- version "0.46.0"
- resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.46.0.tgz#e3720e8ca3ca9f228fbf02f0812f7518c030b05e"
- integrity sha512-VF/MicZ5UOBiXrqBslzwxhN7TVqzu1/LN/QDpkskqM0Zm0aZ4CVRbUygL8d7lrjLn15x5kGIe8VsSphMfPJzlA==
+"@opentelemetry/instrumentation-mongodb@0.47.0":
+ version "0.47.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.47.0.tgz#f8107d878281433905e717f223fb4c0f10356a7b"
+ integrity sha512-yqyXRx2SulEURjgOQyJzhCECSh5i1uM49NUaq9TqLd6fA7g26OahyJfsr9NE38HFqGRHpi4loyrnfYGdrsoVjQ==
dependencies:
- "@opentelemetry/instrumentation" "^0.52.0"
+ "@opentelemetry/instrumentation" "^0.53.0"
"@opentelemetry/sdk-metrics" "^1.9.1"
- "@opentelemetry/semantic-conventions" "^1.22.0"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
-"@opentelemetry/instrumentation-mongoose@0.40.0":
- version "0.40.0"
- resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.40.0.tgz#9c888312e524c381bfdf56a094c799150332dd51"
- integrity sha512-niRi5ZUnkgzRhIGMOozTyoZIvJKNJyhijQI4nF4iFSb+FUx2v5fngfR+8XLmdQAO7xmsD8E5vEGdDVYVtKbZew==
+"@opentelemetry/instrumentation-mongoose@0.42.0":
+ version "0.42.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.42.0.tgz#375afd21adfcd897a8f521c1ffd2d91e6a428705"
+ integrity sha512-AnWv+RaR86uG3qNEMwt3plKX1ueRM7AspfszJYVkvkehiicC3bHQA6vWdb6Zvy5HAE14RyFbu9+2hUUjR2NSyg==
dependencies:
"@opentelemetry/core" "^1.8.0"
- "@opentelemetry/instrumentation" "^0.52.0"
- "@opentelemetry/semantic-conventions" "^1.22.0"
+ "@opentelemetry/instrumentation" "^0.53.0"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
-"@opentelemetry/instrumentation-mysql2@0.40.0":
- version "0.40.0"
- resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.40.0.tgz#fa2992c36d54427dccea68e5c69fff01103dabe6"
- integrity sha512-0xfS1xcqUmY7WE1uWjlmI67Xg3QsSUlNT+AcXHeA4BDUPwZtWqF4ezIwLgpVZfHOnkAEheqGfNSWd1PIu3Wnfg==
+"@opentelemetry/instrumentation-mysql2@0.41.0":
+ version "0.41.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.41.0.tgz#6377b6e2d2487fd88e1d79aa03658db6c8d51651"
+ integrity sha512-REQB0x+IzVTpoNgVmy5b+UnH1/mDByrneimP6sbDHkp1j8QOl1HyWOrBH/6YWR0nrbU3l825Em5PlybjT3232g==
dependencies:
- "@opentelemetry/instrumentation" "^0.52.0"
- "@opentelemetry/semantic-conventions" "^1.22.0"
+ "@opentelemetry/instrumentation" "^0.53.0"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
"@opentelemetry/sql-common" "^0.40.1"
-"@opentelemetry/instrumentation-mysql@0.40.0":
- version "0.40.0"
- resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.40.0.tgz#bde5894c8eb447a4b8e940b030b2b73898da03fa"
- integrity sha512-d7ja8yizsOCNMYIJt5PH/fKZXjb/mS48zLROO4BzZTtDfhNCl2UM/9VIomP2qkGIFVouSJrGr/T00EzY7bPtKA==
+"@opentelemetry/instrumentation-mysql@0.41.0":
+ version "0.41.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.41.0.tgz#2d50691ead5219774bd36d66c35d5b4681485dd7"
+ integrity sha512-jnvrV6BsQWyHS2qb2fkfbfSb1R/lmYwqEZITwufuRl37apTopswu9izc0b1CYRp/34tUG/4k/V39PND6eyiNvw==
dependencies:
- "@opentelemetry/instrumentation" "^0.52.0"
- "@opentelemetry/semantic-conventions" "^1.22.0"
- "@types/mysql" "2.15.22"
+ "@opentelemetry/instrumentation" "^0.53.0"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
+ "@types/mysql" "2.15.26"
-"@opentelemetry/instrumentation-nestjs-core@0.39.0":
- version "0.39.0"
- resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-nestjs-core/-/instrumentation-nestjs-core-0.39.0.tgz#733fef4306c796951d7ea1951b45f9df0aed234d"
- integrity sha512-mewVhEXdikyvIZoMIUry8eb8l3HUjuQjSjVbmLVTt4NQi35tkpnHQrG9bTRBrl3403LoWZ2njMPJyg4l6HfKvA==
+"@opentelemetry/instrumentation-nestjs-core@0.40.0":
+ version "0.40.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-nestjs-core/-/instrumentation-nestjs-core-0.40.0.tgz#2c0e6405b56caaec32747d55c57ff9a034668ea8"
+ integrity sha512-WF1hCUed07vKmf5BzEkL0wSPinqJgH7kGzOjjMAiTGacofNXjb/y4KQ8loj2sNsh5C/NN7s1zxQuCgbWbVTGKg==
dependencies:
- "@opentelemetry/instrumentation" "^0.52.0"
- "@opentelemetry/semantic-conventions" "^1.23.0"
+ "@opentelemetry/instrumentation" "^0.53.0"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
-"@opentelemetry/instrumentation-pg@0.43.0":
- version "0.43.0"
- resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.43.0.tgz#3cd94ad5144e1fd326a921280fa8bb7b49005eb5"
- integrity sha512-og23KLyoxdnAeFs1UWqzSonuCkePUzCX30keSYigIzJe/6WSYA8rnEI5lobcxPEzg+GcU06J7jzokuEHbjVJNw==
+"@opentelemetry/instrumentation-pg@0.44.0":
+ version "0.44.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.44.0.tgz#1e97a0aeb2dca068ee23ce75884a0a0063a7ce3f"
+ integrity sha512-oTWVyzKqXud1BYEGX1loo2o4k4vaU1elr3vPO8NZolrBtFvQ34nx4HgUaexUDuEog00qQt+MLR5gws/p+JXMLQ==
dependencies:
- "@opentelemetry/instrumentation" "^0.52.0"
- "@opentelemetry/semantic-conventions" "^1.22.0"
+ "@opentelemetry/instrumentation" "^0.53.0"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
"@opentelemetry/sql-common" "^0.40.1"
"@types/pg" "8.6.1"
- "@types/pg-pool" "2.0.4"
+ "@types/pg-pool" "2.0.6"
-"@opentelemetry/instrumentation-redis-4@0.41.0":
- version "0.41.0"
- resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-redis-4/-/instrumentation-redis-4-0.41.0.tgz#6c1b1a37c18478887f346a3bc7ef309ee9f726c0"
- integrity sha512-H7IfGTqW2reLXqput4yzAe8YpDC0fmVNal95GHMLOrS89W+qWUKIqxolSh63hJyfmwPSFwXASzj7wpSk8Az+Dg==
+"@opentelemetry/instrumentation-redis-4@0.42.0":
+ version "0.42.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-redis-4/-/instrumentation-redis-4-0.42.0.tgz#fc01104cfe884c7546385eaae03c57a47edd19d1"
+ integrity sha512-NaD+t2JNcOzX/Qa7kMy68JbmoVIV37fT/fJYzLKu2Wwd+0NCxt+K2OOsOakA8GVg8lSpFdbx4V/suzZZ2Pvdjg==
dependencies:
- "@opentelemetry/instrumentation" "^0.52.0"
+ "@opentelemetry/instrumentation" "^0.53.0"
"@opentelemetry/redis-common" "^0.36.2"
- "@opentelemetry/semantic-conventions" "^1.22.0"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
-"@opentelemetry/instrumentation@0.52.1", "@opentelemetry/instrumentation@^0.49 || ^0.50 || ^0.51 || ^0.52.0", "@opentelemetry/instrumentation@^0.52.0", "@opentelemetry/instrumentation@^0.52.1":
- version "0.52.1"
- resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz#2e7e46a38bd7afbf03cf688c862b0b43418b7f48"
- integrity sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==
+"@opentelemetry/instrumentation@0.53.0", "@opentelemetry/instrumentation@^0.53.0":
+ version "0.53.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz#e6369e4015eb5112468a4d45d38dcada7dad892d"
+ integrity sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==
dependencies:
- "@opentelemetry/api-logs" "0.52.1"
- "@types/shimmer" "^1.0.2"
+ "@opentelemetry/api-logs" "0.53.0"
+ "@types/shimmer" "^1.2.0"
import-in-the-middle "^1.8.1"
require-in-the-middle "^7.1.1"
semver "^7.5.2"
@@ -7255,6 +7276,18 @@
semver "^7.5.2"
shimmer "^1.2.1"
+"@opentelemetry/instrumentation@^0.49 || ^0.50 || ^0.51 || ^0.52.0", "@opentelemetry/instrumentation@^0.52.1":
+ version "0.52.1"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz#2e7e46a38bd7afbf03cf688c862b0b43418b7f48"
+ integrity sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==
+ dependencies:
+ "@opentelemetry/api-logs" "0.52.1"
+ "@types/shimmer" "^1.0.2"
+ import-in-the-middle "^1.8.1"
+ require-in-the-middle "^7.1.1"
+ semver "^7.5.2"
+ shimmer "^1.2.1"
+
"@opentelemetry/otlp-transformer@^0.50.0":
version "0.50.0"
resolved "https://registry.yarnpkg.com/@opentelemetry/otlp-transformer/-/otlp-transformer-0.50.0.tgz#211fe512fcce9d76042680f955336dbde3be03ef"
@@ -7267,10 +7300,10 @@
"@opentelemetry/sdk-metrics" "1.23.0"
"@opentelemetry/sdk-trace-base" "1.23.0"
-"@opentelemetry/propagation-utils@^0.30.10":
- version "0.30.10"
- resolved "https://registry.yarnpkg.com/@opentelemetry/propagation-utils/-/propagation-utils-0.30.10.tgz#d3074f7365efc62845928098bb15804aca47aaf0"
- integrity sha512-hhTW8pFp9PSyosYzzuUL9rdm7HF97w3OCyElufFHyUnYnKkCBbu8ne2LyF/KSdI/xZ81ubxWZs78hX4S7pLq5g==
+"@opentelemetry/propagation-utils@^0.30.11":
+ version "0.30.11"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/propagation-utils/-/propagation-utils-0.30.11.tgz#0a1c51cb4a2724fa41c41be07024bbb6f0aade46"
+ integrity sha512-rY4L/2LWNk5p/22zdunpqVmgz6uN419DsRTw5KFMa6u21tWhXS8devlMy4h8m8nnS20wM7r6yYweCNNKjgLYJw==
"@opentelemetry/propagator-aws-xray@^1.3.1":
version "1.25.1"
@@ -7370,11 +7403,16 @@
resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.0.tgz#390eb4d42a29c66bdc30066af9035645e9bb7270"
integrity sha512-M+kkXKRAIAiAP6qYyesfrC5TOmDpDVtsxuGfPcqd9B/iBrac+E14jYwrgm0yZBUIbIP2OnqC3j+UgkXLm1vxUQ==
-"@opentelemetry/semantic-conventions@1.25.1", "@opentelemetry/semantic-conventions@^1.17.0", "@opentelemetry/semantic-conventions@^1.22.0", "@opentelemetry/semantic-conventions@^1.23.0", "@opentelemetry/semantic-conventions@^1.25.1":
+"@opentelemetry/semantic-conventions@1.25.1", "@opentelemetry/semantic-conventions@^1.17.0", "@opentelemetry/semantic-conventions@^1.23.0", "@opentelemetry/semantic-conventions@^1.25.1":
version "1.25.1"
resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz#0deecb386197c5e9c2c28f2f89f51fb8ae9f145e"
integrity sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==
+"@opentelemetry/semantic-conventions@1.27.0", "@opentelemetry/semantic-conventions@^1.27.0":
+ version "1.27.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.27.0.tgz#1a857dcc95a5ab30122e04417148211e6f945e6c"
+ integrity sha512-sAay1RrB+ONOem0OZanAR1ZI/k7yDpnOQSQmTMuGImUQb2y8EbSaCJ94FQluM74xoU03vlb2d2U90hZluL6nQg==
+
"@opentelemetry/semantic-conventions@^0.12.0":
version "0.12.0"
resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-0.12.0.tgz#7e392aecdbdbd5d737d3995998b120dc17589ab0"
@@ -7525,10 +7563,10 @@
resolved "https://registry.yarnpkg.com/@prisma/client/-/client-5.9.1.tgz#d92bd2f7f006e0316cb4fda9d73f235965cf2c64"
integrity sha512-caSOnG4kxcSkhqC/2ShV7rEoWwd3XrftokxJqOCMVvia4NYV/TPtJlS9C2os3Igxw/Qyxumj9GBQzcStzECvtQ==
-"@prisma/instrumentation@5.18.0":
- version "5.18.0"
- resolved "https://registry.yarnpkg.com/@prisma/instrumentation/-/instrumentation-5.18.0.tgz#8b49e25bf3f8f756eb0c4c199b4cf8b6631db891"
- integrity sha512-r074avGkpPXItk+josQPhufZEmGhUCb16PQx4ITPS40vWTpTPET4VsgCBZB2alIN6SS7pRFod2vz2M2HHEEylQ==
+"@prisma/instrumentation@5.19.1":
+ version "5.19.1"
+ resolved "https://registry.yarnpkg.com/@prisma/instrumentation/-/instrumentation-5.19.1.tgz#146319cf85f22b7a43296f0f40cfeac55516e66e"
+ integrity sha512-VLnzMQq7CWroL5AeaW0Py2huiNKeoMfCH3SUxstdzPrlWQi6UQ9UrfcbUkNHlVFqOMacqy8X/8YtE0kuKDpD9w==
dependencies:
"@opentelemetry/api" "^1.8"
"@opentelemetry/instrumentation" "^0.49 || ^0.50 || ^0.51 || ^0.52.0"
@@ -8302,6 +8340,14 @@
"@sentry/cli-win32-i686" "2.33.1"
"@sentry/cli-win32-x64" "2.33.1"
+"@sentry/rollup-plugin@2.22.3":
+ version "2.22.3"
+ resolved "https://registry.yarnpkg.com/@sentry/rollup-plugin/-/rollup-plugin-2.22.3.tgz#18ab4b7903ee723bee4cf789b38bb3febb05faae"
+ integrity sha512-I1UsnYzZm5W7/Pyah2yxuMRxmzgf5iDKoptFfMaerpRO5oBhFO3tMnKSLAlYMvuXKRoYkInNv6ckkUcSOF6jig==
+ dependencies:
+ "@sentry/bundler-plugin-core" "2.22.3"
+ unplugin "1.0.1"
+
"@sentry/vite-plugin@2.22.3", "@sentry/vite-plugin@^2.22.3":
version "2.22.3"
resolved "https://registry.yarnpkg.com/@sentry/vite-plugin/-/vite-plugin-2.22.3.tgz#b52802412b6f3d8e3e56742afc9624d9babae5b6"
@@ -9190,7 +9236,12 @@
resolved "https://registry.yarnpkg.com/@types/array.prototype.flat/-/array.prototype.flat-1.2.1.tgz#5433a141730f8e1d7a8e7486458ceb8144ee5edc"
integrity sha512-JOvNJUU/zjfJWcA1aHDnCKHwQjZ7VQ3UNfbcMKXrkQKKyMkJHrQ9vpSVMhgsztrtsbIRJKazMDvg2QggFVwJqw==
-"@types/aws-lambda@8.10.122", "@types/aws-lambda@^8.10.62":
+"@types/aws-lambda@8.10.143":
+ version "8.10.143"
+ resolved "https://registry.yarnpkg.com/@types/aws-lambda/-/aws-lambda-8.10.143.tgz#383693fbaadc6994a71d64a7c09e8c244fad8dff"
+ integrity sha512-u5vzlcR14ge/4pMTTMDQr3MF0wEe38B2F9o84uC4F43vN5DGTy63npRrB6jQhyt+C0lGv4ZfiRcRkqJoZuPnmg==
+
+"@types/aws-lambda@^8.10.62":
version "8.10.122"
resolved "https://registry.yarnpkg.com/@types/aws-lambda/-/aws-lambda-8.10.122.tgz#206c8d71b09325d26a458dba27db842afdc54df1"
integrity sha512-vBkIh9AY22kVOCEKo5CJlyCgmSWvasC+SWUxL/x/vOwRobMpI/HG1xp/Ae3AqmSiZeLUbOhW0FCD3ZjqqUxmXw==
@@ -9839,7 +9890,14 @@
resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.32.tgz#f6cd08939ae3ad886fcc92ef7f0109dacddf61ab"
integrity sha512-xPSg0jm4mqgEkNhowKgZFBNtwoEwF6gJ4Dhww+GFpm3IgtNseHQZ5IqdNwnquZEoANxyDAKDRAdVo4Z72VvD/g==
-"@types/mysql@2.15.22", "@types/mysql@^2.15.21":
+"@types/mysql@2.15.26":
+ version "2.15.26"
+ resolved "https://registry.yarnpkg.com/@types/mysql/-/mysql-2.15.26.tgz#f0de1484b9e2354d587e7d2bd17a873cc8300836"
+ integrity sha512-DSLCOXhkvfS5WNNPbfn2KdICAmk8lLc+/PNvnPnF7gOdMZCxopXduqv0OQ13y/yA/zXTSikZZqVgybUxOEg6YQ==
+ dependencies:
+ "@types/node" "*"
+
+"@types/mysql@^2.15.21":
version "2.15.22"
resolved "https://registry.yarnpkg.com/@types/mysql/-/mysql-2.15.22.tgz#8705edb9872bf4aa9dbc004cd494e00334e5cdb4"
integrity sha512-wK1pzsJVVAjYCSZWQoWHziQZbNggXFDUEIGf54g4ZM/ERuP86uGdWeKZWMYlqTPMZfHJJvLPyogXGvCOg87yLQ==
@@ -9935,10 +9993,10 @@
resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-6.0.3.tgz#705bb349e789efa06f43f128cef51240753424cb"
integrity sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==
-"@types/pg-pool@2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@types/pg-pool/-/pg-pool-2.0.4.tgz#b5c60f678094ff3acf3442628a7f708928fcf263"
- integrity sha512-qZAvkv1K3QbmHHFYSNRYPkRjOWRLBYrL4B9c+wG0GSVGBw0NtJwPcgx/DSddeDJvRGMHCEQ4VMEVfuJ/0gZ3XQ==
+"@types/pg-pool@2.0.6":
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/@types/pg-pool/-/pg-pool-2.0.6.tgz#1376d9dc5aec4bb2ec67ce28d7e9858227403c77"
+ integrity sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ==
dependencies:
"@types/pg" "*"
@@ -10124,6 +10182,11 @@
resolved "https://registry.yarnpkg.com/@types/shimmer/-/shimmer-1.0.2.tgz#93eb2c243c351f3f17d5c580c7467ae5d686b65f"
integrity sha512-dKkr1bTxbEsFlh2ARpKzcaAmsYixqt9UyCdoEZk8rHyE4iQYcDCyvSjDSf7JUWJHlJiTtbIoQjxKh6ViywqDAg==
+"@types/shimmer@^1.2.0":
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/@types/shimmer/-/shimmer-1.2.0.tgz#9b706af96fa06416828842397a70dfbbf1c14ded"
+ integrity sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==
+
"@types/sinon@^10.0.13":
version "10.0.16"
resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-10.0.16.tgz#4bf10313bd9aa8eef1e50ec9f4decd3dd455b4d3"
@@ -10924,14 +10987,6 @@
"@webassemblyjs/helper-numbers" "1.11.1"
"@webassemblyjs/helper-wasm-bytecode" "1.11.1"
-"@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5":
- version "1.11.6"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.6.tgz#db046555d3c413f8966ca50a95176a0e2c642e24"
- integrity sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==
- dependencies:
- "@webassemblyjs/helper-numbers" "1.11.6"
- "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
-
"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1":
version "1.12.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb"
@@ -10965,11 +11020,6 @@
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5"
integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==
-"@webassemblyjs/helper-buffer@1.11.6":
- version "1.11.6"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz#b66d73c43e296fd5e88006f18524feb0f2c7c093"
- integrity sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==
-
"@webassemblyjs/helper-buffer@1.12.1":
version "1.12.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz#6df20d272ea5439bf20ab3492b7fb70e9bfcb3f6"
@@ -11013,16 +11063,6 @@
"@webassemblyjs/helper-wasm-bytecode" "1.11.1"
"@webassemblyjs/wasm-gen" "1.11.1"
-"@webassemblyjs/helper-wasm-section@1.11.6":
- version "1.11.6"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz#ff97f3863c55ee7f580fd5c41a381e9def4aa577"
- integrity sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==
- dependencies:
- "@webassemblyjs/ast" "1.11.6"
- "@webassemblyjs/helper-buffer" "1.11.6"
- "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
- "@webassemblyjs/wasm-gen" "1.11.6"
-
"@webassemblyjs/helper-wasm-section@1.12.1":
version "1.12.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz#3da623233ae1a60409b509a52ade9bc22a37f7bf"
@@ -11085,20 +11125,6 @@
"@webassemblyjs/wasm-parser" "1.11.1"
"@webassemblyjs/wast-printer" "1.11.1"
-"@webassemblyjs/wasm-edit@^1.11.5":
- version "1.11.6"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz#c72fa8220524c9b416249f3d94c2958dfe70ceab"
- integrity sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==
- dependencies:
- "@webassemblyjs/ast" "1.11.6"
- "@webassemblyjs/helper-buffer" "1.11.6"
- "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
- "@webassemblyjs/helper-wasm-section" "1.11.6"
- "@webassemblyjs/wasm-gen" "1.11.6"
- "@webassemblyjs/wasm-opt" "1.11.6"
- "@webassemblyjs/wasm-parser" "1.11.6"
- "@webassemblyjs/wast-printer" "1.11.6"
-
"@webassemblyjs/wasm-edit@^1.12.1":
version "1.12.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz#9f9f3ff52a14c980939be0ef9d5df9ebc678ae3b"
@@ -11124,17 +11150,6 @@
"@webassemblyjs/leb128" "1.11.1"
"@webassemblyjs/utf8" "1.11.1"
-"@webassemblyjs/wasm-gen@1.11.6":
- version "1.11.6"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz#fb5283e0e8b4551cc4e9c3c0d7184a65faf7c268"
- integrity sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==
- dependencies:
- "@webassemblyjs/ast" "1.11.6"
- "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
- "@webassemblyjs/ieee754" "1.11.6"
- "@webassemblyjs/leb128" "1.11.6"
- "@webassemblyjs/utf8" "1.11.6"
-
"@webassemblyjs/wasm-gen@1.12.1":
version "1.12.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz#a6520601da1b5700448273666a71ad0a45d78547"
@@ -11156,16 +11171,6 @@
"@webassemblyjs/wasm-gen" "1.11.1"
"@webassemblyjs/wasm-parser" "1.11.1"
-"@webassemblyjs/wasm-opt@1.11.6":
- version "1.11.6"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz#d9a22d651248422ca498b09aa3232a81041487c2"
- integrity sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==
- dependencies:
- "@webassemblyjs/ast" "1.11.6"
- "@webassemblyjs/helper-buffer" "1.11.6"
- "@webassemblyjs/wasm-gen" "1.11.6"
- "@webassemblyjs/wasm-parser" "1.11.6"
-
"@webassemblyjs/wasm-opt@1.12.1":
version "1.12.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz#9e6e81475dfcfb62dab574ac2dda38226c232bc5"
@@ -11188,18 +11193,6 @@
"@webassemblyjs/leb128" "1.11.1"
"@webassemblyjs/utf8" "1.11.1"
-"@webassemblyjs/wasm-parser@1.11.6", "@webassemblyjs/wasm-parser@^1.11.5":
- version "1.11.6"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz#bb85378c527df824004812bbdb784eea539174a1"
- integrity sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==
- dependencies:
- "@webassemblyjs/ast" "1.11.6"
- "@webassemblyjs/helper-api-error" "1.11.6"
- "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
- "@webassemblyjs/ieee754" "1.11.6"
- "@webassemblyjs/leb128" "1.11.6"
- "@webassemblyjs/utf8" "1.11.6"
-
"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.12.1":
version "1.12.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz#c47acb90e6f083391e3fa61d113650eea1e95937"
@@ -11220,14 +11213,6 @@
"@webassemblyjs/ast" "1.11.1"
"@xtuc/long" "4.2.2"
-"@webassemblyjs/wast-printer@1.11.6":
- version "1.11.6"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz#a7bf8dd7e362aeb1668ff43f35cb849f188eff20"
- integrity sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==
- dependencies:
- "@webassemblyjs/ast" "1.11.6"
- "@xtuc/long" "4.2.2"
-
"@webassemblyjs/wast-printer@1.12.1":
version "1.12.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz#bcecf661d7d1abdaf989d8341a4833e33e2b31ac"
@@ -16901,18 +16886,10 @@ enhanced-resolve@^5.14.1:
graceful-fs "^4.2.4"
tapable "^2.2.0"
-enhanced-resolve@^5.15.0:
- version "5.15.0"
- resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz#1af946c7d93603eb88e9896cee4904dc012e9c35"
- integrity sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==
- dependencies:
- graceful-fs "^4.2.4"
- tapable "^2.2.0"
-
-enhanced-resolve@^5.17.0:
- version "5.17.0"
- resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz#d037603789dd9555b89aaec7eb78845c49089bc5"
- integrity sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==
+enhanced-resolve@^5.17.1:
+ version "5.17.1"
+ resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz#67bfbbcc2f81d511be77d686a90267ef7f898a15"
+ integrity sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==
dependencies:
graceful-fs "^4.2.4"
tapable "^2.2.0"
@@ -19084,7 +19061,7 @@ generate-function@^2.3.1:
dependencies:
is-property "^1.0.2"
-generic-pool@3.9.0:
+generic-pool@3.9.0, generic-pool@^3.9.0:
version "3.9.0"
resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-3.9.0.tgz#36f4a678e963f4fdb8707eab050823abc4e8f5e4"
integrity sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==
@@ -33803,42 +33780,11 @@ webpack@5.76.1:
watchpack "^2.4.0"
webpack-sources "^3.2.3"
-webpack@^5.90.3, webpack@~5.90.3:
- version "5.90.3"
- resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.90.3.tgz#37b8f74d3ded061ba789bb22b31e82eed75bd9ac"
- integrity sha512-h6uDYlWCctQRuXBs1oYpVe6sFcWedl0dpcVaTf/YF67J9bKvwJajFulMVSYKHrksMB3I/pIagRzDxwxkebuzKA==
- dependencies:
- "@types/eslint-scope" "^3.7.3"
- "@types/estree" "^1.0.5"
- "@webassemblyjs/ast" "^1.11.5"
- "@webassemblyjs/wasm-edit" "^1.11.5"
- "@webassemblyjs/wasm-parser" "^1.11.5"
- acorn "^8.7.1"
- acorn-import-assertions "^1.9.0"
- browserslist "^4.21.10"
- chrome-trace-event "^1.0.2"
- enhanced-resolve "^5.15.0"
- es-module-lexer "^1.2.1"
- eslint-scope "5.1.1"
- events "^3.2.0"
- glob-to-regexp "^0.4.1"
- graceful-fs "^4.2.9"
- json-parse-even-better-errors "^2.3.1"
- loader-runner "^4.2.0"
- mime-types "^2.1.27"
- neo-async "^2.6.2"
- schema-utils "^3.2.0"
- tapable "^2.1.1"
- terser-webpack-plugin "^5.3.10"
- watchpack "^2.4.0"
- webpack-sources "^3.2.3"
-
-webpack@^5.92.1:
- version "5.92.1"
- resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.92.1.tgz#eca5c1725b9e189cffbd86e8b6c3c7400efc5788"
- integrity sha512-JECQ7IwJb+7fgUFBlrJzbyu3GEuNBcdqr1LD7IbSzwkSmIevTm8PF+wej3Oxuz/JFBUZ6O1o43zsPkwm1C4TmA==
+webpack@^5.90.3, webpack@^5.94.0, webpack@~5.94.0:
+ version "5.94.0"
+ resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.94.0.tgz#77a6089c716e7ab90c1c67574a28da518a20970f"
+ integrity sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==
dependencies:
- "@types/eslint-scope" "^3.7.3"
"@types/estree" "^1.0.5"
"@webassemblyjs/ast" "^1.12.1"
"@webassemblyjs/wasm-edit" "^1.12.1"
@@ -33847,7 +33793,7 @@ webpack@^5.92.1:
acorn-import-attributes "^1.9.5"
browserslist "^4.21.10"
chrome-trace-event "^1.0.2"
- enhanced-resolve "^5.17.0"
+ enhanced-resolve "^5.17.1"
es-module-lexer "^1.2.1"
eslint-scope "5.1.1"
events "^3.2.0"