Alright, gather 'round the campfire of burning cash. I finally did what Microsoft probably hopes you never do: I used Sentinel's own logs and data to build a dashboard that tracks what Sentinel itself is costing. The results were, predictably, a masterclass in how opaque pricing models separate the well-intentioned from their budget.
We've all heard the pitch: "unified SIEM and SOAR," "cloud-native scale," "seamless integration with the Microsoft ecosystem." What they whisper is that your bill is a function of ingested data volume, and that volume is a black box you're just supposed to accept. So I wired up a Logic App (because, of course, more Azure services) to periodically query the `_AzureSentinel` table in the Log Analytics workspace. I'm pulling the `_BilledSize` and `_IsBillable` fields for every log that passes through, aggregating by table, source, and ingestion time. The KQL isn't rocket science, but the visibility it provides is damning.
```kql
// Core query pattern for daily cost by table
AzureDiagnostics
| where ResourceProvider == "MICROSOFT.OPERATIONALINSIGHTS"
and Category == "Ingestion"
| project TimeGenerated, _BilledSize, _IsBillable, Table=split(_ResourceId, "/")[8]
| where _IsBillable == true
| summarize DailyBillableGB = sum(_BilledSize) / (1000 * 1000 * 1000) by Table, bin(TimeGenerated, 1d)
| render columnchart
```
The insights? Let's just say "surprising" is a polite term.
First, the sheer volume of diagnostic data Sentinel generates about itself is non-trivial. You're paying to ingest logs about...ingesting logs. A beautiful ouroboros of billing. Second, and more critically, the default diagnostic settings for many Azure resourcesβespecially if you've clicked "enable all" in a moment of hopeful automationβare a firehose of verbose, often low-value data straight into your most expensive log table. I found a single, overly chaty Azure Firewall policy debug log stream costing more per day than the actual security alerts it was supposed to help generate.
The final, cynical lesson? The tool designed to give you visibility into your estate is itself one of the largest opacity-driven cost centers. You cannot manage what you do not measure, and Microsoft is all too happy to not provide the measuring tape unless you build it yourself from their scraps. So before you get swept up in the next "AI-driven security narrative," ask yourself: do you know what each alert actually costs you to generate? I didn't. Now I do, and I'm not thrilled.
-- cynical ops
Your k8s cluster is 40% idle.
This is honestly the kind of post I come here for. I've been trying to wrap my head around our own Sentinel spend, and that black box feeling is so real. The idea of querying its own logs for billing data is brilliant.
Could you maybe share a bit more on the Logic App setup? I'm still getting the hang of Azure, and I'd love a bit of a step-by-step on how you scheduled those queries and where you're pushing the aggregated data. I'm picturing a Power BI dashboard, maybe, but I'm not sure where to start.
Seeing the actual cost broken down by table sounds like it would be a game changer for us.
Your query is broken off mid sentence, but I see where you're headed. That's the right table, but you're making it harder than it needs to be.
Use `_BilledSize` directly from the `AzureDiagnostics` table, not `_AzureSentinel`. The billing data is clearer there. Also, you need to filter on `OperationName == "Data Collection"` to isolate the actual ingestion logs.
Here's a more reliable pattern:
```kql
AzureDiagnostics
| where TimeGenerated > ago(30d)
| where ResourceProvider == "MICROSOFT.OPERATIONALINSIGHTS/WORKSPACES"
| where OperationName == "Data Collection"
| summarize BilledGB = sum(_BilledSize) / (1000*1000*1000) by TableName = tostring(Properties.TableName), bin(TimeGenerated, 1d)
```
That `Properties.TableName` field gives you the actual Sentinel table. The biggest shock for me was seeing how much junk data my own custom connectors were generating.
garbage in, garbage out