evlog 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/posthog.d.mts +72 -0
- package/dist/adapters/posthog.d.ts +72 -0
- package/dist/adapters/posthog.mjs +79 -0
- package/dist/nitro/plugin.mjs +9 -4
- package/package.json +11 -4
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { DrainContext, WideEvent } from '../types.mjs';
|
|
2
|
+
|
|
3
|
+
interface PostHogConfig {
|
|
4
|
+
/** PostHog project API key */
|
|
5
|
+
apiKey: string;
|
|
6
|
+
/** PostHog host URL. Default: https://us.i.posthog.com */
|
|
7
|
+
host?: string;
|
|
8
|
+
/** PostHog event name. Default: evlog_wide_event */
|
|
9
|
+
eventName?: string;
|
|
10
|
+
/** Override distinct_id (defaults to event.service) */
|
|
11
|
+
distinctId?: string;
|
|
12
|
+
/** Request timeout in milliseconds. Default: 5000 */
|
|
13
|
+
timeout?: number;
|
|
14
|
+
}
|
|
15
|
+
/** PostHog event structure for the batch API */
|
|
16
|
+
interface PostHogEvent {
|
|
17
|
+
event: string;
|
|
18
|
+
distinct_id: string;
|
|
19
|
+
timestamp: string;
|
|
20
|
+
properties: Record<string, unknown>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Convert a WideEvent to a PostHog event format.
|
|
24
|
+
*/
|
|
25
|
+
declare function toPostHogEvent(event: WideEvent, config: PostHogConfig): PostHogEvent;
|
|
26
|
+
/**
|
|
27
|
+
* Create a drain function for sending logs to PostHog.
|
|
28
|
+
*
|
|
29
|
+
* Configuration priority (highest to lowest):
|
|
30
|
+
* 1. Overrides passed to createPostHogDrain()
|
|
31
|
+
* 2. runtimeConfig.evlog.posthog
|
|
32
|
+
* 3. runtimeConfig.posthog
|
|
33
|
+
* 4. Environment variables: NUXT_POSTHOG_*, POSTHOG_*
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* // Zero config - just set NUXT_POSTHOG_API_KEY env var
|
|
38
|
+
* nitroApp.hooks.hook('evlog:drain', createPostHogDrain())
|
|
39
|
+
*
|
|
40
|
+
* // With overrides
|
|
41
|
+
* nitroApp.hooks.hook('evlog:drain', createPostHogDrain({
|
|
42
|
+
* apiKey: 'phc_...',
|
|
43
|
+
* host: 'https://eu.i.posthog.com',
|
|
44
|
+
* }))
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
declare function createPostHogDrain(overrides?: Partial<PostHogConfig>): (ctx: DrainContext) => Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Send a single event to PostHog.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* await sendToPostHog(event, {
|
|
54
|
+
* apiKey: process.env.POSTHOG_API_KEY!,
|
|
55
|
+
* })
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
declare function sendToPostHog(event: WideEvent, config: PostHogConfig): Promise<void>;
|
|
59
|
+
/**
|
|
60
|
+
* Send a batch of events to PostHog.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```ts
|
|
64
|
+
* await sendBatchToPostHog(events, {
|
|
65
|
+
* apiKey: process.env.POSTHOG_API_KEY!,
|
|
66
|
+
* })
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
declare function sendBatchToPostHog(events: WideEvent[], config: PostHogConfig): Promise<void>;
|
|
70
|
+
|
|
71
|
+
export { createPostHogDrain, sendBatchToPostHog, sendToPostHog, toPostHogEvent };
|
|
72
|
+
export type { PostHogConfig, PostHogEvent };
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { DrainContext, WideEvent } from '../types.js';
|
|
2
|
+
|
|
3
|
+
interface PostHogConfig {
|
|
4
|
+
/** PostHog project API key */
|
|
5
|
+
apiKey: string;
|
|
6
|
+
/** PostHog host URL. Default: https://us.i.posthog.com */
|
|
7
|
+
host?: string;
|
|
8
|
+
/** PostHog event name. Default: evlog_wide_event */
|
|
9
|
+
eventName?: string;
|
|
10
|
+
/** Override distinct_id (defaults to event.service) */
|
|
11
|
+
distinctId?: string;
|
|
12
|
+
/** Request timeout in milliseconds. Default: 5000 */
|
|
13
|
+
timeout?: number;
|
|
14
|
+
}
|
|
15
|
+
/** PostHog event structure for the batch API */
|
|
16
|
+
interface PostHogEvent {
|
|
17
|
+
event: string;
|
|
18
|
+
distinct_id: string;
|
|
19
|
+
timestamp: string;
|
|
20
|
+
properties: Record<string, unknown>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Convert a WideEvent to a PostHog event format.
|
|
24
|
+
*/
|
|
25
|
+
declare function toPostHogEvent(event: WideEvent, config: PostHogConfig): PostHogEvent;
|
|
26
|
+
/**
|
|
27
|
+
* Create a drain function for sending logs to PostHog.
|
|
28
|
+
*
|
|
29
|
+
* Configuration priority (highest to lowest):
|
|
30
|
+
* 1. Overrides passed to createPostHogDrain()
|
|
31
|
+
* 2. runtimeConfig.evlog.posthog
|
|
32
|
+
* 3. runtimeConfig.posthog
|
|
33
|
+
* 4. Environment variables: NUXT_POSTHOG_*, POSTHOG_*
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* // Zero config - just set NUXT_POSTHOG_API_KEY env var
|
|
38
|
+
* nitroApp.hooks.hook('evlog:drain', createPostHogDrain())
|
|
39
|
+
*
|
|
40
|
+
* // With overrides
|
|
41
|
+
* nitroApp.hooks.hook('evlog:drain', createPostHogDrain({
|
|
42
|
+
* apiKey: 'phc_...',
|
|
43
|
+
* host: 'https://eu.i.posthog.com',
|
|
44
|
+
* }))
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
declare function createPostHogDrain(overrides?: Partial<PostHogConfig>): (ctx: DrainContext) => Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Send a single event to PostHog.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* await sendToPostHog(event, {
|
|
54
|
+
* apiKey: process.env.POSTHOG_API_KEY!,
|
|
55
|
+
* })
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
declare function sendToPostHog(event: WideEvent, config: PostHogConfig): Promise<void>;
|
|
59
|
+
/**
|
|
60
|
+
* Send a batch of events to PostHog.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```ts
|
|
64
|
+
* await sendBatchToPostHog(events, {
|
|
65
|
+
* apiKey: process.env.POSTHOG_API_KEY!,
|
|
66
|
+
* })
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
declare function sendBatchToPostHog(events: WideEvent[], config: PostHogConfig): Promise<void>;
|
|
70
|
+
|
|
71
|
+
export { createPostHogDrain, sendBatchToPostHog, sendToPostHog, toPostHogEvent };
|
|
72
|
+
export type { PostHogConfig, PostHogEvent };
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
function getRuntimeConfig() {
|
|
2
|
+
try {
|
|
3
|
+
const { useRuntimeConfig } = require("nitropack/runtime");
|
|
4
|
+
return useRuntimeConfig();
|
|
5
|
+
} catch {
|
|
6
|
+
return void 0;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
function toPostHogEvent(event, config) {
|
|
10
|
+
const { timestamp, level, service, ...rest } = event;
|
|
11
|
+
return {
|
|
12
|
+
event: config.eventName ?? "evlog_wide_event",
|
|
13
|
+
distinct_id: config.distinctId ?? service,
|
|
14
|
+
timestamp,
|
|
15
|
+
properties: {
|
|
16
|
+
level,
|
|
17
|
+
service,
|
|
18
|
+
...rest
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function createPostHogDrain(overrides) {
|
|
23
|
+
return async (ctx) => {
|
|
24
|
+
const runtimeConfig = getRuntimeConfig();
|
|
25
|
+
const evlogPostHog = runtimeConfig?.evlog?.posthog;
|
|
26
|
+
const rootPostHog = runtimeConfig?.posthog;
|
|
27
|
+
const config = {
|
|
28
|
+
apiKey: overrides?.apiKey ?? evlogPostHog?.apiKey ?? rootPostHog?.apiKey ?? process.env.NUXT_POSTHOG_API_KEY ?? process.env.POSTHOG_API_KEY,
|
|
29
|
+
host: overrides?.host ?? evlogPostHog?.host ?? rootPostHog?.host ?? process.env.NUXT_POSTHOG_HOST ?? process.env.POSTHOG_HOST,
|
|
30
|
+
eventName: overrides?.eventName ?? evlogPostHog?.eventName ?? rootPostHog?.eventName,
|
|
31
|
+
distinctId: overrides?.distinctId ?? evlogPostHog?.distinctId ?? rootPostHog?.distinctId,
|
|
32
|
+
timeout: overrides?.timeout ?? evlogPostHog?.timeout ?? rootPostHog?.timeout
|
|
33
|
+
};
|
|
34
|
+
if (!config.apiKey) {
|
|
35
|
+
console.error("[evlog/posthog] Missing apiKey. Set NUXT_POSTHOG_API_KEY/POSTHOG_API_KEY env var or pass to createPostHogDrain()");
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
await sendToPostHog(ctx.event, config);
|
|
40
|
+
} catch (error) {
|
|
41
|
+
console.error("[evlog/posthog] Failed to send event:", error);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
async function sendToPostHog(event, config) {
|
|
46
|
+
await sendBatchToPostHog([event], config);
|
|
47
|
+
}
|
|
48
|
+
async function sendBatchToPostHog(events, config) {
|
|
49
|
+
if (events.length === 0) return;
|
|
50
|
+
const host = (config.host ?? "https://us.i.posthog.com").replace(/\/$/, "");
|
|
51
|
+
const timeout = config.timeout ?? 5e3;
|
|
52
|
+
const url = `${host}/batch/`;
|
|
53
|
+
const batch = events.map((event) => toPostHogEvent(event, config));
|
|
54
|
+
const payload = {
|
|
55
|
+
api_key: config.apiKey,
|
|
56
|
+
batch
|
|
57
|
+
};
|
|
58
|
+
const controller = new AbortController();
|
|
59
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
60
|
+
try {
|
|
61
|
+
const response = await fetch(url, {
|
|
62
|
+
method: "POST",
|
|
63
|
+
headers: {
|
|
64
|
+
"Content-Type": "application/json"
|
|
65
|
+
},
|
|
66
|
+
body: JSON.stringify(payload),
|
|
67
|
+
signal: controller.signal
|
|
68
|
+
});
|
|
69
|
+
if (!response.ok) {
|
|
70
|
+
const text = await response.text().catch(() => "Unknown error");
|
|
71
|
+
const safeText = text.length > 200 ? `${text.slice(0, 200)}...[truncated]` : text;
|
|
72
|
+
throw new Error(`PostHog API error: ${response.status} ${response.statusText} - ${safeText}`);
|
|
73
|
+
}
|
|
74
|
+
} finally {
|
|
75
|
+
clearTimeout(timeoutId);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export { createPostHogDrain, sendBatchToPostHog, sendToPostHog, toPostHogEvent };
|
package/dist/nitro/plugin.mjs
CHANGED
|
@@ -63,9 +63,9 @@ function callDrainHook(nitroApp, emittedEvent, event) {
|
|
|
63
63
|
}).catch((err) => {
|
|
64
64
|
console.error("[evlog] drain failed:", err);
|
|
65
65
|
});
|
|
66
|
-
const
|
|
67
|
-
if (typeof waitUntil === "function") {
|
|
68
|
-
waitUntil(drainPromise);
|
|
66
|
+
const waitUntilCtx = event.context.cloudflare?.context ?? event.context;
|
|
67
|
+
if (typeof waitUntilCtx?.waitUntil === "function") {
|
|
68
|
+
waitUntilCtx.waitUntil(drainPromise);
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
const plugin = defineNitroPlugin((nitroApp) => {
|
|
@@ -82,10 +82,15 @@ const plugin = defineNitroPlugin((nitroApp) => {
|
|
|
82
82
|
return;
|
|
83
83
|
}
|
|
84
84
|
e.context._evlogStartTime = Date.now();
|
|
85
|
+
let requestIdOverride = void 0;
|
|
86
|
+
if (globalThis.navigator?.userAgent === "Cloudflare-Workers") {
|
|
87
|
+
const cfRay = getSafeHeaders(event)?.["cf-ray"];
|
|
88
|
+
if (cfRay) requestIdOverride = cfRay;
|
|
89
|
+
}
|
|
85
90
|
const log = createRequestLogger({
|
|
86
91
|
method: e.method,
|
|
87
92
|
path: e.path,
|
|
88
|
-
requestId: e.context.requestId || crypto.randomUUID()
|
|
93
|
+
requestId: requestIdOverride || e.context.requestId || crypto.randomUUID()
|
|
89
94
|
});
|
|
90
95
|
const routeService = getServiceForPath(e.path, evlogConfig?.routes);
|
|
91
96
|
if (routeService) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "evlog",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Wide event logging library with structured error handling. Inspired by LoggingSucks.",
|
|
5
5
|
"author": "HugoRCD <contact@hrcd.fr>",
|
|
6
6
|
"homepage": "https://evlog.dev",
|
|
@@ -46,6 +46,10 @@
|
|
|
46
46
|
"./otlp": {
|
|
47
47
|
"types": "./dist/adapters/otlp.d.mts",
|
|
48
48
|
"import": "./dist/adapters/otlp.mjs"
|
|
49
|
+
},
|
|
50
|
+
"./posthog": {
|
|
51
|
+
"types": "./dist/adapters/posthog.d.mts",
|
|
52
|
+
"import": "./dist/adapters/posthog.mjs"
|
|
49
53
|
}
|
|
50
54
|
},
|
|
51
55
|
"main": "./dist/index.mjs",
|
|
@@ -69,6 +73,9 @@
|
|
|
69
73
|
],
|
|
70
74
|
"otlp": [
|
|
71
75
|
"./dist/adapters/otlp.d.mts"
|
|
76
|
+
],
|
|
77
|
+
"posthog": [
|
|
78
|
+
"./dist/adapters/posthog.d.mts"
|
|
72
79
|
]
|
|
73
80
|
}
|
|
74
81
|
},
|
|
@@ -88,17 +95,17 @@
|
|
|
88
95
|
"typecheck": "echo 'Typecheck handled by build'"
|
|
89
96
|
},
|
|
90
97
|
"dependencies": {
|
|
91
|
-
"@nuxt/kit": "^4.3.
|
|
98
|
+
"@nuxt/kit": "^4.3.1",
|
|
92
99
|
"defu": "^6.1.4"
|
|
93
100
|
},
|
|
94
101
|
"devDependencies": {
|
|
95
102
|
"@nuxt/devtools": "^3.1.1",
|
|
96
|
-
"@nuxt/schema": "^4.3.
|
|
103
|
+
"@nuxt/schema": "^4.3.1",
|
|
97
104
|
"@nuxt/test-utils": "^3.23.0",
|
|
98
105
|
"changelogen": "^0.6.2",
|
|
99
106
|
"h3": "^1.15.5",
|
|
100
107
|
"nitropack": "^2.13.1",
|
|
101
|
-
"nuxt": "^4.3.
|
|
108
|
+
"nuxt": "^4.3.1",
|
|
102
109
|
"typescript": "^5.9.3",
|
|
103
110
|
"unbuild": "^3.6.1"
|
|
104
111
|
},
|