Saltar al contenido

Docs / Log sink propio y retención

BYO log sink — extended log retention

Raw CI/review/run logs live on the platform for 72 hours. Bring your own Postgres for retention on your terms.

BYO log sink — extended log retention

developerz.ai keeps the raw logs your runs produce — coding-agent traces, PR-review transcripts, command output — for 72 hours, then redacts the payloads. The run timeline keeps its shape (event kinds, timestamps, outcomes); the raw content is gone. The permanent, tamper-evident audit trail of actions is never pruned — retention applies to raw log content only.

Want logs for longer? Bring your own database. You give us a Postgres connection URL; your runners mirror raw log events straight into it. Your database, your retention — keep a week or keep forever.

The two paths

Path Where logs live Retention
Default Platform database 72 hours (raw payloads), then redacted
BYO sink A Postgres you own Yours — we never delete from your database

On the BYO path the write happens on your own servers: the runner on your box writes directly to your database (ideally through your pooler). Raw log content does not need to transit the platform to reach your sink.

Setup

  1. Create a database and a scoped role for the sink (see security notes below).

  2. In the dashboard, open API keys & log sink and paste the connection URL:

    postgres://dz_logs_writer:PASSWORD@your-pooler.example.com:6432/developerz_logs
    

    We validate the URL (postgres:// or postgresql://, publicly routable host, named database), test-connect once, then store it encrypted with the same envelope custody as BYOK keys. It is delivered to your runner boxes at enrollment and never displayed again — the dashboard shows only host, port, and database.

  3. Runners create an append-only developerz_logs table on first write:

    -- auto-created; shown for reference
    create table if not exists developerz_logs (
      id bigint generated always as identity primary key,
      run_id text not null,
      task_id text not null,
      lane text not null,        -- 'run' | 'review' | 'ci'
      kind text not null,        -- tool_call | command | agent_response | …
      ts timestamptz not null default now(),
      payload jsonb
    );
    

Boxes enrolled before you set the sink pick it up at their next enrollment; to wire an existing box immediately, add DZ_LOG_SINK_URL=… to /etc/dz-runner/env and restart the dz-runner service.

Put a pooler in front (pgbouncer / pgcat)

Our log writers are bursty: an agent step can emit dozens of events in a second, then nothing for minutes — multiplied by every box in your fleet. Each runner caps itself at 2 connections, but a pooler is still strongly recommended so bursts share a few real backend connections instead of piling up against max_connections:

; pgbouncer.ini — three lines that matter
[databases]
developerz_logs = host=10.0.0.5 dbname=developerz_logs
pool_mode = transaction

pgcat in transaction mode works equally well. Runners disable prepared statements, so transaction pooling is safe.

Delivery semantics

  • Best-effort, never blocking. The mirror can never slow down or fail a run. If your database is unreachable, events buffer briefly on the box (bounded — oldest entries drop first), writes back off and retry, and the affected run gets an audited log_sink_degraded warning event. The platform copy still lands regardless.
  • Batched. Events are flushed in small batches about once a second.
  • At-least-once-ish. A box crash can lose its unbuffered tail; the 72-hour platform window is your recovery buffer for gaps.

Security notes

  • Send us a scoped role, not a superuser. The runner needs only CREATE on one schema the first time, then INSERT:

    create role dz_logs_writer login password '…';
    create database developerz_logs owner dz_logs_writer;
    

    Never reuse a role that can read your production data.

  • The connection URL embeds credentials, so it is write-only: encrypted at rest with the platform's key-encryption envelope (the BYOK custody path), never logged, never shown again in the dashboard or API.

  • Private-network hosts (localhost, RFC-1918 ranges, link-local) are rejected — the sink must be reachable from your own boxes over a routable address.

  • Rotating the password? Just paste the new URL — it replaces the old one and is re-verified with a fresh test connection.