From 852f3dfa348fbbd976e34f0513586a7e71f9b3f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Og=C3=B3rek?= Date: Fri, 15 Jan 2021 14:58:02 +0100 Subject: [PATCH 1/4] feat: Allow for attaching metadata and pass it to the API and transports --- packages/angular/src/index.ts | 2 ++ packages/angular/src/sdk.ts | 10 +++++++ packages/browser/src/backend.ts | 1 + packages/browser/src/client.ts | 4 +-- packages/browser/src/exports.ts | 3 ++- packages/browser/src/sdk.ts | 4 +++ packages/browser/src/transports/base.ts | 2 +- packages/browser/src/version.ts | 2 +- packages/core/package.json | 3 ++- packages/core/src/api.ts | 11 +++++--- packages/core/src/index.ts | 1 + packages/core/src/request.ts | 28 +++++++++++++++++++- packages/core/src/sdk.ts | 4 +++ packages/core/src/version.ts | 1 + packages/ember/addon/index.ts | 2 ++ packages/gatsby/gatsby-browser.js | 3 +++ packages/node/src/backend.ts | 1 + packages/node/src/client.ts | 4 +-- packages/node/src/index.ts | 3 ++- packages/node/src/sdk.ts | 4 +++ packages/node/src/transports/base.ts | 6 ++--- packages/node/src/version.ts | 2 +- packages/react/src/index.ts | 1 + packages/react/src/sdk.ts | 10 +++++++ packages/serverless/src/awslambda.ts | 2 ++ packages/serverless/src/gcpfunction/index.ts | 2 ++ packages/types/src/options.ts | 6 +++++ packages/types/src/sdkinfo.ts | 5 +++- packages/types/src/transport.ts | 3 +++ packages/vue/src/sdk.ts | 19 ++++--------- 30 files changed, 117 insertions(+), 32 deletions(-) create mode 100644 packages/angular/src/sdk.ts create mode 100644 packages/core/src/version.ts create mode 100644 packages/react/src/sdk.ts diff --git a/packages/angular/src/index.ts b/packages/angular/src/index.ts index b746af148c1f..19c411fbc8d0 100644 --- a/packages/angular/src/index.ts +++ b/packages/angular/src/index.ts @@ -1,4 +1,6 @@ export * from '@sentry/browser'; + +export { init } from './sdk'; export { createErrorHandler, ErrorHandlerOptions } from './errorhandler'; export { getActiveTransaction, diff --git a/packages/angular/src/sdk.ts b/packages/angular/src/sdk.ts new file mode 100644 index 000000000000..6a363c352425 --- /dev/null +++ b/packages/angular/src/sdk.ts @@ -0,0 +1,10 @@ +import { BrowserOptions, init as browserInit } from '@sentry/browser'; + +/** + * Inits the Angular SDK + */ +export function init(options: BrowserOptions): void { + options.metadata = options.metadata || {}; + options.metadata.name = options.metadata.name || 'sentry.javascript.angular'; + browserInit(options); +} diff --git a/packages/browser/src/backend.ts b/packages/browser/src/backend.ts index 499d37125a1d..03617700ee25 100644 --- a/packages/browser/src/backend.ts +++ b/packages/browser/src/backend.ts @@ -67,6 +67,7 @@ export class BrowserBackend extends BaseBackend { const transportOptions = { ...this._options.transportOptions, dsn: this._options.dsn, + metadata: this._options.metadata, }; if (this._options.transport) { diff --git a/packages/browser/src/client.ts b/packages/browser/src/client.ts index ac8cd3281419..7716bbbf5d58 100644 --- a/packages/browser/src/client.ts +++ b/packages/browser/src/client.ts @@ -1,11 +1,11 @@ -import { BaseClient, Scope } from '@sentry/core'; +import { BaseClient, Scope, SDK_VERSION } from '@sentry/core'; import { Event, EventHint } from '@sentry/types'; import { getGlobalObject, logger } from '@sentry/utils'; import { BrowserBackend, BrowserOptions } from './backend'; import { injectReportDialog, ReportDialogOptions } from './helpers'; import { Breadcrumbs } from './integrations'; -import { SDK_NAME, SDK_VERSION } from './version'; +import { SDK_NAME } from './version'; /** * The Sentry Browser SDK Client. diff --git a/packages/browser/src/exports.ts b/packages/browser/src/exports.ts index cf9e531bdc58..cbe5c0c4f262 100644 --- a/packages/browser/src/exports.ts +++ b/packages/browser/src/exports.ts @@ -28,6 +28,7 @@ export { makeMain, Scope, startTransaction, + SDK_VERSION, setContext, setExtra, setExtras, @@ -42,4 +43,4 @@ export { BrowserClient } from './client'; export { injectReportDialog, ReportDialogOptions } from './helpers'; export { eventFromException, eventFromMessage } from './eventbuilder'; export { defaultIntegrations, forceLoad, init, lastEventId, onLoad, showReportDialog, flush, close, wrap } from './sdk'; -export { SDK_NAME, SDK_VERSION } from './version'; +export { SDK_NAME } from './version'; diff --git a/packages/browser/src/sdk.ts b/packages/browser/src/sdk.ts index 30a7f7a12b03..01aacf0a9f06 100644 --- a/packages/browser/src/sdk.ts +++ b/packages/browser/src/sdk.ts @@ -5,6 +5,7 @@ import { BrowserOptions } from './backend'; import { BrowserClient } from './client'; import { ReportDialogOptions, wrap as internalWrap } from './helpers'; import { Breadcrumbs, GlobalHandlers, LinkedErrors, TryCatch, UserAgent } from './integrations'; +import { SDK_NAME } from './version'; export const defaultIntegrations = [ new CoreIntegrations.InboundFilters(), @@ -88,6 +89,9 @@ export function init(options: BrowserOptions = {}): void { options.autoSessionTracking = false; } + options.metadata = options.metadata || {}; + options.metadata.name = options.metadata.name || SDK_NAME; + initAndBind(BrowserClient, options); if (options.autoSessionTracking) { diff --git a/packages/browser/src/transports/base.ts b/packages/browser/src/transports/base.ts index fa18d5274a50..c8b408c288cc 100644 --- a/packages/browser/src/transports/base.ts +++ b/packages/browser/src/transports/base.ts @@ -26,7 +26,7 @@ export abstract class BaseTransport implements Transport { protected readonly _rateLimits: Record = {}; public constructor(public options: TransportOptions) { - this._api = new API(this.options.dsn); + this._api = new API(options.dsn, options.metadata); // eslint-disable-next-line deprecation/deprecation this.url = this._api.getStoreEndpointWithUrlEncodedAuth(); } diff --git a/packages/browser/src/version.ts b/packages/browser/src/version.ts index e22122255bcd..462be137a6ca 100644 --- a/packages/browser/src/version.ts +++ b/packages/browser/src/version.ts @@ -1,2 +1,2 @@ +// TODO: Remove in the next major release and rely only on @sentry/core SDK_VERSION and SdkInfo metadata export const SDK_NAME = 'sentry.javascript.browser'; -export const SDK_VERSION = '5.30.0'; diff --git a/packages/core/package.json b/packages/core/package.json index 4c5e2030b40f..6ccbdf5928fc 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -48,7 +48,8 @@ "fix:eslint": "eslint . --format stylish --fix", "test": "jest", "test:watch": "jest --watch", - "pack": "npm pack" + "pack": "npm pack", + "version": "node ../../scripts/versionbump.js src/version.ts" }, "volta": { "extends": "../../package.json" diff --git a/packages/core/src/api.ts b/packages/core/src/api.ts index 257ccb929571..f359711aedde 100644 --- a/packages/core/src/api.ts +++ b/packages/core/src/api.ts @@ -1,14 +1,18 @@ -import { DsnLike } from '@sentry/types'; +import { DsnLike, SdkInfo } from '@sentry/types'; import { Dsn, urlEncode } from '@sentry/utils'; const SENTRY_API_VERSION = '7'; -/** Helper class to provide urls to different Sentry endpoints. */ +/** + * Helper class to provide urls, headers and metadata that can be used to form + * different types of requests to Sentry endpoints. + * Supports both envelopes and regular event requests. + **/ export class API { /** The internally used Dsn object. */ private readonly _dsnObject: Dsn; /** Create a new instance of API */ - public constructor(public dsn: DsnLike) { + public constructor(public dsn: DsnLike, public metadata?: Partial) { this._dsnObject = new Dsn(dsn); } @@ -59,6 +63,7 @@ export class API { * This is needed for node and the old /store endpoint in sentry */ public getRequestHeaders(clientName: string, clientVersion: string): { [key: string]: string } { + // CHANGE THIS to use metadata but keep clientName and clientVersion compatible const dsn = this._dsnObject; const header = [`Sentry sentry_version=${SENTRY_API_VERSION}`]; header.push(`sentry_client=${clientName}/${clientVersion}`); diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 6a5e1c6a586f..5fe8450de3ed 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -20,6 +20,7 @@ export { BackendClass, BaseBackend } from './basebackend'; export { eventToSentryRequest, sessionToSentryRequest } from './request'; export { initAndBind, ClientClass } from './sdk'; export { NoopTransport } from './transports/noop'; +export { SDK_VERSION } from './version'; import * as Integrations from './integrations'; diff --git a/packages/core/src/request.ts b/packages/core/src/request.ts index 14084d942c33..0173adb2a332 100644 --- a/packages/core/src/request.ts +++ b/packages/core/src/request.ts @@ -1,11 +1,33 @@ -import { Event, SentryRequest, Session } from '@sentry/types'; +import { Event, SdkInfo, SentryRequest, Session } from '@sentry/types'; +import { isString } from '@sentry/utils'; import { API } from './api'; +/** Extract envelope header containing sdk metadata from the API object */ +function getSdkMetadataForEnvelopeHeader(api: API): Partial | undefined { + if (!api.metadata) { + return; + } + + const { name, version } = api.metadata; + if (!isString(name) || !isString(version)) { + return; + } + + return { + ...(isString(name) && { name }), + ...(isString(version) && { version }), + }; +} + /** Creates a SentryRequest from an event. */ export function sessionToSentryRequest(session: Session, api: API): SentryRequest { + const sdkMetadata = getSdkMetadataForEnvelopeHeader(api); const envelopeHeaders = JSON.stringify({ sent_at: new Date().toISOString(), + ...(sdkMetadata && { + sdk: sdkMetadata, + }), }); const itemHeaders = JSON.stringify({ type: 'session', @@ -39,9 +61,13 @@ export function eventToSentryRequest(event: Event, api: API): SentryRequest { // deserialization. Instead, we only implement a minimal subset of the spec to // serialize events inline here. if (useEnvelope) { + const sdkMetadata = getSdkMetadataForEnvelopeHeader(api); const envelopeHeaders = JSON.stringify({ event_id: event.event_id, sent_at: new Date().toISOString(), + ...(sdkMetadata && { + sdk: sdkMetadata, + }), }); const itemHeaders = JSON.stringify({ type: event.type, diff --git a/packages/core/src/sdk.ts b/packages/core/src/sdk.ts index 17497c57f2be..5720562346ee 100644 --- a/packages/core/src/sdk.ts +++ b/packages/core/src/sdk.ts @@ -2,6 +2,8 @@ import { getCurrentHub } from '@sentry/hub'; import { Client, Options } from '@sentry/types'; import { logger } from '@sentry/utils'; +import { SDK_VERSION } from './version'; + /** A class object that can instantiate Client objects. */ export type ClientClass = new (options: O) => F; @@ -16,6 +18,8 @@ export function initAndBind(clientClass: Cl if (options.debug === true) { logger.enable(); } + options.metadata = options.metadata || {}; + options.metadata.version = SDK_VERSION; const hub = getCurrentHub(); const client = new clientClass(options); hub.bindClient(client); diff --git a/packages/core/src/version.ts b/packages/core/src/version.ts new file mode 100644 index 000000000000..8a207150eec0 --- /dev/null +++ b/packages/core/src/version.ts @@ -0,0 +1 @@ +export const SDK_VERSION = '5.30.0'; diff --git a/packages/ember/addon/index.ts b/packages/ember/addon/index.ts index d65e13faa4d0..afa3c2d2aba7 100644 --- a/packages/ember/addon/index.ts +++ b/packages/ember/addon/index.ts @@ -17,6 +17,8 @@ export function InitSentryForEmber(_runtimeConfig: BrowserOptions | undefined) { assert('Missing configuration for Sentry.', config.sentry); const initConfig = Object.assign({}, config.sentry, _runtimeConfig || {}); + initConfig.metadata = initConfig.metadata || {}; + initConfig.metadata.name = initConfig.metadata.name || 'sentry.javascript.ember'; createEmberEventProcessor(); diff --git a/packages/gatsby/gatsby-browser.js b/packages/gatsby/gatsby-browser.js index 42d5f606f2c8..ef12eb757646 100644 --- a/packages/gatsby/gatsby-browser.js +++ b/packages/gatsby/gatsby-browser.js @@ -6,6 +6,9 @@ exports.onClientEntry = function(_, pluginParams) { return; } + pluginParams.metadata = pluginParams.metadata || {}; + pluginParams.metadata.name = pluginParams.metadata.name || 'sentry.javascript.gatsby'; + const integrations = [...(pluginParams.integrations || [])]; if (Tracing.hasTracingEnabled(pluginParams) && !integrations.some(ele => ele.name === 'BrowserTracing')) { diff --git a/packages/node/src/backend.ts b/packages/node/src/backend.ts index c264bebd1716..0aac0371b448 100644 --- a/packages/node/src/backend.ts +++ b/packages/node/src/backend.ts @@ -140,6 +140,7 @@ export class NodeBackend extends BaseBackend { ...(this._options.httpsProxy && { httpsProxy: this._options.httpsProxy }), ...(this._options.caCerts && { caCerts: this._options.caCerts }), dsn: this._options.dsn, + metadata: this._options.metadata, }; if (this._options.transport) { diff --git a/packages/node/src/client.ts b/packages/node/src/client.ts index bf4230416f0e..c82eebce1b76 100644 --- a/packages/node/src/client.ts +++ b/packages/node/src/client.ts @@ -1,8 +1,8 @@ -import { BaseClient, Scope } from '@sentry/core'; +import { BaseClient, Scope, SDK_VERSION } from '@sentry/core'; import { Event, EventHint } from '@sentry/types'; import { NodeBackend, NodeOptions } from './backend'; -import { SDK_NAME, SDK_VERSION } from './version'; +import { SDK_NAME } from './version'; /** * The Sentry Node SDK Client. diff --git a/packages/node/src/index.ts b/packages/node/src/index.ts index 6429ce3a75c9..ef29ad75a92a 100644 --- a/packages/node/src/index.ts +++ b/packages/node/src/index.ts @@ -28,6 +28,7 @@ export { makeMain, Scope, startTransaction, + SDK_VERSION, setContext, setExtra, setExtras, @@ -40,7 +41,7 @@ export { export { NodeBackend, NodeOptions } from './backend'; export { NodeClient } from './client'; export { defaultIntegrations, init, lastEventId, flush, close } from './sdk'; -export { SDK_NAME, SDK_VERSION } from './version'; +export { SDK_NAME } from './version'; import { Integrations as CoreIntegrations } from '@sentry/core'; import { getMainCarrier } from '@sentry/hub'; diff --git a/packages/node/src/sdk.ts b/packages/node/src/sdk.ts index 9aa7c2f60858..46a3b1327505 100644 --- a/packages/node/src/sdk.ts +++ b/packages/node/src/sdk.ts @@ -6,6 +6,7 @@ import * as domain from 'domain'; import { NodeOptions } from './backend'; import { NodeClient } from './client'; import { Console, Http, LinkedErrors, OnUncaughtException, OnUnhandledRejection } from './integrations'; +import { SDK_NAME } from './version'; export const defaultIntegrations = [ // Common @@ -108,6 +109,9 @@ export function init(options: NodeOptions = {}): void { options.environment = process.env.SENTRY_ENVIRONMENT; } + options.metadata = options.metadata || {}; + options.metadata.name = options.metadata.name || SDK_NAME; + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any if ((domain as any).active) { setHubOnCarrier(getMainCarrier(), getCurrentHub()); diff --git a/packages/node/src/transports/base.ts b/packages/node/src/transports/base.ts index fb2e9f8ba230..5c63f9a08bb6 100644 --- a/packages/node/src/transports/base.ts +++ b/packages/node/src/transports/base.ts @@ -1,4 +1,4 @@ -import { API, eventToSentryRequest } from '@sentry/core'; +import { API, eventToSentryRequest, SDK_VERSION } from '@sentry/core'; import { Event, Response, Status, Transport, TransportOptions } from '@sentry/types'; import { logger, parseRetryAfterHeader, PromiseBuffer, SentryError } from '@sentry/utils'; import * as fs from 'fs'; @@ -6,7 +6,7 @@ import * as http from 'http'; import * as https from 'https'; import * as url from 'url'; -import { SDK_NAME, SDK_VERSION } from '../version'; +import { SDK_NAME } from '../version'; /** * Internal used interface for typescript. @@ -53,7 +53,7 @@ export abstract class BaseTransport implements Transport { /** Create instance and set this.dsn */ public constructor(public options: TransportOptions) { - this._api = new API(options.dsn); + this._api = new API(options.dsn, options.metadata); } /** diff --git a/packages/node/src/version.ts b/packages/node/src/version.ts index 38b745a6835f..b94bd71dd33c 100644 --- a/packages/node/src/version.ts +++ b/packages/node/src/version.ts @@ -1,2 +1,2 @@ +// TODO: Remove in the next major release and rely only on @sentry/core SDK_VERSION and SdkInfo metadata export const SDK_NAME = 'sentry.javascript.node'; -export const SDK_VERSION = '5.30.0'; diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index 57a37862d85d..aa3dc190a885 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -28,6 +28,7 @@ function createReactEventProcessor(): void { export * from '@sentry/browser'; +export { init } from './sdk'; export { Profiler, withProfiler, useProfiler } from './profiler'; export { ErrorBoundary, withErrorBoundary } from './errorboundary'; export { createReduxEnhancer } from './redux'; diff --git a/packages/react/src/sdk.ts b/packages/react/src/sdk.ts new file mode 100644 index 000000000000..57c66b15177e --- /dev/null +++ b/packages/react/src/sdk.ts @@ -0,0 +1,10 @@ +import { BrowserOptions, init as browserInit } from '@sentry/browser'; + +/** + * Inits the React SDK + */ +export function init(options: BrowserOptions): void { + options.metadata = options.metadata || {}; + options.metadata.name = options.metadata.name || 'sentry.javascript.react'; + browserInit(options); +} diff --git a/packages/serverless/src/awslambda.ts b/packages/serverless/src/awslambda.ts index 599ac3ae4656..4c211a41c797 100644 --- a/packages/serverless/src/awslambda.ts +++ b/packages/serverless/src/awslambda.ts @@ -56,6 +56,8 @@ export function init(options: Sentry.NodeOptions = {}): void { if (options.defaultIntegrations === undefined) { options.defaultIntegrations = defaultIntegrations; } + options.metadata = options.metadata || {}; + options.metadata.name = options.metadata.name || 'sentry.javascript.serverless'; Sentry.init(options); Sentry.addGlobalEventProcessor(serverlessEventProcessor('AWSLambda')); } diff --git a/packages/serverless/src/gcpfunction/index.ts b/packages/serverless/src/gcpfunction/index.ts index 3132e7d8caab..4307a869b150 100644 --- a/packages/serverless/src/gcpfunction/index.ts +++ b/packages/serverless/src/gcpfunction/index.ts @@ -22,6 +22,8 @@ export function init(options: Sentry.NodeOptions = {}): void { if (options.defaultIntegrations === undefined) { options.defaultIntegrations = defaultIntegrations; } + options.metadata = options.metadata || {}; + options.metadata.name = options.metadata.name || 'sentry.javascript.serverless'; Sentry.init(options); Sentry.addGlobalEventProcessor(serverlessEventProcessor('GCPFunction')); } diff --git a/packages/types/src/options.ts b/packages/types/src/options.ts index c9035e5eb133..4c0d04e46a86 100644 --- a/packages/types/src/options.ts +++ b/packages/types/src/options.ts @@ -2,6 +2,7 @@ import { Breadcrumb, BreadcrumbHint } from './breadcrumb'; import { Event, EventHint } from './event'; import { Integration } from './integration'; import { LogLevel } from './loglevel'; +import { SdkInfo } from './sdkinfo'; import { SamplingContext } from './transaction'; import { Transport, TransportClass, TransportOptions } from './transport'; @@ -106,6 +107,11 @@ export interface Options { */ shutdownTimeout?: number; + /** + * Set of metadata about the SDK that can be used to enhance envelopes/events and provide additional data about every request. + * */ + metadata?: Partial; + /** * Options which are in beta, or otherwise not guaranteed to be stable. */ diff --git a/packages/types/src/sdkinfo.ts b/packages/types/src/sdkinfo.ts index 45500cad5482..684230c4ac7e 100644 --- a/packages/types/src/sdkinfo.ts +++ b/packages/types/src/sdkinfo.ts @@ -1,6 +1,9 @@ import { Package } from './package'; -/** JSDoc */ +/** + * TODO: Remove `applyIntegrationsMetadata` method from the core and rely on the API instead, once we move to envelopes for all types of requests. + * TODO: Consider renaming to `SdkMetadata`. + */ export interface SdkInfo { name: string; version: string; diff --git a/packages/types/src/transport.ts b/packages/types/src/transport.ts index cfe318b997c7..bbac562bde1a 100644 --- a/packages/types/src/transport.ts +++ b/packages/types/src/transport.ts @@ -1,6 +1,7 @@ import { DsnLike } from './dsn'; import { Event } from './event'; import { Response } from './response'; +import { SdkInfo } from './sdkinfo'; import { Session } from './session'; /** Transport used sending data to Sentry */ @@ -44,4 +45,6 @@ export interface TransportOptions { caCerts?: string; /** Fetch API init parameters */ fetchParameters?: { [key: string]: string }; + /** Set of metadata about the SDK that can be used to enhance envelopes/events and provide additional data about every request. */ + metadata?: Partial; } diff --git a/packages/vue/src/sdk.ts b/packages/vue/src/sdk.ts index 824b5eb37307..69df7d54b93d 100644 --- a/packages/vue/src/sdk.ts +++ b/packages/vue/src/sdk.ts @@ -1,7 +1,6 @@ /* eslint-disable max-lines */ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { BrowserClient, BrowserOptions, defaultIntegrations, getCurrentHub } from '@sentry/browser'; -import { initAndBind } from '@sentry/core'; +import { BrowserOptions, getCurrentHub, init as browserInit } from '@sentry/browser'; import { Span, Transaction } from '@sentry/types'; import { basename, getGlobalObject, logger, timestampWithMs } from '@sentry/utils'; @@ -129,17 +128,6 @@ interface TracingOptions { export function init( options: Partial & { tracingOptions: Partial }> = {}, ): void { - if (options.defaultIntegrations === undefined) { - options.defaultIntegrations = defaultIntegrations; - } - if (options.release === undefined) { - const window = getGlobalObject(); - // This supports the variable that sentry-webpack-plugin injects - if (window.SENTRY_RELEASE && window.SENTRY_RELEASE.id) { - options.release = window.SENTRY_RELEASE.id; - } - } - const finalOptions = { // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access Vue: getGlobalObject().Vue as VueInstance, @@ -155,7 +143,10 @@ export function init( }, } as VueOptions; - initAndBind(BrowserClient, finalOptions); + finalOptions.metadata = finalOptions.metadata || {}; + finalOptions.metadata.name = finalOptions.metadata.name || 'sentry.javascript.serverless'; + + browserInit(finalOptions); if (finalOptions.Vue === undefined) { logger.warn('No Vue instance was provided. Also there is no Vue instance on the `window` object.'); logger.warn('We will only capture global unhandled errors.'); From acd4dd8e408b9cd94452c7a3cfa06a816d03992d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Og=C3=B3rek?= Date: Mon, 18 Jan 2021 13:24:04 +0100 Subject: [PATCH 2/4] Remove all sdkinfo related event processors --- packages/angular/src/errorhandler.ts | 19 ----- packages/angular/src/sdk.ts | 15 +++- packages/browser/package.json | 1 - packages/browser/src/backend.ts | 2 +- packages/browser/src/client.ts | 16 +--- packages/browser/src/sdk.ts | 16 +++- packages/browser/src/transports/base.ts | 2 +- packages/core/src/api.ts | 4 +- packages/core/src/request.ts | 49 +++++------ packages/core/src/sdk.ts | 4 - packages/ember/addon/index.ts | 37 +++------ packages/gatsby/gatsby-browser.js | 28 +++---- packages/gatsby/test/gatsby-browser.test.ts | 34 ++------ packages/node/package.json | 1 - packages/node/src/backend.ts | 2 +- packages/node/src/client.ts | 17 +--- packages/node/src/sdk.ts | 16 +++- packages/node/src/transports/base.ts | 2 +- packages/node/src/version.ts | 2 +- packages/react/src/index.ts | 30 ------- packages/react/src/sdk.ts | 15 +++- packages/serverless/src/awslambda.ts | 18 +++- packages/serverless/src/gcpfunction/index.ts | 18 +++- packages/serverless/src/utils.ts | 28 ++----- packages/serverless/test/awslambda.test.ts | 87 ++++++-------------- packages/serverless/test/gcpfunction.test.ts | 87 ++++++-------------- packages/types/src/index.ts | 1 + packages/types/src/options.ts | 27 +++--- packages/types/src/sdkinfo.ts | 4 - packages/types/src/transport.ts | 9 +- packages/vue/src/eventprocessor.ts | 25 ------ packages/vue/src/sdk.ts | 22 +++-- 32 files changed, 234 insertions(+), 404 deletions(-) delete mode 100644 packages/vue/src/eventprocessor.ts diff --git a/packages/angular/src/errorhandler.ts b/packages/angular/src/errorhandler.ts index 5b608d9bc4d0..b8a672956011 100644 --- a/packages/angular/src/errorhandler.ts +++ b/packages/angular/src/errorhandler.ts @@ -29,25 +29,6 @@ class SentryErrorHandler implements AngularErrorHandler { logErrors: true, ...options, }; - - Sentry.configureScope(scope => { - scope.addEventProcessor(event => { - event.sdk = { - ...event.sdk, - name: 'sentry.javascript.angular', - packages: [ - ...((event.sdk && event.sdk.packages) || []), - { - name: 'npm:@sentry/angular', - version: Sentry.SDK_VERSION, - }, - ], - version: Sentry.SDK_VERSION, - }; - - return event; - }); - }); } /** diff --git a/packages/angular/src/sdk.ts b/packages/angular/src/sdk.ts index 6a363c352425..09267d1f2082 100644 --- a/packages/angular/src/sdk.ts +++ b/packages/angular/src/sdk.ts @@ -1,10 +1,19 @@ -import { BrowserOptions, init as browserInit } from '@sentry/browser'; +import { BrowserOptions, init as browserInit, SDK_VERSION } from '@sentry/browser'; /** * Inits the Angular SDK */ export function init(options: BrowserOptions): void { - options.metadata = options.metadata || {}; - options.metadata.name = options.metadata.name || 'sentry.javascript.angular'; + options._metadata = options._metadata || {}; + options._metadata.sdk = { + name: 'sentry.javascript.angular', + packages: [ + { + name: 'npm:@sentry/angular', + version: SDK_VERSION, + }, + ], + version: SDK_VERSION, + }; browserInit(options); } diff --git a/packages/browser/package.json b/packages/browser/package.json index c90bbfca83b2..eab3161c7632 100644 --- a/packages/browser/package.json +++ b/packages/browser/package.json @@ -81,7 +81,6 @@ "size:check": "run-p size:check:es5 size:check:es6", "size:check:es5": "cat build/bundle.min.js | gzip -9 | wc -c | awk '{$1=$1/1024; print \"ES5: \",$1,\"kB\";}'", "size:check:es6": "cat build/bundle.es6.min.js | gzip -9 | wc -c | awk '{$1=$1/1024; print \"ES6: \",$1,\"kB\";}'", - "version": "node ../../scripts/versionbump.js src/version.ts", "pack": "npm pack" }, "volta": { diff --git a/packages/browser/src/backend.ts b/packages/browser/src/backend.ts index 03617700ee25..db4b83adfdf7 100644 --- a/packages/browser/src/backend.ts +++ b/packages/browser/src/backend.ts @@ -67,7 +67,7 @@ export class BrowserBackend extends BaseBackend { const transportOptions = { ...this._options.transportOptions, dsn: this._options.dsn, - metadata: this._options.metadata, + _metadata: this._options._metadata, }; if (this._options.transport) { diff --git a/packages/browser/src/client.ts b/packages/browser/src/client.ts index 7716bbbf5d58..35595f41abfb 100644 --- a/packages/browser/src/client.ts +++ b/packages/browser/src/client.ts @@ -1,11 +1,10 @@ -import { BaseClient, Scope, SDK_VERSION } from '@sentry/core'; +import { BaseClient, Scope } from '@sentry/core'; import { Event, EventHint } from '@sentry/types'; import { getGlobalObject, logger } from '@sentry/utils'; import { BrowserBackend, BrowserOptions } from './backend'; import { injectReportDialog, ReportDialogOptions } from './helpers'; import { Breadcrumbs } from './integrations'; -import { SDK_NAME } from './version'; /** * The Sentry Browser SDK Client. @@ -51,19 +50,6 @@ export class BrowserClient extends BaseClient { */ protected _prepareEvent(event: Event, scope?: Scope, hint?: EventHint): PromiseLike { event.platform = event.platform || 'javascript'; - event.sdk = { - ...event.sdk, - name: SDK_NAME, - packages: [ - ...((event.sdk && event.sdk.packages) || []), - { - name: 'npm:@sentry/browser', - version: SDK_VERSION, - }, - ], - version: SDK_VERSION, - }; - return super._prepareEvent(event, scope, hint); } diff --git a/packages/browser/src/sdk.ts b/packages/browser/src/sdk.ts index 01aacf0a9f06..d46e0253e4c1 100644 --- a/packages/browser/src/sdk.ts +++ b/packages/browser/src/sdk.ts @@ -1,11 +1,10 @@ -import { getCurrentHub, initAndBind, Integrations as CoreIntegrations } from '@sentry/core'; +import { getCurrentHub, initAndBind, Integrations as CoreIntegrations, SDK_VERSION } from '@sentry/core'; import { getGlobalObject, SyncPromise } from '@sentry/utils'; import { BrowserOptions } from './backend'; import { BrowserClient } from './client'; import { ReportDialogOptions, wrap as internalWrap } from './helpers'; import { Breadcrumbs, GlobalHandlers, LinkedErrors, TryCatch, UserAgent } from './integrations'; -import { SDK_NAME } from './version'; export const defaultIntegrations = [ new CoreIntegrations.InboundFilters(), @@ -89,8 +88,17 @@ export function init(options: BrowserOptions = {}): void { options.autoSessionTracking = false; } - options.metadata = options.metadata || {}; - options.metadata.name = options.metadata.name || SDK_NAME; + options._metadata = options._metadata || {}; + options._metadata.sdk = { + name: 'sentry.javascript.browser', + packages: [ + { + name: 'npm:@sentry/browser', + version: SDK_VERSION, + }, + ], + version: SDK_VERSION, + }; initAndBind(BrowserClient, options); diff --git a/packages/browser/src/transports/base.ts b/packages/browser/src/transports/base.ts index c8b408c288cc..09eb8b058bfd 100644 --- a/packages/browser/src/transports/base.ts +++ b/packages/browser/src/transports/base.ts @@ -26,7 +26,7 @@ export abstract class BaseTransport implements Transport { protected readonly _rateLimits: Record = {}; public constructor(public options: TransportOptions) { - this._api = new API(options.dsn, options.metadata); + this._api = new API(options.dsn, options._metadata); // eslint-disable-next-line deprecation/deprecation this.url = this._api.getStoreEndpointWithUrlEncodedAuth(); } diff --git a/packages/core/src/api.ts b/packages/core/src/api.ts index f359711aedde..333785d8b62c 100644 --- a/packages/core/src/api.ts +++ b/packages/core/src/api.ts @@ -1,4 +1,4 @@ -import { DsnLike, SdkInfo } from '@sentry/types'; +import { DsnLike, SdkMetadata } from '@sentry/types'; import { Dsn, urlEncode } from '@sentry/utils'; const SENTRY_API_VERSION = '7'; @@ -12,7 +12,7 @@ export class API { /** The internally used Dsn object. */ private readonly _dsnObject: Dsn; /** Create a new instance of API */ - public constructor(public dsn: DsnLike, public metadata?: Partial) { + public constructor(public dsn: DsnLike, public metadata?: SdkMetadata) { this._dsnObject = new Dsn(dsn); } diff --git a/packages/core/src/request.ts b/packages/core/src/request.ts index 0173adb2a332..01d80172abe5 100644 --- a/packages/core/src/request.ts +++ b/packages/core/src/request.ts @@ -1,33 +1,37 @@ import { Event, SdkInfo, SentryRequest, Session } from '@sentry/types'; -import { isString } from '@sentry/utils'; import { API } from './api'; -/** Extract envelope header containing sdk metadata from the API object */ -function getSdkMetadataForEnvelopeHeader(api: API): Partial | undefined { - if (!api.metadata) { - return; - } - - const { name, version } = api.metadata; - if (!isString(name) || !isString(version)) { +/** Extract sdk info from from the API metadata */ +function getSdkInfoFromApiMetadata(api: API): SdkInfo | undefined { + if (!api.metadata || !api.metadata.sdk) { return; } + return api.metadata.sdk; +} - return { - ...(isString(name) && { name }), - ...(isString(version) && { version }), +/** + * Apply SdkInfo (name, version, packages, integrations) to the corresponding event key. + * Merge with existing data if any. + **/ +function enhanceEventWithSdkInfo(event: Event, sdkInfo: SdkInfo): Event { + event.sdk = event.sdk || { + name: sdkInfo.name, + version: sdkInfo.version, }; + event.sdk.name = event.sdk.name || sdkInfo.name; + event.sdk.version = event.sdk.version || sdkInfo.version; + event.sdk.integrations = [...(event.sdk.integrations || []), ...(sdkInfo.integrations || [])]; + event.sdk.packages = [...(event.sdk.packages || []), ...(sdkInfo.packages || [])]; + return event; } /** Creates a SentryRequest from an event. */ export function sessionToSentryRequest(session: Session, api: API): SentryRequest { - const sdkMetadata = getSdkMetadataForEnvelopeHeader(api); + const sdkInfo = getSdkInfoFromApiMetadata(api); const envelopeHeaders = JSON.stringify({ sent_at: new Date().toISOString(), - ...(sdkMetadata && { - sdk: sdkMetadata, - }), + ...(sdkInfo && { sdk: sdkInfo }), }); const itemHeaders = JSON.stringify({ type: 'session', @@ -46,11 +50,13 @@ export function eventToSentryRequest(event: Event, api: API): SentryRequest { const { __sentry_samplingMethod: samplingMethod, __sentry_sampleRate: sampleRate, ...otherTags } = event.tags || {}; event.tags = otherTags; - const useEnvelope = event.type === 'transaction'; + const sdkInfo = getSdkInfoFromApiMetadata(api); + const eventType = event.type || 'event'; + const useEnvelope = eventType === 'transaction'; const req: SentryRequest = { - body: JSON.stringify(event), - type: event.type || 'event', + body: JSON.stringify(sdkInfo ? enhanceEventWithSdkInfo(event, sdkInfo) : event), + type: eventType, url: useEnvelope ? api.getEnvelopeEndpointWithUrlEncodedAuth() : api.getStoreEndpointWithUrlEncodedAuth(), }; @@ -61,13 +67,10 @@ export function eventToSentryRequest(event: Event, api: API): SentryRequest { // deserialization. Instead, we only implement a minimal subset of the spec to // serialize events inline here. if (useEnvelope) { - const sdkMetadata = getSdkMetadataForEnvelopeHeader(api); const envelopeHeaders = JSON.stringify({ event_id: event.event_id, sent_at: new Date().toISOString(), - ...(sdkMetadata && { - sdk: sdkMetadata, - }), + ...(sdkInfo && { sdk: sdkInfo }), }); const itemHeaders = JSON.stringify({ type: event.type, diff --git a/packages/core/src/sdk.ts b/packages/core/src/sdk.ts index 5720562346ee..17497c57f2be 100644 --- a/packages/core/src/sdk.ts +++ b/packages/core/src/sdk.ts @@ -2,8 +2,6 @@ import { getCurrentHub } from '@sentry/hub'; import { Client, Options } from '@sentry/types'; import { logger } from '@sentry/utils'; -import { SDK_VERSION } from './version'; - /** A class object that can instantiate Client objects. */ export type ClientClass = new (options: O) => F; @@ -18,8 +16,6 @@ export function initAndBind(clientClass: Cl if (options.debug === true) { logger.enable(); } - options.metadata = options.metadata || {}; - options.metadata.version = SDK_VERSION; const hub = getCurrentHub(); const client = new clientClass(options); hub.bindClient(client); diff --git a/packages/ember/addon/index.ts b/packages/ember/addon/index.ts index afa3c2d2aba7..3f8c56f3514d 100644 --- a/packages/ember/addon/index.ts +++ b/packages/ember/addon/index.ts @@ -1,5 +1,5 @@ import * as Sentry from '@sentry/browser'; -import { addGlobalEventProcessor, SDK_VERSION, BrowserOptions } from '@sentry/browser'; +import { SDK_VERSION, BrowserOptions } from '@sentry/browser'; import environmentConfig from 'ember-get-config'; import { macroCondition, isDevelopingApp } from '@embroider/macros'; import { next } from '@ember/runloop'; @@ -17,10 +17,18 @@ export function InitSentryForEmber(_runtimeConfig: BrowserOptions | undefined) { assert('Missing configuration for Sentry.', config.sentry); const initConfig = Object.assign({}, config.sentry, _runtimeConfig || {}); - initConfig.metadata = initConfig.metadata || {}; - initConfig.metadata.name = initConfig.metadata.name || 'sentry.javascript.ember'; - createEmberEventProcessor(); + initConfig._metadata = initConfig._metadata || {}; + initConfig._metadata.sdk = { + name: 'sentry.javascript.ember', + packages: [ + { + name: 'npm:@sentry/ember', + version: SDK_VERSION, + }, + ], + version: SDK_VERSION, + }; Sentry.init(initConfig); @@ -85,25 +93,4 @@ export const instrumentRoutePerformance = (BaseRoute: any) => { }[BaseRoute.name]; }; -function createEmberEventProcessor(): void { - if (addGlobalEventProcessor) { - addGlobalEventProcessor(event => { - event.sdk = { - ...event.sdk, - name: 'sentry.javascript.ember', - packages: [ - ...((event.sdk && event.sdk.packages) || []), - { - name: 'npm:@sentry/ember', - version: SDK_VERSION, - }, - ], - version: SDK_VERSION, - }; - - return event; - }); - } -} - export * from '@sentry/browser'; diff --git a/packages/gatsby/gatsby-browser.js b/packages/gatsby/gatsby-browser.js index ef12eb757646..5d08192be56e 100644 --- a/packages/gatsby/gatsby-browser.js +++ b/packages/gatsby/gatsby-browser.js @@ -6,8 +6,17 @@ exports.onClientEntry = function(_, pluginParams) { return; } - pluginParams.metadata = pluginParams.metadata || {}; - pluginParams.metadata.name = pluginParams.metadata.name || 'sentry.javascript.gatsby'; + pluginParams._metadata = pluginParams._metadata || {}; + pluginParams._metadata.sdk = { + name: 'sentry.javascript.gatsby', + packages: [ + { + name: 'npm:@sentry/gatsby', + version: Sentry.SDK_VERSION, + }, + ], + version: Sentry.SDK_VERSION, + }; const integrations = [...(pluginParams.integrations || [])]; @@ -27,20 +36,5 @@ exports.onClientEntry = function(_, pluginParams) { integrations, }); - Sentry.addGlobalEventProcessor(event => { - event.sdk = { - ...event.sdk, - name: 'sentry.javascript.gatsby', - packages: [ - ...((event.sdk && event.sdk.packages) || []), - { - name: 'npm:@sentry/gatsby', - version: Sentry.SDK_VERSION, - }, - ], - version: Sentry.SDK_VERSION, - }; - return event; - }); window.Sentry = Sentry; }; diff --git a/packages/gatsby/test/gatsby-browser.test.ts b/packages/gatsby/test/gatsby-browser.test.ts index ba83b407002f..7cfc3b61c557 100644 --- a/packages/gatsby/test/gatsby-browser.test.ts +++ b/packages/gatsby/test/gatsby-browser.test.ts @@ -7,7 +7,6 @@ const { onClientEntry } = require('../gatsby-browser'); (global as any).__SENTRY_DSN__ = 'https://examplePublicKey@o0.ingest.sentry.io/0'; let sentryInit = jest.fn(); -let sentryProcessEvent: (event: T) => T; jest.mock('@sentry/react', () => { const original = jest.requireActual('@sentry/react'); return { @@ -15,9 +14,6 @@ jest.mock('@sentry/react', () => { init: (...args: any[]) => { sentryInit(...args); }, - addGlobalEventProcessor: (callback: any) => { - sentryProcessEvent = callback; - }, }; }); @@ -36,9 +32,6 @@ describe('onClientEntry', () => { beforeEach(() => { sentryInit = jest.fn(); tracingAddExtensionMethods = jest.fn(); - - // @ts-ignore need to set as undefined - sentryProcessEvent = undefined; }); afterEach(() => { @@ -53,20 +46,7 @@ describe('onClientEntry', () => { environment: process.env.NODE_ENV, integrations: [], release: (global as any).__SENTRY_RELEASE__, - }); - }); - - it('sets window.Sentry', () => { - onClientEntry(undefined, {}); - expect((window as any).Sentry).not.toBeUndefined(); - }); - - it('adds a global event processor', () => { - onClientEntry(undefined, {}); - if (sentryProcessEvent) { - const changedEvent = sentryProcessEvent({}); - - expect(changedEvent).toEqual({ + _metadata: { sdk: { name: 'sentry.javascript.gatsby', packages: [ @@ -77,10 +57,13 @@ describe('onClientEntry', () => { ], version: expect.any(String), }, - }); - } else { - fail('process event not defined'); - } + }, + }); + }); + + it('sets window.Sentry', () => { + onClientEntry(undefined, {}); + expect((window as any).Sentry).not.toBeUndefined(); }); it('adds Tracing extension methods', () => { @@ -145,7 +128,6 @@ describe('onClientEntry', () => { onClientEntry(); expect(sentryInit).toHaveBeenCalledTimes(0); expect((window as any).Sentry).toBeUndefined(); - expect(sentryProcessEvent).toBeUndefined(); expect(tracingAddExtensionMethods).toHaveBeenCalledTimes(0); }); }); diff --git a/packages/node/package.json b/packages/node/package.json index 195a78c34420..a97a562bccb4 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -61,7 +61,6 @@ "test:watch": "jest --watch", "test:express": "node test/manual/express-scope-separation/start.js", "test:webpack": "cd test/manual/webpack-domain/ && yarn && node npm-build.js", - "version": "node ../../scripts/versionbump.js src/version.ts", "pack": "npm pack" }, "volta": { diff --git a/packages/node/src/backend.ts b/packages/node/src/backend.ts index 0aac0371b448..ad335f33eb01 100644 --- a/packages/node/src/backend.ts +++ b/packages/node/src/backend.ts @@ -140,7 +140,7 @@ export class NodeBackend extends BaseBackend { ...(this._options.httpsProxy && { httpsProxy: this._options.httpsProxy }), ...(this._options.caCerts && { caCerts: this._options.caCerts }), dsn: this._options.dsn, - metadata: this._options.metadata, + _metadata: this._options._metadata, }; if (this._options.transport) { diff --git a/packages/node/src/client.ts b/packages/node/src/client.ts index c82eebce1b76..13fc0d1f2af9 100644 --- a/packages/node/src/client.ts +++ b/packages/node/src/client.ts @@ -1,8 +1,7 @@ -import { BaseClient, Scope, SDK_VERSION } from '@sentry/core'; +import { BaseClient, Scope } from '@sentry/core'; import { Event, EventHint } from '@sentry/types'; import { NodeBackend, NodeOptions } from './backend'; -import { SDK_NAME } from './version'; /** * The Sentry Node SDK Client. @@ -24,23 +23,9 @@ export class NodeClient extends BaseClient { */ protected _prepareEvent(event: Event, scope?: Scope, hint?: EventHint): PromiseLike { event.platform = event.platform || 'node'; - event.sdk = { - ...event.sdk, - name: SDK_NAME, - packages: [ - ...((event.sdk && event.sdk.packages) || []), - { - name: 'npm:@sentry/node', - version: SDK_VERSION, - }, - ], - version: SDK_VERSION, - }; - if (this.getOptions().serverName) { event.server_name = this.getOptions().serverName; } - return super._prepareEvent(event, scope, hint); } } diff --git a/packages/node/src/sdk.ts b/packages/node/src/sdk.ts index 46a3b1327505..b846a37419a2 100644 --- a/packages/node/src/sdk.ts +++ b/packages/node/src/sdk.ts @@ -1,4 +1,4 @@ -import { getCurrentHub, initAndBind, Integrations as CoreIntegrations } from '@sentry/core'; +import { getCurrentHub, initAndBind, Integrations as CoreIntegrations, SDK_VERSION } from '@sentry/core'; import { getMainCarrier, setHubOnCarrier } from '@sentry/hub'; import { getGlobalObject } from '@sentry/utils'; import * as domain from 'domain'; @@ -6,7 +6,6 @@ import * as domain from 'domain'; import { NodeOptions } from './backend'; import { NodeClient } from './client'; import { Console, Http, LinkedErrors, OnUncaughtException, OnUnhandledRejection } from './integrations'; -import { SDK_NAME } from './version'; export const defaultIntegrations = [ // Common @@ -109,8 +108,17 @@ export function init(options: NodeOptions = {}): void { options.environment = process.env.SENTRY_ENVIRONMENT; } - options.metadata = options.metadata || {}; - options.metadata.name = options.metadata.name || SDK_NAME; + options._metadata = options._metadata || {}; + options._metadata.sdk = { + name: 'sentry.javascript.node', + packages: [ + { + name: 'npm:@sentry/node', + version: SDK_VERSION, + }, + ], + version: SDK_VERSION, + }; // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any if ((domain as any).active) { diff --git a/packages/node/src/transports/base.ts b/packages/node/src/transports/base.ts index 5c63f9a08bb6..1416e49339fe 100644 --- a/packages/node/src/transports/base.ts +++ b/packages/node/src/transports/base.ts @@ -53,7 +53,7 @@ export abstract class BaseTransport implements Transport { /** Create instance and set this.dsn */ public constructor(public options: TransportOptions) { - this._api = new API(options.dsn, options.metadata); + this._api = new API(options.dsn, options._metadata); } /** diff --git a/packages/node/src/version.ts b/packages/node/src/version.ts index b94bd71dd33c..8cfd1070cec5 100644 --- a/packages/node/src/version.ts +++ b/packages/node/src/version.ts @@ -1,2 +1,2 @@ -// TODO: Remove in the next major release and rely only on @sentry/core SDK_VERSION and SdkInfo metadata +// TODO: Remove in the next major release and rely only on @sentry/core SDK_VERSION and SdkMetadata export const SDK_NAME = 'sentry.javascript.node'; diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index aa3dc190a885..306f90e4f943 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -1,31 +1,3 @@ -import { addGlobalEventProcessor, SDK_VERSION } from '@sentry/browser'; - -/** - * A global side effect that makes sure Sentry events that user - * `@sentry/react` will correctly have Sentry events associated - * with it. - */ -function createReactEventProcessor(): void { - if (addGlobalEventProcessor) { - addGlobalEventProcessor(event => { - event.sdk = { - ...event.sdk, - name: 'sentry.javascript.react', - packages: [ - ...((event.sdk && event.sdk.packages) || []), - { - name: 'npm:@sentry/react', - version: SDK_VERSION, - }, - ], - version: SDK_VERSION, - }; - - return event; - }); - } -} - export * from '@sentry/browser'; export { init } from './sdk'; @@ -34,5 +6,3 @@ export { ErrorBoundary, withErrorBoundary } from './errorboundary'; export { createReduxEnhancer } from './redux'; export { reactRouterV3Instrumentation } from './reactrouterv3'; export { reactRouterV4Instrumentation, reactRouterV5Instrumentation, withSentryRouting } from './reactrouter'; - -createReactEventProcessor(); diff --git a/packages/react/src/sdk.ts b/packages/react/src/sdk.ts index 57c66b15177e..823b8ef47a42 100644 --- a/packages/react/src/sdk.ts +++ b/packages/react/src/sdk.ts @@ -1,10 +1,19 @@ -import { BrowserOptions, init as browserInit } from '@sentry/browser'; +import { BrowserOptions, init as browserInit, SDK_VERSION } from '@sentry/browser'; /** * Inits the React SDK */ export function init(options: BrowserOptions): void { - options.metadata = options.metadata || {}; - options.metadata.name = options.metadata.name || 'sentry.javascript.react'; + options._metadata = options._metadata || {}; + options._metadata.sdk = { + name: 'sentry.javascript.react', + packages: [ + { + name: 'npm:@sentry/react', + version: SDK_VERSION, + }, + ], + version: SDK_VERSION, + }; browserInit(options); } diff --git a/packages/serverless/src/awslambda.ts b/packages/serverless/src/awslambda.ts index 4c211a41c797..0c915cd19e25 100644 --- a/packages/serverless/src/awslambda.ts +++ b/packages/serverless/src/awslambda.ts @@ -56,10 +56,22 @@ export function init(options: Sentry.NodeOptions = {}): void { if (options.defaultIntegrations === undefined) { options.defaultIntegrations = defaultIntegrations; } - options.metadata = options.metadata || {}; - options.metadata.name = options.metadata.name || 'sentry.javascript.serverless'; + + options._metadata = options._metadata || {}; + options._metadata.sdk = { + name: 'sentry.javascript.serverless', + integrations: ['AWSLambda'], + packages: [ + { + name: 'npm:@sentry/serverless', + version: Sentry.SDK_VERSION, + }, + ], + version: Sentry.SDK_VERSION, + }; + Sentry.init(options); - Sentry.addGlobalEventProcessor(serverlessEventProcessor('AWSLambda')); + Sentry.addGlobalEventProcessor(serverlessEventProcessor); } /** */ diff --git a/packages/serverless/src/gcpfunction/index.ts b/packages/serverless/src/gcpfunction/index.ts index 4307a869b150..2cd8a0bec73f 100644 --- a/packages/serverless/src/gcpfunction/index.ts +++ b/packages/serverless/src/gcpfunction/index.ts @@ -22,8 +22,20 @@ export function init(options: Sentry.NodeOptions = {}): void { if (options.defaultIntegrations === undefined) { options.defaultIntegrations = defaultIntegrations; } - options.metadata = options.metadata || {}; - options.metadata.name = options.metadata.name || 'sentry.javascript.serverless'; + + options._metadata = options._metadata || {}; + options._metadata.sdk = { + name: 'sentry.javascript.serverless', + integrations: ['GCPFunction'], + packages: [ + { + name: 'npm:@sentry/serverless', + version: Sentry.SDK_VERSION, + }, + ], + version: Sentry.SDK_VERSION, + }; + Sentry.init(options); - Sentry.addGlobalEventProcessor(serverlessEventProcessor('GCPFunction')); + Sentry.addGlobalEventProcessor(serverlessEventProcessor); } diff --git a/packages/serverless/src/utils.ts b/packages/serverless/src/utils.ts index 1f4db9453ffe..6ea78a6cfc4d 100644 --- a/packages/serverless/src/utils.ts +++ b/packages/serverless/src/utils.ts @@ -1,4 +1,4 @@ -import { Event, SDK_VERSION } from '@sentry/node'; +import { Event } from '@sentry/node'; import { addExceptionMechanism } from '@sentry/utils'; import * as domain from 'domain'; @@ -9,28 +9,12 @@ import * as domain from 'domain'; * @param event Event * @param integration Name of the serverless integration ('AWSLambda', 'GCPFunction', etc) */ -export function serverlessEventProcessor(integration: string): (event: Event) => Event { - return event => { - event.sdk = { - ...event.sdk, - name: 'sentry.javascript.serverless', - integrations: [...((event.sdk && event.sdk.integrations) || []), integration], - packages: [ - ...((event.sdk && event.sdk.packages) || []), - { - name: 'npm:@sentry/serverless', - version: SDK_VERSION, - }, - ], - version: SDK_VERSION, - }; - - addExceptionMechanism(event, { - handled: false, - }); +export function serverlessEventProcessor(event: Event): Event { + addExceptionMechanism(event, { + handled: false, + }); - return event; - }; + return event; } /** diff --git a/packages/serverless/test/awslambda.test.ts b/packages/serverless/test/awslambda.test.ts index e80b79f2515d..003e357fca59 100644 --- a/packages/serverless/test/awslambda.test.ts +++ b/packages/serverless/test/awslambda.test.ts @@ -341,66 +341,40 @@ describe('AWSLambda', () => { }); describe('init()', () => { - test('enhance event with SDK info and correct mechanism value', async () => { - expect.assertions(1); - - const eventWithSomeData = { - exception: { - values: [{}], - }, - sdk: { - integrations: ['SomeIntegration'], - packages: [ - { - name: 'some:@random/package', - version: '1337', - }, - ], - }, - }; - // @ts-ignore see "Why @ts-ignore" note - Sentry.addGlobalEventProcessor.mockImplementationOnce(cb => cb(eventWithSomeData)); - Sentry.AWSLambda.init({ defaultIntegrations: [] }); - expect(eventWithSomeData).toEqual({ - exception: { - values: [ - { - mechanism: { - handled: false, - }, - }, - ], - }, - sdk: { - name: 'sentry.javascript.serverless', - integrations: ['SomeIntegration', 'AWSLambda'], - packages: [ - { - name: 'some:@random/package', - version: '1337', - }, - { - name: 'npm:@sentry/serverless', + test('calls Sentry.init with correct sdk info metadata', () => { + Sentry.AWSLambda.init({}); + + expect(Sentry.init).toBeCalledWith( + expect.objectContaining({ + _metadata: { + sdk: { + name: 'sentry.javascript.serverless', + integrations: ['AWSLambda'], + packages: [ + { + name: 'npm:@sentry/serverless', + version: '6.6.6', + }, + ], version: '6.6.6', }, - ], - version: '6.6.6', - }, - }); + }, + }), + ); }); - test('populates missing SDK info and mechanism', async () => { - expect.assertions(1); - - const eventWithoutAnyData: Event = { + test('enhance event with correct mechanism value', () => { + const eventWithSomeData = { exception: { values: [{}], }, }; + // @ts-ignore see "Why @ts-ignore" note - Sentry.addGlobalEventProcessor.mockImplementationOnce(cb => cb(eventWithoutAnyData)); - Sentry.AWSLambda.init({ defaultIntegrations: [] }); - expect(eventWithoutAnyData).toEqual({ + Sentry.addGlobalEventProcessor.mockImplementationOnce(cb => cb(eventWithSomeData)); + Sentry.AWSLambda.init({}); + + expect(eventWithSomeData).toEqual({ exception: { values: [ { @@ -410,17 +384,6 @@ describe('AWSLambda', () => { }, ], }, - sdk: { - name: 'sentry.javascript.serverless', - integrations: ['AWSLambda'], - packages: [ - { - name: 'npm:@sentry/serverless', - version: '6.6.6', - }, - ], - version: '6.6.6', - }, }); }); }); diff --git a/packages/serverless/test/gcpfunction.test.ts b/packages/serverless/test/gcpfunction.test.ts index 0f7903df3240..b11a5b0b99dc 100644 --- a/packages/serverless/test/gcpfunction.test.ts +++ b/packages/serverless/test/gcpfunction.test.ts @@ -361,66 +361,40 @@ describe('GCPFunction', () => { }); describe('init()', () => { - test('enhance event with SDK info and correct mechanism value', async () => { - expect.assertions(1); - - const eventWithSomeData = { - exception: { - values: [{}], - }, - sdk: { - integrations: ['SomeIntegration'], - packages: [ - { - name: 'some:@random/package', - version: '1337', - }, - ], - }, - }; - // @ts-ignore see "Why @ts-ignore" note - Sentry.addGlobalEventProcessor.mockImplementationOnce(cb => cb(eventWithSomeData)); - Sentry.AWSLambda.init({ defaultIntegrations: [] }); - expect(eventWithSomeData).toEqual({ - exception: { - values: [ - { - mechanism: { - handled: false, - }, - }, - ], - }, - sdk: { - name: 'sentry.javascript.serverless', - integrations: ['SomeIntegration', 'AWSLambda'], - packages: [ - { - name: 'some:@random/package', - version: '1337', - }, - { - name: 'npm:@sentry/serverless', + test('calls Sentry.init with correct sdk info metadata', () => { + Sentry.GCPFunction.init({}); + + expect(Sentry.init).toBeCalledWith( + expect.objectContaining({ + _metadata: { + sdk: { + name: 'sentry.javascript.serverless', + integrations: ['GCPFunction'], + packages: [ + { + name: 'npm:@sentry/serverless', + version: '6.6.6', + }, + ], version: '6.6.6', }, - ], - version: '6.6.6', - }, - }); + }, + }), + ); }); - test('populates missing SDK info and mechanism', async () => { - expect.assertions(1); - - const eventWithoutAnyData: Event = { + test('enhance event with correct mechanism value', () => { + const eventWithSomeData = { exception: { values: [{}], }, }; + // @ts-ignore see "Why @ts-ignore" note - Sentry.addGlobalEventProcessor.mockImplementationOnce(cb => cb(eventWithoutAnyData)); - Sentry.AWSLambda.init({ defaultIntegrations: [] }); - expect(eventWithoutAnyData).toEqual({ + Sentry.addGlobalEventProcessor.mockImplementationOnce(cb => cb(eventWithSomeData)); + Sentry.GCPFunction.init({}); + + expect(eventWithSomeData).toEqual({ exception: { values: [ { @@ -430,17 +404,6 @@ describe('GCPFunction', () => { }, ], }, - sdk: { - name: 'sentry.javascript.serverless', - integrations: ['AWSLambda'], - packages: [ - { - name: 'npm:@sentry/serverless', - version: '6.6.6', - }, - ], - version: '6.6.6', - }, }); }); }); diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index fc288847b41a..d334d16b14e1 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -19,6 +19,7 @@ export { Response } from './response'; export { Runtime } from './runtime'; export { CaptureContext, Scope, ScopeContext } from './scope'; export { SdkInfo } from './sdkinfo'; +export { SdkMetadata } from './sdkmetadata'; export { Session, SessionContext, SessionStatus } from './session'; export { Severity } from './severity'; export { Span, SpanContext } from './span'; diff --git a/packages/types/src/options.ts b/packages/types/src/options.ts index 4c0d04e46a86..413c39e81ac4 100644 --- a/packages/types/src/options.ts +++ b/packages/types/src/options.ts @@ -2,7 +2,7 @@ import { Breadcrumb, BreadcrumbHint } from './breadcrumb'; import { Event, EventHint } from './event'; import { Integration } from './integration'; import { LogLevel } from './loglevel'; -import { SdkInfo } from './sdkinfo'; +import { SdkMetadata } from './sdkmetadata'; import { SamplingContext } from './transaction'; import { Transport, TransportClass, TransportOptions } from './transport'; @@ -107,18 +107,6 @@ export interface Options { */ shutdownTimeout?: number; - /** - * Set of metadata about the SDK that can be used to enhance envelopes/events and provide additional data about every request. - * */ - metadata?: Partial; - - /** - * Options which are in beta, or otherwise not guaranteed to be stable. - */ - _experiments?: { - [key: string]: any; - }; - /** * Sample rate to determine trace sampling. * @@ -130,6 +118,19 @@ export interface Options { */ tracesSampleRate?: number; + /** + * Set of metadata about the SDK that can be internally used to enhance envelopes and events, + * and provide additional data about every request. + * */ + _metadata?: SdkMetadata; + + /** + * Options which are in beta, or otherwise not guaranteed to be stable. + */ + _experiments?: { + [key: string]: any; + }; + /** * Function to compute tracing sample rate dynamically and filter unwanted traces. * diff --git a/packages/types/src/sdkinfo.ts b/packages/types/src/sdkinfo.ts index 684230c4ac7e..14bb3c331509 100644 --- a/packages/types/src/sdkinfo.ts +++ b/packages/types/src/sdkinfo.ts @@ -1,9 +1,5 @@ import { Package } from './package'; -/** - * TODO: Remove `applyIntegrationsMetadata` method from the core and rely on the API instead, once we move to envelopes for all types of requests. - * TODO: Consider renaming to `SdkMetadata`. - */ export interface SdkInfo { name: string; version: string; diff --git a/packages/types/src/transport.ts b/packages/types/src/transport.ts index bbac562bde1a..3987768f32fd 100644 --- a/packages/types/src/transport.ts +++ b/packages/types/src/transport.ts @@ -1,7 +1,7 @@ import { DsnLike } from './dsn'; import { Event } from './event'; import { Response } from './response'; -import { SdkInfo } from './sdkinfo'; +import { SdkMetadata } from './sdkmetadata'; import { Session } from './session'; /** Transport used sending data to Sentry */ @@ -45,6 +45,9 @@ export interface TransportOptions { caCerts?: string; /** Fetch API init parameters */ fetchParameters?: { [key: string]: string }; - /** Set of metadata about the SDK that can be used to enhance envelopes/events and provide additional data about every request. */ - metadata?: Partial; + /** + * Set of metadata about the SDK that can be internally used to enhance envelopes and events, + * and provide additional data about every request. + * */ + _metadata?: SdkMetadata; } diff --git a/packages/vue/src/eventprocessor.ts b/packages/vue/src/eventprocessor.ts deleted file mode 100644 index 9a0f55b7ff47..000000000000 --- a/packages/vue/src/eventprocessor.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { addGlobalEventProcessor, SDK_VERSION } from '@sentry/browser'; - -/** - * A global side effect that makes sure Sentry events that user - * `@sentry/react` will correctly have Sentry events associated - * with it. - */ -export function createVueEventProcessor(): void { - addGlobalEventProcessor(event => { - event.sdk = { - ...event.sdk, - name: 'sentry.javascript.vue', - packages: [ - ...((event.sdk && event.sdk.packages) || []), - { - name: 'npm:@sentry/vue', - version: SDK_VERSION, - }, - ], - version: SDK_VERSION, - }; - - return event; - }); -} diff --git a/packages/vue/src/sdk.ts b/packages/vue/src/sdk.ts index 69df7d54b93d..0655cdd86c7a 100644 --- a/packages/vue/src/sdk.ts +++ b/packages/vue/src/sdk.ts @@ -1,11 +1,8 @@ -/* eslint-disable max-lines */ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { BrowserOptions, getCurrentHub, init as browserInit } from '@sentry/browser'; +/* eslint-disable max-lines, @typescript-eslint/no-explicit-any */ +import { BrowserOptions, getCurrentHub, init as browserInit, SDK_VERSION } from '@sentry/browser'; import { Span, Transaction } from '@sentry/types'; import { basename, getGlobalObject, logger, timestampWithMs } from '@sentry/utils'; -import { createVueEventProcessor } from './eventprocessor'; - export interface VueOptions extends BrowserOptions { /** Vue instance to be used inside the integration */ Vue?: VueInstance; @@ -143,8 +140,17 @@ export function init( }, } as VueOptions; - finalOptions.metadata = finalOptions.metadata || {}; - finalOptions.metadata.name = finalOptions.metadata.name || 'sentry.javascript.serverless'; + finalOptions._metadata = finalOptions._metadata || {}; + finalOptions._metadata.sdk = { + name: 'sentry.javascript.vue', + packages: [ + { + name: 'npm:@sentry/vue', + version: SDK_VERSION, + }, + ], + version: SDK_VERSION, + }; browserInit(finalOptions); if (finalOptions.Vue === undefined) { @@ -154,8 +160,6 @@ export function init( const vueHelper = new VueHelper(finalOptions); vueHelper.setup(); } - - createVueEventProcessor(); } /** JSDoc */ From f58a45909171ccd743c3fbd42b7b530960c0dea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Og=C3=B3rek?= Date: Mon, 18 Jan 2021 13:42:56 +0100 Subject: [PATCH 3/4] Adds request tests --- packages/core/src/api.ts | 2 +- packages/core/src/request.ts | 15 +++-- packages/core/test/lib/request.test.ts | 92 ++++++++++++++++++++++---- packages/types/src/sdkmetadata.ts | 5 ++ 4 files changed, 96 insertions(+), 18 deletions(-) create mode 100644 packages/types/src/sdkmetadata.ts diff --git a/packages/core/src/api.ts b/packages/core/src/api.ts index 333785d8b62c..4dadd5539ba3 100644 --- a/packages/core/src/api.ts +++ b/packages/core/src/api.ts @@ -12,7 +12,7 @@ export class API { /** The internally used Dsn object. */ private readonly _dsnObject: Dsn; /** Create a new instance of API */ - public constructor(public dsn: DsnLike, public metadata?: SdkMetadata) { + public constructor(public dsn: DsnLike, public metadata: SdkMetadata = {}) { this._dsnObject = new Dsn(dsn); } diff --git a/packages/core/src/request.ts b/packages/core/src/request.ts index 01d80172abe5..175aef0f289f 100644 --- a/packages/core/src/request.ts +++ b/packages/core/src/request.ts @@ -3,11 +3,12 @@ import { Event, SdkInfo, SentryRequest, Session } from '@sentry/types'; import { API } from './api'; /** Extract sdk info from from the API metadata */ -function getSdkInfoFromApiMetadata(api: API): SdkInfo | undefined { +function getSdkMetadataForEnvelopeHeader(api: API): SdkInfo | undefined { if (!api.metadata || !api.metadata.sdk) { return; } - return api.metadata.sdk; + const { name, version } = api.metadata.sdk; + return { name, version }; } /** @@ -15,6 +16,10 @@ function getSdkInfoFromApiMetadata(api: API): SdkInfo | undefined { * Merge with existing data if any. **/ function enhanceEventWithSdkInfo(event: Event, sdkInfo: SdkInfo): Event { + if (!sdkInfo) { + return event; + } + event.sdk = event.sdk || { name: sdkInfo.name, version: sdkInfo.version, @@ -28,7 +33,7 @@ function enhanceEventWithSdkInfo(event: Event, sdkInfo: SdkInfo): Event { /** Creates a SentryRequest from an event. */ export function sessionToSentryRequest(session: Session, api: API): SentryRequest { - const sdkInfo = getSdkInfoFromApiMetadata(api); + const sdkInfo = getSdkMetadataForEnvelopeHeader(api); const envelopeHeaders = JSON.stringify({ sent_at: new Date().toISOString(), ...(sdkInfo && { sdk: sdkInfo }), @@ -50,12 +55,12 @@ export function eventToSentryRequest(event: Event, api: API): SentryRequest { const { __sentry_samplingMethod: samplingMethod, __sentry_sampleRate: sampleRate, ...otherTags } = event.tags || {}; event.tags = otherTags; - const sdkInfo = getSdkInfoFromApiMetadata(api); + const sdkInfo = getSdkMetadataForEnvelopeHeader(api); const eventType = event.type || 'event'; const useEnvelope = eventType === 'transaction'; const req: SentryRequest = { - body: JSON.stringify(sdkInfo ? enhanceEventWithSdkInfo(event, sdkInfo) : event), + body: JSON.stringify(sdkInfo ? enhanceEventWithSdkInfo(event, api.metadata.sdk) : event), type: eventType, url: useEnvelope ? api.getEnvelopeEndpointWithUrlEncodedAuth() : api.getStoreEndpointWithUrlEncodedAuth(), }; diff --git a/packages/core/test/lib/request.test.ts b/packages/core/test/lib/request.test.ts index be71d72cc8b8..4e19cf5680a8 100644 --- a/packages/core/test/lib/request.test.ts +++ b/packages/core/test/lib/request.test.ts @@ -4,17 +4,29 @@ import { API } from '../../src/api'; import { eventToSentryRequest } from '../../src/request'; describe('eventToSentryRequest', () => { - const api = new API('https://dogsarebadatkeepingsecrets@squirrelchasers.ingest.sentry.io/12312012'); - const event: Event = { - contexts: { trace: { trace_id: '1231201211212012', span_id: '12261980', op: 'pageload' } }, - environment: 'dogpark', - event_id: '0908201304152013', - release: 'off.leash.park', - spans: [], - transaction: '/dogs/are/great/', - type: 'transaction', - user: { id: '1121', username: 'CharlieDog', ip_address: '11.21.20.12' }, - }; + let api: API; + let event: Event; + + beforeEach(() => { + api = new API('https://dogsarebadatkeepingsecrets@squirrelchasers.ingest.sentry.io/12312012', { + sdk: { + integrations: ['AWSLambda'], + name: 'sentry.javascript.browser', + version: `12.31.12`, + packages: [{ name: 'npm:@sentry/browser', version: `6.6.6` }], + }, + }); + event = { + contexts: { trace: { trace_id: '1231201211212012', span_id: '12261980', op: 'pageload' } }, + environment: 'dogpark', + event_id: '0908201304152013', + release: 'off.leash.park', + spans: [], + transaction: '/dogs/are/great/', + type: 'transaction', + user: { id: '1121', username: 'CharlieDog', ip_address: '11.21.20.12' }, + }; + }); [ { method: TransactionSamplingMethod.Rate, rate: '0.1121', dog: 'Charlie' }, @@ -30,7 +42,7 @@ describe('eventToSentryRequest', () => { // TODO kmclb - once tag types are loosened, don't need to cast to string here event.tags = { __sentry_samplingMethod: String(method), __sentry_sampleRate: String(rate), dog }; - const result = eventToSentryRequest(event as Event, api); + const result = eventToSentryRequest(event, api); const [envelopeHeaderString, itemHeaderString, eventString] = result.body.split('\n'); @@ -53,4 +65,60 @@ describe('eventToSentryRequest', () => { expect('dog' in envelope.event.tags).toBe(true); }); }); + + it('adds sdk info to envelope header', () => { + const result = eventToSentryRequest(event, api); + + const envelopeHeaderString = result.body.split('\n')[0]; + const parsedHeader = JSON.parse(envelopeHeaderString); + + expect(parsedHeader).toEqual( + expect.objectContaining({ sdk: { name: 'sentry.javascript.browser', version: '12.31.12' } }), + ); + }); + + it('adds sdk info to event body', () => { + const result = eventToSentryRequest(event, api); + + const eventString = result.body.split('\n')[2]; + const parsedEvent = JSON.parse(eventString); + + expect(parsedEvent).toEqual( + expect.objectContaining({ + sdk: { + integrations: ['AWSLambda'], + name: 'sentry.javascript.browser', + version: `12.31.12`, + packages: [{ name: 'npm:@sentry/browser', version: `6.6.6` }], + }, + }), + ); + }); + + it('merges existing sdk info if one is present on the event body', () => { + event.sdk = { + integrations: ['Clojure'], + name: 'foo', + packages: [{ name: 'npm:@sentry/clj', version: `6.6.6` }], + version: '1337', + }; + const result = eventToSentryRequest(event, api); + + const eventString = result.body.split('\n')[2]; + const parsedEvent = JSON.parse(eventString); + + expect(parsedEvent).toEqual( + expect.objectContaining({ + sdk: { + integrations: ['Clojure', 'AWSLambda'], + name: 'foo', + packages: [ + { name: 'npm:@sentry/clj', version: `6.6.6` }, + { name: 'npm:@sentry/browser', version: `6.6.6` }, + ], + version: '1337', + }, + }), + ); + }); }); diff --git a/packages/types/src/sdkmetadata.ts b/packages/types/src/sdkmetadata.ts new file mode 100644 index 000000000000..d65e989cb4c1 --- /dev/null +++ b/packages/types/src/sdkmetadata.ts @@ -0,0 +1,5 @@ +import { SdkInfo } from './sdkinfo'; + +export interface SdkMetadata { + sdk?: SdkInfo; +} From d3cb487812be499a2f67690c23a086c0db7a8346 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Og=C3=B3rek?= Date: Mon, 18 Jan 2021 13:50:45 +0100 Subject: [PATCH 4/4] Make sdkInfo optional in enhanceEventWithSdkInfo --- packages/core/src/request.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/request.ts b/packages/core/src/request.ts index 175aef0f289f..5a2e966f48f8 100644 --- a/packages/core/src/request.ts +++ b/packages/core/src/request.ts @@ -15,7 +15,7 @@ function getSdkMetadataForEnvelopeHeader(api: API): SdkInfo | undefined { * Apply SdkInfo (name, version, packages, integrations) to the corresponding event key. * Merge with existing data if any. **/ -function enhanceEventWithSdkInfo(event: Event, sdkInfo: SdkInfo): Event { +function enhanceEventWithSdkInfo(event: Event, sdkInfo?: SdkInfo): Event { if (!sdkInfo) { return event; }