You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: REPORT.md
+6-5Lines changed: 6 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -98,9 +98,10 @@ This branch also carries the scout-run log mirror by Andrew Maguire ([#71094](ht
98
98
The privacy postures are compatible because the scopes differ: scout runs are PostHog-authored agents whose transcripts we already own end to end, so full bodies into the internal project are fine there, while the OTLP path covers customer-driven runs and therefore stays metadata-only.
99
99
Mirroring is fire-and-forget — a mirror failure is logged and never breaks the run's S3 log write.
100
100
101
-
The mirror additionally has a **direct OTLP leg for local dev** (added on this branch, on top of #71094): `append_log` runs in the host Django process, and `otel-collector-config.dev.yaml` only tails docker-compose container stdout, so the mirrored lines never reached local Logs — verified during local testing where `/logs` showed only the OTLP metadata records.
102
-
In DEBUG each batch is also shipped straight to the logs OTLP endpoint the agent telemetry already uses (`SANDBOX_AGENT_OTEL_LOGS_URL` + `_TOKEN` — no new settings), arriving as `service.name=task-run-log-mirror` with the run uuid as the trace id and the structlog fields as attributes.
103
-
DEBUG-only by design: in production those settings point at the customer-facing telemetry project, and the collector daemonset already delivers pod stdout to the internal project — reusing them there would double-deliver scout bodies into the wrong project.
101
+
The mirror additionally has a **direct OTLP leg** (added on this branch, on top of #71094): `TASK_RUN_LOGS_MIRROR_OTLP_URL` + `_TOKEN` ship each batch straight to a logs ingest endpoint, arriving as `service.name=task-run-log-mirror` with the run uuid as the trace id and the structlog fields as attributes.
102
+
The token pins the destination — scout runs execute for customer teams, and their mirrored transcripts must only ever land in (and bill) PostHog's own internal logs project, never the customer's — so the intended production value is the internal logs project's API key, deliberately not derived from the run's team and not reusing `SANDBOX_AGENT_OTEL_LOGS_TOKEN` (which addresses the separate agent-telemetry project).
103
+
It is also the only delivery path in local dev, where `append_log` runs in the host Django process whose stdout the dev collector (docker containers only) never tails — verified during local testing where `/logs` showed only the OTLP metadata records until this leg existed.
104
+
Delivery is best-effort (3 s timeout, one POST per persisted batch, scout runs only) and never raises into the run.
104
105
105
106
## Changes in PostHog/code (this branch)
106
107
@@ -131,7 +132,7 @@ Incorporated from [#71094](https://github.com/PostHog/posthog/pull/71094) (scout
131
132
132
133
-`products/tasks/backend/logic/services/run_log_mirror.py` (new): translates each ACP JSONL entry into a `task_run_log` structlog stdout line — readable bodies for agent messages / tool calls / sandbox output / turn ends (8k char cap, entry-count cap per call), severity mapping (`_posthog/error` → error, console level passthrough), run-identity fields (`task_run_id`/`task_id`/`team_id`/`origin_product`/`acp_method`) as log attributes, and `request_id` = run uuid as the trace id.
133
134
-`products/tasks/backend/models.py`: `TaskRun.append_log` calls `_mirror_logs_to_posthog_logs` after the S3 write, gated on the origin-product allowlist and wrapped so any failure is logged and never breaks the write.
134
-
-`posthog/settings/temporal.py`: `TASK_RUN_LOGS_MIRROR_ORIGIN_PRODUCTS` (default `signals_scout`; empty disables). The dev delivery leg reuses `SANDBOX_AGENT_OTEL_LOGS_URL`/`_TOKEN`under DEBUG — no mirror-specific OTLP settings.
135
+
-`posthog/settings/temporal.py`: `TASK_RUN_LOGS_MIRROR_ORIGIN_PRODUCTS` (default `signals_scout`; empty disables), plus `TASK_RUN_LOGS_MIRROR_OTLP_URL`/`_TOKEN`for the direct delivery leg (default unset; prod value = internal logs project's key).
| Sandbox env (injected) |`POSTHOG_AGENT_OTEL_LOGS_URL` / `_TOKEN` / `POSTHOG_AGENT_OTEL_TRACES_URL`| Read by `agent-server` (`bin.ts`); reserved keys, not user-overridable |
174
175
| Django settings |`TASK_RUN_LOGS_MIRROR_ORIGIN_PRODUCTS`| Task origins whose run logs mirror to the internal project's Logs (default `signals_scout`; empty disables) |
175
-
| Django settings (DEBUG) |`SANDBOX_AGENT_OTEL_LOGS_URL` / `_TOKEN`(reused)| Also serve as the mirror's direct dev delivery leg; ignored by the mirror in production|
176
+
| Django settings |`TASK_RUN_LOGS_MIRROR_OTLP_URL` / `_TOKEN`| Direct OTLP delivery for the mirror; the token pins records to the internal logs project so customer projects are never billed|
0 commit comments