Skip to content

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.

EventTableKey fieldsPolicy
shield360.collector.usageshield360_collector_usagerecord_id, tool, model, project, auth_type, plan, input, output and cache tokensAlways
shield360.collector.output_sessionshield360_collector_output_sessionssession_id, source, repo_path, lines_added, lines_removed, started_at, updated_atAlways
shield360.collector.app_activityshield360_collector_app_activityapp_id, app_name, seconds, samples, idle_secondsAlways
shield360.collector.app_spanshield360_collector_app_spansapp_id, app_name, started_at, ended_at, samplesAlways
shield360.collector.machine_stateshield360_collector_machine_statesstate (locked, away), started_at, ended_atAlways
shield360.collector.site_activityshield360_collector_site_activityservice, seconds, samplesBrowsing domains or full
shield360.collector.browsing_visitshield360_collector_browsing_visitsurl, browser, levelBrowsing full
shield360.collector.network_observationshield360_collector_network_observationsprocess, process_path, os_user, provider, key_fingerprintsNetwork observation (+ key fingerprints)
shield360.collector.heartbeatshield360_collector_heartbeatsmode, browsing_level, collector versionAlways
  • auth_type and plan say 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_tier is the tier within the plan: for Codex, the ChatGPT plan (plus, pro, team and 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_tokens is every cache write; cache_write_1h_tokens is the part written with a one-hour lifetime, which costs more. Older rows have 0 there 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_record per response in newer versions. The collector counts those, one per response id, and falls back to token_count events for older rollouts. Archived sessions are read too.
  • machine_state separates 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 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/traces
POST /api/collector/device/otlp/v1/metrics
POST /api/collector/device/otlp/v1/logs

These land in the standard OpenTelemetry tables and power Coding Agents.