Daily cloud cost and budgets across AWS, Azure, Google Cloud and Oracle
How OpsNexus reads inventory and daily cost from four clouds with read-only access, keeps credits apart from usage, forecasts each budget and tells you once per threshold.
Every cloud has a good cost console. The trouble starts when you use more than one. Each console has its own idea of a month, its own grouping and its own handling of credits, and none of them shows the others. The monthly "what did we spend?" email turns into a spreadsheet.
OpsNexus connects to AWS, Azure, Google Cloud and Oracle Cloud, pulls inventory and daily cost into one place, and checks your budgets against it. This post explains where the numbers come from and the choices behind them.
Read-only, always
OpsNexus never changes anything in a cloud account it reads cost from. Every connection uses read-only access:
| Cloud | Sign-in | Roles to grant |
|---|---|---|
| AWS | Access key, or the instance role; optional role to assume with external ID | ReadOnlyAccess plus ce:GetCostAndUsage |
| Azure | Service principal (tenant, client ID, secret, subscriptions) | Reader and Cost Management Reader |
| Google Cloud | Service account JSON key, project IDs | Cloud Asset Viewer, plus BigQuery Data Viewer and Job User on the billing dataset |
| Oracle Cloud | API signing key (tenancy, user, fingerprint, region) | inspect all-resources and read usage-reports |
Secret parts of the sign-in, such as the AWS secret key or the Google JSON key, go to the secret store and never to the database.
For AWS, you can also give OpsNexus a role to assume in another account, with an external ID. That is the usual way to read several accounts without creating keys in each one.
Where each number comes from
Inventory and cost come from different APIs in every cloud, and they fail for different reasons, so OpsNexus tracks them separately.
| Cloud | Inventory | Daily cost |
|---|---|---|
| AWS | Each service's API, per region | Cost Explorer |
| Azure | Resources API, plus VM power state | Cost Management Query |
| Google Cloud | Cloud Asset Inventory | The BigQuery billing export |
| Oracle Cloud | Resource Search | Usage API |
If the resource list works but cost doesn't, the account still shows its resources, along with a cost status that says exactly what's missing. Examples are "grant Cost Management Reader" on Azure, or "Set the billing export table to see GCP cost" on Google Cloud. A partial answer with a clear reason is more useful than an error that hides everything.
The same idea applies inside a sync. If one AWS region or service fails this time, OpsNexus keeps the last known resources for that part instead of deleting them. A brief API error shouldn't make half your inventory disappear.
Daily, and re-read every time
The scheduler syncs every account every CLOUD_SYNC_MINUTES (60 by default). Each sync reads the last CLOUD_COST_DAYS (90 by default) of daily cost and replaces those days. It doesn't just append yesterday.
That's deliberate. Cloud cost data is not final when you first see it. Late usage records, refunds and amortization keep changing the last few days, and sometimes earlier ones. Re-reading the window means your numbers converge to what the bill will say.
Costs are stored per day, service and region. So the Cost & budgets page can show month to date, last month, the trend and the top services and regions for one cloud or all of them together.
Per-resource cost on AWS
AWS can split cost by resource, but Cost Explorer only returns the last 14 days of it. OpsNexus keeps that history itself. Each sync replaces the days AWS sent again, keeps everything older, and holds up to 400 days. That's what makes views such as cost by VPC possible for 30 or 90 days, not just two weeks.
Credits are not savings
Credits and refunds are stored as their own line, Credits & refunds, and they're left out of usage figures and budgets. They're shown separately.
The reason: a budget watches what your workloads consume. If a promotional credit covers half of this month, your workloads didn't get cheaper. When the credit runs out, a budget that counted it would suddenly look broken. Keeping them apart means the trend line shows real usage, and the credits line shows what's actually being paid for you.
Budgets that forecast
A budget is a monthly amount with a scope: all clouds, one cloud, one account, or one service. Each has thresholds, 50%, 80% and 100% by default.
After every sync, OpsNexus checks each budget:
spent = usage this calendar month, in the budget's scope
forecast = spent / days elapsed * days in month
percent = spent / amount * 100The forecast is a straight line on purpose. It's easy to explain, and it's right often enough to answer the question that matters mid-month: "at this rate, where do we land?"
When spend crosses a threshold, OpsNexus sends a cost.alert notification, for example "Budget Production at 82% (80% threshold)", with spend, amount and forecast. Each threshold alerts once per month. Crossing 80% tells you once, and the next message is at 100%. Alerts at 100% or more are high severity. Lower ones are medium.
Recommendations from your own data
The Cost & budgets page also lists recommendations. They come from rules over your synced data, not from a cloud's advisor:
- Stopped virtual machines. They still pay for disks, snapshots and reserved IPs. Where per-resource cost is available, OpsNexus adds what their attached disks cost over the last 14 days.
- Resources without tags. Workloads with no tags can't be split by team or owner. Network plumbing such as subnets and route tables is left out.
- Spend jumps. A service whose spend so far this month is more than 30% above the same days of last month (and above a small floor) gets flagged.
Reports
For the monthly review, Cost & budgets exports a cost report as PDF or Excel for up to 90 days. It covers cost by cloud, region, service, account, VPC and resource. The same data is available from the API:
curl -s "https://opsnexus.example.com/api/cloud/cost-report?days=30&format=xlsx" \
-H "X-API-Key: $ONX_ACCESS_KEY.$ONX_SECRET_KEY" -o cost-report.xlsxGetting started
Connect an account under Cloud, pick the sign-in method, and grant the read-only roles above. The first sync loads the last 90 days. Then add a budget for your largest account and route cost.alert to the right channel. The Cloud accounts and Cost and budgets docs have the step-by-step setup for each cloud.