Skip to content

Commit

Permalink
ref(core)!: Remove Scope type interface in favor of using Scope c…
Browse files Browse the repository at this point in the history
…lass (#14721)

In v8, types have been exported from `@sentry/types`, while
implementations have been exported from other classes.
This lead to some duplication, where we had to keep an interface in
`@sentry/types`, while the implementation mirroring that interface was
kept e.g. in `@sentry/core`.
Since in v9 the types have been merged into `@sentry/core`, we can get
rid of some of this duplication. This means that certain things that
used to be a separate interface, will not expect an actual instance of
the class/concrete implementation. This should not affect most users,
unless you relied on passing things with a similar shape to internal
methods.

This PR removes the `Scope` interface, in favor of just using the scope
class everywhere.

This is related to
#9840

---------

Co-authored-by: Sigrid Huemer <[email protected]>
  • Loading branch information
mydea and s1gr1d authored Dec 17, 2024
1 parent f862dd6 commit c1d374d
Show file tree
Hide file tree
Showing 28 changed files with 178 additions and 388 deletions.
8 changes: 8 additions & 0 deletions docs/migration/v8-to-v9.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,14 @@ Object.defineProperty(exports, '__esModule', { value: true });
The SDK no longer contains these statements.
Let us know if this is causing issues in your setup by opening an issue on GitHub.

## 6. Type Changes

In v8, types have been exported from `@sentry/types`, while implementations have been exported from other classes.
This led to some duplication, where we had to keep an interface in `@sentry/types`, while the implementation mirroring that interface was kept e.g. in `@sentry/core`.
Since v9, the types have been merged into `@sentry/core`, which removed some of this duplication. This means that certain things that used to be a separate interface, will not expect an actual instance of the class/concrete implementation. This should not affect most users, unless you relied on passing things with a similar shape to internal methods. The following types are affected:

- `Scope` now always expects the `Scope` class

# No Version Support Timeline

Version support timelines are stressful for anybody using the SDK, so we won't be defining one.
Expand Down
24 changes: 12 additions & 12 deletions packages/core/src/asyncContext/stackStrategy.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import { getDefaultCurrentScope, getDefaultIsolationScope } from '../defaultScopes';
import { Scope } from '../scope';
import type { Client, Scope as ScopeInterface } from '../types-hoist';
import type { Client } from '../types-hoist';
import { isThenable } from '../utils-hoist/is';
import { getMainCarrier, getSentryCarrier } from './../carrier';
import type { AsyncContextStrategy } from './types';

interface Layer {
client?: Client;
scope: ScopeInterface;
scope: Scope;
}

/**
* This is an object that holds a stack of scopes.
*/
export class AsyncContextStack {
private readonly _stack: [Layer, ...Layer[]];
private _isolationScope: ScopeInterface;
private _isolationScope: Scope;

public constructor(scope?: ScopeInterface, isolationScope?: ScopeInterface) {
public constructor(scope?: Scope, isolationScope?: Scope) {
let assignedScope;
if (!scope) {
assignedScope = new Scope();
Expand All @@ -40,7 +40,7 @@ export class AsyncContextStack {
/**
* Fork a scope for the stack.
*/
public withScope<T>(callback: (scope: ScopeInterface) => T): T {
public withScope<T>(callback: (scope: Scope) => T): T {
const scope = this._pushScope();

let maybePromiseResult: T;
Expand Down Expand Up @@ -79,14 +79,14 @@ export class AsyncContextStack {
/**
* Returns the scope of the top stack.
*/
public getScope(): ScopeInterface {
public getScope(): Scope {
return this.getStackTop().scope;
}

/**
* Get the isolation scope for the stack.
*/
public getIsolationScope(): ScopeInterface {
public getIsolationScope(): Scope {
return this._isolationScope;
}

Expand All @@ -100,7 +100,7 @@ export class AsyncContextStack {
/**
* Push a scope to the stack.
*/
private _pushScope(): ScopeInterface {
private _pushScope(): Scope {
// We want to clone the content of prev scope
const scope = this.getScope().clone();
this._stack.push({
Expand Down Expand Up @@ -130,19 +130,19 @@ function getAsyncContextStack(): AsyncContextStack {
return (sentry.stack = sentry.stack || new AsyncContextStack(getDefaultCurrentScope(), getDefaultIsolationScope()));
}

function withScope<T>(callback: (scope: ScopeInterface) => T): T {
function withScope<T>(callback: (scope: Scope) => T): T {
return getAsyncContextStack().withScope(callback);
}

function withSetScope<T>(scope: ScopeInterface, callback: (scope: ScopeInterface) => T): T {
function withSetScope<T>(scope: Scope, callback: (scope: Scope) => T): T {
const stack = getAsyncContextStack() as AsyncContextStack;
return stack.withScope(() => {
stack.getStackTop().scope = scope;
return callback(scope);
});
}

function withIsolationScope<T>(callback: (isolationScope: ScopeInterface) => T): T {
function withIsolationScope<T>(callback: (isolationScope: Scope) => T): T {
return getAsyncContextStack().withScope(() => {
return callback(getAsyncContextStack().getIsolationScope());
});
Expand All @@ -156,7 +156,7 @@ export function getStackAsyncContextStrategy(): AsyncContextStrategy {
withIsolationScope,
withScope,
withSetScope,
withSetIsolationScope: <T>(_isolationScope: ScopeInterface, callback: (isolationScope: ScopeInterface) => T) => {
withSetIsolationScope: <T>(_isolationScope: Scope, callback: (isolationScope: Scope) => T) => {
return withIsolationScope(callback);
},
getCurrentScope: () => getAsyncContextStack().getScope(),
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/asyncContext/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Scope } from '../types-hoist';
import type { Scope } from '../scope';
import type { getTraceData } from '../utils/traceData';
import type {
startInactiveSpan,
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/carrier.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { AsyncContextStack } from './asyncContext/stackStrategy';
import type { AsyncContextStrategy } from './asyncContext/types';
import type { Client, MetricsAggregator, Scope } from './types-hoist';
import type { Scope } from './scope';
import type { Client, MetricsAggregator } from './types-hoist';
import type { Logger } from './utils-hoist/logger';
import { SDK_VERSION } from './utils-hoist/version';
import { GLOBAL_OBJ } from './utils-hoist/worldwide';
Expand Down
9 changes: 4 additions & 5 deletions packages/core/src/currentScopes.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { getAsyncContextStrategy } from './asyncContext';
import { getMainCarrier } from './carrier';
import { getGlobalSingleton } from './carrier';
import { Scope as ScopeClass } from './scope';
import type { Client, Scope, TraceContext } from './types-hoist';
import { getGlobalSingleton, getMainCarrier } from './carrier';
import { Scope } from './scope';
import type { Client, TraceContext } from './types-hoist';
import { dropUndefinedKeys } from './utils-hoist/object';

/**
Expand All @@ -29,7 +28,7 @@ export function getIsolationScope(): Scope {
* This scope is applied to _all_ events.
*/
export function getGlobalScope(): Scope {
return getGlobalSingleton('globalScope', () => new ScopeClass());
return getGlobalSingleton('globalScope', () => new Scope());
}

/**
Expand Down
7 changes: 3 additions & 4 deletions packages/core/src/defaultScopes.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { getGlobalSingleton } from './carrier';
import { Scope as ScopeClass } from './scope';
import type { Scope } from './types-hoist';
import { Scope } from './scope';

/** Get the default current scope. */
export function getDefaultCurrentScope(): Scope {
return getGlobalSingleton('defaultCurrentScope', () => new ScopeClass());
return getGlobalSingleton('defaultCurrentScope', () => new Scope());
}

/** Get the default isolation scope. */
export function getDefaultIsolationScope(): Scope {
return getGlobalSingleton('defaultIsolationScope', () => new ScopeClass());
return getGlobalSingleton('defaultIsolationScope', () => new Scope());
}
2 changes: 1 addition & 1 deletion packages/core/src/exports.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type {
CaptureContext,
CheckIn,
Event,
EventHint,
Expand All @@ -18,6 +17,7 @@ import type {
import { DEFAULT_ENVIRONMENT } from './constants';
import { getClient, getCurrentScope, getIsolationScope, withIsolationScope } from './currentScopes';
import { DEBUG_BUILD } from './debug-build';
import type { CaptureContext } from './scope';
import { closeSession, makeSession, updateSession } from './session';
import { isThenable } from './utils-hoist/is';
import { logger } from './utils-hoist/logger';
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/fetch.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import type { Scope } from './scope';
import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from './semanticAttributes';
import { SPAN_STATUS_ERROR, setHttpStatus, startInactiveSpan } from './tracing';
import { SentryNonRecordingSpan } from './tracing/sentryNonRecordingSpan';
import type { Client, HandlerDataFetch, Scope, Span, SpanOrigin } from './types-hoist';
import type { Client, HandlerDataFetch, Span, SpanOrigin } from './types-hoist';
import { SENTRY_BAGGAGE_KEY_PREFIX } from './utils-hoist/baggage';
import { isInstanceOf } from './utils-hoist/is';
import { parseUrl } from './utils-hoist/url';
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export { makeSession, closeSession, updateSession } from './session';
// eslint-disable-next-line deprecation/deprecation
export { SessionFlusher } from './sessionflusher';
export { Scope } from './scope';
export type { CaptureContext, ScopeContext, ScopeData } from './scope';
export { notifyEventProcessors } from './eventProcessors';
export { getEnvelopeEndpointWithUrlEncodedAuth, getReportDialogEndpoint } from './api';
export { BaseClient } from './baseclient';
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/integrations/captureconsole.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { getClient, withScope } from '../currentScopes';
import { captureException, captureMessage } from '../exports';
import { defineIntegration } from '../integration';
import type { CaptureContext, IntegrationFn } from '../types-hoist';
import type { CaptureContext } from '../scope';
import type { IntegrationFn } from '../types-hoist';
import { addConsoleInstrumentationHandler } from '../utils-hoist/instrument/console';
import { CONSOLE_LEVELS } from '../utils-hoist/logger';
import { addExceptionMechanism } from '../utils-hoist/misc';
Expand Down
Loading

0 comments on commit c1d374d

Please sign in to comment.