From f2a13650262cf41f6aa0296a8e8f508072220404 Mon Sep 17 00:00:00 2001 From: a Date: Thu, 12 Jun 2025 00:52:24 -0500 Subject: [PATCH 01/26] make it so that you can pass in a stack trace parser to the browser config --- packages/web-sdk/src/config/makeCoreConfig.ts | 4 +++- packages/web-sdk/src/config/types.ts | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/web-sdk/src/config/makeCoreConfig.ts b/packages/web-sdk/src/config/makeCoreConfig.ts index df6286f5d..0e610a273 100644 --- a/packages/web-sdk/src/config/makeCoreConfig.ts +++ b/packages/web-sdk/src/config/makeCoreConfig.ts @@ -65,6 +65,8 @@ export function makeCoreConfig(browserConfig: BrowserConfig): Config { ...restProperties }: BrowserConfig = browserConfig; + const stackTraceParser = browserConfig.parseStacktrace ?? parseStacktrace; + return { ...restProperties, @@ -79,7 +81,7 @@ export function makeCoreConfig(browserConfig: BrowserConfig): Config { isolate, logArgsSerializer, metas, - parseStacktrace, + parseStacktrace: stackTraceParser, paused, preventGlobalExposure, transports, diff --git a/packages/web-sdk/src/config/types.ts b/packages/web-sdk/src/config/types.ts index 4ae11c431..313677787 100644 --- a/packages/web-sdk/src/config/types.ts +++ b/packages/web-sdk/src/config/types.ts @@ -1,6 +1,6 @@ import type { Config, LogLevel } from '@grafana/faro-core'; -export interface BrowserConfig extends Partial>, Pick { +export interface BrowserConfig extends Partial>, Pick { url?: string; apiKey?: string; } From 66c8eecd0715a178d2991e2ce48e5c1558cc3c8c Mon Sep 17 00:00:00 2001 From: a Date: Thu, 12 Jun 2025 01:23:58 -0500 Subject: [PATCH 02/26] noot --- packages/web-sdk/src/config/makeCoreConfig.ts | 2 +- packages/web-sdk/src/index.ts | 9 ++++++--- .../errors/getErrorDetails.ts | 10 +++++----- .../src/instrumentations/errors/index.ts | 2 -- .../errors/instrumentation.ts | 8 +++++++- .../errors/registerOnunhandledrejection.ts | 6 +++--- .../errors/stackFrames/parseStacktrace.ts | 9 --------- .../src/instrumentations/errors/types.ts | 6 ++++++ .../web-sdk/src/instrumentations/index.ts | 5 +---- packages/web-sdk/src/utils/index.ts | 8 ++++++++ .../stackFrames/buildStackFrame.ts | 0 .../errors => utils}/stackFrames/const.ts | 0 .../getDataFromSafariExtensions.ts | 0 .../getStackFramesFromError.test.ts | 0 .../stackFrames/getStackFramesFromError.ts | 10 +++++++++- .../errors => utils}/stackFrames/index.ts | 4 +++- .../src/utils/stackFrames/parseStacktrace.ts | 20 +++++++++++++++++++ .../web-sdk/src/utils/stackFrames/types.ts | 3 +++ 18 files changed, 72 insertions(+), 30 deletions(-) delete mode 100644 packages/web-sdk/src/instrumentations/errors/stackFrames/parseStacktrace.ts rename packages/web-sdk/src/{instrumentations/errors => utils}/stackFrames/buildStackFrame.ts (100%) rename packages/web-sdk/src/{instrumentations/errors => utils}/stackFrames/const.ts (100%) rename packages/web-sdk/src/{instrumentations/errors => utils}/stackFrames/getDataFromSafariExtensions.ts (100%) rename packages/web-sdk/src/{instrumentations/errors => utils}/stackFrames/getStackFramesFromError.test.ts (100%) rename packages/web-sdk/src/{instrumentations/errors => utils}/stackFrames/getStackFramesFromError.ts (85%) rename packages/web-sdk/src/{instrumentations/errors => utils}/stackFrames/index.ts (72%) create mode 100644 packages/web-sdk/src/utils/stackFrames/parseStacktrace.ts create mode 100644 packages/web-sdk/src/utils/stackFrames/types.ts diff --git a/packages/web-sdk/src/config/makeCoreConfig.ts b/packages/web-sdk/src/config/makeCoreConfig.ts index 0e610a273..f39414719 100644 --- a/packages/web-sdk/src/config/makeCoreConfig.ts +++ b/packages/web-sdk/src/config/makeCoreConfig.ts @@ -12,7 +12,7 @@ import { import type { Config, Instrumentation, MetaItem, MetaSession, Transport } from '@grafana/faro-core'; import { defaultEventDomain } from '../consts'; -import { parseStacktrace } from '../instrumentations'; +import { parseStacktrace } from '../utils'; import { defaultSessionTrackingConfig } from '../instrumentations/session'; import { userActionDataAttribute } from '../instrumentations/userActions/const'; import { browserMeta } from '../metas'; diff --git a/packages/web-sdk/src/index.ts b/packages/web-sdk/src/index.ts index 3c3d6a028..d30406665 100644 --- a/packages/web-sdk/src/index.ts +++ b/packages/web-sdk/src/index.ts @@ -6,12 +6,15 @@ export { defaultEventDomain } from './consts'; export { initializeFaro } from './initialize'; export { - buildStackFrame, - ConsoleInstrumentation, - ErrorsInstrumentation, getDataFromSafariExtensions, getStackFramesFromError, parseStacktrace, + buildStackFrame, +} from './utils'; + +export { + ConsoleInstrumentation, + ErrorsInstrumentation, ViewInstrumentation, WebVitalsInstrumentation, SessionInstrumentation, diff --git a/packages/web-sdk/src/instrumentations/errors/getErrorDetails.ts b/packages/web-sdk/src/instrumentations/errors/getErrorDetails.ts index 51c84bad7..59320ad01 100644 --- a/packages/web-sdk/src/instrumentations/errors/getErrorDetails.ts +++ b/packages/web-sdk/src/instrumentations/errors/getErrorDetails.ts @@ -3,10 +3,10 @@ import type { ExceptionStackFrame, LogArgsSerializer } from '@grafana/faro-core' import { domErrorType, domExceptionType, objectEventValue, unknownSymbolString } from './const'; import { getValueAndTypeFromMessage } from './getValueAndTypeFromMessage'; -import { buildStackFrame, getStackFramesFromError } from './stackFrames'; -import type { ErrorEvent } from './types'; +import { buildStackFrame, getStackFramesFromError } from '../../utils/stackFrames'; +import type { ErrorEvent, ErrorInstrumentationOptions } from './types'; -export function getErrorDetails(evt: ErrorEvent): [string | undefined, string | undefined, ExceptionStackFrame[]] { +export function getErrorDetails(evt: ErrorEvent, options: ErrorInstrumentationOptions = {}): [string | undefined, string | undefined, ExceptionStackFrame[]] { let value: string | undefined; let type: string | undefined; let stackFrames: ExceptionStackFrame[] = []; @@ -16,7 +16,7 @@ export function getErrorDetails(evt: ErrorEvent): [string | undefined, string | if (isErrorEvent(evt) && evt.error) { value = evt.error.message; type = evt.error.name; - stackFrames = getStackFramesFromError(evt.error); + stackFrames = getStackFramesFromError(evt.error, options.stackframeParserOptions); } else if ((isDomErrorRes = isDomError(evt)) || isDomException(evt)) { const { name, message } = evt; @@ -24,7 +24,7 @@ export function getErrorDetails(evt: ErrorEvent): [string | undefined, string | value = message ? `${type}: ${message}` : type; } else if (isError(evt)) { value = evt.message; - stackFrames = getStackFramesFromError(evt); + stackFrames = getStackFramesFromError(evt, options.stackframeParserOptions); } else if (isObject(evt) || (isEventRes = isEvent(evt))) { type = isEventRes ? evt.constructor.name : undefined; value = `${objectEventValue} ${Object.keys(evt)}`; diff --git a/packages/web-sdk/src/instrumentations/errors/index.ts b/packages/web-sdk/src/instrumentations/errors/index.ts index 903343a78..391c6fdbf 100644 --- a/packages/web-sdk/src/instrumentations/errors/index.ts +++ b/packages/web-sdk/src/instrumentations/errors/index.ts @@ -1,5 +1,3 @@ export { ErrorsInstrumentation } from './instrumentation'; -export { buildStackFrame, getDataFromSafariExtensions, getStackFramesFromError, parseStacktrace } from './stackFrames'; - export type { ErrorEvent, ExtendedPromiseRejectionEvent } from './types'; diff --git a/packages/web-sdk/src/instrumentations/errors/instrumentation.ts b/packages/web-sdk/src/instrumentations/errors/instrumentation.ts index 2fbd2dfdb..86e6eee1b 100644 --- a/packages/web-sdk/src/instrumentations/errors/instrumentation.ts +++ b/packages/web-sdk/src/instrumentations/errors/instrumentation.ts @@ -3,15 +3,21 @@ import { BaseInstrumentation, VERSION } from '@grafana/faro-core'; import { registerOnerror } from './registerOnerror'; import { registerOnunhandledrejection } from './registerOnunhandledrejection'; +import type { ErrorInstrumentationOptions } from './types'; + export class ErrorsInstrumentation extends BaseInstrumentation { readonly name = '@grafana/faro-web-sdk:instrumentation-errors'; readonly version = VERSION; + constructor(private readonly options: ErrorInstrumentationOptions = {}) { + super(); + } + initialize(): void { this.logDebug('Initializing'); registerOnerror(this.api); - registerOnunhandledrejection(this.api); + registerOnunhandledrejection(this.api, this.options); } } diff --git a/packages/web-sdk/src/instrumentations/errors/registerOnunhandledrejection.ts b/packages/web-sdk/src/instrumentations/errors/registerOnunhandledrejection.ts index f5d1ebc0a..1ad89518a 100644 --- a/packages/web-sdk/src/instrumentations/errors/registerOnunhandledrejection.ts +++ b/packages/web-sdk/src/instrumentations/errors/registerOnunhandledrejection.ts @@ -3,9 +3,9 @@ import type { API, ExceptionStackFrame } from '@grafana/faro-core'; import { primitiveUnhandledType, primitiveUnhandledValue } from './const'; import { getErrorDetails } from './getErrorDetails'; -import type { ExtendedPromiseRejectionEvent } from './types'; +import type { ErrorInstrumentationOptions, ExtendedPromiseRejectionEvent } from './types'; -export function registerOnunhandledrejection(api: API): void { +export function registerOnunhandledrejection(api: API, options: ErrorInstrumentationOptions = {}): void { window.addEventListener('unhandledrejection', (evt: ExtendedPromiseRejectionEvent) => { let error = evt; @@ -22,7 +22,7 @@ export function registerOnunhandledrejection(api: API): void { value = `${primitiveUnhandledValue} ${String(error)}`; type = primitiveUnhandledType; } else { - [value, type, stackFrames] = getErrorDetails(error); + [value, type, stackFrames] = getErrorDetails(error, options); } if (value) { diff --git a/packages/web-sdk/src/instrumentations/errors/stackFrames/parseStacktrace.ts b/packages/web-sdk/src/instrumentations/errors/stackFrames/parseStacktrace.ts deleted file mode 100644 index 353855c94..000000000 --- a/packages/web-sdk/src/instrumentations/errors/stackFrames/parseStacktrace.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { ExtendedError, Stacktrace } from '@grafana/faro-core'; - -import { getStackFramesFromError } from './getStackFramesFromError'; - -export function parseStacktrace(error: ExtendedError): Stacktrace { - return { - frames: getStackFramesFromError(error), - }; -} diff --git a/packages/web-sdk/src/instrumentations/errors/types.ts b/packages/web-sdk/src/instrumentations/errors/types.ts index 4eabd1286..f2b2bc173 100644 --- a/packages/web-sdk/src/instrumentations/errors/types.ts +++ b/packages/web-sdk/src/instrumentations/errors/types.ts @@ -1,3 +1,5 @@ +import type { StackframeParserOptions } from "../../utils/stackFrames/types"; + export interface ExtendedPromiseRejectionEvent extends PromiseRejectionEvent { detail?: { reason: PromiseRejectionEvent['reason']; @@ -7,3 +9,7 @@ export interface ExtendedPromiseRejectionEvent extends PromiseRejectionEvent { export type ErrorEvent = (Error | Event) & { error?: Error; }; + +export type ErrorInstrumentationOptions = { + stackframeParserOptions?: StackframeParserOptions +} diff --git a/packages/web-sdk/src/instrumentations/index.ts b/packages/web-sdk/src/instrumentations/index.ts index a412cd296..9298782b0 100644 --- a/packages/web-sdk/src/instrumentations/index.ts +++ b/packages/web-sdk/src/instrumentations/index.ts @@ -4,12 +4,9 @@ export { ConsoleInstrumentation } from './console'; export type { ConsoleInstrumentationOptions } from './console'; export { - buildStackFrame, ErrorsInstrumentation, - getDataFromSafariExtensions, - getStackFramesFromError, - parseStacktrace, } from './errors'; + export type { ErrorEvent, ExtendedPromiseRejectionEvent } from './errors'; export { ViewInstrumentation } from './view'; diff --git a/packages/web-sdk/src/utils/index.ts b/packages/web-sdk/src/utils/index.ts index 643b7db23..9e1aa83e9 100644 --- a/packages/web-sdk/src/utils/index.ts +++ b/packages/web-sdk/src/utils/index.ts @@ -11,3 +11,11 @@ export { export { throttle } from './throttle'; export { getIgnoreUrls, getUrlFromResource } from './url'; + +export { + buildStackFrame, + getDataFromSafariExtensions, + getStackFramesFromError, + parseStacktrace, + newStackTraceParser, +} from './stackFrames'; diff --git a/packages/web-sdk/src/instrumentations/errors/stackFrames/buildStackFrame.ts b/packages/web-sdk/src/utils/stackFrames/buildStackFrame.ts similarity index 100% rename from packages/web-sdk/src/instrumentations/errors/stackFrames/buildStackFrame.ts rename to packages/web-sdk/src/utils/stackFrames/buildStackFrame.ts diff --git a/packages/web-sdk/src/instrumentations/errors/stackFrames/const.ts b/packages/web-sdk/src/utils/stackFrames/const.ts similarity index 100% rename from packages/web-sdk/src/instrumentations/errors/stackFrames/const.ts rename to packages/web-sdk/src/utils/stackFrames/const.ts diff --git a/packages/web-sdk/src/instrumentations/errors/stackFrames/getDataFromSafariExtensions.ts b/packages/web-sdk/src/utils/stackFrames/getDataFromSafariExtensions.ts similarity index 100% rename from packages/web-sdk/src/instrumentations/errors/stackFrames/getDataFromSafariExtensions.ts rename to packages/web-sdk/src/utils/stackFrames/getDataFromSafariExtensions.ts diff --git a/packages/web-sdk/src/instrumentations/errors/stackFrames/getStackFramesFromError.test.ts b/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.test.ts similarity index 100% rename from packages/web-sdk/src/instrumentations/errors/stackFrames/getStackFramesFromError.test.ts rename to packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.test.ts diff --git a/packages/web-sdk/src/instrumentations/errors/stackFrames/getStackFramesFromError.ts b/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.ts similarity index 85% rename from packages/web-sdk/src/instrumentations/errors/stackFrames/getStackFramesFromError.ts rename to packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.ts index e18627d96..55965bf50 100644 --- a/packages/web-sdk/src/instrumentations/errors/stackFrames/getStackFramesFromError.ts +++ b/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.ts @@ -1,5 +1,6 @@ import { isNumber } from '@grafana/faro-core'; import type { ExceptionStackFrame, ExtendedError } from '@grafana/faro-core'; +import type { StackframeParserOptions } from './types'; import { buildStackFrame } from './buildStackFrame'; import { @@ -17,7 +18,7 @@ import { } from './const'; import { getDataFromSafariExtensions } from './getDataFromSafariExtensions'; -export function getStackFramesFromError(error: ExtendedError): ExceptionStackFrame[] { +export function getStackFramesFromError(error: ExtendedError, options: StackframeParserOptions = {}): ExceptionStackFrame[] { let lines: string[] = []; if (error.stacktrace) { @@ -33,6 +34,13 @@ export function getStackFramesFromError(error: ExtendedError): ExceptionStackFra let lineno: string | undefined; let colno: string | undefined; + // skip attempting to parse stack frames over the limit, if it is set and above 0 + if(options.maximumLineLength !== undefined && options.maximumLineLength > 0) { + if(line.length > options.maximumLineLength) { + return acc; + } + } + if ((parts = webkitLineRegex.exec(line))) { func = parts[1]; filename = parts[2]; diff --git a/packages/web-sdk/src/instrumentations/errors/stackFrames/index.ts b/packages/web-sdk/src/utils/stackFrames/index.ts similarity index 72% rename from packages/web-sdk/src/instrumentations/errors/stackFrames/index.ts rename to packages/web-sdk/src/utils/stackFrames/index.ts index 57049b8f8..2aaf8d940 100644 --- a/packages/web-sdk/src/instrumentations/errors/stackFrames/index.ts +++ b/packages/web-sdk/src/utils/stackFrames/index.ts @@ -4,4 +4,6 @@ export { getDataFromSafariExtensions } from './getDataFromSafariExtensions'; export { getStackFramesFromError } from './getStackFramesFromError'; -export { parseStacktrace } from './parseStacktrace'; +export { parseStacktrace, newStackTraceParser} from './parseStacktrace'; + + diff --git a/packages/web-sdk/src/utils/stackFrames/parseStacktrace.ts b/packages/web-sdk/src/utils/stackFrames/parseStacktrace.ts new file mode 100644 index 000000000..edcc00f18 --- /dev/null +++ b/packages/web-sdk/src/utils/stackFrames/parseStacktrace.ts @@ -0,0 +1,20 @@ +import type { ExtendedError, Stacktrace, StacktraceParser } from '@grafana/faro-core'; + +import type { StackframeParserOptions } from './types'; + +import { getStackFramesFromError } from './getStackFramesFromError'; + + +export function parseStacktrace(error: ExtendedError): Stacktrace { + return { + frames: getStackFramesFromError(error), + }; +} + +export function newStackTraceParser(options?: StackframeParserOptions): StacktraceParser { + return (error: ExtendedError)=>{ + return { + frames: getStackFramesFromError(error, options), + } + } +} diff --git a/packages/web-sdk/src/utils/stackFrames/types.ts b/packages/web-sdk/src/utils/stackFrames/types.ts new file mode 100644 index 000000000..193cf31c5 --- /dev/null +++ b/packages/web-sdk/src/utils/stackFrames/types.ts @@ -0,0 +1,3 @@ +export interface StackframeParserOptions { + maximumLineLength?: number; +} From 292dc47ccee427f4fe7f1772dbc13b22e0db9f15 Mon Sep 17 00:00:00 2001 From: a Date: Thu, 12 Jun 2025 01:28:12 -0500 Subject: [PATCH 03/26] noot --- packages/web-sdk/src/config/getWebInstrumentations.ts | 2 +- packages/web-sdk/src/config/types.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/web-sdk/src/config/getWebInstrumentations.ts b/packages/web-sdk/src/config/getWebInstrumentations.ts index 4dcb7e262..2421621ee 100644 --- a/packages/web-sdk/src/config/getWebInstrumentations.ts +++ b/packages/web-sdk/src/config/getWebInstrumentations.ts @@ -15,7 +15,7 @@ import type { GetWebInstrumentationsOptions } from './types'; export function getWebInstrumentations(options: GetWebInstrumentationsOptions = {}): Instrumentation[] { const instrumentations: Instrumentation[] = [ new UserActionInstrumentation(), - new ErrorsInstrumentation(), + new ErrorsInstrumentation(options.errorInstrumentationOptions), new WebVitalsInstrumentation(), new SessionInstrumentation(), new ViewInstrumentation(), diff --git a/packages/web-sdk/src/config/types.ts b/packages/web-sdk/src/config/types.ts index 313677787..a28551869 100644 --- a/packages/web-sdk/src/config/types.ts +++ b/packages/web-sdk/src/config/types.ts @@ -1,4 +1,5 @@ import type { Config, LogLevel } from '@grafana/faro-core'; +import type { ErrorInstrumentationOptions } from '../instrumentations/errors/types'; export interface BrowserConfig extends Partial>, Pick { url?: string; @@ -9,4 +10,5 @@ export interface GetWebInstrumentationsOptions { captureConsole?: boolean; captureConsoleDisabledLevels?: LogLevel[]; enablePerformanceInstrumentation?: boolean; + errorInstrumentationOptions?: ErrorInstrumentationOptions } From a87ce586495effbd935fdd9a817460f5bc1645e2 Mon Sep 17 00:00:00 2001 From: a Date: Thu, 12 Jun 2025 01:53:31 -0500 Subject: [PATCH 04/26] add a test that has timing --- .../getStackFramesFromError.test.ts | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.test.ts b/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.test.ts index 2ea83a137..a24dc9759 100644 --- a/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.test.ts +++ b/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.test.ts @@ -1,5 +1,6 @@ import { buildStackFrame } from './buildStackFrame'; import { getStackFramesFromError } from './getStackFramesFromError'; +import {hrtime} from 'node:process'; jest.mock('./buildStackFrame', () => ({ buildStackFrame: jest.fn((filename, func, lineno, colno) => ({ filename, func, lineno, colno })), @@ -157,6 +158,18 @@ describe('getStackFramesFromError', () => { buildStackFrame('http://path/to/file.js', 'bar', 108, 168), ]); }); + + it('should correctly skip long lines if configured to', ()=> { + var start = hrtime(); + const result = getStackFramesFromError(CapturedExceptions.SUPER_LONG_LINE, {maximumLineLength: 256}); + const elapsed = hrtime(start)[1] / 1000000 + expect(elapsed).toBeLessThan(0.5); + expect(result).toEqual([ + buildStackFrame('http://localhost:5173/node_modules/.vite/deps/chunk-RH76XVE4.js?v=3214fecf', 'getTransactionError', 1619, 10), + buildStackFrame('http://localhost:5173/node_modules/.vite/deps/chunk-RH76XVE4.js?v=3214fecf', 'sendTransaction', 1750, 11), + buildStackFrame('http://localhost:5173/src/app/hooks/useSwapRouter.tsx?t=1737523345399', 'async Object.executeTxn', 450, 24), + ]); + }) }); /* Taken from: https://github.com/stacktracejs/error-stack-parser/blob/master/spec/fixtures/captured-errors.js */ @@ -358,3 +371,25 @@ CapturedExceptions.NODE_WITH_SPACES = { 'Function.Module.runMain (internal/modules/cjs/loader.js:837:10)\n at ' + 'internal/main/run_main_module.js:17:11', }; + +CapturedExceptions.SUPER_LONG_LINE = { + description: "message string", + message: 'message string', + name: 'Error', + stack:`TransactionExecutionError: User rejected the request. + +Request Arguments: + from: 0xB770B86b1544eDf51BBf82Dd01e8e867607Dba51 + to: 0x6352a56caadC4F1E25CD6c75970Fa768A3304e64 + value: 0 ETH + data: 0x90411a320000000000000000000000002691f337abeb0146f16441ca4f82f363275851d5000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff8500000000000000000000000042000000000000000000000000000000000000060000000000000000000000002691f337abeb0146f16441ca4f82f363275851d5000000000000000000000000b770b86b1544edf51bbf82dd01e8e867607dba510000000000000000000000000000000000000000000000000000000000989680000000000000000000000000000000000000000000000000000a9c0ba2e15270000000000000000000000000000000000000000000000000000aa9b1a4fc2ed50000000000000000000000000000000000000000000000000000000000000002000000000000000000000000de219fe970acbc88c63c9c4d0705837c6701495f00000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000104e5b07cdb000000000000000000000000478946bcd4a5a22b316470f5486fafb928c0ba25000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000009896800000000000000000000000002691f337abeb0146f16441ca4f82f363275851d500000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000002e0b2c639c533813f4aa9d7837caf62653d097ff85000064420000000000000000000000000000000000000600002e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000648a6a1e850000000000000000000000004200000000000000000000000000000000000006000000000000000000000000922164bbbd36acf9e854acbbf32facc949fcaeef000000000000000000000000000000000000000000000000000aa9b1a4fc2ed500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001a49f865422000000000000000000000000420000000000000000000000000000000000000600000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064d1660f990000000000000000000000004200000000000000000000000000000000000006000000000000000000000000b770b86b1544edf51bbf82dd01e8e867607dba5100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + gas: 467935 + +Details: MetaMask Tx Signature: User denied transaction signature. +Version: viem@2.22.11 + at getTransactionError (http://localhost:5173/node_modules/.vite/deps/chunk-RH76XVE4.js?v=3214fecf:1619:10) + at sendTransaction (http://localhost:5173/node_modules/.vite/deps/chunk-RH76XVE4.js?v=3214fecf:1750:11) + at async Object.executeTxn (http://localhost:5173/src/app/hooks/useSwapRouter.tsx?t=1737523345399:450:24)` +}; + + From 2d27b16c0d543eb9a8dde19e76718053b8c3522e Mon Sep 17 00:00:00 2001 From: a Date: Thu, 12 Jun 2025 01:57:59 -0500 Subject: [PATCH 05/26] changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e75c2c1e..3062946c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ URL structure (#1297) - chore(user actions): Rename `userActionEventType` to `userActionTrigger` for improved clarity (#1298) +- chore(`@grafana/faro web-sdk`): Move the stackFrames from the errors instrumentation package to the utils package (#1316) +- improvement (`@grafana/faro-web-sdk`): Allow users to configure the stack frame tracer in the ErrorsInstrumentation and the stackTraceParser in the BrowserConfig (#1316) + + ## 1.18.2 - fix(user actions): don't attach user action context to http request when in halt mode (#1249) From a1de08fe4d5947db2397b40d53a9f4fdc2a50e7d Mon Sep 17 00:00:00 2001 From: a Date: Thu, 12 Jun 2025 02:03:45 -0500 Subject: [PATCH 06/26] run lint --- packages/web-sdk/src/config/types.ts | 2 +- packages/web-sdk/src/index.ts | 7 +--- .../errors/getErrorDetails.ts | 5 ++- .../src/instrumentations/errors/types.ts | 6 +-- .../web-sdk/src/instrumentations/index.ts | 4 +- .../getStackFramesFromError.test.ts | 39 ++++++++++++------- .../stackFrames/getStackFramesFromError.ts | 9 +++-- .../web-sdk/src/utils/stackFrames/index.ts | 4 +- .../src/utils/stackFrames/parseStacktrace.ts | 7 ++-- 9 files changed, 46 insertions(+), 37 deletions(-) diff --git a/packages/web-sdk/src/config/types.ts b/packages/web-sdk/src/config/types.ts index a28551869..4b653cb23 100644 --- a/packages/web-sdk/src/config/types.ts +++ b/packages/web-sdk/src/config/types.ts @@ -10,5 +10,5 @@ export interface GetWebInstrumentationsOptions { captureConsole?: boolean; captureConsoleDisabledLevels?: LogLevel[]; enablePerformanceInstrumentation?: boolean; - errorInstrumentationOptions?: ErrorInstrumentationOptions + errorInstrumentationOptions?: ErrorInstrumentationOptions; } diff --git a/packages/web-sdk/src/index.ts b/packages/web-sdk/src/index.ts index d30406665..a6bd6a59c 100644 --- a/packages/web-sdk/src/index.ts +++ b/packages/web-sdk/src/index.ts @@ -5,12 +5,7 @@ export { defaultEventDomain } from './consts'; export { initializeFaro } from './initialize'; -export { - getDataFromSafariExtensions, - getStackFramesFromError, - parseStacktrace, - buildStackFrame, -} from './utils'; +export { getDataFromSafariExtensions, getStackFramesFromError, parseStacktrace, buildStackFrame } from './utils'; export { ConsoleInstrumentation, diff --git a/packages/web-sdk/src/instrumentations/errors/getErrorDetails.ts b/packages/web-sdk/src/instrumentations/errors/getErrorDetails.ts index 59320ad01..21fc6abde 100644 --- a/packages/web-sdk/src/instrumentations/errors/getErrorDetails.ts +++ b/packages/web-sdk/src/instrumentations/errors/getErrorDetails.ts @@ -6,7 +6,10 @@ import { getValueAndTypeFromMessage } from './getValueAndTypeFromMessage'; import { buildStackFrame, getStackFramesFromError } from '../../utils/stackFrames'; import type { ErrorEvent, ErrorInstrumentationOptions } from './types'; -export function getErrorDetails(evt: ErrorEvent, options: ErrorInstrumentationOptions = {}): [string | undefined, string | undefined, ExceptionStackFrame[]] { +export function getErrorDetails( + evt: ErrorEvent, + options: ErrorInstrumentationOptions = {} +): [string | undefined, string | undefined, ExceptionStackFrame[]] { let value: string | undefined; let type: string | undefined; let stackFrames: ExceptionStackFrame[] = []; diff --git a/packages/web-sdk/src/instrumentations/errors/types.ts b/packages/web-sdk/src/instrumentations/errors/types.ts index f2b2bc173..7fcd97b1a 100644 --- a/packages/web-sdk/src/instrumentations/errors/types.ts +++ b/packages/web-sdk/src/instrumentations/errors/types.ts @@ -1,4 +1,4 @@ -import type { StackframeParserOptions } from "../../utils/stackFrames/types"; +import type { StackframeParserOptions } from '../../utils/stackFrames/types'; export interface ExtendedPromiseRejectionEvent extends PromiseRejectionEvent { detail?: { @@ -11,5 +11,5 @@ export type ErrorEvent = (Error | Event) & { }; export type ErrorInstrumentationOptions = { - stackframeParserOptions?: StackframeParserOptions -} + stackframeParserOptions?: StackframeParserOptions; +}; diff --git a/packages/web-sdk/src/instrumentations/index.ts b/packages/web-sdk/src/instrumentations/index.ts index 9298782b0..f880c2382 100644 --- a/packages/web-sdk/src/instrumentations/index.ts +++ b/packages/web-sdk/src/instrumentations/index.ts @@ -3,9 +3,7 @@ export { SessionInstrumentation } from './session'; export { ConsoleInstrumentation } from './console'; export type { ConsoleInstrumentationOptions } from './console'; -export { - ErrorsInstrumentation, -} from './errors'; +export { ErrorsInstrumentation } from './errors'; export type { ErrorEvent, ExtendedPromiseRejectionEvent } from './errors'; diff --git a/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.test.ts b/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.test.ts index a24dc9759..dc4c2f734 100644 --- a/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.test.ts +++ b/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.test.ts @@ -1,6 +1,6 @@ import { buildStackFrame } from './buildStackFrame'; import { getStackFramesFromError } from './getStackFramesFromError'; -import {hrtime} from 'node:process'; +import { hrtime } from 'node:process'; jest.mock('./buildStackFrame', () => ({ buildStackFrame: jest.fn((filename, func, lineno, colno) => ({ filename, func, lineno, colno })), @@ -159,17 +159,32 @@ describe('getStackFramesFromError', () => { ]); }); - it('should correctly skip long lines if configured to', ()=> { + it('should correctly skip long lines if configured to', () => { var start = hrtime(); - const result = getStackFramesFromError(CapturedExceptions.SUPER_LONG_LINE, {maximumLineLength: 256}); - const elapsed = hrtime(start)[1] / 1000000 + const result = getStackFramesFromError(CapturedExceptions.SUPER_LONG_LINE, { maximumLineLength: 256 }); + const elapsed = hrtime(start)[1] / 1000000; expect(elapsed).toBeLessThan(0.5); expect(result).toEqual([ - buildStackFrame('http://localhost:5173/node_modules/.vite/deps/chunk-RH76XVE4.js?v=3214fecf', 'getTransactionError', 1619, 10), - buildStackFrame('http://localhost:5173/node_modules/.vite/deps/chunk-RH76XVE4.js?v=3214fecf', 'sendTransaction', 1750, 11), - buildStackFrame('http://localhost:5173/src/app/hooks/useSwapRouter.tsx?t=1737523345399', 'async Object.executeTxn', 450, 24), + buildStackFrame( + 'http://localhost:5173/node_modules/.vite/deps/chunk-RH76XVE4.js?v=3214fecf', + 'getTransactionError', + 1619, + 10 + ), + buildStackFrame( + 'http://localhost:5173/node_modules/.vite/deps/chunk-RH76XVE4.js?v=3214fecf', + 'sendTransaction', + 1750, + 11 + ), + buildStackFrame( + 'http://localhost:5173/src/app/hooks/useSwapRouter.tsx?t=1737523345399', + 'async Object.executeTxn', + 450, + 24 + ), ]); - }) + }); }); /* Taken from: https://github.com/stacktracejs/error-stack-parser/blob/master/spec/fixtures/captured-errors.js */ @@ -373,10 +388,10 @@ CapturedExceptions.NODE_WITH_SPACES = { }; CapturedExceptions.SUPER_LONG_LINE = { - description: "message string", + description: 'message string', message: 'message string', name: 'Error', - stack:`TransactionExecutionError: User rejected the request. + stack: `TransactionExecutionError: User rejected the request. Request Arguments: from: 0xB770B86b1544eDf51BBf82Dd01e8e867607Dba51 @@ -389,7 +404,5 @@ Details: MetaMask Tx Signature: User denied transaction signature. Version: viem@2.22.11 at getTransactionError (http://localhost:5173/node_modules/.vite/deps/chunk-RH76XVE4.js?v=3214fecf:1619:10) at sendTransaction (http://localhost:5173/node_modules/.vite/deps/chunk-RH76XVE4.js?v=3214fecf:1750:11) - at async Object.executeTxn (http://localhost:5173/src/app/hooks/useSwapRouter.tsx?t=1737523345399:450:24)` + at async Object.executeTxn (http://localhost:5173/src/app/hooks/useSwapRouter.tsx?t=1737523345399:450:24)`, }; - - diff --git a/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.ts b/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.ts index 55965bf50..e9a308960 100644 --- a/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.ts +++ b/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.ts @@ -18,7 +18,10 @@ import { } from './const'; import { getDataFromSafariExtensions } from './getDataFromSafariExtensions'; -export function getStackFramesFromError(error: ExtendedError, options: StackframeParserOptions = {}): ExceptionStackFrame[] { +export function getStackFramesFromError( + error: ExtendedError, + options: StackframeParserOptions = {} +): ExceptionStackFrame[] { let lines: string[] = []; if (error.stacktrace) { @@ -35,8 +38,8 @@ export function getStackFramesFromError(error: ExtendedError, options: Stackfram let colno: string | undefined; // skip attempting to parse stack frames over the limit, if it is set and above 0 - if(options.maximumLineLength !== undefined && options.maximumLineLength > 0) { - if(line.length > options.maximumLineLength) { + if (options.maximumLineLength !== undefined && options.maximumLineLength > 0) { + if (line.length > options.maximumLineLength) { return acc; } } diff --git a/packages/web-sdk/src/utils/stackFrames/index.ts b/packages/web-sdk/src/utils/stackFrames/index.ts index 2aaf8d940..5109f7073 100644 --- a/packages/web-sdk/src/utils/stackFrames/index.ts +++ b/packages/web-sdk/src/utils/stackFrames/index.ts @@ -4,6 +4,4 @@ export { getDataFromSafariExtensions } from './getDataFromSafariExtensions'; export { getStackFramesFromError } from './getStackFramesFromError'; -export { parseStacktrace, newStackTraceParser} from './parseStacktrace'; - - +export { parseStacktrace, newStackTraceParser } from './parseStacktrace'; diff --git a/packages/web-sdk/src/utils/stackFrames/parseStacktrace.ts b/packages/web-sdk/src/utils/stackFrames/parseStacktrace.ts index edcc00f18..06a9a34a6 100644 --- a/packages/web-sdk/src/utils/stackFrames/parseStacktrace.ts +++ b/packages/web-sdk/src/utils/stackFrames/parseStacktrace.ts @@ -4,7 +4,6 @@ import type { StackframeParserOptions } from './types'; import { getStackFramesFromError } from './getStackFramesFromError'; - export function parseStacktrace(error: ExtendedError): Stacktrace { return { frames: getStackFramesFromError(error), @@ -12,9 +11,9 @@ export function parseStacktrace(error: ExtendedError): Stacktrace { } export function newStackTraceParser(options?: StackframeParserOptions): StacktraceParser { - return (error: ExtendedError)=>{ + return (error: ExtendedError) => { return { frames: getStackFramesFromError(error, options), - } - } + }; + }; } From 33df376b370b7828a612b71953e216aac789c850 Mon Sep 17 00:00:00 2001 From: a Date: Thu, 12 Jun 2025 02:05:17 -0500 Subject: [PATCH 07/26] run eslint --- packages/web-sdk/src/config/makeCoreConfig.ts | 2 +- packages/web-sdk/src/config/types.ts | 1 + .../web-sdk/src/instrumentations/errors/getErrorDetails.ts | 3 ++- .../web-sdk/src/instrumentations/errors/instrumentation.ts | 1 - .../src/utils/stackFrames/getStackFramesFromError.test.ts | 5 +++-- .../web-sdk/src/utils/stackFrames/getStackFramesFromError.ts | 3 ++- packages/web-sdk/src/utils/stackFrames/parseStacktrace.ts | 2 +- 7 files changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/web-sdk/src/config/makeCoreConfig.ts b/packages/web-sdk/src/config/makeCoreConfig.ts index f39414719..a359ed8da 100644 --- a/packages/web-sdk/src/config/makeCoreConfig.ts +++ b/packages/web-sdk/src/config/makeCoreConfig.ts @@ -12,13 +12,13 @@ import { import type { Config, Instrumentation, MetaItem, MetaSession, Transport } from '@grafana/faro-core'; import { defaultEventDomain } from '../consts'; -import { parseStacktrace } from '../utils'; import { defaultSessionTrackingConfig } from '../instrumentations/session'; import { userActionDataAttribute } from '../instrumentations/userActions/const'; import { browserMeta } from '../metas'; import { k6Meta } from '../metas/k6'; import { createPageMeta } from '../metas/page'; import { FetchTransport } from '../transports'; +import { parseStacktrace } from '../utils'; import { getWebInstrumentations } from './getWebInstrumentations'; import type { BrowserConfig } from './types'; diff --git a/packages/web-sdk/src/config/types.ts b/packages/web-sdk/src/config/types.ts index 4b653cb23..13912aeba 100644 --- a/packages/web-sdk/src/config/types.ts +++ b/packages/web-sdk/src/config/types.ts @@ -1,4 +1,5 @@ import type { Config, LogLevel } from '@grafana/faro-core'; + import type { ErrorInstrumentationOptions } from '../instrumentations/errors/types'; export interface BrowserConfig extends Partial>, Pick { diff --git a/packages/web-sdk/src/instrumentations/errors/getErrorDetails.ts b/packages/web-sdk/src/instrumentations/errors/getErrorDetails.ts index 21fc6abde..3fa6c7f8e 100644 --- a/packages/web-sdk/src/instrumentations/errors/getErrorDetails.ts +++ b/packages/web-sdk/src/instrumentations/errors/getErrorDetails.ts @@ -1,9 +1,10 @@ import { isDomError, isDomException, isError, isErrorEvent, isEvent, isObject, isString } from '@grafana/faro-core'; import type { ExceptionStackFrame, LogArgsSerializer } from '@grafana/faro-core'; +import { buildStackFrame, getStackFramesFromError } from '../../utils/stackFrames'; + import { domErrorType, domExceptionType, objectEventValue, unknownSymbolString } from './const'; import { getValueAndTypeFromMessage } from './getValueAndTypeFromMessage'; -import { buildStackFrame, getStackFramesFromError } from '../../utils/stackFrames'; import type { ErrorEvent, ErrorInstrumentationOptions } from './types'; export function getErrorDetails( diff --git a/packages/web-sdk/src/instrumentations/errors/instrumentation.ts b/packages/web-sdk/src/instrumentations/errors/instrumentation.ts index 86e6eee1b..9ba038060 100644 --- a/packages/web-sdk/src/instrumentations/errors/instrumentation.ts +++ b/packages/web-sdk/src/instrumentations/errors/instrumentation.ts @@ -2,7 +2,6 @@ import { BaseInstrumentation, VERSION } from '@grafana/faro-core'; import { registerOnerror } from './registerOnerror'; import { registerOnunhandledrejection } from './registerOnunhandledrejection'; - import type { ErrorInstrumentationOptions } from './types'; export class ErrorsInstrumentation extends BaseInstrumentation { diff --git a/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.test.ts b/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.test.ts index dc4c2f734..980b2444c 100644 --- a/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.test.ts +++ b/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.test.ts @@ -1,6 +1,7 @@ +import { hrtime } from 'node:process'; + import { buildStackFrame } from './buildStackFrame'; import { getStackFramesFromError } from './getStackFramesFromError'; -import { hrtime } from 'node:process'; jest.mock('./buildStackFrame', () => ({ buildStackFrame: jest.fn((filename, func, lineno, colno) => ({ filename, func, lineno, colno })), @@ -160,7 +161,7 @@ describe('getStackFramesFromError', () => { }); it('should correctly skip long lines if configured to', () => { - var start = hrtime(); + let start = hrtime(); const result = getStackFramesFromError(CapturedExceptions.SUPER_LONG_LINE, { maximumLineLength: 256 }); const elapsed = hrtime(start)[1] / 1000000; expect(elapsed).toBeLessThan(0.5); diff --git a/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.ts b/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.ts index e9a308960..4ca6f8fe2 100644 --- a/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.ts +++ b/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.ts @@ -1,6 +1,6 @@ import { isNumber } from '@grafana/faro-core'; import type { ExceptionStackFrame, ExtendedError } from '@grafana/faro-core'; -import type { StackframeParserOptions } from './types'; + import { buildStackFrame } from './buildStackFrame'; import { @@ -17,6 +17,7 @@ import { webkitLineRegex, } from './const'; import { getDataFromSafariExtensions } from './getDataFromSafariExtensions'; +import type { StackframeParserOptions } from './types'; export function getStackFramesFromError( error: ExtendedError, diff --git a/packages/web-sdk/src/utils/stackFrames/parseStacktrace.ts b/packages/web-sdk/src/utils/stackFrames/parseStacktrace.ts index 06a9a34a6..0b11742f8 100644 --- a/packages/web-sdk/src/utils/stackFrames/parseStacktrace.ts +++ b/packages/web-sdk/src/utils/stackFrames/parseStacktrace.ts @@ -1,8 +1,8 @@ import type { ExtendedError, Stacktrace, StacktraceParser } from '@grafana/faro-core'; +import { getStackFramesFromError } from './getStackFramesFromError'; import type { StackframeParserOptions } from './types'; -import { getStackFramesFromError } from './getStackFramesFromError'; export function parseStacktrace(error: ExtendedError): Stacktrace { return { From 57da3858f5ad19a6ccc4fc99bc96b389404d4af6 Mon Sep 17 00:00:00 2001 From: a Date: Thu, 12 Jun 2025 02:05:41 -0500 Subject: [PATCH 08/26] run prettier --- .../web-sdk/src/utils/stackFrames/getStackFramesFromError.ts | 1 - packages/web-sdk/src/utils/stackFrames/parseStacktrace.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.ts b/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.ts index 4ca6f8fe2..28fcf8cbe 100644 --- a/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.ts +++ b/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.ts @@ -1,7 +1,6 @@ import { isNumber } from '@grafana/faro-core'; import type { ExceptionStackFrame, ExtendedError } from '@grafana/faro-core'; - import { buildStackFrame } from './buildStackFrame'; import { evalString, diff --git a/packages/web-sdk/src/utils/stackFrames/parseStacktrace.ts b/packages/web-sdk/src/utils/stackFrames/parseStacktrace.ts index 0b11742f8..3669819e8 100644 --- a/packages/web-sdk/src/utils/stackFrames/parseStacktrace.ts +++ b/packages/web-sdk/src/utils/stackFrames/parseStacktrace.ts @@ -3,7 +3,6 @@ import type { ExtendedError, Stacktrace, StacktraceParser } from '@grafana/faro- import { getStackFramesFromError } from './getStackFramesFromError'; import type { StackframeParserOptions } from './types'; - export function parseStacktrace(error: ExtendedError): Stacktrace { return { frames: getStackFramesFromError(error), From cc23677a19b4fe1e493ea52c1d2ae5802856a5be Mon Sep 17 00:00:00 2001 From: a Date: Thu, 12 Jun 2025 02:10:08 -0500 Subject: [PATCH 09/26] noot --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3062946c1..d95c2e358 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,8 @@ - chore(user actions): Rename `userActionEventType` to `userActionTrigger` for improved clarity (#1298) - chore(`@grafana/faro web-sdk`): Move the stackFrames from the errors instrumentation package to the utils package (#1316) -- improvement (`@grafana/faro-web-sdk`): Allow users to configure the stack frame tracer in the ErrorsInstrumentation and the stackTraceParser in the BrowserConfig (#1316) - +- improvement (`@grafana/faro-web-sdk`): Allow users to configure the stack frame tracer + in the ErrorsInstrumentation and the stackTraceParser in the BrowserConfig (#1316) ## 1.18.2 From ed2367091c6a40e8f72fba6303b578778816a212 Mon Sep 17 00:00:00 2001 From: a Date: Thu, 12 Jun 2025 02:28:23 -0500 Subject: [PATCH 10/26] skipping works --- .../src/utils/stackFrames/getStackFramesFromError.test.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.test.ts b/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.test.ts index 980b2444c..4744f4e39 100644 --- a/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.test.ts +++ b/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.test.ts @@ -186,6 +186,14 @@ describe('getStackFramesFromError', () => { ), ]); }); + + it('should correctly skip short lines if configured to', () => { + let start = hrtime(); + const result = getStackFramesFromError(CapturedExceptions.SUPER_LONG_LINE, { maximumLineLength: 1 }); + const elapsed = hrtime(start)[1] / 1000000; + expect(elapsed).toBeLessThan(0.5); + expect(result).toEqual([]); + }); }); /* Taken from: https://github.com/stacktracejs/error-stack-parser/blob/master/spec/fixtures/captured-errors.js */ From 747a0a3c3da44c9aafe98c2845fe50c25e3b6413 Mon Sep 17 00:00:00 2001 From: a Date: Thu, 12 Jun 2025 02:32:25 -0500 Subject: [PATCH 11/26] better test --- .../getStackFramesFromError.test.ts | 58 +------------------ 1 file changed, 3 insertions(+), 55 deletions(-) diff --git a/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.test.ts b/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.test.ts index 4744f4e39..efa098098 100644 --- a/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.test.ts +++ b/packages/web-sdk/src/utils/stackFrames/getStackFramesFromError.test.ts @@ -1,5 +1,3 @@ -import { hrtime } from 'node:process'; - import { buildStackFrame } from './buildStackFrame'; import { getStackFramesFromError } from './getStackFramesFromError'; @@ -160,39 +158,9 @@ describe('getStackFramesFromError', () => { ]); }); - it('should correctly skip long lines if configured to', () => { - let start = hrtime(); - const result = getStackFramesFromError(CapturedExceptions.SUPER_LONG_LINE, { maximumLineLength: 256 }); - const elapsed = hrtime(start)[1] / 1000000; - expect(elapsed).toBeLessThan(0.5); - expect(result).toEqual([ - buildStackFrame( - 'http://localhost:5173/node_modules/.vite/deps/chunk-RH76XVE4.js?v=3214fecf', - 'getTransactionError', - 1619, - 10 - ), - buildStackFrame( - 'http://localhost:5173/node_modules/.vite/deps/chunk-RH76XVE4.js?v=3214fecf', - 'sendTransaction', - 1750, - 11 - ), - buildStackFrame( - 'http://localhost:5173/src/app/hooks/useSwapRouter.tsx?t=1737523345399', - 'async Object.executeTxn', - 450, - 24 - ), - ]); - }); - - it('should correctly skip short lines if configured to', () => { - let start = hrtime(); - const result = getStackFramesFromError(CapturedExceptions.SUPER_LONG_LINE, { maximumLineLength: 1 }); - const elapsed = hrtime(start)[1] / 1000000; - expect(elapsed).toBeLessThan(0.5); - expect(result).toEqual([]); + it('should correctly skip lines if configured to', () => { + const result = getStackFramesFromError(CapturedExceptions.OPERA_25, { maximumLineLength: 36 }); + expect(result).toEqual([buildStackFrame('http://path/to/file.js', undefined, 47, 22)]); }); }); @@ -395,23 +363,3 @@ CapturedExceptions.NODE_WITH_SPACES = { 'Function.Module.runMain (internal/modules/cjs/loader.js:837:10)\n at ' + 'internal/main/run_main_module.js:17:11', }; - -CapturedExceptions.SUPER_LONG_LINE = { - description: 'message string', - message: 'message string', - name: 'Error', - stack: `TransactionExecutionError: User rejected the request. - -Request Arguments: - from: 0xB770B86b1544eDf51BBf82Dd01e8e867607Dba51 - to: 0x6352a56caadC4F1E25CD6c75970Fa768A3304e64 - value: 0 ETH - data: 0x90411a320000000000000000000000002691f337abeb0146f16441ca4f82f363275851d5000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff8500000000000000000000000042000000000000000000000000000000000000060000000000000000000000002691f337abeb0146f16441ca4f82f363275851d5000000000000000000000000b770b86b1544edf51bbf82dd01e8e867607dba510000000000000000000000000000000000000000000000000000000000989680000000000000000000000000000000000000000000000000000a9c0ba2e15270000000000000000000000000000000000000000000000000000aa9b1a4fc2ed50000000000000000000000000000000000000000000000000000000000000002000000000000000000000000de219fe970acbc88c63c9c4d0705837c6701495f00000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000104e5b07cdb000000000000000000000000478946bcd4a5a22b316470f5486fafb928c0ba25000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000009896800000000000000000000000002691f337abeb0146f16441ca4f82f363275851d500000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000002e0b2c639c533813f4aa9d7837caf62653d097ff85000064420000000000000000000000000000000000000600002e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000648a6a1e850000000000000000000000004200000000000000000000000000000000000006000000000000000000000000922164bbbd36acf9e854acbbf32facc949fcaeef000000000000000000000000000000000000000000000000000aa9b1a4fc2ed500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001a49f865422000000000000000000000000420000000000000000000000000000000000000600000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064d1660f990000000000000000000000004200000000000000000000000000000000000006000000000000000000000000b770b86b1544edf51bbf82dd01e8e867607dba5100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - gas: 467935 - -Details: MetaMask Tx Signature: User denied transaction signature. -Version: viem@2.22.11 - at getTransactionError (http://localhost:5173/node_modules/.vite/deps/chunk-RH76XVE4.js?v=3214fecf:1619:10) - at sendTransaction (http://localhost:5173/node_modules/.vite/deps/chunk-RH76XVE4.js?v=3214fecf:1750:11) - at async Object.executeTxn (http://localhost:5173/src/app/hooks/useSwapRouter.tsx?t=1737523345399:450:24)`, -}; From 85df37e17d6baef719af12982cbd4111341e495b Mon Sep 17 00:00:00 2001 From: a Date: Sun, 15 Jun 2025 20:28:40 -0500 Subject: [PATCH 12/26] noot --- .../src/config/getWebInstrumentations.ts | 2 +- packages/web-sdk/src/config/types.ts | 3 --- .../errors/getErrorDetails.ts | 22 +++++++++++-------- .../errors/instrumentation.ts | 7 +++--- .../errors/registerOnerror.ts | 6 ++--- .../errors/registerOnunhandledrejection.ts | 8 +++---- .../src/instrumentations/errors/types.ts | 6 ----- 7 files changed, 24 insertions(+), 30 deletions(-) diff --git a/packages/web-sdk/src/config/getWebInstrumentations.ts b/packages/web-sdk/src/config/getWebInstrumentations.ts index 2421621ee..4dcb7e262 100644 --- a/packages/web-sdk/src/config/getWebInstrumentations.ts +++ b/packages/web-sdk/src/config/getWebInstrumentations.ts @@ -15,7 +15,7 @@ import type { GetWebInstrumentationsOptions } from './types'; export function getWebInstrumentations(options: GetWebInstrumentationsOptions = {}): Instrumentation[] { const instrumentations: Instrumentation[] = [ new UserActionInstrumentation(), - new ErrorsInstrumentation(options.errorInstrumentationOptions), + new ErrorsInstrumentation(), new WebVitalsInstrumentation(), new SessionInstrumentation(), new ViewInstrumentation(), diff --git a/packages/web-sdk/src/config/types.ts b/packages/web-sdk/src/config/types.ts index 13912aeba..313677787 100644 --- a/packages/web-sdk/src/config/types.ts +++ b/packages/web-sdk/src/config/types.ts @@ -1,7 +1,5 @@ import type { Config, LogLevel } from '@grafana/faro-core'; -import type { ErrorInstrumentationOptions } from '../instrumentations/errors/types'; - export interface BrowserConfig extends Partial>, Pick { url?: string; apiKey?: string; @@ -11,5 +9,4 @@ export interface GetWebInstrumentationsOptions { captureConsole?: boolean; captureConsoleDisabledLevels?: LogLevel[]; enablePerformanceInstrumentation?: boolean; - errorInstrumentationOptions?: ErrorInstrumentationOptions; } diff --git a/packages/web-sdk/src/instrumentations/errors/getErrorDetails.ts b/packages/web-sdk/src/instrumentations/errors/getErrorDetails.ts index 3fa6c7f8e..62871a2a4 100644 --- a/packages/web-sdk/src/instrumentations/errors/getErrorDetails.ts +++ b/packages/web-sdk/src/instrumentations/errors/getErrorDetails.ts @@ -1,15 +1,15 @@ import { isDomError, isDomException, isError, isErrorEvent, isEvent, isObject, isString } from '@grafana/faro-core'; -import type { ExceptionStackFrame, LogArgsSerializer } from '@grafana/faro-core'; +import type { ExceptionStackFrame, LogArgsSerializer, StacktraceParser } from '@grafana/faro-core'; -import { buildStackFrame, getStackFramesFromError } from '../../utils/stackFrames'; +import { buildStackFrame, newStackTraceParser } from '../../utils/stackFrames'; import { domErrorType, domExceptionType, objectEventValue, unknownSymbolString } from './const'; import { getValueAndTypeFromMessage } from './getValueAndTypeFromMessage'; -import type { ErrorEvent, ErrorInstrumentationOptions } from './types'; +import type { ErrorEvent } from './types'; export function getErrorDetails( evt: ErrorEvent, - options: ErrorInstrumentationOptions = {} + stacktraceParser: StacktraceParser = newStackTraceParser() ): [string | undefined, string | undefined, ExceptionStackFrame[]] { let value: string | undefined; let type: string | undefined; @@ -20,15 +20,16 @@ export function getErrorDetails( if (isErrorEvent(evt) && evt.error) { value = evt.error.message; type = evt.error.name; - stackFrames = getStackFramesFromError(evt.error, options.stackframeParserOptions); + const { frames } = stacktraceParser(evt.error); + stackFrames = frames; } else if ((isDomErrorRes = isDomError(evt)) || isDomException(evt)) { const { name, message } = evt; - type = name ?? (isDomErrorRes ? domErrorType : domExceptionType); value = message ? `${type}: ${message}` : type; } else if (isError(evt)) { value = evt.message; - stackFrames = getStackFramesFromError(evt, options.stackframeParserOptions); + const { frames } = stacktraceParser(evt); + stackFrames = frames; } else if (isObject(evt) || (isEventRes = isEvent(evt))) { type = isEventRes ? evt.constructor.name : undefined; value = `${objectEventValue} ${Object.keys(evt)}`; @@ -43,7 +44,10 @@ export interface ErrorDetails { stackFrames?: ExceptionStackFrame[]; } -export function getDetailsFromErrorArgs(args: [any?, ...any[]]): ErrorDetails { +export function getDetailsFromErrorArgs( + args: [any?, ...any[]], + stacktraceParser: StacktraceParser = newStackTraceParser() +): ErrorDetails { const [evt, source, lineno, colno, error] = args; let value: string | undefined; @@ -53,7 +57,7 @@ export function getDetailsFromErrorArgs(args: [any?, ...any[]]): ErrorDetails { const initialStackFrame = buildStackFrame(source, unknownSymbolString, lineno, colno); if (error || !eventIsString) { - [value, type, stackFrames] = getErrorDetails((error ?? evt) as Error | Event); + [value, type, stackFrames] = getErrorDetails((error ?? evt) as Error | Event, stacktraceParser); if (stackFrames.length === 0) { stackFrames = [initialStackFrame]; diff --git a/packages/web-sdk/src/instrumentations/errors/instrumentation.ts b/packages/web-sdk/src/instrumentations/errors/instrumentation.ts index 9ba038060..05e56f1e9 100644 --- a/packages/web-sdk/src/instrumentations/errors/instrumentation.ts +++ b/packages/web-sdk/src/instrumentations/errors/instrumentation.ts @@ -2,21 +2,20 @@ import { BaseInstrumentation, VERSION } from '@grafana/faro-core'; import { registerOnerror } from './registerOnerror'; import { registerOnunhandledrejection } from './registerOnunhandledrejection'; -import type { ErrorInstrumentationOptions } from './types'; export class ErrorsInstrumentation extends BaseInstrumentation { readonly name = '@grafana/faro-web-sdk:instrumentation-errors'; readonly version = VERSION; - constructor(private readonly options: ErrorInstrumentationOptions = {}) { + constructor() { super(); } initialize(): void { this.logDebug('Initializing'); - registerOnerror(this.api); + registerOnerror(this.api, this.config); - registerOnunhandledrejection(this.api, this.options); + registerOnunhandledrejection(this.api, this.config); } } diff --git a/packages/web-sdk/src/instrumentations/errors/registerOnerror.ts b/packages/web-sdk/src/instrumentations/errors/registerOnerror.ts index 609a0c3ae..1f22ee9b0 100644 --- a/packages/web-sdk/src/instrumentations/errors/registerOnerror.ts +++ b/packages/web-sdk/src/instrumentations/errors/registerOnerror.ts @@ -1,13 +1,13 @@ -import type { API, PushErrorOptions } from '@grafana/faro-core'; +import type { API, Config, PushErrorOptions } from '@grafana/faro-core'; import { getDetailsFromErrorArgs } from './getErrorDetails'; -export function registerOnerror(api: API): void { +export function registerOnerror(api: API, config: Config): void { const oldOnerror = window.onerror; window.onerror = (...args) => { try { - const { value, type, stackFrames } = getDetailsFromErrorArgs(args); + const { value, type, stackFrames } = getDetailsFromErrorArgs(args, config.parseStacktrace); const originalError = args[4]; if (value) { diff --git a/packages/web-sdk/src/instrumentations/errors/registerOnunhandledrejection.ts b/packages/web-sdk/src/instrumentations/errors/registerOnunhandledrejection.ts index 1ad89518a..d2d303aeb 100644 --- a/packages/web-sdk/src/instrumentations/errors/registerOnunhandledrejection.ts +++ b/packages/web-sdk/src/instrumentations/errors/registerOnunhandledrejection.ts @@ -1,11 +1,11 @@ import { isPrimitive } from '@grafana/faro-core'; -import type { API, ExceptionStackFrame } from '@grafana/faro-core'; +import type { API, Config, ExceptionStackFrame } from '@grafana/faro-core'; import { primitiveUnhandledType, primitiveUnhandledValue } from './const'; import { getErrorDetails } from './getErrorDetails'; -import type { ErrorInstrumentationOptions, ExtendedPromiseRejectionEvent } from './types'; +import type { ExtendedPromiseRejectionEvent } from './types'; -export function registerOnunhandledrejection(api: API, options: ErrorInstrumentationOptions = {}): void { +export function registerOnunhandledrejection(api: API, config: Config): void { window.addEventListener('unhandledrejection', (evt: ExtendedPromiseRejectionEvent) => { let error = evt; @@ -22,7 +22,7 @@ export function registerOnunhandledrejection(api: API, options: ErrorInstrumenta value = `${primitiveUnhandledValue} ${String(error)}`; type = primitiveUnhandledType; } else { - [value, type, stackFrames] = getErrorDetails(error, options); + [value, type, stackFrames] = getErrorDetails(error, config.parseStacktrace); } if (value) { diff --git a/packages/web-sdk/src/instrumentations/errors/types.ts b/packages/web-sdk/src/instrumentations/errors/types.ts index 7fcd97b1a..4eabd1286 100644 --- a/packages/web-sdk/src/instrumentations/errors/types.ts +++ b/packages/web-sdk/src/instrumentations/errors/types.ts @@ -1,5 +1,3 @@ -import type { StackframeParserOptions } from '../../utils/stackFrames/types'; - export interface ExtendedPromiseRejectionEvent extends PromiseRejectionEvent { detail?: { reason: PromiseRejectionEvent['reason']; @@ -9,7 +7,3 @@ export interface ExtendedPromiseRejectionEvent extends PromiseRejectionEvent { export type ErrorEvent = (Error | Event) & { error?: Error; }; - -export type ErrorInstrumentationOptions = { - stackframeParserOptions?: StackframeParserOptions; -}; From c4414d1708b026a812f7f3c83f206f75e16a2204 Mon Sep 17 00:00:00 2001 From: a Date: Sun, 15 Jun 2025 20:29:55 -0500 Subject: [PATCH 13/26] noot --- CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d95c2e358..62151c6ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,7 @@ - chore(user actions): Rename `userActionEventType` to `userActionTrigger` for improved clarity (#1298) - chore(`@grafana/faro web-sdk`): Move the stackFrames from the errors instrumentation package to the utils package (#1316) -- improvement (`@grafana/faro-web-sdk`): Allow users to configure the stack frame tracer - in the ErrorsInstrumentation and the stackTraceParser in the BrowserConfig (#1316) +- improvement (`@grafana/faro-web-sdk`): Allow users to configure the stackTraceParser in the BrowserConfig (#1316) ## 1.18.2 From 8c1c8e32772e94a16db265c79c22084e1cae24bd Mon Sep 17 00:00:00 2001 From: a Date: Sun, 15 Jun 2025 20:41:20 -0500 Subject: [PATCH 14/26] noot --- .../errors/getErrorDetails.test.ts | 36 +++++++++---------- .../errors/registerOnerror.test.ts | 12 +++---- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/packages/web-sdk/src/instrumentations/errors/getErrorDetails.test.ts b/packages/web-sdk/src/instrumentations/errors/getErrorDetails.test.ts index 414699f5d..b863284c8 100644 --- a/packages/web-sdk/src/instrumentations/errors/getErrorDetails.test.ts +++ b/packages/web-sdk/src/instrumentations/errors/getErrorDetails.test.ts @@ -16,7 +16,7 @@ import { registerOnerror } from './registerOnerror'; describe('errors', () => { it('parses an Error passed to console.error', () => { const transport = new MockTransport(); - const { api } = initializeFaro( + const { api, config } = initializeFaro( mockConfig({ instrumentations: [new ConsoleInstrumentation()], transports: [transport], @@ -26,7 +26,7 @@ describe('errors', () => { }) ); - registerOnerror(api); + registerOnerror(api, config); console.error(new Error('boo')); expect((transport.items[0] as TransportItem).payload.value).toBe('console.error: boo'); @@ -34,7 +34,7 @@ describe('errors', () => { it('parses text values passed to console.error', () => { const transport = new MockTransport(); - const { api } = initializeFaro( + const { api, config } = initializeFaro( mockConfig({ instrumentations: [new ConsoleInstrumentation()], transports: [transport], @@ -44,7 +44,7 @@ describe('errors', () => { }) ); - registerOnerror(api); + registerOnerror(api, config); console.error('boo', 'other', 'details'); expect((transport.items[0] as TransportItem).payload.value).toBe( @@ -54,7 +54,7 @@ describe('errors', () => { it('parses text values and an object passed to console.error', () => { const transport = new MockTransport(); - const { api } = initializeFaro( + const { api, config } = initializeFaro( mockConfig({ instrumentations: [new ConsoleInstrumentation()], transports: [transport], @@ -67,7 +67,7 @@ describe('errors', () => { }) ); - registerOnerror(api); + registerOnerror(api, config); const details = { other: 'details' }; console.error('boo', details); @@ -78,7 +78,7 @@ describe('errors', () => { it('parses text values and an object passed to console.error with custom serializer', () => { const transport = new MockTransport(); - const { api } = initializeFaro( + const { api, config } = initializeFaro( mockConfig({ instrumentations: [new ConsoleInstrumentation()], transports: [transport], @@ -91,7 +91,7 @@ describe('errors', () => { }) ); - registerOnerror(api); + registerOnerror(api, config); const details = { other: 'details' }; console.error('boo', details); @@ -102,7 +102,7 @@ describe('errors', () => { it('parses text values and an object passed to console.error and returns it as a log', () => { const transport = new MockTransport(); - const { api } = initializeFaro( + const { api, config } = initializeFaro( mockConfig({ instrumentations: [new ConsoleInstrumentation()], transports: [transport], @@ -116,7 +116,7 @@ describe('errors', () => { }) ); - registerOnerror(api); + registerOnerror(api, config); const details = { other: 'details' }; console.error('boo', details); @@ -135,7 +135,7 @@ describe('errors', () => { }; const transport = new MockTransport(); - const { api } = initializeFaro( + const { api, config } = initializeFaro( mockConfig({ instrumentations: [new ConsoleInstrumentation()], transports: [transport], @@ -145,7 +145,7 @@ describe('errors', () => { }) ); - registerOnerror(api); + registerOnerror(api, config); window.onerror('boo', 'some file', 10, 10); @@ -163,7 +163,7 @@ describe('errors', () => { }; const transport = new MockTransport(); - const { api } = initializeFaro( + const { api, config } = initializeFaro( mockConfig({ instrumentations: [new ConsoleInstrumentation()], transports: [transport], @@ -173,7 +173,7 @@ describe('errors', () => { }) ); - registerOnerror(api); + registerOnerror(api, config); window.onerror('not boo', 'some file', 10, 10, new Error('boo')); @@ -188,7 +188,7 @@ describe('errors', () => { }; const transport = new MockTransport(); - const { api } = initializeFaro( + const { api, config } = initializeFaro( mockConfig({ instrumentations: [new ConsoleInstrumentation()], transports: [transport], @@ -198,7 +198,7 @@ describe('errors', () => { }) ); - registerOnerror(api); + registerOnerror(api, config); window.onerror(new Error('boo') as unknown as Event); @@ -208,7 +208,7 @@ describe('errors', () => { it('getErrorDetails returns correct values when an ErrorEvent is passed to onerror with special characters in the file path for webkit engine', () => { const transport = new MockTransport(); - const { api } = initializeFaro( + const { api, config } = initializeFaro( mockConfig({ instrumentations: [new ConsoleInstrumentation()], transports: [transport], @@ -218,7 +218,7 @@ describe('errors', () => { }) ); - registerOnerror(api); + registerOnerror(api, config); let e = new Error('Oh crap!'); e.stack = 'Error: Oh crap!\n at Object.eval [as refinement] (https://example.com/(main)/[path]/to.js:1:2345)'; diff --git a/packages/web-sdk/src/instrumentations/errors/registerOnerror.test.ts b/packages/web-sdk/src/instrumentations/errors/registerOnerror.test.ts index 19b2231ae..66c756f81 100644 --- a/packages/web-sdk/src/instrumentations/errors/registerOnerror.test.ts +++ b/packages/web-sdk/src/instrumentations/errors/registerOnerror.test.ts @@ -14,13 +14,13 @@ describe('registerOnerror', () => { }; const transport = new MockTransport(); - const { api } = initializeFaro( + const { api, config } = initializeFaro( mockConfig({ transports: [transport], }) ); - registerOnerror(api); + registerOnerror(api, config); window.onerror('boo', 'some file', 10, 10, new Error('boo')); expect(called).toBe(true); @@ -30,14 +30,14 @@ describe('registerOnerror', () => { it('In case of an error, the original error is not lost', () => { const originalError = new Error('original error'); const transport = new MockTransport(); - const { api } = initializeFaro( + const { api, config } = initializeFaro( mockConfig({ transports: [transport], preserveOriginalError: true, }) ); - registerOnerror(api); + registerOnerror(api, config); window.onerror?.('boo', 'some file', 10, 10, originalError); expect(transport.items).toHaveLength(1); @@ -50,7 +50,7 @@ describe('registerOnerror', () => { it('will filter out errors by string or regex', () => { const transport = new MockTransport(); - const { api } = initializeFaro( + const { api, config } = initializeFaro( mockConfig({ transports: [transport], ignoreErrors: ['chrome-extension'], @@ -58,7 +58,7 @@ describe('registerOnerror', () => { }) ); - registerOnerror(api); + registerOnerror(api, config); window.onerror?.('boo', 'some file', 10, 10, new Error('Tracked error')); From feee0efe1d2de814615603a808d59f5d0fe808e0 Mon Sep 17 00:00:00 2001 From: a Date: Wed, 16 Jul 2025 22:37:55 -0500 Subject: [PATCH 15/26] noot --- .../developer/architecture/components/api.md | 1 - .../core/src/api/exceptions/initialize.ts | 11 +----- packages/core/src/api/exceptions/types.ts | 1 - packages/core/src/api/initialize.test.ts | 1 - packages/core/src/config/types.ts | 2 +- .../errors/getErrorDetails.test.ts | 36 +++++++++---------- .../errors/instrumentation.ts | 4 +-- .../errors/registerOnerror.test.ts | 12 +++---- .../errors/registerOnerror.ts | 6 ++-- .../errors/registerOnunhandledrejection.ts | 6 ++-- 10 files changed, 34 insertions(+), 46 deletions(-) diff --git a/docs/sources/developer/architecture/components/api.md b/docs/sources/developer/architecture/components/api.md index 1a5226cac..b49edfb3a 100644 --- a/docs/sources/developer/architecture/components/api.md +++ b/docs/sources/developer/architecture/components/api.md @@ -24,7 +24,6 @@ like `web-sdk` or by the user. Methods: -- `changeStacktraceParser` - replaces the existing stacktrace parser with a new one - `getStacktraceParser` - returns the current stacktrace parser - `pushError` - sends an exception diff --git a/packages/core/src/api/exceptions/initialize.ts b/packages/core/src/api/exceptions/initialize.ts index f85b453f0..2ba4b0a09 100644 --- a/packages/core/src/api/exceptions/initialize.ts +++ b/packages/core/src/api/exceptions/initialize.ts @@ -49,13 +49,7 @@ export function initializeExceptionsAPI({ let lastPayload: Pick | null = null; - stacktraceParser = config.parseStacktrace ?? stacktraceParser; - - const changeStacktraceParser: ExceptionsAPI['changeStacktraceParser'] = (newStacktraceParser) => { - internalLogger.debug('Changing stacktrace parser'); - - stacktraceParser = newStacktraceParser ?? stacktraceParser; - }; + stacktraceParser = config.parseStacktrace; const getStacktraceParser: ExceptionsAPI['getStacktraceParser'] = () => stacktraceParser; @@ -128,10 +122,7 @@ export function initializeExceptionsAPI({ } }; - changeStacktraceParser(config.parseStacktrace); - return { - changeStacktraceParser, getStacktraceParser, pushError, }; diff --git a/packages/core/src/api/exceptions/types.ts b/packages/core/src/api/exceptions/types.ts index 63c53661e..2570310f7 100644 --- a/packages/core/src/api/exceptions/types.ts +++ b/packages/core/src/api/exceptions/types.ts @@ -72,7 +72,6 @@ export type ErrorWithIndexProperties = Error & { }; export interface ExceptionsAPI { - changeStacktraceParser: (stacktraceParser: StacktraceParser) => void; getStacktraceParser: () => StacktraceParser | undefined; pushError: (value: ErrorWithIndexProperties, options?: PushErrorOptions) => void; } diff --git a/packages/core/src/api/initialize.test.ts b/packages/core/src/api/initialize.test.ts index aa6df3542..8c0e5e354 100644 --- a/packages/core/src/api/initialize.test.ts +++ b/packages/core/src/api/initialize.test.ts @@ -17,7 +17,6 @@ describe('initialize', () => { expect(api).toHaveProperty('pushMeasurement'); expect(api).toHaveProperty('pushTraces'); expect(api).toHaveProperty('pushEvent'); - expect(api).toHaveProperty('changeStacktraceParser'); expect(api).toHaveProperty('getOTEL'); expect(api).toHaveProperty('getPage'); expect(api).toHaveProperty('getSession'); diff --git a/packages/core/src/config/types.ts b/packages/core/src/config/types.ts index 25bfbf84e..150c2dc21 100644 --- a/packages/core/src/config/types.ts +++ b/packages/core/src/config/types.ts @@ -57,7 +57,7 @@ export interface Config

{ metas: MetaItem[]; /** - * Custom function used to parse stack traces + * The stacktrace parser to use for parsing stack traces. */ parseStacktrace: StacktraceParser; diff --git a/packages/web-sdk/src/instrumentations/errors/getErrorDetails.test.ts b/packages/web-sdk/src/instrumentations/errors/getErrorDetails.test.ts index b863284c8..414699f5d 100644 --- a/packages/web-sdk/src/instrumentations/errors/getErrorDetails.test.ts +++ b/packages/web-sdk/src/instrumentations/errors/getErrorDetails.test.ts @@ -16,7 +16,7 @@ import { registerOnerror } from './registerOnerror'; describe('errors', () => { it('parses an Error passed to console.error', () => { const transport = new MockTransport(); - const { api, config } = initializeFaro( + const { api } = initializeFaro( mockConfig({ instrumentations: [new ConsoleInstrumentation()], transports: [transport], @@ -26,7 +26,7 @@ describe('errors', () => { }) ); - registerOnerror(api, config); + registerOnerror(api); console.error(new Error('boo')); expect((transport.items[0] as TransportItem).payload.value).toBe('console.error: boo'); @@ -34,7 +34,7 @@ describe('errors', () => { it('parses text values passed to console.error', () => { const transport = new MockTransport(); - const { api, config } = initializeFaro( + const { api } = initializeFaro( mockConfig({ instrumentations: [new ConsoleInstrumentation()], transports: [transport], @@ -44,7 +44,7 @@ describe('errors', () => { }) ); - registerOnerror(api, config); + registerOnerror(api); console.error('boo', 'other', 'details'); expect((transport.items[0] as TransportItem).payload.value).toBe( @@ -54,7 +54,7 @@ describe('errors', () => { it('parses text values and an object passed to console.error', () => { const transport = new MockTransport(); - const { api, config } = initializeFaro( + const { api } = initializeFaro( mockConfig({ instrumentations: [new ConsoleInstrumentation()], transports: [transport], @@ -67,7 +67,7 @@ describe('errors', () => { }) ); - registerOnerror(api, config); + registerOnerror(api); const details = { other: 'details' }; console.error('boo', details); @@ -78,7 +78,7 @@ describe('errors', () => { it('parses text values and an object passed to console.error with custom serializer', () => { const transport = new MockTransport(); - const { api, config } = initializeFaro( + const { api } = initializeFaro( mockConfig({ instrumentations: [new ConsoleInstrumentation()], transports: [transport], @@ -91,7 +91,7 @@ describe('errors', () => { }) ); - registerOnerror(api, config); + registerOnerror(api); const details = { other: 'details' }; console.error('boo', details); @@ -102,7 +102,7 @@ describe('errors', () => { it('parses text values and an object passed to console.error and returns it as a log', () => { const transport = new MockTransport(); - const { api, config } = initializeFaro( + const { api } = initializeFaro( mockConfig({ instrumentations: [new ConsoleInstrumentation()], transports: [transport], @@ -116,7 +116,7 @@ describe('errors', () => { }) ); - registerOnerror(api, config); + registerOnerror(api); const details = { other: 'details' }; console.error('boo', details); @@ -135,7 +135,7 @@ describe('errors', () => { }; const transport = new MockTransport(); - const { api, config } = initializeFaro( + const { api } = initializeFaro( mockConfig({ instrumentations: [new ConsoleInstrumentation()], transports: [transport], @@ -145,7 +145,7 @@ describe('errors', () => { }) ); - registerOnerror(api, config); + registerOnerror(api); window.onerror('boo', 'some file', 10, 10); @@ -163,7 +163,7 @@ describe('errors', () => { }; const transport = new MockTransport(); - const { api, config } = initializeFaro( + const { api } = initializeFaro( mockConfig({ instrumentations: [new ConsoleInstrumentation()], transports: [transport], @@ -173,7 +173,7 @@ describe('errors', () => { }) ); - registerOnerror(api, config); + registerOnerror(api); window.onerror('not boo', 'some file', 10, 10, new Error('boo')); @@ -188,7 +188,7 @@ describe('errors', () => { }; const transport = new MockTransport(); - const { api, config } = initializeFaro( + const { api } = initializeFaro( mockConfig({ instrumentations: [new ConsoleInstrumentation()], transports: [transport], @@ -198,7 +198,7 @@ describe('errors', () => { }) ); - registerOnerror(api, config); + registerOnerror(api); window.onerror(new Error('boo') as unknown as Event); @@ -208,7 +208,7 @@ describe('errors', () => { it('getErrorDetails returns correct values when an ErrorEvent is passed to onerror with special characters in the file path for webkit engine', () => { const transport = new MockTransport(); - const { api, config } = initializeFaro( + const { api } = initializeFaro( mockConfig({ instrumentations: [new ConsoleInstrumentation()], transports: [transport], @@ -218,7 +218,7 @@ describe('errors', () => { }) ); - registerOnerror(api, config); + registerOnerror(api); let e = new Error('Oh crap!'); e.stack = 'Error: Oh crap!\n at Object.eval [as refinement] (https://example.com/(main)/[path]/to.js:1:2345)'; diff --git a/packages/web-sdk/src/instrumentations/errors/instrumentation.ts b/packages/web-sdk/src/instrumentations/errors/instrumentation.ts index 05e56f1e9..39d45a975 100644 --- a/packages/web-sdk/src/instrumentations/errors/instrumentation.ts +++ b/packages/web-sdk/src/instrumentations/errors/instrumentation.ts @@ -14,8 +14,8 @@ export class ErrorsInstrumentation extends BaseInstrumentation { initialize(): void { this.logDebug('Initializing'); - registerOnerror(this.api, this.config); + registerOnerror(this.api); - registerOnunhandledrejection(this.api, this.config); + registerOnunhandledrejection(this.api); } } diff --git a/packages/web-sdk/src/instrumentations/errors/registerOnerror.test.ts b/packages/web-sdk/src/instrumentations/errors/registerOnerror.test.ts index 66c756f81..19b2231ae 100644 --- a/packages/web-sdk/src/instrumentations/errors/registerOnerror.test.ts +++ b/packages/web-sdk/src/instrumentations/errors/registerOnerror.test.ts @@ -14,13 +14,13 @@ describe('registerOnerror', () => { }; const transport = new MockTransport(); - const { api, config } = initializeFaro( + const { api } = initializeFaro( mockConfig({ transports: [transport], }) ); - registerOnerror(api, config); + registerOnerror(api); window.onerror('boo', 'some file', 10, 10, new Error('boo')); expect(called).toBe(true); @@ -30,14 +30,14 @@ describe('registerOnerror', () => { it('In case of an error, the original error is not lost', () => { const originalError = new Error('original error'); const transport = new MockTransport(); - const { api, config } = initializeFaro( + const { api } = initializeFaro( mockConfig({ transports: [transport], preserveOriginalError: true, }) ); - registerOnerror(api, config); + registerOnerror(api); window.onerror?.('boo', 'some file', 10, 10, originalError); expect(transport.items).toHaveLength(1); @@ -50,7 +50,7 @@ describe('registerOnerror', () => { it('will filter out errors by string or regex', () => { const transport = new MockTransport(); - const { api, config } = initializeFaro( + const { api } = initializeFaro( mockConfig({ transports: [transport], ignoreErrors: ['chrome-extension'], @@ -58,7 +58,7 @@ describe('registerOnerror', () => { }) ); - registerOnerror(api, config); + registerOnerror(api); window.onerror?.('boo', 'some file', 10, 10, new Error('Tracked error')); diff --git a/packages/web-sdk/src/instrumentations/errors/registerOnerror.ts b/packages/web-sdk/src/instrumentations/errors/registerOnerror.ts index 1f22ee9b0..bcb3ebb21 100644 --- a/packages/web-sdk/src/instrumentations/errors/registerOnerror.ts +++ b/packages/web-sdk/src/instrumentations/errors/registerOnerror.ts @@ -1,13 +1,13 @@ -import type { API, Config, PushErrorOptions } from '@grafana/faro-core'; +import type { API, PushErrorOptions } from '@grafana/faro-core'; import { getDetailsFromErrorArgs } from './getErrorDetails'; -export function registerOnerror(api: API, config: Config): void { +export function registerOnerror(api: API): void { const oldOnerror = window.onerror; window.onerror = (...args) => { try { - const { value, type, stackFrames } = getDetailsFromErrorArgs(args, config.parseStacktrace); + const { value, type, stackFrames } = getDetailsFromErrorArgs(args, api.getStacktraceParser()); const originalError = args[4]; if (value) { diff --git a/packages/web-sdk/src/instrumentations/errors/registerOnunhandledrejection.ts b/packages/web-sdk/src/instrumentations/errors/registerOnunhandledrejection.ts index d2d303aeb..dbe18c138 100644 --- a/packages/web-sdk/src/instrumentations/errors/registerOnunhandledrejection.ts +++ b/packages/web-sdk/src/instrumentations/errors/registerOnunhandledrejection.ts @@ -1,11 +1,11 @@ import { isPrimitive } from '@grafana/faro-core'; -import type { API, Config, ExceptionStackFrame } from '@grafana/faro-core'; +import type { API, ExceptionStackFrame } from '@grafana/faro-core'; import { primitiveUnhandledType, primitiveUnhandledValue } from './const'; import { getErrorDetails } from './getErrorDetails'; import type { ExtendedPromiseRejectionEvent } from './types'; -export function registerOnunhandledrejection(api: API, config: Config): void { +export function registerOnunhandledrejection(api: API): void { window.addEventListener('unhandledrejection', (evt: ExtendedPromiseRejectionEvent) => { let error = evt; @@ -22,7 +22,7 @@ export function registerOnunhandledrejection(api: API, config: Config): void { value = `${primitiveUnhandledValue} ${String(error)}`; type = primitiveUnhandledType; } else { - [value, type, stackFrames] = getErrorDetails(error, config.parseStacktrace); + [value, type, stackFrames] = getErrorDetails(error, api.getStacktraceParser()); } if (value) { From b1d283578abda1ccdaa431dcfd50e80f7f9d7199 Mon Sep 17 00:00:00 2001 From: a Date: Wed, 16 Jul 2025 22:46:24 -0500 Subject: [PATCH 16/26] noot --- CHANGELOG.md | 1 + packages/core/src/api/exceptions/initialize.ts | 10 +++------- packages/web-sdk/src/config/makeCoreConfig.ts | 1 + 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 02b0a241d..4498159ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - chore(`@grafana/faro web-sdk`): Move the stackFrames from the errors instrumentation package to the utils package (#1316) - improvement (`@grafana/faro-web-sdk`): Allow users to configure the stackTraceParser in the BrowserConfig (#1316) +- chore(`@grafana/faro-web-sdk`): remove the setStackTraceParser function (#1316) ## 1.18.2 diff --git a/packages/core/src/api/exceptions/initialize.ts b/packages/core/src/api/exceptions/initialize.ts index 2ba4b0a09..5effb4387 100644 --- a/packages/core/src/api/exceptions/initialize.ts +++ b/packages/core/src/api/exceptions/initialize.ts @@ -23,9 +23,7 @@ import type { ApiMessageBusMessages } from '../types'; import { shouldIgnoreEvent } from '../utils'; import { defaultExceptionType } from './const'; -import type { ErrorWithIndexProperties, ExceptionEvent, ExceptionsAPI, StacktraceParser } from './types'; - -let stacktraceParser: StacktraceParser | undefined; +import type { ErrorWithIndexProperties, ExceptionEvent, ExceptionsAPI } from './types'; export function initializeExceptionsAPI({ internalLogger, @@ -49,9 +47,7 @@ export function initializeExceptionsAPI({ let lastPayload: Pick | null = null; - stacktraceParser = config.parseStacktrace; - - const getStacktraceParser: ExceptionsAPI['getStacktraceParser'] = () => stacktraceParser; + const getStacktraceParser: ExceptionsAPI['getStacktraceParser'] = () => config.parseStacktrace; const { ignoreErrors = [], preserveOriginalError } = config; @@ -85,7 +81,7 @@ export function initializeExceptionsAPI({ }, type: TransportItemType.EXCEPTION, }; - + const stacktraceParser = getStacktraceParser() stackFrames = stackFrames ?? (error.stack ? stacktraceParser?.(error).frames : undefined); if (stackFrames?.length) { diff --git a/packages/web-sdk/src/config/makeCoreConfig.ts b/packages/web-sdk/src/config/makeCoreConfig.ts index a359ed8da..2a5eb1e4f 100644 --- a/packages/web-sdk/src/config/makeCoreConfig.ts +++ b/packages/web-sdk/src/config/makeCoreConfig.ts @@ -65,6 +65,7 @@ export function makeCoreConfig(browserConfig: BrowserConfig): Config { ...restProperties }: BrowserConfig = browserConfig; + // use the default stacktrace parser (parseStacktrace) if no custom stacktrace parser is provided const stackTraceParser = browserConfig.parseStacktrace ?? parseStacktrace; return { From 3271d1aa1c3929e58a3920c1b72526cd712a11ee Mon Sep 17 00:00:00 2001 From: a Date: Wed, 16 Jul 2025 22:48:10 -0500 Subject: [PATCH 17/26] noot --- packages/core/src/api/exceptions/initialize.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/api/exceptions/initialize.ts b/packages/core/src/api/exceptions/initialize.ts index 5effb4387..3a9c534e9 100644 --- a/packages/core/src/api/exceptions/initialize.ts +++ b/packages/core/src/api/exceptions/initialize.ts @@ -81,7 +81,7 @@ export function initializeExceptionsAPI({ }, type: TransportItemType.EXCEPTION, }; - const stacktraceParser = getStacktraceParser() + const stacktraceParser = getStacktraceParser(); stackFrames = stackFrames ?? (error.stack ? stacktraceParser?.(error).frames : undefined); if (stackFrames?.length) { From 1746b833cb14691ee23bc4b572c77d3f806d4950 Mon Sep 17 00:00:00 2001 From: a Date: Wed, 16 Jul 2025 22:48:57 -0500 Subject: [PATCH 18/26] remove consturctor --- .../web-sdk/src/instrumentations/errors/instrumentation.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/web-sdk/src/instrumentations/errors/instrumentation.ts b/packages/web-sdk/src/instrumentations/errors/instrumentation.ts index 39d45a975..2fbd2dfdb 100644 --- a/packages/web-sdk/src/instrumentations/errors/instrumentation.ts +++ b/packages/web-sdk/src/instrumentations/errors/instrumentation.ts @@ -7,10 +7,6 @@ export class ErrorsInstrumentation extends BaseInstrumentation { readonly name = '@grafana/faro-web-sdk:instrumentation-errors'; readonly version = VERSION; - constructor() { - super(); - } - initialize(): void { this.logDebug('Initializing'); From 20057ea1e8692018de8fbebba4653a68d8cb7c9f Mon Sep 17 00:00:00 2001 From: a Date: Wed, 16 Jul 2025 22:51:32 -0500 Subject: [PATCH 19/26] export --- packages/web-sdk/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web-sdk/src/index.ts b/packages/web-sdk/src/index.ts index 482097294..7eba8c8ae 100644 --- a/packages/web-sdk/src/index.ts +++ b/packages/web-sdk/src/index.ts @@ -5,7 +5,7 @@ export { defaultEventDomain } from './consts'; export { initializeFaro } from './initialize'; -export { getDataFromSafariExtensions, getStackFramesFromError, parseStacktrace, buildStackFrame } from './utils'; +export { getDataFromSafariExtensions, getStackFramesFromError, parseStacktrace, newStackTraceParser, buildStackFrame } from './utils'; export { ConsoleInstrumentation, From 4581dabd086098efbe17257ed0bc1e216ad93baa Mon Sep 17 00:00:00 2001 From: a Date: Wed, 20 Aug 2025 20:30:09 -0500 Subject: [PATCH 20/26] stack trace parser --- packages/core/src/api/exceptions/index.ts | 1 - packages/core/src/api/exceptions/types.ts | 3 +-- packages/core/src/api/index.ts | 1 - packages/core/src/config/types.ts | 4 ++-- packages/core/src/index.ts | 1 - .../core/src/testUtils/mockStacktraceParser.ts | 4 ++-- packages/react/src/index.ts | 1 - packages/web-sdk/src/index.ts | 3 +-- .../src/instrumentations/errors/getErrorDetails.ts | 8 ++++---- packages/web-sdk/src/utils/index.ts | 1 - packages/web-sdk/src/utils/stackFrames/index.ts | 2 +- .../src/utils/stackFrames/parseStacktrace.ts | 14 +++----------- 12 files changed, 14 insertions(+), 29 deletions(-) diff --git a/packages/core/src/api/exceptions/index.ts b/packages/core/src/api/exceptions/index.ts index ed9d7d86d..bc249689e 100644 --- a/packages/core/src/api/exceptions/index.ts +++ b/packages/core/src/api/exceptions/index.ts @@ -9,7 +9,6 @@ export type { ExtendedError, PushErrorOptions, Stacktrace, - StacktraceParser, ErrorWithIndexProperties, ExceptionEventExtended, } from './types'; diff --git a/packages/core/src/api/exceptions/types.ts b/packages/core/src/api/exceptions/types.ts index 2570310f7..bf61c04db 100644 --- a/packages/core/src/api/exceptions/types.ts +++ b/packages/core/src/api/exceptions/types.ts @@ -3,7 +3,6 @@ import type { SpanContext } from '@opentelemetry/api'; import type { TraceContext } from '../traces'; import type { UserAction } from '../types'; -export type StacktraceParser = (err: ExtendedError) => Stacktrace; export interface ExceptionStackFrame { filename: string; @@ -72,6 +71,6 @@ export type ErrorWithIndexProperties = Error & { }; export interface ExceptionsAPI { - getStacktraceParser: () => StacktraceParser | undefined; + getStacktraceParser: () => ((err: ExtendedError) => Stacktrace) | undefined; pushError: (value: ErrorWithIndexProperties, options?: PushErrorOptions) => void; } diff --git a/packages/core/src/api/index.ts b/packages/core/src/api/index.ts index f78e6495c..fbd57f9fd 100644 --- a/packages/core/src/api/index.ts +++ b/packages/core/src/api/index.ts @@ -20,7 +20,6 @@ export type { ExtendedError, PushErrorOptions, Stacktrace, - StacktraceParser, ExceptionEventExtended, } from './exceptions'; diff --git a/packages/core/src/config/types.ts b/packages/core/src/config/types.ts index 150c2dc21..774ef4c0b 100644 --- a/packages/core/src/config/types.ts +++ b/packages/core/src/config/types.ts @@ -1,4 +1,4 @@ -import type { APIEvent, LogArgsSerializer, StacktraceParser } from '../api'; +import type { APIEvent, ExtendedError, LogArgsSerializer, Stacktrace } from '../api'; import type { Instrumentation } from '../instrumentations'; import type { InternalLoggerLevel } from '../internalLogger'; import type { Meta, MetaApp, MetaItem, MetaPage, MetaSession, MetaUser, MetaView } from '../metas'; @@ -59,7 +59,7 @@ export interface Config

{ /** * The stacktrace parser to use for parsing stack traces. */ - parseStacktrace: StacktraceParser; + parseStacktrace: (err: ExtendedError) => Stacktrace; /** * Pause sending data (default: false) diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index f32ae456b..795df846a 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -32,7 +32,6 @@ export type { PushLogOptions, PushMeasurementOptions, Stacktrace, - StacktraceParser, TraceContext, TraceEvent, TracesAPI, diff --git a/packages/core/src/testUtils/mockStacktraceParser.ts b/packages/core/src/testUtils/mockStacktraceParser.ts index e966a5efa..4b68d0de3 100644 --- a/packages/core/src/testUtils/mockStacktraceParser.ts +++ b/packages/core/src/testUtils/mockStacktraceParser.ts @@ -1,6 +1,6 @@ -import type { ExceptionStackFrame, StacktraceParser } from '../api'; +import type { ExceptionStackFrame, ExtendedError, Stacktrace } from '../api'; -export const mockStacktraceParser: StacktraceParser = (err) => { +export const mockStacktraceParser = (err: ExtendedError): Stacktrace => { const frames: ExceptionStackFrame[] = []; const stack = err.stack ?? err.stacktrace; diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index 143d1c7d5..b98c7569c 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -184,7 +184,6 @@ export type { PushLogOptions, PushMeasurementOptions, Stacktrace, - StacktraceParser, TraceContext, TraceEvent, TracesAPI, diff --git a/packages/web-sdk/src/index.ts b/packages/web-sdk/src/index.ts index 7eba8c8ae..95e41da60 100644 --- a/packages/web-sdk/src/index.ts +++ b/packages/web-sdk/src/index.ts @@ -5,7 +5,7 @@ export { defaultEventDomain } from './consts'; export { initializeFaro } from './initialize'; -export { getDataFromSafariExtensions, getStackFramesFromError, parseStacktrace, newStackTraceParser, buildStackFrame } from './utils'; +export { getDataFromSafariExtensions, getStackFramesFromError, parseStacktrace, buildStackFrame } from './utils'; export { ConsoleInstrumentation, @@ -154,7 +154,6 @@ export type { PushLogOptions, PushMeasurementOptions, Stacktrace, - StacktraceParser, TraceContext, TraceEvent, TracesAPI, diff --git a/packages/web-sdk/src/instrumentations/errors/getErrorDetails.ts b/packages/web-sdk/src/instrumentations/errors/getErrorDetails.ts index 62871a2a4..9355e3c97 100644 --- a/packages/web-sdk/src/instrumentations/errors/getErrorDetails.ts +++ b/packages/web-sdk/src/instrumentations/errors/getErrorDetails.ts @@ -1,7 +1,7 @@ import { isDomError, isDomException, isError, isErrorEvent, isEvent, isObject, isString } from '@grafana/faro-core'; -import type { ExceptionStackFrame, LogArgsSerializer, StacktraceParser } from '@grafana/faro-core'; +import type { ExceptionStackFrame, ExtendedError, LogArgsSerializer, Stacktrace } from '@grafana/faro-core'; -import { buildStackFrame, newStackTraceParser } from '../../utils/stackFrames'; +import { buildStackFrame, parseStacktrace } from '../../utils/stackFrames'; import { domErrorType, domExceptionType, objectEventValue, unknownSymbolString } from './const'; import { getValueAndTypeFromMessage } from './getValueAndTypeFromMessage'; @@ -9,7 +9,7 @@ import type { ErrorEvent } from './types'; export function getErrorDetails( evt: ErrorEvent, - stacktraceParser: StacktraceParser = newStackTraceParser() + stacktraceParser: (error: ExtendedError) => Stacktrace = parseStacktrace ): [string | undefined, string | undefined, ExceptionStackFrame[]] { let value: string | undefined; let type: string | undefined; @@ -46,7 +46,7 @@ export interface ErrorDetails { export function getDetailsFromErrorArgs( args: [any?, ...any[]], - stacktraceParser: StacktraceParser = newStackTraceParser() + stacktraceParser: (error: ExtendedError) => Stacktrace = parseStacktrace ): ErrorDetails { const [evt, source, lineno, colno, error] = args; diff --git a/packages/web-sdk/src/utils/index.ts b/packages/web-sdk/src/utils/index.ts index 9e1aa83e9..8247c2eb4 100644 --- a/packages/web-sdk/src/utils/index.ts +++ b/packages/web-sdk/src/utils/index.ts @@ -17,5 +17,4 @@ export { getDataFromSafariExtensions, getStackFramesFromError, parseStacktrace, - newStackTraceParser, } from './stackFrames'; diff --git a/packages/web-sdk/src/utils/stackFrames/index.ts b/packages/web-sdk/src/utils/stackFrames/index.ts index 5109f7073..57049b8f8 100644 --- a/packages/web-sdk/src/utils/stackFrames/index.ts +++ b/packages/web-sdk/src/utils/stackFrames/index.ts @@ -4,4 +4,4 @@ export { getDataFromSafariExtensions } from './getDataFromSafariExtensions'; export { getStackFramesFromError } from './getStackFramesFromError'; -export { parseStacktrace, newStackTraceParser } from './parseStacktrace'; +export { parseStacktrace } from './parseStacktrace'; diff --git a/packages/web-sdk/src/utils/stackFrames/parseStacktrace.ts b/packages/web-sdk/src/utils/stackFrames/parseStacktrace.ts index 3669819e8..5de62adf9 100644 --- a/packages/web-sdk/src/utils/stackFrames/parseStacktrace.ts +++ b/packages/web-sdk/src/utils/stackFrames/parseStacktrace.ts @@ -1,18 +1,10 @@ -import type { ExtendedError, Stacktrace, StacktraceParser } from '@grafana/faro-core'; +import type { ExtendedError, Stacktrace } from '@grafana/faro-core'; import { getStackFramesFromError } from './getStackFramesFromError'; import type { StackframeParserOptions } from './types'; -export function parseStacktrace(error: ExtendedError): Stacktrace { +export function parseStacktrace(error: ExtendedError, options?: StackframeParserOptions): Stacktrace { return { - frames: getStackFramesFromError(error), - }; -} - -export function newStackTraceParser(options?: StackframeParserOptions): StacktraceParser { - return (error: ExtendedError) => { - return { - frames: getStackFramesFromError(error, options), - }; + frames: getStackFramesFromError(error, options), }; } From 90b9aa8e83f665c4e6a2f4399e12990138779099 Mon Sep 17 00:00:00 2001 From: a Date: Wed, 20 Aug 2025 20:32:00 -0500 Subject: [PATCH 21/26] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4498159ad..2a568eb1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - chore(`@grafana/faro web-sdk`): Move the stackFrames from the errors instrumentation package to the utils package (#1316) - improvement (`@grafana/faro-web-sdk`): Allow users to configure the stackTraceParser in the BrowserConfig (#1316) - chore(`@grafana/faro-web-sdk`): remove the setStackTraceParser function (#1316) +- **BREAKING**: Remove `newStackTraceParser` function and `StacktraceParser` interface. Use `parseStacktrace` function directly instead (#1316) ## 1.18.2 From 007ee98e351c78c6f270a9d3ddef8cd28d6a74a0 Mon Sep 17 00:00:00 2001 From: a Date: Wed, 20 Aug 2025 21:45:01 -0500 Subject: [PATCH 22/26] with factory, i think this is the best --- CHANGELOG.md | 3 ++- packages/core/src/api/exceptions/initialize.ts | 7 +++---- packages/core/src/api/exceptions/types.ts | 2 +- packages/core/src/api/initialize.test.ts | 2 +- packages/web-sdk/src/config/makeCoreConfig.ts | 6 +++--- packages/web-sdk/src/index.ts | 2 +- .../web-sdk/src/instrumentations/errors/registerOnerror.ts | 2 +- .../errors/registerOnunhandledrejection.ts | 2 +- packages/web-sdk/src/utils/index.ts | 1 + packages/web-sdk/src/utils/stackFrames/index.ts | 2 +- packages/web-sdk/src/utils/stackFrames/parseStacktrace.ts | 6 ++++++ 11 files changed, 21 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3a0900de..fc28cb64f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,8 +39,9 @@ Breaking changes coming with Faro version 2 - chore(`@grafana/faro web-sdk`): Move the stackFrames from the errors instrumentation package to the utils package (#1316) - improvement (`@grafana/faro-web-sdk`): Allow users to configure the stackTraceParser in the BrowserConfig (#1316) +- improvement (`@grafana/faro-web-sdk`): Add `createStacktraceParser` function to create parsers with custom options (#1316) - chore(`@grafana/faro-web-sdk`): remove the setStackTraceParser function (#1316) -- **BREAKING**: Remove `newStackTraceParser` function and `StacktraceParser` interface. Use `parseStacktrace` function directly instead (#1316) +- **BREAKING**: Remove `newStackTraceParser` function and `StacktraceParser` interface. Use `parseStacktrace` function directly or `createStacktraceParser` for custom options. Also simplified ExceptionsAPI by replacing `getStacktraceParser()` with direct `parseStacktrace` property (#1316) ## 1.18.2 diff --git a/packages/core/src/api/exceptions/initialize.ts b/packages/core/src/api/exceptions/initialize.ts index 57d83b23d..096fbab80 100644 --- a/packages/core/src/api/exceptions/initialize.ts +++ b/packages/core/src/api/exceptions/initialize.ts @@ -43,7 +43,7 @@ export function initializeExceptionsAPI({ let lastPayload: Pick | null = null; - const getStacktraceParser: ExceptionsAPI['getStacktraceParser'] = () => config.parseStacktrace; + const parseStacktrace = config.parseStacktrace; const { ignoreErrors = [], preserveOriginalError } = config; @@ -77,8 +77,7 @@ export function initializeExceptionsAPI({ }, type: TransportItemType.EXCEPTION, }; - const stacktraceParser = getStacktraceParser(); - stackFrames = stackFrames ?? (error.stack ? stacktraceParser?.(error).frames : undefined); + stackFrames = stackFrames ?? (error.stack ? parseStacktrace?.(error).frames : undefined); if (stackFrames?.length) { item.payload.stacktrace = { @@ -115,7 +114,7 @@ export function initializeExceptionsAPI({ }; return { - getStacktraceParser, + parseStacktrace, pushError, }; } diff --git a/packages/core/src/api/exceptions/types.ts b/packages/core/src/api/exceptions/types.ts index bf61c04db..a8279d79a 100644 --- a/packages/core/src/api/exceptions/types.ts +++ b/packages/core/src/api/exceptions/types.ts @@ -71,6 +71,6 @@ export type ErrorWithIndexProperties = Error & { }; export interface ExceptionsAPI { - getStacktraceParser: () => ((err: ExtendedError) => Stacktrace) | undefined; + parseStacktrace: ((err: ExtendedError) => Stacktrace) | undefined; pushError: (value: ErrorWithIndexProperties, options?: PushErrorOptions) => void; } diff --git a/packages/core/src/api/initialize.test.ts b/packages/core/src/api/initialize.test.ts index a89831bbd..eb3fa2a52 100644 --- a/packages/core/src/api/initialize.test.ts +++ b/packages/core/src/api/initialize.test.ts @@ -17,7 +17,7 @@ describe('initialize', () => { expect(api).toHaveProperty('getOTEL'); expect(api).toHaveProperty('getPage'); expect(api).toHaveProperty('getSession'); - expect(api).toHaveProperty('getStacktraceParser'); + expect(api).toHaveProperty('parseStacktrace'); expect(api).toHaveProperty('getTraceContext'); expect(api).toHaveProperty('getView'); expect(api).toHaveProperty('initOTEL'); diff --git a/packages/web-sdk/src/config/makeCoreConfig.ts b/packages/web-sdk/src/config/makeCoreConfig.ts index 2a5eb1e4f..bc17554cd 100644 --- a/packages/web-sdk/src/config/makeCoreConfig.ts +++ b/packages/web-sdk/src/config/makeCoreConfig.ts @@ -18,7 +18,7 @@ import { browserMeta } from '../metas'; import { k6Meta } from '../metas/k6'; import { createPageMeta } from '../metas/page'; import { FetchTransport } from '../transports'; -import { parseStacktrace } from '../utils'; +import { createStacktraceParser } from '../utils'; import { getWebInstrumentations } from './getWebInstrumentations'; import type { BrowserConfig } from './types'; @@ -65,8 +65,8 @@ export function makeCoreConfig(browserConfig: BrowserConfig): Config { ...restProperties }: BrowserConfig = browserConfig; - // use the default stacktrace parser (parseStacktrace) if no custom stacktrace parser is provided - const stackTraceParser = browserConfig.parseStacktrace ?? parseStacktrace; + // use the default stacktrace parser if no custom stacktrace parser is provided + const stackTraceParser = browserConfig.parseStacktrace ?? createStacktraceParser(); return { ...restProperties, diff --git a/packages/web-sdk/src/index.ts b/packages/web-sdk/src/index.ts index fdf53f7a8..ba56a1718 100644 --- a/packages/web-sdk/src/index.ts +++ b/packages/web-sdk/src/index.ts @@ -5,7 +5,7 @@ export { defaultEventDomain } from './consts'; export { initializeFaro } from './initialize'; -export { getDataFromSafariExtensions, getStackFramesFromError, parseStacktrace, buildStackFrame } from './utils'; +export { getDataFromSafariExtensions, getStackFramesFromError, parseStacktrace, createStacktraceParser, buildStackFrame } from './utils'; export { ConsoleInstrumentation, diff --git a/packages/web-sdk/src/instrumentations/errors/registerOnerror.ts b/packages/web-sdk/src/instrumentations/errors/registerOnerror.ts index bcb3ebb21..c7e6b5274 100644 --- a/packages/web-sdk/src/instrumentations/errors/registerOnerror.ts +++ b/packages/web-sdk/src/instrumentations/errors/registerOnerror.ts @@ -7,7 +7,7 @@ export function registerOnerror(api: API): void { window.onerror = (...args) => { try { - const { value, type, stackFrames } = getDetailsFromErrorArgs(args, api.getStacktraceParser()); + const { value, type, stackFrames } = getDetailsFromErrorArgs(args, api.parseStacktrace); const originalError = args[4]; if (value) { diff --git a/packages/web-sdk/src/instrumentations/errors/registerOnunhandledrejection.ts b/packages/web-sdk/src/instrumentations/errors/registerOnunhandledrejection.ts index dbe18c138..87cc02ee0 100644 --- a/packages/web-sdk/src/instrumentations/errors/registerOnunhandledrejection.ts +++ b/packages/web-sdk/src/instrumentations/errors/registerOnunhandledrejection.ts @@ -22,7 +22,7 @@ export function registerOnunhandledrejection(api: API): void { value = `${primitiveUnhandledValue} ${String(error)}`; type = primitiveUnhandledType; } else { - [value, type, stackFrames] = getErrorDetails(error, api.getStacktraceParser()); + [value, type, stackFrames] = getErrorDetails(error, api.parseStacktrace); } if (value) { diff --git a/packages/web-sdk/src/utils/index.ts b/packages/web-sdk/src/utils/index.ts index 8247c2eb4..39c788229 100644 --- a/packages/web-sdk/src/utils/index.ts +++ b/packages/web-sdk/src/utils/index.ts @@ -17,4 +17,5 @@ export { getDataFromSafariExtensions, getStackFramesFromError, parseStacktrace, + createStacktraceParser, } from './stackFrames'; diff --git a/packages/web-sdk/src/utils/stackFrames/index.ts b/packages/web-sdk/src/utils/stackFrames/index.ts index 57049b8f8..9e84befeb 100644 --- a/packages/web-sdk/src/utils/stackFrames/index.ts +++ b/packages/web-sdk/src/utils/stackFrames/index.ts @@ -4,4 +4,4 @@ export { getDataFromSafariExtensions } from './getDataFromSafariExtensions'; export { getStackFramesFromError } from './getStackFramesFromError'; -export { parseStacktrace } from './parseStacktrace'; +export { parseStacktrace, createStacktraceParser } from './parseStacktrace'; diff --git a/packages/web-sdk/src/utils/stackFrames/parseStacktrace.ts b/packages/web-sdk/src/utils/stackFrames/parseStacktrace.ts index 5de62adf9..604fc6760 100644 --- a/packages/web-sdk/src/utils/stackFrames/parseStacktrace.ts +++ b/packages/web-sdk/src/utils/stackFrames/parseStacktrace.ts @@ -3,6 +3,12 @@ import type { ExtendedError, Stacktrace } from '@grafana/faro-core'; import { getStackFramesFromError } from './getStackFramesFromError'; import type { StackframeParserOptions } from './types'; +export function createStacktraceParser(options?: StackframeParserOptions): (error: ExtendedError) => Stacktrace { + return (error: ExtendedError) => ({ + frames: getStackFramesFromError(error, options), + }); +} + export function parseStacktrace(error: ExtendedError, options?: StackframeParserOptions): Stacktrace { return { frames: getStackFramesFromError(error, options), From 805435ad2ff2562414ff6521dca293500a42b7a8 Mon Sep 17 00:00:00 2001 From: a Date: Wed, 20 Aug 2025 21:50:51 -0500 Subject: [PATCH 23/26] move the code, allow optional --- .../api/exceptions/defaultStacktraceParser.ts | 25 +++++++++++++++++++ .../core/src/api/exceptions/initialize.ts | 4 ++- packages/core/src/config/types.ts | 2 +- packages/web-sdk/src/config/makeCoreConfig.ts | 5 ++-- 4 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 packages/core/src/api/exceptions/defaultStacktraceParser.ts diff --git a/packages/core/src/api/exceptions/defaultStacktraceParser.ts b/packages/core/src/api/exceptions/defaultStacktraceParser.ts new file mode 100644 index 000000000..70ad864d9 --- /dev/null +++ b/packages/core/src/api/exceptions/defaultStacktraceParser.ts @@ -0,0 +1,25 @@ +import type { ExtendedError, Stacktrace, ExceptionStackFrame } from './types'; + +/** + * Simple default stacktrace parser for the core package. + * Web SDK provides a more sophisticated parser. + */ +export function defaultStacktraceParser(error: ExtendedError): Stacktrace { + const frames: ExceptionStackFrame[] = []; + const stack = error.stack ?? error.stacktrace; + + if (stack) { + // Simple line-by-line parsing + const lines = stack.split('\n'); + for (const line of lines) { + if (line.trim()) { + frames.push({ + filename: 'unknown', + function: line.trim(), + }); + } + } + } + + return { frames }; +} \ No newline at end of file diff --git a/packages/core/src/api/exceptions/initialize.ts b/packages/core/src/api/exceptions/initialize.ts index 096fbab80..3e6d75d2b 100644 --- a/packages/core/src/api/exceptions/initialize.ts +++ b/packages/core/src/api/exceptions/initialize.ts @@ -21,6 +21,7 @@ import type { UserActionsAPI } from '../userActions'; import { shouldIgnoreEvent } from '../utils'; import { defaultExceptionType } from './const'; +import { defaultStacktraceParser } from './defaultStacktraceParser'; import type { ErrorWithIndexProperties, ExceptionEvent, ExceptionsAPI } from './types'; export function initializeExceptionsAPI({ @@ -43,7 +44,8 @@ export function initializeExceptionsAPI({ let lastPayload: Pick | null = null; - const parseStacktrace = config.parseStacktrace; + // Use provided parser or fall back to simple default parser + const parseStacktrace = config.parseStacktrace ?? defaultStacktraceParser; const { ignoreErrors = [], preserveOriginalError } = config; diff --git a/packages/core/src/config/types.ts b/packages/core/src/config/types.ts index 774ef4c0b..34b7a4d1a 100644 --- a/packages/core/src/config/types.ts +++ b/packages/core/src/config/types.ts @@ -59,7 +59,7 @@ export interface Config

{ /** * The stacktrace parser to use for parsing stack traces. */ - parseStacktrace: (err: ExtendedError) => Stacktrace; + parseStacktrace?: (err: ExtendedError) => Stacktrace; /** * Pause sending data (default: false) diff --git a/packages/web-sdk/src/config/makeCoreConfig.ts b/packages/web-sdk/src/config/makeCoreConfig.ts index bc17554cd..4ed12dc91 100644 --- a/packages/web-sdk/src/config/makeCoreConfig.ts +++ b/packages/web-sdk/src/config/makeCoreConfig.ts @@ -65,8 +65,6 @@ export function makeCoreConfig(browserConfig: BrowserConfig): Config { ...restProperties }: BrowserConfig = browserConfig; - // use the default stacktrace parser if no custom stacktrace parser is provided - const stackTraceParser = browserConfig.parseStacktrace ?? createStacktraceParser(); return { ...restProperties, @@ -82,7 +80,8 @@ export function makeCoreConfig(browserConfig: BrowserConfig): Config { isolate, logArgsSerializer, metas, - parseStacktrace: stackTraceParser, + // Use browser-provided parser or create default web-sdk parser + parseStacktrace: browserConfig.parseStacktrace ?? createStacktraceParser(), paused, preventGlobalExposure, transports, From 115286fa2a1d23633d9b7c9e25c0097862584d5c Mon Sep 17 00:00:00 2001 From: a Date: Thu, 21 Aug 2025 16:23:55 -0500 Subject: [PATCH 24/26] noot --- .../api/exceptions/defaultStacktraceParser.ts | 25 ------------------- .../core/src/api/exceptions/initialize.ts | 4 +-- 2 files changed, 1 insertion(+), 28 deletions(-) delete mode 100644 packages/core/src/api/exceptions/defaultStacktraceParser.ts diff --git a/packages/core/src/api/exceptions/defaultStacktraceParser.ts b/packages/core/src/api/exceptions/defaultStacktraceParser.ts deleted file mode 100644 index 70ad864d9..000000000 --- a/packages/core/src/api/exceptions/defaultStacktraceParser.ts +++ /dev/null @@ -1,25 +0,0 @@ -import type { ExtendedError, Stacktrace, ExceptionStackFrame } from './types'; - -/** - * Simple default stacktrace parser for the core package. - * Web SDK provides a more sophisticated parser. - */ -export function defaultStacktraceParser(error: ExtendedError): Stacktrace { - const frames: ExceptionStackFrame[] = []; - const stack = error.stack ?? error.stacktrace; - - if (stack) { - // Simple line-by-line parsing - const lines = stack.split('\n'); - for (const line of lines) { - if (line.trim()) { - frames.push({ - filename: 'unknown', - function: line.trim(), - }); - } - } - } - - return { frames }; -} \ No newline at end of file diff --git a/packages/core/src/api/exceptions/initialize.ts b/packages/core/src/api/exceptions/initialize.ts index 3e6d75d2b..096fbab80 100644 --- a/packages/core/src/api/exceptions/initialize.ts +++ b/packages/core/src/api/exceptions/initialize.ts @@ -21,7 +21,6 @@ import type { UserActionsAPI } from '../userActions'; import { shouldIgnoreEvent } from '../utils'; import { defaultExceptionType } from './const'; -import { defaultStacktraceParser } from './defaultStacktraceParser'; import type { ErrorWithIndexProperties, ExceptionEvent, ExceptionsAPI } from './types'; export function initializeExceptionsAPI({ @@ -44,8 +43,7 @@ export function initializeExceptionsAPI({ let lastPayload: Pick | null = null; - // Use provided parser or fall back to simple default parser - const parseStacktrace = config.parseStacktrace ?? defaultStacktraceParser; + const parseStacktrace = config.parseStacktrace; const { ignoreErrors = [], preserveOriginalError } = config; From b0c168a20e7a492f665365bc8509ee14d3de8c40 Mon Sep 17 00:00:00 2001 From: a Date: Thu, 21 Aug 2025 16:24:01 -0500 Subject: [PATCH 25/26] noot --- packages/web-sdk/src/config/makeCoreConfig.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/web-sdk/src/config/makeCoreConfig.ts b/packages/web-sdk/src/config/makeCoreConfig.ts index 4ed12dc91..698ee507f 100644 --- a/packages/web-sdk/src/config/makeCoreConfig.ts +++ b/packages/web-sdk/src/config/makeCoreConfig.ts @@ -18,7 +18,7 @@ import { browserMeta } from '../metas'; import { k6Meta } from '../metas/k6'; import { createPageMeta } from '../metas/page'; import { FetchTransport } from '../transports'; -import { createStacktraceParser } from '../utils'; +import { parseStacktrace } from '../utils'; import { getWebInstrumentations } from './getWebInstrumentations'; import type { BrowserConfig } from './types'; @@ -80,8 +80,8 @@ export function makeCoreConfig(browserConfig: BrowserConfig): Config { isolate, logArgsSerializer, metas, - // Use browser-provided parser or create default web-sdk parser - parseStacktrace: browserConfig.parseStacktrace ?? createStacktraceParser(), + // Use browser-provided parser or use parseStacktrace as default + parseStacktrace: browserConfig.parseStacktrace ?? parseStacktrace, paused, preventGlobalExposure, transports, From 2c9d7a200108a2abcf4a23f214cab777a6b911aa Mon Sep 17 00:00:00 2001 From: a Date: Thu, 21 Aug 2025 16:24:43 -0500 Subject: [PATCH 26/26] fmt --- packages/core/src/api/exceptions/types.ts | 1 - packages/web-sdk/src/config/makeCoreConfig.ts | 1 - packages/web-sdk/src/index.ts | 8 +++++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/core/src/api/exceptions/types.ts b/packages/core/src/api/exceptions/types.ts index a8279d79a..ce3375963 100644 --- a/packages/core/src/api/exceptions/types.ts +++ b/packages/core/src/api/exceptions/types.ts @@ -3,7 +3,6 @@ import type { SpanContext } from '@opentelemetry/api'; import type { TraceContext } from '../traces'; import type { UserAction } from '../types'; - export interface ExceptionStackFrame { filename: string; function: string; diff --git a/packages/web-sdk/src/config/makeCoreConfig.ts b/packages/web-sdk/src/config/makeCoreConfig.ts index 698ee507f..b88e919df 100644 --- a/packages/web-sdk/src/config/makeCoreConfig.ts +++ b/packages/web-sdk/src/config/makeCoreConfig.ts @@ -65,7 +65,6 @@ export function makeCoreConfig(browserConfig: BrowserConfig): Config { ...restProperties }: BrowserConfig = browserConfig; - return { ...restProperties, diff --git a/packages/web-sdk/src/index.ts b/packages/web-sdk/src/index.ts index ba56a1718..09b0e2e62 100644 --- a/packages/web-sdk/src/index.ts +++ b/packages/web-sdk/src/index.ts @@ -5,7 +5,13 @@ export { defaultEventDomain } from './consts'; export { initializeFaro } from './initialize'; -export { getDataFromSafariExtensions, getStackFramesFromError, parseStacktrace, createStacktraceParser, buildStackFrame } from './utils'; +export { + getDataFromSafariExtensions, + getStackFramesFromError, + parseStacktrace, + createStacktraceParser, + buildStackFrame, +} from './utils'; export { ConsoleInstrumentation,