|
| 1 | +--- |
| 2 | +title: Usage Telemetry |
| 3 | +description: Report daily workflow and credit usage from a self-hosted deployment to a Sim instance |
| 4 | +--- |
| 5 | + |
| 6 | +import { Callout } from 'fumadocs-ui/components/callout' |
| 7 | + |
| 8 | +A self-hosted deployment can report a daily summary of its usage — workflow runs, credits, and model token volume — to a Sim instance, so that instance can see how the deployment is used over time and value that usage at a rate agreed for the deployment. |
| 9 | + |
| 10 | +The feature is **off by default**. Nothing is collected or sent until the four variables below are set, and the workflow execution path never touches it: reporting runs from a background job that reads the deployment's own database after the fact. |
| 11 | + |
| 12 | +## What is sent |
| 13 | + |
| 14 | +One record per UTC calendar day, re-sent for a trailing window on every run so a day converges on its final figures once it has elapsed. Each record carries: |
| 15 | + |
| 16 | +| Field | Source | |
| 17 | +|-------|--------| |
| 18 | +| Workflow executions, failures, total duration | Execution logs | |
| 19 | +| Credits | The usage ledger's dollar sum for the day × 200 | |
| 20 | +| Input and output tokens, per model | The usage ledger's token metadata | |
| 21 | +| Events and credits per usage source | The usage ledger (`workflow`, `knowledge-base`, `wand`, …) | |
| 22 | + |
| 23 | +Nothing else crosses the wire: no workflow inputs or outputs, no credentials, no workflow or user identifiers, and no tool or block names. Aggregation happens inside the database query, so per-execution rows never reach the reporting code. |
| 24 | + |
| 25 | +<Callout type="info"> |
| 26 | + On a self-hosted deployment, models usually run on your own API keys, so their ledger rows carry **tokens with zero credits**. Credits on such a deployment mostly reflect the per-run execution charge (1 credit per workflow run); token volume is reported alongside so the receiving instance can see model usage that Sim never billed. |
| 27 | +</Callout> |
| 28 | + |
| 29 | +## Enable reporting |
| 30 | + |
| 31 | +Register the deployment on the receiving instance (see [Receiving reports](#receiving-reports) below), then set on the self-hosted deployment: |
| 32 | + |
| 33 | +```bash |
| 34 | +ONPREM_TELEMETRY_ENABLED=true |
| 35 | +ONPREM_TELEMETRY_ENDPOINT=https://sim.example.com # the receiving instance |
| 36 | +ONPREM_TELEMETRY_DEPLOYMENT_ID=acme-prod # issued at registration |
| 37 | +ONPREM_TELEMETRY_API_KEY=simot_… # issued at registration, shown once |
| 38 | +``` |
| 39 | + |
| 40 | +Optional: |
| 41 | + |
| 42 | +| Variable | Default | Description | |
| 43 | +|----------|---------|-------------| |
| 44 | +| `ONPREM_TELEMETRY_LOOKBACK_DAYS` | `7` | How many trailing days each run re-sends (max 90). Bounds how long the receiving instance can be unreachable before a day is missed. | |
| 45 | + |
| 46 | +The report runs from the `onprem-usage-report` background job every six hours (Docker Compose: `docker/crontab`; Kubernetes: `cronjobs.jobs.onpremUsageReport`). To send immediately: |
| 47 | + |
| 48 | +```bash |
| 49 | +curl -H "Authorization: Bearer $CRON_SECRET" https://your-deployment/api/cron/onprem-usage-report |
| 50 | +``` |
| 51 | + |
| 52 | +The response reports `delivered`, `failed` (with the reason), or `disabled`. |
| 53 | + |
| 54 | +## Disable reporting |
| 55 | + |
| 56 | +Unset `ONPREM_TELEMETRY_ENABLED` (or set it to `false`). The next job run exits before running any query or opening any connection, and stays that way until re-enabled. No restart is needed. This is the right setting for airgapped deployments; the job itself is harmless to leave scheduled. |
| 57 | + |
| 58 | +A deployment that is enabled but cannot reach the endpoint keeps running workflows normally. The job logs the failure and re-sends the same window next time. |
| 59 | + |
| 60 | +## Receiving reports |
| 61 | + |
| 62 | +The receiving instance is any Sim deployment with the [admin API](/platform/self-hosting/environment-variables) enabled. Register a deployment and (optionally) its rate in one call: |
| 63 | + |
| 64 | +```bash |
| 65 | +curl -X POST https://sim.example.com/api/v1/admin/onprem-telemetry/deployments \ |
| 66 | + -H "x-admin-key: $ADMIN_API_KEY" -H "Content-Type: application/json" \ |
| 67 | + -d '{"id": "acme-prod", "name": "Acme production", "usdPerCredit": 0.005}' |
| 68 | +``` |
| 69 | + |
| 70 | +The response includes `apiKey` exactly once; only its hash is stored. |
| 71 | + |
| 72 | +### Conversion rates |
| 73 | + |
| 74 | +Each deployment has its own append-only history of credit → dollar rates: |
| 75 | + |
| 76 | +```bash |
| 77 | +# Set a new rate, effective now |
| 78 | +curl -X POST https://sim.example.com/api/v1/admin/onprem-telemetry/deployments/acme-prod/rates \ |
| 79 | + -H "x-admin-key: $ADMIN_API_KEY" -H "Content-Type: application/json" \ |
| 80 | + -d '{"usdPerCredit": 0.004}' |
| 81 | + |
| 82 | +# Backdate a correction |
| 83 | +curl -X POST … -d '{"usdPerCredit": 0.0045, "effectiveFrom": "2026-09-01T00:00:00Z"}' |
| 84 | +``` |
| 85 | + |
| 86 | +Rates are never edited or deleted. Credits are the stored fact; dollars are computed when usage is read, from the rate whose `effectiveFrom` most recently precedes each day's start. That defines what a rate change does to history: |
| 87 | + |
| 88 | +- A rate effective **now** changes the value of days from now on. Earlier days keep the rate that covered them. |
| 89 | +- A rate effective at an **earlier instant** re-values the days from that instant forward the next time they are read. No credit figure changes, and the rate table shows what applied when. |
| 90 | +- Days before a deployment's first rate have no dollar value; the usage response counts their credits as `unvaluedCredits` rather than pricing them silently. |
| 91 | + |
| 92 | +### Reading usage |
| 93 | + |
| 94 | +```bash |
| 95 | +curl "https://sim.example.com/api/v1/admin/onprem-telemetry/deployments/acme-prod/usage?from=2026-09-01T00:00:00Z&to=2026-10-01T00:00:00Z" \ |
| 96 | + -H "x-admin-key: $ADMIN_API_KEY" |
| 97 | +``` |
| 98 | + |
| 99 | +Every row states its `credits`, the `rate` it was valued with (`usdPerCredit` and `effectiveFrom`), and the resulting `usd`, plus the per-source and per-model breakdown the deployment sent. Totals cover the range. `GET …/deployments` lists deployments with their current rate and last report time; `GET …/deployments/{id}/rates` shows the rate history. |
| 100 | + |
| 101 | +## Limitations |
| 102 | + |
| 103 | +- **Cooperative, not enforced.** The deployment controls its own database and can disable reporting; nothing here proves completeness. It is a usage picture, not a metering system. |
| 104 | +- **Chat usage is not included.** With billing disabled, cost callbacks from the Sim agent service are acknowledged without being recorded, so Chat model usage never reaches the ledger on a self-hosted deployment. |
| 105 | +- **The current day is partial** until the first run after UTC midnight; `reportedAt` on each row says when it was last sent. |
| 106 | +- **Ledger scan.** Each run aggregates the trailing window from `usage_log` by `created_at`. On a very large deployment consider adding an index on `usage_log (created_at)`. |
0 commit comments