@grafana/faro-web-sdk 2.2.3 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/bundle/faro-web-sdk.iife.js +1 -1
  2. package/dist/bundle/types/instrumentations/console/instrumentation.d.ts +1 -1
  3. package/dist/bundle/types/instrumentations/csp/instrumentation.d.ts +1 -1
  4. package/dist/bundle/types/instrumentations/errors/instrumentation.d.ts +1 -1
  5. package/dist/bundle/types/instrumentations/navigation/instrumentation.d.ts +1 -1
  6. package/dist/bundle/types/instrumentations/performance/instrumentation.d.ts +1 -1
  7. package/dist/bundle/types/instrumentations/session/instrumentation.d.ts +1 -1
  8. package/dist/bundle/types/instrumentations/userActions/instrumentation.d.ts +1 -1
  9. package/dist/bundle/types/instrumentations/view/instrumentation.d.ts +1 -1
  10. package/dist/bundle/types/instrumentations/webVitals/instrumentation.d.ts +1 -1
  11. package/dist/bundle/types/transports/console/transport.d.ts +1 -1
  12. package/dist/bundle/types/transports/fetch/transport.d.ts +1 -1
  13. package/dist/bundle/types/transports/fetch/types.d.ts +3 -2
  14. package/dist/cjs/instrumentations/_internal/activityWindowTracker.js +1 -1
  15. package/dist/cjs/instrumentations/_internal/activityWindowTracker.js.map +1 -1
  16. package/dist/cjs/instrumentations/session/sessionManager/sampling.js +2 -5
  17. package/dist/cjs/instrumentations/session/sessionManager/sampling.js.map +1 -1
  18. package/dist/cjs/instrumentations/userActions/processUserActionEventHandler.js +0 -1
  19. package/dist/cjs/instrumentations/userActions/processUserActionEventHandler.js.map +1 -1
  20. package/dist/cjs/transports/fetch/transport.js +58 -35
  21. package/dist/cjs/transports/fetch/transport.js.map +1 -1
  22. package/dist/cjs/transports/fetch/types.js.map +1 -1
  23. package/dist/esm/instrumentations/_internal/activityWindowTracker.js +1 -1
  24. package/dist/esm/instrumentations/_internal/activityWindowTracker.js.map +1 -1
  25. package/dist/esm/instrumentations/session/sessionManager/sampling.js +3 -6
  26. package/dist/esm/instrumentations/session/sessionManager/sampling.js.map +1 -1
  27. package/dist/esm/instrumentations/userActions/processUserActionEventHandler.js +0 -1
  28. package/dist/esm/instrumentations/userActions/processUserActionEventHandler.js.map +1 -1
  29. package/dist/esm/transports/fetch/transport.js +3 -3
  30. package/dist/esm/transports/fetch/transport.js.map +1 -1
  31. package/dist/esm/transports/fetch/types.js.map +1 -1
  32. package/dist/types/instrumentations/console/instrumentation.d.ts +1 -1
  33. package/dist/types/instrumentations/csp/instrumentation.d.ts +1 -1
  34. package/dist/types/instrumentations/errors/instrumentation.d.ts +1 -1
  35. package/dist/types/instrumentations/navigation/instrumentation.d.ts +1 -1
  36. package/dist/types/instrumentations/performance/instrumentation.d.ts +1 -1
  37. package/dist/types/instrumentations/session/instrumentation.d.ts +1 -1
  38. package/dist/types/instrumentations/userActions/instrumentation.d.ts +1 -1
  39. package/dist/types/instrumentations/view/instrumentation.d.ts +1 -1
  40. package/dist/types/instrumentations/webVitals/instrumentation.d.ts +1 -1
  41. package/dist/types/transports/console/transport.d.ts +1 -1
  42. package/dist/types/transports/fetch/transport.d.ts +1 -1
  43. package/dist/types/transports/fetch/types.d.ts +3 -2
  44. package/package.json +4 -4
@@ -3,9 +3,10 @@ export interface FetchTransportRequestOptions extends Omit<RequestInit, 'body' |
3
3
  * Headers to include in every request.
4
4
  * Each value can be:
5
5
  * - a string (static value)
6
- * - a function returning a string (dynamic value)
6
+ * - a function returning a string (dynamic value, sync)
7
+ * - a function returning a Promise of string (dynamic value, async)
7
8
  */
8
- headers?: Record<string, string | (() => string)>;
9
+ headers?: Record<string, string | (() => string | Promise<string>)>;
9
10
  }
