Observability

Request Logs

Every request through VectorAxis — chat, prompts, and media — is captured as a structured log with the who, what, how-much, and how-fast: provider, model, tokens, cost, latency, cache status, retries, fallback, and guardrail outcome. It’s your single place to debug a bad response, attribute spend, and audit what happened.

Why it matters
  • Debug fast. Open any request to see the exact model, timing, error, and (optionally) the full request and response bodies.
  • Attribute cost. Every log carries its dollar cost and the key/config/user behind it — so you know who spent what.
  • Audit & compliance. A durable record of every call, including which guardrail ran and how it resolved.
What’s captured on every log
FieldMeaning
request_idUnique id for the request (also returned to the caller for correlation).
created_atWhen the request was served.
provider / modelWhich provider and model actually served it.
status_codeHTTP result (200, 4xx, 5xx).
duration_msEnd-to-end latency in milliseconds.
prompt_tokens / completion_tokens / total_tokensToken counts (populated for streaming too).
costComputed cost in USD.
cache_statusHIT / SEMANTIC_HIT / MISS / REFRESH / BYPASS / DISABLED.
retry_count / fallback_providerRetries performed and the backup provider used, if any.
virtual_key_slug / config_slugThe virtual key and/or routing config the request used.
guardrail_slug / guardrail_statusThe guardrail applied and its outcome (PASS / BLOCK / REDACT / MONITOR / BYPASS).
organization / workspace_id / user_idAttribution — who the request belongs to.
The detail view adds more. Opening a single log also shows error_message and, when enabled, the full request_body and response_body. For media requests it includes operation_type plus format details — file_size_bytes, mime_type, media_format, image_size / image_quality / image_count, audio_duration_seconds, and voice.
Attribution depends on how you authenticate. Every request is logged with token usage and computed cost either way. But the attribution fields — organization, workspace_id, and virtual_key_slug — are only populated automatically when you call with a virtual key (its owning org and workspace are authoritative). With raw direct credentials (x-provider + x-api-key) those fields stay empty unless you pass x-organization / x-workspace-id yourself — so per-org, per-workspace, and per-key filtering and roll-ups won’t find the request.
Searching & filtering

The Logs page (and GET /v1/logs) let you narrow to exactly the requests you care about, then click a row for the full detail. Every filter is a query parameter:

FilterNarrows to…
provider, modela specific provider and/or model.
statussuccess or error.
cache_statushits, misses, bypass, etc.
virtual_key_slug, config_slug, user_ida specific key, routing config, or user.
guardrail_slug, guardrail_statusrequests a guardrail touched, and how it resolved.
start_time, end_timea date/time range.
min_cost/max_cost, min_duration_ms/max_duration_ms, min_tokens/max_tokensexpensive, slow, or large requests.
searchfree-text across the request.
request_idone exact request.
sort_by / sort_dir, page / page_sizeordering and paging.
Scope any query to a workspace with workspace_id. An org member must scope to a workspace they belong to; org admins can read across the whole org.
Export

Export a filtered set of logs as CSV or JSON (up to 50,000 rows). Because exports can be large, they run asynchronously: you start a job, poll it until it’s DONE, then download the file. Finished exports are available for 1 hour. Exporting is an org-admin action.

Who can view logs

Workspace members and above can view and filter logs for their workspace; org admins see the whole org. Exporting requires an org admin. Full breakdown on the Access Control page.

Developer API reference

MethodPathWho can call it
GET/v1/logsMember (scope to a workspace)
GET/v1/logs/{id}Workspace member
POST/v1/logs/exportOrg admin
GET/v1/logs/export/{jobId}Org admin
GET/v1/logs/export/{jobId}/downloadOrg admin
http
# Slow, expensive OpenAI errors in a workspace, last 24h
GET /v1/logs?organization=acme&workspace_id=<uuid>&provider=OPENAI
    &status=error&min_duration_ms=5000&start_time=2026-06-29T00:00:00Z
Authorization: Bearer va_...

# Kick off an export, then download when DONE
POST /v1/logs/export        { "format": "csv", "provider": "OPENAI" }   -> { "job_id": "...", "status": "PENDING" }
GET  /v1/logs/export/{jobId}                                            -> { "status": "DONE", "row_count": 1234 }
GET  /v1/logs/export/{jobId}/download                                   -> file
Want the aggregate picture instead of individual rows — cost and latency trends, top models, cache-hit rate? See Analytics.