Skip to content

Commit e91686c

Browse files
committed
add more telemetry
1 parent 5c0d54e commit e91686c

File tree

3 files changed

+179
-31
lines changed

3 files changed

+179
-31
lines changed

packages/cli/src/api/index.ts

Lines changed: 91 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,51 +5,136 @@ import { scanSchema, splitSchema, syncSchema } from "./helpers/validation";
55
import { scan } from "./scan";
66
import { split } from "./split";
77
import { sync } from "./sync";
8+
import { TelemetryEvents, trackEvent } from "../telemetry";
89

910
export function getApi(napiConfig: z.infer<typeof napiConfigSchema>) {
1011
const api = Router();
1112

1213
api.use(json());
1314

1415
api.get("/api/config", (_, res) => {
16+
const startTime = Date.now();
17+
trackEvent(TelemetryEvents.API_REQUEST_CONGIG, {
18+
message: "API request config started",
19+
});
20+
1521
if (!napiConfig) {
1622
res.status(400).json({
1723
error: "Missing .napirc file in project. Run `napi init` first",
1824
});
25+
trackEvent(TelemetryEvents.API_REQUEST_CONGIG, {
26+
message: "API request config failed, missing .napirc file",
27+
duration: Date.now(),
28+
});
1929
return;
2030
}
2131

2232
res.status(200).json(napiConfig);
33+
34+
trackEvent(TelemetryEvents.API_REQUEST_CONGIG, {
35+
message: "API request config success",
36+
duration: Date.now() - startTime,
37+
});
2338
});
2439

2540
api.post("/api/scan", (req, res) => {
41+
const startTime = Date.now();
42+
trackEvent(TelemetryEvents.API_REQUEST_SCAN, {
43+
message: "API request scan started",
44+
});
45+
2646
const result = scanSchema.safeParse(req.body);
2747
if (!result.success) {
2848
res.status(400).json(result.error.issues);
49+
trackEvent(TelemetryEvents.API_REQUEST_SCAN, {
50+
message: "API request scan failed",
51+
duration: Date.now() - startTime,
52+
});
2953
return;
3054
}
31-
const scanResponse = scan(result.data);
32-
res.status(200).json(scanResponse);
55+
56+
try {
57+
const scanResponse = scan(result.data);
58+
res.status(200).json(scanResponse);
59+
60+
trackEvent(TelemetryEvents.API_REQUEST_SCAN, {
61+
message: "API request scan success",
62+
duration: Date.now() - startTime,
63+
});
64+
} catch (error) {
65+
trackEvent(TelemetryEvents.API_REQUEST_SCAN, {
66+
message: "API request scan failed",
67+
duration: Date.now() - startTime,
68+
error: error,
69+
});
70+
throw error;
71+
}
3372
});
3473

3574
api.post("/api/sync", (req, res) => {
75+
const startTime = Date.now();
76+
trackEvent(TelemetryEvents.API_REQUEST_SYNC, {
77+
message: "API request sync started",
78+
});
79+
3680
const result = syncSchema.safeParse(req.body);
3781
if (!result.success) {
3882
res.status(400).json(result.error.issues);
83+
trackEvent(TelemetryEvents.API_REQUEST_SYNC, {
84+
message: "API request sync failed",
85+
duration: Date.now() - startTime,
86+
});
3987
return;
4088
}
41-
sync(result.data);
42-
res.status(200).json({ success: true });
89+
90+
try {
91+
sync(result.data);
92+
res.status(200).json({ success: true });
93+
trackEvent(TelemetryEvents.API_REQUEST_SYNC, {
94+
message: "API request sync success",
95+
duration: Date.now() - startTime,
96+
});
97+
} catch (error) {
98+
trackEvent(TelemetryEvents.API_REQUEST_SYNC, {
99+
message: "API request sync failed",
100+
duration: Date.now() - startTime,
101+
error: error,
102+
});
103+
throw error;
104+
}
43105
});
44106

45107
api.post("/api/split", async (req, res) => {
108+
const startTime = Date.now();
109+
trackEvent(TelemetryEvents.API_REQUEST_SPLIT, {
110+
message: "API request split started",
111+
});
112+
46113
const result = splitSchema.safeParse(req.body);
47114
if (!result.success) {
48115
res.status(400).json(result.error.issues);
116+
trackEvent(TelemetryEvents.API_REQUEST_SPLIT, {
117+
message: "API request split failed",
118+
duration: Date.now() - startTime,
119+
});
49120
return;
50121
}
51-
const splitResult = await split(result.data);
52-
res.status(200).json(splitResult);
122+
123+
try {
124+
const splitResult = await split(result.data);
125+
res.status(200).json(splitResult);
126+
trackEvent(TelemetryEvents.API_REQUEST_SPLIT, {
127+
message: "API request split success",
128+
duration: Date.now() - startTime,
129+
});
130+
} catch (error) {
131+
trackEvent(TelemetryEvents.API_REQUEST_SPLIT, {
132+
message: "API request split failed",
133+
duration: Date.now() - startTime,
134+
error: error,
135+
});
136+
throw error;
137+
}
53138
});
54139

55140
return api;

packages/cli/src/index.ts

Lines changed: 69 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ if (process.env.NODE_ENV !== "development") {
2020
}
2121

2222
trackEvent(TelemetryEvents.APP_START, {
23-
message: "Napi started with Telemetry enabled",
23+
message: "Napi started",
2424
});
2525

2626
yargs(hideBin(process.argv))
@@ -40,8 +40,24 @@ yargs(hideBin(process.argv))
4040
"initialize a nanoapi project",
4141
(yargs) => yargs,
4242
(argv) => {
43-
trackEvent(TelemetryEvents.INIT_COMMAND, { message: "Init command" });
44-
initCommandHandler(argv.workdir);
43+
const startTime = Date.now();
44+
trackEvent(TelemetryEvents.INIT_COMMAND, {
45+
message: "Init command started",
46+
});
47+
try {
48+
initCommandHandler(argv.workdir);
49+
trackEvent(TelemetryEvents.INIT_COMMAND, {
50+
message: "Init command finished",
51+
duration: Date.now() - startTime,
52+
});
53+
} catch (error) {
54+
trackEvent(TelemetryEvents.INIT_COMMAND, {
55+
message: "Init command error",
56+
duration: Date.now() - startTime,
57+
error: error,
58+
});
59+
throw error;
60+
}
4561
},
4662
)
4763
// Annotate openai command
@@ -58,13 +74,18 @@ yargs(hideBin(process.argv))
5874
},
5975
}),
6076
(argv) => {
77+
const startTime = Date.now();
6178
trackEvent(TelemetryEvents.ANNOTATE_COMMAND, {
62-
message: "Annotate command",
79+
message: "Annotate command started",
6380
});
6481
const napiConfig = getConfigFromWorkDir(argv.workdir);
6582

6683
if (!napiConfig) {
6784
console.error("Missing .napirc file in project. Run `napi init` first");
85+
trackEvent(TelemetryEvents.ANNOTATE_COMMAND, {
86+
message: "Annotate command failed, missing .napirc file",
87+
duration: Date.now() - startTime,
88+
});
6889
return;
6990
}
7091

@@ -79,10 +100,26 @@ yargs(hideBin(process.argv))
79100
console.error(
80101
"Missing OpenAI API key. Please provide it via --apiKey or in a .napirc file using 'openaiApiKey' or 'openaiApiKeyFilePath'",
81102
);
103+
trackEvent(TelemetryEvents.ANNOTATE_COMMAND, {
104+
message: "Annotate command failed, missing OpenAI API key",
105+
duration: Date.now() - startTime,
106+
});
82107
return;
83108
}
84109

