|
| 1 | +# Privacy-reviewed telemetry dashboards |
| 2 | + |
| 3 | +These panels use only the fields in the |
| 4 | +[telemetry data dictionary](./telemetry-data-dictionary.md). The examples use |
| 5 | +Honeycomb-style metric names and dimensions; Sentry span panels should apply |
| 6 | +the equivalent span attribute filters. |
| 7 | + |
| 8 | +## Product usage |
| 9 | + |
| 10 | +| Panel | Source | Grouping/filter | Question answered | |
| 11 | +| ---------------------- | ---------------------- | ------------------------------------------------------------- | ------------------------------------------------------------ | |
| 12 | +| Feature adoption | `mcp.tool.invocations` | `hevy.feature`, `mcp.tool.operation` | Which Hevy areas and operations are used? | |
| 13 | +| Read/write split | `mcp.tool.invocations` | `mcp.tool.kind` | Are users primarily reading or writing? | |
| 14 | +| Discovery entry points | `mcp.tool.invocations` | `mcp.tool.operation = search`, `mcp.tool.name` | Which bounded search tools start workflows? | |
| 15 | +| Workflow adoption | `mcp.tool.invocations` | `hevy.feature = workflows`, `mcp.tool.operation` | How often are training summaries and routine discovery used? | |
| 16 | +| Write adoption | `mcp.tool.invocations` | `mcp.tool.kind = write`, `hevy.feature`, `mcp.tool.operation` | How frequently are writes made by feature? | |
| 17 | + |
| 18 | +Example aggregate query: |
| 19 | + |
| 20 | +```text |
| 21 | +COUNT mcp.tool.invocations |
| 22 | +GROUP BY hevy.feature, mcp.tool.kind, mcp.tool.operation |
| 23 | +WHERE transport = "stdio" |
| 24 | +``` |
| 25 | + |
| 26 | +## Tool reliability |
| 27 | + |
| 28 | +| Panel | Source | Grouping/filter | Question answered | |
| 29 | +| --------------------------- | ---------------------- | -------------------------------------------------------------- | ------------------------------------------------------------- | |
| 30 | +| User-visible outcome rate | `mcp.tool.outcomes` | `mcp.tool.name`, `outcome` | Which tools return MCP errors versus succeed? | |
| 31 | +| Thrown-error rate | `mcp.tool.errors` | `mcp.tool.name`, `error_type` | Which tools raise uncaught failures? | |
| 32 | +| Client compatibility | `mcp.tool.outcomes` | `client_name`, `client_version`, `protocol_version`, `outcome` | Which sanitized client/protocol combinations fail more often? | |
| 33 | +| Tool latency | `mcp.tool.duration_ms` | `hevy.feature`, `mcp.tool.operation`, `outcome` | Which bounded feature operations are slow? | |
| 34 | +| Result shape versus latency | `mcp.tool.duration_ms` | `mcp.tool.result.item_count_bucket`, `hevy.feature` | Do large result shapes correlate with latency? | |
| 35 | + |
| 36 | +Returned `isError: true` responses use `outcome=returned_error`; thrown |
| 37 | +exceptions use `outcome=thrown_error`. Do not infer user-visible failure rate |
| 38 | +from `mcp.tool.errors` alone. |
| 39 | + |
| 40 | +## Hevy API reliability |
| 41 | + |
| 42 | +| Panel | Source | Grouping/filter | Question answered | |
| 43 | +| ------------------------- | ---------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------- | |
| 44 | +| API status friction | `hevy.api.calls` | normalized `endpoint`, `status_code`, `method` | Which endpoint/status pairs fail? | |
| 45 | +| Stale-resource signals | `hevy.api.calls` | `status_code = 404`, normalized `endpoint` | Are 404s concentrated in resource lookup or pagination? | |
| 46 | +| Conflicting writes | `hevy.api.calls` | `status_code = 409`, normalized `endpoint`, `method` | Are duplicate/conflicting writes concentrated in one feature? | |
| 47 | +| Retry and timeout signals | `hevy.api.calls` | `status_code`, `retry_count_bucket`, `error_category`, `error_code` | How often do retries, rate limits, and timeouts occur? | |
| 48 | +| API duration | `hevy.api.duration_ms` | normalized `endpoint`, `method` | Which API operations are slow? | |
| 49 | + |
| 50 | +Endpoints are normalized before telemetry. Dynamic path segments are replaced |
| 51 | +with placeholders; raw IDs never reach these panels. |
| 52 | + |
| 53 | +## Performance and workflows |
| 54 | + |
| 55 | +| Panel | Source | Grouping/filter | Question answered | |
| 56 | +| ----------------------------- | ----------------------------------------------------------- | ----------------------------------------------- | ---------------------------------------------------------------------- | |
| 57 | +| Workflow pages scanned | `mcp.tool.get-training-summary`, `mcp.tool.search-routines` | `workflow.pagination.*.pages` | Which workflows scan the most pages? | |
| 58 | +| Cache hit/miss | `mcp.tool.get-training-summary`, `mcp.tool.search-routines` | `workflow.cache_status` | How effective is catalog caching? | |
| 59 | +| Workflow scan versus duration | `mcp.tool.get-training-summary`, `mcp.tool.search-routines` | `workflow.items_scanned` | Does scan size correlate with latency? | |
| 60 | +| Session lifecycle | `mcp.session.started`, `mcp.session.ended` | sanitized client fields, `termination_category` | Do sessions end cleanly or fail during startup/connect/tool execution? | |
| 61 | +| Session shape | `mcp.session.ended` | `session_duration_bucket`, `tool_calls_bucket` | How long are sessions and how many tools do they call? | |
| 62 | + |
| 63 | +## Retention and access review |
| 64 | + |
| 65 | +Approved application policy for these dashboards: |
| 66 | + |
| 67 | +- aggregate metrics: 90 days; |
| 68 | +- Sentry/OTel traces containing sanitized client metadata or the pseudonymous |
| 69 | + user hash: 30 days; |
| 70 | +- user-hash troubleshooting views: 24 hours of access and no saved per-user |
| 71 | + dashboard or query; |
| 72 | +- dashboard access owners: repository maintainers and the on-call operator; |
| 73 | +- no export of prompt, argument, result, title, notes, dates, identifiers, or |
| 74 | + measurements. |
| 75 | + |
| 76 | +Backend retention settings must be configured to match this policy before a |
| 77 | +panel is published. A review owner must re-check the Sentry MCP options and the |
| 78 | +telemetry dictionary whenever the SDK or dashboard definitions change. |
| 79 | + |
| 80 | +## Publication checklist |
| 81 | + |
| 82 | +Automated guards that must remain green: |
| 83 | + |
| 84 | +- [x] Sentry MCP input capture is explicitly disabled; `src/index.test.ts` |
| 85 | + asserts `recordInputs: false`. |
| 86 | +- [x] Sentry MCP output capture is explicitly disabled; `src/index.test.ts` |
| 87 | + asserts `recordOutputs: false`. |
| 88 | +- [x] Metric dimensions have fixed taxonomies or bounded sanitization; |
| 89 | + `src/tools/register.test.ts` and `src/utils/telemetry-wrapper.test.ts` |
| 90 | + cover the declared fields. |
| 91 | +- [x] Raw queries, IDs, dates, titles, notes, descriptions, and measurements |
| 92 | + are excluded; privacy regression tests assert secret-sentinel absence. |
| 93 | +- [x] Returned MCP errors and thrown errors have separate outcomes; |
| 94 | + `src/utils/telemetry-wrapper.test.ts` covers both paths. |
| 95 | +- [x] Session termination and sanitized client/protocol fields are covered by |
| 96 | + `src/utils/mcp-session-observability.test.ts`. |
| 97 | +- [x] Backend retention and dashboard access policy are documented above. |
| 98 | + |
| 99 | +Before publishing or changing a panel: |
| 100 | + |
| 101 | +- [ ] Configure backend retention to the policy above. |
| 102 | +- [ ] Confirm repository maintainers and the on-call operator own access. |
| 103 | +- [ ] Re-run the privacy regression tests and re-review the data dictionary |
| 104 | + whenever Sentry, OpenTelemetry, or dashboard definitions change. |
0 commit comments