@loggerjs/browser 0.5.0 → 0.5.2
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.
- package/dist/broadcast-channel-transport.cjs +115 -0
- package/dist/broadcast-channel-transport.cjs.map +1 -0
- package/dist/broadcast-channel-transport.js +114 -0
- package/dist/broadcast-channel-transport.js.map +1 -0
- package/dist/console-integration.cjs +98 -0
- package/dist/console-integration.cjs.map +1 -0
- package/dist/console-integration.js +97 -0
- package/dist/console-integration.js.map +1 -0
- package/dist/context-propagation-integration.cjs +78 -0
- package/dist/context-propagation-integration.cjs.map +1 -0
- package/dist/context-propagation-integration.js +77 -0
- package/dist/context-propagation-integration.js.map +1 -0
- package/dist/error-integration.cjs +128 -0
- package/dist/error-integration.cjs.map +1 -0
- package/dist/error-integration.js +127 -0
- package/dist/error-integration.js.map +1 -0
- package/dist/fetch-integration.cjs +120 -0
- package/dist/fetch-integration.cjs.map +1 -0
- package/dist/fetch-integration.js +119 -0
- package/dist/fetch-integration.js.map +1 -0
- package/dist/framework-error-integration.cjs +102 -0
- package/dist/framework-error-integration.cjs.map +1 -0
- package/dist/framework-error-integration.js +101 -0
- package/dist/framework-error-integration.js.map +1 -0
- package/dist/framework-router-integrations.cjs +88 -0
- package/dist/framework-router-integrations.cjs.map +1 -0
- package/dist/framework-router-integrations.js +84 -0
- package/dist/framework-router-integrations.js.map +1 -0
- package/dist/http-transport.cjs +301 -0
- package/dist/http-transport.cjs.map +1 -0
- package/dist/http-transport.js +299 -0
- package/dist/http-transport.js.map +1 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/indexeddb-offline-queue.cjs +105 -0
- package/dist/indexeddb-offline-queue.cjs.map +1 -0
- package/dist/indexeddb-offline-queue.js +104 -0
- package/dist/indexeddb-offline-queue.js.map +1 -0
- package/dist/indexeddb-transport.cjs +531 -0
- package/dist/indexeddb-transport.cjs.map +1 -0
- package/dist/indexeddb-transport.js +530 -0
- package/dist/indexeddb-transport.js.map +1 -0
- package/dist/offline-first-transport.cjs +675 -0
- package/dist/offline-first-transport.cjs.map +1 -0
- package/dist/offline-first-transport.js +674 -0
- package/dist/offline-first-transport.js.map +1 -0
- package/dist/page-lifecycle.cjs +39 -0
- package/dist/page-lifecycle.cjs.map +1 -0
- package/dist/page-lifecycle.js +38 -0
- package/dist/page-lifecycle.js.map +1 -0
- package/dist/payload-transforms.cjs +30 -0
- package/dist/payload-transforms.cjs.map +1 -0
- package/dist/payload-transforms.js +29 -0
- package/dist/payload-transforms.js.map +1 -0
- package/dist/performance-integration.cjs +135 -0
- package/dist/performance-integration.cjs.map +1 -0
- package/dist/performance-integration.js +133 -0
- package/dist/performance-integration.js.map +1 -0
- package/dist/reporting-integration.cjs +110 -0
- package/dist/reporting-integration.cjs.map +1 -0
- package/dist/reporting-integration.js +109 -0
- package/dist/reporting-integration.js.map +1 -0
- package/dist/router-integration.cjs +97 -0
- package/dist/router-integration.cjs.map +1 -0
- package/dist/router-integration.js +96 -0
- package/dist/router-integration.js.map +1 -0
- package/dist/runtime-host-integration.cjs +181 -0
- package/dist/runtime-host-integration.cjs.map +1 -0
- package/dist/runtime-host-integration.js +180 -0
- package/dist/runtime-host-integration.js.map +1 -0
- package/dist/service-worker-integration.cjs +109 -0
- package/dist/service-worker-integration.cjs.map +1 -0
- package/dist/service-worker-integration.js +108 -0
- package/dist/service-worker-integration.js.map +1 -0
- package/dist/service-worker-transport.cjs +184 -0
- package/dist/service-worker-transport.cjs.map +1 -0
- package/dist/service-worker-transport.js +183 -0
- package/dist/service-worker-transport.js.map +1 -0
- package/dist/user-action-integration.cjs +100 -0
- package/dist/user-action-integration.cjs.map +1 -0
- package/dist/user-action-integration.js +99 -0
- package/dist/user-action-integration.js.map +1 -0
- package/dist/web-vitals-integration.cjs +157 -0
- package/dist/web-vitals-integration.cjs.map +1 -0
- package/dist/web-vitals-integration.js +156 -0
- package/dist/web-vitals-integration.js.map +1 -0
- package/dist/websocket-integration.cjs +158 -0
- package/dist/websocket-integration.cjs.map +1 -0
- package/dist/websocket-integration.js +157 -0
- package/dist/websocket-integration.js.map +1 -0
- package/dist/websocket-transport.cjs +187 -0
- package/dist/websocket-transport.cjs.map +1 -0
- package/dist/websocket-transport.js +186 -0
- package/dist/websocket-transport.js.map +1 -0
- package/dist/xhr-integration.cjs +107 -0
- package/dist/xhr-integration.cjs.map +1 -0
- package/dist/xhr-integration.js +106 -0
- package/dist/xhr-integration.js.map +1 -0
- package/dist/zip-export.cjs +241 -0
- package/dist/zip-export.cjs.map +1 -0
- package/dist/zip-export.js +238 -0
- package/dist/zip-export.js.map +1 -0
- package/package.json +104 -77
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
let _loggerjs_core = require("@loggerjs/core");
|
|
3
|
+
//#region src/broadcast-channel-transport.ts
|
|
4
|
+
let sourceSequence = 0;
|
|
5
|
+
function createSourceId() {
|
|
6
|
+
sourceSequence += 1;
|
|
7
|
+
return `loggerjs-${Date.now().toString(36)}-${sourceSequence.toString(36)}`;
|
|
8
|
+
}
|
|
9
|
+
function defaultChannelFactory(channelName) {
|
|
10
|
+
if (typeof BroadcastChannel === "undefined") throw new Error("BroadcastChannel is not available");
|
|
11
|
+
return new BroadcastChannel(channelName);
|
|
12
|
+
}
|
|
13
|
+
function defaultMapEvent(event, context) {
|
|
14
|
+
return {
|
|
15
|
+
type: "loggerjs.event",
|
|
16
|
+
source: context.source,
|
|
17
|
+
event
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function defaultMapBatch(events, context) {
|
|
21
|
+
return {
|
|
22
|
+
type: "loggerjs.batch",
|
|
23
|
+
source: context.source,
|
|
24
|
+
events
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function browserBroadcastChannelTransport(options) {
|
|
28
|
+
const transportName = options.name ?? "browser-broadcast-channel";
|
|
29
|
+
const source = options.source ?? createSourceId();
|
|
30
|
+
const mapContext = {
|
|
31
|
+
channelName: options.channelName,
|
|
32
|
+
source
|
|
33
|
+
};
|
|
34
|
+
const mapEvent = options.mapEvent ?? defaultMapEvent;
|
|
35
|
+
const mapBatch = options.mapBatch ?? defaultMapBatch;
|
|
36
|
+
const channelFactory = options.channelFactory ?? defaultChannelFactory;
|
|
37
|
+
const closeChannelOnClose = options.closeChannelOnClose ?? true;
|
|
38
|
+
let channel;
|
|
39
|
+
let closed = false;
|
|
40
|
+
const reportError = (error, context, detail) => {
|
|
41
|
+
if (detail.droppedEvents > 0) {
|
|
42
|
+
(0, _loggerjs_core.incrementLoggerMetaCounter)("transport.dropped", detail.droppedEvents);
|
|
43
|
+
(0, _loggerjs_core.incrementLoggerMetaCounter)(`transport.dropped.${detail.operation}`, detail.droppedEvents);
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
options.onError?.(error, detail);
|
|
47
|
+
} catch (onErrorError) {
|
|
48
|
+
context?.reportInternalError(onErrorError, {
|
|
49
|
+
operation: "on-error",
|
|
50
|
+
phase: "transport",
|
|
51
|
+
transport: transportName
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
context?.reportInternalError(error, {
|
|
55
|
+
operation: detail.operation,
|
|
56
|
+
phase: "transport",
|
|
57
|
+
transport: transportName
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
const getChannel = (context) => {
|
|
61
|
+
if (closed) return void 0;
|
|
62
|
+
if (channel) return channel;
|
|
63
|
+
try {
|
|
64
|
+
channel = channelFactory(options.channelName);
|
|
65
|
+
return channel;
|
|
66
|
+
} catch (error) {
|
|
67
|
+
reportError(error, context, {
|
|
68
|
+
droppedEvents: 1,
|
|
69
|
+
operation: "create-channel"
|
|
70
|
+
});
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
const postMessage = (message, context, droppedEvents) => {
|
|
75
|
+
const currentChannel = getChannel(context);
|
|
76
|
+
if (!currentChannel) return;
|
|
77
|
+
try {
|
|
78
|
+
currentChannel.postMessage(message);
|
|
79
|
+
} catch (error) {
|
|
80
|
+
reportError(error, context, {
|
|
81
|
+
droppedEvents,
|
|
82
|
+
operation: "post-message"
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
return {
|
|
87
|
+
name: transportName,
|
|
88
|
+
minLevel: options.minLevel,
|
|
89
|
+
log(event, context) {
|
|
90
|
+
postMessage(mapEvent(event, mapContext), context, 1);
|
|
91
|
+
},
|
|
92
|
+
logBatch(events, context) {
|
|
93
|
+
if (events.length === 0) return;
|
|
94
|
+
postMessage(mapBatch(events, mapContext), context, events.length);
|
|
95
|
+
},
|
|
96
|
+
async close() {
|
|
97
|
+
closed = true;
|
|
98
|
+
if (!channel || !closeChannelOnClose) return;
|
|
99
|
+
try {
|
|
100
|
+
channel.close?.();
|
|
101
|
+
} catch (error) {
|
|
102
|
+
reportError(error, void 0, {
|
|
103
|
+
droppedEvents: 0,
|
|
104
|
+
operation: "close-channel"
|
|
105
|
+
});
|
|
106
|
+
} finally {
|
|
107
|
+
channel = void 0;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
//#endregion
|
|
113
|
+
exports.browserBroadcastChannelTransport = browserBroadcastChannelTransport;
|
|
114
|
+
|
|
115
|
+
//# sourceMappingURL=broadcast-channel-transport.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"broadcast-channel-transport.cjs","names":[],"sources":["../src/broadcast-channel-transport.ts"],"sourcesContent":["import {\n incrementLoggerMetaCounter,\n type LogEvent,\n type LoggerLevel,\n type Transport,\n type TransportContext,\n} from \"@loggerjs/core\";\n\nexport interface BrowserBroadcastChannelLike {\n postMessage: (message: unknown) => void;\n close?: () => void;\n}\n\nexport type BrowserBroadcastChannelFactory = (channelName: string) => BrowserBroadcastChannelLike;\n\nexport interface BrowserBroadcastChannelEventMessage {\n type: \"loggerjs.event\";\n source: string;\n event: LogEvent;\n}\n\nexport interface BrowserBroadcastChannelBatchMessage {\n type: \"loggerjs.batch\";\n source: string;\n events: readonly LogEvent[];\n}\n\nexport type BrowserBroadcastChannelMessage =\n | BrowserBroadcastChannelEventMessage\n | BrowserBroadcastChannelBatchMessage;\n\nexport interface BrowserBroadcastChannelMapContext {\n channelName: string;\n source: string;\n}\n\nexport interface BrowserBroadcastChannelErrorDetail {\n operation: \"create-channel\" | \"post-message\" | \"close-channel\" | \"on-error\";\n droppedEvents: number;\n}\n\nexport interface BrowserBroadcastChannelTransportOptions {\n channelName: string;\n name?: string;\n source?: string;\n minLevel?: LoggerLevel;\n channelFactory?: BrowserBroadcastChannelFactory;\n closeChannelOnClose?: boolean;\n mapEvent?: (event: LogEvent, context: BrowserBroadcastChannelMapContext) => unknown;\n mapBatch?: (events: readonly LogEvent[], context: BrowserBroadcastChannelMapContext) => unknown;\n onError?: (error: unknown, detail: BrowserBroadcastChannelErrorDetail) => void;\n}\n\nlet sourceSequence = 0;\n\nfunction createSourceId() {\n sourceSequence += 1;\n return `loggerjs-${Date.now().toString(36)}-${sourceSequence.toString(36)}`;\n}\n\nfunction defaultChannelFactory(channelName: string): BrowserBroadcastChannelLike {\n if (typeof BroadcastChannel === \"undefined\") {\n throw new Error(\"BroadcastChannel is not available\");\n }\n return new BroadcastChannel(channelName);\n}\n\nfunction defaultMapEvent(\n event: LogEvent,\n context: BrowserBroadcastChannelMapContext,\n): BrowserBroadcastChannelEventMessage {\n return { type: \"loggerjs.event\", source: context.source, event };\n}\n\nfunction defaultMapBatch(\n events: readonly LogEvent[],\n context: BrowserBroadcastChannelMapContext,\n): BrowserBroadcastChannelBatchMessage {\n return { type: \"loggerjs.batch\", source: context.source, events };\n}\n\nexport function browserBroadcastChannelTransport(\n options: BrowserBroadcastChannelTransportOptions,\n): Transport {\n const transportName = options.name ?? \"browser-broadcast-channel\";\n const source = options.source ?? createSourceId();\n const mapContext: BrowserBroadcastChannelMapContext = {\n channelName: options.channelName,\n source,\n };\n const mapEvent = options.mapEvent ?? defaultMapEvent;\n const mapBatch = options.mapBatch ?? defaultMapBatch;\n const channelFactory = options.channelFactory ?? defaultChannelFactory;\n const closeChannelOnClose = options.closeChannelOnClose ?? true;\n let channel: BrowserBroadcastChannelLike | undefined;\n let closed = false;\n\n const reportError = (\n error: unknown,\n context: TransportContext | undefined,\n detail: BrowserBroadcastChannelErrorDetail,\n ) => {\n if (detail.droppedEvents > 0) {\n incrementLoggerMetaCounter(\"transport.dropped\", detail.droppedEvents);\n incrementLoggerMetaCounter(`transport.dropped.${detail.operation}`, detail.droppedEvents);\n }\n\n try {\n options.onError?.(error, detail);\n } catch (onErrorError) {\n context?.reportInternalError(onErrorError, {\n operation: \"on-error\",\n phase: \"transport\",\n transport: transportName,\n });\n }\n\n context?.reportInternalError(error, {\n operation: detail.operation,\n phase: \"transport\",\n transport: transportName,\n });\n };\n\n const getChannel = (context: TransportContext) => {\n if (closed) return undefined;\n if (channel) return channel;\n try {\n channel = channelFactory(options.channelName);\n return channel;\n } catch (error) {\n reportError(error, context, {\n droppedEvents: 1,\n operation: \"create-channel\",\n });\n return undefined;\n }\n };\n\n const postMessage = (message: unknown, context: TransportContext, droppedEvents: number) => {\n const currentChannel = getChannel(context);\n if (!currentChannel) return;\n try {\n // oxlint-disable-next-line require-post-message-target-origin -- BroadcastChannel.postMessage does not accept targetOrigin.\n currentChannel.postMessage(message);\n } catch (error) {\n reportError(error, context, {\n droppedEvents,\n operation: \"post-message\",\n });\n }\n };\n\n return {\n name: transportName,\n minLevel: options.minLevel,\n log(event, context) {\n postMessage(mapEvent(event, mapContext), context, 1);\n },\n logBatch(events, context) {\n if (events.length === 0) return;\n postMessage(mapBatch(events, mapContext), context, events.length);\n },\n async close() {\n closed = true;\n if (!channel || !closeChannelOnClose) return;\n try {\n channel.close?.();\n } catch (error) {\n reportError(error, undefined, {\n droppedEvents: 0,\n operation: \"close-channel\",\n });\n } finally {\n channel = undefined;\n }\n },\n };\n}\n"],"mappings":";;;AAqDA,IAAI,iBAAiB;AAErB,SAAS,iBAAiB;CACxB,kBAAkB;CAClB,OAAO,YAAY,KAAK,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,GAAG,eAAe,SAAS,EAAE;AAC1E;AAEA,SAAS,sBAAsB,aAAkD;CAC/E,IAAI,OAAO,qBAAqB,aAC9B,MAAM,IAAI,MAAM,mCAAmC;CAErD,OAAO,IAAI,iBAAiB,WAAW;AACzC;AAEA,SAAS,gBACP,OACA,SACqC;CACrC,OAAO;EAAE,MAAM;EAAkB,QAAQ,QAAQ;EAAQ;CAAM;AACjE;AAEA,SAAS,gBACP,QACA,SACqC;CACrC,OAAO;EAAE,MAAM;EAAkB,QAAQ,QAAQ;EAAQ;CAAO;AAClE;AAEA,SAAgB,iCACd,SACW;CACX,MAAM,gBAAgB,QAAQ,QAAQ;CACtC,MAAM,SAAS,QAAQ,UAAU,eAAe;CAChD,MAAM,aAAgD;EACpD,aAAa,QAAQ;EACrB;CACF;CACA,MAAM,WAAW,QAAQ,YAAY;CACrC,MAAM,WAAW,QAAQ,YAAY;CACrC,MAAM,iBAAiB,QAAQ,kBAAkB;CACjD,MAAM,sBAAsB,QAAQ,uBAAuB;CAC3D,IAAI;CACJ,IAAI,SAAS;CAEb,MAAM,eACJ,OACA,SACA,WACG;EACH,IAAI,OAAO,gBAAgB,GAAG;GAC5B,CAAA,GAAA,eAAA,2BAAA,CAA2B,qBAAqB,OAAO,aAAa;GACpE,CAAA,GAAA,eAAA,2BAAA,CAA2B,qBAAqB,OAAO,aAAa,OAAO,aAAa;EAC1F;EAEA,IAAI;GACF,QAAQ,UAAU,OAAO,MAAM;EACjC,SAAS,cAAc;GACrB,SAAS,oBAAoB,cAAc;IACzC,WAAW;IACX,OAAO;IACP,WAAW;GACb,CAAC;EACH;EAEA,SAAS,oBAAoB,OAAO;GAClC,WAAW,OAAO;GAClB,OAAO;GACP,WAAW;EACb,CAAC;CACH;CAEA,MAAM,cAAc,YAA8B;EAChD,IAAI,QAAQ,OAAO,KAAA;EACnB,IAAI,SAAS,OAAO;EACpB,IAAI;GACF,UAAU,eAAe,QAAQ,WAAW;GAC5C,OAAO;EACT,SAAS,OAAO;GACd,YAAY,OAAO,SAAS;IAC1B,eAAe;IACf,WAAW;GACb,CAAC;GACD;EACF;CACF;CAEA,MAAM,eAAe,SAAkB,SAA2B,kBAA0B;EAC1F,MAAM,iBAAiB,WAAW,OAAO;EACzC,IAAI,CAAC,gBAAgB;EACrB,IAAI;GAEF,eAAe,YAAY,OAAO;EACpC,SAAS,OAAO;GACd,YAAY,OAAO,SAAS;IAC1B;IACA,WAAW;GACb,CAAC;EACH;CACF;CAEA,OAAO;EACL,MAAM;EACN,UAAU,QAAQ;EAClB,IAAI,OAAO,SAAS;GAClB,YAAY,SAAS,OAAO,UAAU,GAAG,SAAS,CAAC;EACrD;EACA,SAAS,QAAQ,SAAS;GACxB,IAAI,OAAO,WAAW,GAAG;GACzB,YAAY,SAAS,QAAQ,UAAU,GAAG,SAAS,OAAO,MAAM;EAClE;EACA,MAAM,QAAQ;GACZ,SAAS;GACT,IAAI,CAAC,WAAW,CAAC,qBAAqB;GACtC,IAAI;IACF,QAAQ,QAAQ;GAClB,SAAS,OAAO;IACd,YAAY,OAAO,KAAA,GAAW;KAC5B,eAAe;KACf,WAAW;IACb,CAAC;GACH,UAAU;IACR,UAAU,KAAA;GACZ;EACF;CACF;AACF"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { incrementLoggerMetaCounter } from "@loggerjs/core";
|
|
2
|
+
//#region src/broadcast-channel-transport.ts
|
|
3
|
+
let sourceSequence = 0;
|
|
4
|
+
function createSourceId() {
|
|
5
|
+
sourceSequence += 1;
|
|
6
|
+
return `loggerjs-${Date.now().toString(36)}-${sourceSequence.toString(36)}`;
|
|
7
|
+
}
|
|
8
|
+
function defaultChannelFactory(channelName) {
|
|
9
|
+
if (typeof BroadcastChannel === "undefined") throw new Error("BroadcastChannel is not available");
|
|
10
|
+
return new BroadcastChannel(channelName);
|
|
11
|
+
}
|
|
12
|
+
function defaultMapEvent(event, context) {
|
|
13
|
+
return {
|
|
14
|
+
type: "loggerjs.event",
|
|
15
|
+
source: context.source,
|
|
16
|
+
event
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function defaultMapBatch(events, context) {
|
|
20
|
+
return {
|
|
21
|
+
type: "loggerjs.batch",
|
|
22
|
+
source: context.source,
|
|
23
|
+
events
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function browserBroadcastChannelTransport(options) {
|
|
27
|
+
const transportName = options.name ?? "browser-broadcast-channel";
|
|
28
|
+
const source = options.source ?? createSourceId();
|
|
29
|
+
const mapContext = {
|
|
30
|
+
channelName: options.channelName,
|
|
31
|
+
source
|
|
32
|
+
};
|
|
33
|
+
const mapEvent = options.mapEvent ?? defaultMapEvent;
|
|
34
|
+
const mapBatch = options.mapBatch ?? defaultMapBatch;
|
|
35
|
+
const channelFactory = options.channelFactory ?? defaultChannelFactory;
|
|
36
|
+
const closeChannelOnClose = options.closeChannelOnClose ?? true;
|
|
37
|
+
let channel;
|
|
38
|
+
let closed = false;
|
|
39
|
+
const reportError = (error, context, detail) => {
|
|
40
|
+
if (detail.droppedEvents > 0) {
|
|
41
|
+
incrementLoggerMetaCounter("transport.dropped", detail.droppedEvents);
|
|
42
|
+
incrementLoggerMetaCounter(`transport.dropped.${detail.operation}`, detail.droppedEvents);
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
options.onError?.(error, detail);
|
|
46
|
+
} catch (onErrorError) {
|
|
47
|
+
context?.reportInternalError(onErrorError, {
|
|
48
|
+
operation: "on-error",
|
|
49
|
+
phase: "transport",
|
|
50
|
+
transport: transportName
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
context?.reportInternalError(error, {
|
|
54
|
+
operation: detail.operation,
|
|
55
|
+
phase: "transport",
|
|
56
|
+
transport: transportName
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
const getChannel = (context) => {
|
|
60
|
+
if (closed) return void 0;
|
|
61
|
+
if (channel) return channel;
|
|
62
|
+
try {
|
|
63
|
+
channel = channelFactory(options.channelName);
|
|
64
|
+
return channel;
|
|
65
|
+
} catch (error) {
|
|
66
|
+
reportError(error, context, {
|
|
67
|
+
droppedEvents: 1,
|
|
68
|
+
operation: "create-channel"
|
|
69
|
+
});
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
const postMessage = (message, context, droppedEvents) => {
|
|
74
|
+
const currentChannel = getChannel(context);
|
|
75
|
+
if (!currentChannel) return;
|
|
76
|
+
try {
|
|
77
|
+
currentChannel.postMessage(message);
|
|
78
|
+
} catch (error) {
|
|
79
|
+
reportError(error, context, {
|
|
80
|
+
droppedEvents,
|
|
81
|
+
operation: "post-message"
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
return {
|
|
86
|
+
name: transportName,
|
|
87
|
+
minLevel: options.minLevel,
|
|
88
|
+
log(event, context) {
|
|
89
|
+
postMessage(mapEvent(event, mapContext), context, 1);
|
|
90
|
+
},
|
|
91
|
+
logBatch(events, context) {
|
|
92
|
+
if (events.length === 0) return;
|
|
93
|
+
postMessage(mapBatch(events, mapContext), context, events.length);
|
|
94
|
+
},
|
|
95
|
+
async close() {
|
|
96
|
+
closed = true;
|
|
97
|
+
if (!channel || !closeChannelOnClose) return;
|
|
98
|
+
try {
|
|
99
|
+
channel.close?.();
|
|
100
|
+
} catch (error) {
|
|
101
|
+
reportError(error, void 0, {
|
|
102
|
+
droppedEvents: 0,
|
|
103
|
+
operation: "close-channel"
|
|
104
|
+
});
|
|
105
|
+
} finally {
|
|
106
|
+
channel = void 0;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
//#endregion
|
|
112
|
+
export { browserBroadcastChannelTransport };
|
|
113
|
+
|
|
114
|
+
//# sourceMappingURL=broadcast-channel-transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"broadcast-channel-transport.js","names":[],"sources":["../src/broadcast-channel-transport.ts"],"sourcesContent":["import {\n incrementLoggerMetaCounter,\n type LogEvent,\n type LoggerLevel,\n type Transport,\n type TransportContext,\n} from \"@loggerjs/core\";\n\nexport interface BrowserBroadcastChannelLike {\n postMessage: (message: unknown) => void;\n close?: () => void;\n}\n\nexport type BrowserBroadcastChannelFactory = (channelName: string) => BrowserBroadcastChannelLike;\n\nexport interface BrowserBroadcastChannelEventMessage {\n type: \"loggerjs.event\";\n source: string;\n event: LogEvent;\n}\n\nexport interface BrowserBroadcastChannelBatchMessage {\n type: \"loggerjs.batch\";\n source: string;\n events: readonly LogEvent[];\n}\n\nexport type BrowserBroadcastChannelMessage =\n | BrowserBroadcastChannelEventMessage\n | BrowserBroadcastChannelBatchMessage;\n\nexport interface BrowserBroadcastChannelMapContext {\n channelName: string;\n source: string;\n}\n\nexport interface BrowserBroadcastChannelErrorDetail {\n operation: \"create-channel\" | \"post-message\" | \"close-channel\" | \"on-error\";\n droppedEvents: number;\n}\n\nexport interface BrowserBroadcastChannelTransportOptions {\n channelName: string;\n name?: string;\n source?: string;\n minLevel?: LoggerLevel;\n channelFactory?: BrowserBroadcastChannelFactory;\n closeChannelOnClose?: boolean;\n mapEvent?: (event: LogEvent, context: BrowserBroadcastChannelMapContext) => unknown;\n mapBatch?: (events: readonly LogEvent[], context: BrowserBroadcastChannelMapContext) => unknown;\n onError?: (error: unknown, detail: BrowserBroadcastChannelErrorDetail) => void;\n}\n\nlet sourceSequence = 0;\n\nfunction createSourceId() {\n sourceSequence += 1;\n return `loggerjs-${Date.now().toString(36)}-${sourceSequence.toString(36)}`;\n}\n\nfunction defaultChannelFactory(channelName: string): BrowserBroadcastChannelLike {\n if (typeof BroadcastChannel === \"undefined\") {\n throw new Error(\"BroadcastChannel is not available\");\n }\n return new BroadcastChannel(channelName);\n}\n\nfunction defaultMapEvent(\n event: LogEvent,\n context: BrowserBroadcastChannelMapContext,\n): BrowserBroadcastChannelEventMessage {\n return { type: \"loggerjs.event\", source: context.source, event };\n}\n\nfunction defaultMapBatch(\n events: readonly LogEvent[],\n context: BrowserBroadcastChannelMapContext,\n): BrowserBroadcastChannelBatchMessage {\n return { type: \"loggerjs.batch\", source: context.source, events };\n}\n\nexport function browserBroadcastChannelTransport(\n options: BrowserBroadcastChannelTransportOptions,\n): Transport {\n const transportName = options.name ?? \"browser-broadcast-channel\";\n const source = options.source ?? createSourceId();\n const mapContext: BrowserBroadcastChannelMapContext = {\n channelName: options.channelName,\n source,\n };\n const mapEvent = options.mapEvent ?? defaultMapEvent;\n const mapBatch = options.mapBatch ?? defaultMapBatch;\n const channelFactory = options.channelFactory ?? defaultChannelFactory;\n const closeChannelOnClose = options.closeChannelOnClose ?? true;\n let channel: BrowserBroadcastChannelLike | undefined;\n let closed = false;\n\n const reportError = (\n error: unknown,\n context: TransportContext | undefined,\n detail: BrowserBroadcastChannelErrorDetail,\n ) => {\n if (detail.droppedEvents > 0) {\n incrementLoggerMetaCounter(\"transport.dropped\", detail.droppedEvents);\n incrementLoggerMetaCounter(`transport.dropped.${detail.operation}`, detail.droppedEvents);\n }\n\n try {\n options.onError?.(error, detail);\n } catch (onErrorError) {\n context?.reportInternalError(onErrorError, {\n operation: \"on-error\",\n phase: \"transport\",\n transport: transportName,\n });\n }\n\n context?.reportInternalError(error, {\n operation: detail.operation,\n phase: \"transport\",\n transport: transportName,\n });\n };\n\n const getChannel = (context: TransportContext) => {\n if (closed) return undefined;\n if (channel) return channel;\n try {\n channel = channelFactory(options.channelName);\n return channel;\n } catch (error) {\n reportError(error, context, {\n droppedEvents: 1,\n operation: \"create-channel\",\n });\n return undefined;\n }\n };\n\n const postMessage = (message: unknown, context: TransportContext, droppedEvents: number) => {\n const currentChannel = getChannel(context);\n if (!currentChannel) return;\n try {\n // oxlint-disable-next-line require-post-message-target-origin -- BroadcastChannel.postMessage does not accept targetOrigin.\n currentChannel.postMessage(message);\n } catch (error) {\n reportError(error, context, {\n droppedEvents,\n operation: \"post-message\",\n });\n }\n };\n\n return {\n name: transportName,\n minLevel: options.minLevel,\n log(event, context) {\n postMessage(mapEvent(event, mapContext), context, 1);\n },\n logBatch(events, context) {\n if (events.length === 0) return;\n postMessage(mapBatch(events, mapContext), context, events.length);\n },\n async close() {\n closed = true;\n if (!channel || !closeChannelOnClose) return;\n try {\n channel.close?.();\n } catch (error) {\n reportError(error, undefined, {\n droppedEvents: 0,\n operation: \"close-channel\",\n });\n } finally {\n channel = undefined;\n }\n },\n };\n}\n"],"mappings":";;AAqDA,IAAI,iBAAiB;AAErB,SAAS,iBAAiB;CACxB,kBAAkB;CAClB,OAAO,YAAY,KAAK,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,GAAG,eAAe,SAAS,EAAE;AAC1E;AAEA,SAAS,sBAAsB,aAAkD;CAC/E,IAAI,OAAO,qBAAqB,aAC9B,MAAM,IAAI,MAAM,mCAAmC;CAErD,OAAO,IAAI,iBAAiB,WAAW;AACzC;AAEA,SAAS,gBACP,OACA,SACqC;CACrC,OAAO;EAAE,MAAM;EAAkB,QAAQ,QAAQ;EAAQ;CAAM;AACjE;AAEA,SAAS,gBACP,QACA,SACqC;CACrC,OAAO;EAAE,MAAM;EAAkB,QAAQ,QAAQ;EAAQ;CAAO;AAClE;AAEA,SAAgB,iCACd,SACW;CACX,MAAM,gBAAgB,QAAQ,QAAQ;CACtC,MAAM,SAAS,QAAQ,UAAU,eAAe;CAChD,MAAM,aAAgD;EACpD,aAAa,QAAQ;EACrB;CACF;CACA,MAAM,WAAW,QAAQ,YAAY;CACrC,MAAM,WAAW,QAAQ,YAAY;CACrC,MAAM,iBAAiB,QAAQ,kBAAkB;CACjD,MAAM,sBAAsB,QAAQ,uBAAuB;CAC3D,IAAI;CACJ,IAAI,SAAS;CAEb,MAAM,eACJ,OACA,SACA,WACG;EACH,IAAI,OAAO,gBAAgB,GAAG;GAC5B,2BAA2B,qBAAqB,OAAO,aAAa;GACpE,2BAA2B,qBAAqB,OAAO,aAAa,OAAO,aAAa;EAC1F;EAEA,IAAI;GACF,QAAQ,UAAU,OAAO,MAAM;EACjC,SAAS,cAAc;GACrB,SAAS,oBAAoB,cAAc;IACzC,WAAW;IACX,OAAO;IACP,WAAW;GACb,CAAC;EACH;EAEA,SAAS,oBAAoB,OAAO;GAClC,WAAW,OAAO;GAClB,OAAO;GACP,WAAW;EACb,CAAC;CACH;CAEA,MAAM,cAAc,YAA8B;EAChD,IAAI,QAAQ,OAAO,KAAA;EACnB,IAAI,SAAS,OAAO;EACpB,IAAI;GACF,UAAU,eAAe,QAAQ,WAAW;GAC5C,OAAO;EACT,SAAS,OAAO;GACd,YAAY,OAAO,SAAS;IAC1B,eAAe;IACf,WAAW;GACb,CAAC;GACD;EACF;CACF;CAEA,MAAM,eAAe,SAAkB,SAA2B,kBAA0B;EAC1F,MAAM,iBAAiB,WAAW,OAAO;EACzC,IAAI,CAAC,gBAAgB;EACrB,IAAI;GAEF,eAAe,YAAY,OAAO;EACpC,SAAS,OAAO;GACd,YAAY,OAAO,SAAS;IAC1B;IACA,WAAW;GACb,CAAC;EACH;CACF;CAEA,OAAO;EACL,MAAM;EACN,UAAU,QAAQ;EAClB,IAAI,OAAO,SAAS;GAClB,YAAY,SAAS,OAAO,UAAU,GAAG,SAAS,CAAC;EACrD;EACA,SAAS,QAAQ,SAAS;GACxB,IAAI,OAAO,WAAW,GAAG;GACzB,YAAY,SAAS,QAAQ,UAAU,GAAG,SAAS,OAAO,MAAM;EAClE;EACA,MAAM,QAAQ;GACZ,SAAS;GACT,IAAI,CAAC,WAAW,CAAC,qBAAqB;GACtC,IAAI;IACF,QAAQ,QAAQ;GAClB,SAAS,OAAO;IACd,YAAY,OAAO,KAAA,GAAW;KAC5B,eAAe;KACf,WAAW;IACb,CAAC;GACH,UAAU;IACR,UAAU,KAAA;GACZ;EACF;CACF;AACF"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
let _loggerjs_core = require("@loggerjs/core");
|
|
3
|
+
//#region src/console-integration.ts
|
|
4
|
+
const defaultLevels = [
|
|
5
|
+
"debug",
|
|
6
|
+
"info",
|
|
7
|
+
"log",
|
|
8
|
+
"trace",
|
|
9
|
+
"warn",
|
|
10
|
+
"error"
|
|
11
|
+
];
|
|
12
|
+
const levelMap = {
|
|
13
|
+
debug: "debug",
|
|
14
|
+
info: "info",
|
|
15
|
+
log: "info",
|
|
16
|
+
trace: "trace",
|
|
17
|
+
warn: "warn",
|
|
18
|
+
error: "error"
|
|
19
|
+
};
|
|
20
|
+
function formatConsoleMessage(args) {
|
|
21
|
+
return args.map((arg) => {
|
|
22
|
+
if (typeof arg === "string") return arg;
|
|
23
|
+
if (arg instanceof Error) return arg.message;
|
|
24
|
+
try {
|
|
25
|
+
return JSON.stringify((0, _loggerjs_core.normalizeValue)(arg, {
|
|
26
|
+
maxDepth: 3,
|
|
27
|
+
maxArrayLength: 20,
|
|
28
|
+
maxObjectKeys: 40
|
|
29
|
+
}));
|
|
30
|
+
} catch {
|
|
31
|
+
return String(arg);
|
|
32
|
+
}
|
|
33
|
+
}).join(" ");
|
|
34
|
+
}
|
|
35
|
+
function reportRateLimitDrop() {
|
|
36
|
+
(0, _loggerjs_core.incrementLoggerMetaCounter)("integration.dropped");
|
|
37
|
+
(0, _loggerjs_core.incrementLoggerMetaCounter)("integration.dropped.rate-limit");
|
|
38
|
+
}
|
|
39
|
+
function captureConsoleIntegration(options = {}) {
|
|
40
|
+
const levels = options.levels ?? defaultLevels;
|
|
41
|
+
const preserveConsole = options.preserveConsole ?? true;
|
|
42
|
+
const captureArguments = options.captureArguments ?? false;
|
|
43
|
+
const maxCapturesPerSecond = options.maxCapturesPerSecond ?? 100;
|
|
44
|
+
return {
|
|
45
|
+
name: "capture-console",
|
|
46
|
+
setup(api) {
|
|
47
|
+
if (typeof console === "undefined") return;
|
|
48
|
+
const originals = {};
|
|
49
|
+
const boundOriginals = {};
|
|
50
|
+
let windowStarted = Date.now();
|
|
51
|
+
let capturesInWindow = 0;
|
|
52
|
+
let disposed = false;
|
|
53
|
+
const shouldCapture = () => {
|
|
54
|
+
const now = Date.now();
|
|
55
|
+
if (now - windowStarted >= 1e3) {
|
|
56
|
+
windowStarted = now;
|
|
57
|
+
capturesInWindow = 0;
|
|
58
|
+
}
|
|
59
|
+
if (capturesInWindow >= maxCapturesPerSecond) {
|
|
60
|
+
reportRateLimitDrop();
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
capturesInWindow += 1;
|
|
64
|
+
return true;
|
|
65
|
+
};
|
|
66
|
+
for (const level of levels) {
|
|
67
|
+
const original = console[level] ?? console.log.bind(console);
|
|
68
|
+
originals[level] = original;
|
|
69
|
+
const unpatched = api.unpatched.console[level] ?? original;
|
|
70
|
+
api.unpatched.console[level] ??= original;
|
|
71
|
+
boundOriginals[level] = unpatched.bind(console);
|
|
72
|
+
const capture = api.guard((args) => {
|
|
73
|
+
if (!shouldCapture()) return;
|
|
74
|
+
const consoleData = { level };
|
|
75
|
+
if (captureArguments) consoleData.arguments = (0, _loggerjs_core.normalizeValue)(args, { maxDepth: 4 });
|
|
76
|
+
api.capture({
|
|
77
|
+
level: levelMap[level],
|
|
78
|
+
message: formatConsoleMessage(args),
|
|
79
|
+
props: { console: consoleData }
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
console[level] = (...args) => {
|
|
83
|
+
capture(args);
|
|
84
|
+
if (preserveConsole) boundOriginals[level]?.(...args);
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
return () => {
|
|
88
|
+
if (disposed) return;
|
|
89
|
+
disposed = true;
|
|
90
|
+
for (const level of levels) if (originals[level]) console[level] = originals[level];
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
//#endregion
|
|
96
|
+
exports.captureConsoleIntegration = captureConsoleIntegration;
|
|
97
|
+
|
|
98
|
+
//# sourceMappingURL=console-integration.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"console-integration.cjs","names":[],"sources":["../src/console-integration.ts"],"sourcesContent":["import {\n incrementLoggerMetaCounter,\n normalizeValue,\n type Integration,\n type IntegrationSetupContext,\n type LoggerLevel,\n} from \"@loggerjs/core\";\n\ntype ConsoleLevel = \"debug\" | \"info\" | \"log\" | \"trace\" | \"warn\" | \"error\";\n\ntype ConsoleRecord = Partial<Record<ConsoleLevel, (...args: unknown[]) => void>>;\n\nconst defaultLevels: ConsoleLevel[] = [\"debug\", \"info\", \"log\", \"trace\", \"warn\", \"error\"];\n\nconst levelMap: Record<ConsoleLevel, LoggerLevel> = {\n debug: \"debug\",\n info: \"info\",\n log: \"info\",\n trace: \"trace\",\n warn: \"warn\",\n error: \"error\",\n};\n\nexport interface CaptureConsoleOptions {\n levels?: ConsoleLevel[];\n preserveConsole?: boolean;\n captureArguments?: boolean;\n maxCapturesPerSecond?: number;\n}\n\nfunction formatConsoleMessage(args: unknown[]): string {\n return args\n .map((arg) => {\n if (typeof arg === \"string\") return arg;\n if (arg instanceof Error) return arg.message;\n try {\n return JSON.stringify(\n normalizeValue(arg, { maxDepth: 3, maxArrayLength: 20, maxObjectKeys: 40 }),\n );\n } catch {\n return String(arg);\n }\n })\n .join(\" \");\n}\n\nfunction reportRateLimitDrop() {\n incrementLoggerMetaCounter(\"integration.dropped\");\n incrementLoggerMetaCounter(\"integration.dropped.rate-limit\");\n}\n\nexport function captureConsoleIntegration(options: CaptureConsoleOptions = {}): Integration {\n const levels = options.levels ?? defaultLevels;\n const preserveConsole = options.preserveConsole ?? true;\n const captureArguments = options.captureArguments ?? false;\n const maxCapturesPerSecond = options.maxCapturesPerSecond ?? 100;\n\n return {\n name: \"capture-console\",\n setup(api: IntegrationSetupContext) {\n if (typeof console === \"undefined\") return;\n const originals: ConsoleRecord = {};\n const boundOriginals: ConsoleRecord = {};\n let windowStarted = Date.now();\n let capturesInWindow = 0;\n let disposed = false;\n\n const shouldCapture = () => {\n const now = Date.now();\n if (now - windowStarted >= 1000) {\n windowStarted = now;\n capturesInWindow = 0;\n }\n if (capturesInWindow >= maxCapturesPerSecond) {\n reportRateLimitDrop();\n return false;\n }\n capturesInWindow += 1;\n return true;\n };\n\n for (const level of levels) {\n const original = (console as unknown as ConsoleRecord)[level] ?? console.log.bind(console);\n originals[level] = original;\n const unpatched = api.unpatched.console[level] ?? original;\n api.unpatched.console[level] ??= original;\n boundOriginals[level] = unpatched.bind(console);\n\n const capture = api.guard((args: unknown[]) => {\n if (!shouldCapture()) return;\n const consoleData: Record<string, unknown> = { level };\n if (captureArguments) {\n consoleData.arguments = normalizeValue(args, { maxDepth: 4 });\n }\n api.capture({\n level: levelMap[level],\n message: formatConsoleMessage(args),\n props: { console: consoleData },\n });\n });\n\n (console as unknown as ConsoleRecord)[level] = (...args: unknown[]) => {\n capture(args);\n if (preserveConsole) boundOriginals[level]?.(...args);\n };\n }\n\n return () => {\n if (disposed) return;\n disposed = true;\n for (const level of levels) {\n if (originals[level]) (console as unknown as ConsoleRecord)[level] = originals[level];\n }\n };\n },\n };\n}\n"],"mappings":";;;AAYA,MAAM,gBAAgC;CAAC;CAAS;CAAQ;CAAO;CAAS;CAAQ;AAAO;AAEvF,MAAM,WAA8C;CAClD,OAAO;CACP,MAAM;CACN,KAAK;CACL,OAAO;CACP,MAAM;CACN,OAAO;AACT;AASA,SAAS,qBAAqB,MAAyB;CACrD,OAAO,KACJ,KAAK,QAAQ;EACZ,IAAI,OAAO,QAAQ,UAAU,OAAO;EACpC,IAAI,eAAe,OAAO,OAAO,IAAI;EACrC,IAAI;GACF,OAAO,KAAK,WAAA,GAAA,eAAA,eAAA,CACK,KAAK;IAAE,UAAU;IAAG,gBAAgB;IAAI,eAAe;GAAG,CAAC,CAC5E;EACF,QAAQ;GACN,OAAO,OAAO,GAAG;EACnB;CACF,CAAC,CAAC,CACD,KAAK,GAAG;AACb;AAEA,SAAS,sBAAsB;CAC7B,CAAA,GAAA,eAAA,2BAAA,CAA2B,qBAAqB;CAChD,CAAA,GAAA,eAAA,2BAAA,CAA2B,gCAAgC;AAC7D;AAEA,SAAgB,0BAA0B,UAAiC,CAAC,GAAgB;CAC1F,MAAM,SAAS,QAAQ,UAAU;CACjC,MAAM,kBAAkB,QAAQ,mBAAmB;CACnD,MAAM,mBAAmB,QAAQ,oBAAoB;CACrD,MAAM,uBAAuB,QAAQ,wBAAwB;CAE7D,OAAO;EACL,MAAM;EACN,MAAM,KAA8B;GAClC,IAAI,OAAO,YAAY,aAAa;GACpC,MAAM,YAA2B,CAAC;GAClC,MAAM,iBAAgC,CAAC;GACvC,IAAI,gBAAgB,KAAK,IAAI;GAC7B,IAAI,mBAAmB;GACvB,IAAI,WAAW;GAEf,MAAM,sBAAsB;IAC1B,MAAM,MAAM,KAAK,IAAI;IACrB,IAAI,MAAM,iBAAiB,KAAM;KAC/B,gBAAgB;KAChB,mBAAmB;IACrB;IACA,IAAI,oBAAoB,sBAAsB;KAC5C,oBAAoB;KACpB,OAAO;IACT;IACA,oBAAoB;IACpB,OAAO;GACT;GAEA,KAAK,MAAM,SAAS,QAAQ;IAC1B,MAAM,WAAY,QAAqC,UAAU,QAAQ,IAAI,KAAK,OAAO;IACzF,UAAU,SAAS;IACnB,MAAM,YAAY,IAAI,UAAU,QAAQ,UAAU;IAClD,IAAI,UAAU,QAAQ,WAAW;IACjC,eAAe,SAAS,UAAU,KAAK,OAAO;IAE9C,MAAM,UAAU,IAAI,OAAO,SAAoB;KAC7C,IAAI,CAAC,cAAc,GAAG;KACtB,MAAM,cAAuC,EAAE,MAAM;KACrD,IAAI,kBACF,YAAY,aAAA,GAAA,eAAA,eAAA,CAA2B,MAAM,EAAE,UAAU,EAAE,CAAC;KAE9D,IAAI,QAAQ;MACV,OAAO,SAAS;MAChB,SAAS,qBAAqB,IAAI;MAClC,OAAO,EAAE,SAAS,YAAY;KAChC,CAAC;IACH,CAAC;IAED,QAAsC,UAAU,GAAG,SAAoB;KACrE,QAAQ,IAAI;KACZ,IAAI,iBAAiB,eAAe,MAAM,GAAG,GAAG,IAAI;IACtD;GACF;GAEA,aAAa;IACX,IAAI,UAAU;IACd,WAAW;IACX,KAAK,MAAM,SAAS,QAClB,IAAI,UAAU,QAAQ,QAAsC,SAAS,UAAU;GAEnF;EACF;CACF;AACF"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { incrementLoggerMetaCounter, normalizeValue } from "@loggerjs/core";
|
|
2
|
+
//#region src/console-integration.ts
|
|
3
|
+
const defaultLevels = [
|
|
4
|
+
"debug",
|
|
5
|
+
"info",
|
|
6
|
+
"log",
|
|
7
|
+
"trace",
|
|
8
|
+
"warn",
|
|
9
|
+
"error"
|
|
10
|
+
];
|
|
11
|
+
const levelMap = {
|
|
12
|
+
debug: "debug",
|
|
13
|
+
info: "info",
|
|
14
|
+
log: "info",
|
|
15
|
+
trace: "trace",
|
|
16
|
+
warn: "warn",
|
|
17
|
+
error: "error"
|
|
18
|
+
};
|
|
19
|
+
function formatConsoleMessage(args) {
|
|
20
|
+
return args.map((arg) => {
|
|
21
|
+
if (typeof arg === "string") return arg;
|
|
22
|
+
if (arg instanceof Error) return arg.message;
|
|
23
|
+
try {
|
|
24
|
+
return JSON.stringify(normalizeValue(arg, {
|
|
25
|
+
maxDepth: 3,
|
|
26
|
+
maxArrayLength: 20,
|
|
27
|
+
maxObjectKeys: 40
|
|
28
|
+
}));
|
|
29
|
+
} catch {
|
|
30
|
+
return String(arg);
|
|
31
|
+
}
|
|
32
|
+
}).join(" ");
|
|
33
|
+
}
|
|
34
|
+
function reportRateLimitDrop() {
|
|
35
|
+
incrementLoggerMetaCounter("integration.dropped");
|
|
36
|
+
incrementLoggerMetaCounter("integration.dropped.rate-limit");
|
|
37
|
+
}
|
|
38
|
+
function captureConsoleIntegration(options = {}) {
|
|
39
|
+
const levels = options.levels ?? defaultLevels;
|
|
40
|
+
const preserveConsole = options.preserveConsole ?? true;
|
|
41
|
+
const captureArguments = options.captureArguments ?? false;
|
|
42
|
+
const maxCapturesPerSecond = options.maxCapturesPerSecond ?? 100;
|
|
43
|
+
return {
|
|
44
|
+
name: "capture-console",
|
|
45
|
+
setup(api) {
|
|
46
|
+
if (typeof console === "undefined") return;
|
|
47
|
+
const originals = {};
|
|
48
|
+
const boundOriginals = {};
|
|
49
|
+
let windowStarted = Date.now();
|
|
50
|
+
let capturesInWindow = 0;
|
|
51
|
+
let disposed = false;
|
|
52
|
+
const shouldCapture = () => {
|
|
53
|
+
const now = Date.now();
|
|
54
|
+
if (now - windowStarted >= 1e3) {
|
|
55
|
+
windowStarted = now;
|
|
56
|
+
capturesInWindow = 0;
|
|
57
|
+
}
|
|
58
|
+
if (capturesInWindow >= maxCapturesPerSecond) {
|
|
59
|
+
reportRateLimitDrop();
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
capturesInWindow += 1;
|
|
63
|
+
return true;
|
|
64
|
+
};
|
|
65
|
+
for (const level of levels) {
|
|
66
|
+
const original = console[level] ?? console.log.bind(console);
|
|
67
|
+
originals[level] = original;
|
|
68
|
+
const unpatched = api.unpatched.console[level] ?? original;
|
|
69
|
+
api.unpatched.console[level] ??= original;
|
|
70
|
+
boundOriginals[level] = unpatched.bind(console);
|
|
71
|
+
const capture = api.guard((args) => {
|
|
72
|
+
if (!shouldCapture()) return;
|
|
73
|
+
const consoleData = { level };
|
|
74
|
+
if (captureArguments) consoleData.arguments = normalizeValue(args, { maxDepth: 4 });
|
|
75
|
+
api.capture({
|
|
76
|
+
level: levelMap[level],
|
|
77
|
+
message: formatConsoleMessage(args),
|
|
78
|
+
props: { console: consoleData }
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
console[level] = (...args) => {
|
|
82
|
+
capture(args);
|
|
83
|
+
if (preserveConsole) boundOriginals[level]?.(...args);
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
return () => {
|
|
87
|
+
if (disposed) return;
|
|
88
|
+
disposed = true;
|
|
89
|
+
for (const level of levels) if (originals[level]) console[level] = originals[level];
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
//#endregion
|
|
95
|
+
export { captureConsoleIntegration };
|
|
96
|
+
|
|
97
|
+
//# sourceMappingURL=console-integration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"console-integration.js","names":[],"sources":["../src/console-integration.ts"],"sourcesContent":["import {\n incrementLoggerMetaCounter,\n normalizeValue,\n type Integration,\n type IntegrationSetupContext,\n type LoggerLevel,\n} from \"@loggerjs/core\";\n\ntype ConsoleLevel = \"debug\" | \"info\" | \"log\" | \"trace\" | \"warn\" | \"error\";\n\ntype ConsoleRecord = Partial<Record<ConsoleLevel, (...args: unknown[]) => void>>;\n\nconst defaultLevels: ConsoleLevel[] = [\"debug\", \"info\", \"log\", \"trace\", \"warn\", \"error\"];\n\nconst levelMap: Record<ConsoleLevel, LoggerLevel> = {\n debug: \"debug\",\n info: \"info\",\n log: \"info\",\n trace: \"trace\",\n warn: \"warn\",\n error: \"error\",\n};\n\nexport interface CaptureConsoleOptions {\n levels?: ConsoleLevel[];\n preserveConsole?: boolean;\n captureArguments?: boolean;\n maxCapturesPerSecond?: number;\n}\n\nfunction formatConsoleMessage(args: unknown[]): string {\n return args\n .map((arg) => {\n if (typeof arg === \"string\") return arg;\n if (arg instanceof Error) return arg.message;\n try {\n return JSON.stringify(\n normalizeValue(arg, { maxDepth: 3, maxArrayLength: 20, maxObjectKeys: 40 }),\n );\n } catch {\n return String(arg);\n }\n })\n .join(\" \");\n}\n\nfunction reportRateLimitDrop() {\n incrementLoggerMetaCounter(\"integration.dropped\");\n incrementLoggerMetaCounter(\"integration.dropped.rate-limit\");\n}\n\nexport function captureConsoleIntegration(options: CaptureConsoleOptions = {}): Integration {\n const levels = options.levels ?? defaultLevels;\n const preserveConsole = options.preserveConsole ?? true;\n const captureArguments = options.captureArguments ?? false;\n const maxCapturesPerSecond = options.maxCapturesPerSecond ?? 100;\n\n return {\n name: \"capture-console\",\n setup(api: IntegrationSetupContext) {\n if (typeof console === \"undefined\") return;\n const originals: ConsoleRecord = {};\n const boundOriginals: ConsoleRecord = {};\n let windowStarted = Date.now();\n let capturesInWindow = 0;\n let disposed = false;\n\n const shouldCapture = () => {\n const now = Date.now();\n if (now - windowStarted >= 1000) {\n windowStarted = now;\n capturesInWindow = 0;\n }\n if (capturesInWindow >= maxCapturesPerSecond) {\n reportRateLimitDrop();\n return false;\n }\n capturesInWindow += 1;\n return true;\n };\n\n for (const level of levels) {\n const original = (console as unknown as ConsoleRecord)[level] ?? console.log.bind(console);\n originals[level] = original;\n const unpatched = api.unpatched.console[level] ?? original;\n api.unpatched.console[level] ??= original;\n boundOriginals[level] = unpatched.bind(console);\n\n const capture = api.guard((args: unknown[]) => {\n if (!shouldCapture()) return;\n const consoleData: Record<string, unknown> = { level };\n if (captureArguments) {\n consoleData.arguments = normalizeValue(args, { maxDepth: 4 });\n }\n api.capture({\n level: levelMap[level],\n message: formatConsoleMessage(args),\n props: { console: consoleData },\n });\n });\n\n (console as unknown as ConsoleRecord)[level] = (...args: unknown[]) => {\n capture(args);\n if (preserveConsole) boundOriginals[level]?.(...args);\n };\n }\n\n return () => {\n if (disposed) return;\n disposed = true;\n for (const level of levels) {\n if (originals[level]) (console as unknown as ConsoleRecord)[level] = originals[level];\n }\n };\n },\n };\n}\n"],"mappings":";;AAYA,MAAM,gBAAgC;CAAC;CAAS;CAAQ;CAAO;CAAS;CAAQ;AAAO;AAEvF,MAAM,WAA8C;CAClD,OAAO;CACP,MAAM;CACN,KAAK;CACL,OAAO;CACP,MAAM;CACN,OAAO;AACT;AASA,SAAS,qBAAqB,MAAyB;CACrD,OAAO,KACJ,KAAK,QAAQ;EACZ,IAAI,OAAO,QAAQ,UAAU,OAAO;EACpC,IAAI,eAAe,OAAO,OAAO,IAAI;EACrC,IAAI;GACF,OAAO,KAAK,UACV,eAAe,KAAK;IAAE,UAAU;IAAG,gBAAgB;IAAI,eAAe;GAAG,CAAC,CAC5E;EACF,QAAQ;GACN,OAAO,OAAO,GAAG;EACnB;CACF,CAAC,CAAC,CACD,KAAK,GAAG;AACb;AAEA,SAAS,sBAAsB;CAC7B,2BAA2B,qBAAqB;CAChD,2BAA2B,gCAAgC;AAC7D;AAEA,SAAgB,0BAA0B,UAAiC,CAAC,GAAgB;CAC1F,MAAM,SAAS,QAAQ,UAAU;CACjC,MAAM,kBAAkB,QAAQ,mBAAmB;CACnD,MAAM,mBAAmB,QAAQ,oBAAoB;CACrD,MAAM,uBAAuB,QAAQ,wBAAwB;CAE7D,OAAO;EACL,MAAM;EACN,MAAM,KAA8B;GAClC,IAAI,OAAO,YAAY,aAAa;GACpC,MAAM,YAA2B,CAAC;GAClC,MAAM,iBAAgC,CAAC;GACvC,IAAI,gBAAgB,KAAK,IAAI;GAC7B,IAAI,mBAAmB;GACvB,IAAI,WAAW;GAEf,MAAM,sBAAsB;IAC1B,MAAM,MAAM,KAAK,IAAI;IACrB,IAAI,MAAM,iBAAiB,KAAM;KAC/B,gBAAgB;KAChB,mBAAmB;IACrB;IACA,IAAI,oBAAoB,sBAAsB;KAC5C,oBAAoB;KACpB,OAAO;IACT;IACA,oBAAoB;IACpB,OAAO;GACT;GAEA,KAAK,MAAM,SAAS,QAAQ;IAC1B,MAAM,WAAY,QAAqC,UAAU,QAAQ,IAAI,KAAK,OAAO;IACzF,UAAU,SAAS;IACnB,MAAM,YAAY,IAAI,UAAU,QAAQ,UAAU;IAClD,IAAI,UAAU,QAAQ,WAAW;IACjC,eAAe,SAAS,UAAU,KAAK,OAAO;IAE9C,MAAM,UAAU,IAAI,OAAO,SAAoB;KAC7C,IAAI,CAAC,cAAc,GAAG;KACtB,MAAM,cAAuC,EAAE,MAAM;KACrD,IAAI,kBACF,YAAY,YAAY,eAAe,MAAM,EAAE,UAAU,EAAE,CAAC;KAE9D,IAAI,QAAQ;MACV,OAAO,SAAS;MAChB,SAAS,qBAAqB,IAAI;MAClC,OAAO,EAAE,SAAS,YAAY;KAChC,CAAC;IACH,CAAC;IAED,QAAsC,UAAU,GAAG,SAAoB;KACrE,QAAQ,IAAI;KACZ,IAAI,iBAAiB,eAAe,MAAM,GAAG,GAAG,IAAI;IACtD;GACF;GAEA,aAAa;IACX,IAAI,UAAU;IACd,WAAW;IACX,KAAK,MAAM,SAAS,QAClB,IAAI,UAAU,QAAQ,QAAsC,SAAS,UAAU;GAEnF;EACF;CACF;AACF"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
let _loggerjs_core = require("@loggerjs/core");
|
|
3
|
+
//#region src/context-propagation-integration.ts
|
|
4
|
+
const defaultActionEvents = [
|
|
5
|
+
"click",
|
|
6
|
+
"input",
|
|
7
|
+
"change",
|
|
8
|
+
"submit"
|
|
9
|
+
];
|
|
10
|
+
let fallbackIdSeq = 0;
|
|
11
|
+
function defaultIdFactory() {
|
|
12
|
+
const cryptoRandomUUID = globalThis.crypto?.randomUUID;
|
|
13
|
+
if (cryptoRandomUUID) return cryptoRandomUUID.call(globalThis.crypto);
|
|
14
|
+
return `${Date.now().toString(36)}-${(fallbackIdSeq++).toString(36)}`;
|
|
15
|
+
}
|
|
16
|
+
function resolveValue(value) {
|
|
17
|
+
return typeof value === "function" ? value() : value;
|
|
18
|
+
}
|
|
19
|
+
function normalizeBaggage(value) {
|
|
20
|
+
if (typeof value === "string") return (0, _loggerjs_core.parseBaggage)(value);
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
function actionTargetName(target) {
|
|
24
|
+
const item = target;
|
|
25
|
+
if (!item) return void 0;
|
|
26
|
+
return item.id || item.name || item.tagName?.toLowerCase();
|
|
27
|
+
}
|
|
28
|
+
function browserContextPropagationIntegration(options = {}) {
|
|
29
|
+
const actionEvents = options.actionEvents ?? defaultActionEvents;
|
|
30
|
+
const actionTtlMs = Math.max(0, Math.floor(options.actionTtlMs ?? 5e3));
|
|
31
|
+
const clock = options.clock ?? Date.now;
|
|
32
|
+
const idFactory = options.idFactory ?? defaultIdFactory;
|
|
33
|
+
let lastAction;
|
|
34
|
+
return {
|
|
35
|
+
name: "browser-context-propagation",
|
|
36
|
+
setup() {
|
|
37
|
+
const root = options.root ?? globalThis.document;
|
|
38
|
+
const disposeProvider = (0, _loggerjs_core.addContextProvider)(() => {
|
|
39
|
+
const sessionId = resolveValue(options.sessionId);
|
|
40
|
+
const requestId = options.requestId?.();
|
|
41
|
+
const trace = resolveValue(options.trace) ?? (0, _loggerjs_core.parseTraceparent)(resolveValue(options.traceparent));
|
|
42
|
+
const baggage = normalizeBaggage(resolveValue(options.baggage)) ?? trace?.baggage;
|
|
43
|
+
const traceparent = (0, _loggerjs_core.formatTraceparent)(trace);
|
|
44
|
+
const now = clock();
|
|
45
|
+
const action = lastAction && now - lastAction.time <= actionTtlMs ? {
|
|
46
|
+
actionId: lastAction.id,
|
|
47
|
+
actionType: lastAction.type,
|
|
48
|
+
actionTarget: lastAction.target
|
|
49
|
+
} : void 0;
|
|
50
|
+
return {
|
|
51
|
+
sessionId,
|
|
52
|
+
requestId,
|
|
53
|
+
traceparent,
|
|
54
|
+
baggage: (0, _loggerjs_core.formatBaggage)(baggage),
|
|
55
|
+
...action
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
if (!root?.addEventListener || !root.removeEventListener || actionEvents.length === 0) return disposeProvider;
|
|
59
|
+
const onAction = (event) => {
|
|
60
|
+
lastAction = {
|
|
61
|
+
id: idFactory(),
|
|
62
|
+
type: event.type,
|
|
63
|
+
target: actionTargetName(event.target),
|
|
64
|
+
time: clock()
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
for (const event of actionEvents) root.addEventListener(event, onAction, true);
|
|
68
|
+
return () => {
|
|
69
|
+
for (const event of actionEvents) root.removeEventListener(event, onAction, true);
|
|
70
|
+
disposeProvider();
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
//#endregion
|
|
76
|
+
exports.browserContextPropagationIntegration = browserContextPropagationIntegration;
|
|
77
|
+
|
|
78
|
+
//# sourceMappingURL=context-propagation-integration.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-propagation-integration.cjs","names":[],"sources":["../src/context-propagation-integration.ts"],"sourcesContent":["import {\n addContextProvider,\n formatBaggage,\n formatTraceparent,\n parseBaggage,\n parseTraceparent,\n type Baggage,\n type Integration,\n type TraceContext,\n} from \"@loggerjs/core\";\n\nexport type BrowserContextActionEventName = \"change\" | \"click\" | \"input\" | \"keydown\" | \"submit\";\n\nexport interface BrowserContextEventTargetLike {\n addEventListener: typeof globalThis.addEventListener;\n removeEventListener: typeof globalThis.removeEventListener;\n}\n\nexport interface BrowserContextPropagationOptions {\n sessionId?: string | (() => string | undefined);\n requestId?: () => string | undefined;\n trace?: TraceContext | (() => TraceContext | undefined);\n traceparent?: string | (() => string | undefined);\n baggage?: Baggage | string | (() => Baggage | string | undefined);\n actionEvents?: readonly BrowserContextActionEventName[];\n actionTtlMs?: number;\n root?: BrowserContextEventTargetLike;\n clock?: () => number;\n idFactory?: () => string;\n}\n\nconst defaultActionEvents: readonly BrowserContextActionEventName[] = [\n \"click\",\n \"input\",\n \"change\",\n \"submit\",\n];\n\nlet fallbackIdSeq = 0;\n\nfunction defaultIdFactory(): string {\n const cryptoRandomUUID = globalThis.crypto?.randomUUID;\n if (cryptoRandomUUID) return cryptoRandomUUID.call(globalThis.crypto);\n return `${Date.now().toString(36)}-${(fallbackIdSeq++).toString(36)}`;\n}\n\nfunction resolveValue<T>(value: T | (() => T | undefined) | undefined): T | undefined {\n return typeof value === \"function\" ? (value as () => T | undefined)() : value;\n}\n\nfunction normalizeBaggage(value: Baggage | string | undefined): Baggage | undefined {\n if (typeof value === \"string\") return parseBaggage(value);\n return value;\n}\n\nfunction actionTargetName(target: EventTarget | null): string | undefined {\n const item = target as { tagName?: string; id?: string; name?: string } | null;\n if (!item) return undefined;\n return item.id || item.name || item.tagName?.toLowerCase();\n}\n\nexport function browserContextPropagationIntegration(\n options: BrowserContextPropagationOptions = {},\n): Integration {\n const actionEvents = options.actionEvents ?? defaultActionEvents;\n const actionTtlMs = Math.max(0, Math.floor(options.actionTtlMs ?? 5000));\n const clock = options.clock ?? Date.now;\n const idFactory = options.idFactory ?? defaultIdFactory;\n let lastAction:\n | {\n id: string;\n type: string;\n target?: string;\n time: number;\n }\n | undefined;\n\n return {\n name: \"browser-context-propagation\",\n setup() {\n const root = options.root ?? globalThis.document;\n const disposeProvider = addContextProvider(() => {\n const sessionId = resolveValue(options.sessionId);\n const requestId = options.requestId?.();\n const explicitTrace = resolveValue(options.trace);\n const trace = explicitTrace ?? parseTraceparent(resolveValue(options.traceparent));\n const baggage = normalizeBaggage(resolveValue(options.baggage)) ?? trace?.baggage;\n const traceparent = formatTraceparent(trace);\n const now = clock();\n const action =\n lastAction && now - lastAction.time <= actionTtlMs\n ? {\n actionId: lastAction.id,\n actionType: lastAction.type,\n actionTarget: lastAction.target,\n }\n : undefined;\n\n return {\n sessionId,\n requestId,\n traceparent,\n baggage: formatBaggage(baggage),\n ...action,\n };\n });\n\n if (!root?.addEventListener || !root.removeEventListener || actionEvents.length === 0) {\n return disposeProvider;\n }\n\n const onAction = (event: Event) => {\n lastAction = {\n id: idFactory(),\n type: event.type,\n target: actionTargetName(event.target),\n time: clock(),\n };\n };\n\n for (const event of actionEvents) root.addEventListener(event, onAction, true);\n\n return () => {\n for (const event of actionEvents) root.removeEventListener(event, onAction, true);\n disposeProvider();\n };\n },\n };\n}\n"],"mappings":";;;AA+BA,MAAM,sBAAgE;CACpE;CACA;CACA;CACA;AACF;AAEA,IAAI,gBAAgB;AAEpB,SAAS,mBAA2B;CAClC,MAAM,mBAAmB,WAAW,QAAQ;CAC5C,IAAI,kBAAkB,OAAO,iBAAiB,KAAK,WAAW,MAAM;CACpE,OAAO,GAAG,KAAK,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,IAAI,gBAAA,CAAiB,SAAS,EAAE;AACpE;AAEA,SAAS,aAAgB,OAA6D;CACpF,OAAO,OAAO,UAAU,aAAc,MAA8B,IAAI;AAC1E;AAEA,SAAS,iBAAiB,OAA0D;CAClF,IAAI,OAAO,UAAU,UAAU,QAAA,GAAA,eAAA,aAAA,CAAoB,KAAK;CACxD,OAAO;AACT;AAEA,SAAS,iBAAiB,QAAgD;CACxE,MAAM,OAAO;CACb,IAAI,CAAC,MAAM,OAAO,KAAA;CAClB,OAAO,KAAK,MAAM,KAAK,QAAQ,KAAK,SAAS,YAAY;AAC3D;AAEA,SAAgB,qCACd,UAA4C,CAAC,GAChC;CACb,MAAM,eAAe,QAAQ,gBAAgB;CAC7C,MAAM,cAAc,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,eAAe,GAAI,CAAC;CACvE,MAAM,QAAQ,QAAQ,SAAS,KAAK;CACpC,MAAM,YAAY,QAAQ,aAAa;CACvC,IAAI;CASJ,OAAO;EACL,MAAM;EACN,QAAQ;GACN,MAAM,OAAO,QAAQ,QAAQ,WAAW;GACxC,MAAM,mBAAA,GAAA,eAAA,mBAAA,OAA2C;IAC/C,MAAM,YAAY,aAAa,QAAQ,SAAS;IAChD,MAAM,YAAY,QAAQ,YAAY;IAEtC,MAAM,QADgB,aAAa,QAAQ,KACjB,MAAA,GAAA,eAAA,iBAAA,CAAsB,aAAa,QAAQ,WAAW,CAAC;IACjF,MAAM,UAAU,iBAAiB,aAAa,QAAQ,OAAO,CAAC,KAAK,OAAO;IAC1E,MAAM,eAAA,GAAA,eAAA,kBAAA,CAAgC,KAAK;IAC3C,MAAM,MAAM,MAAM;IAClB,MAAM,SACJ,cAAc,MAAM,WAAW,QAAQ,cACnC;KACE,UAAU,WAAW;KACrB,YAAY,WAAW;KACvB,cAAc,WAAW;IAC3B,IACA,KAAA;IAEN,OAAO;KACL;KACA;KACA;KACA,UAAA,GAAA,eAAA,cAAA,CAAuB,OAAO;KAC9B,GAAG;IACL;GACF,CAAC;GAED,IAAI,CAAC,MAAM,oBAAoB,CAAC,KAAK,uBAAuB,aAAa,WAAW,GAClF,OAAO;GAGT,MAAM,YAAY,UAAiB;IACjC,aAAa;KACX,IAAI,UAAU;KACd,MAAM,MAAM;KACZ,QAAQ,iBAAiB,MAAM,MAAM;KACrC,MAAM,MAAM;IACd;GACF;GAEA,KAAK,MAAM,SAAS,cAAc,KAAK,iBAAiB,OAAO,UAAU,IAAI;GAE7E,aAAa;IACX,KAAK,MAAM,SAAS,cAAc,KAAK,oBAAoB,OAAO,UAAU,IAAI;IAChF,gBAAgB;GAClB;EACF;CACF;AACF"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { addContextProvider, formatBaggage, formatTraceparent, parseBaggage, parseTraceparent } from "@loggerjs/core";
|
|
2
|
+
//#region src/context-propagation-integration.ts
|
|
3
|
+
const defaultActionEvents = [
|
|
4
|
+
"click",
|
|
5
|
+
"input",
|
|
6
|
+
"change",
|
|
7
|
+
"submit"
|
|
8
|
+
];
|
|
9
|
+
let fallbackIdSeq = 0;
|
|
10
|
+
function defaultIdFactory() {
|
|
11
|
+
const cryptoRandomUUID = globalThis.crypto?.randomUUID;
|
|
12
|
+
if (cryptoRandomUUID) return cryptoRandomUUID.call(globalThis.crypto);
|
|
13
|
+
return `${Date.now().toString(36)}-${(fallbackIdSeq++).toString(36)}`;
|
|
14
|
+
}
|
|
15
|
+
function resolveValue(value) {
|
|
16
|
+
return typeof value === "function" ? value() : value;
|
|
17
|
+
}
|
|
18
|
+
function normalizeBaggage(value) {
|
|
19
|
+
if (typeof value === "string") return parseBaggage(value);
|
|
20
|
+
return value;
|
|
21
|
+
}
|
|
22
|
+
function actionTargetName(target) {
|
|
23
|
+
const item = target;
|
|
24
|
+
if (!item) return void 0;
|
|
25
|
+
return item.id || item.name || item.tagName?.toLowerCase();
|
|
26
|
+
}
|
|
27
|
+
function browserContextPropagationIntegration(options = {}) {
|
|
28
|
+
const actionEvents = options.actionEvents ?? defaultActionEvents;
|
|
29
|
+
const actionTtlMs = Math.max(0, Math.floor(options.actionTtlMs ?? 5e3));
|
|
30
|
+
const clock = options.clock ?? Date.now;
|
|
31
|
+
const idFactory = options.idFactory ?? defaultIdFactory;
|
|
32
|
+
let lastAction;
|
|
33
|
+
return {
|
|
34
|
+
name: "browser-context-propagation",
|
|
35
|
+
setup() {
|
|
36
|
+
const root = options.root ?? globalThis.document;
|
|
37
|
+
const disposeProvider = addContextProvider(() => {
|
|
38
|
+
const sessionId = resolveValue(options.sessionId);
|
|
39
|
+
const requestId = options.requestId?.();
|
|
40
|
+
const trace = resolveValue(options.trace) ?? parseTraceparent(resolveValue(options.traceparent));
|
|
41
|
+
const baggage = normalizeBaggage(resolveValue(options.baggage)) ?? trace?.baggage;
|
|
42
|
+
const traceparent = formatTraceparent(trace);
|
|
43
|
+
const now = clock();
|
|
44
|
+
const action = lastAction && now - lastAction.time <= actionTtlMs ? {
|
|
45
|
+
actionId: lastAction.id,
|
|
46
|
+
actionType: lastAction.type,
|
|
47
|
+
actionTarget: lastAction.target
|
|
48
|
+
} : void 0;
|
|
49
|
+
return {
|
|
50
|
+
sessionId,
|
|
51
|
+
requestId,
|
|
52
|
+
traceparent,
|
|
53
|
+
baggage: formatBaggage(baggage),
|
|
54
|
+
...action
|
|
55
|
+
};
|
|
56
|
+
});
|
|
57
|
+
if (!root?.addEventListener || !root.removeEventListener || actionEvents.length === 0) return disposeProvider;
|
|
58
|
+
const onAction = (event) => {
|
|
59
|
+
lastAction = {
|
|
60
|
+
id: idFactory(),
|
|
61
|
+
type: event.type,
|
|
62
|
+
target: actionTargetName(event.target),
|
|
63
|
+
time: clock()
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
for (const event of actionEvents) root.addEventListener(event, onAction, true);
|
|
67
|
+
return () => {
|
|
68
|
+
for (const event of actionEvents) root.removeEventListener(event, onAction, true);
|
|
69
|
+
disposeProvider();
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
//#endregion
|
|
75
|
+
export { browserContextPropagationIntegration };
|
|
76
|
+
|
|
77
|
+
//# sourceMappingURL=context-propagation-integration.js.map
|