85-
annotateOpenAICommandHandler(napiConfig.entrypoint, apiKey);
110+
try {
111+
annotateOpenAICommandHandler(napiConfig.entrypoint, apiKey);
112+
trackEvent(TelemetryEvents.ANNOTATE_COMMAND, {
113+
message: "Annotate command finished",
114+
duration: Date.now() - startTime,
115+
});
116+
} catch (error) {
117+
trackEvent(TelemetryEvents.ANNOTATE_COMMAND, {
118+
message: "Annotate command error",
119+
duration: Date.now() - startTime,
120+
error: error,
121+
});
122+
}
86123
},
87124
)
88125
// Split command
@@ -91,17 +128,30 @@ yargs(hideBin(process.argv))
91128
"Split a program into multiple ones",
92129
(yargs) => yargs,
93130
(argv) => {
131+
const startTime = Date.now();
94132
trackEvent(TelemetryEvents.SPLIT_COMMAND, {
95-
message: "Split command",
133+
message: "Split command started",
96134
});
97135
const napiConfig = getConfigFromWorkDir(argv.workdir);
98136

99137
if (!napiConfig) {
100138
console.error("Missing .napirc file in project. Run `napi init` first");
139+
trackEvent(TelemetryEvents.SPLIT_COMMAND, {
140+
message: "Split command failed, missing .napirc file",
141+
duration: Date.now() - startTime,
142+
});
101143
return;
102144
}
103145

104-
splitCommandHandler(napiConfig.entrypoint, napiConfig.out);
146+
try {
147+
splitCommandHandler(napiConfig.entrypoint, napiConfig.out);
148+
} catch (error) {
149+
trackEvent(TelemetryEvents.SPLIT_COMMAND, {
150+
message: "Split command error",
151+
duration: Date.now() - startTime,
152+
error: error,
153+
});
154+
}
105155
},
106156
)
107157
// Open UI command
@@ -110,14 +160,20 @@ yargs(hideBin(process.argv))
110160
"open the NanoAPI UI",
111161
(yargs) => yargs,
112162
async (argv) => {
163+
const start = Date.now();
164+
113165
trackEvent(TelemetryEvents.UI_OPEN, {
114-
message: "UI command",
166+
message: "UI command started",
115167
});
116168

117169
const napiConfig = getConfigFromWorkDir(argv.workdir);
118170

119171
if (!napiConfig) {
120172
console.error("Missing .napirc file in project. Run `napi init` first");
173+
trackEvent(TelemetryEvents.UI_OPEN, {
174+
message: "UI command failed, missing .napirc file",
175+
duration: Date.now() - start,
176+
});
121177
return;
122178
}
123179

@@ -148,6 +204,11 @@ yargs(hideBin(process.argv))
148204
openInBrowser(url);
149205
}
150206
});
207+
208+
trackEvent(TelemetryEvents.UI_OPEN, {
209+
message: "UI command finished",
210+
duration: Date.now() - start,
211+
});
151212
},
152213
)
153214
.parse();

