Skip to content

Commit 9284ebf

Browse files
authored
chore: sync implementation report with prod mirror delivery
Generated-By: PostHog Code Task-Id: 0c511836-2180-455a-9b58-45df2a0661ec
1 parent e45bd3e commit 9284ebf

1 file changed

Lines changed: 6 additions & 5 deletions

File tree

REPORT.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,10 @@ This branch also carries the scout-run log mirror by Andrew Maguire ([#71094](ht
9898
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.
9999
Mirroring is fire-and-forget — a mirror failure is logged and never breaks the run's S3 log write.
100100

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.
104105

105106
## Changes in PostHog/code (this branch)
106107

@@ -131,7 +132,7 @@ Incorporated from [#71094](https://github.com/PostHog/posthog/pull/71094) (scout
131132

132133
- `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.
133134
- `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).
135136
- `products/tasks/backend/tests/test_run_log_mirror.py` (new): severity/body mapping matrix, run-identity fields, truncation/batch caps, and `append_log` gating (allowlist, disabled, mirror-failure isolation).
136137
- `docs/internal/sandboxes-setup-guide.md`: mirroring section.
137138

@@ -172,4 +173,4 @@ Incorporated from [#71094](https://github.com/PostHog/posthog/pull/71094) (scout
172173
| Django settings | `SANDBOX_AGENT_OTEL_TRACES_URL` | Full OTLP traces ingest URL; unset = spans off, logs unaffected |
173174
| 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 |
174175
| 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

Comments
 (0)