diff --git a/CHANGELOG.md b/CHANGELOG.md index ac04fae18f44..182979786d15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,20 @@ - "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott +## 7.106.0 + +- feat(nextjs): Support Hybrid Cloud DSNs with `tunnelRoute` option (#10958) +- feat(remix): Add Vite dev-mode support to Express instrumentation (#10811) +- fix(core): Undeprecate `setTransactionName` +- fix(browser): Don't use chrome variable name (#10874) +- fix(nextjs): Client code should not use Node `global` (#10925) +- fix(node): support undici headers as strings or arrays (#10938) +- fix(types): Add `AttachmentType` and use for envelope `attachment_type` property (#10946) +- ref(ember): Avoid namespace import to hopefully resolve minification issue (#10885) +- chore(sveltekit): Fix punctuation in a console.log (#10895) + +Work in this release contributed by @jessezhang91 and @bfontaine. Thank you for your contributions! + ## 7.105.0 ### Important Changes diff --git a/packages/browser/src/stack-parsers.ts b/packages/browser/src/stack-parsers.ts index 609a6dd1fd51..37d05c453e45 100644 --- a/packages/browser/src/stack-parsers.ts +++ b/packages/browser/src/stack-parsers.ts @@ -58,7 +58,9 @@ const chromeRegex = /^\s*at (?:(.+?\)(?: \[.+\])?|.*?) ?\((?:address at )?)?(?:async )?((?:|[-a-z]+:|.*bundle|\/)?.*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i; const chromeEvalRegex = /\((\S*)(?::(\d+))(?::(\d+))\)/; -const chrome: StackLineParserFn = line => { +// We cannot call this variable `chrome` because it can conflict with global `chrome` variable in certain environments +// See: https://github.com/getsentry/sentry-javascript/issues/6880 +const chromeStackParserFn: StackLineParserFn = line => { const parts = chromeRegex.exec(line); if (parts) { @@ -85,7 +87,7 @@ const chrome: StackLineParserFn = line => { return; }; -export const chromeStackLineParser: StackLineParser = [CHROME_PRIORITY, chrome]; +export const chromeStackLineParser: StackLineParser = [CHROME_PRIORITY, chromeStackParserFn]; // gecko regex: `(?:bundle|\d+\.js)`: `bundle` is for react native, `\d+\.js` also but specifically for ram bundles because it // generates filenames without a prefix like `file://` the filenames in the stacktrace are just 42.js diff --git a/packages/core/src/scope.ts b/packages/core/src/scope.ts index 3e174899f592..613a9e0e1bab 100644 --- a/packages/core/src/scope.ts +++ b/packages/core/src/scope.ts @@ -294,7 +294,6 @@ export class Scope implements ScopeInterface { /** * Sets the transaction name on the scope for future events. - * @deprecated Use extra or tags instead. */ public setTransactionName(name?: string): this { this._transactionName = name; diff --git a/packages/core/test/lib/transports/base.test.ts b/packages/core/test/lib/transports/base.test.ts index 5e6b504d9f6e..e6f33e20e757 100644 --- a/packages/core/test/lib/transports/base.test.ts +++ b/packages/core/test/lib/transports/base.test.ts @@ -23,7 +23,7 @@ const ATTACHMENT_ENVELOPE = createEnvelope( length: 20, filename: 'test-file.txt', content_type: 'text/plain', - attachment_type: 'text', + attachment_type: 'event.attachment', }, 'attachment content', ] as AttachmentItem, diff --git a/packages/ember/addon/instance-initializers/sentry-performance.ts b/packages/ember/addon/instance-initializers/sentry-performance.ts index 9046ead7c7fc..593a387ce53e 100644 --- a/packages/ember/addon/instance-initializers/sentry-performance.ts +++ b/packages/ember/addon/instance-initializers/sentry-performance.ts @@ -6,14 +6,20 @@ import type RouterService from '@ember/routing/router-service'; import { _backburner, run, scheduleOnce } from '@ember/runloop'; import type { EmberRunQueues } from '@ember/runloop/-private/types'; import { getOwnConfig, isTesting, macroCondition } from '@embroider/macros'; -import * as Sentry from '@sentry/browser'; import type { ExtendedBackburner } from '@sentry/ember/runloop'; import type { Span } from '@sentry/types'; import { GLOBAL_OBJ, browserPerformanceTimeOrigin, timestampInSeconds } from '@sentry/utils'; -import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '@sentry/core'; -import type { BrowserClient } from '..'; -import { getActiveSpan, startInactiveSpan } from '..'; +import type { BrowserClient } from '@sentry/browser'; +import { + SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, + SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, + getActiveSpan, + getClient, + startBrowserTracingNavigationSpan, + startBrowserTracingPageLoadSpan, + startInactiveSpan, +} from '@sentry/browser'; import type { EmberRouterMain, EmberSentryConfig, GlobalConfig, OwnConfig } from '../types'; function getSentryConfig(): EmberSentryConfig { @@ -103,7 +109,7 @@ export function _instrumentEmberRouter( const browserTracingOptions = config.browserTracingOptions || config.sentry.browserTracingOptions || {}; const url = getLocationURL(location); - const client = Sentry.getClient(); + const client = getClient(); if (!client) { return; @@ -115,7 +121,7 @@ export function _instrumentEmberRouter( browserTracingOptions.instrumentPageLoad !== false ) { const routeInfo = routerService.recognize(url); - activeRootSpan = Sentry.startBrowserTracingPageLoadSpan(client, { + activeRootSpan = startBrowserTracingPageLoadSpan(client, { name: `route:${routeInfo.name}`, origin: 'auto.pageload.ember', attributes: { @@ -148,7 +154,7 @@ export function _instrumentEmberRouter( const { fromRoute, toRoute } = getTransitionInformation(transition, routerService); activeRootSpan?.end(); - activeRootSpan = Sentry.startBrowserTracingNavigationSpan(client, { + activeRootSpan = startBrowserTracingNavigationSpan(client, { name: `route:${toRoute}`, origin: 'auto.navigation.ember', attributes: { @@ -429,7 +435,7 @@ export async function instrumentForPerformance(appInstance: ApplicationInstance) instrumentPageLoad: false, }); - const client = Sentry.getClient(); + const client = getClient(); const isAlreadyInitialized = macroCondition(isTesting()) ? !!client?.getIntegrationByName('BrowserTracing') : false; diff --git a/packages/nextjs/src/client/rewriteFramesIntegration.ts b/packages/nextjs/src/client/rewriteFramesIntegration.ts index 5c45ff63d983..961d5a7e83c6 100644 --- a/packages/nextjs/src/client/rewriteFramesIntegration.ts +++ b/packages/nextjs/src/client/rewriteFramesIntegration.ts @@ -1,8 +1,9 @@ import { defineIntegration } from '@sentry/core'; import { rewriteFramesIntegration as originalRewriteFramesIntegration } from '@sentry/integrations'; import type { IntegrationFn, StackFrame } from '@sentry/types'; +import { GLOBAL_OBJ } from '@sentry/utils'; -const globalWithInjectedValues = global as typeof global & { +const globalWithInjectedValues = GLOBAL_OBJ as typeof GLOBAL_OBJ & { __rewriteFramesAssetPrefixPath__: string; }; diff --git a/packages/nextjs/src/client/tunnelRoute.ts b/packages/nextjs/src/client/tunnelRoute.ts index b3511e7ab70f..3c93b93e41f2 100644 --- a/packages/nextjs/src/client/tunnelRoute.ts +++ b/packages/nextjs/src/client/tunnelRoute.ts @@ -1,9 +1,9 @@ import type { BrowserOptions } from '@sentry/react'; -import { dsnFromString, logger } from '@sentry/utils'; +import { GLOBAL_OBJ, dsnFromString, logger } from '@sentry/utils'; import { DEBUG_BUILD } from '../common/debug-build'; -const globalWithInjectedValues = global as typeof global & { +const globalWithInjectedValues = GLOBAL_OBJ as typeof GLOBAL_OBJ & { __sentryRewritesTunnelPath__?: string; }; diff --git a/packages/nextjs/src/server/rewriteFramesIntegration.ts b/packages/nextjs/src/server/rewriteFramesIntegration.ts index f27ff9a9993d..912a7635533e 100644 --- a/packages/nextjs/src/server/rewriteFramesIntegration.ts +++ b/packages/nextjs/src/server/rewriteFramesIntegration.ts @@ -5,9 +5,9 @@ import { rewriteFramesIntegration as originalRewriteFramesIntegration, } from '@sentry/integrations'; import type { IntegrationFn, StackFrame } from '@sentry/types'; -import { escapeStringForRegex } from '@sentry/utils'; +import { GLOBAL_OBJ, escapeStringForRegex } from '@sentry/utils'; -const globalWithInjectedValues = global as typeof global & { +const globalWithInjectedValues = GLOBAL_OBJ as typeof GLOBAL_OBJ & { __rewriteFramesDistDir__?: string; }; diff --git a/packages/node/src/integrations/undici/index.ts b/packages/node/src/integrations/undici/index.ts index a2616deb920b..77ba6f9c9815 100644 --- a/packages/node/src/integrations/undici/index.ts +++ b/packages/node/src/integrations/undici/index.ts @@ -309,8 +309,13 @@ function setHeadersOnRequest( sentryTrace: string, sentryBaggageHeader: string | undefined, ): void { - const headerLines = request.headers.split('\r\n'); - const hasSentryHeaders = headerLines.some(headerLine => headerLine.startsWith('sentry-trace:')); + let hasSentryHeaders: boolean; + if (Array.isArray(request.headers)) { + hasSentryHeaders = request.headers.some(headerLine => headerLine === 'sentry-trace'); + } else { + const headerLines = request.headers.split('\r\n'); + hasSentryHeaders = headerLines.some(headerLine => headerLine.startsWith('sentry-trace:')); + } if (hasSentryHeaders) { return; diff --git a/packages/node/src/integrations/undici/types.ts b/packages/node/src/integrations/undici/types.ts index b51da3da2d34..05732811dc68 100644 --- a/packages/node/src/integrations/undici/types.ts +++ b/packages/node/src/integrations/undici/types.ts @@ -224,7 +224,9 @@ export interface UndiciRequest { // Originally was Dispatcher.HttpMethod, but did not want to vendor that in. method?: string; path: string; - headers: string; + // string for undici@<=6.6.2 and string[] for undici@>=6.7.0. + // see for more information: https://github.com/getsentry/sentry-javascript/issues/10936 + headers: string | string[]; addHeader(key: string, value: string): RequestWithSentry; } diff --git a/packages/sveltekit/src/vite/sourceMaps.ts b/packages/sveltekit/src/vite/sourceMaps.ts index 2f5fd28ac1f8..b6c5e6756897 100644 --- a/packages/sveltekit/src/vite/sourceMaps.ts +++ b/packages/sveltekit/src/vite/sourceMaps.ts @@ -212,7 +212,7 @@ export async function makeCustomSentryVitePlugin(options?: CustomSentryVitePlugi console.warn('[Source Maps Plugin] Failed to upload source maps!'); // eslint-disable-next-line no-console console.log( - '[Source Maps Plugin] Please make sure, you specified a valid Sentry auth token, as well as your org and project slugs.', + '[Source Maps Plugin] Please make sure you specified a valid Sentry auth token, as well as your org and project slugs.', ); // eslint-disable-next-line no-console console.log( diff --git a/packages/types/src/attachment.ts b/packages/types/src/attachment.ts index 55cc795732ea..da7678d1d8f1 100644 --- a/packages/types/src/attachment.ts +++ b/packages/types/src/attachment.ts @@ -1,6 +1,23 @@ +export type AttachmentType = + | 'event.attachment' + | 'event.minidump' + | 'event.applecrashreport' + | 'unreal.context' + | 'unreal.logs'; + +/** + * An attachment to an event. This is used to upload arbitrary data to Sentry. + * + * Please take care to not add sensitive information in attachments. + * + * https://develop.sentry.dev/sdk/envelopes/#attachment + */ export interface Attachment { data: string | Uint8Array; filename: string; contentType?: string; - attachmentType?: string; + /** + * The type of the attachment. Defaults to `event.attachment` if not specified. + */ + attachmentType?: AttachmentType; } diff --git a/packages/types/src/envelope.ts b/packages/types/src/envelope.ts index fe08ce1962d1..5db39eb65f3e 100644 --- a/packages/types/src/envelope.ts +++ b/packages/types/src/envelope.ts @@ -1,3 +1,4 @@ +import type { AttachmentType } from './attachment'; import type { SerializedCheckIn } from './checkin'; import type { ClientReport } from './clientreport'; import type { DsnComponents } from './dsn'; @@ -72,7 +73,7 @@ type AttachmentItemHeaders = { length: number; filename: string; content_type?: string; - attachment_type?: string; + attachment_type?: AttachmentType; }; type UserFeedbackItemHeaders = { type: 'user_report' }; type FeedbackItemHeaders = { type: 'feedback' }; diff --git a/packages/types/src/scope.ts b/packages/types/src/scope.ts index fd51eae8e5c4..4d45b5b6a87c 100644 --- a/packages/types/src/scope.ts +++ b/packages/types/src/scope.ts @@ -126,7 +126,6 @@ export interface Scope { /** * Sets the transaction name on the scope for future events. - * @deprecated Use extra or tags instead. */ setTransactionName(name?: string): this; diff --git a/packages/utils/src/vendor/supportsHistory.ts b/packages/utils/src/vendor/supportsHistory.ts index 8dc16b43f1cc..35af156eb96f 100644 --- a/packages/utils/src/vendor/supportsHistory.ts +++ b/packages/utils/src/vendor/supportsHistory.ts @@ -38,8 +38,8 @@ export function supportsHistory(): boolean { // borrowed from: https://github.com/angular/angular.js/pull/13945/files /* eslint-disable @typescript-eslint/no-unsafe-member-access */ // eslint-disable-next-line @typescript-eslint/no-explicit-any - const chrome = (WINDOW as any).chrome; - const isChromePackagedApp = chrome && chrome.app && chrome.app.runtime; + const chromeVar = (WINDOW as any).chrome; + const isChromePackagedApp = chromeVar && chromeVar.app && chromeVar.app.runtime; /* eslint-enable @typescript-eslint/no-unsafe-member-access */ const hasHistoryApi = 'history' in WINDOW && !!WINDOW.history.pushState && !!WINDOW.history.replaceState;