Ingestion Monitoring
Watch ingestion queues and database writes to distinguish accepted SDK traffic from data that Tindra has confirmed as stored.
Delivery and storage
Tindra queues errors, transactions, logs, and profiles in bounded memory buffers, then writes batches to Postgres. An HTTP success response confirms handling of the request, not that every item has been persisted. Use Project Setup to confirm a tagged test event and inspect stored-data milestones.
Errors and transactions refused by a full or closing buffer return HTTP 429. Logs and profiles are best effort: capacity pressure can drop those items while the envelope still succeeds. An envelope can also be partially accepted before a later error or transaction is refused. Retrying the whole envelope may therefore resend already accepted items.
Malformed envelopes, including null headers or truncated items, are rejected before item processing. SDK authentication failures, quota/rate limits, payload-size limits, and invalid individual payloads have separate outcomes. Check the SDK response and setup diagnostics alongside queue metrics; the queue counters do not count every request rejected before it reaches a buffer.
Retryable database failures receive bounded retries with backoff, up to five write attempts within a batch deadline. Permanent record failures are isolated where possible so other records can proceed. Shutdown stops admission and gives writers a finite drain period. These buffers are not disk-backed: a crash, forced stop, exhausted retries, or an expired drain deadline can lose pending data. See Upgrades for graceful shutdown guidance.
Enable Prometheus metrics
Set STATS_API_KEY to an operator secret on the Tindra server and restart it. This key is separate from project API tokens and the SDK's DSN. With the same key available in your shell environment, request:
curl --fail-with-body \
'https://your-hostname.tindra.sh/metrics' \
--header "Authorization: Bearer $STATS_API_KEY"
An unset server key disables this endpoint with HTTP 404; an incorrect credential returns HTTP 401. Authentication does not use a database connection or a user session, so database trouble does not itself hide ingestion metrics.
For Prometheus, mount a file containing only the operator key into the Prometheus process and add this scrape job, replacing the host and secret-file path:
scrape_configs:
- job_name: tindra
scheme: https
metrics_path: /metrics
scrape_interval: 15s
authorization:
type: Bearer
credentials_file: /etc/prometheus/secrets/tindra-stats-key
static_configs:
- targets: ['your-hostname.tindra.sh']
The file is read by Prometheus, not Tindra. See the Prometheus HTTP configuration for credential-file configuration.
Read the metrics
All names below begin with tindra_ingest_ and have a type label: events, transactions, logs, or profiles. Counters and runtime state are process-local and reset on restart, so use counter rates or increases when comparing periods.
| Metric suffix | Meaning |
|---|---|
accepted_total |
Items admitted to a buffer. This is not a storage count. |
persisted_total |
Items confirmed by a successful write, including duplicates already present in the database. This is not a count of new rows. |
rejected_total |
Error or transaction items refused at queue admission. |
dropped_total |
Items abandoned or best-effort admission drops, split by the reason label. |
unknown_commit_items_total |
Items whose commit acknowledgement could not be confirmed. They may already be stored. |
failed_writes_total |
Failed batch write attempts, rather than individual item failures. |
retries_total |
Batch retry attempts. |
queued / capacity |
Items waiting in the queue and its item capacity. |
pending |
All unfinished items, including batches currently writing or retrying. |
pending_bytes / capacity_bytes |
Tracked pending bytes and the configured internal byte ceiling. A zero ceiling means no separate byte budget for that queue. |
oldest_pending_seconds |
Age of the oldest unfinished item. |
last_success_timestamp_seconds |
Unix timestamp of the last confirmed write, or zero before the first success. |
degraded |
1 when the writer reports failure or pressure, including old pending work; otherwise 0. |
Dropped reasons include buffer_full, buffer_bytes, shutdown, write_failed, deadline, invalid_record, and encode_failed. Some apply only to particular queues or failure paths. Admission drops and post-admission failures should be interpreted separately from rejected errors/transactions.
An unknown commit is not confirmed loss. Tindra avoids blindly retrying an ambiguously committed batch because that could duplicate records. Inspect stored data and database logs before deciding whether to resend it.
JSON status and the Overview page
GET /api/instance/ingestion exposes the same queue state as JSON to a signed-in user with manage_projects. Neither a project token nor the operator metrics key substitutes for that session permission.
The Health Overview page shows storage and usage figures. It does not display an ingestion queue dashboard. Queue sizes, retry limits, and byte budgets are internal implementation settings; there are no additional queue-tuning environment variables to configure.
Investigate a backlog
- Compare pending count, oldest pending age, failed-write/retry rates, and last successful writes for the affected data type. An old success timestamp is normal when no traffic is arriving, so interpret it alongside pending work.
- Inspect Tindra writer logs and Postgres connectivity, availability, disk space, and load. A healthy HTTP endpoint does not prove writes are succeeding.
- Check SDK responses, instance usage, request limits, and whether logs or profiles were dropped independently of the error event. Consult Configuration before changing instance limits.
- After resolving the cause, confirm that pending age and counts fall, successful writes resume, and new rejections or drops stop increasing. Historical counters will not return to zero until restart.
- Send a fresh setup check and verify stored data. Recovery of the queue does not restore items already dropped or lost during a crash.
Pending in-memory data is not included in database backups. See Backup for the persisted data and source-map files to retain.