Skip to content

ref: Make it easier to use stackParser #5015

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 4 commits into from
May 3, 2022
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
36 changes: 36 additions & 0 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,42 @@ import {
} from '@sentry/minimal';
```

## Explicit Client Options

In v7, we've updated the `Client` to have options seperate from the options passed into `Sentry.init`. This means that constructing a client now requires 3 options: `integrations`, `transport` and `stackParser`. These can be customized as you see fit.

```ts
import { BrowserClient, defaultStackParser, defaultIntegrations, makeFetchTransport } from '@sentry/browser';

// New in v7:
const client = new BrowserClient({
transport: makeFetchTransport,
stackParser: defaultStackParser,
integrations: [...defaultIntegrations],
});

// Before:
const client = new BrowserClient();
```

Since you now explicitly pass in the dependencies of the client, you can also tree-shake out dependencies that you do not use this way. For example, you can tree-shake out the SDK's default integrations and only use the ones that you want like so:

```ts
import { BrowserClient, defaultStackParser, Integrations, makeFetchTransport } from '@sentry/browser';

// New in v7:
const client = new BrowserClient({
transport: makeFetchTransport,
stackParser: defaultStackParser,
integrations: [
new Integrations.Breadcrumbs(),
new Integrations.GlobalHandlers(),
new Integrations.LinkedErrors(),
new Integrations.Dedupe(),
],
});
```

## Removal Of Old Platform Integrations From `@sentry/integrations` Package

The following classes will be removed from the `@sentry/integrations` package and can no longer be used:
Expand Down
2 changes: 1 addition & 1 deletion packages/browser/src/eventbuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
} from '@sentry/utils';

/**
* This function creates an exception from an TraceKitStackTrace
* This function creates an exception from a JavaScript Error
*/
export function exceptionFromError(stackParser: StackParser, ex: Error): Exception {
// Get the frames first since Opera can lose the stack if we touch anything else first
Expand Down
14 changes: 8 additions & 6 deletions packages/browser/src/exports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,15 @@ export {
} from '@sentry/core';

export { BrowserClient } from './client';
export { makeFetchTransport, makeXHRTransport } from './transports';
export {
defaultStackParsers,
chromeStackParser,
geckoStackParser,
opera10StackParser,
opera11StackParser,
winjsStackParser,
defaultStackParser,
defaultStackLineParsers,
chromeStackLineParser,
geckoStackLineParser,
opera10StackLineParser,
opera11StackLineParser,
winjsStackLineParser,
} from './stack-parsers';
export { defaultIntegrations, forceLoad, init, lastEventId, onLoad, showReportDialog, flush, close, wrap } from './sdk';
export { SDK_NAME } from './version';
3 changes: 1 addition & 2 deletions packages/browser/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { Integrations as CoreIntegrations } from '@sentry/core';
import { getGlobalObject } from '@sentry/utils';

import * as BrowserIntegrations from './integrations';
import * as Transports from './transports';

let windowIntegrations = {};

Expand All @@ -20,4 +19,4 @@ const INTEGRATIONS = {
...BrowserIntegrations,
};

export { INTEGRATIONS as Integrations, Transports };
export { INTEGRATIONS as Integrations };
6 changes: 3 additions & 3 deletions packages/browser/src/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ import {
getGlobalObject,
logger,
resolvedSyncPromise,
stackParserFromOptions,
stackParserFromStackParserOptions,
supportsFetch,
} from '@sentry/utils';

import { BrowserClient, BrowserClientOptions, BrowserOptions } from './client';
import { IS_DEBUG_BUILD } from './flags';
import { ReportDialogOptions, wrap as internalWrap } from './helpers';
import { Breadcrumbs, Dedupe, GlobalHandlers, LinkedErrors, TryCatch, UserAgent } from './integrations';
import { defaultStackParsers } from './stack-parsers';
import { defaultStackParser } from './stack-parsers';
import { makeFetchTransport, makeXHRTransport } from './transports';

export const defaultIntegrations = [
Expand Down Expand Up @@ -110,7 +110,7 @@ export function init(options: BrowserOptions = {}): void {

const clientOptions: BrowserClientOptions = {
...options,
stackParser: stackParserFromOptions(options.stackParser || defaultStackParsers),
stackParser: stackParserFromStackParserOptions(options.stackParser || defaultStackParser),
integrations: getIntegrationsToSetup(options),
transport: options.transport || (supportsFetch() ? makeFetchTransport : makeXHRTransport),
};
Expand Down
15 changes: 9 additions & 6 deletions packages/browser/src/stack-parsers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { StackFrame, StackLineParser, StackLineParserFn } from '@sentry/types';
import { createStackParser } from '@sentry/utils';

// global reference to slice
const UNKNOWN_FUNCTION = '?';
Expand Down Expand Up @@ -60,7 +61,7 @@ const chrome: StackLineParserFn = line => {
return;
};

export const chromeStackParser: StackLineParser = [CHROME_PRIORITY, chrome];
export const chromeStackLineParser: StackLineParser = [CHROME_PRIORITY, chrome];

// gecko regex: `(?:bundle|\d+\.js)`: `bundle` is for react native, `\d+\.js` also but specifically for ram bundles because it
// generates filenames without a prefix like `file://` the filenames in the stacktrace are just 42.js
Expand Down Expand Up @@ -96,7 +97,7 @@ const gecko: StackLineParserFn = line => {
return;
};

