Collector data reference
Collectors send JSON to POST /api/collector/device/events, authenticated with the machine’s collector token. The platform writes each event to a shield360_collector_* table in the tenant’s ClickHouse database, stamping database_config_id and collector_id from the token.
Every table also carries the reporting person (user_name), host, and event time. You can query these tables directly from custom dashboards and from Otter.
| Event | Table | Key fields | Policy |
|---|---|---|---|
shield360.collector.usage | shield360_collector_usage | record_id, tool, model, project, auth_type, plan, input, output and cache tokens | Always |
shield360.collector.output_session | shield360_collector_output_sessions | session_id, source, repo_path, lines_added, lines_removed, started_at, updated_at | Always |
shield360.collector.app_activity | shield360_collector_app_activity | app_id, app_name, seconds, samples, idle_seconds | Always |
shield360.collector.app_span | shield360_collector_app_spans | app_id, app_name, started_at, ended_at, samples | Always |
shield360.collector.machine_state | shield360_collector_machine_states | state (locked, away), started_at, ended_at | Always |
shield360.collector.site_activity | shield360_collector_site_activity | service, seconds, samples | Browsing domains or full |
shield360.collector.browsing_visit | shield360_collector_browsing_visits | url, browser, level | Browsing full |
shield360.collector.network_observation | shield360_collector_network_observations | process, process_path, os_user, provider, key_fingerprints | Network observation (+ key fingerprints) |
shield360.collector.heartbeat | shield360_collector_heartbeats | mode, browsing_level, collector version | Always |
Field notes
Section titled “Field notes”auth_typeandplansay whether usage was billed per token or covered by a subscription, as the tool itself recorded it. They drive coverage in the spend report. Each record is labelled with the billing in force when it happened, so changing plan doesn’t relabel usage already reported.plan_tieris the tier within the plan: for Codex, the ChatGPT plan (plus,pro,teamand so on) from the rollout’s rate-limit snapshot or the sign-in’s token claims, read on the machine. The token never leaves it.cache_write_tokensis every cache write;cache_write_1h_tokensis the part written with a one-hour lifetime, which costs more. Older rows have0there and are priced as five-minute writes.- Claude Code writes a line per content block of each response, and only the last carries the final output count. The collector reports each response once, from its most complete line, at the time of its first line. A response still streaming when the collector reads it is sent again whole on the next run, under the same
record_id, and replaces the partial row. - Codex writes a
token_usage_recordper response in newer versions. The collector counts those, one per response id, and falls back totoken_countevents for older rollouts. Archived sessions are read too. machine_stateseparates locked (on, showing a login window or screensaver) from away (no samples at all: asleep, off, or the collector not running). It doesn’t try to tell apart asleep, off and stopped, because from outside they’re indistinguishable.- Network observations have no byte or token counts by design. They’re an attribution signal, joined against what the provider billed.
Coding-agent telemetry
Section titled “Coding-agent telemetry”Coding-agent hooks send OpenTelemetry traces, metrics and logs through the device-authenticated gateway, so developer machines never need a platform API key:
POST /api/collector/device/otlp/v1/tracesPOST /api/collector/device/otlp/v1/metricsPOST /api/collector/device/otlp/v1/logsThese land in the standard OpenTelemetry tables and power Coding Agents.