@virtu3d/event-manager 0.2.7
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/LICENSE +21 -0
- package/README.md +624 -0
- package/dist/browser/index.d.mts +631 -0
- package/dist/browser/index.d.ts +631 -0
- package/dist/browser/index.js +1140 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/index.mjs +1104 -0
- package/dist/browser/index.mjs.map +1 -0
- package/dist/context/index.d.mts +111 -0
- package/dist/context/index.d.ts +111 -0
- package/dist/context/index.js +186 -0
- package/dist/context/index.js.map +1 -0
- package/dist/context/index.mjs +176 -0
- package/dist/context/index.mjs.map +1 -0
- package/dist/index.d.mts +568 -0
- package/dist/index.d.ts +568 -0
- package/dist/index.js +1044 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +999 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +118 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,999 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
// src/connectors/base.connector.ts
|
|
9
|
+
var BaseConnector = class {
|
|
10
|
+
constructor(config = {}) {
|
|
11
|
+
this.ready = false;
|
|
12
|
+
this.config = {
|
|
13
|
+
enabled: true,
|
|
14
|
+
debug: false,
|
|
15
|
+
...config
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
async init() {
|
|
19
|
+
if (!this.config.enabled) {
|
|
20
|
+
this.log("Connector disabled, skipping init");
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
await this.setup();
|
|
24
|
+
this.ready = true;
|
|
25
|
+
}
|
|
26
|
+
async shutdown() {
|
|
27
|
+
this.ready = false;
|
|
28
|
+
}
|
|
29
|
+
isReady() {
|
|
30
|
+
return this.ready && (this.config.enabled ?? true);
|
|
31
|
+
}
|
|
32
|
+
log(message, data) {
|
|
33
|
+
if (this.config.debug) {
|
|
34
|
+
console.log(`[${this.name}] ${message}`, data || "");
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// src/connectors/console.connector.ts
|
|
40
|
+
var ConsoleConnector = class extends BaseConnector {
|
|
41
|
+
constructor(config = {}) {
|
|
42
|
+
super(config);
|
|
43
|
+
this.name = "console";
|
|
44
|
+
this.type = "custom";
|
|
45
|
+
this.prefix = config.prefix || "[Telemetry]";
|
|
46
|
+
}
|
|
47
|
+
setup() {
|
|
48
|
+
}
|
|
49
|
+
track(event) {
|
|
50
|
+
console.log(`${this.prefix} TRACK:`, event.name, event.payload);
|
|
51
|
+
}
|
|
52
|
+
identify(event) {
|
|
53
|
+
console.log(`${this.prefix} IDENTIFY:`, event.userId, event.traits);
|
|
54
|
+
}
|
|
55
|
+
page(event) {
|
|
56
|
+
console.log(`${this.prefix} PAGE:`, event.name, event.properties);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
function createConsoleConnector(config) {
|
|
60
|
+
return new ConsoleConnector(config);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// src/connectors/otel.connector.ts
|
|
64
|
+
var OtelConnector = class extends BaseConnector {
|
|
65
|
+
constructor(config) {
|
|
66
|
+
super(config);
|
|
67
|
+
this.name = "otel";
|
|
68
|
+
this.type = "observability";
|
|
69
|
+
this.serviceName = config.serviceName;
|
|
70
|
+
this.attributesExtractor = config.attributesExtractor;
|
|
71
|
+
}
|
|
72
|
+
async setup() {
|
|
73
|
+
const api = await import('@opentelemetry/api');
|
|
74
|
+
this.tracer = api.trace.getTracer(this.serviceName);
|
|
75
|
+
this.context = api.context;
|
|
76
|
+
this.log("OTEL tracer initialized");
|
|
77
|
+
}
|
|
78
|
+
track(event) {
|
|
79
|
+
if (!this.tracer) {
|
|
80
|
+
this.log("Tracer not initialized");
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const span = this.tracer.startSpan(event.name, {}, this.context.active());
|
|
84
|
+
span.setAttribute("event.name", event.name);
|
|
85
|
+
span.setAttribute("event.timestamp", event.timestamp || (/* @__PURE__ */ new Date()).toISOString());
|
|
86
|
+
if (this.attributesExtractor) {
|
|
87
|
+
const customAttrs = this.attributesExtractor(event);
|
|
88
|
+
Object.entries(customAttrs).forEach(([key, value]) => {
|
|
89
|
+
span.setAttribute(key, value);
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
Object.entries(event.payload).forEach(([key, value]) => {
|
|
93
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
94
|
+
span.setAttribute(`payload.${key}`, value);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
if (event.meta) {
|
|
98
|
+
Object.entries(event.meta).forEach(([key, value]) => {
|
|
99
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
100
|
+
span.setAttribute(`meta.${key}`, value);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
span.end();
|
|
105
|
+
this.log("Span created", { name: event.name });
|
|
106
|
+
}
|
|
107
|
+
identify(event) {
|
|
108
|
+
this.log("Identify received", { userId: event.userId });
|
|
109
|
+
}
|
|
110
|
+
page(event) {
|
|
111
|
+
this.track({
|
|
112
|
+
name: "page_view",
|
|
113
|
+
payload: { pageName: event.name, ...event.properties },
|
|
114
|
+
timestamp: event.timestamp
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
function createOtelConnector(config) {
|
|
119
|
+
return new OtelConnector(config);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// src/connectors/cloudwatch-emf.connector.ts
|
|
123
|
+
var CloudWatchEmfConnector = class extends BaseConnector {
|
|
124
|
+
constructor(config) {
|
|
125
|
+
super(config);
|
|
126
|
+
this.name = "cloudwatch-emf";
|
|
127
|
+
this.type = "metrics";
|
|
128
|
+
this.namespace = config.namespace;
|
|
129
|
+
this.serviceName = config.serviceName;
|
|
130
|
+
this.region = config.region || process.env.AWS_REGION || "us-east-1";
|
|
131
|
+
this.metricMappings = config.metricMappings || {};
|
|
132
|
+
}
|
|
133
|
+
setup() {
|
|
134
|
+
this.log("CloudWatch EMF connector initialized", {
|
|
135
|
+
namespace: this.namespace,
|
|
136
|
+
serviceName: this.serviceName,
|
|
137
|
+
mappedEvents: Object.keys(this.metricMappings)
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
track(event) {
|
|
141
|
+
const mapping = this.metricMappings[event.name];
|
|
142
|
+
const metricConfig = mapping || {
|
|
143
|
+
metricName: this.toMetricName(event.name),
|
|
144
|
+
unit: "Count",
|
|
145
|
+
dimensions: ["service"]
|
|
146
|
+
};
|
|
147
|
+
const metricValue = metricConfig.valueField ? Number(event.payload[metricConfig.valueField]) || 1 : 1;
|
|
148
|
+
const dimensions = {
|
|
149
|
+
service: this.serviceName
|
|
150
|
+
};
|
|
151
|
+
if (metricConfig.dimensions) {
|
|
152
|
+
for (const dim of metricConfig.dimensions) {
|
|
153
|
+
if (dim !== "service" && event.payload[dim] !== void 0) {
|
|
154
|
+
dimensions[dim] = String(event.payload[dim]);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
if (event.meta?.userId) dimensions["userId"] = String(event.meta.userId);
|
|
159
|
+
if (event.meta?.orgId) dimensions["orgId"] = String(event.meta.orgId);
|
|
160
|
+
const emfLog = {
|
|
161
|
+
_aws: {
|
|
162
|
+
Timestamp: Date.now(),
|
|
163
|
+
CloudWatchMetrics: [
|
|
164
|
+
{
|
|
165
|
+
Namespace: this.namespace,
|
|
166
|
+
Dimensions: [Object.keys(dimensions)],
|
|
167
|
+
Metrics: [
|
|
168
|
+
{
|
|
169
|
+
Name: metricConfig.metricName,
|
|
170
|
+
Unit: metricConfig.unit
|
|
171
|
+
}
|
|
172
|
+
]
|
|
173
|
+
}
|
|
174
|
+
]
|
|
175
|
+
},
|
|
176
|
+
// Dimensions as top-level fields
|
|
177
|
+
...dimensions,
|
|
178
|
+
// Metric value
|
|
179
|
+
[metricConfig.metricName]: metricValue,
|
|
180
|
+
// Additional context (not dimensions, just for log inspection)
|
|
181
|
+
eventName: event.name,
|
|
182
|
+
timestamp: event.timestamp,
|
|
183
|
+
payload: event.payload
|
|
184
|
+
};
|
|
185
|
+
console.log(JSON.stringify(emfLog));
|
|
186
|
+
this.log("EMF metric emitted", {
|
|
187
|
+
metric: metricConfig.metricName,
|
|
188
|
+
value: metricValue,
|
|
189
|
+
dimensions
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
identify(event) {
|
|
193
|
+
const emfLog = {
|
|
194
|
+
_aws: {
|
|
195
|
+
Timestamp: Date.now(),
|
|
196
|
+
CloudWatchMetrics: [
|
|
197
|
+
{
|
|
198
|
+
Namespace: this.namespace,
|
|
199
|
+
Dimensions: [["service"]],
|
|
200
|
+
Metrics: [
|
|
201
|
+
{
|
|
202
|
+
Name: "UserIdentified",
|
|
203
|
+
Unit: "Count"
|
|
204
|
+
}
|
|
205
|
+
]
|
|
206
|
+
}
|
|
207
|
+
]
|
|
208
|
+
},
|
|
209
|
+
service: this.serviceName,
|
|
210
|
+
UserIdentified: 1,
|
|
211
|
+
userId: event.userId,
|
|
212
|
+
traits: event.traits
|
|
213
|
+
};
|
|
214
|
+
console.log(JSON.stringify(emfLog));
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Convert event name to CloudWatch metric name
|
|
218
|
+
* e.g., 'ai_chat_completed' -> 'AiChatCompleted'
|
|
219
|
+
*/
|
|
220
|
+
toMetricName(eventName) {
|
|
221
|
+
return eventName.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
function createCloudWatchEmfConnector(config) {
|
|
225
|
+
return new CloudWatchEmfConnector(config);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// src/factories/index.ts
|
|
229
|
+
var factoryRegistry = /* @__PURE__ */ new Map();
|
|
230
|
+
function registerFactory(typeName, factory) {
|
|
231
|
+
factoryRegistry.set(typeName, factory);
|
|
232
|
+
}
|
|
233
|
+
function getFactory(typeName) {
|
|
234
|
+
return factoryRegistry.get(typeName);
|
|
235
|
+
}
|
|
236
|
+
function hasFactory(typeName) {
|
|
237
|
+
return factoryRegistry.has(typeName);
|
|
238
|
+
}
|
|
239
|
+
function getRegisteredFactories() {
|
|
240
|
+
return Array.from(factoryRegistry.keys());
|
|
241
|
+
}
|
|
242
|
+
function createConnector(typeName, config) {
|
|
243
|
+
const factory = factoryRegistry.get(typeName);
|
|
244
|
+
if (!factory) {
|
|
245
|
+
throw new Error(
|
|
246
|
+
`Unknown connector type: "${typeName}". Registered types: ${getRegisteredFactories().join(", ")}`
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
return factory(config);
|
|
250
|
+
}
|
|
251
|
+
function createConnectorsFromConfig(providers) {
|
|
252
|
+
return providers.filter((p) => p.enabled !== false).map((provider) => {
|
|
253
|
+
const connector = createConnector(provider.type, provider.config || {});
|
|
254
|
+
if (provider.name && provider.name !== connector.name) {
|
|
255
|
+
connector.name = provider.name;
|
|
256
|
+
}
|
|
257
|
+
return connector;
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
registerFactory("console", (config) => new ConsoleConnector(config));
|
|
261
|
+
registerFactory("otel", (config) => new OtelConnector(config));
|
|
262
|
+
registerFactory("cloudwatch-emf", (config) => new CloudWatchEmfConnector(config));
|
|
263
|
+
registerFactory("mixpanel", (config) => {
|
|
264
|
+
try {
|
|
265
|
+
const dynamicRequire = new Function("modulePath", "return require(modulePath)");
|
|
266
|
+
const { MixpanelConnector: MixpanelConnector2 } = dynamicRequire("../connectors/mixpanel.connector");
|
|
267
|
+
return new MixpanelConnector2(config);
|
|
268
|
+
} catch (err) {
|
|
269
|
+
throw new Error(
|
|
270
|
+
'Mixpanel connector requires Node.js environment and the "mixpanel" package. Install with: npm install mixpanel'
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
registerFactory("posthog", (config) => {
|
|
275
|
+
try {
|
|
276
|
+
const dynamicRequire = new Function("modulePath", "return require(modulePath)");
|
|
277
|
+
const { PostHogConnector: PostHogConnector2 } = dynamicRequire("../connectors/posthog.connector");
|
|
278
|
+
return new PostHogConnector2(config);
|
|
279
|
+
} catch (err) {
|
|
280
|
+
throw new Error(
|
|
281
|
+
'PostHog connector requires Node.js environment and the "posthog-node" package. Install with: npm install posthog-node'
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
// src/core/router.ts
|
|
287
|
+
var TelemetryRouter = class {
|
|
288
|
+
constructor(config = {}) {
|
|
289
|
+
this.connectors = /* @__PURE__ */ new Map();
|
|
290
|
+
this.plugins = [];
|
|
291
|
+
this.initialized = false;
|
|
292
|
+
this.config = {
|
|
293
|
+
debug: false,
|
|
294
|
+
globalMeta: {},
|
|
295
|
+
...config
|
|
296
|
+
};
|
|
297
|
+
this.plugins = config.plugins || [];
|
|
298
|
+
if (config.providers && config.providers.length > 0) {
|
|
299
|
+
try {
|
|
300
|
+
const connectors = createConnectorsFromConfig(config.providers);
|
|
301
|
+
for (const connector of connectors) {
|
|
302
|
+
this.registerConnector(connector);
|
|
303
|
+
}
|
|
304
|
+
} catch (error) {
|
|
305
|
+
this.log("Failed to auto-register providers", error);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Initialize all registered connectors
|
|
311
|
+
*/
|
|
312
|
+
async init() {
|
|
313
|
+
if (this.initialized) return;
|
|
314
|
+
const initPromises = Array.from(this.connectors.values()).map(
|
|
315
|
+
async (connector) => {
|
|
316
|
+
try {
|
|
317
|
+
await connector.init?.();
|
|
318
|
+
this.log(`Connector initialized: ${connector.name}`);
|
|
319
|
+
} catch (error) {
|
|
320
|
+
this.log(`Failed to initialize connector: ${connector.name}`, error);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
);
|
|
324
|
+
await Promise.allSettled(initPromises);
|
|
325
|
+
this.initialized = true;
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Register a connector instance directly
|
|
329
|
+
*/
|
|
330
|
+
registerConnector(connector) {
|
|
331
|
+
if (this.connectors.has(connector.name)) {
|
|
332
|
+
this.log(`Connector "${connector.name}" already registered, replacing...`);
|
|
333
|
+
}
|
|
334
|
+
this.connectors.set(connector.name, connector);
|
|
335
|
+
this.log(`Connector registered: ${connector.name} (${connector.type})`);
|
|
336
|
+
return this;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Register connector using a factory
|
|
340
|
+
*/
|
|
341
|
+
use(factory, config) {
|
|
342
|
+
const connector = factory.create(config);
|
|
343
|
+
return this.registerConnector(connector);
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Unregister a connector by name
|
|
347
|
+
*/
|
|
348
|
+
unregisterConnector(name) {
|
|
349
|
+
const connector = this.connectors.get(name);
|
|
350
|
+
if (connector) {
|
|
351
|
+
connector.shutdown?.();
|
|
352
|
+
this.connectors.delete(name);
|
|
353
|
+
this.log(`Connector unregistered: ${name}`);
|
|
354
|
+
}
|
|
355
|
+
return this;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Add a plugin
|
|
359
|
+
*/
|
|
360
|
+
addPlugin(plugin) {
|
|
361
|
+
this.plugins.push(plugin);
|
|
362
|
+
this.log(`Plugin added: ${plugin.name}`);
|
|
363
|
+
return this;
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Track a custom event
|
|
367
|
+
*/
|
|
368
|
+
async track(eventName, payload = {}) {
|
|
369
|
+
const event = {
|
|
370
|
+
name: eventName,
|
|
371
|
+
payload,
|
|
372
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
373
|
+
meta: { ...this.config.globalMeta }
|
|
374
|
+
};
|
|
375
|
+
return this.dispatch("track", event);
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Identify a user
|
|
379
|
+
*/
|
|
380
|
+
async identify(userId, traits = {}) {
|
|
381
|
+
const event = {
|
|
382
|
+
userId,
|
|
383
|
+
traits,
|
|
384
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
385
|
+
};
|
|
386
|
+
const telemetryEvent = {
|
|
387
|
+
name: "identify",
|
|
388
|
+
payload: { userId, traits },
|
|
389
|
+
timestamp: event.timestamp,
|
|
390
|
+
meta: { ...this.config.globalMeta, userId }
|
|
391
|
+
};
|
|
392
|
+
return this.dispatch("identify", telemetryEvent, event);
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Track a page view
|
|
396
|
+
*/
|
|
397
|
+
async page(name, properties = {}) {
|
|
398
|
+
const event = {
|
|
399
|
+
name,
|
|
400
|
+
properties,
|
|
401
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
402
|
+
};
|
|
403
|
+
const telemetryEvent = {
|
|
404
|
+
name: "page_view",
|
|
405
|
+
payload: { pageName: name, ...properties },
|
|
406
|
+
timestamp: event.timestamp,
|
|
407
|
+
meta: { ...this.config.globalMeta }
|
|
408
|
+
};
|
|
409
|
+
return this.dispatch("page", telemetryEvent, event);
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Core dispatch method - sends to all connectors in parallel
|
|
413
|
+
*/
|
|
414
|
+
async dispatch(method, event, originalEvent) {
|
|
415
|
+
let processedEvent = event;
|
|
416
|
+
for (const plugin of this.plugins) {
|
|
417
|
+
if (plugin.beforeDispatch) {
|
|
418
|
+
processedEvent = plugin.beforeDispatch(processedEvent);
|
|
419
|
+
if (!processedEvent) {
|
|
420
|
+
this.log(`Event blocked by plugin: ${plugin.name}`);
|
|
421
|
+
return {
|
|
422
|
+
event,
|
|
423
|
+
results: [],
|
|
424
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
const connectors = Array.from(this.connectors.values());
|
|
430
|
+
const startTime = Date.now();
|
|
431
|
+
const settledResults = await Promise.allSettled(
|
|
432
|
+
connectors.map(async (connector) => {
|
|
433
|
+
const connectorStart = Date.now();
|
|
434
|
+
try {
|
|
435
|
+
switch (method) {
|
|
436
|
+
case "track":
|
|
437
|
+
await connector.track(processedEvent);
|
|
438
|
+
break;
|
|
439
|
+
case "identify":
|
|
440
|
+
await connector.identify?.(originalEvent);
|
|
441
|
+
break;
|
|
442
|
+
case "page":
|
|
443
|
+
await connector.page?.(originalEvent);
|
|
444
|
+
break;
|
|
445
|
+
}
|
|
446
|
+
return {
|
|
447
|
+
connector: connector.name,
|
|
448
|
+
success: true,
|
|
449
|
+
duration: Date.now() - connectorStart
|
|
450
|
+
};
|
|
451
|
+
} catch (error) {
|
|
452
|
+
return {
|
|
453
|
+
connector: connector.name,
|
|
454
|
+
success: false,
|
|
455
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
456
|
+
duration: Date.now() - connectorStart
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
})
|
|
460
|
+
);
|
|
461
|
+
const results = settledResults.map((result) => {
|
|
462
|
+
if (result.status === "fulfilled") {
|
|
463
|
+
return result.value;
|
|
464
|
+
}
|
|
465
|
+
return {
|
|
466
|
+
connector: "unknown",
|
|
467
|
+
success: false,
|
|
468
|
+
error: result.reason
|
|
469
|
+
};
|
|
470
|
+
});
|
|
471
|
+
this.log(`Event dispatched: ${event.name}`, {
|
|
472
|
+
duration: Date.now() - startTime,
|
|
473
|
+
results: results.map((r) => ({
|
|
474
|
+
connector: r.connector,
|
|
475
|
+
success: r.success
|
|
476
|
+
}))
|
|
477
|
+
});
|
|
478
|
+
for (const plugin of this.plugins) {
|
|
479
|
+
plugin.afterDispatch?.(processedEvent, results);
|
|
480
|
+
}
|
|
481
|
+
return {
|
|
482
|
+
event: processedEvent,
|
|
483
|
+
results,
|
|
484
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Get all registered connector names
|
|
489
|
+
*/
|
|
490
|
+
getConnectors() {
|
|
491
|
+
return Array.from(this.connectors.keys());
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Get connectors by type
|
|
495
|
+
*/
|
|
496
|
+
getConnectorsByType(type) {
|
|
497
|
+
return Array.from(this.connectors.values()).filter((c) => c.type === type).map((c) => c.name);
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* Shutdown all connectors
|
|
501
|
+
*/
|
|
502
|
+
async shutdown() {
|
|
503
|
+
const shutdownPromises = Array.from(this.connectors.values()).map(
|
|
504
|
+
async (connector) => {
|
|
505
|
+
try {
|
|
506
|
+
await connector.shutdown?.();
|
|
507
|
+
this.log(`Connector shutdown: ${connector.name}`);
|
|
508
|
+
} catch (error) {
|
|
509
|
+
this.log(`Failed to shutdown connector: ${connector.name}`, error);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
);
|
|
513
|
+
await Promise.allSettled(shutdownPromises);
|
|
514
|
+
this.connectors.clear();
|
|
515
|
+
this.initialized = false;
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* Internal logger
|
|
519
|
+
*/
|
|
520
|
+
log(message, data) {
|
|
521
|
+
if (this.config.debug) {
|
|
522
|
+
console.log(`[TelemetryRouter] ${message}`, data || "");
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
function createTelemetryRouter(config) {
|
|
527
|
+
return new TelemetryRouter(config);
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
// src/core/config.ts
|
|
531
|
+
function validateConfig(config) {
|
|
532
|
+
if (!config.app) {
|
|
533
|
+
throw new Error('TelemetryConfig: "app" is required');
|
|
534
|
+
}
|
|
535
|
+
if (config.analytics.provider !== "none") {
|
|
536
|
+
const providerConfig = config.analytics[config.analytics.provider];
|
|
537
|
+
if (!providerConfig) {
|
|
538
|
+
throw new Error(
|
|
539
|
+
`TelemetryConfig: Missing config for analytics provider "${config.analytics.provider}"`
|
|
540
|
+
);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
if (config.observability.provider !== "none") {
|
|
544
|
+
const providerConfig = config.observability[config.observability.provider];
|
|
545
|
+
if (!providerConfig) {
|
|
546
|
+
throw new Error(
|
|
547
|
+
`TelemetryConfig: Missing config for observability provider "${config.observability.provider}"`
|
|
548
|
+
);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
if (config.metrics?.provider && config.metrics.provider !== "none") {
|
|
552
|
+
const key = config.metrics.provider === "cloudwatch-emf" ? "cloudwatchEmf" : config.metrics.provider;
|
|
553
|
+
const providerConfig = config.metrics[key];
|
|
554
|
+
if (!providerConfig) {
|
|
555
|
+
throw new Error(
|
|
556
|
+
`TelemetryConfig: Missing config for metrics provider "${config.metrics.provider}"`
|
|
557
|
+
);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
// src/context/index.ts
|
|
563
|
+
async function getTraceHeaders() {
|
|
564
|
+
try {
|
|
565
|
+
const { context, propagation, trace } = await import('@opentelemetry/api');
|
|
566
|
+
const headers = {};
|
|
567
|
+
propagation.inject(context.active(), headers);
|
|
568
|
+
if (!headers["traceparent"]) {
|
|
569
|
+
const traceId = generateTraceId();
|
|
570
|
+
const spanId = generateSpanId();
|
|
571
|
+
headers["traceparent"] = generateTraceparent(traceId, spanId, 1);
|
|
572
|
+
}
|
|
573
|
+
return headers;
|
|
574
|
+
} catch {
|
|
575
|
+
const traceId = generateTraceId();
|
|
576
|
+
const spanId = generateSpanId();
|
|
577
|
+
return {
|
|
578
|
+
traceparent: generateTraceparent(traceId, spanId, 1)
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
function getTraceHeadersSync() {
|
|
583
|
+
try {
|
|
584
|
+
const { context, propagation } = __require("@opentelemetry/api");
|
|
585
|
+
const headers = {};
|
|
586
|
+
propagation.inject(context.active(), headers);
|
|
587
|
+
if (!headers["traceparent"]) {
|
|
588
|
+
const traceId = generateTraceId();
|
|
589
|
+
const spanId = generateSpanId();
|
|
590
|
+
headers["traceparent"] = generateTraceparent(traceId, spanId, 1);
|
|
591
|
+
}
|
|
592
|
+
return headers;
|
|
593
|
+
} catch {
|
|
594
|
+
const traceId = generateTraceId();
|
|
595
|
+
const spanId = generateSpanId();
|
|
596
|
+
return {
|
|
597
|
+
traceparent: generateTraceparent(traceId, spanId, 1)
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
async function extractTraceContext(headers) {
|
|
602
|
+
try {
|
|
603
|
+
const { trace, context, propagation, isSpanContextValid } = await import('@opentelemetry/api');
|
|
604
|
+
const normalizedHeaders = {};
|
|
605
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
606
|
+
const lowerKey = key.toLowerCase();
|
|
607
|
+
if (typeof value === "string") {
|
|
608
|
+
normalizedHeaders[lowerKey] = value;
|
|
609
|
+
} else if (Array.isArray(value)) {
|
|
610
|
+
normalizedHeaders[lowerKey] = value[0] || "";
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
const extractedContext = propagation.extract(context.active(), normalizedHeaders);
|
|
614
|
+
const spanContext = trace.getSpanContext(extractedContext);
|
|
615
|
+
if (!spanContext || !isSpanContextValid(spanContext)) {
|
|
616
|
+
const traceparent = normalizedHeaders["traceparent"];
|
|
617
|
+
if (traceparent) {
|
|
618
|
+
const parsed = parseTraceparent(traceparent);
|
|
619
|
+
if (parsed) {
|
|
620
|
+
return {
|
|
621
|
+
traceId: parsed.traceId,
|
|
622
|
+
spanId: parsed.spanId,
|
|
623
|
+
traceFlags: parsed.traceFlags
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
return null;
|
|
628
|
+
}
|
|
629
|
+
return {
|
|
630
|
+
traceId: spanContext.traceId,
|
|
631
|
+
spanId: spanContext.spanId,
|
|
632
|
+
traceFlags: spanContext.traceFlags
|
|
633
|
+
};
|
|
634
|
+
} catch {
|
|
635
|
+
const traceparent = headers["traceparent"] || headers["Traceparent"];
|
|
636
|
+
if (traceparent) {
|
|
637
|
+
const value = typeof traceparent === "string" ? traceparent : traceparent[0];
|
|
638
|
+
const parsed = parseTraceparent(value || "");
|
|
639
|
+
if (parsed) {
|
|
640
|
+
return {
|
|
641
|
+
traceId: parsed.traceId,
|
|
642
|
+
spanId: parsed.spanId,
|
|
643
|
+
traceFlags: parsed.traceFlags
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
return null;
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
async function withTraceContext(headers, fn) {
|
|
651
|
+
try {
|
|
652
|
+
const { context, propagation } = await import('@opentelemetry/api');
|
|
653
|
+
const normalizedHeaders = {};
|
|
654
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
655
|
+
if (typeof value === "string") {
|
|
656
|
+
normalizedHeaders[key] = value;
|
|
657
|
+
} else if (Array.isArray(value)) {
|
|
658
|
+
normalizedHeaders[key] = value[0] || "";
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
const extractedContext = propagation.extract(context.active(), normalizedHeaders);
|
|
662
|
+
return context.with(extractedContext, fn);
|
|
663
|
+
} catch {
|
|
664
|
+
return fn();
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
async function startSpan(name, serviceName = "telemetry") {
|
|
668
|
+
try {
|
|
669
|
+
const { trace } = await import('@opentelemetry/api');
|
|
670
|
+
const tracer = trace.getTracer(serviceName);
|
|
671
|
+
return tracer.startSpan(name);
|
|
672
|
+
} catch {
|
|
673
|
+
return {
|
|
674
|
+
setAttribute: () => {
|
|
675
|
+
},
|
|
676
|
+
setStatus: () => {
|
|
677
|
+
},
|
|
678
|
+
addEvent: () => {
|
|
679
|
+
},
|
|
680
|
+
end: () => {
|
|
681
|
+
},
|
|
682
|
+
spanContext: () => ({ traceId: "", spanId: "", traceFlags: 0 })
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
function parseTraceparent(traceparent) {
|
|
687
|
+
if (!traceparent) return null;
|
|
688
|
+
const parts = traceparent.split("-");
|
|
689
|
+
if (parts.length !== 4) return null;
|
|
690
|
+
const [version, traceId, spanId, flags] = parts;
|
|
691
|
+
if (version.length !== 2 || traceId.length !== 32 || spanId.length !== 16 || flags.length !== 2) {
|
|
692
|
+
return null;
|
|
693
|
+
}
|
|
694
|
+
return {
|
|
695
|
+
version,
|
|
696
|
+
traceId,
|
|
697
|
+
spanId,
|
|
698
|
+
traceFlags: parseInt(flags, 16)
|
|
699
|
+
};
|
|
700
|
+
}
|
|
701
|
+
function generateTraceparent(traceId, spanId, traceFlags = 1) {
|
|
702
|
+
const flagsHex = traceFlags.toString(16).padStart(2, "0");
|
|
703
|
+
return `00-${traceId}-${spanId}-${flagsHex}`;
|
|
704
|
+
}
|
|
705
|
+
function generateTraceId() {
|
|
706
|
+
const bytes = new Uint8Array(16);
|
|
707
|
+
if (typeof crypto !== "undefined" && crypto.getRandomValues) {
|
|
708
|
+
crypto.getRandomValues(bytes);
|
|
709
|
+
} else {
|
|
710
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
711
|
+
bytes[i] = Math.floor(Math.random() * 256);
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
715
|
+
}
|
|
716
|
+
function generateSpanId() {
|
|
717
|
+
const bytes = new Uint8Array(8);
|
|
718
|
+
if (typeof crypto !== "undefined" && crypto.getRandomValues) {
|
|
719
|
+
crypto.getRandomValues(bytes);
|
|
720
|
+
} else {
|
|
721
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
722
|
+
bytes[i] = Math.floor(Math.random() * 256);
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
// src/utils/index.ts
|
|
729
|
+
function detectEnvironment() {
|
|
730
|
+
if (typeof window !== "undefined" && typeof document !== "undefined") {
|
|
731
|
+
return "browser";
|
|
732
|
+
}
|
|
733
|
+
return "node";
|
|
734
|
+
}
|
|
735
|
+
function generateSessionId() {
|
|
736
|
+
const timestamp = Date.now().toString(36);
|
|
737
|
+
const randomPart = Math.random().toString(36).substring(2, 10);
|
|
738
|
+
return `${timestamp}-${randomPart}`;
|
|
739
|
+
}
|
|
740
|
+
function generateEventId() {
|
|
741
|
+
return `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
|
|
742
|
+
}
|
|
743
|
+
function safeStringify(obj, space) {
|
|
744
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
745
|
+
return JSON.stringify(
|
|
746
|
+
obj,
|
|
747
|
+
(key, value) => {
|
|
748
|
+
if (typeof value === "object" && value !== null) {
|
|
749
|
+
if (seen.has(value)) {
|
|
750
|
+
return "[Circular]";
|
|
751
|
+
}
|
|
752
|
+
seen.add(value);
|
|
753
|
+
}
|
|
754
|
+
if (typeof value === "bigint") {
|
|
755
|
+
return value.toString();
|
|
756
|
+
}
|
|
757
|
+
if (value instanceof Error) {
|
|
758
|
+
return {
|
|
759
|
+
name: value.name,
|
|
760
|
+
message: value.message,
|
|
761
|
+
stack: value.stack
|
|
762
|
+
};
|
|
763
|
+
}
|
|
764
|
+
return value;
|
|
765
|
+
},
|
|
766
|
+
space
|
|
767
|
+
);
|
|
768
|
+
}
|
|
769
|
+
function deepMerge(target, source) {
|
|
770
|
+
const result = { ...target };
|
|
771
|
+
for (const key in source) {
|
|
772
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
773
|
+
const sourceValue = source[key];
|
|
774
|
+
const targetValue = result[key];
|
|
775
|
+
if (isObject(sourceValue) && isObject(targetValue)) {
|
|
776
|
+
result[key] = deepMerge(targetValue, sourceValue);
|
|
777
|
+
} else if (sourceValue !== void 0) {
|
|
778
|
+
result[key] = sourceValue;
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
return result;
|
|
783
|
+
}
|
|
784
|
+
function isObject(value) {
|
|
785
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
786
|
+
}
|
|
787
|
+
function sanitizePayload(payload, sensitiveFields = ["password", "token", "secret", "apiKey", "api_key", "authorization"]) {
|
|
788
|
+
const result = {};
|
|
789
|
+
for (const [key, value] of Object.entries(payload)) {
|
|
790
|
+
const lowerKey = key.toLowerCase();
|
|
791
|
+
if (sensitiveFields.some((field) => lowerKey.includes(field.toLowerCase()))) {
|
|
792
|
+
result[key] = "[REDACTED]";
|
|
793
|
+
} else if (isObject(value)) {
|
|
794
|
+
result[key] = sanitizePayload(value, sensitiveFields);
|
|
795
|
+
} else {
|
|
796
|
+
result[key] = value;
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
return result;
|
|
800
|
+
}
|
|
801
|
+
function extractFields(obj, fields) {
|
|
802
|
+
const result = {};
|
|
803
|
+
for (const field of fields) {
|
|
804
|
+
if (field in obj) {
|
|
805
|
+
result[field] = obj[field];
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
return result;
|
|
809
|
+
}
|
|
810
|
+
function flattenObject(obj, prefix = "") {
|
|
811
|
+
const result = {};
|
|
812
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
813
|
+
const newKey = prefix ? `${prefix}.${key}` : key;
|
|
814
|
+
if (isObject(value) && Object.keys(value).length > 0) {
|
|
815
|
+
Object.assign(result, flattenObject(value, newKey));
|
|
816
|
+
} else {
|
|
817
|
+
result[newKey] = value;
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
return result;
|
|
821
|
+
}
|
|
822
|
+
async function retryWithBackoff(fn, options = {}) {
|
|
823
|
+
const { maxRetries = 3, initialDelay = 100, maxDelay = 5e3, factor = 2 } = options;
|
|
824
|
+
let lastError;
|
|
825
|
+
let delay = initialDelay;
|
|
826
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
827
|
+
try {
|
|
828
|
+
return await fn();
|
|
829
|
+
} catch (error) {
|
|
830
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
831
|
+
if (attempt === maxRetries) {
|
|
832
|
+
break;
|
|
833
|
+
}
|
|
834
|
+
await sleep(delay);
|
|
835
|
+
delay = Math.min(delay * factor, maxDelay);
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
throw lastError;
|
|
839
|
+
}
|
|
840
|
+
function sleep(ms) {
|
|
841
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
842
|
+
}
|
|
843
|
+
function debounce(fn, delay) {
|
|
844
|
+
let timeoutId = null;
|
|
845
|
+
return (...args) => {
|
|
846
|
+
if (timeoutId) {
|
|
847
|
+
clearTimeout(timeoutId);
|
|
848
|
+
}
|
|
849
|
+
timeoutId = setTimeout(() => {
|
|
850
|
+
fn(...args);
|
|
851
|
+
timeoutId = null;
|
|
852
|
+
}, delay);
|
|
853
|
+
};
|
|
854
|
+
}
|
|
855
|
+
async function processBatch(items, processor, batchSize = 10) {
|
|
856
|
+
const results = [];
|
|
857
|
+
for (let i = 0; i < items.length; i += batchSize) {
|
|
858
|
+
const batch = items.slice(i, i + batchSize);
|
|
859
|
+
const result = await processor(batch);
|
|
860
|
+
results.push(result);
|
|
861
|
+
}
|
|
862
|
+
return results;
|
|
863
|
+
}
|
|
864
|
+
function createCache(defaultTtl = 6e4) {
|
|
865
|
+
const cache = /* @__PURE__ */ new Map();
|
|
866
|
+
return {
|
|
867
|
+
get(key) {
|
|
868
|
+
const entry = cache.get(key);
|
|
869
|
+
if (!entry) return void 0;
|
|
870
|
+
if (Date.now() > entry.expires) {
|
|
871
|
+
cache.delete(key);
|
|
872
|
+
return void 0;
|
|
873
|
+
}
|
|
874
|
+
return entry.value;
|
|
875
|
+
},
|
|
876
|
+
set(key, value, ttl = defaultTtl) {
|
|
877
|
+
cache.set(key, { value, expires: Date.now() + ttl });
|
|
878
|
+
},
|
|
879
|
+
delete(key) {
|
|
880
|
+
return cache.delete(key);
|
|
881
|
+
},
|
|
882
|
+
clear() {
|
|
883
|
+
cache.clear();
|
|
884
|
+
},
|
|
885
|
+
size() {
|
|
886
|
+
return cache.size;
|
|
887
|
+
}
|
|
888
|
+
};
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
// src/connectors/mixpanel.connector.ts
|
|
892
|
+
var MixpanelConnector = class extends BaseConnector {
|
|
893
|
+
constructor(config) {
|
|
894
|
+
super(config);
|
|
895
|
+
this.name = "mixpanel";
|
|
896
|
+
this.type = "analytics";
|
|
897
|
+
this.token = config.token;
|
|
898
|
+
this.trackFields = config.trackFields;
|
|
899
|
+
}
|
|
900
|
+
async setup() {
|
|
901
|
+
const Mixpanel = await import('mixpanel');
|
|
902
|
+
this.client = Mixpanel.init(this.token);
|
|
903
|
+
this.log("Mixpanel client initialized");
|
|
904
|
+
}
|
|
905
|
+
track(event) {
|
|
906
|
+
if (!this.client) {
|
|
907
|
+
this.log("Client not initialized");
|
|
908
|
+
return;
|
|
909
|
+
}
|
|
910
|
+
let properties = event.payload;
|
|
911
|
+
if (this.trackFields && this.trackFields.length > 0) {
|
|
912
|
+
properties = {};
|
|
913
|
+
this.trackFields.forEach((field) => {
|
|
914
|
+
if (event.payload[field] !== void 0) {
|
|
915
|
+
properties[field] = event.payload[field];
|
|
916
|
+
}
|
|
917
|
+
});
|
|
918
|
+
}
|
|
919
|
+
const mixpanelProps = {
|
|
920
|
+
...properties,
|
|
921
|
+
distinct_id: event.meta?.userId,
|
|
922
|
+
time: event.timestamp ? new Date(event.timestamp).getTime() / 1e3 : void 0
|
|
923
|
+
};
|
|
924
|
+
this.client.track(event.name, mixpanelProps);
|
|
925
|
+
this.log("Event tracked", { name: event.name });
|
|
926
|
+
}
|
|
927
|
+
identify(event) {
|
|
928
|
+
if (!this.client) return;
|
|
929
|
+
this.client.people.set(event.userId, {
|
|
930
|
+
...event.traits,
|
|
931
|
+
$last_seen: (/* @__PURE__ */ new Date()).toISOString()
|
|
932
|
+
});
|
|
933
|
+
this.log("User identified", { userId: event.userId });
|
|
934
|
+
}
|
|
935
|
+
page(event) {
|
|
936
|
+
this.track({
|
|
937
|
+
name: "Page View",
|
|
938
|
+
payload: { page: event.name, ...event.properties },
|
|
939
|
+
timestamp: event.timestamp
|
|
940
|
+
});
|
|
941
|
+
}
|
|
942
|
+
};
|
|
943
|
+
function createMixpanelConnector(config) {
|
|
944
|
+
return new MixpanelConnector(config);
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
// src/connectors/posthog.connector.ts
|
|
948
|
+
var PostHogConnector = class extends BaseConnector {
|
|
949
|
+
constructor(config) {
|
|
950
|
+
super(config);
|
|
951
|
+
this.name = "posthog";
|
|
952
|
+
this.type = "analytics";
|
|
953
|
+
this.apiKey = config.apiKey;
|
|
954
|
+
this.host = config.host || "https://app.posthog.com";
|
|
955
|
+
}
|
|
956
|
+
async setup() {
|
|
957
|
+
const { PostHog } = await import('posthog-node');
|
|
958
|
+
this.client = new PostHog(this.apiKey, { host: this.host });
|
|
959
|
+
this.log("PostHog client initialized");
|
|
960
|
+
}
|
|
961
|
+
track(event) {
|
|
962
|
+
if (!this.client) return;
|
|
963
|
+
this.client.capture({
|
|
964
|
+
distinctId: event.meta?.userId || event.payload.user_id || "anonymous",
|
|
965
|
+
event: event.name,
|
|
966
|
+
properties: event.payload,
|
|
967
|
+
timestamp: event.timestamp ? new Date(event.timestamp) : void 0
|
|
968
|
+
});
|
|
969
|
+
this.log("Event captured", { name: event.name });
|
|
970
|
+
this.client.flush().catch(() => {
|
|
971
|
+
});
|
|
972
|
+
}
|
|
973
|
+
identify(event) {
|
|
974
|
+
if (!this.client) return;
|
|
975
|
+
this.client.identify({
|
|
976
|
+
distinctId: event.userId,
|
|
977
|
+
properties: event.traits
|
|
978
|
+
});
|
|
979
|
+
this.log("User identified", { userId: event.userId });
|
|
980
|
+
}
|
|
981
|
+
page(event) {
|
|
982
|
+
this.track({
|
|
983
|
+
name: "$pageview",
|
|
984
|
+
payload: { $current_url: event.name, ...event.properties },
|
|
985
|
+
timestamp: event.timestamp
|
|
986
|
+
});
|
|
987
|
+
}
|
|
988
|
+
async shutdown() {
|
|
989
|
+
await this.client?.shutdown();
|
|
990
|
+
await super.shutdown();
|
|
991
|
+
}
|
|
992
|
+
};
|
|
993
|
+
function createPostHogConnector(config) {
|
|
994
|
+
return new PostHogConnector(config);
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
export { BaseConnector, CloudWatchEmfConnector, ConsoleConnector, MixpanelConnector, OtelConnector, PostHogConnector, TelemetryRouter, createCache, createCloudWatchEmfConnector, createConnector, createConnectorsFromConfig, createConsoleConnector, createMixpanelConnector, createOtelConnector, createPostHogConnector, createTelemetryRouter, debounce, deepMerge, detectEnvironment, extractFields, extractTraceContext, factoryRegistry, flattenObject, generateEventId, generateSessionId, generateSpanId, generateTraceId, generateTraceparent, getFactory, getRegisteredFactories, getTraceHeaders, getTraceHeadersSync, hasFactory, isObject, parseTraceparent, processBatch, registerFactory, retryWithBackoff, safeStringify, sanitizePayload, sleep, startSpan, validateConfig, withTraceContext };
|
|
998
|
+
//# sourceMappingURL=index.mjs.map
|
|
999
|
+
//# sourceMappingURL=index.mjs.map
|