UNPKG

@embrace-io/web-sdk

Version:
1 lines 7.91 kB
{"version":3,"file":"NavigationInstrumentation.cjs","names":["EmbraceInstrumentationBase","page","KEY_EMB_TYPE","KEY_EMB_PAGE_PATH","KEY_EMB_PAGE_ID"],"sources":["../../../../src/instrumentations/navigation/NavigationInstrumentation/NavigationInstrumentation.ts"],"sourcesContent":["import type { Span } from '@opentelemetry/api';\nimport type { PageManager, Route } from '../../../api-page/index.ts';\nimport { page } from '../../../api-page/index.ts';\nimport type { SessionPartStartedEvent } from '../../../api-sessions/index.ts';\nimport {\n EMB_TYPES,\n KEY_EMB_PAGE_ID,\n KEY_EMB_PAGE_PATH,\n KEY_EMB_TYPE,\n} from '../../../constants/index.ts';\nimport { EmbraceInstrumentationBase } from '../../EmbraceInstrumentationBase/index.ts';\nimport type { NavigationInstrumentationArgs } from './types.ts';\n\n// Regular expression to match path options in the format \"(option)\"\n// Used to clean up paths that are like \"/order/:orderState(pending|shipped|delivered)/type:(sale|normal)\" to \"/order/:orderState/:type\"\n// Could be simplified but done this way to prevent: https://javascript.info/regexp-catastrophic-backtracking\nconst PATH_OPTIONS_RE = /\\([^()]+\\)/g;\n\nexport class NavigationInstrumentation extends EmbraceInstrumentationBase {\n private readonly _shouldCleanupPathOptionsFromRouteName: boolean = true;\n private readonly _pageManager: PageManager;\n private _currentRouteSpan: Span | null = null;\n private _currentRouteSpanUrl: string | null = null;\n private _currentRouteSpanPath: string | null = null;\n\n public constructor({\n diag,\n shouldCleanupPathOptionsFromRouteName = true,\n pageManager,\n }: NavigationInstrumentationArgs) {\n super({\n instrumentationName: 'NavigationInstrumentation',\n instrumentationVersion: '1.0.0',\n diag,\n config: {},\n });\n\n this._shouldCleanupPathOptionsFromRouteName =\n shouldCleanupPathOptionsFromRouteName;\n this._pageManager = pageManager ?? page.getPageManager();\n this._pageManager.addRouteChangedListener(this._onRouteChanged);\n\n if (this._config.enabled) {\n this.enable();\n }\n\n // Starts the inital route span if the page manager already has a current route\n const currentRoute = this._pageManager.getCurrentRoute();\n if (currentRoute) {\n this._onRouteChanged(currentRoute);\n }\n }\n\n private readonly _onRouteChanged = (route: Route): void => {\n if (!this._config.enabled) {\n return;\n }\n\n if (this._currentRouteSpan && this._currentRouteSpanUrl === route.url) {\n // Same url as the currently open span: either the templated path just\n // resolved (rename in place), or a redundant re-render — no-op if the\n // path hasn't actually changed.\n if (this._currentRouteSpanPath !== route.path) {\n this._renameCurrentRouteSpan(route.path);\n }\n return;\n }\n\n this._endRouteSpan();\n this._startRouteSpan(route);\n };\n\n private readonly _startRouteSpan = (route: Route): Span => {\n this._diag.debug(`Starting route span for url: ${route.url}`);\n\n const pathName = this._cleanPath(route.path);\n this._currentRouteSpan = this.tracer.startSpan(pathName, {\n startTime: this.perf.getNowMillis(),\n attributes: {\n [KEY_EMB_TYPE]: EMB_TYPES.Surface,\n [KEY_EMB_PAGE_PATH]: pathName,\n [KEY_EMB_PAGE_ID]: this._pageManager.getCurrentPageId() || undefined,\n },\n });\n this._currentRouteSpanUrl = route.url;\n this._currentRouteSpanPath = route.path;\n\n return this._currentRouteSpan;\n };\n\n private readonly _endRouteSpan = (): void => {\n if (this._currentRouteSpan) {\n this._diag.debug(\n `Ending route span for url: ${this._currentRouteSpanUrl ?? 'unknown'}`,\n );\n\n this._currentRouteSpan.end(this.perf.getNowMillis());\n this._currentRouteSpan = null;\n this._currentRouteSpanUrl = null;\n this._currentRouteSpanPath = null;\n }\n };\n\n private readonly _renameCurrentRouteSpan = (path: string): void => {\n const pathName = this._cleanPath(path);\n this._diag.debug(`Resolved route span path to: ${pathName}`);\n\n this._currentRouteSpan?.updateName(pathName);\n this._currentRouteSpan?.setAttribute(KEY_EMB_PAGE_PATH, pathName);\n this._currentRouteSpanPath = path;\n };\n\n private readonly _cleanPath = (path: string): string =>\n this._shouldCleanupPathOptionsFromRouteName\n ? path.replace(PATH_OPTIONS_RE, '')\n : path;\n\n // A route span must not outlive the session part it started in — e.g. the\n // tab backgrounds, or the session ends, with no further navigation to\n // trigger _onRouteChanged.\n private readonly _onSessionPartEnded = (): void => {\n if (this._currentRouteSpan) {\n this._diag.debug('Session ended, ending route span.');\n this._endRouteSpan();\n }\n };\n\n // Only needed when a session part starts with no route change (e.g.\n // resuming after background/inactivity). Skipped for soft-nav rollovers,\n // since the real new route is reported right after (see\n // EmbracePageManager._onSoftNavigation).\n private readonly _onSessionPartStarted = ({\n reason,\n }: SessionPartStartedEvent): void => {\n if (reason === 'web_soft_navigation') {\n return;\n }\n\n const currentRoute = this._pageManager.getCurrentRoute();\n if (currentRoute) {\n this._onRouteChanged(currentRoute);\n }\n };\n\n public override onEnable = () => {\n this.setConfig({\n enabled: true,\n });\n this.setSessionPartListeners({\n start: this._onSessionPartStarted,\n end: this._onSessionPartEnded,\n });\n this._diag.debug(\n 'NavigationInstrumentation enabled, listening for navigation events.',\n );\n };\n\n public override onDisable = () => {\n this._endRouteSpan();\n this.setConfig({\n enabled: false,\n });\n this._diag.debug(\n 'NavigationInstrumentation disabled, stopped listening for navigation events.',\n );\n };\n}\n"],"mappings":";;;;;AAgBA,MAAM,kBAAkB;AAExB,IAAa,4BAAb,cAA+CA,+EAAAA,2BAA2B;CACxE,yCAAmE;CACnE;CACA,oBAAyC;CACzC,uBAA8C;CAC9C,wBAA+C;CAE/C,YAAmB,EACjB,MACA,wCAAwC,MACxC,eACgC;EAChC,MAAM;GACJ,qBAAqB;GACrB,wBAAwB;GACxB;GACA,QAAQ,CAAC;EACX,CAAC;EAED,KAAK,yCACH;EACF,KAAK,eAAe,eAAeC,yBAAAA,KAAK,eAAe;EACvD,KAAK,aAAa,wBAAwB,KAAK,eAAe;EAE9D,IAAI,KAAK,QAAQ,SACf,KAAK,OAAO;EAId,MAAM,eAAe,KAAK,aAAa,gBAAgB;EACvD,IAAI,cACF,KAAK,gBAAgB,YAAY;CAErC;CAEA,mBAAoC,UAAuB;EACzD,IAAI,CAAC,KAAK,QAAQ,SAChB;EAGF,IAAI,KAAK,qBAAqB,KAAK,yBAAyB,MAAM,KAAK;GAIrE,IAAI,KAAK,0BAA0B,MAAM,MACvC,KAAK,wBAAwB,MAAM,IAAI;GAEzC;EACF;EAEA,KAAK,cAAc;EACnB,KAAK,gBAAgB,KAAK;CAC5B;CAEA,mBAAoC,UAAuB;EACzD,KAAK,MAAM,MAAM,gCAAgC,MAAM,KAAK;EAE5D,MAAM,WAAW,KAAK,WAAW,MAAM,IAAI;EAC3C,KAAK,oBAAoB,KAAK,OAAO,UAAU,UAAU;GACvD,WAAW,KAAK,KAAK,aAAa;GAClC,YAAY;KACTC,6BAAAA,eAAAA;KACAC,6BAAAA,oBAAoB;KACpBC,6BAAAA,kBAAkB,KAAK,aAAa,iBAAiB,KAAK,KAAA;GAC7D;EACF,CAAC;EACD,KAAK,uBAAuB,MAAM;EAClC,KAAK,wBAAwB,MAAM;EAEnC,OAAO,KAAK;CACd;CAEA,sBAA6C;EAC3C,IAAI,KAAK,mBAAmB;GAC1B,KAAK,MAAM,MACT,8BAA8B,KAAK,wBAAwB,WAC7D;GAEA,KAAK,kBAAkB,IAAI,KAAK,KAAK,aAAa,CAAC;GACnD,KAAK,oBAAoB;GACzB,KAAK,uBAAuB;GAC5B,KAAK,wBAAwB;EAC/B;CACF;CAEA,2BAA4C,SAAuB;EACjE,MAAM,WAAW,KAAK,WAAW,IAAI;EACrC,KAAK,MAAM,MAAM,gCAAgC,UAAU;EAE3D,KAAK,mBAAmB,WAAW,QAAQ;EAC3C,KAAK,mBAAmB,aAAaD,6BAAAA,mBAAmB,QAAQ;EAChE,KAAK,wBAAwB;CAC/B;CAEA,cAA+B,SAC7B,KAAK,yCACD,KAAK,QAAQ,iBAAiB,EAAE,IAChC;CAKN,4BAAmD;EACjD,IAAI,KAAK,mBAAmB;GAC1B,KAAK,MAAM,MAAM,mCAAmC;GACpD,KAAK,cAAc;EACrB;CACF;CAMA,yBAA0C,EACxC,aACmC;EACnC,IAAI,WAAW,uBACb;EAGF,MAAM,eAAe,KAAK,aAAa,gBAAgB;EACvD,IAAI,cACF,KAAK,gBAAgB,YAAY;CAErC;CAEA,iBAAiC;EAC/B,KAAK,UAAU,EACb,SAAS,KACX,CAAC;EACD,KAAK,wBAAwB;GAC3B,OAAO,KAAK;GACZ,KAAK,KAAK;EACZ,CAAC;EACD,KAAK,MAAM,MACT,qEACF;CACF;CAEA,kBAAkC;EAChC,KAAK,cAAc;EACnB,KAAK,UAAU,EACb,SAAS,MACX,CAAC;EACD,KAAK,MAAM,MACT,8EACF;CACF;AACF"}