export const geckoStackParser: StackLineParser = [GECKO_PRIORITY, gecko];
export const geckoStackLineParser: StackLineParser = [GECKO_PRIORITY, gecko];

const winjsRegex =
/^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i;
Expand All @@ -109,7 +110,7 @@ const winjs: StackLineParserFn = line => {
: undefined;
};

export const winjsStackParser: StackLineParser = [WINJS_PRIORITY, winjs];
export const winjsStackLineParser: StackLineParser = [WINJS_PRIORITY, winjs];

const opera10Regex = / line (\d+).*script (?:in )?(\S+)(?:: in function (\S+))?$/i;

Expand All @@ -118,7 +119,7 @@ const opera10: StackLineParserFn = line => {
return parts ? createFrame(parts[2], parts[3] || UNKNOWN_FUNCTION, +parts[1]) : undefined;
};

export const opera10StackParser: StackLineParser = [OPERA10_PRIORITY, opera10];
export const opera10StackLineParser: StackLineParser = [OPERA10_PRIORITY, opera10];

const opera11Regex =
/ line (\d+), column (\d+)\s*(?:in (?:<anonymous function: ([^>]+)>|([^)]+))\(.*\))? in (.*):\s*$/i;
Expand All @@ -128,9 +129,11 @@ const opera11: StackLineParserFn = line => {
return parts ? createFrame(parts[5], parts[3] || parts[4] || UNKNOWN_FUNCTION, +parts[1], +parts[2]) : undefined;
};

export const opera11StackParser: StackLineParser = [OPERA11_PRIORITY, opera11];
export const opera11StackLineParser: StackLineParser = [OPERA11_PRIORITY, opera11];

export const defaultStackParsers = [chromeStackParser, geckoStackParser, winjsStackParser];
export const defaultStackLineParsers = [chromeStackLineParser, geckoStackLineParser, winjsStackLineParser];

export const defaultStackParser = createStackParser(...defaultStackLineParsers);