10
11
  export interface FetchTransportOptions {
11
12
  url: string;
@@ -86,7 +86,7 @@ var ActivityWindowTracker = /** @class */ (function (_super) {
86
86
  this._tracking = false;
87
87
  this._clearTimer(this._inactivityTid);
88
88
  this._clearTimer(this._drainTid);
89
- var duration = 0;
89
+ var duration;
90
90
  if (this.hasActiveOperations()) {
91
91
  duration = Date.now() - this._startTime;
92
92
  }
@@ -1 +1 @@
1
- {"version":3,"file":"activityWindowTracker.js","sourceRoot":"","sources":["../../../../src/instrumentations/_internal/activityWindowTracker.ts"],"names":[],"mappings":"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","sourcesContent":["import { Observable } from '@grafana/faro-core';\n\nimport { MESSAGE_TYPE_HTTP_REQUEST_END, MESSAGE_TYPE_HTTP_REQUEST_START } from './monitors/const';\nimport type { HttpRequestEndMessage, HttpRequestStartMessage } from './monitors/types';\n\ntype OperationKey = string;\n\nexport function isRequestStartMessage(msg: any): msg is HttpRequestStartMessage {\n return msg.type === MESSAGE_TYPE_HTTP_REQUEST_START;\n}\n\nexport function isRequestEndMessage(msg: any): msg is HttpRequestEndMessage {\n return msg.type === MESSAGE_TYPE_HTTP_REQUEST_END;\n}\n\nexport interface ActivityWindowTrackerOptions<TMsg = any> {\n inactivityMs?: number;\n drainTimeoutMs?: number;\n isOperationStart?: (msg: TMsg) => OperationKey | undefined;\n isOperationEnd?: (msg: TMsg) => OperationKey | undefined;\n}\n\n/**\n * Tracks events in a time‑boxed activity window. When the window goes quiet for `inactivityMs`,\n * it enters a draining phase: new short events are ignored; only active operations are awaited\n * until they end or `drainTimeoutMs` elapses.\n */\nexport class ActivityWindowTracker extends Observable {\n eventsObservable: Observable;\n\n private _tracking = false;\n private _inactivityTid?: number;\n private _drainTid?: number;\n private _currentEvents?: any[];\n private _activeOperations?: Map<OperationKey, true>;\n private _startTime?: number;\n private _lastEventTime?: number;\n private _options: Required<ActivityWindowTrackerOptions>;\n\n constructor(eventsObservable: Observable, options?: ActivityWindowTrackerOptions) {\n super();\n this.eventsObservable = eventsObservable;\n this._options = {\n inactivityMs: options?.inactivityMs ?? 100,\n drainTimeoutMs: options?.drainTimeoutMs ?? 10 * 1000,\n isOperationStart: options?.isOperationStart ?? (() => undefined),\n isOperationEnd: options?.isOperationEnd ?? (() => undefined),\n } as Required<ActivityWindowTrackerOptions>;\n this._initialize();\n }\n\n private _initialize() {\n this.eventsObservable\n .filter(() => {\n return this._tracking;\n })\n .subscribe((event) => {\n this._lastEventTime = Date.now();\n this._currentEvents?.push(event);\n\n const startKey = this._options.isOperationStart(event as any);\n if (startKey) {\n this._activeOperations?.set(startKey, true);\n }\n\n const endKey = this._options.isOperationEnd(event as any);\n if (endKey) {\n this._activeOperations?.delete(endKey);\n }\n\n this._scheduleInactivityCheck();\n });\n }\n\n startTracking() {\n if (this._tracking) {\n return;\n }\n\n this._tracking = true;\n this._startTime = Date.now();\n this._lastEventTime = Date.now();\n\n this.notify({\n message: 'tracking-started',\n });\n\n this._currentEvents = [];\n this._activeOperations = new Map<OperationKey, true>();\n this._scheduleInactivityCheck();\n }\n\n stopTracking() {\n this._tracking = false;\n this._clearTimer(this._inactivityTid);\n this._clearTimer(this._drainTid);\n\n let duration = 0;\n if (this.hasActiveOperations()) {\n duration = Date.now() - this._startTime!;\n } else {\n duration = this._lastEventTime ? this._lastEventTime - this._startTime! : 0;\n }\n\n this.notify({\n message: 'tracking-ended',\n events: this._currentEvents,\n duration: duration,\n });\n }\n\n private _scheduleInactivityCheck() {\n this._inactivityTid = startTimeout(\n this._inactivityTid,\n () => {\n if (this.hasActiveOperations()) {\n this._startDrainTimeout();\n } else {\n this.stopTracking();\n }\n },\n this._options.inactivityMs\n );\n }\n\n private _startDrainTimeout() {\n this._drainTid = startTimeout(\n this._drainTid,\n () => {\n this.stopTracking();\n },\n this._options.drainTimeoutMs\n );\n }\n\n private hasActiveOperations(): boolean {\n return !!this._activeOperations && this._activeOperations.size > 0;\n }\n\n private _clearTimer(id?: number) {\n if (id) {\n clearTimeout(id);\n }\n }\n}\n\nfunction startTimeout(timeoutId: number | undefined, cb: () => void, delay: number) {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n\n //@ts-expect-error for some reason vscode is using the node types\n timeoutId = setTimeout(() => {\n cb();\n }, delay);\n\n return timeoutId;\n}\n"]}
1
+ {"version":3,"file":"activityWindowTracker.js","sourceRoot":"","sources":["../../../../src/instrumentations/_internal/activityWindowTracker.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAOA,sDAEC;AAED,kDAEC;AAbD,gDAAgD;AAEhD,0CAAkG;AAKlG,SAAgB,qBAAqB,CAAC,GAAQ;IAC5C,OAAO,GAAG,CAAC,IAAI,KAAK,uCAA+B,CAAC;AACtD,CAAC;AAED,SAAgB,mBAAmB,CAAC,GAAQ;IAC1C,OAAO,GAAG,CAAC,IAAI,KAAK,qCAA6B,CAAC;AACpD,CAAC;AASD;;;;GAIG;AACH;IAA2C,yCAAU;IAYnD,+BAAY,gBAA4B,EAAE,OAAsC;;QAC9E,YAAA,MAAK,WAAE,SAAC;QAVF,eAAS,GAAG,KAAK,CAAC;QAWxB,KAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;QACzC,KAAI,CAAC,QAAQ,GAAG;YACd,YAAY,EAAE,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,YAAY,mCAAI,GAAG;YAC1C,cAAc,EAAE,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,cAAc,mCAAI,EAAE,GAAG,IAAI;YACpD,gBAAgB,EAAE,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,gBAAgB,mCAAI,CAAC,cAAM,OAAA,SAAS,EAAT,CAAS,CAAC;YAChE,cAAc,EAAE,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,cAAc,mCAAI,CAAC,cAAM,OAAA,SAAS,EAAT,CAAS,CAAC;SACnB,CAAC;QAC5C,KAAI,CAAC,WAAW,EAAE,CAAC;;IACrB,CAAC;IAEO,2CAAW,GAAnB;QAAA,iBAqBC;QApBC,IAAI,CAAC,gBAAgB;aAClB,MAAM,CAAC;YACN,OAAO,KAAI,CAAC,SAAS,CAAC;QACxB,CAAC,CAAC;aACD,SAAS,CAAC,UAAC,KAAK;;YACf,KAAI,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACjC,MAAA,KAAI,CAAC,cAAc,0CAAE,IAAI,CAAC,KAAK,CAAC,CAAC;YAEjC,IAAM,QAAQ,GAAG,KAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,KAAY,CAAC,CAAC;YAC9D,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAA,KAAI,CAAC,iBAAiB,0CAAE,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YAC9C,CAAC;YAED,IAAM,MAAM,GAAG,KAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,KAAY,CAAC,CAAC;YAC1D,IAAI,MAAM,EAAE,CAAC;gBACX,MAAA,KAAI,CAAC,iBAAiB,0CAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YACzC,CAAC;YAED,KAAI,CAAC,wBAAwB,EAAE,CAAC;QAClC,CAAC,CAAC,CAAC;IACP,CAAC;IAED,6CAAa,GAAb;QACE,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,OAAO;QACT,CAAC;QAED,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEjC,IAAI,CAAC,MAAM,CAAC;YACV,OAAO,EAAE,kBAAkB;SAC5B,CAAC,CAAC;QAEH,IAAI,CAAC,cAAc,GAAG,EAAE,CAAC;QACzB,IAAI,CAAC,iBAAiB,GAAG,IAAI,GAAG,EAAsB,CAAC;QACvD,IAAI,CAAC,wBAAwB,EAAE,CAAC;IAClC,CAAC;IAED,4CAAY,GAAZ;QACE,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACtC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAEjC,IAAI,QAAQ,CAAC;QACb,IAAI,IAAI,CAAC,mBAAmB,EAAE,EAAE,CAAC;YAC/B,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,UAAW,CAAC;QAC3C,CAAC;aAAM,CAAC;YACN,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,UAAW,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9E,CAAC;QAED,IAAI,CAAC,MAAM,CAAC;YACV,OAAO,EAAE,gBAAgB;YACzB,MAAM,EAAE,IAAI,CAAC,cAAc;YAC3B,QAAQ,EAAE,QAAQ;SACnB,CAAC,CAAC;IACL,CAAC;IAEO,wDAAwB,GAAhC;QAAA,iBAYC;QAXC,IAAI,CAAC,cAAc,GAAG,YAAY,CAChC,IAAI,CAAC,cAAc,EACnB;YACE,IAAI,KAAI,CAAC,mBAAmB,EAAE,EAAE,CAAC;gBAC/B,KAAI,CAAC,kBAAkB,EAAE,CAAC;YAC5B,CAAC;iBAAM,CAAC;gBACN,KAAI,CAAC,YAAY,EAAE,CAAC;YACtB,CAAC;QACH,CAAC,EACD,IAAI,CAAC,QAAQ,CAAC,YAAY,CAC3B,CAAC;IACJ,CAAC;IAEO,kDAAkB,GAA1B;QAAA,iBAQC;QAPC,IAAI,CAAC,SAAS,GAAG,YAAY,CAC3B,IAAI,CAAC,SAAS,EACd;YACE,KAAI,CAAC,YAAY,EAAE,CAAC;QACtB,CAAC,EACD,IAAI,CAAC,QAAQ,CAAC,cAAc,CAC7B,CAAC;IACJ,CAAC;IAEO,mDAAmB,GAA3B;QACE,OAAO,CAAC,CAAC,IAAI,CAAC,iBAAiB,IAAI,IAAI,CAAC,iBAAiB,CAAC,IAAI,GAAG,CAAC,CAAC;IACrE,CAAC;IAEO,2CAAW,GAAnB,UAAoB,EAAW;QAC7B,IAAI,EAAE,EAAE,CAAC;YACP,YAAY,CAAC,EAAE,CAAC,CAAC;QACnB,CAAC;IACH,CAAC;IACH,4BAAC;AAAD,CAAC,AArHD,CAA2C,sBAAU,GAqHpD;AArHY,sDAAqB;AAuHlC,SAAS,YAAY,CAAC,SAA6B,EAAE,EAAc,EAAE,KAAa;IAChF,IAAI,SAAS,EAAE,CAAC;QACd,YAAY,CAAC,SAAS,CAAC,CAAC;IAC1B,CAAC;IAED,iEAAiE;IACjE,SAAS,GAAG,UAAU,CAAC;QACrB,EAAE,EAAE,CAAC;IACP,CAAC,EAAE,KAAK,CAAC,CAAC;IAEV,OAAO,SAAS,CAAC;AACnB,CAAC","sourcesContent":["import { Observable } from '@grafana/faro-core';\n\nimport { MESSAGE_TYPE_HTTP_REQUEST_END, MESSAGE_TYPE_HTTP_REQUEST_START } from './monitors/const';\nimport type { HttpRequestEndMessage, HttpRequestStartMessage } from './monitors/types';\n\ntype OperationKey = string;\n\nexport function isRequestStartMessage(msg: any): msg is HttpRequestStartMessage {\n return msg.type === MESSAGE_TYPE_HTTP_REQUEST_START;\n}\n\nexport function isRequestEndMessage(msg: any): msg is HttpRequestEndMessage {\n return msg.type === MESSAGE_TYPE_HTTP_REQUEST_END;\n}\n\nexport interface ActivityWindowTrackerOptions<TMsg = any> {\n inactivityMs?: number;\n drainTimeoutMs?: number;\n isOperationStart?: (msg: TMsg) => OperationKey | undefined;\n isOperationEnd?: (msg: TMsg) => OperationKey | undefined;\n}\n\n/**\n * Tracks events in a time‑boxed activity window. When the window goes quiet for `inactivityMs`,\n * it enters a draining phase: new short events are ignored; only active operations are awaited\n * until they end or `drainTimeoutMs` elapses.\n */\nexport class ActivityWindowTracker extends Observable {\n eventsObservable: Observable;\n\n private _tracking = false;\n private _inactivityTid?: number;\n private _drainTid?: number;\n private _currentEvents?: any[];\n private _activeOperations?: Map<OperationKey, true>;\n private _startTime?: number;\n private _lastEventTime?: number;\n private _options: Required<ActivityWindowTrackerOptions>;\n\n constructor(eventsObservable: Observable, options?: ActivityWindowTrackerOptions) {\n super();\n this.eventsObservable = eventsObservable;\n this._options = {\n inactivityMs: options?.inactivityMs ?? 100,\n drainTimeoutMs: options?.drainTimeoutMs ?? 10 * 1000,\n isOperationStart: options?.isOperationStart ?? (() => undefined),\n isOperationEnd: options?.isOperationEnd ?? (() => undefined),\n } as Required<ActivityWindowTrackerOptions>;\n this._initialize();\n }\n\n private _initialize() {\n this.eventsObservable\n .filter(() => {\n return this._tracking;\n })\n .subscribe((event) => {\n this._lastEventTime = Date.now();\n this._currentEvents?.push(event);\n\n const startKey = this._options.isOperationStart(event as any);\n if (startKey) {\n this._activeOperations?.set(startKey, true);\n }\n\n const endKey = this._options.isOperationEnd(event as any);\n if (endKey) {\n this._activeOperations?.delete(endKey);\n }\n\n this._scheduleInactivityCheck();\n });\n }\n\n startTracking() {\n if (this._tracking) {\n return;\n }\n\n this._tracking = true;\n this._startTime = Date.now();\n this._lastEventTime = Date.now();\n\n this.notify({\n message: 'tracking-started',\n });\n\n this._currentEvents = [];\n this._activeOperations = new Map<OperationKey, true>();\n this._scheduleInactivityCheck();\n }\n\n stopTracking() {\n this._tracking = false;\n this._clearTimer(this._inactivityTid);\n this._clearTimer(this._drainTid);\n\n let duration;\n if (this.hasActiveOperations()) {\n duration = Date.now() - this._startTime!;\n } else {\n duration = this._lastEventTime ? this._lastEventTime - this._startTime! : 0;\n }\n\n this.notify({\n message: 'tracking-ended',\n events: this._currentEvents,\n duration: duration,\n });\n }\n\n private _scheduleInactivityCheck() {\n this._inactivityTid = startTimeout(\n this._inactivityTid,\n () => {\n if (this.hasActiveOperations()) {\n this._startDrainTimeout();\n } else {\n this.stopTracking();\n }\n },\n this._options.inactivityMs\n );\n }\n\n private _startDrainTimeout() {\n this._drainTid = startTimeout(\n this._drainTid,\n () => {\n this.stopTracking();\n },\n this._options.drainTimeoutMs\n );\n }\n\n private hasActiveOperations(): boolean {\n return !!this._activeOperations && this._activeOperations.size > 0;\n }\n\n private _clearTimer(id?: number) {\n if (id) {\n clearTimeout(id);\n }\n }\n}\n\nfunction startTimeout(timeoutId: number | undefined, cb: () => void, delay: number) {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n\n //@ts-expect-error for some reason vscode is using the node types\n timeoutId = setTimeout(() => {\n cb();\n }, delay);\n\n return timeoutId;\n}\n"]}
@@ -6,11 +6,8 @@ function isSampled() {
6
6
  var _a, _b, _c;
7
7
  var sendAllSignals = 1;
8
8
  var sessionTracking = faro_core_1.faro.config.sessionTracking;
9
- var samplingRate = (_c = (_b = (_a = sessionTracking === null || sessionTracking === void 0 ? void 0 : sessionTracking.sampler) === null || _a === void 0 ? void 0 : _a.call(sessionTracking, { metas: faro_core_1.faro.metas.value })) !== null && _b !== void 0 ? _b : sessionTracking === null || sessionTracking === void 0 ? void 0 : sessionTracking.samplingRate) !== null && _c !== void 0 ? _c : sendAllSignals;
10
- if (typeof samplingRate !== 'number') {
11
- var sendNoSignals = 0;
12
- samplingRate = sendNoSignals;
13
- }
9
+ var rawSamplingRate = (_c = (_b = (_a = sessionTracking === null || sessionTracking === void 0 ? void 0 : sessionTracking.sampler) === null || _a === void 0 ? void 0 : _a.call(sessionTracking, { metas: faro_core_1.faro.metas.value })) !== null && _b !== void 0 ? _b : sessionTracking === null || sessionTracking === void 0 ? void 0 : sessionTracking.samplingRate) !== null && _c !== void 0 ? _c : sendAllSignals;
10
+ var samplingRate = typeof rawSamplingRate === 'number' ? (0, faro_core_1.clampSamplingRate)(rawSamplingRate) : 0;
14
11
  return Math.random() < samplingRate;
15
12
  }
16
13
  //# sourceMappingURL=sampling.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sampling.js","sourceRoot":"","sources":["../../../../../src/instrumentations/session/sessionManager/sampling.ts"],"names":[],"mappings":";;AAEA,8BAYC;AAdD,gDAA0C;AAE1C,SAAgB,SAAS;;IACvB,IAAM,cAAc,GAAG,CAAC,CAAC;IACzB,IAAM,eAAe,GAAG,gBAAI,CAAC,MAAM,CAAC,eAAe,CAAC;IACpD,IAAI,YAAY,GACd,MAAA,MAAA,MAAA,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,OAAO,gEAAG,EAAE,KAAK,EAAE,gBAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,mCAAI,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,YAAY,mCAAI,cAAc,CAAC;IAE7G,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE,CAAC;QACrC,IAAM,aAAa,GAAG,CAAC,CAAC;QACxB,YAAY,GAAG,aAAa,CAAC;IAC/B,CAAC;IAED,OAAO,IAAI,CAAC,MAAM,EAAE,GAAG,YAAY,CAAC;AACtC,CAAC","sourcesContent":["import { faro } from '@grafana/faro-core';\n\nexport function isSampled(): boolean {\n const sendAllSignals = 1;\n const sessionTracking = faro.config.sessionTracking;\n let samplingRate =\n sessionTracking?.sampler?.({ metas: faro.metas.value }) ?? sessionTracking?.samplingRate ?? sendAllSignals;\n\n if (typeof samplingRate !== 'number') {\n const sendNoSignals = 0;\n samplingRate = sendNoSignals;\n }\n\n return Math.random() < samplingRate;\n}\n"]}
1
+ {"version":3,"file":"sampling.js","sourceRoot":"","sources":["../../../../../src/instrumentations/session/sessionManager/sampling.ts"],"names":[],"mappings":";;AAEA,8BAQC;AAVD,gDAA6D;AAE7D,SAAgB,SAAS;;IACvB,IAAM,cAAc,GAAG,CAAC,CAAC;IACzB,IAAM,eAAe,GAAG,gBAAI,CAAC,MAAM,CAAC,eAAe,CAAC;IACpD,IAAM,eAAe,GACnB,MAAA,MAAA,MAAA,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,OAAO,gEAAG,EAAE,KAAK,EAAE,gBAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,mCAAI,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,YAAY,mCAAI,cAAc,CAAC;IAC7G,IAAM,YAAY,GAAG,OAAO,eAAe,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAA,6BAAiB,EAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAElG,OAAO,IAAI,CAAC,MAAM,EAAE,GAAG,YAAY,CAAC;AACtC,CAAC","sourcesContent":["import { clampSamplingRate, faro } from '@grafana/faro-core';\n\nexport function isSampled(): boolean {\n const sendAllSignals = 1;\n const sessionTracking = faro.config.sessionTracking;\n const rawSamplingRate =\n sessionTracking?.sampler?.({ metas: faro.metas.value }) ?? sessionTracking?.samplingRate ?? sendAllSignals;\n const samplingRate = typeof rawSamplingRate === 'number' ? clampSamplingRate(rawSamplingRate) : 0;\n\n return Math.random() < samplingRate;\n}\n"]}
@@ -38,6 +38,5 @@ function getUserActionNameFromElement(element, dataAttributeName) {
38
38
  }
39
39
  function unsubscribeAllMonitors(allMonitorsSub) {
40
40
  allMonitorsSub === null || allMonitorsSub === void 0 ? void 0 : allMonitorsSub.unsubscribe();
41
- allMonitorsSub = undefined;
42
41
  }
43
42
  //# sourceMappingURL=processUserActionEventHandler.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"processUserActionEventHandler.js","sourceRoot":"","sources":["../../../../src/instrumentations/userActions/processUserActionEventHandler.ts"],"names":[],"mappings":";;AAMA,kDA0BC;AAED,oEAWC;AAED,wDAGC;AAhDD,iCAAmF;AACnF,+DAA8D;AAC9D,+BAAkD;AAElD,SAAgB,mBAAmB,CAAC,IAAU;IACpC,IAAA,GAAG,GAAa,IAAI,IAAjB,EAAE,MAAM,GAAK,IAAI,OAAT,CAAU;IAE7B,SAAS,gBAAgB,CAAC,KAAmC;;QAC3D,IAAM,cAAc,GAAG,4BAA4B,CACjD,KAAK,CAAC,MAAqB,EAC3B,MAAA,MAAA,MAAM,CAAC,0BAA0B,0CAAE,iBAAiB,mCAAI,qCAAuB,CAChF,CAAC;QAEF,iCAAiC;QACjC,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,OAAO;QACT,CAAC;QAED,IAAM,UAAU,GAAG,GAAG,CAAC,eAAe,CAAC,cAAc,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QACxF,IAAI,UAAU,EAAE,CAAC;YACf,wBAAwB,CAAC,UAAU,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IAED,SAAS,wBAAwB,CAAC,UAA+B;QAC/D,IAAM,kBAAkB,GAAG,UAAoD,CAAC;QAChF,IAAI,2CAAoB,CAAC,kBAAkB,CAAC,CAAC,MAAM,EAAE,CAAC;IACxD,CAAC;IAED,OAAO,EAAE,gBAAgB,kBAAA,EAAE,wBAAwB,0BAAA,EAAE,CAAC;AACxD,CAAC;AAED,SAAgB,4BAA4B,CAAC,OAAoB,EAAE,iBAAyB;IAC1F,IAAM,uBAAuB,GAAG,IAAA,+BAAwB,EAAC,iBAAiB,CAAC,CAAC;IAC5E,IAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAEhC,KAAK,IAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,IAAI,GAAG,KAAK,uBAAuB,EAAE,CAAC;YACpC,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAgB,sBAAsB,CAAC,cAAwC;IAC7E,cAAc,aAAd,cAAc,uBAAd,cAAc,CAAE,WAAW,EAAE,CAAC;IAC9B,cAAc,GAAG,SAAS,CAAC;AAC7B,CAAC","sourcesContent":["import type { Faro, Subscription, UserActionInterface, UserActionInternalInterface } from '@grafana/faro-core';\n\nimport { userActionDataAttributeParsed as userActionDataAttribute } from './const';\nimport { UserActionController } from './userActionController';\nimport { convertDataAttributeName } from './util';\n\nexport function getUserEventHandler(faro: Faro) {\n const { api, config } = faro;\n\n function processUserEvent(event: PointerEvent | KeyboardEvent) {\n const userActionName = getUserActionNameFromElement(\n event.target as HTMLElement,\n config.userActionsInstrumentation?.dataAttributeName ?? userActionDataAttribute\n );\n\n // We don't have a data attribute\n if (!userActionName) {\n return;\n }\n\n const userAction = api.startUserAction(userActionName, {}, { triggerName: event.type });\n if (userAction) {\n processUserActionStarted(userAction);\n }\n }\n\n function processUserActionStarted(userAction: UserActionInterface) {\n const internalUserAction = userAction as unknown as UserActionInternalInterface;\n new UserActionController(internalUserAction).attach();\n }\n\n return { processUserEvent, processUserActionStarted };\n}\n\nexport function getUserActionNameFromElement(element: HTMLElement, dataAttributeName: string): string | undefined {\n const parsedDataAttributeName = convertDataAttributeName(dataAttributeName);\n const dataset = element.dataset;\n\n for (const key in dataset) {\n if (key === parsedDataAttributeName) {\n return dataset[key];\n }\n }\n\n return undefined;\n}\n\nexport function unsubscribeAllMonitors(allMonitorsSub: Subscription | undefined) {\n allMonitorsSub?.unsubscribe();\n allMonitorsSub = undefined;\n}\n"]}
1
+ {"version":3,"file":"processUserActionEventHandler.js","sourceRoot":"","sources":["../../../../src/instrumentations/userActions/processUserActionEventHandler.ts"],"names":[],"mappings":";;AAMA,kDA0BC;AAED,oEAWC;AAED,wDAEC;AA/CD,iCAAmF;AACnF,+DAA8D;AAC9D,+BAAkD;AAElD,SAAgB,mBAAmB,CAAC,IAAU;IACpC,IAAA,GAAG,GAAa,IAAI,IAAjB,EAAE,MAAM,GAAK,IAAI,OAAT,CAAU;IAE7B,SAAS,gBAAgB,CAAC,KAAmC;;QAC3D,IAAM,cAAc,GAAG,4BAA4B,CACjD,KAAK,CAAC,MAAqB,EAC3B,MAAA,MAAA,MAAM,CAAC,0BAA0B,0CAAE,iBAAiB,mCAAI,qCAAuB,CAChF,CAAC;QAEF,iCAAiC;QACjC,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,OAAO;QACT,CAAC;QAED,IAAM,UAAU,GAAG,GAAG,CAAC,eAAe,CAAC,cAAc,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QACxF,IAAI,UAAU,EAAE,CAAC;YACf,wBAAwB,CAAC,UAAU,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IAED,SAAS,wBAAwB,CAAC,UAA+B;QAC/D,IAAM,kBAAkB,GAAG,UAAoD,CAAC;QAChF,IAAI,2CAAoB,CAAC,kBAAkB,CAAC,CAAC,MAAM,EAAE,CAAC;IACxD,CAAC;IAED,OAAO,EAAE,gBAAgB,kBAAA,EAAE,wBAAwB,0BAAA,EAAE,CAAC;AACxD,CAAC;AAED,SAAgB,4BAA4B,CAAC,OAAoB,EAAE,iBAAyB;IAC1F,IAAM,uBAAuB,GAAG,IAAA,+BAAwB,EAAC,iBAAiB,CAAC,CAAC;IAC5E,IAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAEhC,KAAK,IAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,IAAI,GAAG,KAAK,uBAAuB,EAAE,CAAC;YACpC,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAgB,sBAAsB,CAAC,cAAwC;IAC7E,cAAc,aAAd,cAAc,uBAAd,cAAc,CAAE,WAAW,EAAE,CAAC;AAChC,CAAC","sourcesContent":["import type { Faro, Subscription, UserActionInterface, UserActionInternalInterface } from '@grafana/faro-core';\n\nimport { userActionDataAttributeParsed as userActionDataAttribute } from './const';\nimport { UserActionController } from './userActionController';\nimport { convertDataAttributeName } from './util';\n\nexport function getUserEventHandler(faro: Faro) {\n const { api, config } = faro;\n\n function processUserEvent(event: PointerEvent | KeyboardEvent) {\n const userActionName = getUserActionNameFromElement(\n event.target as HTMLElement,\n config.userActionsInstrumentation?.dataAttributeName ?? userActionDataAttribute\n );\n\n // We don't have a data attribute\n if (!userActionName) {\n return;\n }\n\n const userAction = api.startUserAction(userActionName, {}, { triggerName: event.type });\n if (userAction) {\n processUserActionStarted(userAction);\n }\n }\n\n function processUserActionStarted(userAction: UserActionInterface) {\n const internalUserAction = userAction as unknown as UserActionInternalInterface;\n new UserActionController(internalUserAction).attach();\n }\n\n return { processUserEvent, processUserActionStarted };\n}\n\nexport function getUserActionNameFromElement(element: HTMLElement, dataAttributeName: string): string | undefined {\n const parsedDataAttributeName = convertDataAttributeName(dataAttributeName);\n const dataset = element.dataset;\n\n for (const key in dataset) {\n if (key === parsedDataAttributeName) {\n return dataset[key];\n }\n }\n\n return undefined;\n}\n\nexport function unsubscribeAllMonitors(allMonitorsSub: Subscription | undefined) {\n allMonitorsSub?.unsubscribe();\n}\n"]}
@@ -112,43 +112,66 @@ var FetchTransport = /** @class */ (function (_super) {
112
112
  this.logWarn("Dropping transport item due to too many requests. Backoff until ".concat(this.disabledUntil));
113
113
  return [2 /*return*/, Promise.resolve()];
114
114
  }
115
- return [4 /*yield*/, this.promiseBuffer.add(function () {
116
- var body = JSON.stringify((0, faro_core_1.getTransportBody)(items));
117
- var _a = _this.options, url = _a.url, requestOptions = _a.requestOptions, apiKey = _a.apiKey;
118
- var _b = requestOptions !== null && requestOptions !== void 0 ? requestOptions : {}, _c = _b.headers, headers = _c === void 0 ? {} : _c, restOfRequestOptions = __rest(_b, ["headers"]);
119
- var sessionId;
120
- var sessionMeta = _this.metas.value.session;
121
- if (sessionMeta != null) {
122
- sessionId = sessionMeta.id;
123
- }
124
- var resolvedHeaders = {};
125
- for (var _i = 0, _d = Object.entries(headers); _i < _d.length; _i++) {
126
- var _e = _d[_i], key = _e[0], value = _e[1];
127
- resolvedHeaders[key] = typeof value === 'function' ? value() : value;
128
- }
129
- return fetch(url, __assign({ method: 'POST', headers: __assign(__assign(__assign({ 'Content-Type': 'application/json' }, resolvedHeaders), (apiKey ? { 'x-api-key': apiKey } : {})), (sessionId ? { 'x-faro-session-id': sessionId } : {})), body: body, keepalive: body.length <= BEACON_BODY_SIZE_LIMIT }, (restOfRequestOptions !== null && restOfRequestOptions !== void 0 ? restOfRequestOptions : {})))
130
- .then(function (response) { return __awaiter(_this, void 0, void 0, function () {
131
- var sessionExpired;
132
- return __generator(this, function (_a) {
133
- if (response.status === ACCEPTED) {
134
- sessionExpired = response.headers.get('X-Faro-Session-Status') === 'invalid';
135
- if (sessionExpired) {
136
- this.extendFaroSession(this.config, this.logDebug);
115
+ return [4 /*yield*/, this.promiseBuffer.add(function () { return __awaiter(_this, void 0, void 0, function () {
116
+ var body, _a, url, requestOptions, apiKey, _b, _c, headers, restOfRequestOptions, sessionId, sessionMeta, resolvedHeaders, _i, _d, _e, key, value, _f, _g, _h;
117
+ var _this = this;
118
+ return __generator(this, function (_j) {
119
+ switch (_j.label) {
120
+ case 0:
121
+ body = JSON.stringify((0, faro_core_1.getTransportBody)(items));
122
+ _a = this.options, url = _a.url, requestOptions = _a.requestOptions, apiKey = _a.apiKey;
123
+ _b = requestOptions !== null && requestOptions !== void 0 ? requestOptions : {}, _c = _b.headers, headers = _c === void 0 ? {} : _c, restOfRequestOptions = __rest(_b, ["headers"]);
124
+ sessionMeta = this.metas.value.session;
125
+ if (sessionMeta != null) {
126
+ sessionId = sessionMeta.id;
137
127
  }
138
- }
139
- if (response.status === TOO_MANY_REQUESTS) {
140
- this.disabledUntil = this.getRetryAfterDate(response);
141
- this.logWarn("Too many requests, backing off until ".concat(this.disabledUntil));
142
- }
143
- // read the body so the connection can be closed
144
- response.text().catch(faro_core_1.noop);
145
- return [2 /*return*/, response];
146
- });
147
- }); })
148
- .catch(function (err) {
149
- _this.logError('Failed sending payload to the receiver\n', JSON.parse(body), err);
128
+ resolvedHeaders = {};
129
+ _i = 0, _d = Object.entries(headers);
130
+ _j.label = 1;
131
+ case 1:
132
+ if (!(_i < _d.length)) return [3 /*break*/, 6];
133
+ _e = _d[_i], key = _e[0], value = _e[1];
134
+ _f = resolvedHeaders;
135
+ _g = key;
136
+ if (!(typeof value === 'function')) return [3 /*break*/, 3];
137
+ return [4 /*yield*/, Promise.resolve(value())];
138
+ case 2:
139
+ _h = _j.sent();
140
+ return [3 /*break*/, 4];
141
+ case 3:
142
+ _h = value;
143
+ _j.label = 4;
144
+ case 4:
145
+ _f[_g] = _h;
146
+ _j.label = 5;
147
+ case 5:
148
+ _i++;
149
+ return [3 /*break*/, 1];
150
+ case 6: return [2 /*return*/, fetch(url, __assign({ method: 'POST', headers: __assign(__assign(__assign({ 'Content-Type': 'application/json' }, resolvedHeaders), (apiKey ? { 'x-api-key': apiKey } : {})), (sessionId ? { 'x-faro-session-id': sessionId } : {})), body: body, keepalive: body.length <= BEACON_BODY_SIZE_LIMIT }, (restOfRequestOptions !== null && restOfRequestOptions !== void 0 ? restOfRequestOptions : {})))
151
+ .then(function (response) { return __awaiter(_this, void 0, void 0, function () {
152
+ var sessionExpired;
153
+ return __generator(this, function (_a) {
154
+ if (response.status === ACCEPTED) {
155
+ sessionExpired = response.headers.get('X-Faro-Session-Status') === 'invalid';
156
+ if (sessionExpired) {
157
+ this.extendFaroSession(this.config, this.logDebug);
158
+ }
159
+ }
160
+ if (response.status === TOO_MANY_REQUESTS) {
161
+ this.disabledUntil = this.getRetryAfterDate(response);
162
+ this.logWarn("Too many requests, backing off until ".concat(this.disabledUntil));
163
+ }
164
+ // read the body so the connection can be closed
165
+ response.text().catch(faro_core_1.noop);
166
+ return [2 /*return*/, response];
167
+ });
168
+ }); })
169
+ .catch(function (err) {
170
+ _this.logError('Failed sending payload to the receiver\n', JSON.parse(body), err);
171
+ })];
172
+ }
150
173
  });
151
- })];
174
+ }); })];
152
175
  case 1:
153
176
  _a.sent();
154
177
  return [3 /*break*/, 3];
@@ -1 +1 @@
1
- {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../../../src/transports/fetch/transport.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,gDAAwH;AAGxH,gFAA0F;AAC1F,yGAA0G;AAI1G,IAAM,mBAAmB,GAAG,EAAE,CAAC;AAC/B,IAAM,mBAAmB,GAAG,CAAC,CAAC,CAAC,uCAAuC;AACtE,IAAM,6BAA6B,GAAG,IAAI,CAAC;AAE3C,IAAM,sBAAsB,GAAG,KAAK,CAAC;AACrC,IAAM,iBAAiB,GAAG,GAAG,CAAC;AAC9B,IAAM,QAAQ,GAAG,GAAG,CAAC;AAErB;IAAoC,kCAAa;IAU/C,wBAAoB,OAA8B;;QAChD,YAAA,MAAK,WAAE,SAAC;QADU,aAAO,GAAP,OAAO,CAAuB;QATzC,UAAI,GAAG,uCAAuC,CAAC;QAC/C,aAAO,GAAG,mBAAO,CAAC;QAMnB,mBAAa,GAAS,IAAI,IAAI,EAAE,CAAC;QAKvC,KAAI,CAAC,kBAAkB,GAAG,MAAA,OAAO,CAAC,yBAAyB,mCAAI,6BAA6B,CAAC;QAC7F,KAAI,CAAC,MAAM,GAAG,MAAA,OAAO,CAAC,MAAM,mCAAI,CAAC,cAAM,OAAA,IAAI,CAAC,GAAG,EAAE,EAAV,CAAU,CAAC,CAAC;QAEnD,KAAI,CAAC,aAAa,GAAG,IAAA,+BAAmB,EAAC;YACvC,IAAI,EAAE,MAAA,OAAO,CAAC,UAAU,mCAAI,mBAAmB;YAC/C,WAAW,EAAE,MAAA,OAAO,CAAC,WAAW,mCAAI,mBAAmB;SACxD,CAAC,CAAC;;IACL,CAAC;IAEK,6BAAI,GAAV,UAAW,KAAsB;;;;;;;;wBAE7B,IAAI,IAAI,CAAC,aAAa,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;4BACjD,IAAI,CAAC,OAAO,CAAC,0EAAmE,IAAI,CAAC,aAAa,CAAE,CAAC,CAAC;4BAEtG,sBAAO,OAAO,CAAC,OAAO,EAAE,EAAC;wBAC3B,CAAC;wBAED,qBAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC;gCAC3B,IAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAA,4BAAgB,EAAC,KAAK,CAAC,CAAC,CAAC;gCAE/C,IAAA,KAAkC,KAAI,CAAC,OAAO,EAA5C,GAAG,SAAA,EAAE,cAAc,oBAAA,EAAE,MAAM,YAAiB,CAAC;gCAErD,IAAM,KAA4C,cAAc,aAAd,cAAc,cAAd,cAAc,GAAI,EAAE,EAA9D,eAAY,EAAZ,OAAO,mBAAG,EAAE,KAAA,EAAK,oBAAoB,cAAvC,WAAyC,CAAuB,CAAC;gCAEvE,IAAI,SAAS,CAAC;gCACd,IAAM,WAAW,GAAG,KAAI,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC;gCAC7C,IAAI,WAAW,IAAI,IAAI,EAAE,CAAC;oCACxB,SAAS,GAAG,WAAW,CAAC,EAAE,CAAC;gCAC7B,CAAC;gCAED,IAAM,eAAe,GAA2B,EAAE,CAAC;gCACnD,KAA2B,UAAuB,EAAvB,KAAA,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAvB,cAAuB,EAAvB,IAAuB,EAAE,CAAC;oCAA1C,IAAA,WAAY,EAAX,GAAG,QAAA,EAAE,KAAK,QAAA;oCACpB,eAAe,CAAC,GAAG,CAAC,GAAG,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;gCACvE,CAAC;gCAED,OAAO,KAAK,CAAC,GAAG,aACd,MAAM,EAAE,MAAM,EACd,OAAO,+BACL,cAAc,EAAE,kBAAkB,IAC/B,eAAe,GACf,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,GACvC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,mBAAmB,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,GAE1D,IAAI,MAAA,EACJ,SAAS,EAAE,IAAI,CAAC,MAAM,IAAI,sBAAsB,IAC7C,CAAC,oBAAoB,aAApB,oBAAoB,cAApB,oBAAoB,GAAI,EAAE,CAAC,EAC/B;qCACC,IAAI,CAAC,UAAO,QAAQ;;;wCACnB,IAAI,QAAQ,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;4CAC3B,cAAc,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,KAAK,SAAS,CAAC;4CAEnF,IAAI,cAAc,EAAE,CAAC;gDACnB,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;4CACrD,CAAC;wCACH,CAAC;wCAED,IAAI,QAAQ,CAAC,MAAM,KAAK,iBAAiB,EAAE,CAAC;4CAC1C,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;4CACtD,IAAI,CAAC,OAAO,CAAC,+CAAwC,IAAI,CAAC,aAAa,CAAE,CAAC,CAAC;wCAC7E,CAAC;wCAED,gDAAgD;wCAChD,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,gBAAI,CAAC,CAAC;wCAC5B,sBAAO,QAAQ,EAAC;;qCACjB,CAAC;qCACD,KAAK,CAAC,UAAC,GAAG;oCACT,KAAI,CAAC,QAAQ,CAAC,0CAA0C,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;gCACnF,CAAC,CAAC,CAAC;4BACP,CAAC,CAAC,EAAA;;wBAnDF,SAmDE,CAAC;;;;wBAEH,IAAI,CAAC,QAAQ,CAAC,KAAG,CAAC,CAAC;;;;;;KAEtB;IAEQ,sCAAa,GAAtB;;QACE,OAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAc,CAAC,MAAM,CAAC,MAAA,IAAI,CAAC,MAAM,CAAC,UAAU,mCAAI,EAAE,CAAC,CAAC;IAC/E,CAAC;IAEQ,kCAAS,GAAlB;QACE,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,0CAAiB,GAAzB,UAA0B,QAAkB;QAC1C,IAAM,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QAC1B,IAAM,gBAAgB,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAE7D,IAAI,gBAAgB,EAAE,CAAC;YACrB,IAAM,KAAK,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;YAEvC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;gBAClB,OAAO,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI,GAAG,GAAG,CAAC,CAAC;YACtC,CAAC;YAED,IAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;YAE1C,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBACjB,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;QAED,OAAO,IAAI,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,kBAAkB,CAAC,CAAC;IACjD,CAAC;IAEO,0CAAiB,GAAzB,UAA0B,MAAc,EAAE,QAAmC;QAC3E,IAAM,oBAAoB,GAAG,iBAAiB,CAAC;QAE/C,IAAM,qBAAqB,GAAG,MAAM,CAAC,eAAe,CAAC;QAErD,IAAI,qBAAqB,aAArB,qBAAqB,uBAArB,qBAAqB,CAAE,OAAO,EAAE,CAAC;YAC7B,IAAA,KAAyC,IAAA,0CAAyB,EAAC,qBAAqB,CAAC,EAAvF,gBAAgB,sBAAA,EAAE,gBAAgB,sBAAqD,CAAC;YAEhG,IAAA,2CAAqB,EAAC,EAAE,gBAAgB,kBAAA,EAAE,gBAAgB,kBAAA,EAAE,CAAC,CAAC,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC;YAE5F,QAAQ,CAAC,UAAG,oBAAoB,0BAAuB,CAAC,CAAC;QAC3D,CAAC;aAAM,CAAC;YACN,QAAQ,CAAC,UAAG,oBAAoB,MAAG,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IACH,qBAAC;AAAD,CAAC,AAnID,CAAoC,yBAAa,GAmIhD;AAnIY,wCAAc","sourcesContent":["import { BaseExtension, BaseTransport, createPromiseBuffer, getTransportBody, noop, VERSION } from '@grafana/faro-core';\nimport type { Config, Patterns, PromiseBuffer, TransportItem } from '@grafana/faro-core';\n\nimport { getSessionManagerByConfig } from '../../instrumentations/session/sessionManager';\nimport { getUserSessionUpdater } from '../../instrumentations/session/sessionManager/sessionManagerUtils';\n\nimport type { FetchTransportOptions } from './types';\n\nconst DEFAULT_BUFFER_SIZE = 30;\nconst DEFAULT_CONCURRENCY = 5; // chrome supports 10 total, firefox 17\nconst DEFAULT_RATE_LIMIT_BACKOFF_MS = 5000;\n\nconst BEACON_BODY_SIZE_LIMIT = 60000;\nconst TOO_MANY_REQUESTS = 429;\nconst ACCEPTED = 202;\n\nexport class FetchTransport extends BaseTransport {\n readonly name = '@grafana/faro-web-sdk:transport-fetch';\n readonly version = VERSION;\n\n promiseBuffer: PromiseBuffer<Response | void>;\n\n private readonly rateLimitBackoffMs: number;\n private readonly getNow: () => number;\n private disabledUntil: Date = new Date();\n\n constructor(private options: FetchTransportOptions) {\n super();\n\n this.rateLimitBackoffMs = options.defaultRateLimitBackoffMs ?? DEFAULT_RATE_LIMIT_BACKOFF_MS;\n this.getNow = options.getNow ?? (() => Date.now());\n\n this.promiseBuffer = createPromiseBuffer({\n size: options.bufferSize ?? DEFAULT_BUFFER_SIZE,\n concurrency: options.concurrency ?? DEFAULT_CONCURRENCY,\n });\n }\n\n async send(items: TransportItem[]): Promise<void> {\n try {\n if (this.disabledUntil > new Date(this.getNow())) {\n this.logWarn(`Dropping transport item due to too many requests. Backoff until ${this.disabledUntil}`);\n\n return Promise.resolve();\n }\n\n await this.promiseBuffer.add(() => {\n const body = JSON.stringify(getTransportBody(items));\n\n const { url, requestOptions, apiKey } = this.options;\n\n const { headers = {}, ...restOfRequestOptions } = requestOptions ?? {};\n\n let sessionId;\n const sessionMeta = this.metas.value.session;\n if (sessionMeta != null) {\n sessionId = sessionMeta.id;\n }\n\n const resolvedHeaders: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers)) {\n resolvedHeaders[key] = typeof value === 'function' ? value() : value;\n }\n\n return fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...resolvedHeaders,\n ...(apiKey ? { 'x-api-key': apiKey } : {}),\n ...(sessionId ? { 'x-faro-session-id': sessionId } : {}),\n },\n body,\n keepalive: body.length <= BEACON_BODY_SIZE_LIMIT,\n ...(restOfRequestOptions ?? {}),\n })\n .then(async (response) => {\n if (response.status === ACCEPTED) {\n const sessionExpired = response.headers.get('X-Faro-Session-Status') === 'invalid';\n\n if (sessionExpired) {\n this.extendFaroSession(this.config, this.logDebug);\n }\n }\n\n if (response.status === TOO_MANY_REQUESTS) {\n this.disabledUntil = this.getRetryAfterDate(response);\n this.logWarn(`Too many requests, backing off until ${this.disabledUntil}`);\n }\n\n // read the body so the connection can be closed\n response.text().catch(noop);\n return response;\n })\n .catch((err) => {\n this.logError('Failed sending payload to the receiver\\n', JSON.parse(body), err);\n });\n });\n } catch (err) {\n this.logError(err);\n }\n }\n\n override getIgnoreUrls(): Patterns {\n return ([this.options.url] as Patterns).concat(this.config.ignoreUrls ?? []);\n }\n\n override isBatched(): boolean {\n return true;\n }\n\n private getRetryAfterDate(response: Response): Date {\n const now = this.getNow();\n const retryAfterHeader = response.headers.get('Retry-After');\n\n if (retryAfterHeader) {\n const delay = Number(retryAfterHeader);\n\n if (!isNaN(delay)) {\n return new Date(delay * 1000 + now);\n }\n\n const date = Date.parse(retryAfterHeader);\n\n if (!isNaN(date)) {\n return new Date(date);\n }\n }\n\n return new Date(now + this.rateLimitBackoffMs);\n }\n\n private extendFaroSession(config: Config, logDebug: BaseExtension['logDebug']) {\n const SessionExpiredString = `Session expired`;\n\n const sessionTrackingConfig = config.sessionTracking;\n\n if (sessionTrackingConfig?.enabled) {\n const { fetchUserSession, storeUserSession } = getSessionManagerByConfig(sessionTrackingConfig);\n\n getUserSessionUpdater({ fetchUserSession, storeUserSession })({ forceSessionExtend: true });\n\n logDebug(`${SessionExpiredString} created new session.`);\n } else {\n logDebug(`${SessionExpiredString}.`);\n }\n }\n}\n"]}
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../../../src/transports/fetch/transport.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseExtension, BaseTransport, createPromiseBuffer, getTransportBody, noop, VERSION } from '@grafana/faro-core';\nimport type { Config, Patterns, PromiseBuffer, TransportItem } from '@grafana/faro-core';\n\nimport { getSessionManagerByConfig } from '../../instrumentations/session/sessionManager';\nimport { getUserSessionUpdater } from '../../instrumentations/session/sessionManager/sessionManagerUtils';\n\nimport type { FetchTransportOptions } from './types';\n\nconst DEFAULT_BUFFER_SIZE = 30;\nconst DEFAULT_CONCURRENCY = 5; // chrome supports 10 total, firefox 17\nconst DEFAULT_RATE_LIMIT_BACKOFF_MS = 5000;\n\nconst BEACON_BODY_SIZE_LIMIT = 60000;\nconst TOO_MANY_REQUESTS = 429;\nconst ACCEPTED = 202;\n\nexport class FetchTransport extends BaseTransport {\n readonly name = '@grafana/faro-web-sdk:transport-fetch';\n readonly version = VERSION;\n\n promiseBuffer: PromiseBuffer<Response | void>;\n\n private readonly rateLimitBackoffMs: number;\n private readonly getNow: () => number;\n private disabledUntil: Date = new Date();\n\n constructor(private options: FetchTransportOptions) {\n super();\n\n this.rateLimitBackoffMs = options.defaultRateLimitBackoffMs ?? DEFAULT_RATE_LIMIT_BACKOFF_MS;\n this.getNow = options.getNow ?? (() => Date.now());\n\n this.promiseBuffer = createPromiseBuffer({\n size: options.bufferSize ?? DEFAULT_BUFFER_SIZE,\n concurrency: options.concurrency ?? DEFAULT_CONCURRENCY,\n });\n }\n\n async send(items: TransportItem[]): Promise<void> {\n try {\n if (this.disabledUntil > new Date(this.getNow())) {\n this.logWarn(`Dropping transport item due to too many requests. Backoff until ${this.disabledUntil}`);\n\n return Promise.resolve();\n }\n\n await this.promiseBuffer.add(async () => {\n const body = JSON.stringify(getTransportBody(items));\n\n const { url, requestOptions, apiKey } = this.options;\n\n const { headers = {}, ...restOfRequestOptions } = requestOptions ?? {};\n\n let sessionId;\n const sessionMeta = this.metas.value.session;\n if (sessionMeta != null) {\n sessionId = sessionMeta.id;\n }\n\n const resolvedHeaders: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers)) {\n resolvedHeaders[key] = typeof value === 'function' ? await Promise.resolve(value()) : value;\n }\n\n return fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...resolvedHeaders,\n ...(apiKey ? { 'x-api-key': apiKey } : {}),\n ...(sessionId ? { 'x-faro-session-id': sessionId } : {}),\n },\n body,\n keepalive: body.length <= BEACON_BODY_SIZE_LIMIT,\n ...(restOfRequestOptions ?? {}),\n })\n .then(async (response) => {\n if (response.status === ACCEPTED) {\n const sessionExpired = response.headers.get('X-Faro-Session-Status') === 'invalid';\n\n if (sessionExpired) {\n this.extendFaroSession(this.config, this.logDebug);\n }\n }\n\n if (response.status === TOO_MANY_REQUESTS) {\n this.disabledUntil = this.getRetryAfterDate(response);\n this.logWarn(`Too many requests, backing off until ${this.disabledUntil}`);\n }\n\n // read the body so the connection can be closed\n response.text().catch(noop);\n return response;\n })\n .catch((err) => {\n this.logError('Failed sending payload to the receiver\\n', JSON.parse(body), err);\n });\n });\n } catch (err) {\n this.logError(err);\n }\n }\n\n override getIgnoreUrls(): Patterns {\n return ([this.options.url] as Patterns).concat(this.config.ignoreUrls ?? []);\n }\n\n override isBatched(): boolean {\n return true;\n }\n\n private getRetryAfterDate(response: Response): Date {\n const now = this.getNow();\n const retryAfterHeader = response.headers.get('Retry-After');\n\n if (retryAfterHeader) {\n const delay = Number(retryAfterHeader);\n\n if (!isNaN(delay)) {\n return new Date(delay * 1000 + now);\n }\n\n const date = Date.parse(retryAfterHeader);\n\n if (!isNaN(date)) {\n return new Date(date);\n }\n }\n\n return new Date(now + this.rateLimitBackoffMs);\n }\n\n private extendFaroSession(config: Config, logDebug: BaseExtension['logDebug']) {\n const SessionExpiredString = `Session expired`;\n\n const sessionTrackingConfig = config.sessionTracking;\n\n if (sessionTrackingConfig?.enabled) {\n const { fetchUserSession, storeUserSession } = getSessionManagerByConfig(sessionTrackingConfig);\n\n getUserSessionUpdater({ fetchUserSession, storeUserSession })({ forceSessionExtend: true });\n\n logDebug(`${SessionExpiredString} created new session.`);\n } else {\n logDebug(`${SessionExpiredString}.`);\n }\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/transports/fetch/types.ts"],"names":[],"mappings":"","sourcesContent":["export interface FetchTransportRequestOptions extends Omit<RequestInit, 'body' | 'headers'> {\n /**\n * Headers to include in every request.\n * Each value can be:\n * - a string (static value)\n * - a function returning a string (dynamic value)\n */\n headers?: Record<string, string | (() => string)>;\n}\n\nexport interface FetchTransportOptions {\n // url of the collector endpoint\n url: string;\n\n // will be added as `x-api-key` header\n apiKey?: string;\n // how many requests to buffer in total\n bufferSize?: number;\n // how many requests to execute concurrently\n concurrency?: number;\n // if rate limit response does not include a Retry-After header,\n // how many milliseconds to back off before attempting a request.\n // intermediate events will be dropped, not buffered\n defaultRateLimitBackoffMs?: number;\n // get current date. for mocking purposes in tests\n getNow?: ClockFn;\n // addition options for global.Fetch\n requestOptions?: FetchTransportRequestOptions;\n}\n\nexport type ClockFn = () => number;\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/transports/fetch/types.ts"],"names":[],"mappings":"","sourcesContent":["export interface FetchTransportRequestOptions extends Omit<RequestInit, 'body' | 'headers'> {\n /**\n * Headers to include in every request.\n * Each value can be:\n * - a string (static value)\n * - a function returning a string (dynamic value, sync)\n * - a function returning a Promise of string (dynamic value, async)\n */\n headers?: Record<string, string | (() => string | Promise<string>)>;\n}\n\nexport interface FetchTransportOptions {\n // url of the collector endpoint\n url: string;\n\n // will be added as `x-api-key` header\n apiKey?: string;\n // how many requests to buffer in total\n bufferSize?: number;\n // how many requests to execute concurrently\n concurrency?: number;\n // if rate limit response does not include a Retry-After header,\n // how many milliseconds to back off before attempting a request.\n // intermediate events will be dropped, not buffered\n defaultRateLimitBackoffMs?: number;\n // get current date. for mocking purposes in tests\n getNow?: ClockFn;\n // addition options for global.Fetch\n requestOptions?: FetchTransportRequestOptions;\n}\n\nexport type ClockFn = () => number;\n"]}
@@ -63,7 +63,7 @@ export class ActivityWindowTracker extends Observable {
63
63
  this._tracking = false;
64
64
  this._clearTimer(this._inactivityTid);
65
65
  this._clearTimer(this._drainTid);
66
- let duration = 0;
66
+ let duration;
67
67
  if (this.hasActiveOperations()) {
68
68
  duration = Date.now() - this._startTime;
69
69
  }
@@ -1 +1 @@
1
- {"version":3,"file":"activityWindowTracker.js","sourceRoot":"","sources":["../../../../src/instrumentations/_internal/activityWindowTracker.ts"],"names":[],"mappings":"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","sourcesContent":["import { Observable } from '@grafana/faro-core';\n\nimport { MESSAGE_TYPE_HTTP_REQUEST_END, MESSAGE_TYPE_HTTP_REQUEST_START } from './monitors/const';\nimport type { HttpRequestEndMessage, HttpRequestStartMessage } from './monitors/types';\n\ntype OperationKey = string;\n\nexport function isRequestStartMessage(msg: any): msg is HttpRequestStartMessage {\n return msg.type === MESSAGE_TYPE_HTTP_REQUEST_START;\n}\n\nexport function isRequestEndMessage(msg: any): msg is HttpRequestEndMessage {\n return msg.type === MESSAGE_TYPE_HTTP_REQUEST_END;\n}\n\nexport interface ActivityWindowTrackerOptions<TMsg = any> {\n inactivityMs?: number;\n drainTimeoutMs?: number;\n isOperationStart?: (msg: TMsg) => OperationKey | undefined;\n isOperationEnd?: (msg: TMsg) => OperationKey | undefined;\n}\n\n/**\n * Tracks events in a time‑boxed activity window. When the window goes quiet for `inactivityMs`,\n * it enters a draining phase: new short events are ignored; only active operations are awaited\n * until they end or `drainTimeoutMs` elapses.\n */\nexport class ActivityWindowTracker extends Observable {\n eventsObservable: Observable;\n\n private _tracking = false;\n private _inactivityTid?: number;\n private _drainTid?: number;\n private _currentEvents?: any[];\n private _activeOperations?: Map<OperationKey, true>;\n private _startTime?: number;\n private _lastEventTime?: number;\n private _options: Required<ActivityWindowTrackerOptions>;\n\n constructor(eventsObservable: Observable, options?: ActivityWindowTrackerOptions) {\n super();\n this.eventsObservable = eventsObservable;\n this._options = {\n inactivityMs: options?.inactivityMs ?? 100,\n drainTimeoutMs: options?.drainTimeoutMs ?? 10 * 1000,\n isOperationStart: options?.isOperationStart ?? (() => undefined),\n isOperationEnd: options?.isOperationEnd ?? (() => undefined),\n } as Required<ActivityWindowTrackerOptions>;\n this._initialize();\n }\n\n private _initialize() {\n this.eventsObservable\n .filter(() => {\n return this._tracking;\n })\n .subscribe((event) => {\n this._lastEventTime = Date.now();\n this._currentEvents?.push(event);\n\n const startKey = this._options.isOperationStart(event as any);\n if (startKey) {\n this._activeOperations?.set(startKey, true);\n }\n\n const endKey = this._options.isOperationEnd(event as any);\n if (endKey) {\n this._activeOperations?.delete(endKey);\n }\n\n this._scheduleInactivityCheck();\n });\n }\n\n startTracking() {\n if (this._tracking) {\n return;\n }\n\n this._tracking = true;\n this._startTime = Date.now();\n this._lastEventTime = Date.now();\n\n this.notify({\n message: 'tracking-started',\n });\n\n this._currentEvents = [];\n this._activeOperations = new Map<OperationKey, true>();\n this._scheduleInactivityCheck();\n }\n\n stopTracking() {\n this._tracking = false;\n this._clearTimer(this._inactivityTid);\n this._clearTimer(this._drainTid);\n\n let duration = 0;\n if (this.hasActiveOperations()) {\n duration = Date.now() - this._startTime!;\n } else {\n duration = this._lastEventTime ? this._lastEventTime - this._startTime! : 0;\n }\n\n this.notify({\n message: 'tracking-ended',\n events: this._currentEvents,\n duration: duration,\n });\n }\n\n private _scheduleInactivityCheck() {\n this._inactivityTid = startTimeout(\n this._inactivityTid,\n () => {\n if (this.hasActiveOperations()) {\n this._startDrainTimeout();\n } else {\n this.stopTracking();\n }\n },\n this._options.inactivityMs\n );\n }\n\n private _startDrainTimeout() {\n this._drainTid = startTimeout(\n this._drainTid,\n () => {\n this.stopTracking();\n },\n this._options.drainTimeoutMs\n );\n }\n\n private hasActiveOperations(): boolean {\n return !!this._activeOperations && this._activeOperations.size > 0;\n }\n\n private _clearTimer(id?: number) {\n if (id) {\n clearTimeout(id);\n }\n }\n}\n\nfunction startTimeout(timeoutId: number | undefined, cb: () => void, delay: number) {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n\n //@ts-expect-error for some reason vscode is using the node types\n timeoutId = setTimeout(() => {\n cb();\n }, delay);\n\n return timeoutId;\n}\n"]}
1
+ {"version":3,"file":"activityWindowTracker.js","sourceRoot":"","sources":["../../../../src/instrumentations/_internal/activityWindowTracker.ts"],"names":[],"mappings":"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","sourcesContent":["import { Observable } from '@grafana/faro-core';\n\nimport { MESSAGE_TYPE_HTTP_REQUEST_END, MESSAGE_TYPE_HTTP_REQUEST_START } from './monitors/const';\nimport type { HttpRequestEndMessage, HttpRequestStartMessage } from './monitors/types';\n\ntype OperationKey = string;\n\nexport function isRequestStartMessage(msg: any): msg is HttpRequestStartMessage {\n return msg.type === MESSAGE_TYPE_HTTP_REQUEST_START;\n}\n\nexport function isRequestEndMessage(msg: any): msg is HttpRequestEndMessage {\n return msg.type === MESSAGE_TYPE_HTTP_REQUEST_END;\n}\n\nexport interface ActivityWindowTrackerOptions<TMsg = any> {\n inactivityMs?: number;\n drainTimeoutMs?: number;\n isOperationStart?: (msg: TMsg) => OperationKey | undefined;\n isOperationEnd?: (msg: TMsg) => OperationKey | undefined;\n}\n\n/**\n * Tracks events in a time‑boxed activity window. When the window goes quiet for `inactivityMs`,\n * it enters a draining phase: new short events are ignored; only active operations are awaited\n * until they end or `drainTimeoutMs` elapses.\n */\nexport class ActivityWindowTracker extends Observable {\n eventsObservable: Observable;\n\n private _tracking = false;\n private _inactivityTid?: number;\n private _drainTid?: number;\n private _currentEvents?: any[];\n private _activeOperations?: Map<OperationKey, true>;\n private _startTime?: number;\n private _lastEventTime?: number;\n private _options: Required<ActivityWindowTrackerOptions>;\n\n constructor(eventsObservable: Observable, options?: ActivityWindowTrackerOptions) {\n super();\n this.eventsObservable = eventsObservable;\n this._options = {\n inactivityMs: options?.inactivityMs ?? 100,\n drainTimeoutMs: options?.drainTimeoutMs ?? 10 * 1000,\n isOperationStart: options?.isOperationStart ?? (() => undefined),\n isOperationEnd: options?.isOperationEnd ?? (() => undefined),\n } as Required<ActivityWindowTrackerOptions>;\n this._initialize();\n }\n\n private _initialize() {\n this.eventsObservable\n .filter(() => {\n return this._tracking;\n })\n .subscribe((event) => {\n this._lastEventTime = Date.now();\n this._currentEvents?.push(event);\n\n const startKey = this._options.isOperationStart(event as any);\n if (startKey) {\n this._activeOperations?.set(startKey, true);\n }\n\n const endKey = this._options.isOperationEnd(event as any);\n if (endKey) {\n this._activeOperations?.delete(endKey);\n }\n\n this._scheduleInactivityCheck();\n });\n }\n\n startTracking() {\n if (this._tracking) {\n return;\n }\n\n this._tracking = true;\n this._startTime = Date.now();\n this._lastEventTime = Date.now();\n\n this.notify({\n message: 'tracking-started',\n });\n\n this._currentEvents = [];\n this._activeOperations = new Map<OperationKey, true>();\n this._scheduleInactivityCheck();\n }\n\n stopTracking() {\n this._tracking = false;\n this._clearTimer(this._inactivityTid);\n this._clearTimer(this._drainTid);\n\n let duration;\n if (this.hasActiveOperations()) {\n duration = Date.now() - this._startTime!;\n } else {\n duration = this._lastEventTime ? this._lastEventTime - this._startTime! : 0;\n }\n\n this.notify({\n message: 'tracking-ended',\n events: this._currentEvents,\n duration: duration,\n });\n }\n\n private _scheduleInactivityCheck() {\n this._inactivityTid = startTimeout(\n this._inactivityTid,\n () => {\n if (this.hasActiveOperations()) {\n this._startDrainTimeout();\n } else {\n this.stopTracking();\n }\n },\n this._options.inactivityMs\n );\n }\n\n private _startDrainTimeout() {\n this._drainTid = startTimeout(\n this._drainTid,\n () => {\n this.stopTracking();\n },\n this._options.drainTimeoutMs\n );\n }\n\n private hasActiveOperations(): boolean {\n return !!this._activeOperations && this._activeOperations.size > 0;\n }\n\n private _clearTimer(id?: number) {\n if (id) {\n clearTimeout(id);\n }\n }\n}\n\nfunction startTimeout(timeoutId: number | undefined, cb: () => void, delay: number) {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n\n //@ts-expect-error for some reason vscode is using the node types\n timeoutId = setTimeout(() => {\n cb();\n }, delay);\n\n return timeoutId;\n}\n"]}
@@ -1,13 +1,10 @@
1
- import { faro } from '@grafana/faro-core';
1
+ import { clampSamplingRate, faro } from '@grafana/faro-core';
2
2
  export function isSampled() {
3
3
  var _a, _b, _c;
4
4
  const sendAllSignals = 1;
5
5
  const sessionTracking = faro.config.sessionTracking;
6
- let samplingRate = (_c = (_b = (_a = sessionTracking === null || sessionTracking === void 0 ? void 0 : sessionTracking.sampler) === null || _a === void 0 ? void 0 : _a.call(sessionTracking, { metas: faro.metas.value })) !== null && _b !== void 0 ? _b : sessionTracking === null || sessionTracking === void 0 ? void 0 : sessionTracking.samplingRate) !== null && _c !== void 0 ? _c : sendAllSignals;
7
- if (typeof samplingRate !== 'number') {
8
- const sendNoSignals = 0;
9
- samplingRate = sendNoSignals;
10
- }
6
+ const rawSamplingRate = (_c = (_b = (_a = sessionTracking === null || sessionTracking === void 0 ? void 0 : sessionTracking.sampler) === null || _a === void 0 ? void 0 : _a.call(sessionTracking, { metas: faro.metas.value })) !== null && _b !== void 0 ? _b : sessionTracking === null || sessionTracking === void 0 ? void 0 : sessionTracking.samplingRate) !== null && _c !== void 0 ? _c : sendAllSignals;
7
+ const samplingRate = typeof rawSamplingRate === 'number' ? clampSamplingRate(rawSamplingRate) : 0;
11
8
  return Math.random() < samplingRate;
12
9
  }
13
10
  //# sourceMappingURL=sampling.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sampling.js","sourceRoot":"","sources":["../../../../../src/instrumentations/session/sessionManager/sampling.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAE1C,MAAM,UAAU,SAAS;;IACvB,MAAM,cAAc,GAAG,CAAC,CAAC;IACzB,MAAM,eAAe,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC;IACpD,IAAI,YAAY,GACd,MAAA,MAAA,MAAA,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,OAAO,gEAAG,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,mCAAI,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,YAAY,mCAAI,cAAc,CAAC;IAE7G,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE,CAAC;QACrC,MAAM,aAAa,GAAG,CAAC,CAAC;QACxB,YAAY,GAAG,aAAa,CAAC;IAC/B,CAAC;IAED,OAAO,IAAI,CAAC,MAAM,EAAE,GAAG,YAAY,CAAC;AACtC,CAAC","sourcesContent":["import { faro } from '@grafana/faro-core';\n\nexport function isSampled(): boolean {\n const sendAllSignals = 1;\n const sessionTracking = faro.config.sessionTracking;\n let samplingRate =\n sessionTracking?.sampler?.({ metas: faro.metas.value }) ?? sessionTracking?.samplingRate ?? sendAllSignals;\n\n if (typeof samplingRate !== 'number') {\n const sendNoSignals = 0;\n samplingRate = sendNoSignals;\n }\n\n return Math.random() < samplingRate;\n}\n"]}
1
+ {"version":3,"file":"sampling.js","sourceRoot":"","sources":["../../../../../src/instrumentations/session/sessionManager/sampling.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAE7D,MAAM,UAAU,SAAS;;IACvB,MAAM,cAAc,GAAG,CAAC,CAAC;IACzB,MAAM,eAAe,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC;IACpD,MAAM,eAAe,GACnB,MAAA,MAAA,MAAA,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,OAAO,gEAAG,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,mCAAI,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,YAAY,mCAAI,cAAc,CAAC;IAC7G,MAAM,YAAY,GAAG,OAAO,eAAe,KAAK,QAAQ,CAAC,CAAC,CAAC,iBAAiB,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAElG,OAAO,IAAI,CAAC,MAAM,EAAE,GAAG,YAAY,CAAC;AACtC,CAAC","sourcesContent":["import { clampSamplingRate, faro } from '@grafana/faro-core';\n\nexport function isSampled(): boolean {\n const sendAllSignals = 1;\n const sessionTracking = faro.config.sessionTracking;\n const rawSamplingRate =\n sessionTracking?.sampler?.({ metas: faro.metas.value }) ?? sessionTracking?.samplingRate ?? sendAllSignals;\n const samplingRate = typeof rawSamplingRate === 'number' ? clampSamplingRate(rawSamplingRate) : 0;\n\n return Math.random() < samplingRate;\n}\n"]}
@@ -33,6 +33,5 @@ export function getUserActionNameFromElement(element, dataAttributeName) {
33
33
  }
34
34
  export function unsubscribeAllMonitors(allMonitorsSub) {
35
35
  allMonitorsSub === null || allMonitorsSub === void 0 ? void 0 : allMonitorsSub.unsubscribe();
36
- allMonitorsSub = undefined;
37
36
  }
38
37
  //# sourceMappingURL=processUserActionEventHandler.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"processUserActionEventHandler.js","sourceRoot":"","sources":["../../../../src/instrumentations/userActions/processUserActionEventHandler.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,6BAA6B,IAAI,uBAAuB,EAAE,MAAM,SAAS,CAAC;AACnF,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,wBAAwB,EAAE,MAAM,QAAQ,CAAC;AAElD,MAAM,UAAU,mBAAmB,CAAC,IAAU;IAC5C,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAE7B,SAAS,gBAAgB,CAAC,KAAmC;;QAC3D,MAAM,cAAc,GAAG,4BAA4B,CACjD,KAAK,CAAC,MAAqB,EAC3B,MAAA,MAAA,MAAM,CAAC,0BAA0B,0CAAE,iBAAiB,mCAAI,uBAAuB,CAChF,CAAC;QAEF,iCAAiC;QACjC,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,OAAO;QACT,CAAC;QAED,MAAM,UAAU,GAAG,GAAG,CAAC,eAAe,CAAC,cAAc,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QACxF,IAAI,UAAU,EAAE,CAAC;YACf,wBAAwB,CAAC,UAAU,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IAED,SAAS,wBAAwB,CAAC,UAA+B;QAC/D,MAAM,kBAAkB,GAAG,UAAoD,CAAC;QAChF,IAAI,oBAAoB,CAAC,kBAAkB,CAAC,CAAC,MAAM,EAAE,CAAC;IACxD,CAAC;IAED,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,OAAoB,EAAE,iBAAyB;IAC1F,MAAM,uBAAuB,GAAG,wBAAwB,CAAC,iBAAiB,CAAC,CAAC;IAC5E,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAEhC,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,IAAI,GAAG,KAAK,uBAAuB,EAAE,CAAC;YACpC,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,cAAwC;IAC7E,cAAc,aAAd,cAAc,uBAAd,cAAc,CAAE,WAAW,EAAE,CAAC;IAC9B,cAAc,GAAG,SAAS,CAAC;AAC7B,CAAC","sourcesContent":["import type { Faro, Subscription, UserActionInterface, UserActionInternalInterface } from '@grafana/faro-core';\n\nimport { userActionDataAttributeParsed as userActionDataAttribute } from './const';\nimport { UserActionController } from './userActionController';\nimport { convertDataAttributeName } from './util';\n\nexport function getUserEventHandler(faro: Faro) {\n const { api, config } = faro;\n\n function processUserEvent(event: PointerEvent | KeyboardEvent) {\n const userActionName = getUserActionNameFromElement(\n event.target as HTMLElement,\n config.userActionsInstrumentation?.dataAttributeName ?? userActionDataAttribute\n );\n\n // We don't have a data attribute\n if (!userActionName) {\n return;\n }\n\n const userAction = api.startUserAction(userActionName, {}, { triggerName: event.type });\n if (userAction) {\n processUserActionStarted(userAction);\n }\n }\n\n function processUserActionStarted(userAction: UserActionInterface) {\n const internalUserAction = userAction as unknown as UserActionInternalInterface;\n new UserActionController(internalUserAction).attach();\n }\n\n return { processUserEvent, processUserActionStarted };\n}\n\nexport function getUserActionNameFromElement(element: HTMLElement, dataAttributeName: string): string | undefined {\n const parsedDataAttributeName = convertDataAttributeName(dataAttributeName);\n const dataset = element.dataset;\n\n for (const key in dataset) {\n if (key === parsedDataAttributeName) {\n return dataset[key];\n }\n }\n\n return undefined;\n}\n\nexport function unsubscribeAllMonitors(allMonitorsSub: Subscription | undefined) {\n allMonitorsSub?.unsubscribe();\n allMonitorsSub = undefined;\n}\n"]}
1
+ {"version":3,"file":"processUserActionEventHandler.js","sourceRoot":"","sources":["../../../../src/instrumentations/userActions/processUserActionEventHandler.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,6BAA6B,IAAI,uBAAuB,EAAE,MAAM,SAAS,CAAC;AACnF,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,wBAAwB,EAAE,MAAM,QAAQ,CAAC;AAElD,MAAM,UAAU,mBAAmB,CAAC,IAAU;IAC5C,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAE7B,SAAS,gBAAgB,CAAC,KAAmC;;QAC3D,MAAM,cAAc,GAAG,4BAA4B,CACjD,KAAK,CAAC,MAAqB,EAC3B,MAAA,MAAA,MAAM,CAAC,0BAA0B,0CAAE,iBAAiB,mCAAI,uBAAuB,CAChF,CAAC;QAEF,iCAAiC;QACjC,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,OAAO;QACT,CAAC;QAED,MAAM,UAAU,GAAG,GAAG,CAAC,eAAe,CAAC,cAAc,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QACxF,IAAI,UAAU,EAAE,CAAC;YACf,wBAAwB,CAAC,UAAU,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IAED,SAAS,wBAAwB,CAAC,UAA+B;QAC/D,MAAM,kBAAkB,GAAG,UAAoD,CAAC;QAChF,IAAI,oBAAoB,CAAC,kBAAkB,CAAC,CAAC,MAAM,EAAE,CAAC;IACxD,CAAC;IAED,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,OAAoB,EAAE,iBAAyB;IAC1F,MAAM,uBAAuB,GAAG,wBAAwB,CAAC,iBAAiB,CAAC,CAAC;IAC5E,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAEhC,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,IAAI,GAAG,KAAK,uBAAuB,EAAE,CAAC;YACpC,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,cAAwC;IAC7E,cAAc,aAAd,cAAc,uBAAd,cAAc,CAAE,WAAW,EAAE,CAAC;AAChC,CAAC","sourcesContent":["import type { Faro, Subscription, UserActionInterface, UserActionInternalInterface } from '@grafana/faro-core';\n\nimport { userActionDataAttributeParsed as userActionDataAttribute } from './const';\nimport { UserActionController } from './userActionController';\nimport { convertDataAttributeName } from './util';\n\nexport function getUserEventHandler(faro: Faro) {\n const { api, config } = faro;\n\n function processUserEvent(event: PointerEvent | KeyboardEvent) {\n const userActionName = getUserActionNameFromElement(\n event.target as HTMLElement,\n config.userActionsInstrumentation?.dataAttributeName ?? userActionDataAttribute\n );\n\n // We don't have a data attribute\n if (!userActionName) {\n return;\n }\n\n const userAction = api.startUserAction(userActionName, {}, { triggerName: event.type });\n if (userAction) {\n processUserActionStarted(userAction);\n }\n }\n\n function processUserActionStarted(userAction: UserActionInterface) {\n const internalUserAction = userAction as unknown as UserActionInternalInterface;\n new UserActionController(internalUserAction).attach();\n }\n\n return { processUserEvent, processUserActionStarted };\n}\n\nexport function getUserActionNameFromElement(element: HTMLElement, dataAttributeName: string): string | undefined {\n const parsedDataAttributeName = convertDataAttributeName(dataAttributeName);\n const dataset = element.dataset;\n\n for (const key in dataset) {\n if (key === parsedDataAttributeName) {\n return dataset[key];\n }\n }\n\n return undefined;\n}\n\nexport function unsubscribeAllMonitors(allMonitorsSub: Subscription | undefined) {\n allMonitorsSub?.unsubscribe();\n}\n"]}
@@ -49,7 +49,7 @@ export class FetchTransport extends BaseTransport {
49
49
  this.logWarn(`Dropping transport item due to too many requests. Backoff until ${this.disabledUntil}`);
50
50
  return Promise.resolve();
51
51
  }
52
- yield this.promiseBuffer.add(() => {
52
+ yield this.promiseBuffer.add(() => __awaiter(this, void 0, void 0, function* () {
53
53
  const body = JSON.stringify(getTransportBody(items));
54
54
  const { url, requestOptions, apiKey } = this.options;
55
55
  const _a = requestOptions !== null && requestOptions !== void 0 ? requestOptions : {}, { headers = {} } = _a, restOfRequestOptions = __rest(_a, ["headers"]);
@@ -60,7 +60,7 @@ export class FetchTransport extends BaseTransport {
60
60
  }
61
61
  const resolvedHeaders = {};
62
62
  for (const [key, value] of Object.entries(headers)) {
63
- resolvedHeaders[key] = typeof value === 'function' ? value() : value;
63
+ resolvedHeaders[key] = typeof value === 'function' ? yield Promise.resolve(value()) : value;
64
64
  }
65
65
  return fetch(url, Object.assign({ method: 'POST', headers: Object.assign(Object.assign(Object.assign({ 'Content-Type': 'application/json' }, resolvedHeaders), (apiKey ? { 'x-api-key': apiKey } : {})), (sessionId ? { 'x-faro-session-id': sessionId } : {})), body, keepalive: body.length <= BEACON_BODY_SIZE_LIMIT }, (restOfRequestOptions !== null && restOfRequestOptions !== void 0 ? restOfRequestOptions : {})))
66
66
  .then((response) => __awaiter(this, void 0, void 0, function* () {
@@ -81,7 +81,7 @@ export class FetchTransport extends BaseTransport {
81
81
  .catch((err) => {
82
82
  this.logError('Failed sending payload to the receiver\n', JSON.parse(body), err);
83
83
  });
84
- });
84
+ }));
85
85
  }
86
86
  catch (err) {
87
87
  this.logError(err);
@@ -1 +1 @@
1
- {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../../../src/transports/fetch/transport.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseExtension, BaseTransport, createPromiseBuffer, getTransportBody, noop, VERSION } from '@grafana/faro-core';\nimport type { Config, Patterns, PromiseBuffer, TransportItem } from '@grafana/faro-core';\n\nimport { getSessionManagerByConfig } from '../../instrumentations/session/sessionManager';\nimport { getUserSessionUpdater } from '../../instrumentations/session/sessionManager/sessionManagerUtils';\n\nimport type { FetchTransportOptions } from './types';\n\nconst DEFAULT_BUFFER_SIZE = 30;\nconst DEFAULT_CONCURRENCY = 5; // chrome supports 10 total, firefox 17\nconst DEFAULT_RATE_LIMIT_BACKOFF_MS = 5000;\n\nconst BEACON_BODY_SIZE_LIMIT = 60000;\nconst TOO_MANY_REQUESTS = 429;\nconst ACCEPTED = 202;\n\nexport class FetchTransport extends BaseTransport {\n readonly name = '@grafana/faro-web-sdk:transport-fetch';\n readonly version = VERSION;\n\n promiseBuffer: PromiseBuffer<Response | void>;\n\n private readonly rateLimitBackoffMs: number;\n private readonly getNow: () => number;\n private disabledUntil: Date = new Date();\n\n constructor(private options: FetchTransportOptions) {\n super();\n\n this.rateLimitBackoffMs = options.defaultRateLimitBackoffMs ?? DEFAULT_RATE_LIMIT_BACKOFF_MS;\n this.getNow = options.getNow ?? (() => Date.now());\n\n this.promiseBuffer = createPromiseBuffer({\n size: options.bufferSize ?? DEFAULT_BUFFER_SIZE,\n concurrency: options.concurrency ?? DEFAULT_CONCURRENCY,\n });\n }\n\n async send(items: TransportItem[]): Promise<void> {\n try {\n if (this.disabledUntil > new Date(this.getNow())) {\n this.logWarn(`Dropping transport item due to too many requests. Backoff until ${this.disabledUntil}`);\n\n return Promise.resolve();\n }\n\n await this.promiseBuffer.add(() => {\n const body = JSON.stringify(getTransportBody(items));\n\n const { url, requestOptions, apiKey } = this.options;\n\n const { headers = {}, ...restOfRequestOptions } = requestOptions ?? {};\n\n let sessionId;\n const sessionMeta = this.metas.value.session;\n if (sessionMeta != null) {\n sessionId = sessionMeta.id;\n }\n\n const resolvedHeaders: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers)) {\n resolvedHeaders[key] = typeof value === 'function' ? value() : value;\n }\n\n return fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...resolvedHeaders,\n ...(apiKey ? { 'x-api-key': apiKey } : {}),\n ...(sessionId ? { 'x-faro-session-id': sessionId } : {}),\n },\n body,\n keepalive: body.length <= BEACON_BODY_SIZE_LIMIT,\n ...(restOfRequestOptions ?? {}),\n })\n .then(async (response) => {\n if (response.status === ACCEPTED) {\n const sessionExpired = response.headers.get('X-Faro-Session-Status') === 'invalid';\n\n if (sessionExpired) {\n this.extendFaroSession(this.config, this.logDebug);\n }\n }\n\n if (response.status === TOO_MANY_REQUESTS) {\n this.disabledUntil = this.getRetryAfterDate(response);\n this.logWarn(`Too many requests, backing off until ${this.disabledUntil}`);\n }\n\n // read the body so the connection can be closed\n response.text().catch(noop);\n return response;\n })\n .catch((err) => {\n this.logError('Failed sending payload to the receiver\\n', JSON.parse(body), err);\n });\n });\n } catch (err) {\n this.logError(err);\n }\n }\n\n override getIgnoreUrls(): Patterns {\n return ([this.options.url] as Patterns).concat(this.config.ignoreUrls ?? []);\n }\n\n override isBatched(): boolean {\n return true;\n }\n\n private getRetryAfterDate(response: Response): Date {\n const now = this.getNow();\n const retryAfterHeader = response.headers.get('Retry-After');\n\n if (retryAfterHeader) {\n const delay = Number(retryAfterHeader);\n\n if (!isNaN(delay)) {\n return new Date(delay * 1000 + now);\n }\n\n const date = Date.parse(retryAfterHeader);\n\n if (!isNaN(date)) {\n return new Date(date);\n }\n }\n\n return new Date(now + this.rateLimitBackoffMs);\n }\n\n private extendFaroSession(config: Config, logDebug: BaseExtension['logDebug']) {\n const SessionExpiredString = `Session expired`;\n\n const sessionTrackingConfig = config.sessionTracking;\n\n if (sessionTrackingConfig?.enabled) {\n const { fetchUserSession, storeUserSession } = getSessionManagerByConfig(sessionTrackingConfig);\n\n getUserSessionUpdater({ fetchUserSession, storeUserSession })({ forceSessionExtend: true });\n\n logDebug(`${SessionExpiredString} created new session.`);\n } else {\n logDebug(`${SessionExpiredString}.`);\n }\n }\n}\n"]}
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../../../src/transports/fetch/transport.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseExtension, BaseTransport, createPromiseBuffer, getTransportBody, noop, VERSION } from '@grafana/faro-core';\nimport type { Config, Patterns, PromiseBuffer, TransportItem } from '@grafana/faro-core';\n\nimport { getSessionManagerByConfig } from '../../instrumentations/session/sessionManager';\nimport { getUserSessionUpdater } from '../../instrumentations/session/sessionManager/sessionManagerUtils';\n\nimport type { FetchTransportOptions } from './types';\n\nconst DEFAULT_BUFFER_SIZE = 30;\nconst DEFAULT_CONCURRENCY = 5; // chrome supports 10 total, firefox 17\nconst DEFAULT_RATE_LIMIT_BACKOFF_MS = 5000;\n\nconst BEACON_BODY_SIZE_LIMIT = 60000;\nconst TOO_MANY_REQUESTS = 429;\nconst ACCEPTED = 202;\n\nexport class FetchTransport extends BaseTransport {\n readonly name = '@grafana/faro-web-sdk:transport-fetch';\n readonly version = VERSION;\n\n promiseBuffer: PromiseBuffer<Response | void>;\n\n private readonly rateLimitBackoffMs: number;\n private readonly getNow: () => number;\n private disabledUntil: Date = new Date();\n\n constructor(private options: FetchTransportOptions) {\n super();\n\n this.rateLimitBackoffMs = options.defaultRateLimitBackoffMs ?? DEFAULT_RATE_LIMIT_BACKOFF_MS;\n this.getNow = options.getNow ?? (() => Date.now());\n\n this.promiseBuffer = createPromiseBuffer({\n size: options.bufferSize ?? DEFAULT_BUFFER_SIZE,\n concurrency: options.concurrency ?? DEFAULT_CONCURRENCY,\n });\n }\n\n async send(items: TransportItem[]): Promise<void> {\n try {\n if (this.disabledUntil > new Date(this.getNow())) {\n this.logWarn(`Dropping transport item due to too many requests. Backoff until ${this.disabledUntil}`);\n\n return Promise.resolve();\n }\n\n await this.promiseBuffer.add(async () => {\n const body = JSON.stringify(getTransportBody(items));\n\n const { url, requestOptions, apiKey } = this.options;\n\n const { headers = {}, ...restOfRequestOptions } = requestOptions ?? {};\n\n let sessionId;\n const sessionMeta = this.metas.value.session;\n if (sessionMeta != null) {\n sessionId = sessionMeta.id;\n }\n\n const resolvedHeaders: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers)) {\n resolvedHeaders[key] = typeof value === 'function' ? await Promise.resolve(value()) : value;\n }\n\n return fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...resolvedHeaders,\n ...(apiKey ? { 'x-api-key': apiKey } : {}),\n ...(sessionId ? { 'x-faro-session-id': sessionId } : {}),\n },\n body,\n keepalive: body.length <= BEACON_BODY_SIZE_LIMIT,\n ...(restOfRequestOptions ?? {}),\n })\n .then(async (response) => {\n if (response.status === ACCEPTED) {\n const sessionExpired = response.headers.get('X-Faro-Session-Status') === 'invalid';\n\n if (sessionExpired) {\n this.extendFaroSession(this.config, this.logDebug);\n }\n }\n\n if (response.status === TOO_MANY_REQUESTS) {\n this.disabledUntil = this.getRetryAfterDate(response);\n this.logWarn(`Too many requests, backing off until ${this.disabledUntil}`);\n }\n\n // read the body so the connection can be closed\n response.text().catch(noop);\n return response;\n })\n .catch((err) => {\n this.logError('Failed sending payload to the receiver\\n', JSON.parse(body), err);\n });\n });\n } catch (err) {\n this.logError(err);\n }\n }\n\n override getIgnoreUrls(): Patterns {\n return ([this.options.url] as Patterns).concat(this.config.ignoreUrls ?? []);\n }\n\n override isBatched(): boolean {\n return true;\n }\n\n private getRetryAfterDate(response: Response): Date {\n const now = this.getNow();\n const retryAfterHeader = response.headers.get('Retry-After');\n\n if (retryAfterHeader) {\n const delay = Number(retryAfterHeader);\n\n if (!isNaN(delay)) {\n return new Date(delay * 1000 + now);\n }\n\n const date = Date.parse(retryAfterHeader);\n\n if (!isNaN(date)) {\n return new Date(date);\n }\n }\n\n return new Date(now + this.rateLimitBackoffMs);\n }\n\n private extendFaroSession(config: Config, logDebug: BaseExtension['logDebug']) {\n const SessionExpiredString = `Session expired`;\n\n const sessionTrackingConfig = config.sessionTracking;\n\n if (sessionTrackingConfig?.enabled) {\n const { fetchUserSession, storeUserSession } = getSessionManagerByConfig(sessionTrackingConfig);\n\n getUserSessionUpdater({ fetchUserSession, storeUserSession })({ forceSessionExtend: true });\n\n logDebug(`${SessionExpiredString} created new session.`);\n } else {\n logDebug(`${SessionExpiredString}.`);\n }\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/transports/fetch/types.ts"],"names":[],"mappings":"","sourcesContent":["export interface FetchTransportRequestOptions extends Omit<RequestInit, 'body' | 'headers'> {\n /**\n * Headers to include in every request.\n * Each value can be:\n * - a string (static value)\n * - a function returning a string (dynamic value)\n */\n headers?: Record<string, string | (() => string)>;\n}\n\nexport interface FetchTransportOptions {\n // url of the collector endpoint\n url: string;\n\n // will be added as `x-api-key` header\n apiKey?: string;\n // how many requests to buffer in total\n bufferSize?: number;\n // how many requests to execute concurrently\n concurrency?: number;\n // if rate limit response does not include a Retry-After header,\n // how many milliseconds to back off before attempting a request.\n // intermediate events will be dropped, not buffered\n defaultRateLimitBackoffMs?: number;\n // get current date. for mocking purposes in tests\n getNow?: ClockFn;\n // addition options for global.Fetch\n requestOptions?: FetchTransportRequestOptions;\n}\n\nexport type ClockFn = () => number;\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/transports/fetch/types.ts"],"names":[],"mappings":"","sourcesContent":["export interface FetchTransportRequestOptions extends Omit<RequestInit, 'body' | 'headers'> {\n /**\n * Headers to include in every request.\n * Each value can be:\n * - a string (static value)\n * - a function returning a string (dynamic value, sync)\n * - a function returning a Promise of string (dynamic value, async)\n */\n headers?: Record<string, string | (() => string | Promise<string>)>;\n}\n\nexport interface FetchTransportOptions {\n // url of the collector endpoint\n url: string;\n\n // will be added as `x-api-key` header\n apiKey?: string;\n // how many requests to buffer in total\n bufferSize?: number;\n // how many requests to execute concurrently\n concurrency?: number;\n // if rate limit response does not include a Retry-After header,\n // how many milliseconds to back off before attempting a request.\n // intermediate events will be dropped, not buffered\n defaultRateLimitBackoffMs?: number;\n // get current date. for mocking purposes in tests\n getNow?: ClockFn;\n // addition options for global.Fetch\n requestOptions?: FetchTransportRequestOptions;\n}\n\nexport type ClockFn = () => number;\n"]}
@@ -1,7 +1,7 @@
1
1
  import { BaseInstrumentation, LogLevel } from '@grafana/faro-core';
2
2
  export declare class ConsoleInstrumentation extends BaseInstrumentation {
3
3
  readonly name = "@grafana/faro-web-sdk:instrumentation-console";
4
- readonly version = "2.2.3";
4
+ readonly version = "2.3.0";
5
5
  static defaultDisabledLevels: LogLevel[];
6
6
  static consoleErrorPrefix: string;
7
7
  private errorSerializer;
@@ -2,7 +2,7 @@ import { BaseInstrumentation } from '@grafana/faro-core';
2
2
  import type { Instrumentation } from '@grafana/faro-core';
3
3
  export declare class CSPInstrumentation extends BaseInstrumentation implements Instrumentation {
4
4
  readonly name = "@grafana/faro-web-sdk:instrumentation-csp";
5
- readonly version = "2.2.3";
5
+ readonly version = "2.3.0";
6
6
  constructor();
7
7
  initialize(): void;
8
8
  destroy(): void;
@@ -1,6 +1,6 @@
1
1
  import { BaseInstrumentation } from '@grafana/faro-core';
2
2
  export declare class ErrorsInstrumentation extends BaseInstrumentation {
3
3
  readonly name = "@grafana/faro-web-sdk:instrumentation-errors";
4
- readonly version = "2.2.3";
4
+ readonly version = "2.3.0";
5
5
  initialize(): void;
6
6
  }
@@ -1,6 +1,6 @@
1
1
  import { BaseInstrumentation } from '@grafana/faro-core';
2
2
  export declare class NavigationInstrumentation extends BaseInstrumentation {
3
3
  readonly name = "@grafana/faro-web-sdk:instrumentation-navigation";
4
- readonly version = "2.2.3";
4
+ readonly version = "2.3.0";
5
5
  initialize(): void;
6
6
  }
@@ -3,6 +3,6 @@ import type { ResourceEntryMessage } from './types';
3
3
  export declare const performanceEntriesSubscription: Observable<ResourceEntryMessage>;
4
4
  export declare class PerformanceInstrumentation extends BaseInstrumentation {
5
5
  readonly name = "@grafana/faro-web-sdk:instrumentation-performance";
6
- readonly version = "2.2.3";
6
+ readonly version = "2.3.0";
7
7
  initialize(): void;
8
8
  }
@@ -1,7 +1,7 @@
1
1
  import { BaseInstrumentation } from '@grafana/faro-core';
2
2
  export declare class SessionInstrumentation extends BaseInstrumentation {
3
3
  readonly name = "@grafana/faro-web-sdk:instrumentation-session";
4
- readonly version = "2.2.3";
4
+ readonly version = "2.3.0";
5
5
  private notifiedSession;
6
6
  private sendSessionStartEvent;
7
7
  private createInitialSession;
@@ -1,7 +1,7 @@
1
1
  import { BaseInstrumentation } from '@grafana/faro-core';
2
2
  export declare class UserActionInstrumentation extends BaseInstrumentation {
3
3
  readonly name = "@grafana/faro-web-sdk:instrumentation-user-action";
4
- readonly version = "2.2.3";
4
+ readonly version = "2.3.0";
5
5
  private _userActionSub?;
6
6
  initialize(): void;
7
7
  destroy(): void;
@@ -1,7 +1,7 @@
1
1
  import { BaseInstrumentation } from '@grafana/faro-core';
2
2
  export declare class ViewInstrumentation extends BaseInstrumentation {
3
3
  readonly name = "@grafana/faro-web-sdk:instrumentation-view";
4
- readonly version = "2.2.3";
4
+ readonly version = "2.3.0";
5
5
  private notifiedView;
6
6
  private sendViewChangedEvent;
7
7
  initialize(): void;
@@ -1,6 +1,6 @@
1
1
  import { BaseInstrumentation } from '@grafana/faro-core';
2
2
  export declare class WebVitalsInstrumentation extends BaseInstrumentation {
3
3
  readonly name = "@grafana/faro-web-sdk:instrumentation-web-vitals";
4
- readonly version = "2.2.3";
4
+ readonly version = "2.3.0";
5
5
  initialize(): void;
6
6
  }
@@ -4,7 +4,7 @@ import type { ConsoleTransportOptions } from './types';
4
4
  export declare class ConsoleTransport extends BaseTransport {
5
5
  private options;
6
6
  readonly name = "@grafana/faro-web-sdk:transport-console";
7
- readonly version = "2.2.3";
7
+ readonly version = "2.3.0";
8
8
  constructor(options?: ConsoleTransportOptions);
9
9
  send(item: TransportItem): void;
10
10
  }
@@ -4,7 +4,7 @@ import type { FetchTransportOptions } from './types';
4
4
  export declare class FetchTransport extends BaseTransport {
5
5
  private options;
6
6
  readonly name = "@grafana/faro-web-sdk:transport-fetch";
7
- readonly version = "2.2.3";
7
+ readonly version = "2.3.0";
8
8
  promiseBuffer: PromiseBuffer<Response | void>;
9
9
  private readonly rateLimitBackoffMs;
10
10
  private readonly getNow;