Skip to content

Commit 58e966a

Browse files
committed
docs: add telemetry instrumentation guide
1 parent 52a24ce commit 58e966a

3 files changed

Lines changed: 80 additions & 0 deletions

File tree

.github/harness/prompts/review.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,5 @@ comment on the PR saying it looks good to merge (or that all issues have already
2525
- **Excessive mocking** — Avoid excessive mocking; it couples tests to implementation details, provides weaker
2626
guarantees, and often points to mismanaged dependencies. Prefer real dependencies (e.g. temp directories over fs
2727
mocks) and only mock at true I/O boundaries (e.g., network calls, AWS SDK clients, HTTP requests).
28+
- **Missing telemetry** — New features should include telemetry instrumentation. See `src/cli/telemetry/README.md` for
29+
guidance on what and how to instrument.

AGENTS.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,10 @@ See `docs/TESTING.md` for details.
143143
- Always look for existing types before creating a new type inline.
144144
- Re-usable constants must be defined in a constants file in the closest sensible subdirectory.
145145

146+
## Telemetry
147+
148+
New features must include telemetry instrumentation. See `src/cli/telemetry/README.md` for how to add metrics.
149+
146150
## Multi-Partition Support (GovCloud, China)
147151

148152
The CLI supports multiple AWS partitions (commercial, GovCloud, China) through a central utility at

src/cli/telemetry/README.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Adding New Telemetry Metrics
2+
3+
## Overview
4+
5+
Every CLI command emits a `command_run` metric with a command key, exit reason, and command-specific attributes. This
6+
guide shows how to add telemetry to a new command.
7+
8+
## Step 1: Register the command in `schemas/command-run.ts`
9+
10+
Add an entry to `COMMAND_SCHEMAS`:
11+
12+
```ts
13+
// No attributes:
14+
'remove.widget': NoAttrs,
15+
16+
// With attributes:
17+
'add.widget': safeSchema({
18+
widget_type: WidgetType, // z.enum(), z.boolean(), z.number(), or z.literal() only
19+
count: Count,
20+
}),
21+
```
22+
23+
`safeSchema` enforces allowed field types at compile time. No `z.string()` fields.
24+
25+
## Step 2: Add enums to `schemas/common-shapes.ts`
26+
27+
```ts
28+
export const WidgetType = z.enum(['basic', 'advanced']);
29+
```
30+
31+
Use `standardize()` to normalize input before recording:
32+
33+
```ts
34+
import { WidgetType, standardize } from '../telemetry/schemas/common-shapes.js';
35+
36+
const type = standardize(WidgetType, userInput);
37+
```
38+
39+
## Step 3: Instrument the command handler
40+
41+
| Helper | Use case |
42+
| --------------------------------------------- | ----------------------------------- |
43+
| `runCliCommand(command, json, fn)` | CLI handlers that `process.exit` |
44+
| `withCommandRunTelemetry(command, attrs, fn)` | CLI/TUI handlers returning `Result` |
45+
| `withAddTelemetry(command, attrs, fn)` | TUI hooks wrapping `.add()` calls |
46+
47+
**`runCliCommand`** — throw on failure, return attrs on success:
48+
49+
```ts
50+
await runCliCommand('add.widget', !!options.json, async () => {
51+
const result = await widgetPrimitive.add(options);
52+
if (!result.success) throw new Error(result.error);
53+
console.log(JSON.stringify(result));
54+
return { widget_type: standardize(WidgetType, options.type), count: options.items.length };
55+
});
56+
```
57+
58+
**`withCommandRunTelemetry`** / **`withAddTelemetry`** — returns `Result` to caller:
59+
60+
```ts
61+
const result = await withAddTelemetry(
62+
'add.widget',
63+
{ widget_type: standardize(WidgetType, config.type), count: config.items.length },
64+
() => widgetPrimitive.add(config)
65+
);
66+
```
67+
68+
## Key Points
69+
70+
- Telemetry never crashes the CLI — `standardize()` falls back gracefully, `resilientParse` defaults invalid fields to
71+
`'unknown'`.
72+
- `runCliCommand` callback must **throw** on failure. The helper catches, records failure telemetry, prints the error,
73+
and exits.
74+
- `withCommandRunTelemetry` and `withAddTelemetry` return the `Result` for further handling.

0 commit comments

Comments
 (0)