packages/cli/src/telemetry.ts

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ export enum TelemetryEvents {
99
ANNOTATE_COMMAND = "annotate_command",
1010
SPLIT_COMMAND = "split_command",
1111
UI_OPEN = "ui_open",
12-
SERVER_STARTED = "server_started",
13-
API_REQUEST = "api_request",
14-
ERROR_OCCURRED = "error_occurred",
15-
USER_ACTION = "user_action",
12+
API_REQUEST_CONGIG = "api_request_config",
13+
API_REQUEST_SCAN = "api_request_scan",
14+
API_REQUEST_SYNC = "api_request_sync",
15+
API_REQUEST_SPLIT = "api_request_split",
1616
}
1717

1818
export interface TelemetryEvent {
@@ -39,21 +39,23 @@ async function sendTelemetryData(data: TelemetryEvent) {
3939
const timeoutId = setTimeout(() => controller.abort(), timeoutSeconds * 1000);
4040

4141
try {
42-
const response = await fetch(TELEMETRY_ENDPOINT, {
43-
method: "POST",
44-
headers: {
45-
"Content-Type": "application/json",
46-
"User-Agent": "napi",
47-
},
48-
body: JSON.stringify(data),
49-
signal: controller.signal,
50-
});
42+
if (process.env.NODE_ENV !== "development") {
43+
const response = await fetch(TELEMETRY_ENDPOINT, {
44+
method: "POST",
45+
headers: {
46+
"Content-Type": "application/json",
47+
"User-Agent": "napi",
48+
},
49+
body: JSON.stringify(data),
50+
signal: controller.signal,
51+
});
5152

52-
clearTimeout(timeoutId);
53-
54-
if (!response.ok) {
55-
console.debug(`Failed to send telemetry data: ${response.statusText}`);
53+
if (!response.ok) {
54+
console.debug(`Failed to send telemetry data: ${response.statusText}`);
55+
}
5656
}
57+
58+
clearTimeout(timeoutId);
5759
} catch (error) {
5860
if (error instanceof Error && error.name === "AbortError") {
5961
console.debug("Request timed out");

0 commit comments

Comments
 (0)