/**
* Safari web extensions, starting version unknown, can produce "frames-only" stacktraces.
Expand Down
5 changes: 1 addition & 4 deletions packages/browser/test/unit/integrations/linkederrors.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { Event as SentryEvent, Exception, ExtendedError } from '@sentry/types';
import { createStackParser } from '@sentry/utils';

import { BrowserClient } from '../../../src/client';
import * as LinkedErrorsModule from '../../../src/integrations/linkederrors';
import { defaultStackParsers } from '../../../src/stack-parsers';
import { defaultStackParser as parser } from '../../../src/stack-parsers';
import { getDefaultBrowserClientOptions } from '../helper/browser-client-options';

const parser = createStackParser(...defaultStackParsers);

type EventWithException = SentryEvent & {
exception: {
values: Exception[];
Expand Down
6 changes: 1 addition & 5 deletions packages/browser/test/unit/tracekit/chromium.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import { createStackParser } from '@sentry/utils';

import { exceptionFromError } from '../../../src/eventbuilder';
import { defaultStackParsers } from '../../../src/stack-parsers';

const parser = createStackParser(...defaultStackParsers);
import { defaultStackParser as parser } from '../../../src/stack-parsers';

describe('Tracekit - Chrome Tests', () => {
it('should parse Chrome error with no location', () => {
Expand Down
6 changes: 1 addition & 5 deletions packages/browser/test/unit/tracekit/firefox.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import { createStackParser } from '@sentry/utils';

import { exceptionFromError } from '../../../src/eventbuilder';
import { defaultStackParsers } from '../../../src/stack-parsers';

const parser = createStackParser(...defaultStackParsers);
import { defaultStackParser as parser } from '../../../src/stack-parsers';

describe('Tracekit - Firefox Tests', () => {
it('should parse Firefox 3 error', () => {
Expand Down
6 changes: 1 addition & 5 deletions packages/browser/test/unit/tracekit/ie.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import { createStackParser } from '@sentry/utils';

import { exceptionFromError } from '../../../src/eventbuilder';
import { defaultStackParsers } from '../../../src/stack-parsers';

const parser = createStackParser(...defaultStackParsers);
import { defaultStackParser as parser } from '../../../src/stack-parsers';

describe('Tracekit - IE Tests', () => {
it('should parse IE 10 error', () => {
Expand Down
6 changes: 1 addition & 5 deletions packages/browser/test/unit/tracekit/misc.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import { createStackParser } from '@sentry/utils';

import { exceptionFromError } from '../../../src/eventbuilder';
import { defaultStackParsers } from '../../../src/stack-parsers';

const parser = createStackParser(...defaultStackParsers);
import { defaultStackParser as parser } from '../../../src/stack-parsers';

describe('Tracekit - Misc Tests', () => {
it('should parse PhantomJS 1.19 error', () => {
Expand Down
6 changes: 3 additions & 3 deletions packages/browser/test/unit/tracekit/opera.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { createStackParser } from '@sentry/utils';

import { exceptionFromError } from '../../../src/eventbuilder';
import { defaultStackParsers, opera10StackParser, opera11StackParser } from '../../../src/stack-parsers';
import { defaultStackParser, opera10StackLineParser, opera11StackLineParser } from '../../../src/stack-parsers';

const operaParser = createStackParser(opera10StackParser, opera11StackParser);
const chromiumParser = createStackParser(...defaultStackParsers);
const operaParser = createStackParser(opera10StackLineParser, opera11StackLineParser);
const chromiumParser = defaultStackParser;

describe('Tracekit - Opera Tests', () => {
it('should parse Opera 10 error', () => {
Expand Down
6 changes: 1 addition & 5 deletions packages/browser/test/unit/tracekit/react-native.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import { createStackParser } from '@sentry/utils';

import { exceptionFromError } from '../../../src/eventbuilder';
import { defaultStackParsers } from '../../../src/stack-parsers';

const parser = createStackParser(...defaultStackParsers);
import { defaultStackParser as parser } from '../../../src/stack-parsers';

describe('Tracekit - React Native Tests', () => {
it('should parse exceptions for react-native-v8', () => {
Expand Down
6 changes: 1 addition & 5 deletions packages/browser/test/unit/tracekit/react.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import { createStackParser } from '@sentry/utils';

import { exceptionFromError } from '../../../src/eventbuilder';
import { defaultStackParsers } from '../../../src/stack-parsers';

const parser = createStackParser(...defaultStackParsers);
import { defaultStackParser as parser } from '../../../src/stack-parsers';

describe('Tracekit - React Tests', () => {
it('should correctly parse Invariant Violation errors and use framesToPop to drop info message', () => {
Expand Down
6 changes: 1 addition & 5 deletions packages/browser/test/unit/tracekit/safari.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import { createStackParser } from '@sentry/utils';

import { exceptionFromError } from '../../../src/eventbuilder';
import { defaultStackParsers } from '../../../src/stack-parsers';

const parser = createStackParser(...defaultStackParsers);
import { defaultStackParser as parser } from '../../../src/stack-parsers';

describe('Tracekit - Safari Tests', () => {
it('should parse Safari 6 error', () => {
Expand Down
6 changes: 3 additions & 3 deletions packages/node/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,25 +43,25 @@ export {
} from '@sentry/core';

export { NodeClient } from './client';
export { makeNodeTransport } from './transports';
export { defaultIntegrations, init, lastEventId, flush, close, getSentryRelease } from './sdk';
export { deepReadDirSync } from './utils';
export { SDK_NAME } from './version';
export { nodeStackParser } from './stack-parser';
export { defaultStackParser } from './stack-parser';

import { Integrations as CoreIntegrations } from '@sentry/core';
import { getMainCarrier } from '@sentry/hub';
import * as domain from 'domain';

import * as Handlers from './handlers';
import * as NodeIntegrations from './integrations';
import * as Transports from './transports';

const INTEGRATIONS = {
...CoreIntegrations,
...NodeIntegrations,
};

export { INTEGRATIONS as Integrations, Transports, Handlers };
export { INTEGRATIONS as Integrations, Handlers };

// We need to patch domain on the global __SENTRY__ object to make it work for node in cross-platform packages like
// @sentry/hub. If we don't do this, browser bundlers will have troubles resolving `require('domain')`.
Expand Down
6 changes: 3 additions & 3 deletions packages/node/src/sdk.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { getCurrentHub, getIntegrationsToSetup, initAndBind, Integrations as CoreIntegrations } from '@sentry/core';
import { getMainCarrier, setHubOnCarrier } from '@sentry/hub';
import { SessionStatus } from '@sentry/types';
import { getGlobalObject, logger, stackParserFromOptions } from '@sentry/utils';
import { getGlobalObject, logger, stackParserFromStackParserOptions } from '@sentry/utils';
import * as domain from 'domain';

import { NodeClient } from './client';
import { IS_DEBUG_BUILD } from './flags';
import { Console, ContextLines, Http, LinkedErrors, OnUncaughtException, OnUnhandledRejection } from './integrations';
import { nodeStackParser } from './stack-parser';
import { defaultStackParser } from './stack-parser';
import { makeNodeTransport } from './transports';
import { NodeClientOptions, NodeOptions } from './types';

Expand Down Expand Up @@ -130,7 +130,7 @@ export function init(options: NodeOptions = {}): void {
// TODO(v7): Refactor this to reduce the logic above
const clientOptions: NodeClientOptions = {
...options,
stackParser: stackParserFromOptions(options.stackParser || [nodeStackParser]),
stackParser: stackParserFromStackParserOptions(options.stackParser || defaultStackParser),
integrations: getIntegrationsToSetup(options),
transport: options.transport || makeNodeTransport,
};
Expand Down
6 changes: 4 additions & 2 deletions packages/node/src/stack-parser.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { StackLineParser, StackLineParserFn } from '@sentry/types';
import { basename, dirname } from '@sentry/utils';
import { basename, createStackParser, dirname } from '@sentry/utils';

/** Gets the module */
function getModule(filename: string | undefined): string | undefined {
Expand Down Expand Up @@ -114,4 +114,6 @@ const node: StackLineParserFn = (line: string) => {
};
};

