Skip to content

Commit 47eef3a

Browse files
committed
fix capture methods
1 parent 0080af5 commit 47eef3a

File tree

3 files changed

+84
-8
lines changed

3 files changed

+84
-8
lines changed

packages/node-experimental/src/sdk/api.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { DEFAULT_ENVIRONMENT, closeSession, makeSession, updateSession } from '@
55
import type {
66
Breadcrumb,
77
BreadcrumbHint,
8+
CaptureContext,
89
Client,
910
Event,
1011
EventHint,
@@ -17,9 +18,10 @@ import type {
1718
SeverityLevel,
1819
User,
1920
} from '@sentry/types';
20-
import { GLOBAL_OBJ, consoleSandbox, dateTimestampInSeconds, logger } from '@sentry/utils';
21+
import { GLOBAL_OBJ, consoleSandbox, dateTimestampInSeconds } from '@sentry/utils';
2122

2223
import { getScopesFromContext, setScopesOnContext } from '../utils/contextData';
24+
import { ExclusiveEventHintOrCaptureContext, parseEventHintOrCaptureContext } from '../utils/prepareEvent';
2325
import { getGlobalCarrier } from './globals';
2426
import { Scope } from './scope';
2527
import type { CurrentScopes, SentryCarrier } from './types';
@@ -118,18 +120,22 @@ export function configureScope(callback: (scope: Scope) => void): void {
118120
}
119121

120122
/** Capture an exception to Sentry. */
121-
export function captureException(exception: unknown, hint?: EventHint): string {
122-
return getCurrentScope().captureException(exception, hint);
123+
export function captureException(exception: unknown, hint?: ExclusiveEventHintOrCaptureContext): string {
124+
return getCurrentScope().captureException(exception, parseEventHintOrCaptureContext(hint));
123125
}
124126

125127
/** Capture a message to Sentry. */
126128
export function captureMessage(
127129
message: string,
128130
// eslint-disable-next-line deprecation/deprecation
129-
level?: Severity | SeverityLevel,
130-
hint?: EventHint,
131+
captureContext?: CaptureContext | Severity | SeverityLevel,
131132
): string {
132-
return getCurrentScope().captureMessage(message, level, hint);
133+
// This is necessary to provide explicit scopes upgrade, without changing the original
134+
// arity of the `captureMessage(message, level)` method.
135+
const level = typeof captureContext === 'string' ? captureContext : undefined;
136+
const context = typeof captureContext !== 'string' ? { captureContext } : undefined;
137+
138+
return getCurrentScope().captureMessage(message, level, context);
133139
}
134140

135141
/** Capture a generic event to Sentry. */

packages/node-experimental/src/sdk/hub.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import type {
22
Client,
33
CustomSamplingContext,
4+
EventHint,
45
Hub,
56
Integration,
67
IntegrationClass,
78
Session,
9+
Severity,
10+
SeverityLevel,
811
TransactionContext,
912
} from '@sentry/types';
1013

@@ -64,8 +67,17 @@ export function getCurrentHub(): Hub {
6467
withScope,
6568
getClient,
6669
getScope: getCurrentScope,
67-
captureException,
68-
captureMessage,
70+
captureException: (exception: unknown, hint?: EventHint) => {
71+
return getCurrentScope().captureException(exception, hint);
72+
},
73+
captureMessage: (
74+
message: string,
75+
// eslint-disable-next-line deprecation/deprecation
76+
level?: Severity | SeverityLevel,
77+
hint?: EventHint,
78+
) => {
79+
return getCurrentScope().captureMessage(message, level, hint);
80+
},
6981
captureEvent,
7082
lastEventId,
7183
addBreadcrumb,
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { Scope } from '@sentry/core';
2+
import { CaptureContext, EventHint, Scope as ScopeInterface, ScopeContext } from '@sentry/types';
3+
4+
/**
5+
* This type makes sure that we get either a CaptureContext, OR an EventHint.
6+
* It does not allow mixing them, which could lead to unexpected outcomes, e.g. this is disallowed:
7+
* { user: { id: '123' }, mechanism: { handled: false } }
8+
*/
9+
export type ExclusiveEventHintOrCaptureContext =
10+
| (CaptureContext & Partial<{ [key in keyof EventHint]: never }>)
11+
| (EventHint & Partial<{ [key in keyof ScopeContext]: never }>);
12+
13+
/**
14+
* Parse either an `EventHint` directly, or convert a `CaptureContext` to an `EventHint`.
15+
* This is used to allow to update method signatures that used to accept a `CaptureContext` but should now accept an `EventHint`.
16+
*/
17+
export function parseEventHintOrCaptureContext(
18+
hint: ExclusiveEventHintOrCaptureContext | undefined,
19+
): EventHint | undefined {
20+
if (!hint) {
21+
return undefined;
22+
}
23+
24+
// If you pass a Scope or `() => Scope` as CaptureContext, we just return this as captureContext
25+
if (hintIsScopeOrFunction(hint)) {
26+
return { captureContext: hint };
27+
}
28+
29+
if (hintIsScopeContext(hint)) {
30+
return {
31+
captureContext: hint,
32+
};
33+
}
34+
35+
return hint;
36+
}
37+
38+
function hintIsScopeOrFunction(
39+
hint: CaptureContext | EventHint,
40+
): hint is ScopeInterface | ((scope: ScopeInterface) => ScopeInterface) {
41+
return hint instanceof Scope || typeof hint === 'function';
42+
}
43+
44+
type ScopeContextProperty = keyof ScopeContext;
45+
const captureContextKeys: readonly ScopeContextProperty[] = [
46+
'user',
47+
'level',
48+
'extra',
49+
'contexts',
50+
'tags',
51+
'fingerprint',
52+
'requestSession',
53+
'propagationContext',
54+
] as const;
55+
56+
function hintIsScopeContext(hint: Partial<ScopeContext> | EventHint): hint is Partial<ScopeContext> {
57+
return Object.keys(hint).some(key => captureContextKeys.includes(key as ScopeContextProperty));
58+
}

0 commit comments

Comments
 (0)