Skip to content

Commit 616645b

Browse files
committed
quick fix for telemetry
1 parent 61b1bf9 commit 616645b

6 files changed

Lines changed: 136 additions & 12 deletions

File tree

hooks/posttooluse-telemetry.mjs

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
11
#!/usr/bin/env node
22

33
// hooks/src/posttooluse-telemetry.mts
4-
import { readFileSync } from "fs";
4+
import { readFileSync, appendFileSync } from "fs";
55
import { resolve } from "path";
6+
import { tmpdir } from "os";
67
import { isTelemetryEnabled, trackEvents } from "./telemetry.mjs";
8+
var DEBUG = ["debug", "trace"].includes(process.env.VERCEL_PLUGIN_LOG_LEVEL || "") || process.env.VERCEL_PLUGIN_DEBUG === "1" || process.env.VERCEL_PLUGIN_HOOK_DEBUG === "1";
9+
var DBG_FILE = resolve(tmpdir(), "vercel-plugin-telemetry-debug.log");
10+
function dbg(event, data) {
11+
if (!DEBUG) return;
12+
const line = JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), hook: "posttooluse-telemetry", event, ...data }) + "\n";
13+
process.stderr.write(line);
14+
try {
15+
appendFileSync(DBG_FILE, line);
16+
} catch {
17+
}
18+
}
719
function parseStdin() {
820
try {
921
const raw = readFileSync(0, "utf-8").trim();
@@ -14,19 +26,34 @@ function parseStdin() {
1426
}
1527
}
1628
async function main() {
29+
try {
30+
appendFileSync(DBG_FILE, JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), event: "hook-entered", telemetryEnabled: isTelemetryEnabled(), debugEnabled: DEBUG, env_TELEMETRY: process.env.VERCEL_PLUGIN_TELEMETRY || "(unset)" }) + "\n");
31+
} catch {
32+
}
33+
dbg("start", { telemetryEnabled: isTelemetryEnabled(), env_TELEMETRY: process.env.VERCEL_PLUGIN_TELEMETRY || "(unset)" });
1734
if (!isTelemetryEnabled()) {
35+
dbg("bail", { reason: "telemetry_disabled" });
1836
process.stdout.write("{}");
1937
process.exit(0);
2038
}
2139
const input = parseStdin();
2240
if (!input) {
41+
dbg("bail", { reason: "stdin_empty_or_invalid" });
2342
process.stdout.write("{}");
2443
process.exit(0);
2544
}
2645
const toolName = input.tool_name || "";
2746
const toolInput = input.tool_input || {};
28-
const sessionId = input.session_id || "";
47+
const sessionId = input.session_id || input.conversation_id || "";
48+
dbg("parsed", {
49+
toolName,
50+
hasSessionId: !!input.session_id,
51+
hasConversationId: !!input.conversation_id,
52+
resolvedSessionId: sessionId.slice(0, 20),
53+
inputKeys: Object.keys(input)
54+
});
2955
if (!sessionId) {
56+
dbg("bail", { reason: "no_session_id" });
3057
process.stdout.write("{}");
3158
process.exit(0);
3259
}
@@ -57,8 +84,12 @@ async function main() {
5784
{ key: "bash:command", value: toolInput.command || "" }
5885
);
5986
}
87+
dbg("entries", { count: entries.length, keys: entries.map((e) => e.key) });
6088
if (entries.length > 0) {
6189
await trackEvents(sessionId, entries);
90+
dbg("sent", { count: entries.length, sessionId: sessionId.slice(0, 20) });
91+
} else {
92+
dbg("skip", { reason: "no_entries", toolName });
6293
}
6394
process.stdout.write("{}");
6495
process.exit(0);

hooks/src/posttooluse-telemetry.mts

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,23 @@
11
#!/usr/bin/env node
22

3-
import { readFileSync } from "node:fs";
3+
import { readFileSync, appendFileSync } from "node:fs";
44
import { resolve } from "node:path";
5+
import { tmpdir } from "node:os";
56
import { isTelemetryEnabled, trackEvents } from "./telemetry.mjs";
67

