Skip to content

Commit 8741a20

Browse files
committed
fix: observability reporting
1 parent ae0a88e commit 8741a20

2 files changed

Lines changed: 80 additions & 33 deletions

File tree

.changeset/big-numbers-end.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"lingo.dev": patch
3+
---
4+
5+
fix observability tracking
Lines changed: 75 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,90 @@
11
import pkg from "node-machine-id";
22
const { machineIdSync } = pkg;
3+
import https from "https";
34

4-
export async function createPosthogClient() {
5-
const { PostHog } = await import("posthog-node");
6-
const posthog = new PostHog(
7-
"phc_eR0iSoQufBxNY36k0f0T15UvHJdTfHlh8rJcxsfhfXk",
8-
{
9-
host: "https://eu.i.posthog.com",
10-
flushAt: 1,
11-
flushInterval: 0,
12-
},
13-
);
14-
15-
return posthog;
16-
}
5+
const POSTHOG_API_KEY = "phc_eR0iSoQufBxNY36k0f0T15UvHJdTfHlh8rJcxsfhfXk";
6+
const POSTHOG_HOST = "eu.i.posthog.com";
7+
const POSTHOG_PATH = "/i/v0/e/"; // Correct PostHog capture endpoint
8+
const REQUEST_TIMEOUT_MS = 1000;
179

18-
export default async function trackEvent(
10+
/**
11+
* Sends an analytics event to PostHog using direct HTTPS API.
12+
* This is a fire-and-forget implementation that won't block the process.
13+
*
14+
* @param distinctId - Unique identifier for the user/device
15+
* @param event - Name of the event to track
16+
* @param properties - Additional properties to attach to the event
17+
*/
18+
export default function trackEvent(
1919
distinctId: string | null | undefined,
2020
event: string,
2121
properties?: Record<string, any>,
22-
) {
23-
if (process.env.DO_NOT_TRACK) {
22+
): void {
23+
// Skip tracking if explicitly disabled or in CI environment
24+
if (process.env.DO_NOT_TRACK === "1") {
2425
return;
2526
}
2627

27-
try {
28-
const actualId = distinctId || `device-${machineIdSync()}`;
28+
// Defer execution to next tick to avoid blocking
29+
setImmediate(() => {
30+
try {
31+
const actualId = distinctId || `device-${machineIdSync()}`;
32+
33+
// PostHog expects distinct_id at the root level, not nested in properties
34+
const eventData = {
35+
api_key: POSTHOG_API_KEY,
36+
event,
37+
distinct_id: actualId,
38+
properties: {
39+
...properties,
40+
$lib: "lingo.dev-cli",
41+
$lib_version: process.env.npm_package_version || "unknown",
42+
},
43+
timestamp: new Date().toISOString(),
44+
};
2945

30-
const posthog = await createPosthogClient();
46+
const payload = JSON.stringify(eventData);
3147

32-
await posthog.capture({
33-
distinctId: actualId,
34-
event,
35-
properties: {
36-
...properties,
37-
meta: {
38-
version: process.env.npm_package_version,
39-
isCi: process.env.CI === "true",
48+
const options: https.RequestOptions = {
49+
hostname: POSTHOG_HOST,
50+
path: POSTHOG_PATH,
51+
method: "POST",
52+
headers: {
53+
"Content-Type": "application/json",
54+
"Content-Length": Buffer.byteLength(payload).toString(),
4055
},
41-
},
42-
});
43-
} catch (error) {
44-
if (process.env.DEBUG) {
45-
console.error(error);
56+
timeout: REQUEST_TIMEOUT_MS,
57+
};
58+
59+
const req = https.request(options);
60+
61+
// Handle timeout by destroying the request
62+
req.on("timeout", () => {
63+
req.destroy();
64+
});
65+
66+
// Silently ignore errors to prevent crashes
67+
req.on("error", (error) => {
68+
if (process.env.DEBUG === "true") {
69+
console.error("[Tracking] Error ignored:", error.message);
70+
}
71+
});
72+
73+
// Send payload and close the request
74+
req.write(payload);
75+
req.end();
76+
77+
// Ensure cleanup after timeout
78+
setTimeout(() => {
79+
if (!req.destroyed) {
80+
req.destroy();
81+
}
82+
}, REQUEST_TIMEOUT_MS);
83+
} catch (error) {
84+
// Catch-all for any synchronous errors
85+
if (process.env.DEBUG === "true") {
86+
console.error("[Tracking] Failed to send event:", error);
87+
}
4688
}
47-
}
89+
});
4890
}

0 commit comments

Comments
 (0)