Skip to content

feat(core): Add top level getClient() method #9638

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/angular/src/errorhandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ class SentryErrorHandler implements AngularErrorHandler {

// Optionally show user dialog to provide details on what happened.
if (this._options.showDialog) {
const client = Sentry.getCurrentHub().getClient();
const client = Sentry.getClient();

if (client && client.on && !this._registeredAfterSendEventHandler) {
client.on('afterSendEvent', (event: Event) => {
Expand Down
7 changes: 2 additions & 5 deletions packages/angular/test/errorhandler.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { HttpErrorResponse } from '@angular/common/http';
import * as SentryBrowser from '@sentry/browser';
import type { Event } from '@sentry/types';
import type { Client, Event } from '@sentry/types';

import { createErrorHandler, SentryErrorHandler } from '../src/errorhandler';

Expand Down Expand Up @@ -505,10 +505,7 @@ describe('SentryErrorHandler', () => {
}),
};

// @ts-expect-error this is a minmal hub, we're missing a few props but that's ok
jest.spyOn(SentryBrowser, 'getCurrentHub').mockImplementationOnce(() => {
return { getClient: () => client };
});
jest.spyOn(SentryBrowser, 'getClient').mockImplementationOnce(() => client as unknown as Client);

const showReportDialogSpy = jest.spyOn(SentryBrowser, 'showReportDialog');

Expand Down
1 change: 1 addition & 0 deletions packages/astro/src/index.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export {
getActiveTransaction,
getHubFromCarrier,
getCurrentHub,
getClient,
Hub,
makeMain,
Scope,
Expand Down
12 changes: 5 additions & 7 deletions packages/astro/test/client/sdk.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { BrowserClient } from '@sentry/browser';
import * as SentryBrowser from '@sentry/browser';
import { BrowserTracing, getCurrentHub, SDK_VERSION, WINDOW } from '@sentry/browser';
import { BrowserTracing, getClient, getCurrentHub, SDK_VERSION, WINDOW } from '@sentry/browser';
import { vi } from 'vitest';

import { init } from '../../../astro/src/client/sdk';
Expand Down Expand Up @@ -60,7 +60,7 @@ describe('Sentry client SDK', () => {
});

const integrationsToInit = browserInit.mock.calls[0][0]?.integrations;
const browserTracing = (getCurrentHub().getClient() as BrowserClient)?.getIntegrationById('BrowserTracing');
const browserTracing = getClient<BrowserClient>()?.getIntegrationById('BrowserTracing');

expect(integrationsToInit).toContainEqual(expect.objectContaining({ name: 'BrowserTracing' }));
expect(browserTracing).toBeDefined();
Expand All @@ -76,7 +76,7 @@ describe('Sentry client SDK', () => {
});

const integrationsToInit = browserInit.mock.calls[0][0]?.integrations;
const browserTracing = (getCurrentHub().getClient() as BrowserClient)?.getIntegrationById('BrowserTracing');
const browserTracing = getClient<BrowserClient>()?.getIntegrationById('BrowserTracing');

expect(integrationsToInit).not.toContainEqual(expect.objectContaining({ name: 'BrowserTracing' }));
expect(browserTracing).toBeUndefined();
Expand All @@ -91,7 +91,7 @@ describe('Sentry client SDK', () => {
});

const integrationsToInit = browserInit.mock.calls[0][0]?.integrations;
const browserTracing = (getCurrentHub().getClient() as BrowserClient)?.getIntegrationById('BrowserTracing');
const browserTracing = getClient<BrowserClient>()?.getIntegrationById('BrowserTracing');

expect(integrationsToInit).not.toContainEqual(expect.objectContaining({ name: 'BrowserTracing' }));
expect(browserTracing).toBeUndefined();
Expand All @@ -108,9 +108,7 @@ describe('Sentry client SDK', () => {

const integrationsToInit = browserInit.mock.calls[0][0]?.integrations;

const browserTracing = (getCurrentHub().getClient() as BrowserClient)?.getIntegrationById(
'BrowserTracing',
) as BrowserTracing;
const browserTracing = getClient<BrowserClient>()?.getIntegrationById('BrowserTracing') as BrowserTracing;
const options = browserTracing.options;

expect(integrationsToInit).toContainEqual(expect.objectContaining({ name: 'BrowserTracing' }));
Expand Down
1 change: 1 addition & 0 deletions packages/browser/src/exports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export {
flush,
getHubFromCarrier,
getCurrentHub,
getClient,
Hub,
lastEventId,
makeMain,
Expand Down
3 changes: 2 additions & 1 deletion packages/browser/src/integrations/breadcrumbs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
severityLevelFromString,
} from '@sentry/utils';

import { getClient } from '../exports';
import { WINDOW } from '../helpers';

type HandlerData = Record<string, unknown>;
Expand Down Expand Up @@ -103,7 +104,7 @@ export class Breadcrumbs implements Integration {
addInstrumentationHandler('history', _historyBreadcrumb);
}
if (this.options.sentry) {
const client = getCurrentHub().getClient();
const client = getClient();
client && client.on && client.on('beforeSendEvent', addSentryBreadcrumb);
}
}
Expand Down
3 changes: 2 additions & 1 deletion packages/browser/src/profiling/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type { DebugImage, Envelope, Event, StackFrame, StackParser, Transaction
import type { Profile, ThreadCpuProfile } from '@sentry/types/src/profiling';
import { browserPerformanceTimeOrigin, forEachEnvelopeItem, GLOBAL_OBJ, logger, uuid4 } from '@sentry/utils';

import { getClient } from '../exports';
import { WINDOW } from '../helpers';
import type { JSSelfProfile, JSSelfProfiler, JSSelfProfilerConstructor, JSSelfProfileStack } from './jsSelfProfiling';

Expand Down Expand Up @@ -532,7 +533,7 @@ export function shouldProfileTransaction(transaction: Transaction): boolean {
return false;
}

const client = getCurrentHub().getClient();
const client = getClient();
const options = client && client.getOptions();
if (!options) {
__DEBUG_BUILD__ && logger.log('[Profiling] Profiling disabled, no options found.');
Expand Down
3 changes: 2 additions & 1 deletion packages/browser/src/sdk.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Hub } from '@sentry/core';
import {
getClient,
getCurrentHub,
getIntegrationsToSetup,
getReportDialogEndpoint,
Expand Down Expand Up @@ -252,7 +253,7 @@ function startSessionTracking(): void {
* Captures user feedback and sends it to Sentry.
*/
export function captureUserFeedback(feedback: UserFeedback): void {
const client = getCurrentHub().getClient<BrowserClient>();
const client = getClient<BrowserClient>();
if (client) {
client.captureUserFeedback(feedback);
}
Expand Down
13 changes: 8 additions & 5 deletions packages/browser/test/unit/eventbuilder.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import type { Client } from '@sentry/types';

import { defaultStackParser } from '../../src';
import { eventFromPlainObject } from '../../src/eventbuilder';

jest.mock('@sentry/core', () => {
const original = jest.requireActual('@sentry/core');
return {
...original,
getCurrentHub(): {
getClient(): Client;
} {
getClient() {
return {
getOptions(): any {
return { normalizeDepth: 6 };
},
};
},
getCurrentHub() {
return {
getClient(): any {
return {
Expand Down
21 changes: 11 additions & 10 deletions packages/browser/test/unit/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
captureMessage,
configureScope,
flush,
getClient,
getCurrentHub,
init,
Integrations,
Expand Down Expand Up @@ -271,31 +272,31 @@ describe('SentryBrowser initialization', () => {
it('should set SDK data when Sentry.init() is called', () => {
init({ dsn });

const sdkData = (getCurrentHub().getClient() as any).getOptions()._metadata.sdk;
const sdkData = getClient()?.getOptions()._metadata?.sdk || {};

expect(sdkData?.name).toBe('sentry.javascript.browser');
expect(sdkData?.packages[0].name).toBe('npm:@sentry/browser');
expect(sdkData?.packages[0].version).toBe(SDK_VERSION);
expect(sdkData?.packages?.[0].name).toBe('npm:@sentry/browser');
expect(sdkData?.packages?.[0].version).toBe(SDK_VERSION);
expect(sdkData?.version).toBe(SDK_VERSION);
});

it('uses SDK source from window for package name', () => {
global.SENTRY_SDK_SOURCE = 'loader';
init({ dsn });

const sdkData = (getCurrentHub().getClient() as any).getOptions()._metadata.sdk;
const sdkData = getClient()?.getOptions()._metadata?.sdk || {};

expect(sdkData?.packages[0].name).toBe('loader:@sentry/browser');
expect(sdkData.packages?.[0].name).toBe('loader:@sentry/browser');
delete global.SENTRY_SDK_SOURCE;
});

it('uses SDK source from global for package name', () => {
const spy = jest.spyOn(utils, 'getSDKSource').mockReturnValue('cdn');
init({ dsn });

const sdkData = (getCurrentHub().getClient() as any).getOptions()._metadata.sdk;
const sdkData = getClient()?.getOptions()._metadata?.sdk || {};

expect(sdkData?.packages[0].name).toBe('cdn:@sentry/browser');
expect(sdkData.packages?.[0].name).toBe('cdn:@sentry/browser');
expect(utils.getSDKSource).toBeCalledTimes(1);
spy.mockRestore();
});
Expand Down Expand Up @@ -332,11 +333,11 @@ describe('SentryBrowser initialization', () => {
},
});

const sdkData = (getCurrentHub().getClient() as any).getOptions()._metadata?.sdk;
const sdkData = getClient()?.getOptions()._metadata?.sdk || {};

expect(sdkData.name).toBe('sentry.javascript.angular');
expect(sdkData.packages[0].name).toBe('npm:@sentry/angular');
expect(sdkData.packages[0].version).toBe(SDK_VERSION);
expect(sdkData.packages?.[0].name).toBe('npm:@sentry/angular');
expect(sdkData.packages?.[0].version).toBe(SDK_VERSION);
expect(sdkData.version).toBe(SDK_VERSION);
});
});
Expand Down
5 changes: 4 additions & 1 deletion packages/browser/test/unit/integrations/breadcrumbs.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import { getCurrentHub } from '@sentry/core';
import type { Client } from '@sentry/types';

import { Breadcrumbs, BrowserClient, flush, Hub } from '../../../src';
import { getDefaultBrowserClientOptions } from '../helper/browser-client-options';

const hub = new Hub();
let client: Client | undefined;

jest.mock('@sentry/core', () => {
const original = jest.requireActual('@sentry/core');
return {
...original,
getCurrentHub: () => hub,
getClient: () => client,
};
});

Expand All @@ -18,7 +21,7 @@ describe('Breadcrumbs', () => {
const addBreadcrumb = jest.fn();
hub.addBreadcrumb = addBreadcrumb;

const client = new BrowserClient({
client = new BrowserClient({
...getDefaultBrowserClientOptions(),
dsn: 'https://username@domain/123',
integrations: [new Breadcrumbs()],
Expand Down
4 changes: 2 additions & 2 deletions packages/browser/test/unit/profiling/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@ describe('BrowserProfilingIntegration', () => {
integrations: [new Sentry.BrowserTracing(), new BrowserProfilingIntegration()],
});

const client = Sentry.getCurrentHub().getClient() as BrowserClient;
const client = Sentry.getClient<BrowserClient>();

const currentTransaction = Sentry.getCurrentHub().getScope().getTransaction();
expect(currentTransaction?.op).toBe('pageload');
currentTransaction?.finish();
await client.flush(1000);
await client?.flush(1000);

expect(send).toHaveBeenCalledTimes(1);

Expand Down
1 change: 1 addition & 0 deletions packages/bun/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export {
getActiveTransaction,
getHubFromCarrier,
getCurrentHub,
getClient,
Hub,
lastEventId,
makeMain,
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/baseclient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import type {
EventDropReason,
EventHint,
EventProcessor,
FeedbackEvent,
Integration,
IntegrationClass,
Outcome,
Expand All @@ -27,7 +28,6 @@ import type {
Transport,
TransportMakeRequestResponse,
} from '@sentry/types';
import type { FeedbackEvent } from '@sentry/types';
import {
addItemToEnvelope,
checkOrSetAlreadyCaught,
Expand Down
12 changes: 10 additions & 2 deletions packages/core/src/exports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type {
Breadcrumb,
CaptureContext,
CheckIn,
Client,
CustomSamplingContext,
Event,
EventHint,
Expand Down Expand Up @@ -266,7 +267,7 @@ export function withMonitor<T>(
* doesn't (or if there's no client defined).
*/
export async function flush(timeout?: number): Promise<boolean> {
const client = getCurrentHub().getClient();
const client = getClient();
if (client) {
return client.flush(timeout);
}
Expand All @@ -283,7 +284,7 @@ export async function flush(timeout?: number): Promise<boolean> {
* doesn't (or if there's no client defined).
*/
export async function close(timeout?: number): Promise<boolean> {
const client = getCurrentHub().getClient();
const client = getClient();
if (client) {
return client.close(timeout);
}
Expand All @@ -299,3 +300,10 @@ export async function close(timeout?: number): Promise<boolean> {
export function lastEventId(): string | undefined {
return getCurrentHub().lastEventId();
}

/**
* Get the currently active client.
*/
export function getClient<C extends Client>(): C | undefined {
return getCurrentHub().getClient<C>();
}
1 change: 1 addition & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export {
setTags,
setUser,
withScope,
getClient,
} from './exports';
export {
getCurrentHub,
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/integration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { Client, Event, EventHint, Integration, Options } from '@sentry/typ
import { arrayify, logger } from '@sentry/utils';

import { addGlobalEventProcessor } from './eventProcessors';
import { getClient } from './exports';
import { getCurrentHub } from './hub';

declare module '@sentry/types' {
Expand Down Expand Up @@ -132,7 +133,7 @@ export function setupIntegration(client: Client, integration: Integration, integ

/** Add an integration to the current hub's client. */
export function addIntegration(integration: Integration): void {
const client = getCurrentHub().getClient();
const client = getClient();

if (!client || !client.addIntegration) {
__DEBUG_BUILD__ && logger.warn(`Cannot add integration "${integration.name}" because no SDK Client is available.`);
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/utils/hasTracingEnabled.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Options } from '@sentry/types';

import { getCurrentHub } from '../hub';
import { getClient } from '../exports';

// Treeshakable guard to remove all code related to tracing
declare const __SENTRY_TRACING__: boolean | undefined;
Expand All @@ -17,7 +17,7 @@ export function hasTracingEnabled(
return false;
}

const client = getCurrentHub().getClient();
const client = getClient();
const options = maybeOptions || (client && client.getOptions());
return !!options && (options.enableTracing || 'tracesSampleRate' in options || 'tracesSampler' in options);
}
1 change: 1 addition & 0 deletions packages/deno/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export {
getActiveTransaction,
getHubFromCarrier,
getCurrentHub,
getClient,
Hub,
lastEventId,
makeMain,
Expand Down
4 changes: 2 additions & 2 deletions packages/feedback/test/sendFeedback.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { getCurrentHub } from '@sentry/core';
import { getClient } from '@sentry/core';

import { sendFeedback } from '../src/sendFeedback';
import { mockSdk } from './utils/mockSdk';

describe('sendFeedback', () => {
it('sends feedback', async () => {
mockSdk();
const mockTransport = jest.spyOn(getCurrentHub().getClient()!.getTransport()!, 'send');
const mockTransport = jest.spyOn(getClient()!.getTransport()!, 'send');

await sendFeedback({
name: 'doe',
Expand Down
Loading