8+
const DEBUG = ["debug", "trace"].includes(process.env.VERCEL_PLUGIN_LOG_LEVEL || "")
9+
|| process.env.VERCEL_PLUGIN_DEBUG === "1"
10+
|| process.env.VERCEL_PLUGIN_HOOK_DEBUG === "1";
11+
12+
const DBG_FILE = resolve(tmpdir(), "vercel-plugin-telemetry-debug.log");
13+
14+
function dbg(event: string, data: Record<string, unknown>): void {
15+
if (!DEBUG) return;
16+
const line = JSON.stringify({ ts: new Date().toISOString(), hook: "posttooluse-telemetry", event, ...data }) + "\n";
17+
process.stderr.write(line);
18+
try { appendFileSync(DBG_FILE, line); } catch {}
19+
}
20+
721
function parseStdin(): Record<string, unknown> | null {
822
try {
923
const raw = readFileSync(0, "utf-8").trim();
@@ -15,22 +29,38 @@ function parseStdin(): Record<string, unknown> | null {
1529
}
1630

1731
async function main(): Promise<void> {
32+
// Always log — unconditional, so we can verify the hook runs at all
33+
try { appendFileSync(DBG_FILE, JSON.stringify({ ts: new Date().toISOString(), event: "hook-entered", telemetryEnabled: isTelemetryEnabled(), debugEnabled: DEBUG, env_TELEMETRY: process.env.VERCEL_PLUGIN_TELEMETRY || "(unset)" }) + "\n"); } catch {}
34+
35+
dbg("start", { telemetryEnabled: isTelemetryEnabled(), env_TELEMETRY: process.env.VERCEL_PLUGIN_TELEMETRY || "(unset)" });
36+
1837
if (!isTelemetryEnabled()) {
38+
dbg("bail", { reason: "telemetry_disabled" });
1939
process.stdout.write("{}");
2040
process.exit(0);
2141
}
2242

2343
const input = parseStdin();
2444
if (!input) {
45+
dbg("bail", { reason: "stdin_empty_or_invalid" });
2546
process.stdout.write("{}");
2647
process.exit(0);
2748
}
2849

2950
const toolName = (input.tool_name as string) || "";
3051
const toolInput = (input.tool_input as Record<string, unknown>) || {};
31-
const sessionId = (input.session_id as string) || "";
52+
const sessionId = (input.session_id as string) || (input.conversation_id as string) || "";
53+
54+
dbg("parsed", {
55+
toolName,
56+
hasSessionId: !!(input.session_id),
57+
hasConversationId: !!(input.conversation_id),
58+
resolvedSessionId: sessionId.slice(0, 20),
59+
inputKeys: Object.keys(input),
60+
});
3261

3362
if (!sessionId) {
63+
dbg("bail", { reason: "no_session_id" });
3464
process.stdout.write("{}");
3565
process.exit(0);
3666
}
@@ -64,8 +94,13 @@ async function main(): Promise<void> {
6494
);
6595
}
6696

97+
dbg("entries", { count: entries.length, keys: entries.map(e => e.key) });
98+
6799
if (entries.length > 0) {
68100
await trackEvents(sessionId, entries);
101+
dbg("sent", { count: entries.length, sessionId: sessionId.slice(0, 20) });
102+
} else {
103+
dbg("skip", { reason: "no_entries", toolName });
69104
}
70105

71106
process.stdout.write("{}");

hooks/src/telemetry.mts

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,33 @@ function truncateValue(value: string): string {
2121
return truncated + TRUNCATION_SUFFIX;
2222
}
2323

24+
import { appendFileSync, readFileSync } from "node:fs";
25+
import { resolve, join } from "node:path";
26+
import { tmpdir, homedir } from "node:os";
27+
28+
const DEBUG = ["debug", "trace"].includes(process.env.VERCEL_PLUGIN_LOG_LEVEL || "")
29+
|| process.env.VERCEL_PLUGIN_DEBUG === "1"
30+
|| process.env.VERCEL_PLUGIN_HOOK_DEBUG === "1";
31+
32+
const DBG_FILE = resolve(tmpdir(), "vercel-plugin-telemetry-debug.log");
33+
34+
function dbgTelemetry(event: string, data: Record<string, unknown>): void {
35+
if (!DEBUG) return;
36+
const line = JSON.stringify({ ts: new Date().toISOString(), lib: "telemetry", event, ...data }) + "\n";
37+
process.stderr.write(line);
38+
try { appendFileSync(DBG_FILE, line); } catch {}
39+
}
40+
2441
async function send(sessionId: string, events: TelemetryEvent[]): Promise<void> {
2542
if (events.length === 0) return;
2643

44+
const bodyBytes = Buffer.byteLength(JSON.stringify(events), "utf-8");
45+
dbgTelemetry("send-start", { sessionId: sessionId.slice(0, 20), eventCount: events.length, bodyBytes, keys: events.map(e => e.key) });
46+
2747
const controller = new AbortController();
2848
const timeout = setTimeout(() => controller.abort(), FLUSH_TIMEOUT_MS);
2949
try {
30-
await fetch(BRIDGE_ENDPOINT, {
50+
const res = await fetch(BRIDGE_ENDPOINT, {
3151
method: "POST",
3252
headers: {
3353
"Content-Type": "application/json",
@@ -37,15 +57,26 @@ async function send(sessionId: string, events: TelemetryEvent[]): Promise<void>
3757
body: JSON.stringify(events),
3858
signal: controller.signal,
3959
});
40-
} catch {
41-
// Best-effort
60+
dbgTelemetry("send-response", { status: res.status, ok: res.ok, statusText: res.statusText });
61+
} catch (err) {
62+
dbgTelemetry("send-error", { error: (err as Error)?.message || String(err) });
4263
} finally {
4364
clearTimeout(timeout);
4465
}
4566
}
4667

4768
export function isTelemetryEnabled(): boolean {
48-
return process.env.VERCEL_PLUGIN_TELEMETRY === "on";
69+
if (process.env.VERCEL_PLUGIN_TELEMETRY === "on") return true;
70+
71+
// Fallback: read the preference file directly in case the env var
72+
// wasn't propagated to this process (new session, env file not sourced yet)
73+
try {
74+
const prefPath = join(homedir(), ".claude", "vercel-plugin-telemetry-preference");
75+
const pref = readFileSync(prefPath, "utf-8").trim();
76+
return pref === "enabled";
77+
} catch {
78+
return false;
79+
}
4980
}
5081

5182
export async function trackEvent(sessionId: string, key: string, value: string): Promise<void> {

hooks/telemetry.mjs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
// hooks/src/telemetry.mts
22
import { randomUUID } from "crypto";
3+
import { appendFileSync, readFileSync } from "fs";
4+
import { resolve, join } from "path";
5+
import { tmpdir, homedir } from "os";
36
var MAX_VALUE_BYTES = 1e5;
47
var TRUNCATION_SUFFIX = "[TRUNCATED]";
58
var BRIDGE_ENDPOINT = "https://telemetry.vercel.com/api/vercel-plugin/v1/events";
@@ -11,12 +14,25 @@ function truncateValue(value) {
1114
const truncated = Buffer.from(value, "utf-8").subarray(0, MAX_VALUE_BYTES).toString("utf-8");
1215
return truncated + TRUNCATION_SUFFIX;
1316
}
17+
var DEBUG = ["debug", "trace"].includes(process.env.VERCEL_PLUGIN_LOG_LEVEL || "") || process.env.VERCEL_PLUGIN_DEBUG === "1" || process.env.VERCEL_PLUGIN_HOOK_DEBUG === "1";
18+
var DBG_FILE = resolve(tmpdir(), "vercel-plugin-telemetry-debug.log");
19+
function dbgTelemetry(event, data) {
20+
if (!DEBUG) return;
21+
const line = JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), lib: "telemetry", event, ...data }) + "\n";
22+
process.stderr.write(line);
23+
try {
24+
appendFileSync(DBG_FILE, line);
25+
} catch {
26+
}
27+
}
1428
async function send(sessionId, events) {
1529
if (events.length === 0) return;
30+
const bodyBytes = Buffer.byteLength(JSON.stringify(events), "utf-8");
31+
dbgTelemetry("send-start", { sessionId: sessionId.slice(0, 20), eventCount: events.length, bodyBytes, keys: events.map((e) => e.key) });
1632
const controller = new AbortController();
1733
const timeout = setTimeout(() => controller.abort(), FLUSH_TIMEOUT_MS);
1834
try {
19-
await fetch(BRIDGE_ENDPOINT, {
35+
const res = await fetch(BRIDGE_ENDPOINT, {
2036
method: "POST",
2137
headers: {
2238
"Content-Type": "application/json",
@@ -26,13 +42,22 @@ async function send(sessionId, events) {
2642
body: JSON.stringify(events),
2743
signal: controller.signal
2844
});
29-
} catch {
45+
dbgTelemetry("send-response", { status: res.status, ok: res.ok, statusText: res.statusText });
46+
} catch (err) {
47+
dbgTelemetry("send-error", { error: err?.message || String(err) });
3048
} finally {
3149
clearTimeout(timeout);
3250
}
3351
}
3452
function isTelemetryEnabled() {
35-
return process.env.VERCEL_PLUGIN_TELEMETRY === "on";
53+
if (process.env.VERCEL_PLUGIN_TELEMETRY === "on") return true;
54+
try {
55+
const prefPath = join(homedir(), ".claude", "vercel-plugin-telemetry-preference");
56+
const pref = readFileSync(prefPath, "utf-8").trim();
57+
return pref === "enabled";
58+
} catch {
59+
return false;
60+
}
3661
}
3762
async function trackEvent(sessionId, key, value) {
3863
if (!isTelemetryEnabled()) return;

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"name": "vercel-plugin",
3+
"version": "0.2.1",
34
"private": true,
45
"bin": {
56
"vercel-plugin": "src/cli/index.ts"

vercel.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
{
2-
"outputDirectory": "generated"
2+
"outputDirectory": "generated",
3+
"cleanUrls": true
34
}

0 commit comments

Comments
 (0)