Skip to content

Commit

Permalink
fix: custom tracing in production builds (#27124)
Browse files Browse the repository at this point in the history
Update trace utilities to use Sentry functions via `globalThis`.
Add trace E2E tests.
  • Loading branch information
matthewwalsh0 authored Sep 19, 2024
1 parent 0c3e391 commit 9c77f61
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 6 deletions.
4 changes: 2 additions & 2 deletions app/scripts/lib/createTracingMiddleware.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ describe('createTracingMiddleware', () => {

request = { ...REQUEST_MOCK };

global.sentry = {
getMetaMetricsEnabled: () => Promise.resolve(true),
globalThis.sentry = {
withIsolationScope: jest.fn().mockReturnValue({}),
};
});

Expand Down
2 changes: 1 addition & 1 deletion app/scripts/lib/createTracingMiddleware.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Request and repsones are currently untyped.
// Request and responses are currently untyped.
/* eslint-disable @typescript-eslint/no-explicit-any */

import { MESSAGE_TYPE } from '../../../shared/constants/app';
Expand Down
8 changes: 8 additions & 0 deletions app/scripts/lib/ppom/ppom-middleware.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,14 @@ describe('PPOMMiddleware', () => {
generateSecurityAlertIdMock.mockReturnValue(SECURITY_ALERT_ID_MOCK);
handlePPOMErrorMock.mockReturnValue(SECURITY_ALERT_RESPONSE_MOCK);
isChainSupportedMock.mockResolvedValue(true);

globalThis.sentry = {
withIsolationScope: jest
.fn()
.mockImplementation((fn) => fn({ setTags: jest.fn() })),
startSpan: jest.fn().mockImplementation((_, fn) => fn({})),
startSpanManual: jest.fn().mockImplementation((_, fn) => fn({})),
};
});

it('updates alert response after validating request', async () => {
Expand Down
4 changes: 4 additions & 0 deletions app/scripts/metamask-controller.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,10 @@ describe('MetaMaskController', () => {
},
]),
);

globalThis.sentry = {
withIsolationScope: jest.fn(),
};
});

afterEach(() => {
Expand Down
6 changes: 6 additions & 0 deletions shared/lib/trace.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ describe('Trace', () => {
beforeEach(() => {
jest.resetAllMocks();

globalThis.sentry = {
startSpan: startSpanMock,
startSpanManual: startSpanManualMock,
withIsolationScope: withIsolationScopeMock,
};

startSpanMock.mockImplementation((_, fn) => fn({} as Span));

// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand Down
6 changes: 3 additions & 3 deletions shared/lib/trace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ function traceCallback<T>(request: TraceRequest, fn: TraceCallback<T>): T {
};

return startSpan(request, (spanOptions) =>
Sentry.startSpan(spanOptions, callback),
globalThis.sentry.startSpan(spanOptions, callback),
);
}

Expand All @@ -138,7 +138,7 @@ function startTrace(request: TraceRequest): TraceContext {
};

return startSpan(request, (spanOptions) =>
Sentry.startSpanManual(spanOptions, callback),
globalThis.sentry.startSpanManual(spanOptions, callback),
);
}

Expand All @@ -157,7 +157,7 @@ function startSpan<T>(
startTime,
};

return Sentry.withIsolationScope((scope) => {
return globalThis.sentry.withIsolationScope((scope: Sentry.Scope) => {
scope.setTags(tags as Record<string, Primitive>);

return callback(spanOptions);
Expand Down
129 changes: 129 additions & 0 deletions test/e2e/tests/metrics/traces.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import { MockttpServer } from 'mockttp';
import FixtureBuilder from '../../fixture-builder';
import {
defaultGanacheOptions,
unlockWallet,
withFixtures,
} from '../../helpers';
import {
expectMockRequest,
expectNoMockRequest,
} from '../../helpers/mock-server';

async function mockSentryCustomTrace(mockServer: MockttpServer) {
return [
await mockServer
.forPost(/sentry/u)
.withBodyIncluding('"transaction":"UI Startup"')
.thenCallback(() => {
return {
statusCode: 200,
json: {},
};
}),
];
}

async function mockSentryAutomatedTrace(mockServer: MockttpServer) {
return [
await mockServer
.forPost(/sentry/u)
.withBodyIncluding('"transaction":"/home.html"')
.thenCallback(() => {
return {
statusCode: 200,
json: {},
};
}),
];
}

describe('Traces', function () {
it('sends custom trace when opening UI if metrics enabled', async function () {
await withFixtures(
{
fixtures: new FixtureBuilder()
.withMetaMetricsController({
participateInMetaMetrics: true,
})
.build(),
ganacheOptions: defaultGanacheOptions,
title: this.test?.fullTitle(),
testSpecificMock: mockSentryCustomTrace,
manifestFlags: {
doNotForceSentryForThisTest: true,
},
},
async ({ driver, mockedEndpoint }) => {
await unlockWallet(driver);
await expectMockRequest(driver, mockedEndpoint[0], { timeout: 3000 });
},
);
});

it('does not send custom trace when opening UI if metrics disabled @no-mmi', async function () {
await withFixtures(
{
fixtures: new FixtureBuilder()
.withMetaMetricsController({
participateInMetaMetrics: false,
})
.build(),
ganacheOptions: defaultGanacheOptions,
title: this.test?.fullTitle(),
testSpecificMock: mockSentryCustomTrace,
manifestFlags: {
doNotForceSentryForThisTest: true,
},
},
async ({ driver, mockedEndpoint }) => {
await unlockWallet(driver);
await expectNoMockRequest(driver, mockedEndpoint[0], { timeout: 3000 });
},
);
});

it('sends automated trace when opening UI if metrics enabled', async function () {
await withFixtures(
{
fixtures: new FixtureBuilder()
.withMetaMetricsController({
participateInMetaMetrics: true,
})
.build(),
ganacheOptions: defaultGanacheOptions,
title: this.test?.fullTitle(),
testSpecificMock: mockSentryAutomatedTrace,
manifestFlags: {
doNotForceSentryForThisTest: true,
},
},
async ({ driver, mockedEndpoint }) => {
await unlockWallet(driver);
await expectMockRequest(driver, mockedEndpoint[0], { timeout: 3000 });
},
);
});

it('does not send automated trace when opening UI if metrics disabled @no-mmi', async function () {
await withFixtures(
{
fixtures: new FixtureBuilder()
.withMetaMetricsController({
participateInMetaMetrics: false,
})
.build(),
ganacheOptions: defaultGanacheOptions,
title: this.test?.fullTitle(),
testSpecificMock: mockSentryAutomatedTrace,
manifestFlags: {
doNotForceSentryForThisTest: true,
},
},
async ({ driver, mockedEndpoint }) => {
await unlockWallet(driver);
await expectNoMockRequest(driver, mockedEndpoint[0], { timeout: 3000 });
},
);
});
});

0 comments on commit 9c77f61

Please sign in to comment.