Skip to content

Commit 025471d

Browse files
committed
update to catch within patch
1 parent 846b445 commit 025471d

File tree

6 files changed

+80
-117
lines changed

6 files changed

+80
-117
lines changed

packages/core/src/integration.ts

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ const MARKED_DISABLED_INTEGRATIONS = new Set<string>();
2424
* @param integrationName The name(s) of the integration(s) to mark as disabled
2525
*/
2626
export function _markIntegrationsDisabled(integrationName: string | string[]): void {
27-
if (Array.isArray(integrationName)) {
28-
integrationName.forEach(name => MARKED_DISABLED_INTEGRATIONS.add(name));
29-
} else {
30-
MARKED_DISABLED_INTEGRATIONS.add(integrationName);
31-
}
27+
const names = Array.isArray(integrationName) ? integrationName : [integrationName];
28+
names.forEach(name => {
29+
MARKED_DISABLED_INTEGRATIONS.add(name);
30+
DEBUG_BUILD && debug.log(`Integration marked as disabled: ${name}`);
31+
});
3232
}
3333

3434
/**
@@ -160,11 +160,8 @@ export function setupIntegration(client: Client, integration: Integration, integ
160160

161161
// `setupOnce` is only called the first time
162162
if (!installedIntegrations.includes(integration.name) && typeof integration.setupOnce === 'function') {
163-
// Skip setup if integration is marked as disabled
164-
if (!_isIntegrationMarkedDisabled(integration.name)) {
165-
integration.setupOnce();
166-
installedIntegrations.push(integration.name);
167-
}
163+
integration.setupOnce();
164+
installedIntegrations.push(integration.name);
168165
}
169166

170167
// `setup` is run for each client

packages/core/test/lib/integration.test.ts

Lines changed: 33 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
} from '../../src/integration';
1212
import { setCurrentClient } from '../../src/sdk';
1313
import type { Integration } from '../../src/types-hoist/integration';
14-
import type { Options } from '../../src/types-hoist/options';
14+
import type { CoreOptions } from '../../src/types-hoist/options';
1515
import { debug } from '../../src/utils/debug-logger';
1616
import { getDefaultTestClientOptions, TestClient } from '../mocks/client';
1717

@@ -40,8 +40,8 @@ class MockIntegration implements Integration {
4040

4141
type TestCase = [
4242
string, // test name
43-
Options['defaultIntegrations'], // default integrations
44-
Options['integrations'], // user-provided integrations
43+
CoreOptions['defaultIntegrations'], // default integrations
44+
CoreOptions['integrations'], // user-provided integrations
4545
Array<string | string[]>, // expected results
4646
];
4747

@@ -694,124 +694,57 @@ describe('addIntegration', () => {
694694

695695
describe('Integration marking system', () => {
696696
beforeEach(() => {
697-
// Clear marks before each test
698697
_clearDisabledIntegrationsMarks();
699-
// Reset installed integrations
700698
installedIntegrations.splice(0, installedIntegrations.length);
701699
});
702700

703701
afterEach(() => {
704-
// Clean up after tests
705702
_clearDisabledIntegrationsMarks();
706703
});
707704

708-
describe('_markIntegrationsDisabled', () => {
709-
it('marks a single integration as disabled', () => {
710-
_markIntegrationsDisabled('TestIntegration');
711-
expect(_isIntegrationMarkedDisabled('TestIntegration')).toBe(true);
712-
});
705+
it('marks and checks single integration', () => {
706+
expect(_isIntegrationMarkedDisabled('TestIntegration')).toBe(false);
713707

714-
it('marks multiple integrations as disabled using array', () => {
715-
_markIntegrationsDisabled(['Integration1', 'Integration2', 'Integration3']);
716-
expect(_isIntegrationMarkedDisabled('Integration1')).toBe(true);
717-
expect(_isIntegrationMarkedDisabled('Integration2')).toBe(true);
718-
expect(_isIntegrationMarkedDisabled('Integration3')).toBe(true);
719-
});
708+
_markIntegrationsDisabled('TestIntegration');
720709

721-
it('does not affect unmarked integrations', () => {
722-
_markIntegrationsDisabled('Integration1');
723-
expect(_isIntegrationMarkedDisabled('Integration1')).toBe(true);
724-
expect(_isIntegrationMarkedDisabled('Integration2')).toBe(false);
725-
});
710+
expect(_isIntegrationMarkedDisabled('TestIntegration')).toBe(true);
726711
});
727712

728-
describe('_isIntegrationMarkedDisabled', () => {
729-
it('returns false for integrations that are not marked', () => {
730-
expect(_isIntegrationMarkedDisabled('SomeIntegration')).toBe(false);
731-
});
713+
it('marks and checks multiple integrations', () => {
714+
_markIntegrationsDisabled(['OpenAI', 'Anthropic', 'GoogleGenAI']);
732715

733-
it('returns true for integrations that are marked', () => {
734-
_markIntegrationsDisabled('MarkedIntegration');
735-
expect(_isIntegrationMarkedDisabled('MarkedIntegration')).toBe(true);
736-
});
716+
expect(_isIntegrationMarkedDisabled('OpenAI')).toBe(true);
717+
expect(_isIntegrationMarkedDisabled('Anthropic')).toBe(true);
718+
expect(_isIntegrationMarkedDisabled('GoogleGenAI')).toBe(true);
719+
expect(_isIntegrationMarkedDisabled('Other')).toBe(false);
737720
});
738721

739-
describe('_clearDisabledIntegrationsMarks', () => {
740-
it('clears all marks', () => {
741-
_markIntegrationsDisabled(['Integration1', 'Integration2']);
742-
expect(_isIntegrationMarkedDisabled('Integration1')).toBe(true);
743-
expect(_isIntegrationMarkedDisabled('Integration2')).toBe(true);
744-
745-
_clearDisabledIntegrationsMarks();
746-
747-
expect(_isIntegrationMarkedDisabled('Integration1')).toBe(false);
748-
expect(_isIntegrationMarkedDisabled('Integration2')).toBe(false);
749-
});
750-
751-
it('removes marked integrations from installedIntegrations list', () => {
752-
// Simulate integrations being installed
753-
installedIntegrations.push('Integration1', 'Integration2', 'Integration3');
754-
755-
// Mark some as disabled
756-
_markIntegrationsDisabled(['Integration1', 'Integration3']);
757-
758-
// Clear should remove marked ones from installed list
759-
_clearDisabledIntegrationsMarks();
722+
it('clears marks and removes from installedIntegrations', () => {
723+
// Simulate scenario: integrations installed, some marked for cleanup
724+
installedIntegrations.push('LangChain', 'OpenAI', 'Anthropic', 'Normal');
725+
_markIntegrationsDisabled(['OpenAI', 'Anthropic']);
760726

761-
expect(installedIntegrations).toEqual(['Integration2']);
762-
});
763-
764-
it('preserves integrations that are not marked when clearing', () => {
765-
installedIntegrations.push('Integration1', 'Integration2', 'Integration3');
766-
_markIntegrationsDisabled('Integration2');
727+
_clearDisabledIntegrationsMarks();
767728

768-
_clearDisabledIntegrationsMarks();
729+
// Marks are cleared
730+
expect(_isIntegrationMarkedDisabled('OpenAI')).toBe(false);
731+
expect(_isIntegrationMarkedDisabled('Anthropic')).toBe(false);
769732

770-
expect(installedIntegrations).toEqual(['Integration1', 'Integration3']);
771-
});
733+
// Marked integrations removed from installed list (can setup again in new client)
734+
expect(installedIntegrations).toEqual(['LangChain', 'Normal']);
772735
});
773736

774-
describe('setupIntegration with marked integrations', () => {
775-
it('skips setupOnce for marked integrations', () => {
776-
const client = getTestClient();
777-
const integration = new MockIntegration('MarkedIntegration');
778-
779-
// Mark the integration as disabled before setup
780-
_markIntegrationsDisabled('MarkedIntegration');
781-
782-
setupIntegration(client, integration, {});
783-
784-
// setupOnce should not be called
785-
expect(integration.setupOnce).not.toHaveBeenCalled();
786-
// Integration should not be in installed list
787-
expect(installedIntegrations).not.toContain('MarkedIntegration');
788-
});
789-
790-
it('calls setupOnce for non-marked integrations', () => {
791-
const client = getTestClient();
792-
const integration = new MockIntegration('NormalIntegration');
793-
794-
setupIntegration(client, integration, {});
737+
it('handles multi-client scenario correctly', () => {
738+
// First client with LangChain
739+
installedIntegrations.push('LangChain', 'OpenAI');
740+
_markIntegrationsDisabled('OpenAI');
741+
expect(_isIntegrationMarkedDisabled('OpenAI')).toBe(true);
795742

796-
// setupOnce should be called
797-
expect(integration.setupOnce).toHaveBeenCalledTimes(1);
798-
// Integration should be in installed list
799-
expect(installedIntegrations).toContain('NormalIntegration');
800-
});
801-
802-
it('allows setup after clearing marks', () => {
803-
const client = getTestClient();
804-
const integration = new MockIntegration('TestIntegration');
805-
806-
// Mark, clear, then setup
807-
_markIntegrationsDisabled('TestIntegration');
808-
_clearDisabledIntegrationsMarks();
809-
810-
setupIntegration(client, integration, {});
743+
// Second client initialization clears marks
744+
_clearDisabledIntegrationsMarks();
811745

812-
// setupOnce should be called after marks are cleared
813-
expect(integration.setupOnce).toHaveBeenCalledTimes(1);
814-
expect(installedIntegrations).toContain('TestIntegration');
815-
});
746+
// OpenAI can be used standalone in second client
747+
expect(_isIntegrationMarkedDisabled('OpenAI')).toBe(false);
748+
expect(installedIntegrations).toEqual(['LangChain']); // OpenAI removed, can setup fresh
816749
});
817750
});

packages/node/src/integrations/tracing/anthropic-ai/instrumentation.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,13 @@ import {
55
InstrumentationNodeModuleDefinition,
66
} from '@opentelemetry/instrumentation';
77
import type { AnthropicAiClient, AnthropicAiOptions } from '@sentry/core';
8-
import { getClient, instrumentAnthropicAiClient, SDK_VERSION } from '@sentry/core';
8+
import {
9+
_isIntegrationMarkedDisabled,
10+
ANTHROPIC_AI_INTEGRATION_NAME,
11+
getClient,
12+
instrumentAnthropicAiClient,
13+
SDK_VERSION,
14+
} from '@sentry/core';
915

1016
const supportedVersions = ['>=0.19.2 <1.0.0'];
1117

@@ -48,6 +54,12 @@ export class SentryAnthropicAiInstrumentation extends InstrumentationBase<Anthro
4854
const config = this.getConfig();
4955

5056
const WrappedAnthropic = function (this: unknown, ...args: unknown[]) {
57+
// Check if disabled at runtime (after module is loaded, in case LangChain marked it)
58+
if (_isIntegrationMarkedDisabled(ANTHROPIC_AI_INTEGRATION_NAME)) {
59+
// Return unwrapped instance - no instrumentation
60+
return Reflect.construct(Original, args) as AnthropicAiClient;
61+
}
62+
5163
const instance = Reflect.construct(Original, args);
5264
const client = getClient();
5365
const defaultPii = Boolean(client?.getOptions().sendDefaultPii);

packages/node/src/integrations/tracing/google-genai/instrumentation.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,14 @@ import {
66
InstrumentationNodeModuleFile,
77
} from '@opentelemetry/instrumentation';
88
import type { GoogleGenAIClient, GoogleGenAIOptions } from '@sentry/core';
9-
import { getClient, instrumentGoogleGenAIClient, replaceExports, SDK_VERSION } from '@sentry/core';
9+
import {
10+
_isIntegrationMarkedDisabled,
11+
getClient,
12+
GOOGLE_GENAI_INTEGRATION_NAME,
13+
instrumentGoogleGenAIClient,
14+
replaceExports,
15+
SDK_VERSION,
16+
} from '@sentry/core';
1017

1118
const supportedVersions = ['>=0.10.0 <2'];
1219

@@ -65,14 +72,18 @@ export class SentryGoogleGenAiInstrumentation extends InstrumentationBase<Google
6572
}
6673

6774
const WrappedGoogleGenAI = function (this: unknown, ...args: unknown[]): GoogleGenAIClient {
75+
// Check if disabled at runtime (after module is loaded, in case LangChain marked it)
76+
if (_isIntegrationMarkedDisabled(GOOGLE_GENAI_INTEGRATION_NAME)) {
77+
// Return unwrapped instance - no instrumentation
78+
return Reflect.construct(Original, args) as GoogleGenAIClient;
79+
}
80+
6881
const instance = Reflect.construct(Original, args);
6982
const client = getClient();
7083
const defaultPii = Boolean(client?.getOptions().sendDefaultPii);
7184

7285
const typedConfig = config;
73-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
7486
const recordInputs = typedConfig?.recordInputs ?? defaultPii;
75-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
7687
const recordOutputs = typedConfig?.recordOutputs ?? defaultPii;
7788

7889
return instrumentGoogleGenAIClient(instance, {

packages/node/src/integrations/tracing/langchain/instrumentation.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,7 @@ export class SentryLangChainInstrumentation extends InstrumentationBase<LangChai
160160

161161
const config = this.getConfig();
162162

163-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
164163
const recordInputs = config?.recordInputs ?? defaultPii;
165-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
166164
const recordOutputs = config?.recordOutputs ?? defaultPii;
167165

168166
// Create a shared handler instance

packages/node/src/integrations/tracing/openai/instrumentation.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,13 @@ import {
55
InstrumentationNodeModuleDefinition,
66
} from '@opentelemetry/instrumentation';
77
import type { Integration, OpenAiClient, OpenAiOptions } from '@sentry/core';
8-
import { getClient, instrumentOpenAiClient, OPENAI_INTEGRATION_NAME, SDK_VERSION } from '@sentry/core';
8+
import {
9+
_isIntegrationMarkedDisabled,
10+
getClient,
11+
instrumentOpenAiClient,
12+
OPENAI_INTEGRATION_NAME,
13+
SDK_VERSION,
14+
} from '@sentry/core';
915

1016
const supportedVersions = ['>=4.0.0 <6'];
1117

@@ -56,6 +62,12 @@ export class SentryOpenAiInstrumentation extends InstrumentationBase<Instrumenta
5662
const Original = exports.OpenAI;
5763

5864
const WrappedOpenAI = function (this: unknown, ...args: unknown[]) {
65+
// Check if disabled at runtime (after module is loaded, in case LangChain marked it)
66+
if (_isIntegrationMarkedDisabled(OPENAI_INTEGRATION_NAME)) {
67+
// Return unwrapped instance - no instrumentation
68+
return Reflect.construct(Original, args) as OpenAiClient;
69+
}
70+
5971
const instance = Reflect.construct(Original, args);
6072
const client = getClient();
6173
const integration = client?.getIntegrationByName<OpenAiIntegration>(OPENAI_INTEGRATION_NAME);

0 commit comments

Comments
 (0)