export const nodeStackParser: StackLineParser = [90, node];
export const nodeStackLineParser: StackLineParser = [90, node];

export const defaultStackParser = createStackParser(nodeStackLineParser);
13 changes: 5 additions & 8 deletions packages/node/test/context-lines.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import { StackFrame } from '@sentry/types';
import { createStackParser } from '@sentry/utils';
import * as fs from 'fs';

import { parseStackFrames } from '../src/eventbuilder';
import { ContextLines, resetFileContentCache } from '../src/integrations/contextlines';
import { nodeStackParser } from '../src/stack-parser';
import { defaultStackParser } from '../src/stack-parser';
import { getError } from './helper/error';

const parser = createStackParser(nodeStackParser);

describe('ContextLines', () => {
let readFileSpy: jest.SpyInstance;
let contextLines: ContextLines;
Expand All @@ -31,7 +28,7 @@ describe('ContextLines', () => {
test('parseStack with same file', async () => {
expect.assertions(1);

const frames = parseStackFrames(parser, new Error('test'));
const frames = parseStackFrames(defaultStackParser, new Error('test'));

await addContext(Array.from(frames));

Expand Down Expand Up @@ -61,12 +58,12 @@ describe('ContextLines', () => {

test('parseStack with adding different file', async () => {
expect.assertions(1);
const frames = parseStackFrames(parser, new Error('test'));
const frames = parseStackFrames(defaultStackParser, new Error('test'));

await addContext(frames);

const numCalls = readFileSpy.mock.calls.length;
const parsedFrames = parseStackFrames(parser, getError());
const parsedFrames = parseStackFrames(defaultStackParser, getError());
await addContext(parsedFrames);

const newErrorCalls = readFileSpy.mock.calls.length;
Expand Down Expand Up @@ -104,7 +101,7 @@ describe('ContextLines', () => {
contextLines = new ContextLines({ frameContextLines: 0 });

expect.assertions(1);
const frames = parseStackFrames(parser, new Error('test'));
const frames = parseStackFrames(defaultStackParser, new Error('test'));

await addContext(frames);
expect(readFileSpy).toHaveBeenCalledTimes(0);
Expand Down
Loading