From 3944672a2160d3e4399a9a06518fd64dd2d0f841 Mon Sep 17 00:00:00 2001
From: Dr Bill Mcilhargey <19168174+billmcilhargey@users.noreply.github.com>
Date: Thu, 27 Aug 2026 15:27:25 -0400
Subject: [PATCH 1/6] Update Sentinel Costs workbook
---
Workbooks/SentinelCosts.json | 3068 ++++++++++++++++++++----------
Workbooks/WorkbooksMetadata.json | 2 +-
2 files changed, 2103 insertions(+), 967 deletions(-)
diff --git a/Workbooks/SentinelCosts.json b/Workbooks/SentinelCosts.json
index 37a6cc5ae94..80bc4406cf7 100644
--- a/Workbooks/SentinelCosts.json
+++ b/Workbooks/SentinelCosts.json
@@ -1,968 +1,2104 @@
{
- "version": "Notebook/1.0",
- "items": [
- {
- "type": 1,
- "content": {
- "json": "# Microsoft Sentinel cost summary\n---\n"
- },
- "name": "text - 2"
- },
- {
- "type": 9,
- "content": {
- "version": "KqlParameterItem/1.0",
- "parameters": [
- {
- "id": "9d001d6f-301c-4d03-b02c-b8cc6dce210b",
- "version": "KqlParameterItem/1.0",
- "name": "TimeRange",
- "type": 4,
- "isRequired": true,
- "value": {
- "durationMs": 604800000
- },
- "typeSettings": {
- "selectableValues": [
- {
- "durationMs": 300000
- },
- {
- "durationMs": 900000
- },
- {
- "durationMs": 1800000
- },
- {
- "durationMs": 3600000
- },
- {
- "durationMs": 14400000
- },
- {
- "durationMs": 43200000
- },
- {
- "durationMs": 86400000
- },
- {
- "durationMs": 172800000
- },
- {
- "durationMs": 259200000
- },
- {
- "durationMs": 604800000
- },
- {
- "durationMs": 1209600000
- },
- {
- "durationMs": 2419200000
- },
- {
- "durationMs": 2592000000
- },
- {
- "durationMs": 5184000000
- },
- {
- "durationMs": 7776000000
- }
+ "version": "Notebook/1.0",
+ "items": [
+ {
+ "type": 1,
+ "content": {
+ "json": "# Microsoft Sentinel cost summary\n---\n"
+ },
+ "name": "text - 2"
+ },
+ {
+ "type": 9,
+ "content": {
+ "version": "KqlParameterItem/1.0",
+ "parameters": [
+ {
+ "id": "9d001d6f-301c-4d03-b02c-b8cc6dce210b",
+ "version": "KqlParameterItem/1.0",
+ "name": "TimeRange",
+ "type": 4,
+ "isRequired": true,
+ "value": {
+ "durationMs": 604800000
+ },
+ "typeSettings": {
+ "selectableValues": [
+ {
+ "durationMs": 300000
+ },
+ {
+ "durationMs": 900000
+ },
+ {
+ "durationMs": 1800000
+ },
+ {
+ "durationMs": 3600000
+ },
+ {
+ "durationMs": 14400000
+ },
+ {
+ "durationMs": 43200000
+ },
+ {
+ "durationMs": 86400000
+ },
+ {
+ "durationMs": 172800000
+ },
+ {
+ "durationMs": 259200000
+ },
+ {
+ "durationMs": 604800000
+ },
+ {
+ "durationMs": 1209600000
+ },
+ {
+ "durationMs": 2419200000
+ },
+ {
+ "durationMs": 2592000000
+ },
+ {
+ "durationMs": 5184000000
+ },
+ {
+ "durationMs": 7776000000
+ }
+ ],
+ "allowCustom": true
+ },
+ "timeContext": {
+ "durationMs": 86400000
+ }
+ },
+ {
+ "id": "67c2ce6e-ea54-4ae4-8343-3fcad8e53d1b",
+ "version": "KqlParameterItem/1.0",
+ "name": "Workspace",
+ "type": 5,
+ "isRequired": true,
+ "multiSelect": true,
+ "quote": "\u0027",
+ "delimiter": ",",
+ "query": "resources | where type =~ \u0027Microsoft.operationsmanagement/solutions\u0027 | where name contains \u0027SecurityInsights\u0027 | extend workspaceResourceId = tostring(properties.workspaceResourceId) | join kind=leftouter (resources | where type =~ \u0027Microsoft.OperationalInsights/workspaces\u0027 | project workspaceResourceId = id, workspaceName = name) on workspaceResourceId | project value = workspaceResourceId, label = coalesce(workspaceName, workspaceResourceId)",
+ "crossComponentResources": [
+ "value::all"
+ ],
+ "value": [
+ "value::all"
+ ],
+ "typeSettings": {
+ "limitSelectTo": 100,
+ "additionalResourceOptions": [
+ "value::all"
+ ],
+ "showDefault": false
+ },
+ "timeContext": {
+ "durationMs": 86400000
+ },
+ "queryType": 1,
+ "resourceType": "microsoft.resourcegraph/resources"
+ },
+ {
+ "id": "9375c625-e916-4f48-b072-352d6aeefddb",
+ "version": "KqlParameterItem/1.0",
+ "name": "Price",
+ "label": "Ingestion price",
+ "type": 1,
+ "description": "Enter your ingestion price per GB (PAYG or Commitment Tier). You can also refer to Azure Pricing Calculator.",
+ "typeSettings": {
+ "paramValidationRules": [
+ {
+ "regExp": "^(0|[1-9][0-9]*)(\\.[0-9]+)?$",
+ "match": true,
+ "message": "Enter a non-negative price."
+ }
+ ]
+ },
+ "value": "4"
+ },
+ {
+ "id": "9d5299d0-36a0-4666-9803-ca6931bdaab7",
+ "version": "KqlParameterItem/1.0",
+ "name": "RetentionPrice",
+ "label": "Retention price",
+ "type": 1,
+ "description": "Enter the retention price per GB/month that will be used in this workbook\u0027s calculations",
+ "typeSettings": {
+ "paramValidationRules": [
+ {
+ "regExp": "^(0|[1-9][0-9]*)(\\.[0-9]+)?$",
+ "match": true,
+ "message": "Enter a non-negative price."
+ }
+ ]
+ },
+ "value": "0.1"
+ },
+ {
+ "id": "8f552e99-2d30-4679-b4b0-25429bf0216b",
+ "version": "KqlParameterItem/1.0",
+ "name": "ExecutionCost",
+ "label": "Logic App execution cost",
+ "type": 1,
+ "isRequired": true,
+ "description": "Enter the cost per Logic App execution used for the SOAR estimate.",
+ "typeSettings": {
+ "paramValidationRules": [
+ {
+ "regExp": "^(0|[1-9][0-9]*)(\\.[0-9]+)?$",
+ "match": true,
+ "message": "Enter a non-negative price."
+ }
+ ]
+ },
+ "value": "0.000125"
+ },
+ {
+ "id": "67494f3e-322e-4411-9b45-1cbea03ed618",
+ "version": "KqlParameterItem/1.0",
+ "name": "TotalE5Seats",
+ "label": "Total Microsoft 365 E7/E5/A5/F5/G5 seats",
+ "type": 1,
+ "quote": "\u0027",
+ "description": "Enter the total number of eligible Microsoft 365 E7, E5, A5, F5, and G5 or corresponding Security licenses in your environment. Eligibility depends on the current offer terms and agreement type.",
+ "value": "\u003cunset\u003e",
+ "typeSettings": {
+ "paramValidationRules": [
+ {
+ "regExp": "^([1-9][0-9]*|\u003cunset\u003e|)$",
+ "match": true,
+ "message": "Enter a whole number greater than zero, or clear the value."
+ }
+ ]
+ }
+ },
+ {
+ "id": "f1a5dc2c-7e7f-4e48-9d65-0d52e77b6e3a",
+ "version": "KqlParameterItem/1.0",
+ "name": "TotalDfSP2Licenses",
+ "label": "Protected Defender for Servers Plan 2 servers or nodes",
+ "type": 1,
+ "quote": "\u0027",
+ "description": "Enter the number of protected Defender for Servers Plan 2 servers or nodes used to estimate the 500 MB per server or node per day ingestion benefit. Leave as \u003cunset\u003e when the entitlement is unknown; grant and savings metrics will show N/A.",
+ "value": "\u003cunset\u003e",
+ "typeSettings": {
+ "paramValidationRules": [
+ {
+ "regExp": "^([1-9][0-9]*|\u003cunset\u003e|)$",
+ "match": true,
+ "message": "Enter a whole number greater than zero, or clear the value."
+ }
+ ]
+ }
+ }
+ ],
+ "style": "pills",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces"
+ },
+ "name": "parameters - 5"
+ },
+ {
+ "type": 1,
+ "content": {
+ "json": "## Ingestion summary"
+ },
+ "name": "text - ingestion summary"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let selectedDays = max_of(datetime_diff(\u0027second\u0027, {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); union withsource = SourceTableName * | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where _IsBillable == true | summarize [\u0027Average Billable Daily Ingestion\u0027] = sum(_BilledSize) / 1024.0 / 1024.0 / 1024.0 / selectedDays",
+ "size": 1,
+ "title": "Average Billable Daily Ingestion",
+ "timeContextFromParameter": "TimeRange",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "Average Billable Daily Ingestion",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "greenRed"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ "showBorder": false,
+ "size": "auto"
+ }
+ },
+ "name": "query - 6",
+ "customWidth": "25"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let selectedDays = max_of(datetime_diff(\u0027second\u0027, {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); union withsource = SourceTableName * | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where _IsBillable == true | summarize [\u0027Estimated Average Daily Ingestion Cost\u0027] = sum(_BilledSize) / 1024.0 / 1024.0 / 1024.0 / selectedDays * todouble(\u0027{Price}\u0027)",
+ "size": 1,
+ "title": "Estimated Daily Ingestion Cost",
+ "timeContextFromParameter": "TimeRange",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "Estimated Average Daily Ingestion Cost",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "greenRed"
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ "showBorder": false,
+ "size": "auto"
+ }
+ },
+ "name": "AverageDailyBillableIngestionCost",
+ "customWidth": "25"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true | summarize [\u0027Total Billable Ingestion\u0027] = sum(Quantity) / 1024.0",
+ "size": 1,
+ "title": "Billable Ingestion: {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "Total Billable Ingestion",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "greenRed"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "useGrouping": false,
+ "maximumFractionDigits": 1
+ }
+ }
+ },
+ "showBorder": false,
+ "size": "auto"
+ }
+ },
+ "name": "query - 8",
+ "customWidth": "50"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true | summarize TotalBillableIngestionGB = sum(Quantity) / 1024.0 | project [\u0027Estimated Ingestion Cost\u0027] = TotalBillableIngestionGB * todouble(\u0027{Price}\u0027)",
+ "size": 1,
+ "title": "Estimated Ingestion Cost: {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "Estimated Ingestion Cost",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "greenRed"
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "name": "BillableIngestionCost",
+ "customWidth": "50"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let Categories = datatable(Type:string,Category:string)\r\n[\r\n \"AuditLogs\", \"Azure Active Directory\",\r\n \"SigninLogs\", \"Azure Active Directory\",\r\n \"AADNonInteractiveUserSignInLogs\", \"Azure Active Directory\",\r\n \"AADServicePrincipalSignInLogs\", \"Azure Active Directory\",\r\n \"AADManagedIdentitySignInLogs\", \"Azure Active Directory\",\r\n \"AADProvisioningLogs\",\"Azure Active Directory\",\r\n \"BehaviorAnalytics\", \"User Entity Behavior Analytics\",\r\n \"UserPeerAnalytics\",\"User Entity Behavior Analytics\",\r\n \"UserAccessAnalytics\",\"User Entity Behavior Analytics\",\r\n \"IdentityInfo\",\"User Entity Behavior Analytics\",\r\n \"DeviceLogonEvents\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceEvents\",\"Microsoft Defender for Endpoint\",\r\n\t\"DeviceNetworkInfo\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceImageLoadEvents\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceFileEvents\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceInfo\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceProcessEvents\", \"Microsoft Defender for Endpoint\",\t\r\n\t\"DeviceNetworkEvents\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceRegistryEvents\", \"Microsoft Defender for Endpoint\",\r\n \"DeviceFileCertificateInfo\", \"Microsoft Defender for Endpoint\",\r\n \"EmailAttachmentInfo\", \"Microsoft Defender for Office 365\", \r\n \"EmailEvents\", \"Microsoft Defender for Office 365\", \r\n \"EmailPostDeliveryEvents\", \"Microsoft Defender for Office 365\", \r\n \"EmailUrlInfo\", \"Microsoft Defender for Office 365\",\r\n \"IdentityLogonEvents\", \"Microsoft Defender for Identity\",\r\n \"IdentityQueryEvents\", \"Microsoft Defender for Identity\",\r\n \"IdentityDirectoryEvents\", \"Microsoft Defender for Identity\",\r\n \"CloudAppEvents\", \"Microsoft Defender for Cloud Apps\",\r\n \"AlertEvidence\", \"Microsoft Defender Alert Evidence\",\r\n \"InsightsMetrics\", \"Azure Monitor for VMs\",\r\n \"VMBoundPort\", \"Azure Monitor for VMs\",\r\n \"VMComputer\", \"Azure Monitor for VMs\",\r\n \"VMConnection\", \"Azure Monitor for VMs\",\r\n \"VMProcess\", \"Azure Monitor for VMs\",\r\n \"SecurityEvent\", \"Windows Security Events\",\r\n \"Syslog\", \"Syslog/CEF\",\r\n \"CommonSecurityLog\", \"Syslog/CEF\",\r\n \"ThreatIntelligenceIndicator\", \"Threat Intelligence\",\r\n \"DnsEvents\", \"DNS Logs\",\r\n \"DnsInventory\", \"DNS Logs\",\r\n \"AWSCloudTrail\", \"AWS Cloud Trail\",\r\n \"ConfigurationChange\", \"Change Tracking\",\r\n \"ConfigurationData\", \"Change Tracking\",\r\n \"AzureDiagnostics\", \"Azure Resources\",\r\n \"LAQueryLogs\", \"Management\",\r\n \"SentinelHealth\",\"Management\",\r\n \"Perf\",\"Performance\",\r\n \"AzureMetrics\",\"Azure Metrics\",\r\n \"SecurityNestedRecommendation\", \"Microsoft Defender for Cloud\",\r\n \"SecurityRecommendation\", \"Microsoft Defender for Cloud\",\r\n \"SecurityRegulatoryCompliance\", \"Microsoft Defender for Cloud\",\r\n \"SecureScoreControls\", \"Microsoft Defender for Cloud\",\r\n \"SecurityBaseline\", \"Microsoft Defender for Cloud\",\r\n \"SecureScores\", \"Microsoft Defender for Cloud\",\r\n \"Update\", \"Update Management\",\r\n \"UpdateSummary\", \"Update Management\"\r\n];\r\nlet customTables = Usage\r\n| where TimeGenerated between ({TimeRange:start} .. {TimeRange:end})\r\n| where IsBillable == true\r\n| where DataType contains \"_CL\"\r\n| summarize size = sum(Quantity)/1024 by DataType\r\n| project [\u0027Log Type\u0027] = DataType, [\u0027Table Size\u0027] = size, [\u0027Estimated Cost\u0027] = size*{Price};\r\nlet knownTables = Usage\r\n| where TimeGenerated between ({TimeRange:start} .. {TimeRange:end})\r\n| where IsBillable == true \r\n| join kind=leftouter Categories on $left.DataType == $right.Type\r\n| summarize size =sumif(Quantity, isnotempty(Category))/1024, sizeOther= sumif(Quantity,(isempty(Category) and DataType !contains \"_CL\"))/1024 by Category\r\n| project [\u0027Log Type\u0027] = iif(isnotempty( Category),Category,\"Other\"), [\u0027Table Size\u0027] = iif(isnotempty( Category),size,sizeOther), [\u0027Estimated Cost\u0027] = iif(isnotempty(Category),size*{Price},sizeOther*4);\r\nunion customTables, knownTables\r\n| order by [\u0027Table Size\u0027] desc",
+ "size": 1,
+ "title": "Breakdown of billable ingestion by log category in the last {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "table",
+ "gridSettings": {
+ "formatters": [
+ {
+ "columnMatch": "Log Type",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "35%"
+ }
+ },
+ {
+ "columnMatch": "Table Size",
+ "formatter": 3,
+ "formatOptions": {
+ "palette": "greenRed",
+ "customColumnWidthSetting": "40%"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "useGrouping": false
+ }
+ }
+ },
+ {
+ "columnMatch": "Estimated Cost",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "25%"
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency"
+ }
+ }
+ }
+ ]
+ },
+ "graphSettings": {
+ "type": 0,
+ "topContent": {
+ "columnMatch": "Log Category",
+ "formatter": 1
+ },
+ "centerContent": {
+ "columnMatch": "Billed Size",
+ "formatter": 1,
+ "numberFormat": {
+ "unit": 17,
+ "options": {
+ "maximumSignificantDigits": 3,
+ "maximumFractionDigits": 2
+ }
+ }
+ }
+ }
+ },
+ "name": "query - 2"
+ },
+ {
+ "type": 1,
+ "content": {
+ "json": "## Free Sentinel Data Summary\r\n\r\nMicrosoft documents the following Sentinel data sources as free:\r\n\r\n- Azure Activity Logs (`AzureActivity`)\r\n- Health monitoring for Microsoft Sentinel (`SentinelHealth`)\r\n- Microsoft 365 audit activity (`OfficeActivity`)\r\n- Microsoft Entra ID Protection alerts (`SecurityAlert`)\r\n- Microsoft Defender for Cloud and Defender for IoT alerts (`SecurityAlert`)\r\n- Microsoft Defender XDR incidents and alerts (`SecurityIncident`, `SecurityAlert`)\r\n- Microsoft Defender for Endpoint, Identity, Cloud Apps, and Office 365 alerts (`SecurityAlert`)\r\n\r\nThis section estimates Analytics-tier ingestion in the selected workspace scope and keeps it separate from billable ingestion. It does not estimate data lake-only ingestion, storage, processing, or query charges. Usage is grouped by table and cannot reliably identify the originating connector, so `SecurityAlert` cannot be allocated reliably among its contributing services. This estimate does not calculate the separate Sentinel free trial. Review the [Microsoft Sentinel free data sources](https://learn.microsoft.com/en-us/azure/sentinel/billing?tabs=simplified%2Ccommitment-tiers#free-data-sources) documentation for current eligibility and billing terms."
+ },
+ "name": "text - free Sentinel data"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let freeTypes = dynamic([\"AzureActivity\",\"SentinelHealth\",\"OfficeActivity\",\"SecurityAlert\",\"SecurityIncident\"]); let periodDays = max_of(datetime_diff(\u0027second\u0027, {TimeRange:end}, {TimeRange:start}) / 86400.0, 1); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where DataType in (freeTypes) | summarize [\u0027Average Free Data Per Day\u0027] = sum(Quantity) / 1024.0 / periodDays",
+ "size": 1,
+ "title": "Average Free Data Per Day",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No documented free Sentinel data was observed in the selected time range.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "Average Free Data Per Day",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "blue"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 3
+ }
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "25",
+ "name": "FreeSentinelDataTotal"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let freeTypes = dynamic([\"AzureActivity\",\"SentinelHealth\",\"OfficeActivity\",\"SecurityAlert\",\"SecurityIncident\"]); let periodDays = max_of(datetime_diff(\u0027second\u0027, {TimeRange:end}, {TimeRange:start}) / 86400.0, 1); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where DataType in (freeTypes) | summarize [\u0027Estimated Free-Data Savings Per Day\u0027] = sum(Quantity) / 1024.0 / periodDays * todouble(\u0027{Price}\u0027)",
+ "size": 1,
+ "title": "Avg Daily Free-Data Savings",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No documented free Sentinel data was observed in the selected time range.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "Estimated Free-Data Savings Per Day",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "greenRed"
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "25",
+ "name": "AverageDailyFreeDataSavings"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let freeTypes = dynamic([\"AzureActivity\",\"SentinelHealth\",\"OfficeActivity\",\"SecurityAlert\",\"SecurityIncident\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where DataType in (freeTypes) | summarize [\u0027Free Data\u0027] = sum(Quantity) / 1024.0",
+ "size": 1,
+ "title": "Free Data: {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No documented free Sentinel data was observed in the selected time range.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "Free Data",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "blue"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 3
+ }
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "25",
+ "name": "FreeSentinelDataSavings"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let freeTypes = dynamic([\"AzureActivity\",\"SentinelHealth\",\"OfficeActivity\",\"SecurityAlert\",\"SecurityIncident\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where DataType in (freeTypes) | summarize [\u0027Estimated Free-Data Savings\u0027] = sum(Quantity) / 1024.0 * todouble(\u0027{Price}\u0027)",
+ "size": 1,
+ "title": "Free-Data Savings: {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No documented free Sentinel data was observed in the selected time range.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "Estimated Free-Data Savings",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "greenRed"
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "25",
+ "name": "FreeDataSavingsForTimeRange"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let freeTypes = dynamic([\"AzureActivity\",\"SentinelHealth\",\"OfficeActivity\",\"SecurityAlert\",\"SecurityIncident\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where DataType in (freeTypes) | summarize TableSizeGB = sum(Quantity) / 1024.0 by DataType | project [\u0027Log Type\u0027] = DataType, [\u0027Table Size\u0027] = TableSizeGB, [\u0027Estimated Cost Savings\u0027] = TableSizeGB * todouble(\u0027{Price}\u0027) | order by [\u0027Table Size\u0027] desc",
+ "size": 1,
+ "title": "Free data by source table in the last {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No documented free Sentinel data was observed in the selected time range.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "table",
+ "gridSettings": {
+ "showExportToExcel": true,
+ "formatters": [
+ {
+ "columnMatch": "Log Type",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "30%"
+ }
+ },
+ {
+ "columnMatch": "Table Size",
+ "formatter": 3,
+ "formatOptions": {
+ "palette": "greenRed",
+ "customColumnWidthSetting": "45%"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 3
+ }
+ }
+ },
+ {
+ "columnMatch": "Estimated Cost Savings",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "25%"
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency",
+ "maximumFractionDigits": 2
+ }
+ }
+ }
+ ]
+ }
+ },
+ "name": "FreeSentinelDataDetail"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let freeTypes = dynamic([\"AzureActivity\",\"SentinelHealth\",\"OfficeActivity\",\"SecurityAlert\",\"SecurityIncident\"]); let timeGrain = case({TimeRange:end} - {TimeRange:start} \u003c= 2d, 1h, {TimeRange:end} - {TimeRange:start} \u003c= 14d, 1d, {TimeRange:end} - {TimeRange:start} \u003c= 90d, 7d, 30d); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | summarize [\u0027Free Data Size\u0027] = sumif(Quantity, DataType in (freeTypes)) / 1024.0, [\u0027Billable Data Size\u0027] = sumif(Quantity, IsBillable == true) / 1024.0 by bin(TimeGenerated, timeGrain) | order by TimeGenerated asc",
+ "size": 1,
+ "title": "Free Data Size vs Billable Data Size in the last {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No free or billable Sentinel data was observed in the selected time range.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "linechart",
+ "chartSettings": {
+ "xAxis": "TimeGenerated",
+ "showDataPoints": true,
+ "ySettings": {
+ "numberFormatSettings": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 3
+ }
+ }
+ }
+ }
+ },
+ "name": "FreeDataVsBillableDataDaily"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "union withsource=TableName1 * | where TimeGenerated \u003c ago(90d) | extend key = \u0027Key\u0027 | summarize size = sum(_BilledSize)/1024/1024/1024 by key\r\n| project [\u0027Data over 90 days\u0027] = size, [\u0027Retention Cost\u0027] = size*{RetentionPrice}\r\n\r\n\r\n",
+ "size": 1,
+ "title": "Data older than 90 days and resulting retention cost",
+ "noDataMessage": "You have no data older than 90 days",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "gridSettings": {
+ "formatters": [
+ {
+ "columnMatch": "Data over 90 days",
+ "formatter": 0,
+ "numberFormat": {
+ "unit": 36,
+ "options": {
+ "style": "decimal",
+ "useGrouping": false
+ }
+ }
+ },
+ {
+ "columnMatch": "Retention Cost",
+ "formatter": 0,
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "style": "decimal"
+ }
+ }
+ }
+ ]
+ },
+ "tileSettings": {
+ "titleContent": {
+
+ },
+ "leftContent": {
+ "columnMatch": "Data over 90 days",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "greenRed"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 1
+ }
+ }
+ },
+ "rightContent": {
+ "columnMatch": "Retention Cost",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "greenRed"
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ "showBorder": false,
+ "size": "auto"
+ }
+ },
+ "name": "query - 7",
+ "conditionalVisibility": {
+ "parameterName": "TotalE5Seats",
+ "comparison": "isEqualTo",
+ "value": "__never_display_legacy_retention__"
+ }
+ },
+ {
+ "type": 1,
+ "content": {
+ "json": "## Microsoft Sentinel benefit for Microsoft 365 E7/E5/A5/F5/G5 customers\r\n\r\nQualifying Microsoft 365 E7, E5, A5, F5, and G5 licenses, and corresponding Security licenses, may receive a Microsoft Sentinel data grant of up to 5 MB per qualifying user per day for eligible Microsoft 365 data.\r\n\r\nEligible data-source groups include:\r\n\r\n- Microsoft Entra ID sign-in and audit logs (`SigninLogs`, `AuditLogs`, `AADNonInteractiveUserSignInLogs`, `AADServicePrincipalSignInLogs`, `AADManagedIdentitySignInLogs`, `AADProvisioningLogs`, `ADFSSignInLogs`, `AADUserRiskEvents`, `AADRiskyUsers`)\r\n- Microsoft Defender for Cloud Apps Guard shadow IT discovery logs (`McasShadowItReporting`)\r\n- Microsoft Purview Information Protection logs (`InformationProtectionLogs_CL`)\r\n- Microsoft 365 advanced hunting data (the eligible `Device*`, `Email*`, `Identity*`, `AlertEvidence`, and `CloudAppEvents` tables shown below)\r\n\r\nThis workbook estimates the Analytics-tier ingestion benefit from billable Usage data in the selected workspace scope. It does not estimate data lake-only charges or prove that a row came from an eligible connector, that the offer applies to your agreement, or that the calculated amount matches billing. The grant cap is modeled once across the selected scope; it is not multiplied per workspace.\r\n\r\nReview the [Microsoft 365 Sentinel benefit offer](https://azure.microsoft.com/en-us/pricing/offers/sentinel-microsoft-365-offer/) for current eligibility, agreement terms, and supported data types. Enter **Total Microsoft 365 E7/E5/A5/F5/G5 seats** and **Ingestion price** above to calculate the estimate."
+ },
+ "name": "text - 12"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "Usage\r\n| where TimeGenerated between ({TimeRange:start} .. {TimeRange:end})\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\", \r\n\"DeviceFileEvents\", \r\n\"DeviceImageLoadEvents\", \r\n\"DeviceInfo\", \r\n\"DeviceLogonEvents\", \r\n\"DeviceNetworkEvents\", \r\n\"DeviceNetworkInfo\", \r\n\"DeviceProcessEvents\", \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\", \r\n\"EmailAttachmentInfo\", \r\n\"EmailEvents\", \r\n\"EmailPostDeliveryEvents\", \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\"\r\n) \r\n| summarize BillableDataGB = sum(Quantity) / 1000. by DataType\r\n| order by BillableDataGB desc\r\n",
+ "size": 0,
+ "title": "Eligible Microsoft 365 data by table (GB)",
+ "timeContextFromParameter": "TimeRange",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "gridSettings": {
+ "formatters": [
+ {
+ "columnMatch": "BillableDataGB",
+ "formatter": 3,
+ "formatOptions": {
+ "palette": "blue"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 3
+ }
+ }
+ }
+ ]
+ }
+ },
+ "name": "query - 13",
+ "conditionalVisibility": {
+ "parameterName": "TotalE5Seats",
+ "comparison": "isEqualTo",
+ "value": "__never_display_legacy_e5_table__"
+ }
+ },
+ {
+ "type": 1,
+ "content": {
+ "json": "Daily ingestion size vs Maximum data grant"
+ },
+ "name": "text - DailyIngestionVsAllocation",
+ "conditionalVisibility": {
+ "parameterName": "TotalE5Seats",
+ "comparison": "isEqualTo",
+ "value": "__never_display_legacy_e5_chart__"
+ }
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "Usage\r\n| where TimeGenerated between ({TimeRange:start} .. {TimeRange:end})\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\", \r\n\"DeviceFileEvents\", \r\n\"DeviceImageLoadEvents\", \r\n\"DeviceInfo\", \r\n\"DeviceLogonEvents\", \r\n\"DeviceNetworkEvents\", \r\n\"DeviceNetworkInfo\", \r\n\"DeviceProcessEvents\", \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\", \r\n\"EmailAttachmentInfo\", \r\n\"EmailEvents\", \r\n\"EmailPostDeliveryEvents\", \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\") \r\n| summarize [\u0027Daily Ingestion\u0027] = toreal(sum(Quantity))/ 1024 by format_datetime(TimeGenerated, \u0027yyyy-MM-dd\u0027) \r\n| extend MaxDataGrantGB = ((5*todouble(\u0027{TotalE5Seats}\u0027))/1024)\r\n| sort by TimeGenerated asc\r\n",
+ "size": 0,
+ "aggregation": 3,
+ "timeContextFromParameter": "TimeRange",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "linechart",
+ "chartSettings": {
+ "xAxis": "TimeGenerated",
+ "showDataPoints": true,
+ "ySettings": {
+ "numberFormatSettings": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "useGrouping": true,
+ "maximumFractionDigits": 3
+ }
+ }
+ }
+ }
+ },
+ "name": "DailyIngestionVSAllocation",
+ "conditionalVisibility": {
+ "parameterName": "TotalE5Seats",
+ "comparison": "isEqualTo",
+ "value": "__never_display_legacy_e5_chart__"
+ }
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "Usage\r\n| where TimeGenerated between ({TimeRange:start} .. {TimeRange:end})\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\", \r\n\"DeviceFileEvents\", \r\n\"DeviceImageLoadEvents\", \r\n\"DeviceInfo\", \r\n\"DeviceLogonEvents\", \r\n\"DeviceNetworkEvents\", \r\n\"DeviceNetworkInfo\", \r\n\"DeviceProcessEvents\", \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\", \r\n\"EmailAttachmentInfo\", \r\n\"EmailEvents\", \r\n\"EmailPostDeliveryEvents\", \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\"\r\n) \r\n| summarize TotalBillableDataGB = sum(Quantity) / 1024\r\n\r\n",
+ "size": 1,
+ "title": "Eligible M365 Data",
+ "timeContextFromParameter": "TimeRange",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "TotalBillableDataGB",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "greenRed"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "20",
+ "name": "E5IngestionSize"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let DailyMaxDiscountGB = ((5*todouble(\u0027{TotalE5Seats}\u0027))/1024);\r\nUsage\r\n| where TimeGenerated between ({TimeRange:start} .. {TimeRange:end})\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\", \r\n\"DeviceFileEvents\", \r\n\"DeviceImageLoadEvents\", \r\n\"DeviceInfo\", \r\n\"DeviceLogonEvents\", \r\n\"DeviceNetworkEvents\", \r\n\"DeviceNetworkInfo\", \r\n\"DeviceProcessEvents\", \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\", \r\n\"EmailAttachmentInfo\", \r\n\"EmailEvents\", \r\n\"EmailPostDeliveryEvents\", \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\") \r\n| summarize DailyBillableGB = toreal(sum(Quantity))/ 1024 by format_datetime(TimeGenerated, \u0027yy-MM-dd\u0027) \r\n| extend DailyMaxGrantGB = DailyMaxDiscountGB\r\n| summarize MaxDataGrantGB = sum(toreal(DailyMaxGrantGB))\r\n\r\n",
+ "size": 1,
+ "title": "Total Data Grant Limit: {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "MaxDataGrantGB",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "orangeBlue"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ "showBorder": false,
+ "sortOrderField": 1
+ }
+ },
+ "customWidth": "20",
+ "name": "DataGrantLimit"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let DailyMaxDiscountGB = ((5*todouble(\u0027{TotalE5Seats}\u0027))/1024);\r\nUsage\r\n| where TimeGenerated between ({TimeRange:start} .. {TimeRange:end})\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\", \r\n\"DeviceFileEvents\", \r\n\"DeviceImageLoadEvents\", \r\n\"DeviceInfo\", \r\n\"DeviceLogonEvents\", \r\n\"DeviceNetworkEvents\", \r\n\"DeviceNetworkInfo\", \r\n\"DeviceProcessEvents\", \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\", \r\n\"EmailAttachmentInfo\", \r\n\"EmailEvents\", \r\n\"EmailPostDeliveryEvents\", \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\") \r\n| summarize DailyBillableGB = toreal(sum(Quantity))/ 1024 by format_datetime(TimeGenerated, \u0027yy-MM-dd\u0027) \r\n| summarize TotalEligibleGB = sum(iif(toreal(DailyBillableGB)\u003etoreal(DailyMaxDiscountGB),toreal(DailyMaxDiscountGB),DailyBillableGB))\r\n\r\n",
+ "size": 1,
+ "title": "Total Data Grant Used: {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "TotalEligibleGB",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "coldHot"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ "showBorder": false,
+ "sortOrderField": 1
+ }
+ },
+ "customWidth": "30",
+ "name": "EligibleE5Ingestion"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let DailyMaxDiscountGB = ((5*todouble(\u0027{TotalE5Seats}\u0027))/1024);\r\nUsage\r\n| where TimeGenerated between ({TimeRange:start} .. {TimeRange:end})\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\", \r\n\"DeviceFileEvents\", \r\n\"DeviceImageLoadEvents\", \r\n\"DeviceInfo\", \r\n\"DeviceLogonEvents\", \r\n\"DeviceNetworkEvents\", \r\n\"DeviceNetworkInfo\", \r\n\"DeviceProcessEvents\", \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\", \r\n\"EmailAttachmentInfo\", \r\n\"EmailEvents\", \r\n\"EmailPostDeliveryEvents\", \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\") \r\n| summarize DailyBillableGB = toreal(sum(Quantity))/ 1024 by format_datetime(TimeGenerated, \u0027yy-MM-dd\u0027) \r\n| summarize TotalEligibleGB = sum(iif(toreal(DailyBillableGB)\u003etoreal(DailyMaxDiscountGB),toreal(DailyMaxDiscountGB),DailyBillableGB))\r\n| extend TotalDiscount = toreal(TotalEligibleGB)*{Price}\r\n| project TotalDiscount\r\n\r\n",
+ "size": 1,
+ "title": "Estimated Cost Savings: {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "TotalDiscount",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "greenRed"
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "20",
+ "name": "EstimateE5Discount"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let eligibleTables = dynamic([\"SigninLogs\",\"AuditLogs\",\"AADNonInteractiveUserSignInLogs\",\"AADServicePrincipalSignInLogs\",\"AADManagedIdentitySignInLogs\",\"AADProvisioningLogs\",\"ADFSSignInLogs\",\"AADUserRiskEvents\",\"AADRiskyUsers\",\"McasShadowItReporting\",\"InformationProtectionLogs_CL\",\"DeviceEvents\",\"DeviceFileEvents\",\"DeviceImageLoadEvents\",\"DeviceInfo\",\"DeviceLogonEvents\",\"DeviceNetworkEvents\",\"DeviceNetworkInfo\",\"DeviceProcessEvents\",\"DeviceRegistryEvents\",\"DeviceFileCertificateInfo\",\"EmailAttachmentInfo\",\"EmailEvents\",\"EmailPostDeliveryEvents\",\"EmailUrlInfo\",\"IdentityLogonEvents\",\"IdentityQueryEvents\",\"IdentityDirectoryEvents\",\"AlertEvidence\",\"CloudAppEvents\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize TableSizeGB = sum(Quantity) / 1024.0 by DataType | project [\u0027Log Type\u0027] = DataType, [\u0027Table Size\u0027] = TableSizeGB | order by [\u0027Table Size\u0027] desc",
+ "size": 1,
+ "title": "Eligible Microsoft 365 data by source table in the last {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No eligible Microsoft 365 data was found in the selected time range.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "table",
+ "gridSettings": {
+ "showExportToExcel": true,
+ "formatters": [
+ {
+ "columnMatch": "Log Type",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "40%"
+ }
+ },
+ {
+ "columnMatch": "Table Size",
+ "formatter": 3,
+ "formatOptions": {
+ "palette": "greenRed",
+ "customColumnWidthSetting": "60%"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 3
+ }
+ }
+ }
+ ]
+ }
+ },
+ "name": "E5EligibleDataDetail"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let eligibleTables = dynamic([\"SigninLogs\",\"AuditLogs\",\"AADNonInteractiveUserSignInLogs\",\"AADServicePrincipalSignInLogs\",\"AADManagedIdentitySignInLogs\",\"AADProvisioningLogs\",\"ADFSSignInLogs\",\"AADUserRiskEvents\",\"AADRiskyUsers\",\"McasShadowItReporting\",\"InformationProtectionLogs_CL\",\"DeviceEvents\",\"DeviceFileEvents\",\"DeviceImageLoadEvents\",\"DeviceInfo\",\"DeviceLogonEvents\",\"DeviceNetworkEvents\",\"DeviceNetworkInfo\",\"DeviceProcessEvents\",\"DeviceRegistryEvents\",\"DeviceFileCertificateInfo\",\"EmailAttachmentInfo\",\"EmailEvents\",\"EmailPostDeliveryEvents\",\"EmailUrlInfo\",\"IdentityLogonEvents\",\"IdentityQueryEvents\",\"IdentityDirectoryEvents\",\"AlertEvidence\",\"CloudAppEvents\"]); let licenseCount = todouble(\u0027{TotalE5Seats}\u0027); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize [\u0027Daily Ingestion Size\u0027] = sum(Quantity) / 1024.0 by bin(TimeGenerated, 1d) | extend [\u0027Maximum Data Grant\u0027] = iif(isnull(licenseCount), real(null), licenseCount * 5.0 / 1024.0) | order by TimeGenerated asc",
+ "size": 1,
+ "title": "Daily Ingestion Size vs Maximum Data Grant",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No eligible Microsoft 365 data was found in the selected time range.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "linechart",
+ "chartSettings": {
+ "xAxis": "TimeGenerated",
+ "showDataPoints": true,
+ "ySettings": {
+ "numberFormatSettings": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 3
+ }
+ }
+ }
+ }
+ },
+ "name": "E5DailyIngestionVsGrant"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let licenseCount = todouble(\u0027{TotalDfSP2Licenses}\u0027); let periodDays = max_of(datetime_diff(\u0027second\u0027, {TimeRange:end}, {TimeRange:start}) / 86400.0, 1); print TotalGrantGB = iif(isnull(licenseCount), \u0027N/A\u0027, tostring(licenseCount * 500.0 / 1024.0 * periodDays))",
+ "size": 1,
+ "title": "Period grant",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate the selected-period grant.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "TotalGrantGB",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "orangeBlue"
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "30",
+ "name": "DfSP2TotalGrant",
+ "conditionalVisibility": {
+ "parameterName": "TotalDfSP2Licenses",
+ "comparison": "isEqualTo",
+ "value": "__never_display_legacy_dfsp2__"
+ }
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let licenseCount = todouble(\u0027{TotalDfSP2Licenses}\u0027); let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); let periodDays = max_of(datetime_diff(\u0027second\u0027, {TimeRange:end}, {TimeRange:start}) / 86400.0, 1); let eligibleGBPerDay = toreal(coalesce(toscalar(Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize sum(Quantity) / 1024.0 / periodDays), 0.0)); print EstimatedSavings = iif(isnull(licenseCount), \u0027N/A\u0027, tostring(min_of(eligibleGBPerDay, licenseCount * 500.0 / 1024.0) * periodDays * toreal({Price})))",
+ "size": 1,
+ "title": "Estimated Cost Savings: {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate estimated savings.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "EstimatedSavings",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "greenRed"
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "20",
+ "name": "DfSP2EstimatedSavings",
+ "conditionalVisibility": {
+ "parameterName": "TotalDfSP2Licenses",
+ "comparison": "isEqualTo",
+ "value": "__never_display_legacy_dfsp2__"
+ }
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let coreEligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\"]); let conditionalEligibleTables = dynamic([\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); let eligibleTables = array_concat(coreEligibleTables, conditionalEligibleTables); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize EligibleGBPerDay = sum(Quantity) / 1024.0 / max_of(datetime_diff(\u0027second\u0027, {TimeRange:end}, {TimeRange:start}) / 86400.0, 1) by DataType | extend Eligibility = iif(DataType in (coreEligibleTables), \"Core\", \"Conditional\") | project Table = DataType, Eligibility, EligibleGBPerDay | order by EligibleGBPerDay desc",
+ "size": 0,
+ "title": "DfSP2 eligible ingestion detail",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No eligible DfSP2 tables were found in the selected time range.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "table"
+ },
+ "name": "query - DfSP2 table detail current",
+ "conditionalVisibility": {
+ "parameterName": "TotalDfSP2Licenses",
+ "comparison": "isEqualTo",
+ "value": "__never_display_legacy_dfsp2__"
+ }
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); let licenseCount = todouble(\u0027{TotalDfSP2Licenses}\u0027); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize EligibleGBPerDay = sum(Quantity) / 1024.0 by bin(TimeGenerated, 1d) | extend DailyAllowanceGB = iif(isnull(licenseCount), real(null), licenseCount * 500.0 / 1024.0) | project TimeGenerated, EligibleGBPerDay, DailyAllowanceGB | order by TimeGenerated asc",
+ "size": 0,
+ "title": "Pooled DfSP2 data versus daily grant",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No eligible DfSP2 data was found in the selected time range.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "linechart"
+ },
+ "name": "query - DfSP2 pooled trend current",
+ "conditionalVisibility": {
+ "parameterName": "TotalDfSP2Licenses",
+ "comparison": "isEqualTo",
+ "value": "__never_display_legacy_dfsp2__"
+ }
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize EligibleGB = sum(Quantity) / 1024.0",
+ "size": 1,
+ "title": "Eligible DfSP2 Data",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No eligible DfSP2 data was found in the selected time range.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "EligibleGB",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "blue"
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "20",
+ "name": "DfSP2IngestionSize",
+ "conditionalVisibility": {
+ "parameterName": "TotalDfSP2Licenses",
+ "comparison": "isEqualTo",
+ "value": "__never_display_legacy_dfsp2__"
+ }
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "Heartbeat | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | summarize NodesIdentified = dcount(Computer)",
+ "size": 1,
+ "title": "Nodes",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No Heartbeat nodes were identified in the selected time range.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "NodesIdentified",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "blue"
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "10",
+ "name": "DfSP2NodesIdentified",
+ "conditionalVisibility": {
+ "parameterName": "TotalDfSP2Licenses",
+ "comparison": "isEqualTo",
+ "value": "__never_display_legacy_dfsp2__"
+ }
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let licenseCount = todouble(\u0027{TotalDfSP2Licenses}\u0027); print DailyGrantGB = iif(isnull(licenseCount), \u0027N/A\u0027, tostring(licenseCount * 500.0 / 1024.0))",
+ "size": 1,
+ "title": "Daily grant",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate the daily grant.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "DailyGrantGB",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "orangeBlue"
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "20",
+ "name": "DfSP2DailyGrantLimit",
+ "conditionalVisibility": {
+ "parameterName": "TotalDfSP2Licenses",
+ "comparison": "isEqualTo",
+ "value": "__never_display_legacy_dfsp2__"
+ }
+ },
+ {
+ "type": 1,
+ "content": {
+ "json": "## Microsoft Sentinel benefit for Defender for Servers Plan 2\r\n\r\nDefender for Servers Plan 2 provides up to 500 MB of eligible Analytics-tier ingestion per protected server or node per day. The allowance is pooled across machines in each subscription and applied at workspace level. This workbook estimates observed usage; it does not prove Plan 2 protection, licensing, eligibility, or data lake-only charges.\r\n\r\nCore eligible tables:\r\n\r\n- `SecurityAlert`, `SecurityBaseline`, `SecurityBaselineSummary`, `SecurityDetection`, `SecurityEvent`\r\n- `WindowsFirewall`, `ProtectionStatus`, `MDCFileIntegrityMonitoringEvents`\r\n- `DeviceCustomFileEvents`, `DeviceCustomRegistryEvents`\r\n\r\nConditionally eligible tables:\r\n\r\n- `Update`, `UpdateSummary`: review the applicable Update Management conditions\r\n- `WindowsEvent`: only security data from the Microsoft-SecurityEvent stream\r\n\r\nNodes is the distinct `Computer` count observed in `Heartbeat`, not proof of licensing or Plan 2 protection. Review the [Defender for Servers Plan 2 data ingestion benefit](https://learn.microsoft.com/en-us/azure/defender-for-cloud/data-ingestion-benefit) for current eligibility and terms."
+ },
+ "name": "text - DfSP2 benefit"
+ },
+ {
+ "type": 1,
+ "content": {
+ "json": "Enter the number of protected Defender for Servers Plan 2 servers or nodes above to calculate the daily and total data grants, grant usage, and estimated cost savings."
+ },
+ "name": "text - DfSP2 entitlement required",
+ "conditionalVisibility": {
+ "parameterName": "TotalDfSP2Licenses",
+ "comparison": "isEqualTo",
+ "value": "\u003cunset\u003e"
+ }
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize EligibleGB = sum(Quantity) / 1024.0",
+ "size": 1,
+ "title": "Eligible Defender for Servers Plan 2 data",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No eligible DfSP2 data was found in the selected time range.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "EligibleGB",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "blue"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 3
+ }
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "20",
+ "name": "DfSP2IngestionSize current"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "Heartbeat | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | summarize NodesIdentified = dcount(Computer)",
+ "size": 1,
+ "title": "Nodes",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No Heartbeat nodes were identified in the selected time range.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "NodesIdentified",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "blue"
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "10",
+ "name": "DfSP2NodesIdentified current"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let licenseCount = todouble(\u0027{TotalDfSP2Licenses}\u0027); print DailyGrantGB = iif(isnull(licenseCount), \u0027N/A\u0027, strcat(tostring(round(licenseCount * 500.0 / 1024.0, 3)), \u0027 GB\u0027))",
+ "size": 1,
+ "title": "Daily Grant Limit",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate the daily grant.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "DailyGrantGB",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "orangeBlue"
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "15",
+ "name": "DfSP2DailyGrant"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let licenseCount = todouble(\u0027{TotalDfSP2Licenses}\u0027); let periodDays = max_of(datetime_diff(\u0027second\u0027, {TimeRange:end}, {TimeRange:start}) / 86400.0, 1); print PeriodGrantGB = iif(isnull(licenseCount), \u0027N/A\u0027, strcat(tostring(round(licenseCount * 500.0 / 1024.0 * periodDays, 3)), \u0027 GB\u0027))",
+ "size": 1,
+ "title": "Total Grant Limit: {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate the selected-period grant.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "PeriodGrantGB",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "orangeBlue"
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "20",
+ "name": "DfSP2PeriodGrant"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); let licenseCount = todouble(\u0027{TotalDfSP2Licenses}\u0027); let periodDays = max_of(datetime_diff(\u0027second\u0027, {TimeRange:end}, {TimeRange:start}) / 86400.0, 1); let eligibleGB = toreal(coalesce(toscalar(Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize sum(Quantity) / 1024.0), 0.0)); let periodGrantGB = licenseCount * 500.0 / 1024.0 * periodDays; print GrantUsedGB = iif(isnull(licenseCount), \u0027N/A\u0027, strcat(tostring(round(min_of(eligibleGB, periodGrantGB), 3)), \u0027 GB\u0027))",
+ "size": 1,
+ "title": "Total Grant Used: {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate grant use.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "GrantUsedGB",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "coldHot"
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "20",
+ "name": "DfSP2GrantUsed"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); let licenseCount = todouble(\u0027{TotalDfSP2Licenses}\u0027); let periodDays = max_of(datetime_diff(\u0027second\u0027, {TimeRange:end}, {TimeRange:start}) / 86400.0, 1); let eligibleGB = toreal(coalesce(toscalar(Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize sum(Quantity) / 1024.0), 0.0)); let periodGrantGB = licenseCount * 500.0 / 1024.0 * periodDays; print EstimatedSavings = iif(isnull(licenseCount), \u0027N/A\u0027, strcat(\u0027$\u0027, tostring(round(min_of(eligibleGB, periodGrantGB) * todouble(\u0027{Price}\u0027), 2))))",
+ "size": 1,
+ "title": "Estimated Savings: {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate estimated savings.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "EstimatedSavings",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "greenRed"
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "15",
+ "name": "DfSP2EstimatedSavings"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize TableSizeGB = sum(Quantity) / 1024.0 by DataType | project [\u0027Log Type\u0027] = DataType, [\u0027Table Size\u0027] = TableSizeGB | order by [\u0027Table Size\u0027] desc",
+ "size": 1,
+ "title": "Eligible Defender for Servers Plan 2 data by source table in the last {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No eligible DfSP2 data was found in the selected time range.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "table",
+ "gridSettings": {
+ "showExportToExcel": true,
+ "formatters": [
+ {
+ "columnMatch": "Log Type",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "40%"
+ }
+ },
+ {
+ "columnMatch": "Table Size",
+ "formatter": 3,
+ "formatOptions": {
+ "palette": "greenRed",
+ "customColumnWidthSetting": "60%"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 3
+ }
+ }
+ }
+ ]
+ }
+ },
+ "name": "DfSP2CapacityDetailCurrent"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); let licenseCount = todouble(\u0027{TotalDfSP2Licenses}\u0027); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize [\u0027Daily Ingestion Size\u0027] = sum(Quantity) / 1024.0 by bin(TimeGenerated, 1d) | extend [\u0027Total Data Grant\u0027] = iif(isnull(licenseCount), real(null), licenseCount * 500.0 / 1024.0) | order by TimeGenerated asc",
+ "size": 1,
+ "title": "Daily Ingestion Size vs Total Data Grant",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No eligible DfSP2 data was found in the selected time range.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "linechart",
+ "chartSettings": {
+ "xAxis": "TimeGenerated",
+ "showDataPoints": true,
+ "ySettings": {
+ "numberFormatSettings": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 3
+ }
+ }
+ }
+ }
+ },
+ "name": "DfSP2DailyIngestionVsGrant"
+ },
+ {
+ "type": 1,
+ "content": {
+ "json": "## Retention summary\r\n\r\nThis section estimates Analytics-tier charges for billable data retained longer than 90 days, using historical billable workspace records. XDR and data lake retention use separate billing models. Review [Manage data tiers and retention in Microsoft Sentinel](https://learn.microsoft.com/en-us/azure/sentinel/manage-data-overview) for retention and data-tier guidance."
+ },
+ "name": "text - retention summary"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let retainedDataGB = toreal(coalesce(toscalar((union withsource = SourceTableName * | where TimeGenerated \u003c startofday(now()) - 90d | where _IsBillable == true | summarize sum(_BilledSize) / 1024.0 / 1024.0 / 1024.0)), 0.0)); print [\u0027Average Daily Retention Cost\u0027] = retainedDataGB * todouble(\u0027{RetentionPrice}\u0027) / 30.0",
+ "size": 1,
+ "title": "Average Daily Retention Cost",
+ "noDataMessage": "No retained billable data was found in the selected workspace scope.",
+ "noDataMessageStyle": 3,
+ "timeContextFromParameter": "TimeRange",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "Average Daily Retention Cost",
+ "formatter": 12,
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "25",
+ "name": "AverageDailyRetentionCost"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let selectedDays = max_of(datetime_diff(\u0027second\u0027, {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); let retainedDataGB = toreal(coalesce(toscalar((union withsource = SourceTableName * | where TimeGenerated \u003c startofday(now()) - 90d | where _IsBillable == true | summarize sum(_BilledSize) / 1024.0 / 1024.0 / 1024.0)), 0.0)); print [\u0027Retention Cost\u0027] = retainedDataGB * todouble(\u0027{RetentionPrice}\u0027) * selectedDays / 30.0",
+ "size": 1,
+ "title": "Retention Cost: {TimeRange}",
+ "noDataMessage": "No retained billable data was found in the selected workspace scope.",
+ "noDataMessageStyle": 3,
+ "timeContextFromParameter": "TimeRange",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "Retention Cost",
+ "formatter": 12,
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "25",
+ "name": "RetentionCostForTimeRange"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let selectedDays = max_of(datetime_diff(\u0027second\u0027, {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); union withsource = SourceTableName * | where TimeGenerated \u003c startofday(now()) - 90d | where _IsBillable == true | summarize RetainedDataGB = sum(_BilledSize) / 1024.0 / 1024.0 / 1024.0 by SourceTableName | project [\u0027Log Type\u0027] = SourceTableName, [\u0027Retained Data\u0027] = RetainedDataGB, [\u0027Average Daily Retention Cost\u0027] = RetainedDataGB * todouble(\u0027{RetentionPrice}\u0027) / 30.0, [\u0027Retention Cost\u0027] = RetainedDataGB * todouble(\u0027{RetentionPrice}\u0027) * selectedDays / 30.0 | order by [\u0027Retained Data\u0027] desc",
+ "size": 1,
+ "title": "Retained data by source table in the last {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No billable data older than 90 days was found in the selected workspace scope.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "table",
+ "gridSettings": {
+ "showExportToExcel": true,
+ "formatters": [
+ {
+ "columnMatch": "Log Type",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "30%"
+ }
+ },
+ {
+ "columnMatch": "Retained Data",
+ "formatter": 3,
+ "formatOptions": {
+ "palette": "greenRed",
+ "customColumnWidthSetting": "25%"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 3
+ }
+ }
+ },
+ {
+ "columnMatch": "Average Daily Retention Cost",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "20%"
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ {
+ "columnMatch": "Retention Cost",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "25%"
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency",
+ "maximumFractionDigits": 2
+ }
+ }
+ }
+ ]
+ }
+ },
+ "name": "RetentionDataDetail"
+ },
+ {
+ "type": 1,
+ "content": {
+ "json": "## Microsoft Sentinel Data Lake\r\n\r\nThe data lake provides long-term, cost-effective storage outside the Analytics tier. Its costs are billed separately for data lake ingestion, processing, storage, query, and advanced data insights. Microsoft Defender XDR data also has separate 30-day default and extended-retention pricing.\r\n\r\nData lake charges are not available from the Log Analytics `Usage` table, so this workbook cannot calculate billing-accurate data lake costs. Review current usage and costs in **Microsoft Sentinel \u003e Cost management** in the Microsoft Defender portal. Learn more in the [Microsoft Sentinel data lake overview](https://learn.microsoft.com/en-us/azure/sentinel/datalake/sentinel-lake-overview) and [Manage and monitor costs for Microsoft Sentinel](https://learn.microsoft.com/en-us/azure/sentinel/billing-monitor-costs)."
+ },
+ "name": "text - Microsoft Sentinel Data Lake"
+ },
+ {
+ "type": 1,
+ "content": {
+ "json": "## SOAR summary\r\n\r\nMicrosoft Sentinel playbooks use Azure Logic Apps to automate responses to incidents, alerts, and other security operations workflows. This section summarizes billable Logic App executions across accessible playbooks and estimates their execution cost using the **Logic App execution cost** input at the top of the workbook.\r\n\r\nTo populate this estimate, export the `TotalBillableExecutions` metric to the selected Log Analytics workspace and use the Analytics plan for the `AzureMetrics` table. Basic Logs tables cannot run this query. The estimate is not an invoice; use Azure Cost Management to validate billed charges.\r\n\r\nReview [Automate threat response with playbooks in Microsoft Sentinel](https://learn.microsoft.com/en-us/azure/sentinel/automation/automate-responses-with-playbooks) for playbook guidance. Because playbooks use Azure Logic Apps, additional charges can apply. Go to the [Azure Logic Apps](https://azure.microsoft.com/pricing/details/logic-apps/) pricing page for more details."
+ },
+ "name": "text - 3"
+ },
+ {
+ "type": 9,
+ "content": {
+ "version": "KqlParameterItem/1.0",
+ "parameters": [
+ {
+ "id": "6f50ee54-8f0e-424e-9e16-70eca531af7f",
+ "version": "KqlParameterItem/1.0",
+ "name": "ResourceTypes",
+ "label": "Resource types",
+ "type": 7,
+ "isRequired": true,
+ "multiSelect": true,
+ "quote": "\u0027",
+ "delimiter": ",",
+ "value": [
+ "microsoft.logic/workflows"
+ ],
+ "isHiddenWhenLocked": true,
+ "typeSettings": {
+ "additionalResourceOptions": [
+
+ ],
+ "includeAll": true
+ },
+ "timeContext": {
+ "durationMs": 86400000
+ }
+ },
+ {
+ "id": "1c8dc8da-2233-426c-8cfc-52ec31bf1e84",
+ "version": "KqlParameterItem/1.0",
+ "name": "Subscription",
+ "label": "Subscriptions",
+ "type": 6,
+ "isRequired": true,
+ "multiSelect": true,
+ "quote": "\u0027",
+ "delimiter": ",",
+ "query": "Resources\r\n| where type in~ ({ResourceTypes})\r\n| summarize Count = count() by subscriptionId\r\n| order by Count desc\r\n| extend Rank = row_number()\r\n| project value = subscriptionId, label = subscriptionId, selected = Rank == 1",
+ "typeSettings": {
+ "additionalResourceOptions": [
+ "value::all"
+ ],
+ "showDefault": false
+ },
+ "timeContext": {
+ "durationMs": 86400000
+ },
+ "defaultValue": "value::all",
+ "queryType": 1,
+ "resourceType": "microsoft.resourcegraph/resources",
+ "value": [
+ "value::all"
+ ]
+ },
+ {
+ "id": "f103ef04-042e-45ed-8f78-b31e676258d7",
+ "version": "KqlParameterItem/1.0",
+ "name": "ResourceGroups",
+ "label": "Resource groups",
+ "type": 2,
+ "isRequired": true,
+ "multiSelect": true,
+ "quote": "\u0027",
+ "delimiter": ",",
+ "query": "Resources\r\n| where type in~ ({ResourceTypes})\r\n| summarize Count = count() by subscriptionId, resourceGroup\r\n| order by Count desc\r\n| extend Rank = row_number()\r\n| project value = strcat(\u0027/subscriptions/\u0027, subscriptionId, \u0027/resourceGroups/\u0027, resourceGroup), label = resourceGroup, selected = false",
+ "typeSettings": {
+ "additionalResourceOptions": [
+ "value::all"
+ ],
+ "showDefault": false
+ },
+ "timeContext": {
+ "durationMs": 86400000
+ },
+ "defaultValue": "value::all",
+ "queryType": 1,
+ "resourceType": "microsoft.resourcegraph/resources",
+ "value": [
+ "value::all"
+ ]
+ },
+ {
+ "id": "b6514d02-8893-44b8-896e-e53ada5024d5",
+ "version": "KqlParameterItem/1.0",
+ "name": "Resources",
+ "label": "Logic Apps",
+ "type": 5,
+ "isRequired": true,
+ "multiSelect": true,
+ "quote": "\u0027",
+ "delimiter": ",",
+ "query": "Resources\r\n| where type in~({ResourceTypes})\r\n| extend resourceGroupId = strcat(\u0027/subscriptions/\u0027, subscriptionId, \u0027/resourceGroups/\u0027, resourceGroup)\r\n| where resourceGroupId in~({ResourceGroups}) or \u0027*\u0027 in~({ResourceGroups})\r\n| order by name asc\r\n| extend Rank = row_number()\r\n| project value = id, label = tostring(name), selected = Rank \u003c= 10, group = resourceGroup",
+ "value": [
+ "value::all"
+ ],
+ "typeSettings": {
+ "additionalResourceOptions": [
+ "value::all"
+ ],
+ "showDefault": false
+ },
+ "timeContext": {
+ "durationMs": 86400000
+ },
+ "queryType": 1,
+ "resourceType": "microsoft.resourcegraph/resources"
+ }
+ ],
+ "style": "pills",
+ "queryType": 1,
+ "resourceType": "microsoft.resourcegraph/resources"
+ },
+ "name": "parameters - 10",
+ "conditionalVisibility": {
+ "parameterName": "Total",
+ "comparison": "isEqualTo",
+ "value": "__never_display_soar_parameters__"
+ }
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "AzureMetrics | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where MetricName == \u0027TotalBillableExecutions\u0027 | where ResourceId in~ ({Resources}) or \u0027value::all\u0027 in~ ({Resources}) | summarize TotalBillableExecutions = sum(Total) | project [\u0027Total billable executions\u0027] = TotalBillableExecutions, [\u0027Estimated automation cost\u0027] = TotalBillableExecutions * todouble(\u0027{ExecutionCost}\u0027)",
+ "size": 1,
+ "title": "Logic App automation summary",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No exported TotalBillableExecutions metrics were found. Configure Logic App metric export to this workspace to calculate the total without selecting a row.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "leftContent": {
+ "columnMatch": "Total billable executions",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "blue"
+ }
+ },
+ "rightContent": {
+ "columnMatch": "Estimated automation cost",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "greenRed"
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency",
+ "minimumFractionDigits": 2,
+ "maximumFractionDigits": 3
+ }
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "name": "SOARSummaryFromAzureMetrics"
+ },
+ {
+ "type": 10,
+ "content": {
+ "chartId": "workbooke70b7cbc-f1d7-4a74-b8b9-75cc8d5ab586",
+ "version": "MetricsItem/2.0",
+ "size": 1,
+ "chartType": 0,
+ "resourceType": "microsoft.logic/workflows",
+ "metricScope": 0,
+ "resourceParameter": "Resources",
+ "resourceIds": [
+ "{Resources}"
+ ],
+ "timeContextFromParameter": "TimeRange",
+ "timeContext": {
+ "durationMs": 604800000
+ },
+ "metrics": [
+ {
+ "namespace": "microsoft.logic/workflows",
+ "metric": "microsoft.logic/workflows--TotalBillableExecutions",
+ "aggregation": 1
+ }
+ ],
+ "title": "Logic App execution detail",
+ "resourceLimit": 10000,
+ "gridSettings": {
+ "formatters": [
+ {
+ "columnMatch": "$gen_group",
+ "formatter": 15,
+ "formatOptions": {
+ "linkTarget": null,
+ "showIcon": true
+ }
+ },
+ {
+ "columnMatch": "Subscription",
+ "formatter": 5
+ },
+ {
+ "columnMatch": "Name",
+ "formatter": 13,
+ "formatOptions": {
+ "linkTarget": "Resource",
+ "showIcon": true
+ }
+ },
+ {
+ "columnMatch": "microsoft.logic/workflows--TotalBillableExecutions",
+ "formatter": 8,
+ "formatOptions": {
+ "palette": "blue",
+ "aggregation": "Sum"
+ }
+ },
+ {
+ "columnMatch": "microsoft.logic/workflows--TotalBillableExecutions Timeline",
+ "formatter": 21,
+ "formatOptions": {
+ "palette": "blue"
+ }
+ },
+ {
+ "columnMatch": "microsoft.logic/workflows--BillableTriggerExecutions Timeline",
+ "formatter": 5
+ },
+ {
+ "columnMatch": "microsoft.logic/workflows--BillableActionExecutions",
+ "formatter": 8,
+ "formatOptions": {
+ "palette": "blue"
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "style": "decimal"
+ }
+ }
+ },
+ {
+ "columnMatch": "microsoft.logic/workflows--BillableActionExecutions Timeline",
+ "formatter": 5
+ },
+ {
+ "columnMatch": "RG",
+ "formatter": 13,
+ "formatOptions": {
+ "linkTarget": null,
+ "showIcon": true
+ }
+ },
+ {
+ "columnMatch": "Sum",
+ "formatter": 1,
+ "formatOptions": {
+ "aggregation": "Sum"
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "style": "decimal"
+ }
+ }
+ }
+ ],
+ "rowLimit": 10000,
+ "filter": true,
+ "hierarchySettings": {
+ "treeType": 1,
+ "groupBy": [
+ "Subscription"
+ ]
+ },
+ "labelSettings": [
+ {
+ "columnId": "microsoft.logic/workflows--TotalBillableExecutions",
+ "label": "Total Billable Executions (Sum)"
+ },
+ {
+ "columnId": "microsoft.logic/workflows--TotalBillableExecutions Timeline",
+ "label": "Total Billable Executions Timeline"
+ }
+ ]
+ },
+ "sortBy": [
+
+ ],
+ "exportFieldName": "microsoft.logic/workflows--TotalBillableExecutions",
+ "exportParameterName": "Total",
+ "exportDefaultValue": "0"
+ },
+ "name": "Billable Metric"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "print [\u0027Estimated automation costs\u0027] = todouble(\u0027{Total}\u0027) * todouble(\u0027{ExecutionCost}\u0027)",
+ "size": 1,
+ "title": "Estimated Logic App cost",
+ "timeContext": {
+ "durationMs": 86400000
+ },
+ "noDataMessage": "Select a subscription or Logic App row above to calculate the estimated cost.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "Estimated automation costs",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "greenRed"
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency",
+ "minimumFractionDigits": 2,
+ "maximumFractionDigits": 3
+ }
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "conditionalVisibility": {
+ "parameterName": "Total",
+ "comparison": "isEqualTo",
+ "value": "__never_display_legacy_soar_cost__"
+ },
+ "name": "query - 11"
+ }
],
- "allowCustom": true
- },
- "timeContext": {
- "durationMs": 86400000
- }
- },
- {
- "id": "67c2ce6e-ea54-4ae4-8343-3fcad8e53d1b",
- "version": "KqlParameterItem/1.0",
- "name": "Workspace",
- "type": 5,
- "isRequired": true,
- "multiSelect": true,
- "quote": "'",
- "delimiter": ",",
- "query": "resources | where type =~ 'Microsoft.operationsmanagement/solutions' | where name contains 'SecurityInsights' | project id = tostring(properties.workspaceResourceId)",
- "crossComponentResources": [
- "value::all"
- ],
- "value": [
- "value::all"
- ],
- "typeSettings": {
- "limitSelectTo": 100,
- "additionalResourceOptions": [
- "value::all"
- ],
- "showDefault": false
- },
- "timeContext": {
- "durationMs": 86400000
- },
- "queryType": 1,
- "resourceType": "microsoft.resourcegraph/resources"
- },
- {
- "id": "9375c625-e916-4f48-b072-352d6aeefddb",
- "version": "KqlParameterItem/1.0",
- "name": "Price",
- "label": "Ingestion price",
- "type": 1,
- "description": "Enter your ingestion price per GB (PAYG or Commitment Tier). You can also refer to Azure Pricing Calculator.",
- "value": "4"
- },
- {
- "id": "9d5299d0-36a0-4666-9803-ca6931bdaab7",
- "version": "KqlParameterItem/1.0",
- "name": "RetentionPrice",
- "label": "Retention price",
- "type": 1,
- "description": "Enter the retention price per GB/month that will be used in this workbook's calculations",
- "value": "0.1"
- },
- {
- "id": "67494f3e-322e-4411-9b45-1cbea03ed618",
- "version": "KqlParameterItem/1.0",
- "name": "TotalE5Seats",
- "label": "Total seats (E5/A5/F5/G5)",
- "type": 1,
- "description": "Enter the total number of Microsoft 365 E5, A5, F5, G5 and Microsoft 365 E5, A5, F5, G5 Security licenses in your environment",
- "value": "0"
- }
- ],
- "style": "pills",
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces"
- },
- "name": "parameters - 5"
- },
- {
- "type": 1,
- "content": {
- "json": "## Ingestion summary"
- },
- "name": "text - 2"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "union withsource = tt *\r\n| where TimeGenerated > startofday({TimeRange:start}) and TimeGenerated < startofday({TimeRange:end})\r\n// Only look at chargeable Tables\r\n| where _IsBillable == True\r\n| summarize TotalGBytes =round(sum(_BilledSize/(1024*1024*1024)),2) by bin(TimeGenerated, 1d)//, Solution=tt\r\n| summarize ['GBs/day'] =round(avg(TotalGBytes),2)",
- "size": 4,
- "title": "Average billable GBs/day ingested in the last {TimeRange}",
- "timeContextFromParameter": "TimeRange",
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "GBs/day",
- "formatter": 12,
- "formatOptions": {
- "palette": "greenRed"
- }
- },
- "showBorder": false,
- "size": "auto"
- }
- },
- "name": "query - 6"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "Usage\r\n| where IsBillable == true\r\n| summarize size = sum(Quantity)/1024 by IsBillable\r\n| project ['Total data ingestion'] = size, ['Estimated cost'] = size*{Price}",
- "size": 4,
- "title": "Total billable ingestion and cost in the last {TimeRange}",
- "timeContextFromParameter": "TimeRange",
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "formatter": 12,
- "formatOptions": {
- "palette": "greenRed",
- "compositeBarSettings": {
- "labelText": "",
- "columnSettings": []
- }
- },
- "numberFormat": {
- "unit": 0,
- "options": {
- "currency": "USD",
- "style": "currency",
- "useGrouping": false
- }
- }
- },
- "leftContent": {
- "columnMatch": "Total data ingestion",
- "formatter": 12,
- "formatOptions": {
- "palette": "greenRed"
- },
- "numberFormat": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "useGrouping": false,
- "maximumFractionDigits": 1
- }
- }
- },
- "rightContent": {
- "columnMatch": "Estimated cost",
- "formatter": 12,
- "formatOptions": {
- "palette": "greenRed"
- },
- "numberFormat": {
- "unit": 0,
- "options": {
- "currency": "USD",
- "style": "currency",
- "useGrouping": false,
- "maximumFractionDigits": 1
- }
- }
- },
- "showBorder": false,
- "size": "auto"
- }
- },
- "name": "query - 8"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let Categories = datatable(Type:string,Category:string)\r\n[\r\n \"AuditLogs\", \"Azure Active Directory\",\r\n \"SigninLogs\", \"Azure Active Directory\",\r\n \"AADNonInteractiveUserSignInLogs\", \"Azure Active Directory\",\r\n \"AADServicePrincipalSignInLogs\", \"Azure Active Directory\",\r\n \"AADManagedIdentitySignInLogs\", \"Azure Active Directory\",\r\n \"AADProvisioningLogs\",\"Azure Active Directory\",\r\n \"BehaviorAnalytics\", \"User Entity Behavior Analytics\",\r\n \"UserPeerAnalytics\",\"User Entity Behavior Analytics\",\r\n \"UserAccessAnalytics\",\"User Entity Behavior Analytics\",\r\n \"IdentityInfo\",\"User Entity Behavior Analytics\",\r\n \"DeviceLogonEvents\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceEvents\",\"Microsoft Defender for Endpoint\",\r\n\t\"DeviceNetworkInfo\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceImageLoadEvents\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceFileEvents\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceInfo\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceProcessEvents\", \"Microsoft Defender for Endpoint\",\t\r\n\t\"DeviceNetworkEvents\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceRegistryEvents\", \"Microsoft Defender for Endpoint\",\r\n \"DeviceFileCertificateInfo\", \"Microsoft Defender for Endpoint\",\r\n \"EmailAttachmentInfo\", \"Microsoft Defender for Office 365\",  \r\n \"EmailEvents\", \"Microsoft Defender for Office 365\",  \r\n \"EmailPostDeliveryEvents\", \"Microsoft Defender for Office 365\",  \r\n \"EmailUrlInfo\", \"Microsoft Defender for Office 365\",\r\n \"IdentityLogonEvents\", \"Microsoft Defender for Identity\",\r\n \"IdentityQueryEvents\", \"Microsoft Defender for Identity\",\r\n \"IdentityDirectoryEvents\", \"Microsoft Defender for Identity\",\r\n \"CloudAppEvents\", \"Microsoft Defender for Cloud Apps\",\r\n \"AlertEvidence\", \"Microsoft Defender Alert Evidence\",\r\n \"InsightsMetrics\", \"Azure Monitor for VMs\",\r\n \"VMBoundPort\", \"Azure Monitor for VMs\",\r\n \"VMComputer\", \"Azure Monitor for VMs\",\r\n \"VMConnection\", \"Azure Monitor for VMs\",\r\n \"VMProcess\", \"Azure Monitor for VMs\",\r\n \"SecurityEvent\", \"Windows Security Events\",\r\n \"Syslog\", \"Syslog/CEF\",\r\n \"CommonSecurityLog\", \"Syslog/CEF\",\r\n \"ThreatIntelligenceIndicator\", \"Threat Intelligence\",\r\n \"DnsEvents\", \"DNS Logs\",\r\n \"DnsInventory\", \"DNS Logs\",\r\n \"AWSCloudTrail\", \"AWS Cloud Trail\",\r\n \"ConfigurationChange\", \"Change Tracking\",\r\n \"ConfigurationData\", \"Change Tracking\",\r\n \"AzureDiagnostics\", \"Azure Resources\",\r\n \"LAQueryLogs\", \"Management\",\r\n \"SentinelHealth\",\"Management\",\r\n \"Perf\",\"Performance\",\r\n \"AzureMetrics\",\"Azure Metrics\",\r\n \"SecurityNestedRecommendation\", \"Microsoft Defender for Cloud\",\r\n \"SecurityRecommendation\", \"Microsoft Defender for Cloud\",\r\n \"SecurityRegulatoryCompliance\", \"Microsoft Defender for Cloud\",\r\n \"SecureScoreControls\", \"Microsoft Defender for Cloud\",\r\n \"SecurityBaseline\", \"Microsoft Defender for Cloud\",\r\n \"SecureScores\", \"Microsoft Defender for Cloud\",\r\n \"Update\", \"Update Management\",\r\n \"UpdateSummary\", \"Update Management\"\r\n];\r\nlet customTables = Usage\r\n| where IsBillable == true\r\n| where DataType contains \"_CL\"\r\n| summarize size = sum(Quantity)/1024 by DataType\r\n| project ['Log Type'] = DataType, ['Table Size'] = size, ['Estimated cost'] = size*{Price};\r\nlet knownTables = Usage\r\n| where IsBillable == true \r\n| join kind=leftouter Categories on $left.DataType == $right.Type\r\n| summarize size =sumif(Quantity, isnotempty(Category))/1024, sizeOther= sumif(Quantity,(isempty(Category) and DataType !contains \"_CL\"))/1024 by Category\r\n| project ['Log Type'] = iif(isnotempty( Category),Category,\"Other\"), ['Table Size'] = iif(isnotempty( Category),size,sizeOther), ['Estimated cost'] = iif(isnotempty(Category),size*{Price},sizeOther*4);\r\nunion customTables, knownTables\r\n| order by ['Table Size'] desc",
- "size": 0,
- "title": "Breakdown of billable ingestion by log category in the last {TimeRange}",
- "timeContextFromParameter": "TimeRange",
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "table",
- "gridSettings": {
- "formatters": [
- {
- "columnMatch": "Table Size",
- "formatter": 3,
- "formatOptions": {
- "palette": "greenRed"
- },
- "numberFormat": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "useGrouping": false
- }
- }
- },
- {
- "columnMatch": "Estimated cost",
- "formatter": 0,
- "numberFormat": {
- "unit": 0,
- "options": {
- "currency": "USD",
- "style": "currency"
- }
- }
- }
- ]
- },
- "graphSettings": {
- "type": 0,
- "topContent": {
- "columnMatch": "Log Category",
- "formatter": 1
- },
- "centerContent": {
- "columnMatch": "Billed Size",
- "formatter": 1,
- "numberFormat": {
- "unit": 17,
- "options": {
- "maximumSignificantDigits": 3,
- "maximumFractionDigits": 2
- }
- }
- }
- }
- },
- "name": "query - 2"
- },
- {
- "type": 1,
- "content": {
- "json": "## Retention summary"
- },
- "name": "text - 4"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "union withsource=TableName1 * | where TimeGenerated < ago(90d) | extend key = 'Key' | summarize size = sum(_BilledSize)/1024/1024/1024 by key\r\n| project ['Data over 90 days'] = size, ['Retention Cost'] = size*{RetentionPrice}\r\n\r\n\r\n",
- "size": 4,
- "title": "Data older than 90 days and resulting retention cost",
- "noDataMessage": "You have no data older than 90 days",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "gridSettings": {
- "formatters": [
- {
- "columnMatch": "Data over 90 days",
- "formatter": 0,
- "numberFormat": {
- "unit": 36,
- "options": {
- "style": "decimal",
- "useGrouping": false
- }
- }
- },
- {
- "columnMatch": "Retention Cost",
- "formatter": 0,
- "numberFormat": {
- "unit": 0,
- "options": {
- "style": "decimal"
- }
- }
- }
- ]
- },
- "tileSettings": {
- "titleContent": {},
- "leftContent": {
- "columnMatch": "Data over 90 days",
- "formatter": 12,
- "formatOptions": {
- "palette": "greenRed"
- },
- "numberFormat": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "maximumFractionDigits": 1
- }
- }
- },
- "rightContent": {
- "columnMatch": "Retention Cost",
- "formatter": 12,
- "formatOptions": {
- "palette": "greenRed"
- },
- "numberFormat": {
- "unit": 0,
- "options": {
- "currency": "USD",
- "style": "currency",
- "maximumFractionDigits": 2
- }
- }
- },
- "showBorder": false,
- "size": "auto"
- }
- },
- "name": "query - 7"
- },
- {
- "type": 1,
- "content": {
- "json": "## Microsoft Sentinel benefit for Microsoft 365 E5, A5, F5 and G5 customers\r\n\r\nWith security information and event management (SIEM) and extended detection and response (XDR) from Microsoft, you’re armed with the context and automation you need to stop sophisticated, cross-domain attacks across your entire organization. \r\n\r\nMicrosoft 365 E5, A5, F5, G5 and Microsoft 365 E5, A5, F5, G5 Security customers can get data grant up to 5MB per user/day of Microsoft 365 data ingestion into Microsoft Sentinel.
\r\nThe data sources included in this offer include:\r\n\r\n- Microsoft Entra ID (Azure AD) sign-in and audit logs\r\n- Microsoft Cloud App Security shadow IT discovery logs\r\n- Microsoft Information Protection logs\r\n- Microsoft 365 advanced hunting data\r\n\r\nThe data grant will be calculated at the end of the month and applied to your bill, covering the cost of up to 5 MB of data ingestion per user/day.\r\n\r\nVisit https://azure.microsoft.com/offers/sentinel-microsoft-365-offer/ for more information\r\n\r\n
\r\n\r\n### Below are the ingestion for the eligible data sources:\r\n\r\n_**Note:** Kindly specify **Total seats (E5/A5/F5/G5)** and **Ingestion Price** parameters for calculation._"
- },
- "name": "text - 12"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "Usage\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\",  \r\n\"DeviceFileEvents\",  \r\n\"DeviceImageLoadEvents\",  \r\n\"DeviceInfo\",  \r\n\"DeviceLogonEvents\",  \r\n\"DeviceNetworkEvents\",  \r\n\"DeviceNetworkInfo\",  \r\n\"DeviceProcessEvents\",  \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\",  \r\n\"EmailAttachmentInfo\",  \r\n\"EmailEvents\",  \r\n\"EmailPostDeliveryEvents\",  \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\"\r\n)   \r\n| summarize BillableDataGB = sum(Quantity) / 1000. by DataType\r\n| order by BillableDataGB desc\r\n",
- "size": 0,
- "timeContextFromParameter": "TimeRange",
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "gridSettings": {
- "formatters": [
- {
- "columnMatch": "BillableDataGB",
- "formatter": 3,
- "formatOptions": {
- "palette": "blue"
- }
- }
- ]
- }
- },
- "name": "query - 13"
- },
- {
- "type": 1,
- "content": {
- "json": "
\r\n**Daily ingestion size (for eligible data sources) vs Maximum data grant:**"
- },
- "conditionalVisibilities": [
- {
- "parameterName": "TotalE5Seats",
- "comparison": "isNotEqualTo",
- "value": "0"
- },
- {
- "parameterName": "TotalE5Seats",
- "comparison": "isNotEqualTo"
- }
- ],
- "name": "text - DailyIngestionVsAllocation"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "Usage\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\",  \r\n\"DeviceFileEvents\",  \r\n\"DeviceImageLoadEvents\",  \r\n\"DeviceInfo\",  \r\n\"DeviceLogonEvents\",  \r\n\"DeviceNetworkEvents\",  \r\n\"DeviceNetworkInfo\",  \r\n\"DeviceProcessEvents\",  \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\",  \r\n\"EmailAttachmentInfo\",  \r\n\"EmailEvents\",  \r\n\"EmailPostDeliveryEvents\",  \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\")   \r\n| summarize DailyIngestionGB = toreal(sum(Quantity))/ 1024 by format_datetime(TimeGenerated, 'yyyy-MM-dd') \r\n| extend MaxDataGrantGB = ((5*toreal({TotalE5Seats}))/1024)\r\n| sort by TimeGenerated asc\r\n",
- "size": 0,
- "aggregation": 3,
- "timeContextFromParameter": "TimeRange",
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "linechart",
- "chartSettings": {
- "xAxis": "TimeGenerated",
- "showDataPoints": true,
- "ySettings": {
- "numberFormatSettings": {
- "unit": 0,
- "options": {
- "style": "decimal",
- "useGrouping": true,
- "maximumFractionDigits": 3
- }
- }
- }
- }
- },
- "conditionalVisibilities": [
- {
- "parameterName": "TotalE5Seats",
- "comparison": "isNotEqualTo"
- },
- {
- "parameterName": "TotalE5Seats",
- "comparison": "isNotEqualTo",
- "value": "0"
- }
- ],
- "name": "DailyIngestionVSAllocation"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "Usage\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\",  \r\n\"DeviceFileEvents\",  \r\n\"DeviceImageLoadEvents\",  \r\n\"DeviceInfo\",  \r\n\"DeviceLogonEvents\",  \r\n\"DeviceNetworkEvents\",  \r\n\"DeviceNetworkInfo\",  \r\n\"DeviceProcessEvents\",  \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\",  \r\n\"EmailAttachmentInfo\",  \r\n\"EmailEvents\",  \r\n\"EmailPostDeliveryEvents\",  \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\"\r\n)   \r\n| summarize TotalBillableDataGB = sum(Quantity) / 1024\r\n\r\n",
- "size": 4,
- "title": "Total ingestion",
- "timeContextFromParameter": "TimeRange",
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "TotalBillableDataGB",
- "formatter": 12,
- "formatOptions": {
- "palette": "greenRed"
- },
- "numberFormat": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "maximumFractionDigits": 2
- }
- }
- },
- "showBorder": false
- }
- },
- "customWidth": "20",
- "name": "E5IngestionSize"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let DailyMaxDiscountGB = ((5*toreal({TotalE5Seats}))/1024);\r\nUsage\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\",  \r\n\"DeviceFileEvents\",  \r\n\"DeviceImageLoadEvents\",  \r\n\"DeviceInfo\",  \r\n\"DeviceLogonEvents\",  \r\n\"DeviceNetworkEvents\",  \r\n\"DeviceNetworkInfo\",  \r\n\"DeviceProcessEvents\",  \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\",  \r\n\"EmailAttachmentInfo\",  \r\n\"EmailEvents\",  \r\n\"EmailPostDeliveryEvents\",  \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\")   \r\n| summarize DailyBillableGB = toreal(sum(Quantity))/ 1024 by format_datetime(TimeGenerated, 'yy-MM-dd') \r\n| extend DailyMaxGrantGB = DailyMaxDiscountGB\r\n| summarize MaxDataGrantGB = sum(toreal(DailyMaxGrantGB))\r\n\r\n",
- "size": 4,
- "title": "Total Data Grant Limit",
- "timeContextFromParameter": "TimeRange",
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "MaxDataGrantGB",
- "formatter": 12,
- "formatOptions": {
- "palette": "orangeBlue"
- },
- "numberFormat": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "maximumFractionDigits": 2
- }
- }
- },
- "showBorder": false,
- "sortOrderField": 1
- }
- },
- "conditionalVisibilities": [
- {
- "parameterName": "TotalE5Seats",
- "comparison": "isNotEqualTo"
- },
- {
- "parameterName": "TotalE5Seats",
- "comparison": "isNotEqualTo",
- "value": "0"
- }
- ],
- "customWidth": "20",
- "name": "DataGrantLimit"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let DailyMaxDiscountGB = ((5*toreal({TotalE5Seats}))/1024);\r\nUsage\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\",  \r\n\"DeviceFileEvents\",  \r\n\"DeviceImageLoadEvents\",  \r\n\"DeviceInfo\",  \r\n\"DeviceLogonEvents\",  \r\n\"DeviceNetworkEvents\",  \r\n\"DeviceNetworkInfo\",  \r\n\"DeviceProcessEvents\",  \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\",  \r\n\"EmailAttachmentInfo\",  \r\n\"EmailEvents\",  \r\n\"EmailPostDeliveryEvents\",  \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\")   \r\n| summarize DailyBillableGB = toreal(sum(Quantity))/ 1024 by format_datetime(TimeGenerated, 'yy-MM-dd') \r\n| summarize TotalEligibleGB = sum(iif(toreal(DailyBillableGB)>toreal(DailyMaxDiscountGB),toreal(DailyMaxDiscountGB),DailyBillableGB))\r\n\r\n",
- "size": 4,
- "title": "Total Data Grant Used",
- "timeContextFromParameter": "TimeRange",
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "TotalEligibleGB",
- "formatter": 12,
- "formatOptions": {
- "palette": "coldHot"
- },
- "numberFormat": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "maximumFractionDigits": 2
- }
- }
- },
- "showBorder": false,
- "sortOrderField": 1
- }
- },
- "conditionalVisibilities": [
- {
- "parameterName": "TotalE5Seats",
- "comparison": "isNotEqualTo"
- },
- {
- "parameterName": "TotalE5Seats",
- "comparison": "isNotEqualTo",
- "value": "0"
- }
- ],
- "customWidth": "30",
- "name": "EligibleE5Ingestion"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let DailyMaxDiscountGB = ((5*toreal({TotalE5Seats}))/1024);\r\nUsage\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\",  \r\n\"DeviceFileEvents\",  \r\n\"DeviceImageLoadEvents\",  \r\n\"DeviceInfo\",  \r\n\"DeviceLogonEvents\",  \r\n\"DeviceNetworkEvents\",  \r\n\"DeviceNetworkInfo\",  \r\n\"DeviceProcessEvents\",  \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\",  \r\n\"EmailAttachmentInfo\",  \r\n\"EmailEvents\",  \r\n\"EmailPostDeliveryEvents\",  \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\")   \r\n| summarize DailyBillableGB = toreal(sum(Quantity))/ 1024 by format_datetime(TimeGenerated, 'yy-MM-dd') \r\n| summarize TotalEligibleGB = sum(iif(toreal(DailyBillableGB)>toreal(DailyMaxDiscountGB),toreal(DailyMaxDiscountGB),DailyBillableGB))\r\n| extend TotalDiscount = toreal(TotalEligibleGB)*{Price}\r\n| project TotalDiscount\r\n\r\n",
- "size": 4,
- "title": "Estimated Saving",
- "timeContextFromParameter": "TimeRange",
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "TotalDiscount",
- "formatter": 12,
- "formatOptions": {
- "palette": "greenRed"
- },
- "numberFormat": {
- "unit": 0,
- "options": {
- "currency": "USD",
- "style": "currency",
- "maximumFractionDigits": 2
- }
- }
- },
- "showBorder": false
- }
- },
- "conditionalVisibilities": [
- {
- "parameterName": "TotalE5Seats",
- "comparison": "isNotEqualTo",
- "value": "0"
- },
- {
- "parameterName": "TotalE5Seats",
- "comparison": "isNotEqualTo"
- }
- ],
- "customWidth": "20",
- "name": "EstimateE5Discount"
- },
- {
- "type": 1,
- "content": {
- "json": "## SOAR summary\r\n\r\nIn this section, you can view billable information regarding your Logic Apps. The data is based on Logic Apps' built-in metrics. To view the list of Logic Apps click the \">\" icon in the subscription column.\r\n\r\nYou can change the default Logic App execution cost in the parameter below.\r\n\r\nTo see the approximate cost of your logic apps, **click on any subscription on the table below**.\r\n\r\nFor more billable information, visit: https://azure.microsoft.com/pricing/details/logic-apps/"
- },
- "name": "text - 3"
- },
- {
- "type": 9,
- "content": {
- "version": "KqlParameterItem/1.0",
- "parameters": [
- {
- "id": "6f50ee54-8f0e-424e-9e16-70eca531af7f",
- "version": "KqlParameterItem/1.0",
- "name": "ResourceTypes",
- "label": "Resource types",
- "type": 7,
- "isRequired": true,
- "multiSelect": true,
- "quote": "'",
- "delimiter": ",",
- "value": [
- "microsoft.logic/workflows"
- ],
- "isHiddenWhenLocked": true,
- "typeSettings": {
- "additionalResourceOptions": [],
- "includeAll": true
- },
- "timeContext": {
- "durationMs": 86400000
- }
- },
- {
- "id": "1c8dc8da-2233-426c-8cfc-52ec31bf1e84",
- "version": "KqlParameterItem/1.0",
- "name": "Subscription",
- "label": "Subscriptions",
- "type": 6,
- "isRequired": true,
- "multiSelect": true,
- "quote": "'",
- "delimiter": ",",
- "query": "Resources\r\n| where type in~ ({ResourceTypes})\r\n| summarize Count = count() by subscriptionId\r\n| order by Count desc\r\n| extend Rank = row_number()\r\n| project value = subscriptionId, label = subscriptionId, selected = Rank == 1",
- "typeSettings": {
- "additionalResourceOptions": [
- "value::all"
- ],
- "showDefault": false
- },
- "timeContext": {
- "durationMs": 86400000
- },
- "defaultValue": "value::all",
- "queryType": 1,
- "resourceType": "microsoft.resourcegraph/resources",
- "value": [
- "value::all"
- ]
- },
- {
- "id": "f103ef04-042e-45ed-8f78-b31e676258d7",
- "version": "KqlParameterItem/1.0",
- "name": "ResourceGroups",
- "label": "Resource groups",
- "type": 2,
- "isRequired": true,
- "multiSelect": true,
- "quote": "'",
- "delimiter": ",",
- "query": "Resources\r\n| where type in~ ({ResourceTypes})\r\n| summarize Count = count() by subscriptionId, resourceGroup\r\n| order by Count desc\r\n| extend Rank = row_number()\r\n| project value = strcat('/subscriptions/', subscriptionId, '/resourceGroups/', resourceGroup), label = resourceGroup, selected = false",
- "typeSettings": {
- "additionalResourceOptions": [
- "value::all"
- ],
- "showDefault": false
- },
- "timeContext": {
- "durationMs": 86400000
- },
- "defaultValue": "value::all",
- "queryType": 1,
- "resourceType": "microsoft.resourcegraph/resources",
- "value": [
- "value::all"
- ]
- },
- {
- "id": "b6514d02-8893-44b8-896e-e53ada5024d5",
- "version": "KqlParameterItem/1.0",
- "name": "Resources",
- "label": "Logic Apps",
- "type": 5,
- "isRequired": true,
- "multiSelect": true,
- "quote": "'",
- "delimiter": ",",
- "query": "Resources\r\n| where type in~({ResourceTypes})\r\n| extend resourceGroupId = strcat('/subscriptions/', subscriptionId, '/resourceGroups/', resourceGroup)\r\n| where resourceGroupId in~({ResourceGroups}) or '*' in~({ResourceGroups})\r\n| order by name asc\r\n| extend Rank = row_number()\r\n| project value = id, label = tostring(name), selected = Rank <= 10, group = resourceGroup",
- "value": [
- "value::all"
- ],
- "typeSettings": {
- "additionalResourceOptions": [
- "value::all"
- ],
- "showDefault": false
- },
- "timeContext": {
- "durationMs": 86400000
- },
- "queryType": 1,
- "resourceType": "microsoft.resourcegraph/resources"
- },
- {
- "id": "8f552e99-2d30-4679-b4b0-25429bf0216b",
- "version": "KqlParameterItem/1.0",
- "name": "ExecutionCost",
- "label": "Logic App execution cost",
- "type": 1,
- "isRequired": true,
- "value": "0.000125"
- }
- ],
- "style": "pills",
- "queryType": 1,
- "resourceType": "microsoft.resourcegraph/resources"
- },
- "name": "parameters - 10"
- },
- {
- "type": 10,
- "content": {
- "chartId": "workbooke70b7cbc-f1d7-4a74-b8b9-75cc8d5ab586",
- "version": "MetricsItem/2.0",
- "size": 1,
- "chartType": 0,
- "resourceType": "microsoft.logic/workflows",
- "metricScope": 0,
- "resourceParameter": "Resources",
- "resourceIds": [
- "{Resources}"
- ],
- "timeContextFromParameter": "TimeRange",
- "timeContext": {
- "durationMs": 604800000
- },
- "metrics": [
- {
- "namespace": "microsoft.logic/workflows",
- "metric": "microsoft.logic/workflows--TotalBillableExecutions",
- "aggregation": 1
- }
- ],
- "title": "Click on a subscription below to calculate the estimated automation costs",
- "resourceLimit": 10000,
- "gridSettings": {
- "formatters": [
- {
- "columnMatch": "$gen_group",
- "formatter": 15,
- "formatOptions": {
- "linkTarget": null,
- "showIcon": true
- }
- },
- {
- "columnMatch": "Subscription",
- "formatter": 5
- },
- {
- "columnMatch": "Name",
- "formatter": 13,
- "formatOptions": {
- "linkTarget": "Resource",
- "showIcon": true
- }
- },
- {
- "columnMatch": "microsoft.logic/workflows--TotalBillableExecutions",
- "formatter": 8,
- "formatOptions": {
- "palette": "blue",
- "aggregation": "Sum"
- }
- },
- {
- "columnMatch": "microsoft.logic/workflows--TotalBillableExecutions Timeline",
- "formatter": 21,
- "formatOptions": {
- "palette": "blue"
- }
- },
- {
- "columnMatch": "microsoft.logic/workflows--BillableTriggerExecutions Timeline",
- "formatter": 5
- },
- {
- "columnMatch": "microsoft.logic/workflows--BillableActionExecutions",
- "formatter": 8,
- "formatOptions": {
- "palette": "blue"
- },
- "numberFormat": {
- "unit": 0,
- "options": {
- "style": "decimal"
- }
- }
- },
- {
- "columnMatch": "microsoft.logic/workflows--BillableActionExecutions Timeline",
- "formatter": 5
- },
- {
- "columnMatch": "RG",
- "formatter": 13,
- "formatOptions": {
- "linkTarget": null,
- "showIcon": true
- }
- },
- {
- "columnMatch": "Sum",
- "formatter": 1,
- "formatOptions": {
- "aggregation": "Sum"
- },
- "numberFormat": {
- "unit": 0,
- "options": {
- "style": "decimal"
- }
- }
- }
- ],
- "rowLimit": 10000,
- "filter": true,
- "hierarchySettings": {
- "treeType": 1,
- "groupBy": [
- "Subscription"
- ]
- },
- "labelSettings": [
- {
- "columnId": "microsoft.logic/workflows--TotalBillableExecutions",
- "label": "Total Billable Executions (Sum)"
- },
- {
- "columnId": "microsoft.logic/workflows--TotalBillableExecutions Timeline",
- "label": "Total Billable Executions Timeline"
- }
- ]
- },
- "sortBy": [],
- "exportFieldName": "microsoft.logic/workflows--TotalBillableExecutions",
- "exportParameterName": "Total",
- "exportDefaultValue": "0"
- },
- "name": "Billable Metric"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "Usage | take 1 | project ['Estimated automation costs'] ={Total}*{ExecutionCost}",
- "size": 4,
- "title": "Estimated Logic App execution cost over the last {TimeRange}",
- "timeContext": {
- "durationMs": 86400000
- },
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "Estimated automation costs",
- "formatter": 12,
- "formatOptions": {
- "palette": "greenRed"
- },
- "numberFormat": {
- "unit": 0,
- "options": {
- "currency": "USD",
- "style": "currency",
- "minimumFractionDigits": 2,
- "maximumFractionDigits": 3
- }
- }
- },
- "showBorder": false
- }
- },
- "conditionalVisibility": {
- "parameterName": "Total",
- "comparison": "isNotEqualTo"
- },
- "name": "query - 11"
- }
- ],
- "fromTemplateId": "sentinel-SentinelCosts",
- "$schema": "https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json"
-}
+ "fromTemplateId": "sentinel-SentinelCosts",
+ "$schema": "https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json"
+}
\ No newline at end of file
diff --git a/Workbooks/WorkbooksMetadata.json b/Workbooks/WorkbooksMetadata.json
index d3043416f15..a8a58f9dedd 100644
--- a/Workbooks/WorkbooksMetadata.json
+++ b/Workbooks/WorkbooksMetadata.json
@@ -7005,7 +7005,7 @@
"SentinelCostsWhite.png",
"SentinelCostsBlack.png"
],
- "version": "1.5.1",
+ "version": "1.6.0",
"title": "Sentinel Costs",
"templateRelativePath": "SentinelCosts.json",
"subtitle": "",
From 0b93b338f3906a1e017cfc2c267349025dd905e9 Mon Sep 17 00:00:00 2001
From: Dr Bill Mcilhargey <19168174+billmcilhargey@users.noreply.github.com>
Date: Fri, 28 Aug 2026 16:45:19 -0400
Subject: [PATCH 2/6] Enhance Sentinel Costs workbook with optional SOAR
automation inputs and resource selectors
---
Workbooks/SentinelCosts.json | 305 +++++++++++++++++++++--------------
1 file changed, 186 insertions(+), 119 deletions(-)
diff --git a/Workbooks/SentinelCosts.json b/Workbooks/SentinelCosts.json
index 80bc4406cf7..d27d9c1d370 100644
--- a/Workbooks/SentinelCosts.json
+++ b/Workbooks/SentinelCosts.json
@@ -205,6 +205,129 @@
},
"name": "parameters - 5"
},
+ {
+ "type": 1,
+ "content": {
+ "json": "---\r\n### Optional: SOAR automation inputs\r\n\r\nThe selectors below are optional. Set **Subscriptions**, **Resource groups**, and **Logic Apps** only if you want to estimate SOAR/Logic App automation costs in the SOAR summary section further down. Microsoft Sentinel Data Lake costs cannot be estimated from Log Analytics `Usage` data, so no additional parameters are needed for the Data Lake section."
+ },
+ "name": "text - optional SOAR and Data Lake inputs"
+ },
+ {
+ "type": 9,
+ "content": {
+ "version": "KqlParameterItem/1.0",
+ "parameters": [
+ {
+ "id": "6f50ee54-8f0e-424e-9e16-70eca531af7f",
+ "version": "KqlParameterItem/1.0",
+ "name": "ResourceTypes",
+ "label": "Resource types",
+ "type": 7,
+ "isRequired": true,
+ "multiSelect": true,
+ "quote": "\u0027",
+ "delimiter": ",",
+ "value": [
+ "microsoft.logic/workflows"
+ ],
+ "isHiddenWhenLocked": true,
+ "typeSettings": {
+ "additionalResourceOptions": [
+
+ ],
+ "includeAll": true
+ },
+ "timeContext": {
+ "durationMs": 86400000
+ }
+ },
+ {
+ "id": "1c8dc8da-2233-426c-8cfc-52ec31bf1e84",
+ "version": "KqlParameterItem/1.0",
+ "name": "Subscription",
+ "label": "Subscriptions",
+ "type": 6,
+ "isRequired": true,
+ "multiSelect": true,
+ "quote": "\u0027",
+ "delimiter": ",",
+ "query": "Resources\r\n| where type in~ ({ResourceTypes})\r\n| summarize Count = count() by subscriptionId\r\n| order by Count desc\r\n| extend Rank = row_number()\r\n| project value = subscriptionId, label = subscriptionId, selected = Rank == 1",
+ "typeSettings": {
+ "additionalResourceOptions": [
+ "value::all"
+ ],
+ "showDefault": false
+ },
+ "timeContext": {
+ "durationMs": 86400000
+ },
+ "defaultValue": "value::all",
+ "queryType": 1,
+ "resourceType": "microsoft.resourcegraph/resources",
+ "value": [
+ "value::all"
+ ]
+ },
+ {
+ "id": "f103ef04-042e-45ed-8f78-b31e676258d7",
+ "version": "KqlParameterItem/1.0",
+ "name": "ResourceGroups",
+ "label": "Resource groups",
+ "type": 2,
+ "isRequired": true,
+ "multiSelect": true,
+ "quote": "\u0027",
+ "delimiter": ",",
+ "query": "Resources\r\n| where type in~ ({ResourceTypes})\r\n| summarize Count = count() by subscriptionId, resourceGroup\r\n| order by Count desc\r\n| extend Rank = row_number()\r\n| project value = strcat(\u0027/subscriptions/\u0027, subscriptionId, \u0027/resourceGroups/\u0027, resourceGroup), label = resourceGroup, selected = false",
+ "typeSettings": {
+ "additionalResourceOptions": [
+ "value::all"
+ ],
+ "showDefault": false
+ },
+ "timeContext": {
+ "durationMs": 86400000
+ },
+ "defaultValue": "value::all",
+ "queryType": 1,
+ "resourceType": "microsoft.resourcegraph/resources",
+ "value": [
+ "value::all"
+ ]
+ },
+ {
+ "id": "b6514d02-8893-44b8-896e-e53ada5024d5",
+ "version": "KqlParameterItem/1.0",
+ "name": "Resources",
+ "label": "Logic Apps",
+ "type": 5,
+ "isRequired": true,
+ "multiSelect": true,
+ "quote": "\u0027",
+ "delimiter": ",",
+ "query": "Resources\r\n| where type in~({ResourceTypes})\r\n| extend resourceGroupId = strcat(\u0027/subscriptions/\u0027, subscriptionId, \u0027/resourceGroups/\u0027, resourceGroup)\r\n| where resourceGroupId in~({ResourceGroups}) or \u0027*\u0027 in~({ResourceGroups})\r\n| order by name asc\r\n| extend Rank = row_number()\r\n| project value = id, label = tostring(name), selected = Rank \u003c= 10, group = resourceGroup",
+ "value": [
+ "value::all"
+ ],
+ "typeSettings": {
+ "additionalResourceOptions": [
+ "value::all"
+ ],
+ "showDefault": false
+ },
+ "timeContext": {
+ "durationMs": 86400000
+ },
+ "queryType": 1,
+ "resourceType": "microsoft.resourcegraph/resources"
+ }
+ ],
+ "style": "pills",
+ "queryType": 1,
+ "resourceType": "microsoft.resourcegraph/resources"
+ },
+ "name": "parameters - SOAR resource selectors"
+ },
{
"type": 1,
"content": {
@@ -1745,137 +1868,81 @@
{
"type": 1,
"content": {
- "json": "## Microsoft Sentinel Data Lake\r\n\r\nThe data lake provides long-term, cost-effective storage outside the Analytics tier. Its costs are billed separately for data lake ingestion, processing, storage, query, and advanced data insights. Microsoft Defender XDR data also has separate 30-day default and extended-retention pricing.\r\n\r\nData lake charges are not available from the Log Analytics `Usage` table, so this workbook cannot calculate billing-accurate data lake costs. Review current usage and costs in **Microsoft Sentinel \u003e Cost management** in the Microsoft Defender portal. Learn more in the [Microsoft Sentinel data lake overview](https://learn.microsoft.com/en-us/azure/sentinel/datalake/sentinel-lake-overview) and [Manage and monitor costs for Microsoft Sentinel](https://learn.microsoft.com/en-us/azure/sentinel/billing-monitor-costs)."
+ "json": "## Microsoft Sentinel Data Lake\r\n\r\nThe data lake provides long-term, cost-effective storage outside the Analytics tier. Its costs are billed separately for data lake ingestion, processing, storage, query, and advanced data insights. Microsoft Defender XDR data also has separate 30-day default and extended-retention pricing.\r\n\r\nData lake charges are not available from the Log Analytics `Usage` table, so this workbook cannot calculate billing-accurate data lake costs. Review current usage and costs in **Microsoft Sentinel \u003e Cost management** in the Microsoft Defender portal. Learn more in the [Microsoft Sentinel data lake overview](https://learn.microsoft.com/en-us/azure/sentinel/datalake/sentinel-lake-overview) and [Manage and monitor costs for Microsoft Sentinel](https://learn.microsoft.com/en-us/azure/sentinel/billing-monitor-costs). Review current data lake rates on the [Microsoft Sentinel pricing page](https://www.microsoft.com/en-us/security/pricing/microsoft-sentinel/)."
},
"name": "text - Microsoft Sentinel Data Lake"
},
{
"type": 1,
"content": {
- "json": "## SOAR summary\r\n\r\nMicrosoft Sentinel playbooks use Azure Logic Apps to automate responses to incidents, alerts, and other security operations workflows. This section summarizes billable Logic App executions across accessible playbooks and estimates their execution cost using the **Logic App execution cost** input at the top of the workbook.\r\n\r\nTo populate this estimate, export the `TotalBillableExecutions` metric to the selected Log Analytics workspace and use the Analytics plan for the `AzureMetrics` table. Basic Logs tables cannot run this query. The estimate is not an invoice; use Azure Cost Management to validate billed charges.\r\n\r\nReview [Automate threat response with playbooks in Microsoft Sentinel](https://learn.microsoft.com/en-us/azure/sentinel/automation/automate-responses-with-playbooks) for playbook guidance. Because playbooks use Azure Logic Apps, additional charges can apply. Go to the [Azure Logic Apps](https://azure.microsoft.com/pricing/details/logic-apps/) pricing page for more details."
+ "json": "## Commitment tiers\r\n\r\nMicrosoft Sentinel and Log Analytics offer Pay-As-You-Go and Commitment Tier pricing (100, 200, 300, 400, 500, 1000, 2000, and 5000+ GB/day). This section is fully automatic: it detects your **current commitment tier** from the selected workspace configuration and calculates a **recommended tier** from your average billable daily ingestion over the selected time range. No additional input is required.\r\n\r\nCommitment tier changes typically require a minimum 31-day commitment before switching again \u2014 review **Days since tier last changed** before making a change. Actual per-GB rates vary by region, currency, and agreement type and change over time, so this workbook cannot calculate exact savings. Confirm current rates on the [Microsoft Sentinel pricing page](https://www.microsoft.com/en-us/security/pricing/microsoft-sentinel/) and review [Plan costs and understand pricing and billing for Microsoft Sentinel](https://learn.microsoft.com/en-us/azure/sentinel/billing?tabs=simplified%2Ccommitment-tiers#analytics-tier) before changing your commitment tier."
},
- "name": "text - 3"
+ "name": "text - commitment tiers"
},
{
- "type": 9,
+ "type": 3,
"content": {
- "version": "KqlParameterItem/1.0",
- "parameters": [
- {
- "id": "6f50ee54-8f0e-424e-9e16-70eca531af7f",
- "version": "KqlParameterItem/1.0",
- "name": "ResourceTypes",
- "label": "Resource types",
- "type": 7,
- "isRequired": true,
- "multiSelect": true,
- "quote": "\u0027",
- "delimiter": ",",
- "value": [
- "microsoft.logic/workflows"
- ],
- "isHiddenWhenLocked": true,
- "typeSettings": {
- "additionalResourceOptions": [
-
- ],
- "includeAll": true
- },
- "timeContext": {
- "durationMs": 86400000
- }
- },
- {
- "id": "1c8dc8da-2233-426c-8cfc-52ec31bf1e84",
- "version": "KqlParameterItem/1.0",
- "name": "Subscription",
- "label": "Subscriptions",
- "type": 6,
- "isRequired": true,
- "multiSelect": true,
- "quote": "\u0027",
- "delimiter": ",",
- "query": "Resources\r\n| where type in~ ({ResourceTypes})\r\n| summarize Count = count() by subscriptionId\r\n| order by Count desc\r\n| extend Rank = row_number()\r\n| project value = subscriptionId, label = subscriptionId, selected = Rank == 1",
- "typeSettings": {
- "additionalResourceOptions": [
- "value::all"
- ],
- "showDefault": false
- },
- "timeContext": {
- "durationMs": 86400000
- },
- "defaultValue": "value::all",
- "queryType": 1,
- "resourceType": "microsoft.resourcegraph/resources",
- "value": [
- "value::all"
- ]
- },
- {
- "id": "f103ef04-042e-45ed-8f78-b31e676258d7",
- "version": "KqlParameterItem/1.0",
- "name": "ResourceGroups",
- "label": "Resource groups",
- "type": 2,
- "isRequired": true,
- "multiSelect": true,
- "quote": "\u0027",
- "delimiter": ",",
- "query": "Resources\r\n| where type in~ ({ResourceTypes})\r\n| summarize Count = count() by subscriptionId, resourceGroup\r\n| order by Count desc\r\n| extend Rank = row_number()\r\n| project value = strcat(\u0027/subscriptions/\u0027, subscriptionId, \u0027/resourceGroups/\u0027, resourceGroup), label = resourceGroup, selected = false",
- "typeSettings": {
- "additionalResourceOptions": [
- "value::all"
- ],
- "showDefault": false
- },
- "timeContext": {
- "durationMs": 86400000
- },
- "defaultValue": "value::all",
- "queryType": 1,
- "resourceType": "microsoft.resourcegraph/resources",
- "value": [
- "value::all"
- ]
- },
- {
- "id": "b6514d02-8893-44b8-896e-e53ada5024d5",
- "version": "KqlParameterItem/1.0",
- "name": "Resources",
- "label": "Logic Apps",
- "type": 5,
- "isRequired": true,
- "multiSelect": true,
- "quote": "\u0027",
- "delimiter": ",",
- "query": "Resources\r\n| where type in~({ResourceTypes})\r\n| extend resourceGroupId = strcat(\u0027/subscriptions/\u0027, subscriptionId, \u0027/resourceGroups/\u0027, resourceGroup)\r\n| where resourceGroupId in~({ResourceGroups}) or \u0027*\u0027 in~({ResourceGroups})\r\n| order by name asc\r\n| extend Rank = row_number()\r\n| project value = id, label = tostring(name), selected = Rank \u003c= 10, group = resourceGroup",
- "value": [
- "value::all"
- ],
- "typeSettings": {
- "additionalResourceOptions": [
- "value::all"
- ],
- "showDefault": false
- },
- "timeContext": {
- "durationMs": 86400000
- },
- "queryType": 1,
- "resourceType": "microsoft.resourcegraph/resources"
- }
- ],
- "style": "pills",
+ "version": "KqlItem/1.0",
+ "query": "resources\r\n| where type =~ \u0027microsoft.operationalinsights/workspaces\u0027\r\n| where id in~ ({Workspace}) or \u0027value::all\u0027 in~ ({Workspace})\r\n| extend skuName = tostring(properties.sku.name), capacityReservationLevel = toint(properties.sku.capacityReservationLevel), lastSkuUpdate = todatetime(properties.sku.lastSkuUpdate)\r\n| extend daysSinceTierChange = iif(isnotempty(lastSkuUpdate), datetime_diff(\u0027day\u0027, now(), lastSkuUpdate), int(null))\r\n| project [\u0027Workspace\u0027] = name, [\u0027Current commitment tier\u0027] = case(skuName == \u0027CapacityReservation\u0027, strcat(tostring(capacityReservationLevel), \u0027 GB/day commitment\u0027), isnotempty(skuName), skuName, \u0027Unknown\u0027), [\u0027Days since tier last changed\u0027] = daysSinceTierChange\r\n| order by [\u0027Workspace\u0027] asc",
+ "size": 1,
+ "title": "Current commitment tier by workspace (auto-detected)",
+ "noDataMessage": "No workspace SKU information was found for the selected workspace scope.",
+ "noDataMessageStyle": 3,
"queryType": 1,
- "resourceType": "microsoft.resourcegraph/resources"
+ "resourceType": "microsoft.resourcegraph/resources",
+ "visualization": "table"
},
- "name": "parameters - 10",
- "conditionalVisibility": {
- "parameterName": "Total",
- "comparison": "isEqualTo",
- "value": "__never_display_soar_parameters__"
- }
+ "name": "CommitmentTierCurrent"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let selectedDays = max_of(datetime_diff(\u0027second\u0027, {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0);\r\nlet avgDailyGB = toreal(coalesce(toscalar(union withsource = SourceTableName * | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where _IsBillable == true | summarize sum(_BilledSize) / 1024.0 / 1024.0 / 1024.0 / selectedDays), 0.0));\r\nlet tierLevels = dynamic([100,200,300,400,500,1000,2000,5000]);\r\nprint AvgDailyIngestionGB = avgDailyGB, TierLevels = tierLevels\r\n| mv-expand TierLevel = TierLevels to typeof(int)\r\n| extend Eligible = TierLevel \u003e= AvgDailyIngestionGB\r\n| summarize RecommendedTierGBPerDay = minif(TierLevel, Eligible), MaxTierGBPerDay = max(TierLevel), AvgDailyIngestionGB = any(AvgDailyIngestionGB)\r\n| project [\u0027Average Billable Daily Ingestion (GB)\u0027] = round(AvgDailyIngestionGB, 2), [\u0027Recommended commitment tier\u0027] = iif(isnotempty(RecommendedTierGBPerDay), strcat(tostring(RecommendedTierGBPerDay), \u0027 GB/day\u0027), strcat(\u0027Above \u0027, tostring(MaxTierGBPerDay), \u0027 GB/day \u2014 review Enterprise Agreement options\u0027))",
+ "size": 1,
+ "title": "Recommended commitment tier based on {TimeRange} usage",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No billable ingestion was found in the selected time range.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "leftContent": {
+ "columnMatch": "Average Billable Daily Ingestion (GB)",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "blue"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ "rightContent": {
+ "columnMatch": "Recommended commitment tier",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "orangeBlue"
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "name": "CommitmentTierRecommendation"
+ },
+ {
+ "type": 1,
+ "content": {
+ "json": "## SOAR summary\r\n\r\nMicrosoft Sentinel playbooks use Azure Logic Apps to automate responses to incidents, alerts, and other security operations workflows. This section summarizes billable Logic App executions across accessible playbooks and estimates their execution cost using the **Logic App execution cost** input at the top of the workbook.\r\n\r\nTo populate this estimate, export the `TotalBillableExecutions` metric to the selected Log Analytics workspace and use the Analytics plan for the `AzureMetrics` table. Basic Logs tables cannot run this query. The estimate is not an invoice; use Azure Cost Management to validate billed charges.\r\n\r\nReview [Automate threat response with playbooks in Microsoft Sentinel](https://learn.microsoft.com/en-us/azure/sentinel/automation/automate-responses-with-playbooks) for playbook guidance. Because playbooks use Azure Logic Apps, additional charges can apply. Go to the [Azure Logic Apps](https://azure.microsoft.com/pricing/details/logic-apps/) pricing page for more details."
+ },
+ "name": "text - 3"
},
{
"type": 3,
From a2957e89ccca427d833a81487fff51246850056a Mon Sep 17 00:00:00 2001
From: Dr Bill Mcilhargey <19168174+billmcilhargey@users.noreply.github.com>
Date: Mon, 31 Aug 2026 11:38:13 -0400
Subject: [PATCH 3/6] Move Sentinel cost workbook enhancements into SOC
Handbook solution
Reverts Workbooks/SentinelCosts.json and Workbooks/WorkbooksMetadata.json to master. All enhancements now live in the SOC Handbook solution workbook (AzureSentinelCost.json), bumped to 3.0.8.
Structure: reorganized into 7 collapsible groups - Costing, Free Sentinel Data, E5 Benefits, Defender for Cloud Plan 2, Retention, Commitment Tiers, Data Lake. Parameters scoped per section; TimeRange/Workspace/Price remain global. Removed 10 hidden legacy placeholder items.
New sections: Free Sentinel Data (documented free tables, savings), Retention (>90 day billable retention costs), Commitment Tiers (auto-detected current tier plus usage-based suggestion), Data Lake (per-table storage cost from mirrored volume at documented 6:1 compression, plus manual-entry table for ingestion/processing/query/insights meters that are not observable from the workspace).
Behavior fixes: charts now derive bin size from the selected TimeRange (5m to 30d) instead of fixed daily bins; E5 and Defender P2 grant lines are prorated per interval rather than compared against a full-day allowance; commitment tier recommendation is withheld with a days-remaining countdown until 31 days of billable history exist; Logic App selector now emits concrete resource IDs (selected = Rank <= 10) instead of the value::all sentinel, which prevented the Azure Monitor metrics control from resolving scope.
Defect fixes in the existing workbook: removed 85 invisible U+202F characters embedded in KQL; resolved duplicate item name 'EstimateMdcPlan2Discount - Copy'; corrected 'Defedner' typo; replaced hardcoded \ Defender P2 license price with a DfSP2LicensePrice parameter; scoped the licensing savings query to TimeRange instead of scanning all data; set fallbackResourceIds to [] per workbook guidance; stripped en-us locale codes from 11 Microsoft documentation URLs.
Not included: Package/ artifacts are still at 3.0.7 and require regeneration via build-and-validate.ps1, which needs PowerShell 7 (only 5.1 is available locally).
---
.../Data/Solution_SOC Handbook.json | 2 +-
Solutions/SOC Handbook/ReleaseNotes.md | 1 +
.../Workbooks/AzureSentinelCost.json | 2420 +++++++++----
Workbooks/SentinelCosts.json | 3135 +++++------------
Workbooks/WorkbooksMetadata.json | 2 +-
5 files changed, 2789 insertions(+), 2771 deletions(-)
diff --git a/Solutions/SOC Handbook/Data/Solution_SOC Handbook.json b/Solutions/SOC Handbook/Data/Solution_SOC Handbook.json
index 8e9e9c253bb..861498f2173 100644
--- a/Solutions/SOC Handbook/Data/Solution_SOC Handbook.json
+++ b/Solutions/SOC Handbook/Data/Solution_SOC Handbook.json
@@ -20,7 +20,7 @@
],
"Metadata": "SolutionMetadata.json",
"BasePath": "C:\\GitHub\\azure-sentinel\\Solutions\\SOC Handbook",
- "Version": "3.0.7",
+ "Version": "3.0.8",
"TemplateSpec": true,
"Is1PConnector": false
}
\ No newline at end of file
diff --git a/Solutions/SOC Handbook/ReleaseNotes.md b/Solutions/SOC Handbook/ReleaseNotes.md
index ad0880f0638..a0a18e684cd 100644
--- a/Solutions/SOC Handbook/ReleaseNotes.md
+++ b/Solutions/SOC Handbook/ReleaseNotes.md
@@ -1,5 +1,6 @@
| **Version** | **Date Modified (DD-MM-YYYY)** | **Change History** |
|-------------|--------------------------------|-------------------------------------------------------------------------------------|
+| 3.0.8 | 31-08-2026 | Reorganized *AzureSentinelCost* **Workbook** into collapsible sections and added Free Sentinel Data, Retention, Commitment Tier, and Data Lake cost estimates. Charts now scale their time grain to the selected range, license grants are prorated per interval, the commitment tier recommendation is withheld with a countdown until 31 days of data are available, and Logic App scoping was corrected to use explicit resource IDs.|
| 3.0.7 | 21-07-2026 | Fixed bugs in *AnalyticsEfficiency* **Workbook** (typo fixes, added MITRE ATT&CK tactics, removed hardcoded timeContext overrides), rebranded 'Azure Sentinel' to 'Microsoft Sentinel' across *SentinelCentral*, *AzureSentinelSecurityAlerts*, and *AnalyticsEfficiency* **Workbooks**, fixed layout issues in *IntsightsIOCWorkbook*, and updated *MITREAttack* **Workbook** tactic mappings.|
| 3.0.6 | 13-01-2026 | Updated *IncidentOverview* **Workbook** to correct the incident render issue by using ProviderIncidentId with IncidentNumber|
| 3.0.5 | 24-09-2025 | Updated *SecurityOperationsEfficiency* to fix Mean time to triage |
diff --git a/Solutions/SOC Handbook/Workbooks/AzureSentinelCost.json b/Solutions/SOC Handbook/Workbooks/AzureSentinelCost.json
index 7e6889000ef..a40e03285ce 100644
--- a/Solutions/SOC Handbook/Workbooks/AzureSentinelCost.json
+++ b/Solutions/SOC Handbook/Workbooks/AzureSentinelCost.json
@@ -20,7 +20,7 @@
"type": 4,
"isRequired": true,
"value": {
- "durationMs": 7776000000
+ "durationMs": 604800000
},
"typeSettings": {
"selectableValues": [
@@ -80,15 +80,18 @@
"id": "67c2ce6e-ea54-4ae4-8343-3fcad8e53d1b",
"version": "KqlParameterItem/1.0",
"name": "Workspace",
+ "label": "Workspaces (all sections)",
"type": 5,
"isRequired": true,
+ "description": "Select the Microsoft Sentinel workspaces used throughout the workbook, including the observed table-usage context in the Data Lake section. All accessible workspaces are selected by default.",
"multiSelect": true,
"quote": "'",
"delimiter": ",",
- "query": "resources | where type =~ 'Microsoft.operationsmanagement/solutions' | where name contains 'SecurityInsights' | project id = tostring(properties.workspaceResourceId)",
+ "query": "resources | where type =~ 'Microsoft.operationsmanagement/solutions' | where name contains 'SecurityInsights' | extend workspaceResourceId = tostring(properties.workspaceResourceId) | join kind=leftouter (resources | where type =~ 'Microsoft.OperationalInsights/workspaces' | project workspaceResourceId = id, workspaceName = name) on workspaceResourceId | project value = workspaceResourceId, label = coalesce(workspaceName, workspaceResourceId)",
"crossComponentResources": [
"value::all"
],
+ "defaultValue": "value::all",
"value": [
"value::all"
],
@@ -111,97 +114,58 @@
"name": "Price",
"label": "Ingestion price",
"type": 1,
- "value": "4.3",
- "description": "Enter your ingestion price per GB (PAYG or Commitment Tier). Combine the cost of log analytics and sentinel ingestion for the region. Use Azure Pricing Calculator to find current pricing. Sentinel table by default is 'Analytic', not Basic. Equation is: LAW+Sentinel (ingestion by region and tier)."
- },
- {
- "id": "9d5299d0-36a0-4666-9803-ca6931bdaab7",
- "version": "KqlParameterItem/1.0",
- "name": "RetentionPrice",
- "label": "Retention price",
- "type": 1,
- "description": "Enter the retention price per GB/month that will be used in this workbook's calculations",
- "value": "0.1"
- },
- {
- "id": "67494f3e-322e-4411-9b45-1cbea03ed618",
- "version": "KqlParameterItem/1.0",
- "name": "TotalE5Seats",
- "label": "Total seats (E5/A5/F5/G5)",
- "type": 1,
- "description": "Enter the total number of Microsoft 365 E5, A5, F5, G5 and Microsoft 365 E5, A5, F5, G5 Security licenses in your environment"
- },
- {
- "id": "3c0ef385-0db2-4f4b-a04c-a8a8fea6c2f5",
- "version": "KqlParameterItem/1.0",
- "name": "TotalMdcPlan2",
- "label": "Total Defender for Servers Plan 2",
- "type": 1,
- "description": "Enter the total number Defender for Servers Plan 2 servers"
+ "description": "Enter your ingestion price per GB (PAYG or Commitment Tier). You can also refer to Azure Pricing Calculator.",
+ "typeSettings": {
+ "paramValidationRules": [
+ {
+ "regExp": "^(0|[1-9][0-9]*)(\\.[0-9]+)?$",
+ "match": true,
+ "message": "Enter a non-negative price."
+ }
+ ]
+ },
+ "value": "4"
}
],
"style": "pills",
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces"
},
- "name": "parameters - 5"
- },
- {
- "type": 1,
- "content": {
- "json": "## Ingestion and Retention Summary"
- },
- "name": "text - 2"
+ "name": "parameters - global"
},
{
"type": 12,
"content": {
"version": "NotebookGroup/1.0",
"groupType": "editable",
+ "title": "Costing",
+ "expandable": true,
+ "expanded": true,
"items": [
+ {
+ "type": 1,
+ "content": {
+ "json": "## Workspace Ingestion summary"
+ },
+ "name": "text - ingestion summary"
+ },
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "union withsource=TableName1 * | where TimeGenerated < ago(90d) | extend key = 'Key' | summarize size = sum(_BilledSize)/1024/1024/1024 by key\r\n| project ['Data over 90 days'] = size, ['Retention Cost'] = size*{RetentionPrice}\r\n\r\n\r\n",
- "size": 4,
- "title": "Data older than 90 days and resulting retention cost",
- "noDataMessage": "You have no data older than 90 days",
- "noDataMessageStyle": 3,
+ "query": "let selectedDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); union withsource = SourceTableName * | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where _IsBillable == true | summarize ['Workspace Average Billable Daily Ingestion'] = sum(_BilledSize) / 1024.0 / 1024.0 / 1024.0 / selectedDays",
+ "size": 1,
+ "title": "Workspace Average Billable Daily Ingestion",
+ "timeContextFromParameter": "TimeRange",
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
"{Workspace}"
],
"visualization": "tiles",
- "gridSettings": {
- "formatters": [
- {
- "columnMatch": "Data over 90 days",
- "formatter": 0,
- "numberFormat": {
- "unit": 36,
- "options": {
- "style": "decimal",
- "useGrouping": false
- }
- }
- },
- {
- "columnMatch": "Retention Cost",
- "formatter": 0,
- "numberFormat": {
- "unit": 0,
- "options": {
- "style": "decimal"
- }
- }
- }
- ]
- },
"tileSettings": {
- "leftContent": {
- "columnMatch": "Data over 90 days",
+ "titleContent": {
+ "columnMatch": "Workspace Average Billable Daily Ingestion",
"formatter": 12,
"formatOptions": {
"palette": "greenRed"
@@ -210,21 +174,6 @@
"unit": 39,
"options": {
"style": "decimal",
- "maximumFractionDigits": 1
- }
- }
- },
- "rightContent": {
- "columnMatch": "Retention Cost",
- "formatter": 12,
- "formatOptions": {
- "palette": "greenRed"
- },
- "numberFormat": {
- "unit": 0,
- "options": {
- "currency": "USD",
- "style": "currency",
"maximumFractionDigits": 2
}
}
@@ -233,16 +182,16 @@
"size": "auto"
}
},
- "customWidth": "33",
- "name": "query - 7"
+ "name": "query - 6",
+ "customWidth": "25"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "union withsource = tt *\r\n| where TimeGenerated > startofday({TimeRange:start}) and TimeGenerated < startofday({TimeRange:end})\r\n// Only look at chargeable Tables\r\n| where _IsBillable == True\r\n| summarize TotalGBytes =round(sum(_BilledSize/(1024*1024*1024)),2) by bin(TimeGenerated, 1d)//, Solution=tt\r\n| summarize ['GBs/day'] =round(avg(TotalGBytes),2)",
- "size": 4,
- "title": "Average billable GBs/day ingested in the last {TimeRange}",
+ "query": "let selectedDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); union withsource = SourceTableName * | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where _IsBillable == true | summarize ['Estimated Average Daily Ingestion Cost'] = sum(_BilledSize) / 1024.0 / 1024.0 / 1024.0 / selectedDays * todouble('{Price}')",
+ "size": 1,
+ "title": "Estimated Daily Ingestion Cost",
"timeContextFromParameter": "TimeRange",
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
@@ -252,26 +201,34 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "GBs/day",
+ "columnMatch": "Estimated Average Daily Ingestion Cost",
"formatter": 12,
"formatOptions": {
"palette": "greenRed"
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency",
+ "maximumFractionDigits": 2
+ }
}
},
"showBorder": false,
"size": "auto"
}
},
- "customWidth": "33",
- "name": "query - 6"
+ "name": "AverageDailyBillableIngestionCost",
+ "customWidth": "25"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "Usage\r\n| where IsBillable == true\r\n| summarize size = sum(Quantity)/1024 by IsBillable\r\n| project ['Total data ingestion'] = size, ['Estimated cost'] = size*{Price}",
- "size": 4,
- "title": "Total billable ingestion and cost in the last {TimeRange}",
+ "query": "Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true | summarize ['Workspace Billable Ingestion'] = sum(Quantity) / 1024.0",
+ "size": 1,
+ "title": "Workspace Billable Ingestion: {TimeRange}",
"timeContextFromParameter": "TimeRange",
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
@@ -281,24 +238,7 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "formatter": 12,
- "formatOptions": {
- "palette": "greenRed",
- "compositeBarSettings": {
- "labelText": ""
- }
- },
- "numberFormat": {
- "unit": 0,
- "options": {
- "currency": "USD",
- "style": "currency",
- "useGrouping": false
- }
- }
- },
- "leftContent": {
- "columnMatch": "Total data ingestion",
+ "columnMatch": "Workspace Billable Ingestion",
"formatter": 12,
"formatOptions": {
"palette": "greenRed"
@@ -312,8 +252,30 @@
}
}
},
- "rightContent": {
- "columnMatch": "Estimated cost",
+ "showBorder": false,
+ "size": "auto"
+ }
+ },
+ "name": "query - 8",
+ "customWidth": "25"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true | summarize TotalBillableIngestionGB = sum(Quantity) / 1024.0 | project ['Estimated Ingestion Cost'] = TotalBillableIngestionGB * todouble('{Price}')",
+ "size": 1,
+ "title": "Estimated Ingestion Cost: {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "Estimated Ingestion Cost",
"formatter": 12,
"formatOptions": {
"palette": "greenRed"
@@ -323,188 +285,101 @@
"options": {
"currency": "USD",
"style": "currency",
- "useGrouping": false,
- "maximumFractionDigits": 1
+ "maximumFractionDigits": 2
}
}
},
- "showBorder": false,
- "size": "auto"
- }
- },
- "customWidth": "33",
- "name": "query - 8"
- }
- ]
- },
- "name": "Costing"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let Categories = datatable(Type:string,Category:string)\r\n[\r\n\"AuditLogs\" , \"Azure Active Directory\",\r\n\"SigninLogs\" , \"Azure Active Directory\",\r\n\"AADNonInteractiveUserSignInLogs\" , \"Azure Active Directory\",\r\n\"AADRiskyUsers\" , \"Azure Active Directory\",\r\n\"AADRiskyServicePrincipals\" , \"Azure Active Directory\",\r\n\"AADServicePrincipalRiskEvents\" , \"Azure Active Directory\",\r\n\"ADFSSignInLogs\" , \"Azure Active Directory\",\r\n\"NetworkAccessTraffic\" , \"Azure Active Directory\",\r\n\"AADUserRiskEvents\" , \"Azure Active Directory\",\r\n\"AADServicePrincipalSignInLogs\" , \"Azure Active Directory\",\r\n\"AADManagedIdentitySignInLogs\" , \"Azure Active Directory\",\r\n\"AADProvisioningLogs\" , \"Azure Active Directory\",\r\n\"AZFWApplicationRule\" , \"Firewall\",\r\n\"AZFWApplicationRuleAggregation\" , \"Firewall\",\r\n\"AZFWDnsQuery\" , \"Firewall\",\r\n\"AZFWIdpsSignature\" , \"Firewall\",\r\n\"AZFWNatRule\" , \"Firewall\",\r\n\"AZFWNatRuleAggregation\" , \"Firewall\",\r\n\"AZFWNetworkRule\" , \"Firewall\",\r\n\"AZFWNetworkRuleAggregation\" , \"Firewall\",\r\n\"WindowsFirewall\" , \"Firewall\",\r\n\"Event\" , \"Custom Events\",\r\n\"BehaviorAnalytics\" , \"User Entity Behavior Analytics\",\r\n\"UserPeerAnalytics\" , \"User Entity Behavior Analytics\",\r\n\"UserAccessAnalytics\" , \"User Entity Behavior Analytics\",\r\n\"IdentityInfo\" , \"User Entity Behavior Analytics\",\r\n\"DeviceLogonEvents\" , \"Microsoft Defender for Endpoint\",\r\n\"DeviceEvents\" , \"Microsoft Defender for Endpoint\",\r\n\"DeviceNetworkInfo\" , \"Microsoft Defender for Endpoint\",\r\n\"DeviceImageLoadEvents\" , \"Microsoft Defender for Endpoint\",\r\n\"DeviceFileEvents\" , \"Microsoft Defender for Endpoint\",\r\n\"DeviceInfo\" , \"Microsoft Defender for Endpoint\",\r\n\"DeviceProcessEvents\" , \"Microsoft Defender for Endpoint\",\r\n\"DeviceNetworkEvents\" , \"Microsoft Defender for Endpoint\",\r\n\"DeviceRegistryEvents\" , \"Microsoft Defender for Endpoint\",\r\n\"DeviceFileCertificateInfo\" , \"Microsoft Defender for Endpoint\",\r\n\"EmailAttachmentInfo\" , \"Microsoft Defender for Office 365\",\r\n\"EmailEvents\" , \"Microsoft Defender for Office 365\",\r\n\"EmailPostDeliveryEvents\" , \"Microsoft Defender for Office 365\",\r\n\"EmailUrlInfo\" , \"Microsoft Defender for Office 365\",\r\n\"IdentityLogonEvents\" , \"Microsoft Defender for Identity\",\r\n\"IdentityQueryEvents\" , \"Microsoft Defender for Identity\",\r\n\"IdentityDirectoryEvents\" , \"Microsoft Defender for Identity\",\r\n\"CloudAppEvents\" , \"Microsoft Defender for Cloud Apps\",\r\n\"AlertEvidence\" , \"Microsoft Defender Alert Evidence\",\r\n\"InsightsMetrics\" , \"Azure Monitor for VMs\",\r\n\"VMBoundPort\" , \"Azure Monitor for VMs\",\r\n\"VMComputer\" , \"Azure Monitor for VMs\",\r\n\"VMConnection\" , \"Azure Monitor for VMs\",\r\n\"VMProcess\" , \"Azure Monitor for VMs\",\r\n\"SecurityEvent\" , \"Windows Security Events\",\r\n\"StorageBlobLogs\" , \"Azure Storage\",\r\n\"StorageFileLogs\" , \"Azure Storage\",\r\n\"Syslog\" , \"Syslog/CEF\",\r\n\"SecurityIoTRawEvent\" , \"IoT Logs\",\r\n\"CommonSecurityLog\" , \"Syslog/CEF\",\r\n\"ThreatIntelligenceIndicator\" , \"Sentinel\",\r\n\"DnsEvents\" , \"DNS Logs\",\r\n\"DnsInventory\" , \"DNS Logs\",\r\n\"AWSCloudTrail\" , \"AWS Logs\",\r\n\"AWSVPCFlow\" , \"AWS Logs\",\r\n\"ConfigurationChange\" , \"Change Tracking\",\r\n\"ConfigurationData\" , \"Change Tracking\",\r\n\"AzureDiagnostics\" , \"Azure Resources\",\r\n\"AzureActivity\" , \"Azure Resources\",\r\n\"LAQueryLogs\" , \"Management\",\r\n\"SentinelHealth\" , \"Sentinel\",\r\n\"Perf\" , \"Performance\",\r\n\"AzureMetrics\" , \"Azure Metrics\",\r\n\"SecurityNestedRecommendation\" , \"Microsoft Defender for Cloud\",\r\n\"SecurityRecommendation\" , \"Microsoft Defender for Cloud\",\r\n\"SecurityRegulatoryCompliance\" , \"Microsoft Defender for Cloud\",\r\n\"SecureScoreControls\" , \"Microsoft Defender for Cloud\",\r\n\"SecurityBaseline\" , \"Microsoft Defender for Cloud\",\r\n\"SecureScores\" , \"Microsoft Defender for Cloud\",\r\n\"Update\" , \"Update Management\",\r\n\"UpdateSummary\" , \"Update Management\",\r\n\"DeviceTvmSecureConfigurationAssessment\" , \"Microsoft Defender Vuln. Management\",\r\n\"DeviceTvmSoftwareVulnerabilities\" , \"Microsoft Defender Vuln. Management\",\r\n\"DeviceTvmSoftwareInventory\" , \"Microsoft Defender Vuln. Management\",\r\n\"UrlClickEvents\" , \"Microsoft Defender for Office 365\",\r\n\"SecurityBaselineSummary\" , \"Microsoft Defender for Cloud\",\r\n\"AZFWThreatIntel\" , \"Firewall\",\r\n\"AWSGuardDuty\" , \"AWS Logs\",\r\n\"Watchlist\" , \"Sentinel\",\r\n\"HuntingBookmark\" , \"Sentinel\",\r\n\"SentinelAudit\" , \"Sentinel\",\r\n\"Operation\" , \"Log Management\",\r\n\"StorageTableLogs\" , \"Azure Storage\",\r\n\"AddonAzureBackupStorage\" , \"Azure Storage\",\r\n\"AddonAzureBackupPolicy\" , \"Azure Storage\",\r\n\"StorageQueueLogs\" , \"Azure Storage\",\r\n\"AddonAzureBackupProtectedInstance\" , \"Azure Storage\",\r\n\"AddonAzureBackupJobs\" , \"Azure Storage\"\r\n];\r\nlet customTables = Usage\r\n| where IsBillable == true\r\n| where DataType contains \"_CL\"\r\n| summarize size = sum(Quantity)/1024 by DataType\r\n| project ['Log Type'] = \"Custom Log\",['Table'] = DataType, ['Table Size'] = size, ['Estimated cost'] = size*4.3;\r\nlet AzDiagTables = AzureDiagnostics\r\n| summarize TotalIngestBytes=sum(_BilledSize) by Category\r\n| project ['Log Type'] = \"AzureDiagnostics\", ['Table'] = Category ,['Table Size'] = TotalIngestBytes/1024000000 , ['Estimated cost'] = (TotalIngestBytes/1024000000 ) * 4.3;\r\nlet knownTables = Usage\r\n| where IsBillable == true \r\n| where DataType <> \"AzureDiagnostics\"\r\n| join kind=leftouter Categories on $left.DataType == $right.Type\r\n| summarize size =sumif(Quantity, isnotempty(Category))/1024, sizeOther= sumif(Quantity,(isempty(Category) and DataType !contains \"_CL\"))/1024 by Category, DataType\r\n| project ['Log Type'] = iif(isnotempty( Category),Category,\"Other\"), ['Table'] = DataType, ['Table Size'] = iif(isnotempty( Category),size,sizeOther), ['Estimated cost'] = iif(isnotempty(Category),size*4.3,sizeOther*4.3);\r\nunion customTables, knownTables, AzDiagTables\r\n| sort by ['Estimated cost'] desc",
- "size": 2,
- "title": "Breakdown of billable ingestion by log category in the last {TimeRange}",
- "timeContextFromParameter": "TimeRange",
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "table",
- "gridSettings": {
- "formatters": [
- {
- "columnMatch": "Log Type",
- "formatter": 5
- },
- {
- "columnMatch": "Table",
- "formatter": 5
- },
- {
- "columnMatch": "Table Size",
- "formatter": 3,
- "formatOptions": {
- "palette": "greenRed",
- "aggregation": "Sum"
- },
- "numberFormat": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "useGrouping": false
- }
- }
- },
- {
- "columnMatch": "Estimated cost",
- "formatter": 0,
- "formatOptions": {
- "aggregation": "Sum"
- },
- "numberFormat": {
- "unit": 0,
- "options": {
- "currency": "USD",
- "style": "currency"
- }
- }
- }
- ],
- "hierarchySettings": {
- "treeType": 1,
- "groupBy": [
- "Log Type"
- ],
- "finalBy": "Table"
- }
- },
- "graphSettings": {
- "type": 0,
- "topContent": {
- "columnMatch": "Log Category",
- "formatter": 1
- },
- "centerContent": {
- "columnMatch": "Billed Size",
- "formatter": 1,
- "numberFormat": {
- "unit": 17,
- "options": {
- "maximumSignificantDigits": 3,
- "maximumFractionDigits": 2
+ "showBorder": false
}
- }
- }
- }
- },
- "name": "query - 2"
- },
- {
- "type": 12,
- "content": {
- "version": "NotebookGroup/1.0",
- "groupType": "editable",
- "items": [
- {
- "type": 1,
- "content": {
- "json": "## Microsoft Sentinel benefit for Microsoft 365 E5, A5, F5 and G5 customers\r\n\r\nWith security information and event management (SIEM) and extended detection and response (XDR) from Microsoft, you’re armed with the context and automation you need to stop sophisticated, cross-domain attacks across your entire organization. \r\n\r\nMicrosoft 365 E5, A5, F5, G5 and Microsoft 365 E5, A5, F5, G5 Security customers can get data grant up to 5MB per user/day of Microsoft 365 data ingestion into Microsoft Sentinel.
\r\nThe data sources included in this offer include:\r\n\r\n- Microsoft Entra ID sign-in and audit logs\r\n- Microsoft Cloud App Security shadow IT discovery logs\r\n- Microsoft Information Protection logs\r\n- Microsoft 365 advanced hunting data\r\n\r\nThe data grant will be calculated at the end of the month and applied to your bill, covering the cost of up to 5 MB of data ingestion per user/day.\r\n\r\nVisit https://azure.microsoft.com/offers/sentinel-microsoft-365-offer/ for more information\r\n\r\n
\r\n\r\n### Below are the ingestion for the eligible data sources:\r\n\r\n_**Note:** Kindly specify **Total seats (E5/A5/F5/G5)** and **Ingestion Price** parameters for calculation._"
},
- "name": "text - 12"
+ "name": "BillableIngestionCost",
+ "customWidth": "25"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "Usage\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\",  \r\n\"DeviceFileEvents\",  \r\n\"DeviceImageLoadEvents\",  \r\n\"DeviceInfo\",  \r\n\"DeviceLogonEvents\",  \r\n\"DeviceNetworkEvents\",  \r\n\"DeviceNetworkInfo\",  \r\n\"DeviceProcessEvents\",  \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\",  \r\n\"EmailAttachmentInfo\",  \r\n\"EmailEvents\",  \r\n\"EmailPostDeliveryEvents\",  \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\"\r\n)   \r\n| summarize BillableDataGB = sum(Quantity) / 1000. by DataType\r\n| order by BillableDataGB desc\r\n",
- "size": 0,
+ "query": "let Categories = datatable(Type:string,Category:string)\r\n[\r\n \"AuditLogs\", \"Azure Active Directory\",\r\n \"SigninLogs\", \"Azure Active Directory\",\r\n \"AADNonInteractiveUserSignInLogs\", \"Azure Active Directory\",\r\n \"AADServicePrincipalSignInLogs\", \"Azure Active Directory\",\r\n \"AADManagedIdentitySignInLogs\", \"Azure Active Directory\",\r\n \"AADProvisioningLogs\",\"Azure Active Directory\",\r\n \"BehaviorAnalytics\", \"User Entity Behavior Analytics\",\r\n \"UserPeerAnalytics\",\"User Entity Behavior Analytics\",\r\n \"UserAccessAnalytics\",\"User Entity Behavior Analytics\",\r\n \"IdentityInfo\",\"User Entity Behavior Analytics\",\r\n \"DeviceLogonEvents\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceEvents\",\"Microsoft Defender for Endpoint\",\r\n\t\"DeviceNetworkInfo\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceImageLoadEvents\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceFileEvents\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceInfo\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceProcessEvents\", \"Microsoft Defender for Endpoint\",\t\r\n\t\"DeviceNetworkEvents\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceRegistryEvents\", \"Microsoft Defender for Endpoint\",\r\n \"DeviceFileCertificateInfo\", \"Microsoft Defender for Endpoint\",\r\n \"EmailAttachmentInfo\", \"Microsoft Defender for Office 365\", \r\n \"EmailEvents\", \"Microsoft Defender for Office 365\", \r\n \"EmailPostDeliveryEvents\", \"Microsoft Defender for Office 365\", \r\n \"EmailUrlInfo\", \"Microsoft Defender for Office 365\",\r\n \"IdentityLogonEvents\", \"Microsoft Defender for Identity\",\r\n \"IdentityQueryEvents\", \"Microsoft Defender for Identity\",\r\n \"IdentityDirectoryEvents\", \"Microsoft Defender for Identity\",\r\n \"CloudAppEvents\", \"Microsoft Defender for Cloud Apps\",\r\n \"AlertEvidence\", \"Microsoft Defender Alert Evidence\",\r\n \"InsightsMetrics\", \"Azure Monitor for VMs\",\r\n \"VMBoundPort\", \"Azure Monitor for VMs\",\r\n \"VMComputer\", \"Azure Monitor for VMs\",\r\n \"VMConnection\", \"Azure Monitor for VMs\",\r\n \"VMProcess\", \"Azure Monitor for VMs\",\r\n \"SecurityEvent\", \"Windows Security Events\",\r\n \"Syslog\", \"Syslog/CEF\",\r\n \"CommonSecurityLog\", \"Syslog/CEF\",\r\n \"ThreatIntelligenceIndicator\", \"Threat Intelligence\",\r\n \"DnsEvents\", \"DNS Logs\",\r\n \"DnsInventory\", \"DNS Logs\",\r\n \"AWSCloudTrail\", \"AWS Cloud Trail\",\r\n \"ConfigurationChange\", \"Change Tracking\",\r\n \"ConfigurationData\", \"Change Tracking\",\r\n \"AzureDiagnostics\", \"Azure Resources\",\r\n \"LAQueryLogs\", \"Management\",\r\n \"SentinelHealth\",\"Management\",\r\n \"Perf\",\"Performance\",\r\n \"AzureMetrics\",\"Azure Metrics\",\r\n \"SecurityNestedRecommendation\", \"Microsoft Defender for Cloud\",\r\n \"SecurityRecommendation\", \"Microsoft Defender for Cloud\",\r\n \"SecurityRegulatoryCompliance\", \"Microsoft Defender for Cloud\",\r\n \"SecureScoreControls\", \"Microsoft Defender for Cloud\",\r\n \"SecurityBaseline\", \"Microsoft Defender for Cloud\",\r\n \"SecureScores\", \"Microsoft Defender for Cloud\",\r\n \"Update\", \"Update Management\",\r\n \"UpdateSummary\", \"Update Management\"\r\n];\r\nlet customTables = Usage\r\n| where TimeGenerated between ({TimeRange:start} .. {TimeRange:end})\r\n| where IsBillable == true\r\n| where DataType contains \"_CL\"\r\n| summarize size = sum(Quantity)/1024 by DataType\r\n| project ['Log Type'] = DataType, ['Table Size'] = size, ['Estimated Cost'] = size*{Price};\r\nlet knownTables = Usage\r\n| where TimeGenerated between ({TimeRange:start} .. {TimeRange:end})\r\n| where IsBillable == true \r\n| join kind=leftouter Categories on $left.DataType == $right.Type\r\n| summarize size =sumif(Quantity, isnotempty(Category))/1024, sizeOther= sumif(Quantity,(isempty(Category) and DataType !contains \"_CL\"))/1024 by Category\r\n| project ['Log Type'] = iif(isnotempty( Category),Category,\"Other\"), ['Table Size'] = iif(isnotempty( Category),size,sizeOther), ['Estimated Cost'] = iif(isnotempty(Category),size*{Price},sizeOther*4);\r\nunion customTables, knownTables\r\n| order by ['Table Size'] desc",
+ "size": 1,
+ "title": "Breakdown of Workspace billable ingestion by log category in the {TimeRange}",
"timeContextFromParameter": "TimeRange",
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
"{Workspace}"
],
+ "visualization": "table",
"gridSettings": {
"formatters": [
{
- "columnMatch": "BillableDataGB",
+ "columnMatch": "Log Type",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "2fr"
+ }
+ },
+ {
+ "columnMatch": "Table Size",
"formatter": 3,
"formatOptions": {
- "palette": "blue"
+ "palette": "greenRed",
+ "customColumnWidthSetting": "1fr"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "useGrouping": false
+ }
+ }
+ },
+ {
+ "columnMatch": "Estimated Cost",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "1fr"
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency"
+ }
}
}
]
- }
- },
- "name": "query - 13"
- },
- {
- "type": 1,
- "content": {
- "json": "
\r\n**Daily ingestion size (for eligible data sources) vs Maximum data grant:**"
- },
- "conditionalVisibilities": [
- {
- "parameterName": "TotalE5Seats",
- "comparison": "isNotEqualTo",
- "value": "0"
},
- {
- "parameterName": "TotalE5Seats",
- "comparison": "isNotEqualTo"
+ "graphSettings": {
+ "type": 0,
+ "topContent": {
+ "columnMatch": "Log Category",
+ "formatter": 1
+ },
+ "centerContent": {
+ "columnMatch": "Billed Size",
+ "formatter": 1,
+ "numberFormat": {
+ "unit": 17,
+ "options": {
+ "maximumSignificantDigits": 3,
+ "maximumFractionDigits": 2
+ }
+ }
+ }
}
- ],
- "name": "text - DailyIngestionVsAllocation"
- },
- {
- "type": 1,
- "content": {
- "json": "
\r\n**Daily ingestion size (for eligible data sources) vs Maximum data grant:**"
},
- "conditionalVisibilities": [
- {
- "parameterName": "TotalE5Seats",
- "comparison": "isNotEqualTo",
- "value": "0"
- },
- {
- "parameterName": "TotalE5Seats",
- "comparison": "isNotEqualTo"
- }
- ],
- "name": "text - DailyIngestionVsAllocation - Copy"
+ "name": "query - 2"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "Usage\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\",  \r\n\"DeviceFileEvents\",  \r\n\"DeviceImageLoadEvents\",  \r\n\"DeviceInfo\",  \r\n\"DeviceLogonEvents\",  \r\n\"DeviceNetworkEvents\",  \r\n\"DeviceNetworkInfo\",  \r\n\"DeviceProcessEvents\",  \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\",  \r\n\"EmailAttachmentInfo\",  \r\n\"EmailEvents\",  \r\n\"EmailPostDeliveryEvents\",  \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\")   \r\n| summarize DailyIngestionGB = toreal(sum(Quantity))/ 1024 by format_datetime(TimeGenerated, 'yyyy-MM-dd') \r\n| extend MaxDataGrantGB = ((5*toreal({TotalE5Seats}))/1024)\r\n| sort by TimeGenerated asc\r\n",
- "size": 0,
- "aggregation": 3,
+ "query": "let selectedDuration = {TimeRange:end} - {TimeRange:start}; let timeGrain = case(selectedDuration <= 1h, 5m, selectedDuration <= 4h, 15m, selectedDuration <= 1d, 1h, selectedDuration <= 7d, 6h, selectedDuration <= 31d, 1d, selectedDuration <= 90d, 7d, 30d); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true | summarize ['Workspace Billable Ingestion Size'] = sum(Quantity) / 1024.0 by bin(TimeGenerated, timeGrain) | order by TimeGenerated asc",
+ "size": 1,
+ "title": "Workspace Billable Ingestion Size in the {TimeRange}",
"timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No billable ingestion was found in the selected time range.",
+ "noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
@@ -516,37 +391,47 @@
"showDataPoints": true,
"ySettings": {
"numberFormatSettings": {
- "unit": 0,
+ "unit": 39,
"options": {
"style": "decimal",
- "useGrouping": true,
"maximumFractionDigits": 3
}
}
}
}
},
- "conditionalVisibilities": [
- {
- "parameterName": "TotalE5Seats",
- "comparison": "isNotEqualTo"
- },
- {
- "parameterName": "TotalE5Seats",
- "comparison": "isNotEqualTo",
- "value": "0"
- }
- ],
- "name": "DailyIngestionVSAllocation"
+ "name": "WorkspaceBillableIngestionSizeTrend"
+ }
+ ]
+ },
+ "name": "group - Costing"
+ },
+ {
+ "type": 12,
+ "content": {
+ "version": "NotebookGroup/1.0",
+ "groupType": "editable",
+ "title": "Free Sentinel Data",
+ "expandable": true,
+ "expanded": true,
+ "items": [
+ {
+ "type": 1,
+ "content": {
+ "json": "## Free Sentinel Data Summary\r\n\r\nMicrosoft documents the following Sentinel data sources as free:\r\n\r\n- Azure Activity Logs (`AzureActivity`)\r\n- Health monitoring for Microsoft Sentinel (`SentinelHealth`)\r\n- Microsoft 365 audit activity (`OfficeActivity`)\r\n- Microsoft Entra ID Protection alerts (`SecurityAlert`)\r\n- Microsoft Defender for Cloud and Defender for IoT alerts (`SecurityAlert`)\r\n- Microsoft Defender XDR incidents and alerts (`SecurityIncident`, `SecurityAlert`)\r\n- Microsoft Defender for Endpoint, Identity, Cloud Apps, and Office 365 alerts (`SecurityAlert`)\r\n\r\nThis section estimates Analytics-tier ingestion in the selected workspace scope and keeps it separate from billable ingestion. It does not estimate data lake-only ingestion, storage, processing, or query charges. Usage is grouped by table and cannot reliably identify the originating connector, so `SecurityAlert` cannot be allocated reliably among its contributing services. This estimate does not calculate the separate Sentinel free trial. Review the [Microsoft Sentinel free data sources](https://learn.microsoft.com/azure/sentinel/billing?tabs=simplified%2Ccommitment-tiers#free-data-sources) documentation for current eligibility and billing terms."
+ },
+ "name": "text - free Sentinel data"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "Usage\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\",  \r\n\"DeviceFileEvents\",  \r\n\"DeviceImageLoadEvents\",  \r\n\"DeviceInfo\",  \r\n\"DeviceLogonEvents\",  \r\n\"DeviceNetworkEvents\",  \r\n\"DeviceNetworkInfo\",  \r\n\"DeviceProcessEvents\",  \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\",  \r\n\"EmailAttachmentInfo\",  \r\n\"EmailEvents\",  \r\n\"EmailPostDeliveryEvents\",  \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\"\r\n)   \r\n| summarize TotalBillableDataGB = sum(Quantity) / 1024\r\n\r\n",
- "size": 4,
- "title": "Total ingestion",
+ "query": "let freeTypes = dynamic([\"AzureActivity\",\"SentinelHealth\",\"OfficeActivity\",\"SecurityAlert\",\"SecurityIncident\"]); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where DataType in (freeTypes) | summarize ['Average Free Data Per Day'] = sum(Quantity) / 1024.0 / periodDays",
+ "size": 1,
+ "title": "Average Free Data Per Day",
"timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No documented free Sentinel data was observed in the selected time range.",
+ "noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
@@ -555,33 +440,35 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "TotalBillableDataGB",
+ "columnMatch": "Average Free Data Per Day",
"formatter": 12,
"formatOptions": {
- "palette": "greenRed"
+ "palette": "blue"
},
"numberFormat": {
"unit": 39,
"options": {
"style": "decimal",
- "maximumFractionDigits": 2
+ "maximumFractionDigits": 3
}
}
},
"showBorder": false
}
},
- "customWidth": "20",
- "name": "E5IngestionSize"
+ "customWidth": "25",
+ "name": "FreeSentinelDataTotal"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let DailyMaxDiscountGB = ((5*toreal({TotalE5Seats}))/1024);\r\nUsage\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\",  \r\n\"DeviceFileEvents\",  \r\n\"DeviceImageLoadEvents\",  \r\n\"DeviceInfo\",  \r\n\"DeviceLogonEvents\",  \r\n\"DeviceNetworkEvents\",  \r\n\"DeviceNetworkInfo\",  \r\n\"DeviceProcessEvents\",  \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\",  \r\n\"EmailAttachmentInfo\",  \r\n\"EmailEvents\",  \r\n\"EmailPostDeliveryEvents\",  \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\")   \r\n| summarize DailyBillableGB = toreal(sum(Quantity))/ 1024 by format_datetime(TimeGenerated, 'yy-MM-dd') \r\n| extend DailyMaxGrantGB = DailyMaxDiscountGB\r\n| summarize MaxDataGrantGB = sum(toreal(DailyMaxGrantGB))\r\n\r\n",
- "size": 4,
- "title": "Total Data Grant Limit",
+ "query": "let freeTypes = dynamic([\"AzureActivity\",\"SentinelHealth\",\"OfficeActivity\",\"SecurityAlert\",\"SecurityIncident\"]); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where DataType in (freeTypes) | summarize ['Estimated Free Data Savings Per Day'] = sum(Quantity) / 1024.0 / periodDays * todouble('{Price}')",
+ "size": 1,
+ "title": "Avg Daily Free Data Savings",
"timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No documented free Sentinel data was observed in the selected time range.",
+ "noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
@@ -590,45 +477,36 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "MaxDataGrantGB",
+ "columnMatch": "Estimated Free Data Savings Per Day",
"formatter": 12,
"formatOptions": {
- "palette": "orangeBlue"
+ "palette": "greenRed"
},
"numberFormat": {
- "unit": 39,
+ "unit": 0,
"options": {
- "style": "decimal",
+ "currency": "USD",
+ "style": "currency",
"maximumFractionDigits": 2
}
}
},
- "showBorder": false,
- "sortOrderField": 1
+ "showBorder": false
}
},
- "customWidth": "20",
- "conditionalVisibilities": [
- {
- "parameterName": "TotalE5Seats",
- "comparison": "isNotEqualTo"
- },
- {
- "parameterName": "TotalE5Seats",
- "comparison": "isNotEqualTo",
- "value": "0"
- }
- ],
- "name": "DataGrantLimit"
+ "customWidth": "25",
+ "name": "AverageDailyFreeDataSavings"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let DailyMaxDiscountGB = ((5*toreal({TotalE5Seats}))/1024);\r\nUsage\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\",  \r\n\"DeviceFileEvents\",  \r\n\"DeviceImageLoadEvents\",  \r\n\"DeviceInfo\",  \r\n\"DeviceLogonEvents\",  \r\n\"DeviceNetworkEvents\",  \r\n\"DeviceNetworkInfo\",  \r\n\"DeviceProcessEvents\",  \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\",  \r\n\"EmailAttachmentInfo\",  \r\n\"EmailEvents\",  \r\n\"EmailPostDeliveryEvents\",  \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\")   \r\n| summarize DailyBillableGB = toreal(sum(Quantity))/ 1024 by format_datetime(TimeGenerated, 'yy-MM-dd') \r\n| summarize TotalEligibleGB = sum(iif(toreal(DailyBillableGB)>toreal(DailyMaxDiscountGB),toreal(DailyMaxDiscountGB),DailyBillableGB))\r\n\r\n",
- "size": 4,
- "title": "Total Data Grant Used",
+ "query": "let freeTypes = dynamic([\"AzureActivity\",\"SentinelHealth\",\"OfficeActivity\",\"SecurityAlert\",\"SecurityIncident\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where DataType in (freeTypes) | summarize ['Free Data'] = sum(Quantity) / 1024.0",
+ "size": 1,
+ "title": "Free Data: {TimeRange}",
"timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No documented free Sentinel data was observed in the selected time range.",
+ "noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
@@ -637,45 +515,35 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "TotalEligibleGB",
+ "columnMatch": "Free Data",
"formatter": 12,
"formatOptions": {
- "palette": "coldHot"
+ "palette": "blue"
},
"numberFormat": {
"unit": 39,
"options": {
"style": "decimal",
- "maximumFractionDigits": 2
+ "maximumFractionDigits": 3
}
}
},
- "showBorder": false,
- "sortOrderField": 1
+ "showBorder": false
}
},
- "customWidth": "30",
- "conditionalVisibilities": [
- {
- "parameterName": "TotalE5Seats",
- "comparison": "isNotEqualTo"
- },
- {
- "parameterName": "TotalE5Seats",
- "comparison": "isNotEqualTo",
- "value": "0"
- }
- ],
- "name": "EligibleE5Ingestion"
+ "customWidth": "25",
+ "name": "FreeSentinelDataSavings"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let DailyMaxDiscountGB = ((5*toreal({TotalE5Seats}))/1024);\r\nUsage\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\",  \r\n\"DeviceFileEvents\",  \r\n\"DeviceImageLoadEvents\",  \r\n\"DeviceInfo\",  \r\n\"DeviceLogonEvents\",  \r\n\"DeviceNetworkEvents\",  \r\n\"DeviceNetworkInfo\",  \r\n\"DeviceProcessEvents\",  \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\",  \r\n\"EmailAttachmentInfo\",  \r\n\"EmailEvents\",  \r\n\"EmailPostDeliveryEvents\",  \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\")   \r\n| summarize DailyBillableGB = toreal(sum(Quantity))/ 1024 by format_datetime(TimeGenerated, 'yy-MM-dd') \r\n| summarize TotalEligibleGB = sum(iif(toreal(DailyBillableGB)>toreal(DailyMaxDiscountGB),toreal(DailyMaxDiscountGB),DailyBillableGB))\r\n| extend TotalDiscount = toreal(TotalEligibleGB)*{Price}\r\n| project TotalDiscount\r\n\r\n",
- "size": 4,
- "title": "Estimated Saving",
+ "query": "let freeTypes = dynamic([\"AzureActivity\",\"SentinelHealth\",\"OfficeActivity\",\"SecurityAlert\",\"SecurityIncident\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where DataType in (freeTypes) | summarize ['Estimated Free Data Savings'] = sum(Quantity) / 1024.0 * todouble('{Price}')",
+ "size": 1,
+ "title": "Estimated Free Data Savings: {TimeRange}",
"timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No documented free Sentinel data was observed in the selected time range.",
+ "noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
@@ -684,7 +552,7 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "TotalDiscount",
+ "columnMatch": "Estimated Free Data Savings",
"formatter": 12,
"formatOptions": {
"palette": "greenRed"
@@ -701,114 +569,1384 @@
"showBorder": false
}
},
- "customWidth": "20",
- "conditionalVisibilities": [
- {
- "parameterName": "TotalE5Seats",
- "comparison": "isNotEqualTo",
- "value": "0"
- },
- {
- "parameterName": "TotalE5Seats",
- "comparison": "isNotEqualTo"
+ "customWidth": "25",
+ "name": "FreeDataSavingsForTimeRange"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let freeTypes = dynamic([\"AzureActivity\",\"SentinelHealth\",\"OfficeActivity\",\"SecurityAlert\",\"SecurityIncident\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where DataType in (freeTypes) | summarize TableSizeGB = sum(Quantity) / 1024.0 by DataType | project ['Log Type'] = DataType, ['Table Size'] = TableSizeGB, ['Estimated Cost Savings'] = TableSizeGB * todouble('{Price}') | order by ['Table Size'] desc",
+ "size": 1,
+ "title": "Free data by source table in the {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No documented free Sentinel data was observed in the selected time range.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "table",
+ "gridSettings": {
+ "showExportToExcel": true,
+ "formatters": [
+ {
+ "columnMatch": "Log Type",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "2fr"
+ }
+ },
+ {
+ "columnMatch": "Table Size",
+ "formatter": 3,
+ "formatOptions": {
+ "palette": "greenRed",
+ "customColumnWidthSetting": "1fr"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 3
+ }
+ }
+ },
+ {
+ "columnMatch": "Estimated Cost Savings",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "1fr"
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency",
+ "maximumFractionDigits": 2
+ }
+ }
+ }
+ ]
}
- ],
- "name": "EstimateE5Discount"
+ },
+ "name": "FreeSentinelDataDetail"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let freeTypes = dynamic([\"AzureActivity\",\"SentinelHealth\",\"OfficeActivity\",\"SecurityAlert\",\"SecurityIncident\"]); let selectedDuration = {TimeRange:end} - {TimeRange:start}; let timeGrain = case(selectedDuration <= 1h, 5m, selectedDuration <= 4h, 15m, selectedDuration <= 1d, 1h, selectedDuration <= 7d, 6h, selectedDuration <= 31d, 1d, selectedDuration <= 90d, 7d, 30d); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where DataType in (freeTypes) | summarize ['Free Data Size'] = sum(Quantity) / 1024.0 by bin(TimeGenerated, timeGrain) | order by TimeGenerated asc",
+ "size": 1,
+ "title": "Free Data Size in the {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No documented free Sentinel data was observed in the selected time range.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "linechart",
+ "chartSettings": {
+ "xAxis": "TimeGenerated",
+ "showDataPoints": true,
+ "ySettings": {
+ "numberFormatSettings": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 3
+ }
+ }
+ }
+ }
+ },
+ "name": "FreeDataVsBillableDataDaily"
}
]
},
- "name": "E5 Benefits"
+ "name": "group - Free Sentinel Data"
},
{
"type": 12,
"content": {
"version": "NotebookGroup/1.0",
"groupType": "editable",
+ "title": "E5 Benefits",
+ "expandable": true,
+ "expanded": true,
"items": [
{
"type": 1,
"content": {
- "json": "## Microsoft Sentinel benefit for Defender for Cloud Servers Plan 2\r\n\r\nWith security information and event management (SIEM) and extended detection and response (XDR) from Microsoft, you’re armed with the context and automation you need to stop sophisticated, cross-domain attacks across your entire organization. \r\n\r\nMicrosoft Defender for Cloud Plan 2 customers can get data grant up to 500MB per server/day of Microsoft Defender For Cloud data ingestion into Microsoft Sentinel.\r\nThe data sources included in this offer include::\r\n\r\n- SecurityAlert\r\n- SecurityBaseline\r\n- SecurityBaselineSummary\r\n- SecurityDetection\r\n- SecurityEvent\r\n- WindowsFirewall\r\n- ProtectionStatus\r\n- Update and UpdateSummary when the Update Management solution isn't running in the workspace or solution targeting is enabled.\r\n- MDCFileIntegrityMonitoringEvents\r\n\r\nThe data grant will be calculated at the end of the month and applied to your bill, covering the cost of up to 500 MB of data ingestion per server/day.\r\n\r\nVisit https://learn.microsoft.com/en-us/azure/defender-for-cloud/data-ingestion-benefit for more information\r\n\r\n
\r\n\r\n### Below are the ingestion for the eligible data sources:\r\n\r\n_**Note:** Kindly specify **Total Servers for Servers seat** and **Ingestion Price** parameters for calculation._"
+ "json": "## Microsoft Sentinel benefit for Microsoft 365 E7/E5/A5/F5/G5 customers\r\n\r\nQualifying Microsoft 365 E7, E5, A5, F5, and G5 licenses, and corresponding Security licenses, may receive a Microsoft Sentinel data grant of up to 5 MB per qualifying user per day for eligible Microsoft 365 data.\r\n\r\nEligible data-source groups include:\r\n\r\n- Microsoft Entra ID sign-in and audit logs (`SigninLogs`, `AuditLogs`, `AADNonInteractiveUserSignInLogs`, `AADServicePrincipalSignInLogs`, `AADManagedIdentitySignInLogs`, `AADProvisioningLogs`, `ADFSSignInLogs`, `AADUserRiskEvents`, `AADRiskyUsers`)\r\n- Microsoft Defender for Cloud Apps Guard shadow IT discovery logs (`McasShadowItReporting`)\r\n- Microsoft Purview Information Protection logs (`InformationProtectionLogs_CL`)\r\n- Microsoft 365 advanced hunting data (the eligible `Device*`, `Email*`, `Identity*`, `AlertEvidence`, and `CloudAppEvents` tables shown below)\r\n\r\nThis workbook estimates the Analytics-tier ingestion benefit from billable Usage data in the selected workspace scope. It does not estimate data lake-only charges or prove that a row came from an eligible connector, that the offer applies to your agreement, or that the calculated amount matches billing. The grant cap is modeled once across the selected scope; it is not multiplied per workspace.\r\n\r\nReview the [Microsoft 365 Sentinel benefit offer](https://azure.microsoft.com/pricing/offers/sentinel-microsoft-365-offer/) for current eligibility, agreement terms, and supported data types. Enter **Total Microsoft 365 E7/E5/A5/F5/G5 seats** below and use the global **Ingestion price** to calculate the estimate."
+ },
+ "name": "text - 12"
+ },
+ {
+ "type": 9,
+ "content": {
+ "version": "KqlParameterItem/1.0",
+ "parameters": [
+ {
+ "id": "67494f3e-322e-4411-9b45-1cbea03ed618",
+ "version": "KqlParameterItem/1.0",
+ "name": "TotalE5Seats",
+ "label": "Total Microsoft 365 E7/E5/A5/F5/G5 seats",
+ "type": 1,
+ "quote": "'",
+ "description": "Enter the total number of eligible Microsoft 365 E7, E5, A5, F5, and G5 or corresponding Security licenses in your environment. Eligibility depends on the current offer terms and agreement type.",
+ "value": "",
+ "typeSettings": {
+ "paramValidationRules": [
+ {
+ "regExp": "^([1-9][0-9]*||)$",
+ "match": true,
+ "message": "Enter a whole number greater than zero, or clear the value."
+ }
+ ]
+ }
+ }
+ ],
+ "style": "pills",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces"
},
- "name": "MdcPlan2 Intro"
+ "name": "parameters - Microsoft 365 benefit"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "Usage\r\n| where IsBillable == true\r\n| where DataType in (\"SecurityAlert\", \r\n\"SecurityBaseline\",\r\n\"SecurityBaselineSummary\",\r\n\"SecurityDetection\",\r\n\"SecurityEvent\",\r\n\"WindowsFirewall\",\r\n\"ProtectionStatus\",\r\n\"MDCFileIntegrityMonitoringEvents\"\r\n)   \r\n| summarize BillableDataGB = sum(Quantity) / 1000. by DataType\r\n| order by BillableDataGB desc\r\n",
- "size": 0,
+ "query": "Usage\r\n| where TimeGenerated between ({TimeRange:start} .. {TimeRange:end})\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\", \r\n\"DeviceFileEvents\", \r\n\"DeviceImageLoadEvents\", \r\n\"DeviceInfo\", \r\n\"DeviceLogonEvents\", \r\n\"DeviceNetworkEvents\", \r\n\"DeviceNetworkInfo\", \r\n\"DeviceProcessEvents\", \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\", \r\n\"EmailAttachmentInfo\", \r\n\"EmailEvents\", \r\n\"EmailPostDeliveryEvents\", \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\"\r\n) \r\n| summarize TotalBillableDataGB = sum(Quantity) / 1024\r\n\r\n",
+ "size": 1,
+ "title": "Eligible M365 Data",
+ "timeContextFromParameter": "TimeRange",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "TotalBillableDataGB",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "greenRed"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "20",
+ "name": "E5IngestionSize"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let licenseCount = todouble('{TotalE5Seats}'); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); print MaxDataGrantGB = iif(isnull(licenseCount), 'N/A', strcat(tostring(round(licenseCount * 5.0 / 1024.0 * periodDays, 3)), ' GB'))",
+ "size": 1,
+ "title": "Total Data Grant Limit: {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "MaxDataGrantGB",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "orangeBlue"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ "showBorder": false,
+ "sortOrderField": 1
+ }
+ },
+ "customWidth": "20",
+ "name": "DataGrantLimit"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let eligibleTables = dynamic([\"SigninLogs\",\"AuditLogs\",\"AADNonInteractiveUserSignInLogs\",\"AADServicePrincipalSignInLogs\",\"AADManagedIdentitySignInLogs\",\"AADProvisioningLogs\",\"ADFSSignInLogs\",\"McasShadowItReporting\",\"InformationProtectionLogs_CL\",\"DeviceEvents\",\"DeviceFileEvents\",\"DeviceImageLoadEvents\",\"DeviceInfo\",\"DeviceLogonEvents\",\"DeviceNetworkEvents\",\"DeviceNetworkInfo\",\"DeviceProcessEvents\",\"DeviceRegistryEvents\",\"DeviceFileCertificateInfo\",\"EmailAttachmentInfo\",\"EmailEvents\",\"EmailPostDeliveryEvents\",\"EmailUrlInfo\",\"IdentityLogonEvents\",\"IdentityQueryEvents\",\"IdentityDirectoryEvents\",\"AlertEvidence\",\"CloudAppEvents\"]); let licenseCount = todouble('{TotalE5Seats}'); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); let eligibleGB = toreal(coalesce(toscalar(Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize sum(Quantity) / 1024.0), 0.0)); let periodGrantGB = licenseCount * 5.0 / 1024.0 * periodDays; print TotalEligibleGB = iif(isnull(licenseCount), 'N/A', strcat(tostring(round(min_of(eligibleGB, periodGrantGB), 3)), ' GB'))",
+ "size": 1,
+ "title": "Total Data Grant Used: {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "TotalEligibleGB",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "coldHot"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ "showBorder": false,
+ "sortOrderField": 1
+ }
+ },
+ "customWidth": "30",
+ "name": "EligibleE5Ingestion"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let eligibleTables = dynamic([\"SigninLogs\",\"AuditLogs\",\"AADNonInteractiveUserSignInLogs\",\"AADServicePrincipalSignInLogs\",\"AADManagedIdentitySignInLogs\",\"AADProvisioningLogs\",\"ADFSSignInLogs\",\"McasShadowItReporting\",\"InformationProtectionLogs_CL\",\"DeviceEvents\",\"DeviceFileEvents\",\"DeviceImageLoadEvents\",\"DeviceInfo\",\"DeviceLogonEvents\",\"DeviceNetworkEvents\",\"DeviceNetworkInfo\",\"DeviceProcessEvents\",\"DeviceRegistryEvents\",\"DeviceFileCertificateInfo\",\"EmailAttachmentInfo\",\"EmailEvents\",\"EmailPostDeliveryEvents\",\"EmailUrlInfo\",\"IdentityLogonEvents\",\"IdentityQueryEvents\",\"IdentityDirectoryEvents\",\"AlertEvidence\",\"CloudAppEvents\"]); let licenseCount = todouble('{TotalE5Seats}'); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); let eligibleGB = toreal(coalesce(toscalar(Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize sum(Quantity) / 1024.0), 0.0)); let periodGrantGB = licenseCount * 5.0 / 1024.0 * periodDays; print TotalDiscount = iif(isnull(licenseCount), 'N/A', strcat('$', tostring(round(min_of(eligibleGB, periodGrantGB) * todouble('{Price}'), 2))))",
+ "size": 1,
+ "title": "Estimated Cost Savings: {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "TotalDiscount",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "greenRed"
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "20",
+ "name": "EstimateE5Discount"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let eligibleTables = dynamic([\"SigninLogs\",\"AuditLogs\",\"AADNonInteractiveUserSignInLogs\",\"AADServicePrincipalSignInLogs\",\"AADManagedIdentitySignInLogs\",\"AADProvisioningLogs\",\"ADFSSignInLogs\",\"AADUserRiskEvents\",\"AADRiskyUsers\",\"McasShadowItReporting\",\"InformationProtectionLogs_CL\",\"DeviceEvents\",\"DeviceFileEvents\",\"DeviceImageLoadEvents\",\"DeviceInfo\",\"DeviceLogonEvents\",\"DeviceNetworkEvents\",\"DeviceNetworkInfo\",\"DeviceProcessEvents\",\"DeviceRegistryEvents\",\"DeviceFileCertificateInfo\",\"EmailAttachmentInfo\",\"EmailEvents\",\"EmailPostDeliveryEvents\",\"EmailUrlInfo\",\"IdentityLogonEvents\",\"IdentityQueryEvents\",\"IdentityDirectoryEvents\",\"AlertEvidence\",\"CloudAppEvents\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize TableSizeGB = sum(Quantity) / 1024.0 by DataType | project ['Log Type'] = DataType, ['Table Size'] = TableSizeGB | order by ['Table Size'] desc",
+ "size": 1,
+ "title": "Eligible Microsoft 365 data by source table in the {TimeRange}",
"timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No eligible Microsoft 365 data was found in the selected time range.",
+ "noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
"{Workspace}"
],
- "gridSettings": {
- "formatters": [
- {
- "columnMatch": "BillableDataGB",
- "formatter": 3,
- "formatOptions": {
- "palette": "blue"
- }
- }
- ]
- }
- },
- "name": "MdcPlan2 Ingestion"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "Usage\r\n| where IsBillable == true\r\n| where DataType in (\"SecurityAlert\", \r\n\"SecurityBaseline\",\r\n\"SecurityBaselineSummary\",\r\n\"SecurityDetection\",\r\n\"SecurityEvent\",\r\n\"WindowsFirewall\",\r\n\"ProtectionStatus\",\r\n\"MDCFileIntegrityMonitoringEvents\")   \r\n| summarize DailyIngestionGB = toreal(sum(Quantity))/ 1024 by format_datetime(TimeGenerated, 'yyyy-MM-dd') \r\n| extend MaxDataGrantGB = ((500*toreal({TotalMdcPlan2}))/1024)\r\n| sort by TimeGenerated asc\r\n",
- "size": 0,
- "aggregation": 3,
- "title": "Daily ingestion size (for eligible data sources) vs Maximum data grant:",
- "timeContextFromParameter": "TimeRange",
+ "visualization": "table",
+ "gridSettings": {
+ "showExportToExcel": true,
+ "formatters": [
+ {
+ "columnMatch": "Log Type",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "2fr"
+ }
+ },
+ {
+ "columnMatch": "Table Size",
+ "formatter": 3,
+ "formatOptions": {
+ "palette": "greenRed",
+ "customColumnWidthSetting": "1fr"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 3
+ }
+ }
+ }
+ ]
+ }
+ },
+ "name": "E5EligibleDataDetail"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let eligibleTables = dynamic([\"SigninLogs\",\"AuditLogs\",\"AADNonInteractiveUserSignInLogs\",\"AADServicePrincipalSignInLogs\",\"AADManagedIdentitySignInLogs\",\"AADProvisioningLogs\",\"ADFSSignInLogs\",\"AADUserRiskEvents\",\"AADRiskyUsers\",\"McasShadowItReporting\",\"InformationProtectionLogs_CL\",\"DeviceEvents\",\"DeviceFileEvents\",\"DeviceImageLoadEvents\",\"DeviceInfo\",\"DeviceLogonEvents\",\"DeviceNetworkEvents\",\"DeviceNetworkInfo\",\"DeviceProcessEvents\",\"DeviceRegistryEvents\",\"DeviceFileCertificateInfo\",\"EmailAttachmentInfo\",\"EmailEvents\",\"EmailPostDeliveryEvents\",\"EmailUrlInfo\",\"IdentityLogonEvents\",\"IdentityQueryEvents\",\"IdentityDirectoryEvents\",\"AlertEvidence\",\"CloudAppEvents\"]); let licenseCount = todouble('{TotalE5Seats}'); let selectedDuration = {TimeRange:end} - {TimeRange:start}; let timeGrain = case(selectedDuration <= 1h, 5m, selectedDuration <= 4h, 15m, selectedDuration <= 1d, 1h, selectedDuration <= 7d, 6h, selectedDuration <= 31d, 1d, selectedDuration <= 90d, 7d, 30d); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize ['Ingestion Size'] = sum(Quantity) / 1024.0 by bin(TimeGenerated, timeGrain) | extend ['Grant Limit for Interval'] = iif(isnull(licenseCount), real(null), licenseCount * 5.0 / 1024.0 * (timeGrain / 1d)) | order by TimeGenerated asc",
+ "size": 1,
+ "title": "Ingestion Size vs Prorated Data Grant in the {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No eligible Microsoft 365 data was found in the selected time range.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "linechart",
+ "chartSettings": {
+ "xAxis": "TimeGenerated",
+ "showDataPoints": true,
+ "ySettings": {
+ "numberFormatSettings": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 3
+ }
+ }
+ }
+ }
+ },
+ "name": "E5DailyIngestionVsGrant"
+ }
+ ]
+ },
+ "name": "group - E5 Benefits"
+ },
+ {
+ "type": 12,
+ "content": {
+ "version": "NotebookGroup/1.0",
+ "groupType": "editable",
+ "title": "Defender for Cloud Plan 2 Ingestion Benefit",
+ "expandable": true,
+ "expanded": true,
+ "items": [
+ {
+ "type": 1,
+ "content": {
+ "json": "## Microsoft Sentinel benefit for Defender for Servers Plan 2\r\n\r\nDefender for Servers Plan 2 provides up to 500 MB of eligible Analytics-tier ingestion per protected server or node per day. The allowance is pooled across machines in each subscription and applied at workspace level. This workbook estimates observed usage; it does not prove Plan 2 protection, licensing, eligibility, or data lake-only charges.\r\n\r\nCore eligible tables:\r\n\r\n- `SecurityAlert`, `SecurityBaseline`, `SecurityBaselineSummary`, `SecurityDetection`, `SecurityEvent`\r\n- `WindowsFirewall`, `ProtectionStatus`, `MDCFileIntegrityMonitoringEvents`\r\n- `DeviceCustomFileEvents`, `DeviceCustomRegistryEvents`\r\n\r\nConditionally eligible tables:\r\n\r\n- `Update`, `UpdateSummary`: review the applicable Update Management conditions\r\n- `WindowsEvent`: only security data from the Microsoft-SecurityEvent stream\r\n\r\nNodes is the distinct `Computer` count observed in `Heartbeat`, not proof of licensing or Plan 2 protection. Review the [Defender for Servers Plan 2 data ingestion benefit](https://learn.microsoft.com/azure/defender-for-cloud/data-ingestion-benefit) for current eligibility and terms."
+ },
+ "name": "text - DfSP2 benefit"
+ },
+ {
+ "type": 9,
+ "content": {
+ "version": "KqlParameterItem/1.0",
+ "parameters": [
+ {
+ "id": "f1a5dc2c-7e7f-4e48-9d65-0d52e77b6e3a",
+ "version": "KqlParameterItem/1.0",
+ "name": "TotalDfSP2Licenses",
+ "label": "Protected Defender for Servers Plan 2 servers or nodes",
+ "type": 1,
+ "quote": "'",
+ "description": "Enter the number of protected Defender for Servers Plan 2 servers or nodes used to estimate the 500 MB per server or node per day ingestion benefit. Leave as when the entitlement is unknown; grant and savings metrics will show N/A.",
+ "value": "",
+ "typeSettings": {
+ "paramValidationRules": [
+ {
+ "regExp": "^([1-9][0-9]*||)$",
+ "match": true,
+ "message": "Enter a whole number greater than zero, or clear the value."
+ }
+ ]
+ }
+ },
+ {
+ "id": "c4f7a2d1-5b83-4e96-9a07-1f6c8b3d2e54",
+ "version": "KqlParameterItem/1.0",
+ "name": "DfSP2LicensePrice",
+ "label": "Defender for Servers Plan 2 price (per server/month)",
+ "type": 1,
+ "isRequired": true,
+ "description": "Monthly list price per protected server or node. Verify against your agreement and region.",
+ "typeSettings": {
+ "paramValidationRules": [
+ {
+ "regExp": "^(0|[1-9][0-9]*)(\\.[0-9]+)?$",
+ "match": true,
+ "message": "Enter a non-negative price."
+ }
+ ]
+ },
+ "value": "15"
+ }
+ ],
+ "style": "pills",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces"
+ },
+ "name": "parameters - Defender for Servers Plan 2 benefit"
+ },
+ {
+ "type": 1,
+ "content": {
+ "json": "Enter the number of protected Defender for Servers Plan 2 servers or nodes above to calculate the daily and total data grants, grant usage, and estimated cost savings."
+ },
+ "name": "text - DfSP2 entitlement required",
+ "conditionalVisibility": {
+ "parameterName": "TotalDfSP2Licenses",
+ "comparison": "isEqualTo",
+ "value": ""
+ }
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize EligibleGB = sum(Quantity) / 1024.0",
+ "size": 1,
+ "title": "Eligible Defender for Servers Plan 2 data",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No eligible DfSP2 data was found in the selected time range.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "EligibleGB",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "blue"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 3
+ }
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "20",
+ "name": "DfSP2IngestionSize current"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "Heartbeat | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | summarize NodesIdentified = dcount(Computer)",
+ "size": 1,
+ "title": "Nodes",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No Heartbeat nodes were identified in the selected time range.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "NodesIdentified",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "blue"
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "10",
+ "name": "DfSP2NodesIdentified current"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let licenseCount = todouble('{TotalDfSP2Licenses}'); print DailyGrantGB = iif(isnull(licenseCount), 'N/A', strcat(tostring(round(licenseCount * 500.0 / 1024.0, 3)), ' GB'))",
+ "size": 1,
+ "title": "Daily Grant Limit",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate the daily grant.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "DailyGrantGB",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "orangeBlue"
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "15",
+ "name": "DfSP2DailyGrant"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let licenseCount = todouble('{TotalDfSP2Licenses}'); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1); print PeriodGrantGB = iif(isnull(licenseCount), 'N/A', strcat(tostring(round(licenseCount * 500.0 / 1024.0 * periodDays, 3)), ' GB'))",
+ "size": 1,
+ "title": "Total Grant Limit: {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate the selected-period grant.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "PeriodGrantGB",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "orangeBlue"
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "20",
+ "name": "DfSP2PeriodGrant"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); let licenseCount = todouble('{TotalDfSP2Licenses}'); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1); let eligibleGB = toreal(coalesce(toscalar(Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize sum(Quantity) / 1024.0), 0.0)); let periodGrantGB = licenseCount * 500.0 / 1024.0 * periodDays; print GrantUsedGB = iif(isnull(licenseCount), 'N/A', strcat(tostring(round(min_of(eligibleGB, periodGrantGB), 3)), ' GB'))",
+ "size": 1,
+ "title": "Total Grant Used: {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate grant use.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "GrantUsedGB",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "coldHot"
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "20",
+ "name": "DfSP2GrantUsed"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); let licenseCount = todouble('{TotalDfSP2Licenses}'); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1); let eligibleGB = toreal(coalesce(toscalar(Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize sum(Quantity) / 1024.0), 0.0)); let periodGrantGB = licenseCount * 500.0 / 1024.0 * periodDays; print EstimatedSavings = iif(isnull(licenseCount), 'N/A', strcat('$', tostring(round(min_of(eligibleGB, periodGrantGB) * todouble('{Price}'), 2))))",
+ "size": 1,
+ "title": "Estimated Savings: {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate estimated savings.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "EstimatedSavings",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "greenRed"
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "15",
+ "name": "DfSP2EstimatedSavings"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize TableSizeGB = sum(Quantity) / 1024.0 by DataType | project ['Log Type'] = DataType, ['Table Size'] = TableSizeGB | order by ['Table Size'] desc",
+ "size": 1,
+ "title": "Eligible Defender for Servers Plan 2 data by source table in the {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No eligible DfSP2 data was found in the selected time range.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "table",
+ "gridSettings": {
+ "showExportToExcel": true,
+ "formatters": [
+ {
+ "columnMatch": "Log Type",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "2fr"
+ }
+ },
+ {
+ "columnMatch": "Table Size",
+ "formatter": 3,
+ "formatOptions": {
+ "palette": "greenRed",
+ "customColumnWidthSetting": "1fr"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 3
+ }
+ }
+ }
+ ]
+ }
+ },
+ "name": "DfSP2CapacityDetailCurrent"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); let licenseCount = todouble('{TotalDfSP2Licenses}'); let selectedDuration = {TimeRange:end} - {TimeRange:start}; let timeGrain = case(selectedDuration <= 1h, 5m, selectedDuration <= 4h, 15m, selectedDuration <= 1d, 1h, selectedDuration <= 7d, 6h, selectedDuration <= 31d, 1d, selectedDuration <= 90d, 7d, 30d); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize ['Ingestion Size'] = sum(Quantity) / 1024.0 by bin(TimeGenerated, timeGrain) | extend ['Grant Limit for Interval'] = iif(isnull(licenseCount), real(null), licenseCount * 500.0 / 1024.0 * (timeGrain / 1d)) | order by TimeGenerated asc",
+ "size": 1,
+ "title": "Ingestion Size vs Prorated Data Grant in the {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No eligible DfSP2 data was found in the selected time range.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "linechart",
+ "chartSettings": {
+ "xAxis": "TimeGenerated",
+ "showDataPoints": true,
+ "ySettings": {
+ "numberFormatSettings": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 3
+ }
+ }
+ }
+ }
+ },
+ "name": "DfSP2DailyIngestionVsGrant"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let licenseCount = todouble('{TotalDfSP2Licenses}'); let unitPrice = todouble('{DfSP2LicensePrice}'); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); print LicensingCost = iif(isnull(licenseCount), 'N/A', strcat('$', tostring(round(licenseCount * unitPrice * periodDays / 30.0, 2))))",
+ "size": 1,
+ "title": "Defender for Servers Plan 2 licensing cost: {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate licensing cost.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "LicensingCost",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "orangeBlue"
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "50",
+ "name": "DfSP2LicensingCost"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); let licenseCount = todouble('{TotalDfSP2Licenses}'); let unitPrice = todouble('{DfSP2LicensePrice}'); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); let eligibleGB = toreal(coalesce(toscalar(Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize sum(Quantity) / 1024.0), 0.0)); let periodGrantGB = licenseCount * 500.0 / 1024.0 * periodDays; let licensingCost = licenseCount * unitPrice * periodDays / 30.0; print NetSavings = iif(isnull(licenseCount), 'N/A', strcat('$', tostring(round(min_of(eligibleGB, periodGrantGB) * todouble('{Price}') - licensingCost, 2))))",
+ "size": 1,
+ "title": "Estimated savings after licensing cost: {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate net savings.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "NetSavings",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "greenRed"
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "50",
+ "name": "DfSP2NetSavingsAfterLicensing"
+ }
+ ]
+ },
+ "name": "group - Defender for Cloud Plan 2 Ingestion Benefit"
+ },
+ {
+ "type": 12,
+ "content": {
+ "version": "NotebookGroup/1.0",
+ "groupType": "editable",
+ "title": "Retention",
+ "expandable": true,
+ "expanded": true,
+ "items": [
+ {
+ "type": 1,
+ "content": {
+ "json": "## Retention summary\r\n\r\nThis section estimates Analytics-tier charges for billable data retained longer than 90 days, using historical billable workspace records. XDR and data lake retention use separate billing models. Review [Manage data tiers and retention in Microsoft Sentinel](https://learn.microsoft.com/azure/sentinel/manage-data-overview) for retention and data-tier guidance."
+ },
+ "name": "text - retention summary"
+ },
+ {
+ "type": 9,
+ "content": {
+ "version": "KqlParameterItem/1.0",
+ "parameters": [
+ {
+ "id": "9d5299d0-36a0-4666-9803-ca6931bdaab7",
+ "version": "KqlParameterItem/1.0",
+ "name": "RetentionPrice",
+ "label": "Retention price",
+ "type": 1,
+ "description": "Enter the retention price per GB/month used for this section's estimates.",
+ "typeSettings": {
+ "paramValidationRules": [
+ {
+ "regExp": "^(0|[1-9][0-9]*)(\\.[0-9]+)?$",
+ "match": true,
+ "message": "Enter a non-negative price."
+ }
+ ]
+ },
+ "value": "0.1"
+ }
+ ],
+ "style": "pills",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces"
+ },
+ "name": "parameters - retention pricing"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let retainedDataGB = toreal(coalesce(toscalar((union withsource = SourceTableName * | where TimeGenerated < startofday(now()) - 90d | where _IsBillable == true | summarize sum(_BilledSize) / 1024.0 / 1024.0 / 1024.0)), 0.0)); print ['Average Daily Retention Cost'] = retainedDataGB * todouble('{RetentionPrice}') / 30.0",
+ "size": 1,
+ "title": "Average Daily Retention Cost",
+ "noDataMessage": "No retained billable data was found in the selected workspace scope.",
+ "noDataMessageStyle": 3,
+ "timeContextFromParameter": "TimeRange",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "Average Daily Retention Cost",
+ "formatter": 12,
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "25",
+ "name": "AverageDailyRetentionCost"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let selectedDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); let retainedDataGB = toreal(coalesce(toscalar((union withsource = SourceTableName * | where TimeGenerated < startofday(now()) - 90d | where _IsBillable == true | summarize sum(_BilledSize) / 1024.0 / 1024.0 / 1024.0)), 0.0)); print ['Retention Cost'] = retainedDataGB * todouble('{RetentionPrice}') * selectedDays / 30.0",
+ "size": 1,
+ "title": "Retention Cost: {TimeRange}",
+ "noDataMessage": "No retained billable data was found in the selected workspace scope.",
+ "noDataMessageStyle": 3,
+ "timeContextFromParameter": "TimeRange",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "Retention Cost",
+ "formatter": 12,
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "25",
+ "name": "RetentionCostForTimeRange"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let selectedDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); union withsource = SourceTableName * | where TimeGenerated < startofday(now()) - 90d | where _IsBillable == true | summarize RetainedDataGB = sum(_BilledSize) / 1024.0 / 1024.0 / 1024.0 by SourceTableName | project ['Log Type'] = SourceTableName, ['Retained Data'] = RetainedDataGB, ['Average Daily Retention Cost'] = RetainedDataGB * todouble('{RetentionPrice}') / 30.0, ['Retention Cost'] = RetainedDataGB * todouble('{RetentionPrice}') * selectedDays / 30.0 | order by ['Retained Data'] desc",
+ "size": 1,
+ "title": "Retained data by source table in the last {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No billable data older than 90 days was found in the selected workspace scope.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "table",
+ "gridSettings": {
+ "showExportToExcel": true,
+ "formatters": [
+ {
+ "columnMatch": "Log Type",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "2fr"
+ }
+ },
+ {
+ "columnMatch": "Retained Data",
+ "formatter": 3,
+ "formatOptions": {
+ "palette": "greenRed",
+ "customColumnWidthSetting": "1fr"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 3
+ }
+ }
+ },
+ {
+ "columnMatch": "Average Daily Retention Cost",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "1fr"
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ {
+ "columnMatch": "Retention Cost",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "1fr"
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency",
+ "maximumFractionDigits": 2
+ }
+ }
+ }
+ ],
+ "labelSettings": [
+ {
+ "columnId": "Average Daily Retention Cost",
+ "label": "Avg daily cost"
+ },
+ {
+ "columnId": "Retention Cost",
+ "label": "Period cost"
+ }
+ ]
+ }
+ },
+ "name": "RetentionDataDetail"
+ }
+ ]
+ },
+ "name": "group - Retention"
+ },
+ {
+ "type": 12,
+ "content": {
+ "version": "NotebookGroup/1.0",
+ "groupType": "editable",
+ "title": "Commitment Tiers",
+ "expandable": true,
+ "expanded": true,
+ "items": [
+ {
+ "type": 1,
+ "content": {
+ "json": "## Commitment tiers\r\n\r\nMicrosoft Sentinel and Log Analytics offer Pay-As-You-Go and Commitment Tier pricing. This section automatically detects the current workspace tier and calculates a **usage-based suggested tier** from average billable daily ingestion over the last 31 days.\r\n\r\n> **New workspace notice:** A recommendation is shown only after 31 days of billable data are detected. Until then, the table reports how many days remain before the recommendation becomes available; a shorter history cannot accurately represent the fixed 31-day review period.\r\n\r\n> **Estimate only:** The suggested tier uses ingestion volume, not actual pricing. It is not the Azure portal **Recommended Tier** and should not be used as the sole basis for a pricing change. Azure evaluates each available tier using the prior 31 days and your applicable pricing to identify the lowest estimated-cost option. Review [Usage and estimated costs in the Azure portal](https://learn.microsoft.com/azure/azure-monitor/logs/change-pricing-tier#changing-pricing-tier) before changing a tier.\r\n\r\nReview **Days since tier last changed** before making a change: a commitment tier has a 31-day period during which it cannot move to a lower commitment or consumption tier. Confirm rates on the [Microsoft Sentinel pricing page](https://www.microsoft.com/security/pricing/microsoft-sentinel/) and review [Plan costs and understand pricing and billing for Microsoft Sentinel](https://learn.microsoft.com/azure/sentinel/billing?tabs=simplified%2Ccommitment-tiers#analytics-tier)."
+ },
+ "name": "text - commitment tiers"
+ },
+ {
+ "type": 9,
+ "content": {
+ "version": "KqlParameterItem/1.0",
+ "parameters": [
+ {
+ "id": "7df48bd0-c79e-4c17-9a6d-b00b9511d9e1",
+ "version": "KqlParameterItem/1.0",
+ "name": "CurrentCommitmentTier",
+ "type": 1,
+ "isRequired": true,
+ "query": "resources\r\n| where type =~ 'microsoft.operationalinsights/workspaces'\r\n| where id in~ ({Workspace}) or 'value::all' in~ ({Workspace})\r\n| extend skuName = tolower(tostring(properties.sku.name)), capacityReservationLevel = toint(properties.sku.capacityReservationLevel)\r\n| extend currentTier = case(skuName == 'capacityreservation', strcat(tostring(capacityReservationLevel), ' GB/day commitment'), skuName == 'pergb2018', 'Pay-As-You-Go', skuName == 'free', 'Free tier', skuName == 'standalone', 'Standalone tier', skuName == 'standard', 'Standard tier', skuName == 'premium', 'Premium tier', 'Unknown')\r\n| summarize WorkspaceCount = dcount(id), CurrentTier = any(currentTier)\r\n| project CurrentCommitmentTier = iif(WorkspaceCount == 1, CurrentTier, 'Multiple workspaces')",
+ "isHiddenWhenLocked": true,
+ "queryType": 1,
+ "resourceType": "microsoft.resourcegraph/resources"
+ }
+ ],
+ "style": "pills",
+ "queryType": 1,
+ "resourceType": "microsoft.resourcegraph/resources"
+ },
+ "name": "parameters - commitment tier current"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let reviewDays = 31.0; let reviewStart = ago(31d); let historyProbeStart = ago(32d); let currentTier = '{CurrentCommitmentTier}'; let tierLevels = dynamic([50,100,200,300,400,500,1000,2000,5000]); union withsource = SourceTableName * | where TimeGenerated between (historyProbeStart .. now()) | where _IsBillable == true | summarize TotalBilledBytes = sumif(_BilledSize, TimeGenerated >= reviewStart), FirstObserved = min(TimeGenerated) | extend ObservedHistoryDays = iif(isnull(FirstObserved), 0.0, min_of(reviewDays, datetime_diff('second', now(), FirstObserved) / 86400.0)) | extend DaysRemaining = toint(ceiling(max_of(reviewDays - ObservedHistoryDays, 0.0))) | extend AvgDailyGB = iif(DaysRemaining == 0, TotalBilledBytes / 1024.0 / 1024.0 / 1024.0 / reviewDays, real(null)), TierLevels = tierLevels | mv-expand TierLevel = TierLevels to typeof(int) | extend IsEligible = TierLevel >= AvgDailyGB | summarize SuggestedTierGBPerDay = minif(TierLevel, IsEligible), AvgDailyGB = any(AvgDailyGB), ObservedHistoryDays = any(ObservedHistoryDays), DaysRemaining = any(DaysRemaining) | extend suggestedTier = case(DaysRemaining > 0, strcat('Available in ', tostring(DaysRemaining), iif(DaysRemaining == 1, ' day', ' days')), AvgDailyGB < 50.0, 'Pay-As-You-Go', isnotempty(SuggestedTierGBPerDay), strcat(tostring(SuggestedTierGBPerDay), ' GB/day commitment'), 'Above 5000 GB/day - review Azure portal options') | extend alignmentStatus = case(DaysRemaining > 0, 'Collecting data', currentTier == 'Not available' or currentTier == 'Unknown' or currentTier == 'Multiple workspaces', 'Not evaluated', suggestedTier startswith 'Above 5000 GB/day', 'Review in portal', currentTier == suggestedTier, 'Aligned', 'Review tier') | project ['Current tier'] = currentTier, ['Recommended next tier'] = suggestedTier, ['Alignment status'] = alignmentStatus, ['Observed history (days)'] = round(ObservedHistoryDays, 1), ['Days until recommendation'] = DaysRemaining, ['Average billable daily ingestion (GB)'] = round(AvgDailyGB, 2)",
+ "size": 0,
+ "title": "Usage-based suggested tier (estimate, last 31 days)",
+ "noDataMessage": "No billable ingestion was found in the last 31 days.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "table",
+ "gridSettings": {
+ "formatters": [
+ {
+ "columnMatch": "Current tier",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "1fr"
+ }
+ },
+ {
+ "columnMatch": "Recommended next tier",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "1fr"
+ }
+ },
+ {
+ "columnMatch": "Alignment status",
+ "formatter": 18,
+ "formatOptions": {
+ "thresholdsOptions": "icons",
+ "customColumnWidthSetting": "1fr",
+ "thresholdsGrid": [
+ {
+ "operator": "==",
+ "thresholdValue": "Aligned",
+ "representation": "success",
+ "text": "{0}{1}"
+ },
+ {
+ "operator": "==",
+ "thresholdValue": "Review tier",
+ "representation": "failed",
+ "text": "{0}{1}"
+ },
+ {
+ "operator": "Default",
+ "thresholdValue": null,
+ "representation": "2",
+ "text": "{0}{1}"
+ }
+ ]
+ }
+ },
+ {
+ "columnMatch": "Average billable daily ingestion (GB)",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "1fr"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ {
+ "columnMatch": "Observed history (days)",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "1fr"
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 1
+ }
+ }
+ },
+ {
+ "columnMatch": "Days until recommendation",
+ "formatter": 18,
+ "formatOptions": {
+ "thresholdsOptions": "icons",
+ "customColumnWidthSetting": "1fr",
+ "thresholdsGrid": [
+ {
+ "operator": "==",
+ "thresholdValue": "0",
+ "representation": "success",
+ "text": "Ready"
+ },
+ {
+ "operator": "Default",
+ "thresholdValue": null,
+ "representation": "warning",
+ "text": "{0} days"
+ }
+ ]
+ }
+ }
+ ],
+ "labelSettings": [
+ {
+ "columnId": "Recommended next tier",
+ "label": "Suggested tier"
+ },
+ {
+ "columnId": "Average billable daily ingestion (GB)",
+ "label": "Avg daily ingestion (GB)"
+ }
+ ]
+ }
+ },
+ "name": "CommitmentTierUsageContext",
+ "customWidth": "100"
+ }
+ ]
+ },
+ "name": "group - Commitment Tiers"
+ },
+ {
+ "type": 12,
+ "content": {
+ "version": "NotebookGroup/1.0",
+ "groupType": "editable",
+ "title": "Data Lake",
+ "expandable": true,
+ "expanded": true,
+ "items": [
+ {
+ "type": 1,
+ "content": {
+ "json": "## Microsoft Sentinel Data Lake\r\n\r\nThe data lake stores security data outside the Analytics tier and is billed on five separate meters. Enter your rates below from the [Microsoft Sentinel pricing page](https://www.microsoft.com/security/pricing/microsoft-sentinel/); the defaults are placeholders and must be verified against your agreement and region.\r\n\r\n**What this section can and cannot observe.** Only the storage meter can be derived per table from workspace data:\r\n\r\n| Meter | Source | Per-table detail |\r\n| --- | --- | --- |\r\n| Data lake storage | Estimated from mirrored `Usage` volume | Yes |\r\n| Data lake ingestion | Manual entry | No |\r\n| Data processing | Manual entry | No |\r\n| Data lake query | Manual entry | No |\r\n| Advanced data insights | Manual entry | No |\r\n\r\nWhen the data lake is enabled, Analytics-tier data is **mirrored** to the lake at no extra ingestion charge, so mirrored volume is visible in `Usage` and is used for the storage estimate. Ingestion and data processing are charged only for tables set to **data lake tier only**; that data never reaches the Analytics workspace, so its volume must be entered manually. Query charges depend on GB scanned and insights charges on notebook compute hours, neither of which is recorded in `Usage`.\r\n\r\nStorage is billed on compressed data at a documented **6:1** ratio and applies only to data still retained after the Analytics retention period ends. These are planning estimates, not invoice values. Validate in **Microsoft Sentinel > Cost management** in the Microsoft Defender portal, and review the [data lake overview](https://learn.microsoft.com/azure/sentinel/datalake/sentinel-lake-overview), [billing model](https://learn.microsoft.com/azure/sentinel/billing#understand-the-full-billing-model-for-microsoft-sentinel), and [cost monitoring guidance](https://learn.microsoft.com/azure/sentinel/billing-monitor-costs)."
+ },
+ "name": "text - Microsoft Sentinel Data Lake"
+ },
+ {
+ "type": 9,
+ "content": {
+ "version": "KqlParameterItem/1.0",
+ "parameters": [
+ {
+ "id": "3a7c1f0e-6b21-4d4c-9f83-1c5c4a9d2b71",
+ "version": "KqlParameterItem/1.0",
+ "name": "LakeStoragePrice",
+ "label": "Lake storage price (per compressed GB/month)",
+ "type": 1,
+ "isRequired": true,
+ "description": "Data lake storage rate per compressed GB per month. Storage is billed at a 6:1 compression ratio on data retained after Analytics retention ends.",
+ "typeSettings": {
+ "paramValidationRules": [
+ {
+ "regExp": "^(0|[1-9][0-9]*)(\\.[0-9]+)?$",
+ "match": true,
+ "message": "Enter a non-negative price."
+ }
+ ]
+ },
+ "value": "0.026"
+ },
+ {
+ "id": "5d92b83a-4f17-4a6e-bd15-9e2f7c3a8d64",
+ "version": "KqlParameterItem/1.0",
+ "name": "LakeAnalyticsRetentionDays",
+ "label": "Analytics retention (days)",
+ "type": 1,
+ "isRequired": true,
+ "description": "Analytics-tier retention in days. Lake storage is charged only for data retained beyond this period.",
+ "typeSettings": {
+ "paramValidationRules": [
+ {
+ "regExp": "^[1-9][0-9]*$",
+ "match": true,
+ "message": "Enter a whole number of days greater than zero."
+ }
+ ]
+ },
+ "value": "90"
+ },
+ {
+ "id": "7e4a6c25-8d39-4b72-a1f6-3b8d5e0c9a17",
+ "version": "KqlParameterItem/1.0",
+ "name": "LakeTotalRetentionMonths",
+ "label": "Total lake retention (months)",
+ "type": 1,
+ "isRequired": true,
+ "description": "Total retention in the data lake tier, up to 12 years (144 months).",
+ "typeSettings": {
+ "paramValidationRules": [
+ {
+ "regExp": "^[1-9][0-9]*$",
+ "match": true,
+ "message": "Enter a whole number of months greater than zero."
+ }
+ ]
+ },
+ "value": "12"
+ },
+ {
+ "id": "9f1b7d43-2c58-4e19-8a6d-4d7c1f2b6e35",
+ "version": "KqlParameterItem/1.0",
+ "name": "LakeOnlyIngestionGB",
+ "label": "Lake-only ingestion (GB/month)",
+ "type": 1,
+ "description": "Monthly GB ingested into tables set to data lake tier only. This data is not present in the Analytics workspace, so it cannot be measured here. Leave as to report N/A.",
+ "typeSettings": {
+ "paramValidationRules": [
+ {
+ "regExp": "^((0|[1-9][0-9]*)(\\.[0-9]+)?||)$",
+ "match": true,
+ "message": "Enter a non-negative number, or clear the value."
+ }
+ ]
+ },
+ "value": ""
+ },
+ {
+ "id": "2b6e9a17-7f34-4c81-95d2-8a1e3f7b4c60",
+ "version": "KqlParameterItem/1.0",
+ "name": "LakeIngestionPrice",
+ "label": "Lake ingestion price (per GB)",
+ "type": 1,
+ "isRequired": true,
+ "description": "Ingestion rate per GB for tables set to data lake tier only. Mirrored data is not charged this meter.",
+ "typeSettings": {
+ "paramValidationRules": [
+ {
+ "regExp": "^(0|[1-9][0-9]*)(\\.[0-9]+)?$",
+ "match": true,
+ "message": "Enter a non-negative price."
+ }
+ ]
+ },
+ "value": "0.05"
+ },
+ {
+ "id": "4c8f2e61-9b47-4d3a-8e15-6f2a9c4d7b83",
+ "version": "KqlParameterItem/1.0",
+ "name": "LakeProcessingPrice",
+ "label": "Data processing price (per GB)",
+ "type": 1,
+ "isRequired": true,
+ "description": "Data processing rate per GB for tables set to data lake tier only, covering transformations such as redaction, splitting, filtering, and normalization.",
+ "typeSettings": {
+ "paramValidationRules": [
+ {
+ "regExp": "^(0|[1-9][0-9]*)(\\.[0-9]+)?$",
+ "match": true,
+ "message": "Enter a non-negative price."
+ }
+ ]
+ },
+ "value": "0.10"
+ },
+ {
+ "id": "6a3d5b98-1e72-4f60-b94c-2d8f7a1c5e49",
+ "version": "KqlParameterItem/1.0",
+ "name": "LakeQueryScannedGB",
+ "label": "Lake query data scanned (GB/month)",
+ "type": 1,
+ "description": "Monthly GB of uncompressed data scanned by KQL queries and jobs against the lake. Not recorded in the workspace. Leave as to report N/A.",
+ "typeSettings": {
+ "paramValidationRules": [
+ {
+ "regExp": "^((0|[1-9][0-9]*)(\\.[0-9]+)?||)$",
+ "match": true,
+ "message": "Enter a non-negative number, or clear the value."
+ }
+ ]
+ },
+ "value": ""
+ },
+ {
+ "id": "8d17c4a6-3f95-42be-9c1d-7e5b2a8f0d63",
+ "version": "KqlParameterItem/1.0",
+ "name": "LakeQueryPrice",
+ "label": "Lake query price (per GB scanned)",
+ "type": 1,
+ "isRequired": true,
+ "description": "Query rate per GB of uncompressed data scanned in the data lake tier.",
+ "typeSettings": {
+ "paramValidationRules": [
+ {
+ "regExp": "^(0|[1-9][0-9]*)(\\.[0-9]+)?$",
+ "match": true,
+ "message": "Enter a non-negative price."
+ }
+ ]
+ },
+ "value": "0.005"
+ },
+ {
+ "id": "1e5f8b30-6d24-4a97-85c3-9b6d4e2a7f18",
+ "version": "KqlParameterItem/1.0",
+ "name": "LakeInsightsHours",
+ "label": "Advanced data insights (compute hours/month)",
+ "type": 1,
+ "description": "Monthly notebook and job compute hours for advanced data insights. Not recorded in the workspace. Leave as to report N/A.",
+ "typeSettings": {
+ "paramValidationRules": [
+ {
+ "regExp": "^((0|[1-9][0-9]*)(\\.[0-9]+)?||)$",
+ "match": true,
+ "message": "Enter a non-negative number, or clear the value."
+ }
+ ]
+ },
+ "value": ""
+ },
+ {
+ "id": "7b2a9d54-8c61-4e35-a7f9-3d1c6b8e5a02",
+ "version": "KqlParameterItem/1.0",
+ "name": "LakeInsightsPrice",
+ "label": "Advanced data insights price (per compute hour)",
+ "type": 1,
+ "isRequired": true,
+ "description": "Rate per compute hour for advanced data insights sessions and jobs.",
+ "typeSettings": {
+ "paramValidationRules": [
+ {
+ "regExp": "^(0|[1-9][0-9]*)(\\.[0-9]+)?$",
+ "match": true,
+ "message": "Enter a non-negative price."
+ }
+ ]
+ },
+ "value": "1.00"
+ }
+ ],
+ "style": "pills",
"queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "linechart",
- "chartSettings": {
- "xAxis": "TimeGenerated",
- "showDataPoints": true,
- "ySettings": {
- "numberFormatSettings": {
- "unit": 0,
- "options": {
- "style": "decimal",
- "useGrouping": true,
- "maximumFractionDigits": 3
- }
- }
- }
- }
+ "resourceType": "microsoft.operationalinsights/workspaces"
},
- "conditionalVisibilities": [
- {
- "parameterName": "TotalMdcPlan2",
- "comparison": "isNotEqualTo"
- },
- {
- "parameterName": "TotalMdcPlan2",
- "comparison": "isNotEqualTo",
- "value": "0"
- }
- ],
- "name": "MdcPlan2DailyIngestionVSAllocation"
+ "name": "parameters - data lake pricing"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "Usage\r\n| where IsBillable == true\r\n| where DataType in (\"SecurityAlert\", \r\n\"SecurityBaseline\",\r\n\"SecurityBaselineSummary\",\r\n\"SecurityDetection\",\r\n\"SecurityEvent\",\r\n\"WindowsFirewall\",\r\n\"ProtectionStatus\",\r\n\"MDCFileIntegrityMonitoringEvents\"\r\n)   \r\n| summarize TotalBillableDataGB = sum(Quantity) / 1024\r\n\r\n",
- "size": 4,
- "title": "Total ingestion",
+ "query": "let selectedDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | summarize ['Average Daily Mirrored Volume'] = sum(Quantity) / 1024.0 / selectedDays",
+ "size": 1,
+ "title": "Average Daily Mirrored Volume",
"timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No billable table usage data was found in the selected time range.",
+ "noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
@@ -817,10 +1955,10 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "TotalBillableDataGB",
+ "columnMatch": "Average Daily Mirrored Volume",
"formatter": 12,
"formatOptions": {
- "palette": "greenRed"
+ "palette": "blue"
},
"numberFormat": {
"unit": 39,
@@ -833,17 +1971,19 @@
"showBorder": false
}
},
- "customWidth": "20",
- "name": "MdCP2IngestionSize"
+ "customWidth": "25",
+ "name": "DataLakeAverageMirroredVolume"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let DailyMaxDiscountGB = ((500*toreal({TotalMdcPlan2}))/1024);\r\nUsage\r\n| where IsBillable == true\r\n| where DataType in (\"SecurityAlert\", \r\n\"SecurityBaseline\",\r\n\"SecurityBaselineSummary\",\r\n\"SecurityDetection\",\r\n\"SecurityEvent\",\r\n\"WindowsFirewall\",\r\n\"ProtectionStatus\",\r\n\"MDCFileIntegrityMonitoringEvents\")   \r\n| summarize DailyBillableGB = toreal(sum(Quantity))/ 1024 by format_datetime(TimeGenerated, 'yy-MM-dd') \r\n| extend DailyMaxGrantGB = DailyMaxDiscountGB\r\n| summarize MaxDataGrantGB = sum(toreal(DailyMaxGrantGB))\r\n\r\n",
- "size": 4,
- "title": "Total Data Grant Limit",
+ "query": "Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | summarize ['Mirrored Volume'] = sum(Quantity) / 1024.0",
+ "size": 1,
+ "title": "Mirrored Volume: {TimeRange}",
"timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No billable table usage data was found in the selected time range.",
+ "noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
@@ -852,10 +1992,10 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "MaxDataGrantGB",
+ "columnMatch": "Mirrored Volume",
"formatter": 12,
"formatOptions": {
- "palette": "orangeBlue"
+ "palette": "blue"
},
"numberFormat": {
"unit": 39,
@@ -865,32 +2005,22 @@
}
}
},
- "showBorder": false,
- "sortOrderField": 1
+ "showBorder": false
}
},
- "customWidth": "20",
- "conditionalVisibilities": [
- {
- "parameterName": "TotalMdcPlan2",
- "comparison": "isNotEqualTo"
- },
- {
- "parameterName": "TotalMdcPlan2",
- "comparison": "isNotEqualTo",
- "value": "0"
- }
- ],
- "name": "MdCP2DataGrantLimit"
+ "customWidth": "25",
+ "name": "DataLakeMirroredVolume"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let DailyMaxDiscountGB = ((500*toreal({TotalMdcPlan2}))/1024);\r\nUsage\r\n| where IsBillable == true\r\n| where DataType in (\"SecurityAlert\", \r\n\"SecurityBaseline\",\r\n\"SecurityBaselineSummary\",\r\n\"SecurityDetection\",\r\n\"SecurityEvent\",\r\n\"WindowsFirewall\",\r\n\"ProtectionStatus\",\r\n\"MDCFileIntegrityMonitoringEvents\")   \r\n| summarize DailyBillableGB = toreal(sum(Quantity))/ 1024 by format_datetime(TimeGenerated, 'yy-MM-dd') \r\n| summarize TotalEligibleGB = sum(iif(toreal(DailyBillableGB)>toreal(DailyMaxDiscountGB),toreal(DailyMaxDiscountGB),DailyBillableGB))\r\n\r\n",
- "size": 4,
- "title": "Total Data Grant Used",
+ "query": "let compressionRatio = 6.0; let selectedDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); let chargeableDays = max_of(todouble('{LakeTotalRetentionMonths}') * 30.0 - todouble('{LakeAnalyticsRetentionDays}'), 0.0); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | summarize RawGB = sum(Quantity) / 1024.0 | extend ['Billed Compressed Volume'] = RawGB / selectedDays * chargeableDays / compressionRatio | project ['Billed Compressed Volume']",
+ "size": 1,
+ "title": "Est. Lake Storage at Steady State",
"timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No mirrored table usage data was found in the selected time range.",
+ "noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
@@ -899,10 +2029,10 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "TotalEligibleGB",
+ "columnMatch": "Billed Compressed Volume",
"formatter": 12,
"formatOptions": {
- "palette": "coldHot"
+ "palette": "orangeBlue"
},
"numberFormat": {
"unit": 39,
@@ -912,32 +2042,22 @@
}
}
},
- "showBorder": false,
- "sortOrderField": 1
+ "showBorder": false
}
},
- "customWidth": "30",
- "conditionalVisibilities": [
- {
- "parameterName": "TotalMdcPlan2",
- "comparison": "isNotEqualTo"
- },
- {
- "parameterName": "TotalMdcPlan2",
- "comparison": "isNotEqualTo",
- "value": "0"
- }
- ],
- "name": "EligibleMdcPlan2Ingestion"
+ "customWidth": "25",
+ "name": "DataLakeSteadyStateCompressedVolume"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let DailyMaxDiscountGB = ((500*toreal({TotalMdcPlan2}))/1024);\r\nUsage\r\n| where IsBillable == true\r\n| where DataType in (\"SecurityAlert\", \r\n\"SecurityBaseline\",\r\n\"SecurityBaselineSummary\",\r\n\"SecurityDetection\",\r\n\"SecurityEvent\",\r\n\"WindowsFirewall\",\r\n\"ProtectionStatus\",\r\n\"MDCFileIntegrityMonitoringEvents\")   \r\n| summarize DailyBillableGB = toreal(sum(Quantity))/ 1024 by format_datetime(TimeGenerated, 'yy-MM-dd') \r\n| summarize TotalEligibleGB = sum(iif(toreal(DailyBillableGB)>toreal(DailyMaxDiscountGB),toreal(DailyMaxDiscountGB),DailyBillableGB))\r\n| extend TotalDiscount = toreal(TotalEligibleGB)*{Price}\r\n| project TotalDiscount\r\n\r\n",
- "size": 4,
- "title": "Estimated Saving",
+ "query": "let compressionRatio = 6.0; let selectedDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); let chargeableDays = max_of(todouble('{LakeTotalRetentionMonths}') * 30.0 - todouble('{LakeAnalyticsRetentionDays}'), 0.0); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | summarize RawGB = sum(Quantity) / 1024.0 | extend ['Estimated Monthly Storage Cost'] = RawGB / selectedDays * chargeableDays / compressionRatio * todouble('{LakeStoragePrice}') | project ['Estimated Monthly Storage Cost']",
+ "size": 1,
+ "title": "Est. Monthly Lake Storage Cost",
"timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No mirrored table usage data was found in the selected time range.",
+ "noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
@@ -946,7 +2066,7 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "TotalDiscount",
+ "columnMatch": "Estimated Monthly Storage Cost",
"formatter": 12,
"formatOptions": {
"palette": "greenRed"
@@ -963,146 +2083,201 @@
"showBorder": false
}
},
- "customWidth": "20",
- "conditionalVisibilities": [
- {
- "parameterName": "TotalMdcPlan2",
- "comparison": "isNotEqualTo",
- "value": "0"
- },
- {
- "parameterName": "TotalMdcPlan2",
- "comparison": "isNotEqualTo"
- }
- ],
- "name": "EstimateMdcPlan2Discount"
+ "customWidth": "25",
+ "name": "DataLakeEstimatedMonthlyStorageCost"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let LicenseCost = (15*toreal({TotalMdcPlan2}));\r\nprint LicenseCost\r\n",
- "size": 4,
- "title": "Defedner For Servers Plan 2 Licensing Cost",
+ "query": "let compressionRatio = 6.0; let selectedDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); let chargeableDays = max_of(todouble('{LakeTotalRetentionMonths}') * 30.0 - todouble('{LakeAnalyticsRetentionDays}'), 0.0); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | summarize RawGB = sum(Quantity) / 1024.0 by DataType | extend AvgDailyRawGB = RawGB / selectedDays | extend RetainedRawGB = AvgDailyRawGB * chargeableDays | extend CompressedGB = RetainedRawGB / compressionRatio | project ['Log Type'] = DataType, ['Avg Daily Volume'] = AvgDailyRawGB, ['Lake Retained Volume'] = RetainedRawGB, ['Billed Compressed Volume'] = CompressedGB, ['Monthly Storage Cost'] = CompressedGB * todouble('{LakeStoragePrice}') | order by ['Monthly Storage Cost'] desc",
+ "size": 1,
+ "title": "Estimated data lake storage cost by table (steady state at {LakeTotalRetentionMonths}-month retention)",
"timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No mirrored table usage data was found in the selected time range.",
+ "noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
"{Workspace}"
],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "print_0",
- "formatter": 12,
- "formatOptions": {
- "palette": "redGreen"
+ "visualization": "table",
+ "gridSettings": {
+ "showExportToExcel": true,
+ "formatters": [
+ {
+ "columnMatch": "Log Type",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "2fr"
+ }
},
- "numberFormat": {
- "unit": 0,
- "options": {
- "currency": "USD",
- "style": "currency",
- "maximumFractionDigits": 0
+ {
+ "columnMatch": "Avg Daily Volume",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "1fr"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 3
+ }
+ }
+ },
+ {
+ "columnMatch": "Lake Retained Volume",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "1fr"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ {
+ "columnMatch": "Billed Compressed Volume",
+ "formatter": 3,
+ "formatOptions": {
+ "palette": "blue",
+ "customColumnWidthSetting": "1fr"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ {
+ "columnMatch": "Monthly Storage Cost",
+ "formatter": 3,
+ "formatOptions": {
+ "palette": "greenRed",
+ "customColumnWidthSetting": "1fr"
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency",
+ "maximumFractionDigits": 2
+ }
}
}
- },
- "showBorder": false,
- "sortCriteriaField": "LicenseCost"
+ ],
+ "labelSettings": [
+ {
+ "columnId": "Avg Daily Volume",
+ "label": "Avg daily (GB)"
+ },
+ {
+ "columnId": "Lake Retained Volume",
+ "label": "Retained raw (GB)"
+ },
+ {
+ "columnId": "Billed Compressed Volume",
+ "label": "Billed compressed (GB)"
+ }
+ ]
}
},
- "customWidth": "20",
- "conditionalVisibilities": [
- {
- "parameterName": "TotalMdcPlan2",
- "comparison": "isNotEqualTo",
- "value": "0"
- },
- {
- "parameterName": "TotalMdcPlan2",
- "comparison": "isNotEqualTo"
+ "name": "DataLakeStorageCostByTable"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let lakeOnlyGB = todouble('{LakeOnlyIngestionGB}'); let queryScannedGB = todouble('{LakeQueryScannedGB}'); let insightsHours = todouble('{LakeInsightsHours}'); union (print SortOrder = 1, Meter = 'Data lake ingestion', Basis = 'Lake-tier-only tables, not visible in the workspace', Volume = lakeOnlyGB, Unit = 'GB/month', Cost = lakeOnlyGB * todouble('{LakeIngestionPrice}')), (print SortOrder = 2, Meter = 'Data processing', Basis = 'Lake-tier-only tables, not visible in the workspace', Volume = lakeOnlyGB, Unit = 'GB/month', Cost = lakeOnlyGB * todouble('{LakeProcessingPrice}')), (print SortOrder = 3, Meter = 'Data lake query', Basis = 'Uncompressed data scanned by KQL queries and jobs', Volume = queryScannedGB, Unit = 'GB/month', Cost = queryScannedGB * todouble('{LakeQueryPrice}')), (print SortOrder = 4, Meter = 'Advanced data insights', Basis = 'Notebook and job compute time', Volume = insightsHours, Unit = 'hours/month', Cost = insightsHours * todouble('{LakeInsightsPrice}')) | order by SortOrder asc | project Meter, ['Billing basis'] = Basis, ['Entered volume'] = iif(isnull(Volume), 'Not set', strcat(tostring(round(Volume, 2)), ' ', Unit)), ['Estimated monthly cost'] = iif(isnull(Cost), 'N/A - enter a volume above', strcat('$', tostring(round(Cost, 2))))",
+ "size": 1,
+ "title": "Data lake meters that cannot be measured from the workspace",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "table",
+ "gridSettings": {
+ "formatters": [
+ {
+ "columnMatch": "Meter",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "1fr"
+ }
+ },
+ {
+ "columnMatch": "Billing basis",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "2fr"
+ }
+ },
+ {
+ "columnMatch": "Entered volume",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "1fr"
+ }
+ },
+ {
+ "columnMatch": "Estimated monthly cost",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "1fr"
+ }
+ }
+ ]
}
- ],
- "name": "EstimateMdcPlan2Discount - Copy"
+ },
+ "name": "DataLakeManualMeterEstimates"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let DailyMaxDiscountGB = ((500*toreal({TotalMdcPlan2}))/1024);\r\nlet LicenseCost = (15*toreal({TotalMdcPlan2}));\r\nUsage\r\n| where IsBillable == true\r\n| where DataType in (\"SecurityAlert\", \r\n\"SecurityBaseline\",\r\n\"SecurityBaselineSummary\",\r\n\"SecurityDetection\",\r\n\"SecurityEvent\",\r\n\"WindowsFirewall\",\r\n\"ProtectionStatus\",\r\n\"MDCFileIntegrityMonitoringEvents\")   \r\n| summarize DailyBillableGB = toreal(sum(Quantity))/ 1024 by format_datetime(TimeGenerated, 'yy-MM-dd') \r\n| summarize TotalEligibleGB = sum(iif(toreal(DailyBillableGB)>toreal(DailyMaxDiscountGB),toreal(DailyMaxDiscountGB),DailyBillableGB))\r\n| extend TotalDiscount = toreal(TotalEligibleGB)*{Price}\r\n| project TotalDiscount - LicenseCost\r\n\r\n",
- "size": 4,
- "title": "Estimated Savings After Licensing Cost",
+ "query": "let selectedDuration = {TimeRange:end} - {TimeRange:start}; let timeGrain = case(selectedDuration <= 1h, 5m, selectedDuration <= 4h, 15m, selectedDuration <= 1d, 1h, selectedDuration <= 7d, 6h, selectedDuration <= 31d, 1d, selectedDuration <= 90d, 7d, 30d); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | summarize ['Mirrored Volume'] = sum(Quantity) / 1024.0 by bin(TimeGenerated, timeGrain) | order by TimeGenerated asc",
+ "size": 1,
+ "title": "Mirrored Volume in the {TimeRange}",
"timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No mirrored table usage data was found in the selected time range.",
+ "noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
"{Workspace}"
],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "Column1",
- "formatter": 18,
- "formatOptions": {
- "thresholdsOptions": "icons",
- "thresholdsGrid": [
- {
- "operator": "<",
- "thresholdValue": "0",
- "representation": "dot-red",
- "text": "{0}{1}"
- },
- {
- "operator": ">",
- "thresholdValue": "0",
- "representation": "dot-green",
- "text": "{0}{1}"
- },
- {
- "operator": "Default",
- "thresholdValue": null,
- "representation": "Line",
- "text": "{0}{1}"
- }
- ]
- },
- "numberFormat": {
- "unit": 0,
+ "visualization": "linechart",
+ "chartSettings": {
+ "xAxis": "TimeGenerated",
+ "showDataPoints": true,
+ "ySettings": {
+ "numberFormatSettings": {
+ "unit": 39,
"options": {
- "currency": "USD",
- "style": "currency",
- "useGrouping": true,
- "maximumFractionDigits": 2
+ "style": "decimal",
+ "maximumFractionDigits": 3
}
}
- },
- "showBorder": false,
- "sortCriteriaField": "Column1",
- "size": "auto"
+ }
}
},
- "customWidth": "20",
- "conditionalVisibilities": [
- {
- "parameterName": "TotalMdcPlan2",
- "comparison": "isNotEqualTo",
- "value": "0"
- },
- {
- "parameterName": "TotalMdcPlan2",
- "comparison": "isNotEqualTo"
- }
- ],
- "name": "EstimateMdcPlan2Discount - Copy"
+ "name": "DataLakeMirroredVolumeTrend"
}
]
},
- "name": "Defender for Cloud Plan 2 Ingestion Benefit"
+ "name": "group - Data Lake"
},
{
"type": 1,
"content": {
- "json": "## SOAR summary\r\n\r\nIn this section, you can view billable information regarding your Logic Apps. The data is based on Logic Apps' built-in metrics. To view the list of Logic Apps click the \">\" icon in the subscription column.\r\n\r\nYou can change the default Logic App execution cost in the parameter below.\r\n\r\nTo see the approximate cost of your logic apps, **click on any subscription on the table below**.\r\n\r\nFor more billable information, visit: https://azure.microsoft.com/pricing/details/logic-apps/"
+ "json": "## SOAR summary\r\n\r\nMicrosoft Sentinel playbooks use Azure Logic Apps to automate responses to incidents, alerts, and other security operations workflows. This section automatically discovers accessible Logic Apps and summarizes billable executions from Azure Monitor metrics.\r\n\r\nAll accessible subscriptions and resource groups are included by default, and the first 10 discovered Logic Apps are selected with concrete resource IDs. Use the Logic Apps control to change or expand that selection. The execution table updates directly from the selected Logic Apps and time range. Select a row to calculate the estimated automation cost for that scope using the **Logic App execution cost** value below. It does not query the `AzureMetrics` table and is not affected when `AzureMetrics` is configured as Basic Logs.\r\n\r\nReview [Automate threat response with playbooks in Microsoft Sentinel](https://learn.microsoft.com/azure/sentinel/automation/automate-responses-with-playbooks) for playbook guidance. Because playbooks use Azure Logic Apps, additional charges can apply. Go to the [Azure Logic Apps](https://azure.microsoft.com/pricing/details/logic-apps/) pricing page for more details."
},
"name": "text - 3"
},
@@ -1126,6 +2301,7 @@
],
"isHiddenWhenLocked": true,
"typeSettings": {
+ "additionalResourceOptions": [],
"includeAll": true
},
"timeContext": {
@@ -1142,11 +2318,11 @@
"multiSelect": true,
"quote": "'",
"delimiter": ",",
- "query": "Resources\r\n| where type in~ ({ResourceTypes})\r\n| summarize Count = count() by subscriptionId\r\n| order by Count desc\r\n| extend Rank = row_number()\r\n| project value = subscriptionId, label = subscriptionId, selected = Rank == 1",
"typeSettings": {
"additionalResourceOptions": [
"value::all"
],
+ "includeAll": true,
"showDefault": false
},
"timeContext": {
@@ -1169,7 +2345,10 @@
"multiSelect": true,
"quote": "'",
"delimiter": ",",
- "query": "Resources\r\n| where type in~ ({ResourceTypes})\r\n| summarize Count = count() by subscriptionId, resourceGroup\r\n| order by Count desc\r\n| extend Rank = row_number()\r\n| project value = strcat('/subscriptions/', subscriptionId, '/resourceGroups/', resourceGroup), label = resourceGroup, selected = false",
+ "query": "Resources\r\n| where type in~ ({ResourceTypes})\r\n| summarize Count = count() by subscriptionId, resourceGroup\r\n| order by Count desc\r\n| project value = strcat('/subscriptions/', subscriptionId, '/resourceGroups/', resourceGroup), label = resourceGroup",
+ "crossComponentResources": [
+ "{Subscription}"
+ ],
"typeSettings": {
"additionalResourceOptions": [
"value::all"
@@ -1196,14 +2375,12 @@
"multiSelect": true,
"quote": "'",
"delimiter": ",",
- "query": "Resources\r\n| where type in~({ResourceTypes})\r\n| extend resourceGroupId = strcat('/subscriptions/', subscriptionId, '/resourceGroups/', resourceGroup)\r\n| where resourceGroupId in~({ResourceGroups}) or '*' in~({ResourceGroups})\r\n| order by name asc\r\n| extend Rank = row_number()\r\n| project value = id, label = tostring(name), selected = Rank <= 10, group = resourceGroup",
- "value": [
- "value::all"
+ "query": "Resources\r\n| where type in~ ({ResourceTypes})\r\n| extend resourceGroupId = strcat('/subscriptions/', subscriptionId, '/resourceGroups/', resourceGroup)\r\n| where resourceGroupId in~ ({ResourceGroups}) or '*' in~ ({ResourceGroups})\r\n| order by name asc\r\n| extend Rank = row_number()\r\n| project value = id, label = tostring(name), selected = Rank <= 10, group = resourceGroup",
+ "crossComponentResources": [
+ "{Subscription}"
],
"typeSettings": {
- "additionalResourceOptions": [
- "value::all"
- ],
+ "additionalResourceOptions": [],
"showDefault": false
},
"timeContext": {
@@ -1219,6 +2396,16 @@
"label": "Logic App execution cost",
"type": 1,
"isRequired": true,
+ "description": "Enter the cost per Logic App execution used for the SOAR estimate.",
+ "typeSettings": {
+ "paramValidationRules": [
+ {
+ "regExp": "^(0|[1-9][0-9]*)(\\.[0-9]+)?$",
+ "match": true,
+ "message": "Enter a non-negative price."
+ }
+ ]
+ },
"value": "0.000125"
}
],
@@ -1226,14 +2413,14 @@
"queryType": 1,
"resourceType": "microsoft.resourcegraph/resources"
},
- "name": "parameters - 10"
+ "name": "parameters - SOAR resource selectors section"
},
{
"type": 10,
"content": {
"chartId": "workbooke70b7cbc-f1d7-4a74-b8b9-75cc8d5ab586",
"version": "MetricsItem/2.0",
- "size": 1,
+ "size": 0,
"chartType": 0,
"resourceType": "microsoft.logic/workflows",
"metricScope": 0,
@@ -1242,9 +2429,6 @@
"{Resources}"
],
"timeContextFromParameter": "TimeRange",
- "timeContext": {
- "durationMs": 7776000000
- },
"metrics": [
{
"namespace": "microsoft.logic/workflows",
@@ -1252,29 +2436,26 @@
"aggregation": 1
}
],
- "title": "Click on a subscription below to calculate the estimated automation costs",
+ "title": "Logic App billable executions in the {TimeRange}",
+ "noDataMessage": "No Logic App metric data is available for the selected scope and time range. Confirm that the Logic Apps are accessible, then expand the time range or choose a narrower scope.",
+ "noDataMessageStyle": 3,
"resourceLimit": 10000,
"gridSettings": {
"formatters": [
{
- "columnMatch": "$gen_group",
- "formatter": 15,
+ "columnMatch": "Subscription",
+ "formatter": 5,
"formatOptions": {
- "showIcon": true,
- "customColumnWidthSetting": "10fr"
+ "customColumnWidthSetting": "1fr"
}
},
- {
- "columnMatch": "Subscription",
- "formatter": 5
- },
{
"columnMatch": "Name",
"formatter": 13,
"formatOptions": {
"linkTarget": "Resource",
"showIcon": true,
- "customColumnWidthSetting": "10fr"
+ "customColumnWidthSetting": "2fr"
}
},
{
@@ -1283,7 +2464,7 @@
"formatOptions": {
"palette": "blue",
"aggregation": "Sum",
- "customColumnWidthSetting": "15fr"
+ "customColumnWidthSetting": "1fr"
}
},
{
@@ -1291,7 +2472,7 @@
"formatter": 21,
"formatOptions": {
"palette": "blue",
- "customColumnWidthSetting": "15fr"
+ "customColumnWidthSetting": "2fr"
}
},
{
@@ -1319,6 +2500,7 @@
"columnMatch": "RG",
"formatter": 13,
"formatOptions": {
+ "linkTarget": null,
"showIcon": true
}
},
@@ -1337,13 +2519,6 @@
}
],
"rowLimit": 10000,
- "filter": true,
- "hierarchySettings": {
- "treeType": 1,
- "groupBy": [
- "Subscription"
- ]
- },
"labelSettings": [
{
"columnId": "microsoft.logic/workflows--TotalBillableExecutions",
@@ -1355,20 +2530,65 @@
}
]
},
+ "sortBy": [],
"exportFieldName": "microsoft.logic/workflows--TotalBillableExecutions",
"exportParameterName": "Total",
- "exportDefaultValue": "0"
+ "exportDefaultValue": "N/A"
},
- "customWidth": "60",
"name": "Billable Metric"
},
+ {
+ "type": 1,
+ "content": {
+ "json": "> **N/A:** No Logic App metric row is selected. Select a Logic App or subscription rollup above after metric data loads. If the grid is empty, confirm access to the selected Logic Apps and try a wider time range.",
+ "style": "info"
+ },
+ "conditionalVisibility": {
+ "parameterName": "Total",
+ "comparison": "isEqualTo",
+ "value": "N/A"
+ },
+ "name": "text - SOAR metric selection required"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "print ['Total billable executions'] = todouble('{Total}')",
+ "size": 1,
+ "title": "Total billable executions: selected scope",
+ "timeContext": {
+ "durationMs": 86400000
+ },
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "Total billable executions",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "blue"
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "name": "SOARBillableExecutions",
+ "customWidth": "50",
+ "conditionalVisibility": {
+ "parameterName": "Total",
+ "comparison": "isNotEqualTo",
+ "value": "N/A"
+ }
+ },
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "Usage | take 1 | project ['Estimated automation costs'] ={Total}*{ExecutionCost}",
- "size": 4,
- "title": "Estimated Logic App execution cost over the last {TimeRange}",
+ "query": "print ['Estimated automation cost'] = todouble('{Total}') * todouble('{ExecutionCost}')",
+ "size": 1,
+ "title": "Estimated automation cost: selected scope",
"timeContext": {
"durationMs": 86400000
},
@@ -1377,7 +2597,7 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "Estimated automation costs",
+ "columnMatch": "Estimated automation cost",
"formatter": 12,
"formatOptions": {
"palette": "greenRed"
@@ -1395,16 +2615,16 @@
"showBorder": false
}
},
+ "name": "SOAREstimatedAutomationCost",
+ "customWidth": "50",
"conditionalVisibility": {
"parameterName": "Total",
- "comparison": "isNotEqualTo"
- },
- "name": "query - 11"
+ "comparison": "isNotEqualTo",
+ "value": "N/A"
+ }
}
],
- "fallbackResourceIds": [
- "Azure Monitor"
- ],
+ "fallbackResourceIds": [],
"fromTemplateId": "sentinel-CostWorkbook",
"$schema": "https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json"
-}
+}
\ No newline at end of file
diff --git a/Workbooks/SentinelCosts.json b/Workbooks/SentinelCosts.json
index d27d9c1d370..37a6cc5ae94 100644
--- a/Workbooks/SentinelCosts.json
+++ b/Workbooks/SentinelCosts.json
@@ -1,2171 +1,968 @@
{
- "version": "Notebook/1.0",
- "items": [
- {
- "type": 1,
- "content": {
- "json": "# Microsoft Sentinel cost summary\n---\n"
- },
- "name": "text - 2"
- },
- {
- "type": 9,
- "content": {
- "version": "KqlParameterItem/1.0",
- "parameters": [
- {
- "id": "9d001d6f-301c-4d03-b02c-b8cc6dce210b",
- "version": "KqlParameterItem/1.0",
- "name": "TimeRange",
- "type": 4,
- "isRequired": true,
- "value": {
- "durationMs": 604800000
- },
- "typeSettings": {
- "selectableValues": [
- {
- "durationMs": 300000
- },
- {
- "durationMs": 900000
- },
- {
- "durationMs": 1800000
- },
- {
- "durationMs": 3600000
- },
- {
- "durationMs": 14400000
- },
- {
- "durationMs": 43200000
- },
- {
- "durationMs": 86400000
- },
- {
- "durationMs": 172800000
- },
- {
- "durationMs": 259200000
- },
- {
- "durationMs": 604800000
- },
- {
- "durationMs": 1209600000
- },
- {
- "durationMs": 2419200000
- },
- {
- "durationMs": 2592000000
- },
- {
- "durationMs": 5184000000
- },
- {
- "durationMs": 7776000000
- }
- ],
- "allowCustom": true
- },
- "timeContext": {
- "durationMs": 86400000
- }
- },
- {
- "id": "67c2ce6e-ea54-4ae4-8343-3fcad8e53d1b",
- "version": "KqlParameterItem/1.0",
- "name": "Workspace",
- "type": 5,
- "isRequired": true,
- "multiSelect": true,
- "quote": "\u0027",
- "delimiter": ",",
- "query": "resources | where type =~ \u0027Microsoft.operationsmanagement/solutions\u0027 | where name contains \u0027SecurityInsights\u0027 | extend workspaceResourceId = tostring(properties.workspaceResourceId) | join kind=leftouter (resources | where type =~ \u0027Microsoft.OperationalInsights/workspaces\u0027 | project workspaceResourceId = id, workspaceName = name) on workspaceResourceId | project value = workspaceResourceId, label = coalesce(workspaceName, workspaceResourceId)",
- "crossComponentResources": [
- "value::all"
- ],
- "value": [
- "value::all"
- ],
- "typeSettings": {
- "limitSelectTo": 100,
- "additionalResourceOptions": [
- "value::all"
- ],
- "showDefault": false
- },
- "timeContext": {
- "durationMs": 86400000
- },
- "queryType": 1,
- "resourceType": "microsoft.resourcegraph/resources"
- },
- {
- "id": "9375c625-e916-4f48-b072-352d6aeefddb",
- "version": "KqlParameterItem/1.0",
- "name": "Price",
- "label": "Ingestion price",
- "type": 1,
- "description": "Enter your ingestion price per GB (PAYG or Commitment Tier). You can also refer to Azure Pricing Calculator.",
- "typeSettings": {
- "paramValidationRules": [
- {
- "regExp": "^(0|[1-9][0-9]*)(\\.[0-9]+)?$",
- "match": true,
- "message": "Enter a non-negative price."
- }
- ]
- },
- "value": "4"
- },
- {
- "id": "9d5299d0-36a0-4666-9803-ca6931bdaab7",
- "version": "KqlParameterItem/1.0",
- "name": "RetentionPrice",
- "label": "Retention price",
- "type": 1,
- "description": "Enter the retention price per GB/month that will be used in this workbook\u0027s calculations",
- "typeSettings": {
- "paramValidationRules": [
- {
- "regExp": "^(0|[1-9][0-9]*)(\\.[0-9]+)?$",
- "match": true,
- "message": "Enter a non-negative price."
- }
- ]
- },
- "value": "0.1"
- },
- {
- "id": "8f552e99-2d30-4679-b4b0-25429bf0216b",
- "version": "KqlParameterItem/1.0",
- "name": "ExecutionCost",
- "label": "Logic App execution cost",
- "type": 1,
- "isRequired": true,
- "description": "Enter the cost per Logic App execution used for the SOAR estimate.",
- "typeSettings": {
- "paramValidationRules": [
- {
- "regExp": "^(0|[1-9][0-9]*)(\\.[0-9]+)?$",
- "match": true,
- "message": "Enter a non-negative price."
- }
- ]
- },
- "value": "0.000125"
- },
- {
- "id": "67494f3e-322e-4411-9b45-1cbea03ed618",
- "version": "KqlParameterItem/1.0",
- "name": "TotalE5Seats",
- "label": "Total Microsoft 365 E7/E5/A5/F5/G5 seats",
- "type": 1,
- "quote": "\u0027",
- "description": "Enter the total number of eligible Microsoft 365 E7, E5, A5, F5, and G5 or corresponding Security licenses in your environment. Eligibility depends on the current offer terms and agreement type.",
- "value": "\u003cunset\u003e",
- "typeSettings": {
- "paramValidationRules": [
- {
- "regExp": "^([1-9][0-9]*|\u003cunset\u003e|)$",
- "match": true,
- "message": "Enter a whole number greater than zero, or clear the value."
- }
- ]
- }
- },
- {
- "id": "f1a5dc2c-7e7f-4e48-9d65-0d52e77b6e3a",
- "version": "KqlParameterItem/1.0",
- "name": "TotalDfSP2Licenses",
- "label": "Protected Defender for Servers Plan 2 servers or nodes",
- "type": 1,
- "quote": "\u0027",
- "description": "Enter the number of protected Defender for Servers Plan 2 servers or nodes used to estimate the 500 MB per server or node per day ingestion benefit. Leave as \u003cunset\u003e when the entitlement is unknown; grant and savings metrics will show N/A.",
- "value": "\u003cunset\u003e",
- "typeSettings": {
- "paramValidationRules": [
- {
- "regExp": "^([1-9][0-9]*|\u003cunset\u003e|)$",
- "match": true,
- "message": "Enter a whole number greater than zero, or clear the value."
- }
- ]
- }
- }
- ],
- "style": "pills",
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces"
- },
- "name": "parameters - 5"
- },
- {
- "type": 1,
- "content": {
- "json": "---\r\n### Optional: SOAR automation inputs\r\n\r\nThe selectors below are optional. Set **Subscriptions**, **Resource groups**, and **Logic Apps** only if you want to estimate SOAR/Logic App automation costs in the SOAR summary section further down. Microsoft Sentinel Data Lake costs cannot be estimated from Log Analytics `Usage` data, so no additional parameters are needed for the Data Lake section."
- },
- "name": "text - optional SOAR and Data Lake inputs"
- },
- {
- "type": 9,
- "content": {
- "version": "KqlParameterItem/1.0",
- "parameters": [
- {
- "id": "6f50ee54-8f0e-424e-9e16-70eca531af7f",
- "version": "KqlParameterItem/1.0",
- "name": "ResourceTypes",
- "label": "Resource types",
- "type": 7,
- "isRequired": true,
- "multiSelect": true,
- "quote": "\u0027",
- "delimiter": ",",
- "value": [
- "microsoft.logic/workflows"
- ],
- "isHiddenWhenLocked": true,
- "typeSettings": {
- "additionalResourceOptions": [
-
- ],
- "includeAll": true
- },
- "timeContext": {
- "durationMs": 86400000
- }
- },
- {
- "id": "1c8dc8da-2233-426c-8cfc-52ec31bf1e84",
- "version": "KqlParameterItem/1.0",
- "name": "Subscription",
- "label": "Subscriptions",
- "type": 6,
- "isRequired": true,
- "multiSelect": true,
- "quote": "\u0027",
- "delimiter": ",",
- "query": "Resources\r\n| where type in~ ({ResourceTypes})\r\n| summarize Count = count() by subscriptionId\r\n| order by Count desc\r\n| extend Rank = row_number()\r\n| project value = subscriptionId, label = subscriptionId, selected = Rank == 1",
- "typeSettings": {
- "additionalResourceOptions": [
- "value::all"
- ],
- "showDefault": false
- },
- "timeContext": {
- "durationMs": 86400000
- },
- "defaultValue": "value::all",
- "queryType": 1,
- "resourceType": "microsoft.resourcegraph/resources",
- "value": [
- "value::all"
- ]
- },
- {
- "id": "f103ef04-042e-45ed-8f78-b31e676258d7",
- "version": "KqlParameterItem/1.0",
- "name": "ResourceGroups",
- "label": "Resource groups",
- "type": 2,
- "isRequired": true,
- "multiSelect": true,
- "quote": "\u0027",
- "delimiter": ",",
- "query": "Resources\r\n| where type in~ ({ResourceTypes})\r\n| summarize Count = count() by subscriptionId, resourceGroup\r\n| order by Count desc\r\n| extend Rank = row_number()\r\n| project value = strcat(\u0027/subscriptions/\u0027, subscriptionId, \u0027/resourceGroups/\u0027, resourceGroup), label = resourceGroup, selected = false",
- "typeSettings": {
- "additionalResourceOptions": [
- "value::all"
- ],
- "showDefault": false
- },
- "timeContext": {
- "durationMs": 86400000
- },
- "defaultValue": "value::all",
- "queryType": 1,
- "resourceType": "microsoft.resourcegraph/resources",
- "value": [
- "value::all"
- ]
- },
- {
- "id": "b6514d02-8893-44b8-896e-e53ada5024d5",
- "version": "KqlParameterItem/1.0",
- "name": "Resources",
- "label": "Logic Apps",
- "type": 5,
- "isRequired": true,
- "multiSelect": true,
- "quote": "\u0027",
- "delimiter": ",",
- "query": "Resources\r\n| where type in~({ResourceTypes})\r\n| extend resourceGroupId = strcat(\u0027/subscriptions/\u0027, subscriptionId, \u0027/resourceGroups/\u0027, resourceGroup)\r\n| where resourceGroupId in~({ResourceGroups}) or \u0027*\u0027 in~({ResourceGroups})\r\n| order by name asc\r\n| extend Rank = row_number()\r\n| project value = id, label = tostring(name), selected = Rank \u003c= 10, group = resourceGroup",
- "value": [
- "value::all"
- ],
- "typeSettings": {
- "additionalResourceOptions": [
- "value::all"
- ],
- "showDefault": false
- },
- "timeContext": {
- "durationMs": 86400000
- },
- "queryType": 1,
- "resourceType": "microsoft.resourcegraph/resources"
- }
- ],
- "style": "pills",
- "queryType": 1,
- "resourceType": "microsoft.resourcegraph/resources"
- },
- "name": "parameters - SOAR resource selectors"
- },
- {
- "type": 1,
- "content": {
- "json": "## Ingestion summary"
- },
- "name": "text - ingestion summary"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let selectedDays = max_of(datetime_diff(\u0027second\u0027, {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); union withsource = SourceTableName * | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where _IsBillable == true | summarize [\u0027Average Billable Daily Ingestion\u0027] = sum(_BilledSize) / 1024.0 / 1024.0 / 1024.0 / selectedDays",
- "size": 1,
- "title": "Average Billable Daily Ingestion",
- "timeContextFromParameter": "TimeRange",
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "Average Billable Daily Ingestion",
- "formatter": 12,
- "formatOptions": {
- "palette": "greenRed"
- },
- "numberFormat": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "maximumFractionDigits": 2
- }
- }
- },
- "showBorder": false,
- "size": "auto"
- }
- },
- "name": "query - 6",
- "customWidth": "25"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let selectedDays = max_of(datetime_diff(\u0027second\u0027, {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); union withsource = SourceTableName * | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where _IsBillable == true | summarize [\u0027Estimated Average Daily Ingestion Cost\u0027] = sum(_BilledSize) / 1024.0 / 1024.0 / 1024.0 / selectedDays * todouble(\u0027{Price}\u0027)",
- "size": 1,
- "title": "Estimated Daily Ingestion Cost",
- "timeContextFromParameter": "TimeRange",
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "Estimated Average Daily Ingestion Cost",
- "formatter": 12,
- "formatOptions": {
- "palette": "greenRed"
- },
- "numberFormat": {
- "unit": 0,
- "options": {
- "currency": "USD",
- "style": "currency",
- "maximumFractionDigits": 2
- }
- }
- },
- "showBorder": false,
- "size": "auto"
- }
- },
- "name": "AverageDailyBillableIngestionCost",
- "customWidth": "25"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true | summarize [\u0027Total Billable Ingestion\u0027] = sum(Quantity) / 1024.0",
- "size": 1,
- "title": "Billable Ingestion: {TimeRange}",
- "timeContextFromParameter": "TimeRange",
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "Total Billable Ingestion",
- "formatter": 12,
- "formatOptions": {
- "palette": "greenRed"
- },
- "numberFormat": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "useGrouping": false,
- "maximumFractionDigits": 1
- }
- }
- },
- "showBorder": false,
- "size": "auto"
- }
- },
- "name": "query - 8",
- "customWidth": "50"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true | summarize TotalBillableIngestionGB = sum(Quantity) / 1024.0 | project [\u0027Estimated Ingestion Cost\u0027] = TotalBillableIngestionGB * todouble(\u0027{Price}\u0027)",
- "size": 1,
- "title": "Estimated Ingestion Cost: {TimeRange}",
- "timeContextFromParameter": "TimeRange",
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "Estimated Ingestion Cost",
- "formatter": 12,
- "formatOptions": {
- "palette": "greenRed"
- },
- "numberFormat": {
- "unit": 0,
- "options": {
- "currency": "USD",
- "style": "currency",
- "maximumFractionDigits": 2
- }
- }
- },
- "showBorder": false
- }
- },
- "name": "BillableIngestionCost",
- "customWidth": "50"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let Categories = datatable(Type:string,Category:string)\r\n[\r\n \"AuditLogs\", \"Azure Active Directory\",\r\n \"SigninLogs\", \"Azure Active Directory\",\r\n \"AADNonInteractiveUserSignInLogs\", \"Azure Active Directory\",\r\n \"AADServicePrincipalSignInLogs\", \"Azure Active Directory\",\r\n \"AADManagedIdentitySignInLogs\", \"Azure Active Directory\",\r\n \"AADProvisioningLogs\",\"Azure Active Directory\",\r\n \"BehaviorAnalytics\", \"User Entity Behavior Analytics\",\r\n \"UserPeerAnalytics\",\"User Entity Behavior Analytics\",\r\n \"UserAccessAnalytics\",\"User Entity Behavior Analytics\",\r\n \"IdentityInfo\",\"User Entity Behavior Analytics\",\r\n \"DeviceLogonEvents\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceEvents\",\"Microsoft Defender for Endpoint\",\r\n\t\"DeviceNetworkInfo\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceImageLoadEvents\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceFileEvents\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceInfo\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceProcessEvents\", \"Microsoft Defender for Endpoint\",\t\r\n\t\"DeviceNetworkEvents\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceRegistryEvents\", \"Microsoft Defender for Endpoint\",\r\n \"DeviceFileCertificateInfo\", \"Microsoft Defender for Endpoint\",\r\n \"EmailAttachmentInfo\", \"Microsoft Defender for Office 365\", \r\n \"EmailEvents\", \"Microsoft Defender for Office 365\", \r\n \"EmailPostDeliveryEvents\", \"Microsoft Defender for Office 365\", \r\n \"EmailUrlInfo\", \"Microsoft Defender for Office 365\",\r\n \"IdentityLogonEvents\", \"Microsoft Defender for Identity\",\r\n \"IdentityQueryEvents\", \"Microsoft Defender for Identity\",\r\n \"IdentityDirectoryEvents\", \"Microsoft Defender for Identity\",\r\n \"CloudAppEvents\", \"Microsoft Defender for Cloud Apps\",\r\n \"AlertEvidence\", \"Microsoft Defender Alert Evidence\",\r\n \"InsightsMetrics\", \"Azure Monitor for VMs\",\r\n \"VMBoundPort\", \"Azure Monitor for VMs\",\r\n \"VMComputer\", \"Azure Monitor for VMs\",\r\n \"VMConnection\", \"Azure Monitor for VMs\",\r\n \"VMProcess\", \"Azure Monitor for VMs\",\r\n \"SecurityEvent\", \"Windows Security Events\",\r\n \"Syslog\", \"Syslog/CEF\",\r\n \"CommonSecurityLog\", \"Syslog/CEF\",\r\n \"ThreatIntelligenceIndicator\", \"Threat Intelligence\",\r\n \"DnsEvents\", \"DNS Logs\",\r\n \"DnsInventory\", \"DNS Logs\",\r\n \"AWSCloudTrail\", \"AWS Cloud Trail\",\r\n \"ConfigurationChange\", \"Change Tracking\",\r\n \"ConfigurationData\", \"Change Tracking\",\r\n \"AzureDiagnostics\", \"Azure Resources\",\r\n \"LAQueryLogs\", \"Management\",\r\n \"SentinelHealth\",\"Management\",\r\n \"Perf\",\"Performance\",\r\n \"AzureMetrics\",\"Azure Metrics\",\r\n \"SecurityNestedRecommendation\", \"Microsoft Defender for Cloud\",\r\n \"SecurityRecommendation\", \"Microsoft Defender for Cloud\",\r\n \"SecurityRegulatoryCompliance\", \"Microsoft Defender for Cloud\",\r\n \"SecureScoreControls\", \"Microsoft Defender for Cloud\",\r\n \"SecurityBaseline\", \"Microsoft Defender for Cloud\",\r\n \"SecureScores\", \"Microsoft Defender for Cloud\",\r\n \"Update\", \"Update Management\",\r\n \"UpdateSummary\", \"Update Management\"\r\n];\r\nlet customTables = Usage\r\n| where TimeGenerated between ({TimeRange:start} .. {TimeRange:end})\r\n| where IsBillable == true\r\n| where DataType contains \"_CL\"\r\n| summarize size = sum(Quantity)/1024 by DataType\r\n| project [\u0027Log Type\u0027] = DataType, [\u0027Table Size\u0027] = size, [\u0027Estimated Cost\u0027] = size*{Price};\r\nlet knownTables = Usage\r\n| where TimeGenerated between ({TimeRange:start} .. {TimeRange:end})\r\n| where IsBillable == true \r\n| join kind=leftouter Categories on $left.DataType == $right.Type\r\n| summarize size =sumif(Quantity, isnotempty(Category))/1024, sizeOther= sumif(Quantity,(isempty(Category) and DataType !contains \"_CL\"))/1024 by Category\r\n| project [\u0027Log Type\u0027] = iif(isnotempty( Category),Category,\"Other\"), [\u0027Table Size\u0027] = iif(isnotempty( Category),size,sizeOther), [\u0027Estimated Cost\u0027] = iif(isnotempty(Category),size*{Price},sizeOther*4);\r\nunion customTables, knownTables\r\n| order by [\u0027Table Size\u0027] desc",
- "size": 1,
- "title": "Breakdown of billable ingestion by log category in the last {TimeRange}",
- "timeContextFromParameter": "TimeRange",
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "table",
- "gridSettings": {
- "formatters": [
- {
- "columnMatch": "Log Type",
- "formatter": 0,
- "formatOptions": {
- "customColumnWidthSetting": "35%"
- }
- },
- {
- "columnMatch": "Table Size",
- "formatter": 3,
- "formatOptions": {
- "palette": "greenRed",
- "customColumnWidthSetting": "40%"
- },
- "numberFormat": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "useGrouping": false
- }
- }
- },
- {
- "columnMatch": "Estimated Cost",
- "formatter": 0,
- "formatOptions": {
- "customColumnWidthSetting": "25%"
- },
- "numberFormat": {
- "unit": 0,
- "options": {
- "currency": "USD",
- "style": "currency"
- }
- }
- }
- ]
- },
- "graphSettings": {
- "type": 0,
- "topContent": {
- "columnMatch": "Log Category",
- "formatter": 1
- },
- "centerContent": {
- "columnMatch": "Billed Size",
- "formatter": 1,
- "numberFormat": {
- "unit": 17,
- "options": {
- "maximumSignificantDigits": 3,
- "maximumFractionDigits": 2
- }
- }
- }
- }
- },
- "name": "query - 2"
- },
- {
- "type": 1,
- "content": {
- "json": "## Free Sentinel Data Summary\r\n\r\nMicrosoft documents the following Sentinel data sources as free:\r\n\r\n- Azure Activity Logs (`AzureActivity`)\r\n- Health monitoring for Microsoft Sentinel (`SentinelHealth`)\r\n- Microsoft 365 audit activity (`OfficeActivity`)\r\n- Microsoft Entra ID Protection alerts (`SecurityAlert`)\r\n- Microsoft Defender for Cloud and Defender for IoT alerts (`SecurityAlert`)\r\n- Microsoft Defender XDR incidents and alerts (`SecurityIncident`, `SecurityAlert`)\r\n- Microsoft Defender for Endpoint, Identity, Cloud Apps, and Office 365 alerts (`SecurityAlert`)\r\n\r\nThis section estimates Analytics-tier ingestion in the selected workspace scope and keeps it separate from billable ingestion. It does not estimate data lake-only ingestion, storage, processing, or query charges. Usage is grouped by table and cannot reliably identify the originating connector, so `SecurityAlert` cannot be allocated reliably among its contributing services. This estimate does not calculate the separate Sentinel free trial. Review the [Microsoft Sentinel free data sources](https://learn.microsoft.com/en-us/azure/sentinel/billing?tabs=simplified%2Ccommitment-tiers#free-data-sources) documentation for current eligibility and billing terms."
- },
- "name": "text - free Sentinel data"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let freeTypes = dynamic([\"AzureActivity\",\"SentinelHealth\",\"OfficeActivity\",\"SecurityAlert\",\"SecurityIncident\"]); let periodDays = max_of(datetime_diff(\u0027second\u0027, {TimeRange:end}, {TimeRange:start}) / 86400.0, 1); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where DataType in (freeTypes) | summarize [\u0027Average Free Data Per Day\u0027] = sum(Quantity) / 1024.0 / periodDays",
- "size": 1,
- "title": "Average Free Data Per Day",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "No documented free Sentinel data was observed in the selected time range.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "Average Free Data Per Day",
- "formatter": 12,
- "formatOptions": {
- "palette": "blue"
- },
- "numberFormat": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "maximumFractionDigits": 3
- }
- }
- },
- "showBorder": false
- }
- },
- "customWidth": "25",
- "name": "FreeSentinelDataTotal"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let freeTypes = dynamic([\"AzureActivity\",\"SentinelHealth\",\"OfficeActivity\",\"SecurityAlert\",\"SecurityIncident\"]); let periodDays = max_of(datetime_diff(\u0027second\u0027, {TimeRange:end}, {TimeRange:start}) / 86400.0, 1); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where DataType in (freeTypes) | summarize [\u0027Estimated Free-Data Savings Per Day\u0027] = sum(Quantity) / 1024.0 / periodDays * todouble(\u0027{Price}\u0027)",
- "size": 1,
- "title": "Avg Daily Free-Data Savings",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "No documented free Sentinel data was observed in the selected time range.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "Estimated Free-Data Savings Per Day",
- "formatter": 12,
- "formatOptions": {
- "palette": "greenRed"
- },
- "numberFormat": {
- "unit": 0,
- "options": {
- "currency": "USD",
- "style": "currency",
- "maximumFractionDigits": 2
- }
- }
- },
- "showBorder": false
- }
- },
- "customWidth": "25",
- "name": "AverageDailyFreeDataSavings"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let freeTypes = dynamic([\"AzureActivity\",\"SentinelHealth\",\"OfficeActivity\",\"SecurityAlert\",\"SecurityIncident\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where DataType in (freeTypes) | summarize [\u0027Free Data\u0027] = sum(Quantity) / 1024.0",
- "size": 1,
- "title": "Free Data: {TimeRange}",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "No documented free Sentinel data was observed in the selected time range.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "Free Data",
- "formatter": 12,
- "formatOptions": {
- "palette": "blue"
- },
- "numberFormat": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "maximumFractionDigits": 3
- }
- }
- },
- "showBorder": false
- }
- },
- "customWidth": "25",
- "name": "FreeSentinelDataSavings"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let freeTypes = dynamic([\"AzureActivity\",\"SentinelHealth\",\"OfficeActivity\",\"SecurityAlert\",\"SecurityIncident\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where DataType in (freeTypes) | summarize [\u0027Estimated Free-Data Savings\u0027] = sum(Quantity) / 1024.0 * todouble(\u0027{Price}\u0027)",
- "size": 1,
- "title": "Free-Data Savings: {TimeRange}",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "No documented free Sentinel data was observed in the selected time range.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "Estimated Free-Data Savings",
- "formatter": 12,
- "formatOptions": {
- "palette": "greenRed"
- },
- "numberFormat": {
- "unit": 0,
- "options": {
- "currency": "USD",
- "style": "currency",
- "maximumFractionDigits": 2
- }
- }
- },
- "showBorder": false
- }
- },
- "customWidth": "25",
- "name": "FreeDataSavingsForTimeRange"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let freeTypes = dynamic([\"AzureActivity\",\"SentinelHealth\",\"OfficeActivity\",\"SecurityAlert\",\"SecurityIncident\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where DataType in (freeTypes) | summarize TableSizeGB = sum(Quantity) / 1024.0 by DataType | project [\u0027Log Type\u0027] = DataType, [\u0027Table Size\u0027] = TableSizeGB, [\u0027Estimated Cost Savings\u0027] = TableSizeGB * todouble(\u0027{Price}\u0027) | order by [\u0027Table Size\u0027] desc",
- "size": 1,
- "title": "Free data by source table in the last {TimeRange}",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "No documented free Sentinel data was observed in the selected time range.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "table",
- "gridSettings": {
- "showExportToExcel": true,
- "formatters": [
- {
- "columnMatch": "Log Type",
- "formatter": 0,
- "formatOptions": {
- "customColumnWidthSetting": "30%"
- }
- },
- {
- "columnMatch": "Table Size",
- "formatter": 3,
- "formatOptions": {
- "palette": "greenRed",
- "customColumnWidthSetting": "45%"
- },
- "numberFormat": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "maximumFractionDigits": 3
- }
- }
- },
- {
- "columnMatch": "Estimated Cost Savings",
- "formatter": 0,
- "formatOptions": {
- "customColumnWidthSetting": "25%"
- },
- "numberFormat": {
- "unit": 0,
- "options": {
- "currency": "USD",
- "style": "currency",
- "maximumFractionDigits": 2
- }
- }
- }
- ]
- }
- },
- "name": "FreeSentinelDataDetail"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let freeTypes = dynamic([\"AzureActivity\",\"SentinelHealth\",\"OfficeActivity\",\"SecurityAlert\",\"SecurityIncident\"]); let timeGrain = case({TimeRange:end} - {TimeRange:start} \u003c= 2d, 1h, {TimeRange:end} - {TimeRange:start} \u003c= 14d, 1d, {TimeRange:end} - {TimeRange:start} \u003c= 90d, 7d, 30d); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | summarize [\u0027Free Data Size\u0027] = sumif(Quantity, DataType in (freeTypes)) / 1024.0, [\u0027Billable Data Size\u0027] = sumif(Quantity, IsBillable == true) / 1024.0 by bin(TimeGenerated, timeGrain) | order by TimeGenerated asc",
- "size": 1,
- "title": "Free Data Size vs Billable Data Size in the last {TimeRange}",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "No free or billable Sentinel data was observed in the selected time range.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "linechart",
- "chartSettings": {
- "xAxis": "TimeGenerated",
- "showDataPoints": true,
- "ySettings": {
- "numberFormatSettings": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "maximumFractionDigits": 3
- }
- }
- }
- }
- },
- "name": "FreeDataVsBillableDataDaily"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "union withsource=TableName1 * | where TimeGenerated \u003c ago(90d) | extend key = \u0027Key\u0027 | summarize size = sum(_BilledSize)/1024/1024/1024 by key\r\n| project [\u0027Data over 90 days\u0027] = size, [\u0027Retention Cost\u0027] = size*{RetentionPrice}\r\n\r\n\r\n",
- "size": 1,
- "title": "Data older than 90 days and resulting retention cost",
- "noDataMessage": "You have no data older than 90 days",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "gridSettings": {
- "formatters": [
- {
- "columnMatch": "Data over 90 days",
- "formatter": 0,
- "numberFormat": {
- "unit": 36,
- "options": {
- "style": "decimal",
- "useGrouping": false
- }
- }
- },
- {
- "columnMatch": "Retention Cost",
- "formatter": 0,
- "numberFormat": {
- "unit": 0,
- "options": {
- "style": "decimal"
- }
- }
- }
- ]
- },
- "tileSettings": {
- "titleContent": {
-
- },
- "leftContent": {
- "columnMatch": "Data over 90 days",
- "formatter": 12,
- "formatOptions": {
- "palette": "greenRed"
- },
- "numberFormat": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "maximumFractionDigits": 1
- }
- }
- },
- "rightContent": {
- "columnMatch": "Retention Cost",
- "formatter": 12,
- "formatOptions": {
- "palette": "greenRed"
- },
- "numberFormat": {
- "unit": 0,
- "options": {
- "currency": "USD",
- "style": "currency",
- "maximumFractionDigits": 2
- }
- }
- },
- "showBorder": false,
- "size": "auto"
- }
- },
- "name": "query - 7",
- "conditionalVisibility": {
- "parameterName": "TotalE5Seats",
- "comparison": "isEqualTo",
- "value": "__never_display_legacy_retention__"
- }
- },
- {
- "type": 1,
- "content": {
- "json": "## Microsoft Sentinel benefit for Microsoft 365 E7/E5/A5/F5/G5 customers\r\n\r\nQualifying Microsoft 365 E7, E5, A5, F5, and G5 licenses, and corresponding Security licenses, may receive a Microsoft Sentinel data grant of up to 5 MB per qualifying user per day for eligible Microsoft 365 data.\r\n\r\nEligible data-source groups include:\r\n\r\n- Microsoft Entra ID sign-in and audit logs (`SigninLogs`, `AuditLogs`, `AADNonInteractiveUserSignInLogs`, `AADServicePrincipalSignInLogs`, `AADManagedIdentitySignInLogs`, `AADProvisioningLogs`, `ADFSSignInLogs`, `AADUserRiskEvents`, `AADRiskyUsers`)\r\n- Microsoft Defender for Cloud Apps Guard shadow IT discovery logs (`McasShadowItReporting`)\r\n- Microsoft Purview Information Protection logs (`InformationProtectionLogs_CL`)\r\n- Microsoft 365 advanced hunting data (the eligible `Device*`, `Email*`, `Identity*`, `AlertEvidence`, and `CloudAppEvents` tables shown below)\r\n\r\nThis workbook estimates the Analytics-tier ingestion benefit from billable Usage data in the selected workspace scope. It does not estimate data lake-only charges or prove that a row came from an eligible connector, that the offer applies to your agreement, or that the calculated amount matches billing. The grant cap is modeled once across the selected scope; it is not multiplied per workspace.\r\n\r\nReview the [Microsoft 365 Sentinel benefit offer](https://azure.microsoft.com/en-us/pricing/offers/sentinel-microsoft-365-offer/) for current eligibility, agreement terms, and supported data types. Enter **Total Microsoft 365 E7/E5/A5/F5/G5 seats** and **Ingestion price** above to calculate the estimate."
- },
- "name": "text - 12"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "Usage\r\n| where TimeGenerated between ({TimeRange:start} .. {TimeRange:end})\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\", \r\n\"DeviceFileEvents\", \r\n\"DeviceImageLoadEvents\", \r\n\"DeviceInfo\", \r\n\"DeviceLogonEvents\", \r\n\"DeviceNetworkEvents\", \r\n\"DeviceNetworkInfo\", \r\n\"DeviceProcessEvents\", \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\", \r\n\"EmailAttachmentInfo\", \r\n\"EmailEvents\", \r\n\"EmailPostDeliveryEvents\", \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\"\r\n) \r\n| summarize BillableDataGB = sum(Quantity) / 1000. by DataType\r\n| order by BillableDataGB desc\r\n",
- "size": 0,
- "title": "Eligible Microsoft 365 data by table (GB)",
- "timeContextFromParameter": "TimeRange",
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "gridSettings": {
- "formatters": [
- {
- "columnMatch": "BillableDataGB",
- "formatter": 3,
- "formatOptions": {
- "palette": "blue"
- },
- "numberFormat": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "maximumFractionDigits": 3
- }
- }
- }
- ]
- }
- },
- "name": "query - 13",
- "conditionalVisibility": {
- "parameterName": "TotalE5Seats",
- "comparison": "isEqualTo",
- "value": "__never_display_legacy_e5_table__"
- }
- },
- {
- "type": 1,
- "content": {
- "json": "Daily ingestion size vs Maximum data grant"
- },
- "name": "text - DailyIngestionVsAllocation",
- "conditionalVisibility": {
- "parameterName": "TotalE5Seats",
- "comparison": "isEqualTo",
- "value": "__never_display_legacy_e5_chart__"
- }
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "Usage\r\n| where TimeGenerated between ({TimeRange:start} .. {TimeRange:end})\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\", \r\n\"DeviceFileEvents\", \r\n\"DeviceImageLoadEvents\", \r\n\"DeviceInfo\", \r\n\"DeviceLogonEvents\", \r\n\"DeviceNetworkEvents\", \r\n\"DeviceNetworkInfo\", \r\n\"DeviceProcessEvents\", \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\", \r\n\"EmailAttachmentInfo\", \r\n\"EmailEvents\", \r\n\"EmailPostDeliveryEvents\", \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\") \r\n| summarize [\u0027Daily Ingestion\u0027] = toreal(sum(Quantity))/ 1024 by format_datetime(TimeGenerated, \u0027yyyy-MM-dd\u0027) \r\n| extend MaxDataGrantGB = ((5*todouble(\u0027{TotalE5Seats}\u0027))/1024)\r\n| sort by TimeGenerated asc\r\n",
- "size": 0,
- "aggregation": 3,
- "timeContextFromParameter": "TimeRange",
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "linechart",
- "chartSettings": {
- "xAxis": "TimeGenerated",
- "showDataPoints": true,
- "ySettings": {
- "numberFormatSettings": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "useGrouping": true,
- "maximumFractionDigits": 3
- }
- }
- }
- }
- },
- "name": "DailyIngestionVSAllocation",
- "conditionalVisibility": {
- "parameterName": "TotalE5Seats",
- "comparison": "isEqualTo",
- "value": "__never_display_legacy_e5_chart__"
- }
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "Usage\r\n| where TimeGenerated between ({TimeRange:start} .. {TimeRange:end})\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\", \r\n\"DeviceFileEvents\", \r\n\"DeviceImageLoadEvents\", \r\n\"DeviceInfo\", \r\n\"DeviceLogonEvents\", \r\n\"DeviceNetworkEvents\", \r\n\"DeviceNetworkInfo\", \r\n\"DeviceProcessEvents\", \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\", \r\n\"EmailAttachmentInfo\", \r\n\"EmailEvents\", \r\n\"EmailPostDeliveryEvents\", \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\"\r\n) \r\n| summarize TotalBillableDataGB = sum(Quantity) / 1024\r\n\r\n",
- "size": 1,
- "title": "Eligible M365 Data",
- "timeContextFromParameter": "TimeRange",
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "TotalBillableDataGB",
- "formatter": 12,
- "formatOptions": {
- "palette": "greenRed"
- },
- "numberFormat": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "maximumFractionDigits": 2
- }
- }
- },
- "showBorder": false
- }
- },
- "customWidth": "20",
- "name": "E5IngestionSize"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let DailyMaxDiscountGB = ((5*todouble(\u0027{TotalE5Seats}\u0027))/1024);\r\nUsage\r\n| where TimeGenerated between ({TimeRange:start} .. {TimeRange:end})\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\", \r\n\"DeviceFileEvents\", \r\n\"DeviceImageLoadEvents\", \r\n\"DeviceInfo\", \r\n\"DeviceLogonEvents\", \r\n\"DeviceNetworkEvents\", \r\n\"DeviceNetworkInfo\", \r\n\"DeviceProcessEvents\", \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\", \r\n\"EmailAttachmentInfo\", \r\n\"EmailEvents\", \r\n\"EmailPostDeliveryEvents\", \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\") \r\n| summarize DailyBillableGB = toreal(sum(Quantity))/ 1024 by format_datetime(TimeGenerated, \u0027yy-MM-dd\u0027) \r\n| extend DailyMaxGrantGB = DailyMaxDiscountGB\r\n| summarize MaxDataGrantGB = sum(toreal(DailyMaxGrantGB))\r\n\r\n",
- "size": 1,
- "title": "Total Data Grant Limit: {TimeRange}",
- "timeContextFromParameter": "TimeRange",
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "MaxDataGrantGB",
- "formatter": 12,
- "formatOptions": {
- "palette": "orangeBlue"
- },
- "numberFormat": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "maximumFractionDigits": 2
- }
- }
- },
- "showBorder": false,
- "sortOrderField": 1
- }
- },
- "customWidth": "20",
- "name": "DataGrantLimit"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let DailyMaxDiscountGB = ((5*todouble(\u0027{TotalE5Seats}\u0027))/1024);\r\nUsage\r\n| where TimeGenerated between ({TimeRange:start} .. {TimeRange:end})\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\", \r\n\"DeviceFileEvents\", \r\n\"DeviceImageLoadEvents\", \r\n\"DeviceInfo\", \r\n\"DeviceLogonEvents\", \r\n\"DeviceNetworkEvents\", \r\n\"DeviceNetworkInfo\", \r\n\"DeviceProcessEvents\", \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\", \r\n\"EmailAttachmentInfo\", \r\n\"EmailEvents\", \r\n\"EmailPostDeliveryEvents\", \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\") \r\n| summarize DailyBillableGB = toreal(sum(Quantity))/ 1024 by format_datetime(TimeGenerated, \u0027yy-MM-dd\u0027) \r\n| summarize TotalEligibleGB = sum(iif(toreal(DailyBillableGB)\u003etoreal(DailyMaxDiscountGB),toreal(DailyMaxDiscountGB),DailyBillableGB))\r\n\r\n",
- "size": 1,
- "title": "Total Data Grant Used: {TimeRange}",
- "timeContextFromParameter": "TimeRange",
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "TotalEligibleGB",
- "formatter": 12,
- "formatOptions": {
- "palette": "coldHot"
- },
- "numberFormat": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "maximumFractionDigits": 2
- }
- }
- },
- "showBorder": false,
- "sortOrderField": 1
- }
- },
- "customWidth": "30",
- "name": "EligibleE5Ingestion"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let DailyMaxDiscountGB = ((5*todouble(\u0027{TotalE5Seats}\u0027))/1024);\r\nUsage\r\n| where TimeGenerated between ({TimeRange:start} .. {TimeRange:end})\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\", \r\n\"DeviceFileEvents\", \r\n\"DeviceImageLoadEvents\", \r\n\"DeviceInfo\", \r\n\"DeviceLogonEvents\", \r\n\"DeviceNetworkEvents\", \r\n\"DeviceNetworkInfo\", \r\n\"DeviceProcessEvents\", \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\", \r\n\"EmailAttachmentInfo\", \r\n\"EmailEvents\", \r\n\"EmailPostDeliveryEvents\", \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\") \r\n| summarize DailyBillableGB = toreal(sum(Quantity))/ 1024 by format_datetime(TimeGenerated, \u0027yy-MM-dd\u0027) \r\n| summarize TotalEligibleGB = sum(iif(toreal(DailyBillableGB)\u003etoreal(DailyMaxDiscountGB),toreal(DailyMaxDiscountGB),DailyBillableGB))\r\n| extend TotalDiscount = toreal(TotalEligibleGB)*{Price}\r\n| project TotalDiscount\r\n\r\n",
- "size": 1,
- "title": "Estimated Cost Savings: {TimeRange}",
- "timeContextFromParameter": "TimeRange",
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "TotalDiscount",
- "formatter": 12,
- "formatOptions": {
- "palette": "greenRed"
- },
- "numberFormat": {
- "unit": 0,
- "options": {
- "currency": "USD",
- "style": "currency",
- "maximumFractionDigits": 2
- }
- }
- },
- "showBorder": false
- }
- },
- "customWidth": "20",
- "name": "EstimateE5Discount"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let eligibleTables = dynamic([\"SigninLogs\",\"AuditLogs\",\"AADNonInteractiveUserSignInLogs\",\"AADServicePrincipalSignInLogs\",\"AADManagedIdentitySignInLogs\",\"AADProvisioningLogs\",\"ADFSSignInLogs\",\"AADUserRiskEvents\",\"AADRiskyUsers\",\"McasShadowItReporting\",\"InformationProtectionLogs_CL\",\"DeviceEvents\",\"DeviceFileEvents\",\"DeviceImageLoadEvents\",\"DeviceInfo\",\"DeviceLogonEvents\",\"DeviceNetworkEvents\",\"DeviceNetworkInfo\",\"DeviceProcessEvents\",\"DeviceRegistryEvents\",\"DeviceFileCertificateInfo\",\"EmailAttachmentInfo\",\"EmailEvents\",\"EmailPostDeliveryEvents\",\"EmailUrlInfo\",\"IdentityLogonEvents\",\"IdentityQueryEvents\",\"IdentityDirectoryEvents\",\"AlertEvidence\",\"CloudAppEvents\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize TableSizeGB = sum(Quantity) / 1024.0 by DataType | project [\u0027Log Type\u0027] = DataType, [\u0027Table Size\u0027] = TableSizeGB | order by [\u0027Table Size\u0027] desc",
- "size": 1,
- "title": "Eligible Microsoft 365 data by source table in the last {TimeRange}",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "No eligible Microsoft 365 data was found in the selected time range.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "table",
- "gridSettings": {
- "showExportToExcel": true,
- "formatters": [
- {
- "columnMatch": "Log Type",
- "formatter": 0,
- "formatOptions": {
- "customColumnWidthSetting": "40%"
- }
- },
- {
- "columnMatch": "Table Size",
- "formatter": 3,
- "formatOptions": {
- "palette": "greenRed",
- "customColumnWidthSetting": "60%"
- },
- "numberFormat": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "maximumFractionDigits": 3
- }
- }
- }
- ]
- }
- },
- "name": "E5EligibleDataDetail"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let eligibleTables = dynamic([\"SigninLogs\",\"AuditLogs\",\"AADNonInteractiveUserSignInLogs\",\"AADServicePrincipalSignInLogs\",\"AADManagedIdentitySignInLogs\",\"AADProvisioningLogs\",\"ADFSSignInLogs\",\"AADUserRiskEvents\",\"AADRiskyUsers\",\"McasShadowItReporting\",\"InformationProtectionLogs_CL\",\"DeviceEvents\",\"DeviceFileEvents\",\"DeviceImageLoadEvents\",\"DeviceInfo\",\"DeviceLogonEvents\",\"DeviceNetworkEvents\",\"DeviceNetworkInfo\",\"DeviceProcessEvents\",\"DeviceRegistryEvents\",\"DeviceFileCertificateInfo\",\"EmailAttachmentInfo\",\"EmailEvents\",\"EmailPostDeliveryEvents\",\"EmailUrlInfo\",\"IdentityLogonEvents\",\"IdentityQueryEvents\",\"IdentityDirectoryEvents\",\"AlertEvidence\",\"CloudAppEvents\"]); let licenseCount = todouble(\u0027{TotalE5Seats}\u0027); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize [\u0027Daily Ingestion Size\u0027] = sum(Quantity) / 1024.0 by bin(TimeGenerated, 1d) | extend [\u0027Maximum Data Grant\u0027] = iif(isnull(licenseCount), real(null), licenseCount * 5.0 / 1024.0) | order by TimeGenerated asc",
- "size": 1,
- "title": "Daily Ingestion Size vs Maximum Data Grant",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "No eligible Microsoft 365 data was found in the selected time range.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "linechart",
- "chartSettings": {
- "xAxis": "TimeGenerated",
- "showDataPoints": true,
- "ySettings": {
- "numberFormatSettings": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "maximumFractionDigits": 3
- }
- }
- }
- }
- },
- "name": "E5DailyIngestionVsGrant"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let licenseCount = todouble(\u0027{TotalDfSP2Licenses}\u0027); let periodDays = max_of(datetime_diff(\u0027second\u0027, {TimeRange:end}, {TimeRange:start}) / 86400.0, 1); print TotalGrantGB = iif(isnull(licenseCount), \u0027N/A\u0027, tostring(licenseCount * 500.0 / 1024.0 * periodDays))",
- "size": 1,
- "title": "Period grant",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate the selected-period grant.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "TotalGrantGB",
- "formatter": 12,
- "formatOptions": {
- "palette": "orangeBlue"
- }
- },
- "showBorder": false
- }
- },
- "customWidth": "30",
- "name": "DfSP2TotalGrant",
- "conditionalVisibility": {
- "parameterName": "TotalDfSP2Licenses",
- "comparison": "isEqualTo",
- "value": "__never_display_legacy_dfsp2__"
- }
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let licenseCount = todouble(\u0027{TotalDfSP2Licenses}\u0027); let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); let periodDays = max_of(datetime_diff(\u0027second\u0027, {TimeRange:end}, {TimeRange:start}) / 86400.0, 1); let eligibleGBPerDay = toreal(coalesce(toscalar(Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize sum(Quantity) / 1024.0 / periodDays), 0.0)); print EstimatedSavings = iif(isnull(licenseCount), \u0027N/A\u0027, tostring(min_of(eligibleGBPerDay, licenseCount * 500.0 / 1024.0) * periodDays * toreal({Price})))",
- "size": 1,
- "title": "Estimated Cost Savings: {TimeRange}",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate estimated savings.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "EstimatedSavings",
- "formatter": 12,
- "formatOptions": {
- "palette": "greenRed"
- }
- },
- "showBorder": false
- }
- },
- "customWidth": "20",
- "name": "DfSP2EstimatedSavings",
- "conditionalVisibility": {
- "parameterName": "TotalDfSP2Licenses",
- "comparison": "isEqualTo",
- "value": "__never_display_legacy_dfsp2__"
- }
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let coreEligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\"]); let conditionalEligibleTables = dynamic([\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); let eligibleTables = array_concat(coreEligibleTables, conditionalEligibleTables); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize EligibleGBPerDay = sum(Quantity) / 1024.0 / max_of(datetime_diff(\u0027second\u0027, {TimeRange:end}, {TimeRange:start}) / 86400.0, 1) by DataType | extend Eligibility = iif(DataType in (coreEligibleTables), \"Core\", \"Conditional\") | project Table = DataType, Eligibility, EligibleGBPerDay | order by EligibleGBPerDay desc",
- "size": 0,
- "title": "DfSP2 eligible ingestion detail",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "No eligible DfSP2 tables were found in the selected time range.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "table"
- },
- "name": "query - DfSP2 table detail current",
- "conditionalVisibility": {
- "parameterName": "TotalDfSP2Licenses",
- "comparison": "isEqualTo",
- "value": "__never_display_legacy_dfsp2__"
- }
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); let licenseCount = todouble(\u0027{TotalDfSP2Licenses}\u0027); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize EligibleGBPerDay = sum(Quantity) / 1024.0 by bin(TimeGenerated, 1d) | extend DailyAllowanceGB = iif(isnull(licenseCount), real(null), licenseCount * 500.0 / 1024.0) | project TimeGenerated, EligibleGBPerDay, DailyAllowanceGB | order by TimeGenerated asc",
- "size": 0,
- "title": "Pooled DfSP2 data versus daily grant",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "No eligible DfSP2 data was found in the selected time range.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "linechart"
- },
- "name": "query - DfSP2 pooled trend current",
- "conditionalVisibility": {
- "parameterName": "TotalDfSP2Licenses",
- "comparison": "isEqualTo",
- "value": "__never_display_legacy_dfsp2__"
- }
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize EligibleGB = sum(Quantity) / 1024.0",
- "size": 1,
- "title": "Eligible DfSP2 Data",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "No eligible DfSP2 data was found in the selected time range.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "EligibleGB",
- "formatter": 12,
- "formatOptions": {
- "palette": "blue"
- }
- },
- "showBorder": false
- }
- },
- "customWidth": "20",
- "name": "DfSP2IngestionSize",
- "conditionalVisibility": {
- "parameterName": "TotalDfSP2Licenses",
- "comparison": "isEqualTo",
- "value": "__never_display_legacy_dfsp2__"
- }
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "Heartbeat | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | summarize NodesIdentified = dcount(Computer)",
- "size": 1,
- "title": "Nodes",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "No Heartbeat nodes were identified in the selected time range.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "NodesIdentified",
- "formatter": 12,
- "formatOptions": {
- "palette": "blue"
- }
- },
- "showBorder": false
- }
- },
- "customWidth": "10",
- "name": "DfSP2NodesIdentified",
- "conditionalVisibility": {
- "parameterName": "TotalDfSP2Licenses",
- "comparison": "isEqualTo",
- "value": "__never_display_legacy_dfsp2__"
- }
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let licenseCount = todouble(\u0027{TotalDfSP2Licenses}\u0027); print DailyGrantGB = iif(isnull(licenseCount), \u0027N/A\u0027, tostring(licenseCount * 500.0 / 1024.0))",
- "size": 1,
- "title": "Daily grant",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate the daily grant.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "DailyGrantGB",
- "formatter": 12,
- "formatOptions": {
- "palette": "orangeBlue"
- }
- },
- "showBorder": false
- }
- },
- "customWidth": "20",
- "name": "DfSP2DailyGrantLimit",
- "conditionalVisibility": {
- "parameterName": "TotalDfSP2Licenses",
- "comparison": "isEqualTo",
- "value": "__never_display_legacy_dfsp2__"
- }
- },
- {
- "type": 1,
- "content": {
- "json": "## Microsoft Sentinel benefit for Defender for Servers Plan 2\r\n\r\nDefender for Servers Plan 2 provides up to 500 MB of eligible Analytics-tier ingestion per protected server or node per day. The allowance is pooled across machines in each subscription and applied at workspace level. This workbook estimates observed usage; it does not prove Plan 2 protection, licensing, eligibility, or data lake-only charges.\r\n\r\nCore eligible tables:\r\n\r\n- `SecurityAlert`, `SecurityBaseline`, `SecurityBaselineSummary`, `SecurityDetection`, `SecurityEvent`\r\n- `WindowsFirewall`, `ProtectionStatus`, `MDCFileIntegrityMonitoringEvents`\r\n- `DeviceCustomFileEvents`, `DeviceCustomRegistryEvents`\r\n\r\nConditionally eligible tables:\r\n\r\n- `Update`, `UpdateSummary`: review the applicable Update Management conditions\r\n- `WindowsEvent`: only security data from the Microsoft-SecurityEvent stream\r\n\r\nNodes is the distinct `Computer` count observed in `Heartbeat`, not proof of licensing or Plan 2 protection. Review the [Defender for Servers Plan 2 data ingestion benefit](https://learn.microsoft.com/en-us/azure/defender-for-cloud/data-ingestion-benefit) for current eligibility and terms."
- },
- "name": "text - DfSP2 benefit"
- },
- {
- "type": 1,
- "content": {
- "json": "Enter the number of protected Defender for Servers Plan 2 servers or nodes above to calculate the daily and total data grants, grant usage, and estimated cost savings."
- },
- "name": "text - DfSP2 entitlement required",
- "conditionalVisibility": {
- "parameterName": "TotalDfSP2Licenses",
- "comparison": "isEqualTo",
- "value": "\u003cunset\u003e"
- }
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize EligibleGB = sum(Quantity) / 1024.0",
- "size": 1,
- "title": "Eligible Defender for Servers Plan 2 data",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "No eligible DfSP2 data was found in the selected time range.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "EligibleGB",
- "formatter": 12,
- "formatOptions": {
- "palette": "blue"
- },
- "numberFormat": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "maximumFractionDigits": 3
- }
- }
- },
- "showBorder": false
- }
- },
- "customWidth": "20",
- "name": "DfSP2IngestionSize current"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "Heartbeat | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | summarize NodesIdentified = dcount(Computer)",
- "size": 1,
- "title": "Nodes",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "No Heartbeat nodes were identified in the selected time range.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "NodesIdentified",
- "formatter": 12,
- "formatOptions": {
- "palette": "blue"
- }
- },
- "showBorder": false
- }
- },
- "customWidth": "10",
- "name": "DfSP2NodesIdentified current"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let licenseCount = todouble(\u0027{TotalDfSP2Licenses}\u0027); print DailyGrantGB = iif(isnull(licenseCount), \u0027N/A\u0027, strcat(tostring(round(licenseCount * 500.0 / 1024.0, 3)), \u0027 GB\u0027))",
- "size": 1,
- "title": "Daily Grant Limit",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate the daily grant.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "DailyGrantGB",
- "formatter": 12,
- "formatOptions": {
- "palette": "orangeBlue"
- }
- },
- "showBorder": false
- }
- },
- "customWidth": "15",
- "name": "DfSP2DailyGrant"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let licenseCount = todouble(\u0027{TotalDfSP2Licenses}\u0027); let periodDays = max_of(datetime_diff(\u0027second\u0027, {TimeRange:end}, {TimeRange:start}) / 86400.0, 1); print PeriodGrantGB = iif(isnull(licenseCount), \u0027N/A\u0027, strcat(tostring(round(licenseCount * 500.0 / 1024.0 * periodDays, 3)), \u0027 GB\u0027))",
- "size": 1,
- "title": "Total Grant Limit: {TimeRange}",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate the selected-period grant.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "PeriodGrantGB",
- "formatter": 12,
- "formatOptions": {
- "palette": "orangeBlue"
- }
- },
- "showBorder": false
- }
- },
- "customWidth": "20",
- "name": "DfSP2PeriodGrant"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); let licenseCount = todouble(\u0027{TotalDfSP2Licenses}\u0027); let periodDays = max_of(datetime_diff(\u0027second\u0027, {TimeRange:end}, {TimeRange:start}) / 86400.0, 1); let eligibleGB = toreal(coalesce(toscalar(Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize sum(Quantity) / 1024.0), 0.0)); let periodGrantGB = licenseCount * 500.0 / 1024.0 * periodDays; print GrantUsedGB = iif(isnull(licenseCount), \u0027N/A\u0027, strcat(tostring(round(min_of(eligibleGB, periodGrantGB), 3)), \u0027 GB\u0027))",
- "size": 1,
- "title": "Total Grant Used: {TimeRange}",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate grant use.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "GrantUsedGB",
- "formatter": 12,
- "formatOptions": {
- "palette": "coldHot"
- }
- },
- "showBorder": false
- }
- },
- "customWidth": "20",
- "name": "DfSP2GrantUsed"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); let licenseCount = todouble(\u0027{TotalDfSP2Licenses}\u0027); let periodDays = max_of(datetime_diff(\u0027second\u0027, {TimeRange:end}, {TimeRange:start}) / 86400.0, 1); let eligibleGB = toreal(coalesce(toscalar(Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize sum(Quantity) / 1024.0), 0.0)); let periodGrantGB = licenseCount * 500.0 / 1024.0 * periodDays; print EstimatedSavings = iif(isnull(licenseCount), \u0027N/A\u0027, strcat(\u0027$\u0027, tostring(round(min_of(eligibleGB, periodGrantGB) * todouble(\u0027{Price}\u0027), 2))))",
- "size": 1,
- "title": "Estimated Savings: {TimeRange}",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate estimated savings.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "EstimatedSavings",
- "formatter": 12,
- "formatOptions": {
- "palette": "greenRed"
- }
- },
- "showBorder": false
- }
- },
- "customWidth": "15",
- "name": "DfSP2EstimatedSavings"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize TableSizeGB = sum(Quantity) / 1024.0 by DataType | project [\u0027Log Type\u0027] = DataType, [\u0027Table Size\u0027] = TableSizeGB | order by [\u0027Table Size\u0027] desc",
- "size": 1,
- "title": "Eligible Defender for Servers Plan 2 data by source table in the last {TimeRange}",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "No eligible DfSP2 data was found in the selected time range.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "table",
- "gridSettings": {
- "showExportToExcel": true,
- "formatters": [
- {
- "columnMatch": "Log Type",
- "formatter": 0,
- "formatOptions": {
- "customColumnWidthSetting": "40%"
- }
- },
- {
- "columnMatch": "Table Size",
- "formatter": 3,
- "formatOptions": {
- "palette": "greenRed",
- "customColumnWidthSetting": "60%"
- },
- "numberFormat": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "maximumFractionDigits": 3
- }
- }
- }
- ]
- }
- },
- "name": "DfSP2CapacityDetailCurrent"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); let licenseCount = todouble(\u0027{TotalDfSP2Licenses}\u0027); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize [\u0027Daily Ingestion Size\u0027] = sum(Quantity) / 1024.0 by bin(TimeGenerated, 1d) | extend [\u0027Total Data Grant\u0027] = iif(isnull(licenseCount), real(null), licenseCount * 500.0 / 1024.0) | order by TimeGenerated asc",
- "size": 1,
- "title": "Daily Ingestion Size vs Total Data Grant",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "No eligible DfSP2 data was found in the selected time range.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "linechart",
- "chartSettings": {
- "xAxis": "TimeGenerated",
- "showDataPoints": true,
- "ySettings": {
- "numberFormatSettings": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "maximumFractionDigits": 3
- }
- }
- }
- }
- },
- "name": "DfSP2DailyIngestionVsGrant"
- },
- {
- "type": 1,
- "content": {
- "json": "## Retention summary\r\n\r\nThis section estimates Analytics-tier charges for billable data retained longer than 90 days, using historical billable workspace records. XDR and data lake retention use separate billing models. Review [Manage data tiers and retention in Microsoft Sentinel](https://learn.microsoft.com/en-us/azure/sentinel/manage-data-overview) for retention and data-tier guidance."
- },
- "name": "text - retention summary"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let retainedDataGB = toreal(coalesce(toscalar((union withsource = SourceTableName * | where TimeGenerated \u003c startofday(now()) - 90d | where _IsBillable == true | summarize sum(_BilledSize) / 1024.0 / 1024.0 / 1024.0)), 0.0)); print [\u0027Average Daily Retention Cost\u0027] = retainedDataGB * todouble(\u0027{RetentionPrice}\u0027) / 30.0",
- "size": 1,
- "title": "Average Daily Retention Cost",
- "noDataMessage": "No retained billable data was found in the selected workspace scope.",
- "noDataMessageStyle": 3,
- "timeContextFromParameter": "TimeRange",
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "Average Daily Retention Cost",
- "formatter": 12,
- "numberFormat": {
- "unit": 0,
- "options": {
- "currency": "USD",
- "style": "currency",
- "maximumFractionDigits": 2
- }
- }
- },
- "showBorder": false
- }
- },
- "customWidth": "25",
- "name": "AverageDailyRetentionCost"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let selectedDays = max_of(datetime_diff(\u0027second\u0027, {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); let retainedDataGB = toreal(coalesce(toscalar((union withsource = SourceTableName * | where TimeGenerated \u003c startofday(now()) - 90d | where _IsBillable == true | summarize sum(_BilledSize) / 1024.0 / 1024.0 / 1024.0)), 0.0)); print [\u0027Retention Cost\u0027] = retainedDataGB * todouble(\u0027{RetentionPrice}\u0027) * selectedDays / 30.0",
- "size": 1,
- "title": "Retention Cost: {TimeRange}",
- "noDataMessage": "No retained billable data was found in the selected workspace scope.",
- "noDataMessageStyle": 3,
- "timeContextFromParameter": "TimeRange",
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "Retention Cost",
- "formatter": 12,
- "numberFormat": {
- "unit": 0,
- "options": {
- "currency": "USD",
- "style": "currency",
- "maximumFractionDigits": 2
- }
- }
- },
- "showBorder": false
- }
- },
- "customWidth": "25",
- "name": "RetentionCostForTimeRange"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let selectedDays = max_of(datetime_diff(\u0027second\u0027, {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); union withsource = SourceTableName * | where TimeGenerated \u003c startofday(now()) - 90d | where _IsBillable == true | summarize RetainedDataGB = sum(_BilledSize) / 1024.0 / 1024.0 / 1024.0 by SourceTableName | project [\u0027Log Type\u0027] = SourceTableName, [\u0027Retained Data\u0027] = RetainedDataGB, [\u0027Average Daily Retention Cost\u0027] = RetainedDataGB * todouble(\u0027{RetentionPrice}\u0027) / 30.0, [\u0027Retention Cost\u0027] = RetainedDataGB * todouble(\u0027{RetentionPrice}\u0027) * selectedDays / 30.0 | order by [\u0027Retained Data\u0027] desc",
- "size": 1,
- "title": "Retained data by source table in the last {TimeRange}",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "No billable data older than 90 days was found in the selected workspace scope.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "table",
- "gridSettings": {
- "showExportToExcel": true,
- "formatters": [
- {
- "columnMatch": "Log Type",
- "formatter": 0,
- "formatOptions": {
- "customColumnWidthSetting": "30%"
- }
- },
- {
- "columnMatch": "Retained Data",
- "formatter": 3,
- "formatOptions": {
- "palette": "greenRed",
- "customColumnWidthSetting": "25%"
- },
- "numberFormat": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "maximumFractionDigits": 3
- }
- }
- },
- {
- "columnMatch": "Average Daily Retention Cost",
- "formatter": 0,
- "formatOptions": {
- "customColumnWidthSetting": "20%"
- },
- "numberFormat": {
- "unit": 0,
- "options": {
- "currency": "USD",
- "style": "currency",
- "maximumFractionDigits": 2
- }
- }
- },
- {
- "columnMatch": "Retention Cost",
- "formatter": 0,
- "formatOptions": {
- "customColumnWidthSetting": "25%"
- },
- "numberFormat": {
- "unit": 0,
- "options": {
- "currency": "USD",
- "style": "currency",
- "maximumFractionDigits": 2
- }
- }
- }
- ]
- }
- },
- "name": "RetentionDataDetail"
- },
- {
- "type": 1,
- "content": {
- "json": "## Microsoft Sentinel Data Lake\r\n\r\nThe data lake provides long-term, cost-effective storage outside the Analytics tier. Its costs are billed separately for data lake ingestion, processing, storage, query, and advanced data insights. Microsoft Defender XDR data also has separate 30-day default and extended-retention pricing.\r\n\r\nData lake charges are not available from the Log Analytics `Usage` table, so this workbook cannot calculate billing-accurate data lake costs. Review current usage and costs in **Microsoft Sentinel \u003e Cost management** in the Microsoft Defender portal. Learn more in the [Microsoft Sentinel data lake overview](https://learn.microsoft.com/en-us/azure/sentinel/datalake/sentinel-lake-overview) and [Manage and monitor costs for Microsoft Sentinel](https://learn.microsoft.com/en-us/azure/sentinel/billing-monitor-costs). Review current data lake rates on the [Microsoft Sentinel pricing page](https://www.microsoft.com/en-us/security/pricing/microsoft-sentinel/)."
- },
- "name": "text - Microsoft Sentinel Data Lake"
- },
- {
- "type": 1,
- "content": {
- "json": "## Commitment tiers\r\n\r\nMicrosoft Sentinel and Log Analytics offer Pay-As-You-Go and Commitment Tier pricing (100, 200, 300, 400, 500, 1000, 2000, and 5000+ GB/day). This section is fully automatic: it detects your **current commitment tier** from the selected workspace configuration and calculates a **recommended tier** from your average billable daily ingestion over the selected time range. No additional input is required.\r\n\r\nCommitment tier changes typically require a minimum 31-day commitment before switching again \u2014 review **Days since tier last changed** before making a change. Actual per-GB rates vary by region, currency, and agreement type and change over time, so this workbook cannot calculate exact savings. Confirm current rates on the [Microsoft Sentinel pricing page](https://www.microsoft.com/en-us/security/pricing/microsoft-sentinel/) and review [Plan costs and understand pricing and billing for Microsoft Sentinel](https://learn.microsoft.com/en-us/azure/sentinel/billing?tabs=simplified%2Ccommitment-tiers#analytics-tier) before changing your commitment tier."
- },
- "name": "text - commitment tiers"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "resources\r\n| where type =~ \u0027microsoft.operationalinsights/workspaces\u0027\r\n| where id in~ ({Workspace}) or \u0027value::all\u0027 in~ ({Workspace})\r\n| extend skuName = tostring(properties.sku.name), capacityReservationLevel = toint(properties.sku.capacityReservationLevel), lastSkuUpdate = todatetime(properties.sku.lastSkuUpdate)\r\n| extend daysSinceTierChange = iif(isnotempty(lastSkuUpdate), datetime_diff(\u0027day\u0027, now(), lastSkuUpdate), int(null))\r\n| project [\u0027Workspace\u0027] = name, [\u0027Current commitment tier\u0027] = case(skuName == \u0027CapacityReservation\u0027, strcat(tostring(capacityReservationLevel), \u0027 GB/day commitment\u0027), isnotempty(skuName), skuName, \u0027Unknown\u0027), [\u0027Days since tier last changed\u0027] = daysSinceTierChange\r\n| order by [\u0027Workspace\u0027] asc",
- "size": 1,
- "title": "Current commitment tier by workspace (auto-detected)",
- "noDataMessage": "No workspace SKU information was found for the selected workspace scope.",
- "noDataMessageStyle": 3,
- "queryType": 1,
- "resourceType": "microsoft.resourcegraph/resources",
- "visualization": "table"
- },
- "name": "CommitmentTierCurrent"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let selectedDays = max_of(datetime_diff(\u0027second\u0027, {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0);\r\nlet avgDailyGB = toreal(coalesce(toscalar(union withsource = SourceTableName * | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where _IsBillable == true | summarize sum(_BilledSize) / 1024.0 / 1024.0 / 1024.0 / selectedDays), 0.0));\r\nlet tierLevels = dynamic([100,200,300,400,500,1000,2000,5000]);\r\nprint AvgDailyIngestionGB = avgDailyGB, TierLevels = tierLevels\r\n| mv-expand TierLevel = TierLevels to typeof(int)\r\n| extend Eligible = TierLevel \u003e= AvgDailyIngestionGB\r\n| summarize RecommendedTierGBPerDay = minif(TierLevel, Eligible), MaxTierGBPerDay = max(TierLevel), AvgDailyIngestionGB = any(AvgDailyIngestionGB)\r\n| project [\u0027Average Billable Daily Ingestion (GB)\u0027] = round(AvgDailyIngestionGB, 2), [\u0027Recommended commitment tier\u0027] = iif(isnotempty(RecommendedTierGBPerDay), strcat(tostring(RecommendedTierGBPerDay), \u0027 GB/day\u0027), strcat(\u0027Above \u0027, tostring(MaxTierGBPerDay), \u0027 GB/day \u2014 review Enterprise Agreement options\u0027))",
- "size": 1,
- "title": "Recommended commitment tier based on {TimeRange} usage",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "No billable ingestion was found in the selected time range.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "leftContent": {
- "columnMatch": "Average Billable Daily Ingestion (GB)",
- "formatter": 12,
- "formatOptions": {
- "palette": "blue"
- },
- "numberFormat": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "maximumFractionDigits": 2
- }
- }
- },
- "rightContent": {
- "columnMatch": "Recommended commitment tier",
- "formatter": 12,
- "formatOptions": {
- "palette": "orangeBlue"
- }
- },
- "showBorder": false
- }
- },
- "name": "CommitmentTierRecommendation"
- },
- {
- "type": 1,
- "content": {
- "json": "## SOAR summary\r\n\r\nMicrosoft Sentinel playbooks use Azure Logic Apps to automate responses to incidents, alerts, and other security operations workflows. This section summarizes billable Logic App executions across accessible playbooks and estimates their execution cost using the **Logic App execution cost** input at the top of the workbook.\r\n\r\nTo populate this estimate, export the `TotalBillableExecutions` metric to the selected Log Analytics workspace and use the Analytics plan for the `AzureMetrics` table. Basic Logs tables cannot run this query. The estimate is not an invoice; use Azure Cost Management to validate billed charges.\r\n\r\nReview [Automate threat response with playbooks in Microsoft Sentinel](https://learn.microsoft.com/en-us/azure/sentinel/automation/automate-responses-with-playbooks) for playbook guidance. Because playbooks use Azure Logic Apps, additional charges can apply. Go to the [Azure Logic Apps](https://azure.microsoft.com/pricing/details/logic-apps/) pricing page for more details."
- },
- "name": "text - 3"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "AzureMetrics | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where MetricName == \u0027TotalBillableExecutions\u0027 | where ResourceId in~ ({Resources}) or \u0027value::all\u0027 in~ ({Resources}) | summarize TotalBillableExecutions = sum(Total) | project [\u0027Total billable executions\u0027] = TotalBillableExecutions, [\u0027Estimated automation cost\u0027] = TotalBillableExecutions * todouble(\u0027{ExecutionCost}\u0027)",
- "size": 1,
- "title": "Logic App automation summary",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "No exported TotalBillableExecutions metrics were found. Configure Logic App metric export to this workspace to calculate the total without selecting a row.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "leftContent": {
- "columnMatch": "Total billable executions",
- "formatter": 12,
- "formatOptions": {
- "palette": "blue"
- }
- },
- "rightContent": {
- "columnMatch": "Estimated automation cost",
- "formatter": 12,
- "formatOptions": {
- "palette": "greenRed"
- },
- "numberFormat": {
- "unit": 0,
- "options": {
- "currency": "USD",
- "style": "currency",
- "minimumFractionDigits": 2,
- "maximumFractionDigits": 3
- }
- }
- },
- "showBorder": false
- }
- },
- "name": "SOARSummaryFromAzureMetrics"
- },
- {
- "type": 10,
- "content": {
- "chartId": "workbooke70b7cbc-f1d7-4a74-b8b9-75cc8d5ab586",
- "version": "MetricsItem/2.0",
- "size": 1,
- "chartType": 0,
- "resourceType": "microsoft.logic/workflows",
- "metricScope": 0,
- "resourceParameter": "Resources",
- "resourceIds": [
- "{Resources}"
- ],
- "timeContextFromParameter": "TimeRange",
- "timeContext": {
- "durationMs": 604800000
- },
- "metrics": [
- {
- "namespace": "microsoft.logic/workflows",
- "metric": "microsoft.logic/workflows--TotalBillableExecutions",
- "aggregation": 1
- }
- ],
- "title": "Logic App execution detail",
- "resourceLimit": 10000,
- "gridSettings": {
- "formatters": [
- {
- "columnMatch": "$gen_group",
- "formatter": 15,
- "formatOptions": {
- "linkTarget": null,
- "showIcon": true
- }
- },
- {
- "columnMatch": "Subscription",
- "formatter": 5
- },
- {
- "columnMatch": "Name",
- "formatter": 13,
- "formatOptions": {
- "linkTarget": "Resource",
- "showIcon": true
- }
- },
- {
- "columnMatch": "microsoft.logic/workflows--TotalBillableExecutions",
- "formatter": 8,
- "formatOptions": {
- "palette": "blue",
- "aggregation": "Sum"
- }
- },
- {
- "columnMatch": "microsoft.logic/workflows--TotalBillableExecutions Timeline",
- "formatter": 21,
- "formatOptions": {
- "palette": "blue"
- }
- },
- {
- "columnMatch": "microsoft.logic/workflows--BillableTriggerExecutions Timeline",
- "formatter": 5
- },
- {
- "columnMatch": "microsoft.logic/workflows--BillableActionExecutions",
- "formatter": 8,
- "formatOptions": {
- "palette": "blue"
- },
- "numberFormat": {
- "unit": 0,
- "options": {
- "style": "decimal"
- }
- }
- },
- {
- "columnMatch": "microsoft.logic/workflows--BillableActionExecutions Timeline",
- "formatter": 5
- },
- {
- "columnMatch": "RG",
- "formatter": 13,
- "formatOptions": {
- "linkTarget": null,
- "showIcon": true
- }
- },
- {
- "columnMatch": "Sum",
- "formatter": 1,
- "formatOptions": {
- "aggregation": "Sum"
- },
- "numberFormat": {
- "unit": 0,
- "options": {
- "style": "decimal"
- }
- }
- }
- ],
- "rowLimit": 10000,
- "filter": true,
- "hierarchySettings": {
- "treeType": 1,
- "groupBy": [
- "Subscription"
- ]
- },
- "labelSettings": [
- {
- "columnId": "microsoft.logic/workflows--TotalBillableExecutions",
- "label": "Total Billable Executions (Sum)"
- },
- {
- "columnId": "microsoft.logic/workflows--TotalBillableExecutions Timeline",
- "label": "Total Billable Executions Timeline"
- }
- ]
- },
- "sortBy": [
-
- ],
- "exportFieldName": "microsoft.logic/workflows--TotalBillableExecutions",
- "exportParameterName": "Total",
- "exportDefaultValue": "0"
- },
- "name": "Billable Metric"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "print [\u0027Estimated automation costs\u0027] = todouble(\u0027{Total}\u0027) * todouble(\u0027{ExecutionCost}\u0027)",
- "size": 1,
- "title": "Estimated Logic App cost",
- "timeContext": {
- "durationMs": 86400000
- },
- "noDataMessage": "Select a subscription or Logic App row above to calculate the estimated cost.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "Estimated automation costs",
- "formatter": 12,
- "formatOptions": {
- "palette": "greenRed"
- },
- "numberFormat": {
- "unit": 0,
- "options": {
- "currency": "USD",
- "style": "currency",
- "minimumFractionDigits": 2,
- "maximumFractionDigits": 3
- }
- }
- },
- "showBorder": false
- }
- },
- "conditionalVisibility": {
- "parameterName": "Total",
- "comparison": "isEqualTo",
- "value": "__never_display_legacy_soar_cost__"
- },
- "name": "query - 11"
- }
+ "version": "Notebook/1.0",
+ "items": [
+ {
+ "type": 1,
+ "content": {
+ "json": "# Microsoft Sentinel cost summary\n---\n"
+ },
+ "name": "text - 2"
+ },
+ {
+ "type": 9,
+ "content": {
+ "version": "KqlParameterItem/1.0",
+ "parameters": [
+ {
+ "id": "9d001d6f-301c-4d03-b02c-b8cc6dce210b",
+ "version": "KqlParameterItem/1.0",
+ "name": "TimeRange",
+ "type": 4,
+ "isRequired": true,
+ "value": {
+ "durationMs": 604800000
+ },
+ "typeSettings": {
+ "selectableValues": [
+ {
+ "durationMs": 300000
+ },
+ {
+ "durationMs": 900000
+ },
+ {
+ "durationMs": 1800000
+ },
+ {
+ "durationMs": 3600000
+ },
+ {
+ "durationMs": 14400000
+ },
+ {
+ "durationMs": 43200000
+ },
+ {
+ "durationMs": 86400000
+ },
+ {
+ "durationMs": 172800000
+ },
+ {
+ "durationMs": 259200000
+ },
+ {
+ "durationMs": 604800000
+ },
+ {
+ "durationMs": 1209600000
+ },
+ {
+ "durationMs": 2419200000
+ },
+ {
+ "durationMs": 2592000000
+ },
+ {
+ "durationMs": 5184000000
+ },
+ {
+ "durationMs": 7776000000
+ }
],
- "fromTemplateId": "sentinel-SentinelCosts",
- "$schema": "https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json"
-}
\ No newline at end of file
+ "allowCustom": true
+ },
+ "timeContext": {
+ "durationMs": 86400000
+ }
+ },
+ {
+ "id": "67c2ce6e-ea54-4ae4-8343-3fcad8e53d1b",
+ "version": "KqlParameterItem/1.0",
+ "name": "Workspace",
+ "type": 5,
+ "isRequired": true,
+ "multiSelect": true,
+ "quote": "'",
+ "delimiter": ",",
+ "query": "resources | where type =~ 'Microsoft.operationsmanagement/solutions' | where name contains 'SecurityInsights' | project id = tostring(properties.workspaceResourceId)",
+ "crossComponentResources": [
+ "value::all"
+ ],
+ "value": [
+ "value::all"
+ ],
+ "typeSettings": {
+ "limitSelectTo": 100,
+ "additionalResourceOptions": [
+ "value::all"
+ ],
+ "showDefault": false
+ },
+ "timeContext": {
+ "durationMs": 86400000
+ },
+ "queryType": 1,
+ "resourceType": "microsoft.resourcegraph/resources"
+ },
+ {
+ "id": "9375c625-e916-4f48-b072-352d6aeefddb",
+ "version": "KqlParameterItem/1.0",
+ "name": "Price",
+ "label": "Ingestion price",
+ "type": 1,
+ "description": "Enter your ingestion price per GB (PAYG or Commitment Tier). You can also refer to Azure Pricing Calculator.",
+ "value": "4"
+ },
+ {
+ "id": "9d5299d0-36a0-4666-9803-ca6931bdaab7",
+ "version": "KqlParameterItem/1.0",
+ "name": "RetentionPrice",
+ "label": "Retention price",
+ "type": 1,
+ "description": "Enter the retention price per GB/month that will be used in this workbook's calculations",
+ "value": "0.1"
+ },
+ {
+ "id": "67494f3e-322e-4411-9b45-1cbea03ed618",
+ "version": "KqlParameterItem/1.0",
+ "name": "TotalE5Seats",
+ "label": "Total seats (E5/A5/F5/G5)",
+ "type": 1,
+ "description": "Enter the total number of Microsoft 365 E5, A5, F5, G5 and Microsoft 365 E5, A5, F5, G5 Security licenses in your environment",
+ "value": "0"
+ }
+ ],
+ "style": "pills",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces"
+ },
+ "name": "parameters - 5"
+ },
+ {
+ "type": 1,
+ "content": {
+ "json": "## Ingestion summary"
+ },
+ "name": "text - 2"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "union withsource = tt *\r\n| where TimeGenerated > startofday({TimeRange:start}) and TimeGenerated < startofday({TimeRange:end})\r\n// Only look at chargeable Tables\r\n| where _IsBillable == True\r\n| summarize TotalGBytes =round(sum(_BilledSize/(1024*1024*1024)),2) by bin(TimeGenerated, 1d)//, Solution=tt\r\n| summarize ['GBs/day'] =round(avg(TotalGBytes),2)",
+ "size": 4,
+ "title": "Average billable GBs/day ingested in the last {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "GBs/day",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "greenRed"
+ }
+ },
+ "showBorder": false,
+ "size": "auto"
+ }
+ },
+ "name": "query - 6"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "Usage\r\n| where IsBillable == true\r\n| summarize size = sum(Quantity)/1024 by IsBillable\r\n| project ['Total data ingestion'] = size, ['Estimated cost'] = size*{Price}",
+ "size": 4,
+ "title": "Total billable ingestion and cost in the last {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "greenRed",
+ "compositeBarSettings": {
+ "labelText": "",
+ "columnSettings": []
+ }
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency",
+ "useGrouping": false
+ }
+ }
+ },
+ "leftContent": {
+ "columnMatch": "Total data ingestion",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "greenRed"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "useGrouping": false,
+ "maximumFractionDigits": 1
+ }
+ }
+ },
+ "rightContent": {
+ "columnMatch": "Estimated cost",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "greenRed"
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency",
+ "useGrouping": false,
+ "maximumFractionDigits": 1
+ }
+ }
+ },
+ "showBorder": false,
+ "size": "auto"
+ }
+ },
+ "name": "query - 8"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let Categories = datatable(Type:string,Category:string)\r\n[\r\n \"AuditLogs\", \"Azure Active Directory\",\r\n \"SigninLogs\", \"Azure Active Directory\",\r\n \"AADNonInteractiveUserSignInLogs\", \"Azure Active Directory\",\r\n \"AADServicePrincipalSignInLogs\", \"Azure Active Directory\",\r\n \"AADManagedIdentitySignInLogs\", \"Azure Active Directory\",\r\n \"AADProvisioningLogs\",\"Azure Active Directory\",\r\n \"BehaviorAnalytics\", \"User Entity Behavior Analytics\",\r\n \"UserPeerAnalytics\",\"User Entity Behavior Analytics\",\r\n \"UserAccessAnalytics\",\"User Entity Behavior Analytics\",\r\n \"IdentityInfo\",\"User Entity Behavior Analytics\",\r\n \"DeviceLogonEvents\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceEvents\",\"Microsoft Defender for Endpoint\",\r\n\t\"DeviceNetworkInfo\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceImageLoadEvents\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceFileEvents\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceInfo\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceProcessEvents\", \"Microsoft Defender for Endpoint\",\t\r\n\t\"DeviceNetworkEvents\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceRegistryEvents\", \"Microsoft Defender for Endpoint\",\r\n \"DeviceFileCertificateInfo\", \"Microsoft Defender for Endpoint\",\r\n \"EmailAttachmentInfo\", \"Microsoft Defender for Office 365\",  \r\n \"EmailEvents\", \"Microsoft Defender for Office 365\",  \r\n \"EmailPostDeliveryEvents\", \"Microsoft Defender for Office 365\",  \r\n \"EmailUrlInfo\", \"Microsoft Defender for Office 365\",\r\n \"IdentityLogonEvents\", \"Microsoft Defender for Identity\",\r\n \"IdentityQueryEvents\", \"Microsoft Defender for Identity\",\r\n \"IdentityDirectoryEvents\", \"Microsoft Defender for Identity\",\r\n \"CloudAppEvents\", \"Microsoft Defender for Cloud Apps\",\r\n \"AlertEvidence\", \"Microsoft Defender Alert Evidence\",\r\n \"InsightsMetrics\", \"Azure Monitor for VMs\",\r\n \"VMBoundPort\", \"Azure Monitor for VMs\",\r\n \"VMComputer\", \"Azure Monitor for VMs\",\r\n \"VMConnection\", \"Azure Monitor for VMs\",\r\n \"VMProcess\", \"Azure Monitor for VMs\",\r\n \"SecurityEvent\", \"Windows Security Events\",\r\n \"Syslog\", \"Syslog/CEF\",\r\n \"CommonSecurityLog\", \"Syslog/CEF\",\r\n \"ThreatIntelligenceIndicator\", \"Threat Intelligence\",\r\n \"DnsEvents\", \"DNS Logs\",\r\n \"DnsInventory\", \"DNS Logs\",\r\n \"AWSCloudTrail\", \"AWS Cloud Trail\",\r\n \"ConfigurationChange\", \"Change Tracking\",\r\n \"ConfigurationData\", \"Change Tracking\",\r\n \"AzureDiagnostics\", \"Azure Resources\",\r\n \"LAQueryLogs\", \"Management\",\r\n \"SentinelHealth\",\"Management\",\r\n \"Perf\",\"Performance\",\r\n \"AzureMetrics\",\"Azure Metrics\",\r\n \"SecurityNestedRecommendation\", \"Microsoft Defender for Cloud\",\r\n \"SecurityRecommendation\", \"Microsoft Defender for Cloud\",\r\n \"SecurityRegulatoryCompliance\", \"Microsoft Defender for Cloud\",\r\n \"SecureScoreControls\", \"Microsoft Defender for Cloud\",\r\n \"SecurityBaseline\", \"Microsoft Defender for Cloud\",\r\n \"SecureScores\", \"Microsoft Defender for Cloud\",\r\n \"Update\", \"Update Management\",\r\n \"UpdateSummary\", \"Update Management\"\r\n];\r\nlet customTables = Usage\r\n| where IsBillable == true\r\n| where DataType contains \"_CL\"\r\n| summarize size = sum(Quantity)/1024 by DataType\r\n| project ['Log Type'] = DataType, ['Table Size'] = size, ['Estimated cost'] = size*{Price};\r\nlet knownTables = Usage\r\n| where IsBillable == true \r\n| join kind=leftouter Categories on $left.DataType == $right.Type\r\n| summarize size =sumif(Quantity, isnotempty(Category))/1024, sizeOther= sumif(Quantity,(isempty(Category) and DataType !contains \"_CL\"))/1024 by Category\r\n| project ['Log Type'] = iif(isnotempty( Category),Category,\"Other\"), ['Table Size'] = iif(isnotempty( Category),size,sizeOther), ['Estimated cost'] = iif(isnotempty(Category),size*{Price},sizeOther*4);\r\nunion customTables, knownTables\r\n| order by ['Table Size'] desc",
+ "size": 0,
+ "title": "Breakdown of billable ingestion by log category in the last {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "table",
+ "gridSettings": {
+ "formatters": [
+ {
+ "columnMatch": "Table Size",
+ "formatter": 3,
+ "formatOptions": {
+ "palette": "greenRed"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "useGrouping": false
+ }
+ }
+ },
+ {
+ "columnMatch": "Estimated cost",
+ "formatter": 0,
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency"
+ }
+ }
+ }
+ ]
+ },
+ "graphSettings": {
+ "type": 0,
+ "topContent": {
+ "columnMatch": "Log Category",
+ "formatter": 1
+ },
+ "centerContent": {
+ "columnMatch": "Billed Size",
+ "formatter": 1,
+ "numberFormat": {
+ "unit": 17,
+ "options": {
+ "maximumSignificantDigits": 3,
+ "maximumFractionDigits": 2
+ }
+ }
+ }
+ }
+ },
+ "name": "query - 2"
+ },
+ {
+ "type": 1,
+ "content": {
+ "json": "## Retention summary"
+ },
+ "name": "text - 4"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "union withsource=TableName1 * | where TimeGenerated < ago(90d) | extend key = 'Key' | summarize size = sum(_BilledSize)/1024/1024/1024 by key\r\n| project ['Data over 90 days'] = size, ['Retention Cost'] = size*{RetentionPrice}\r\n\r\n\r\n",
+ "size": 4,
+ "title": "Data older than 90 days and resulting retention cost",
+ "noDataMessage": "You have no data older than 90 days",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "gridSettings": {
+ "formatters": [
+ {
+ "columnMatch": "Data over 90 days",
+ "formatter": 0,
+ "numberFormat": {
+ "unit": 36,
+ "options": {
+ "style": "decimal",
+ "useGrouping": false
+ }
+ }
+ },
+ {
+ "columnMatch": "Retention Cost",
+ "formatter": 0,
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "style": "decimal"
+ }
+ }
+ }
+ ]
+ },
+ "tileSettings": {
+ "titleContent": {},
+ "leftContent": {
+ "columnMatch": "Data over 90 days",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "greenRed"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 1
+ }
+ }
+ },
+ "rightContent": {
+ "columnMatch": "Retention Cost",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "greenRed"
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ "showBorder": false,
+ "size": "auto"
+ }
+ },
+ "name": "query - 7"
+ },
+ {
+ "type": 1,
+ "content": {
+ "json": "## Microsoft Sentinel benefit for Microsoft 365 E5, A5, F5 and G5 customers\r\n\r\nWith security information and event management (SIEM) and extended detection and response (XDR) from Microsoft, you’re armed with the context and automation you need to stop sophisticated, cross-domain attacks across your entire organization. \r\n\r\nMicrosoft 365 E5, A5, F5, G5 and Microsoft 365 E5, A5, F5, G5 Security customers can get data grant up to 5MB per user/day of Microsoft 365 data ingestion into Microsoft Sentinel.
\r\nThe data sources included in this offer include:\r\n\r\n- Microsoft Entra ID (Azure AD) sign-in and audit logs\r\n- Microsoft Cloud App Security shadow IT discovery logs\r\n- Microsoft Information Protection logs\r\n- Microsoft 365 advanced hunting data\r\n\r\nThe data grant will be calculated at the end of the month and applied to your bill, covering the cost of up to 5 MB of data ingestion per user/day.\r\n\r\nVisit https://azure.microsoft.com/offers/sentinel-microsoft-365-offer/ for more information\r\n\r\n
\r\n\r\n### Below are the ingestion for the eligible data sources:\r\n\r\n_**Note:** Kindly specify **Total seats (E5/A5/F5/G5)** and **Ingestion Price** parameters for calculation._"
+ },
+ "name": "text - 12"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "Usage\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\",  \r\n\"DeviceFileEvents\",  \r\n\"DeviceImageLoadEvents\",  \r\n\"DeviceInfo\",  \r\n\"DeviceLogonEvents\",  \r\n\"DeviceNetworkEvents\",  \r\n\"DeviceNetworkInfo\",  \r\n\"DeviceProcessEvents\",  \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\",  \r\n\"EmailAttachmentInfo\",  \r\n\"EmailEvents\",  \r\n\"EmailPostDeliveryEvents\",  \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\"\r\n)   \r\n| summarize BillableDataGB = sum(Quantity) / 1000. by DataType\r\n| order by BillableDataGB desc\r\n",
+ "size": 0,
+ "timeContextFromParameter": "TimeRange",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "gridSettings": {
+ "formatters": [
+ {
+ "columnMatch": "BillableDataGB",
+ "formatter": 3,
+ "formatOptions": {
+ "palette": "blue"
+ }
+ }
+ ]
+ }
+ },
+ "name": "query - 13"
+ },
+ {
+ "type": 1,
+ "content": {
+ "json": "
\r\n**Daily ingestion size (for eligible data sources) vs Maximum data grant:**"
+ },
+ "conditionalVisibilities": [
+ {
+ "parameterName": "TotalE5Seats",
+ "comparison": "isNotEqualTo",
+ "value": "0"
+ },
+ {
+ "parameterName": "TotalE5Seats",
+ "comparison": "isNotEqualTo"
+ }
+ ],
+ "name": "text - DailyIngestionVsAllocation"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "Usage\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\",  \r\n\"DeviceFileEvents\",  \r\n\"DeviceImageLoadEvents\",  \r\n\"DeviceInfo\",  \r\n\"DeviceLogonEvents\",  \r\n\"DeviceNetworkEvents\",  \r\n\"DeviceNetworkInfo\",  \r\n\"DeviceProcessEvents\",  \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\",  \r\n\"EmailAttachmentInfo\",  \r\n\"EmailEvents\",  \r\n\"EmailPostDeliveryEvents\",  \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\")   \r\n| summarize DailyIngestionGB = toreal(sum(Quantity))/ 1024 by format_datetime(TimeGenerated, 'yyyy-MM-dd') \r\n| extend MaxDataGrantGB = ((5*toreal({TotalE5Seats}))/1024)\r\n| sort by TimeGenerated asc\r\n",
+ "size": 0,
+ "aggregation": 3,
+ "timeContextFromParameter": "TimeRange",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "linechart",
+ "chartSettings": {
+ "xAxis": "TimeGenerated",
+ "showDataPoints": true,
+ "ySettings": {
+ "numberFormatSettings": {
+ "unit": 0,
+ "options": {
+ "style": "decimal",
+ "useGrouping": true,
+ "maximumFractionDigits": 3
+ }
+ }
+ }
+ }
+ },
+ "conditionalVisibilities": [
+ {
+ "parameterName": "TotalE5Seats",
+ "comparison": "isNotEqualTo"
+ },
+ {
+ "parameterName": "TotalE5Seats",
+ "comparison": "isNotEqualTo",
+ "value": "0"
+ }
+ ],
+ "name": "DailyIngestionVSAllocation"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "Usage\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\",  \r\n\"DeviceFileEvents\",  \r\n\"DeviceImageLoadEvents\",  \r\n\"DeviceInfo\",  \r\n\"DeviceLogonEvents\",  \r\n\"DeviceNetworkEvents\",  \r\n\"DeviceNetworkInfo\",  \r\n\"DeviceProcessEvents\",  \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\",  \r\n\"EmailAttachmentInfo\",  \r\n\"EmailEvents\",  \r\n\"EmailPostDeliveryEvents\",  \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\"\r\n)   \r\n| summarize TotalBillableDataGB = sum(Quantity) / 1024\r\n\r\n",
+ "size": 4,
+ "title": "Total ingestion",
+ "timeContextFromParameter": "TimeRange",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "TotalBillableDataGB",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "greenRed"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "customWidth": "20",
+ "name": "E5IngestionSize"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let DailyMaxDiscountGB = ((5*toreal({TotalE5Seats}))/1024);\r\nUsage\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\",  \r\n\"DeviceFileEvents\",  \r\n\"DeviceImageLoadEvents\",  \r\n\"DeviceInfo\",  \r\n\"DeviceLogonEvents\",  \r\n\"DeviceNetworkEvents\",  \r\n\"DeviceNetworkInfo\",  \r\n\"DeviceProcessEvents\",  \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\",  \r\n\"EmailAttachmentInfo\",  \r\n\"EmailEvents\",  \r\n\"EmailPostDeliveryEvents\",  \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\")   \r\n| summarize DailyBillableGB = toreal(sum(Quantity))/ 1024 by format_datetime(TimeGenerated, 'yy-MM-dd') \r\n| extend DailyMaxGrantGB = DailyMaxDiscountGB\r\n| summarize MaxDataGrantGB = sum(toreal(DailyMaxGrantGB))\r\n\r\n",
+ "size": 4,
+ "title": "Total Data Grant Limit",
+ "timeContextFromParameter": "TimeRange",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "MaxDataGrantGB",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "orangeBlue"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ "showBorder": false,
+ "sortOrderField": 1
+ }
+ },
+ "conditionalVisibilities": [
+ {
+ "parameterName": "TotalE5Seats",
+ "comparison": "isNotEqualTo"
+ },
+ {
+ "parameterName": "TotalE5Seats",
+ "comparison": "isNotEqualTo",
+ "value": "0"
+ }
+ ],
+ "customWidth": "20",
+ "name": "DataGrantLimit"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let DailyMaxDiscountGB = ((5*toreal({TotalE5Seats}))/1024);\r\nUsage\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\",  \r\n\"DeviceFileEvents\",  \r\n\"DeviceImageLoadEvents\",  \r\n\"DeviceInfo\",  \r\n\"DeviceLogonEvents\",  \r\n\"DeviceNetworkEvents\",  \r\n\"DeviceNetworkInfo\",  \r\n\"DeviceProcessEvents\",  \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\",  \r\n\"EmailAttachmentInfo\",  \r\n\"EmailEvents\",  \r\n\"EmailPostDeliveryEvents\",  \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\")   \r\n| summarize DailyBillableGB = toreal(sum(Quantity))/ 1024 by format_datetime(TimeGenerated, 'yy-MM-dd') \r\n| summarize TotalEligibleGB = sum(iif(toreal(DailyBillableGB)>toreal(DailyMaxDiscountGB),toreal(DailyMaxDiscountGB),DailyBillableGB))\r\n\r\n",
+ "size": 4,
+ "title": "Total Data Grant Used",
+ "timeContextFromParameter": "TimeRange",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "TotalEligibleGB",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "coldHot"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ "showBorder": false,
+ "sortOrderField": 1
+ }
+ },
+ "conditionalVisibilities": [
+ {
+ "parameterName": "TotalE5Seats",
+ "comparison": "isNotEqualTo"
+ },
+ {
+ "parameterName": "TotalE5Seats",
+ "comparison": "isNotEqualTo",
+ "value": "0"
+ }
+ ],
+ "customWidth": "30",
+ "name": "EligibleE5Ingestion"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let DailyMaxDiscountGB = ((5*toreal({TotalE5Seats}))/1024);\r\nUsage\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\",  \r\n\"DeviceFileEvents\",  \r\n\"DeviceImageLoadEvents\",  \r\n\"DeviceInfo\",  \r\n\"DeviceLogonEvents\",  \r\n\"DeviceNetworkEvents\",  \r\n\"DeviceNetworkInfo\",  \r\n\"DeviceProcessEvents\",  \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\",  \r\n\"EmailAttachmentInfo\",  \r\n\"EmailEvents\",  \r\n\"EmailPostDeliveryEvents\",  \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\")   \r\n| summarize DailyBillableGB = toreal(sum(Quantity))/ 1024 by format_datetime(TimeGenerated, 'yy-MM-dd') \r\n| summarize TotalEligibleGB = sum(iif(toreal(DailyBillableGB)>toreal(DailyMaxDiscountGB),toreal(DailyMaxDiscountGB),DailyBillableGB))\r\n| extend TotalDiscount = toreal(TotalEligibleGB)*{Price}\r\n| project TotalDiscount\r\n\r\n",
+ "size": 4,
+ "title": "Estimated Saving",
+ "timeContextFromParameter": "TimeRange",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "TotalDiscount",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "greenRed"
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "conditionalVisibilities": [
+ {
+ "parameterName": "TotalE5Seats",
+ "comparison": "isNotEqualTo",
+ "value": "0"
+ },
+ {
+ "parameterName": "TotalE5Seats",
+ "comparison": "isNotEqualTo"
+ }
+ ],
+ "customWidth": "20",
+ "name": "EstimateE5Discount"
+ },
+ {
+ "type": 1,
+ "content": {
+ "json": "## SOAR summary\r\n\r\nIn this section, you can view billable information regarding your Logic Apps. The data is based on Logic Apps' built-in metrics. To view the list of Logic Apps click the \">\" icon in the subscription column.\r\n\r\nYou can change the default Logic App execution cost in the parameter below.\r\n\r\nTo see the approximate cost of your logic apps, **click on any subscription on the table below**.\r\n\r\nFor more billable information, visit: https://azure.microsoft.com/pricing/details/logic-apps/"
+ },
+ "name": "text - 3"
+ },
+ {
+ "type": 9,
+ "content": {
+ "version": "KqlParameterItem/1.0",
+ "parameters": [
+ {
+ "id": "6f50ee54-8f0e-424e-9e16-70eca531af7f",
+ "version": "KqlParameterItem/1.0",
+ "name": "ResourceTypes",
+ "label": "Resource types",
+ "type": 7,
+ "isRequired": true,
+ "multiSelect": true,
+ "quote": "'",
+ "delimiter": ",",
+ "value": [
+ "microsoft.logic/workflows"
+ ],
+ "isHiddenWhenLocked": true,
+ "typeSettings": {
+ "additionalResourceOptions": [],
+ "includeAll": true
+ },
+ "timeContext": {
+ "durationMs": 86400000
+ }
+ },
+ {
+ "id": "1c8dc8da-2233-426c-8cfc-52ec31bf1e84",
+ "version": "KqlParameterItem/1.0",
+ "name": "Subscription",
+ "label": "Subscriptions",
+ "type": 6,
+ "isRequired": true,
+ "multiSelect": true,
+ "quote": "'",
+ "delimiter": ",",
+ "query": "Resources\r\n| where type in~ ({ResourceTypes})\r\n| summarize Count = count() by subscriptionId\r\n| order by Count desc\r\n| extend Rank = row_number()\r\n| project value = subscriptionId, label = subscriptionId, selected = Rank == 1",
+ "typeSettings": {
+ "additionalResourceOptions": [
+ "value::all"
+ ],
+ "showDefault": false
+ },
+ "timeContext": {
+ "durationMs": 86400000
+ },
+ "defaultValue": "value::all",
+ "queryType": 1,
+ "resourceType": "microsoft.resourcegraph/resources",
+ "value": [
+ "value::all"
+ ]
+ },
+ {
+ "id": "f103ef04-042e-45ed-8f78-b31e676258d7",
+ "version": "KqlParameterItem/1.0",
+ "name": "ResourceGroups",
+ "label": "Resource groups",
+ "type": 2,
+ "isRequired": true,
+ "multiSelect": true,
+ "quote": "'",
+ "delimiter": ",",
+ "query": "Resources\r\n| where type in~ ({ResourceTypes})\r\n| summarize Count = count() by subscriptionId, resourceGroup\r\n| order by Count desc\r\n| extend Rank = row_number()\r\n| project value = strcat('/subscriptions/', subscriptionId, '/resourceGroups/', resourceGroup), label = resourceGroup, selected = false",
+ "typeSettings": {
+ "additionalResourceOptions": [
+ "value::all"
+ ],
+ "showDefault": false
+ },
+ "timeContext": {
+ "durationMs": 86400000
+ },
+ "defaultValue": "value::all",
+ "queryType": 1,
+ "resourceType": "microsoft.resourcegraph/resources",
+ "value": [
+ "value::all"
+ ]
+ },
+ {
+ "id": "b6514d02-8893-44b8-896e-e53ada5024d5",
+ "version": "KqlParameterItem/1.0",
+ "name": "Resources",
+ "label": "Logic Apps",
+ "type": 5,
+ "isRequired": true,
+ "multiSelect": true,
+ "quote": "'",
+ "delimiter": ",",
+ "query": "Resources\r\n| where type in~({ResourceTypes})\r\n| extend resourceGroupId = strcat('/subscriptions/', subscriptionId, '/resourceGroups/', resourceGroup)\r\n| where resourceGroupId in~({ResourceGroups}) or '*' in~({ResourceGroups})\r\n| order by name asc\r\n| extend Rank = row_number()\r\n| project value = id, label = tostring(name), selected = Rank <= 10, group = resourceGroup",
+ "value": [
+ "value::all"
+ ],
+ "typeSettings": {
+ "additionalResourceOptions": [
+ "value::all"
+ ],
+ "showDefault": false
+ },
+ "timeContext": {
+ "durationMs": 86400000
+ },
+ "queryType": 1,
+ "resourceType": "microsoft.resourcegraph/resources"
+ },
+ {
+ "id": "8f552e99-2d30-4679-b4b0-25429bf0216b",
+ "version": "KqlParameterItem/1.0",
+ "name": "ExecutionCost",
+ "label": "Logic App execution cost",
+ "type": 1,
+ "isRequired": true,
+ "value": "0.000125"
+ }
+ ],
+ "style": "pills",
+ "queryType": 1,
+ "resourceType": "microsoft.resourcegraph/resources"
+ },
+ "name": "parameters - 10"
+ },
+ {
+ "type": 10,
+ "content": {
+ "chartId": "workbooke70b7cbc-f1d7-4a74-b8b9-75cc8d5ab586",
+ "version": "MetricsItem/2.0",
+ "size": 1,
+ "chartType": 0,
+ "resourceType": "microsoft.logic/workflows",
+ "metricScope": 0,
+ "resourceParameter": "Resources",
+ "resourceIds": [
+ "{Resources}"
+ ],
+ "timeContextFromParameter": "TimeRange",
+ "timeContext": {
+ "durationMs": 604800000
+ },
+ "metrics": [
+ {
+ "namespace": "microsoft.logic/workflows",
+ "metric": "microsoft.logic/workflows--TotalBillableExecutions",
+ "aggregation": 1
+ }
+ ],
+ "title": "Click on a subscription below to calculate the estimated automation costs",
+ "resourceLimit": 10000,
+ "gridSettings": {
+ "formatters": [
+ {
+ "columnMatch": "$gen_group",
+ "formatter": 15,
+ "formatOptions": {
+ "linkTarget": null,
+ "showIcon": true
+ }
+ },
+ {
+ "columnMatch": "Subscription",
+ "formatter": 5
+ },
+ {
+ "columnMatch": "Name",
+ "formatter": 13,
+ "formatOptions": {
+ "linkTarget": "Resource",
+ "showIcon": true
+ }
+ },
+ {
+ "columnMatch": "microsoft.logic/workflows--TotalBillableExecutions",
+ "formatter": 8,
+ "formatOptions": {
+ "palette": "blue",
+ "aggregation": "Sum"
+ }
+ },
+ {
+ "columnMatch": "microsoft.logic/workflows--TotalBillableExecutions Timeline",
+ "formatter": 21,
+ "formatOptions": {
+ "palette": "blue"
+ }
+ },
+ {
+ "columnMatch": "microsoft.logic/workflows--BillableTriggerExecutions Timeline",
+ "formatter": 5
+ },
+ {
+ "columnMatch": "microsoft.logic/workflows--BillableActionExecutions",
+ "formatter": 8,
+ "formatOptions": {
+ "palette": "blue"
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "style": "decimal"
+ }
+ }
+ },
+ {
+ "columnMatch": "microsoft.logic/workflows--BillableActionExecutions Timeline",
+ "formatter": 5
+ },
+ {
+ "columnMatch": "RG",
+ "formatter": 13,
+ "formatOptions": {
+ "linkTarget": null,
+ "showIcon": true
+ }
+ },
+ {
+ "columnMatch": "Sum",
+ "formatter": 1,
+ "formatOptions": {
+ "aggregation": "Sum"
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "style": "decimal"
+ }
+ }
+ }
+ ],
+ "rowLimit": 10000,
+ "filter": true,
+ "hierarchySettings": {
+ "treeType": 1,
+ "groupBy": [
+ "Subscription"
+ ]
+ },
+ "labelSettings": [
+ {
+ "columnId": "microsoft.logic/workflows--TotalBillableExecutions",
+ "label": "Total Billable Executions (Sum)"
+ },
+ {
+ "columnId": "microsoft.logic/workflows--TotalBillableExecutions Timeline",
+ "label": "Total Billable Executions Timeline"
+ }
+ ]
+ },
+ "sortBy": [],
+ "exportFieldName": "microsoft.logic/workflows--TotalBillableExecutions",
+ "exportParameterName": "Total",
+ "exportDefaultValue": "0"
+ },
+ "name": "Billable Metric"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "Usage | take 1 | project ['Estimated automation costs'] ={Total}*{ExecutionCost}",
+ "size": 4,
+ "title": "Estimated Logic App execution cost over the last {TimeRange}",
+ "timeContext": {
+ "durationMs": 86400000
+ },
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "Estimated automation costs",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "greenRed"
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency",
+ "minimumFractionDigits": 2,
+ "maximumFractionDigits": 3
+ }
+ }
+ },
+ "showBorder": false
+ }
+ },
+ "conditionalVisibility": {
+ "parameterName": "Total",
+ "comparison": "isNotEqualTo"
+ },
+ "name": "query - 11"
+ }
+ ],
+ "fromTemplateId": "sentinel-SentinelCosts",
+ "$schema": "https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json"
+}
diff --git a/Workbooks/WorkbooksMetadata.json b/Workbooks/WorkbooksMetadata.json
index a8a58f9dedd..d3043416f15 100644
--- a/Workbooks/WorkbooksMetadata.json
+++ b/Workbooks/WorkbooksMetadata.json
@@ -7005,7 +7005,7 @@
"SentinelCostsWhite.png",
"SentinelCostsBlack.png"
],
- "version": "1.6.0",
+ "version": "1.5.1",
"title": "Sentinel Costs",
"templateRelativePath": "SentinelCosts.json",
"subtitle": "",
From 04cb636a47f852e2b4bbe66cd2c15768d189483a Mon Sep 17 00:00:00 2001
From: Dr Bill Mcilhargey <19168174+billmcilhargey@users.noreply.github.com>
Date: Mon, 31 Aug 2026 14:51:41 -0400
Subject: [PATCH 4/6] Update Sentinel cost workbook package
---
Solutions/SOC Handbook/ReleaseNotes.md | 1 +
.../Workbooks/AzureSentinelCost.json | 2107 +++++++----------
2 files changed, 887 insertions(+), 1221 deletions(-)
diff --git a/Solutions/SOC Handbook/ReleaseNotes.md b/Solutions/SOC Handbook/ReleaseNotes.md
index a0a18e684cd..4182a3129c4 100644
--- a/Solutions/SOC Handbook/ReleaseNotes.md
+++ b/Solutions/SOC Handbook/ReleaseNotes.md
@@ -1,5 +1,6 @@
| **Version** | **Date Modified (DD-MM-YYYY)** | **Change History** |
|-------------|--------------------------------|-------------------------------------------------------------------------------------|
+| 3.0.9 | 31-08-2026 | Packaged the *AzureSentinelCost* **Workbook** enhancements for the SOC Handbook solution.|
| 3.0.8 | 31-08-2026 | Reorganized *AzureSentinelCost* **Workbook** into collapsible sections and added Free Sentinel Data, Retention, Commitment Tier, and Data Lake cost estimates. Charts now scale their time grain to the selected range, license grants are prorated per interval, the commitment tier recommendation is withheld with a countdown until 31 days of data are available, and Logic App scoping was corrected to use explicit resource IDs.|
| 3.0.7 | 21-07-2026 | Fixed bugs in *AnalyticsEfficiency* **Workbook** (typo fixes, added MITRE ATT&CK tactics, removed hardcoded timeContext overrides), rebranded 'Azure Sentinel' to 'Microsoft Sentinel' across *SentinelCentral*, *AzureSentinelSecurityAlerts*, and *AnalyticsEfficiency* **Workbooks**, fixed layout issues in *IntsightsIOCWorkbook*, and updated *MITREAttack* **Workbook** tactic mappings.|
| 3.0.6 | 13-01-2026 | Updated *IncidentOverview* **Workbook** to correct the incident render issue by using ProviderIncidentId with IncidentNumber|
diff --git a/Solutions/SOC Handbook/Workbooks/AzureSentinelCost.json b/Solutions/SOC Handbook/Workbooks/AzureSentinelCost.json
index a40e03285ce..4db4ae6d2c3 100644
--- a/Solutions/SOC Handbook/Workbooks/AzureSentinelCost.json
+++ b/Solutions/SOC Handbook/Workbooks/AzureSentinelCost.json
@@ -7,8 +7,7 @@
"json": "# Microsoft Sentinel cost summary\n---\n"
},
"name": "text - 2"
- },
- {
+ },{
"type": 9,
"content": {
"version": "KqlParameterItem/1.0",
@@ -132,31 +131,25 @@
"resourceType": "microsoft.operationalinsights/workspaces"
},
"name": "parameters - global"
- },
- {
+ },{
"type": 12,
"content": {
"version": "NotebookGroup/1.0",
"groupType": "editable",
- "title": "Costing",
+ "title": "Workspace Ingestion summary",
"expandable": true,
"expanded": true,
"items": [
- {
- "type": 1,
- "content": {
- "json": "## Workspace Ingestion summary"
- },
- "name": "text - ingestion summary"
- },
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let selectedDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); union withsource = SourceTableName * | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where _IsBillable == true | summarize ['Workspace Average Billable Daily Ingestion'] = sum(_BilledSize) / 1024.0 / 1024.0 / 1024.0 / selectedDays",
- "size": 1,
- "title": "Workspace Average Billable Daily Ingestion",
+ "query": "let selectedDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true | summarize ['Avg Daily Billable Ingestion'] = sum(Quantity) / 1024.0 / selectedDays",
+ "size": 4,
+ "title": "Avg Daily Billable Ingestion",
"timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No billable ingestion was found in the selected time range.",
+ "noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
@@ -165,10 +158,10 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "Workspace Average Billable Daily Ingestion",
+ "columnMatch": "Avg Daily Billable Ingestion",
"formatter": 12,
"formatOptions": {
- "palette": "greenRed"
+ "palette": "blue"
},
"numberFormat": {
"unit": 39,
@@ -182,17 +175,19 @@
"size": "auto"
}
},
- "name": "query - 6",
- "customWidth": "25"
+ "customWidth": "25",
+ "name": "WorkspaceAvgDailyBillableIngestion"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let selectedDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); union withsource = SourceTableName * | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where _IsBillable == true | summarize ['Estimated Average Daily Ingestion Cost'] = sum(_BilledSize) / 1024.0 / 1024.0 / 1024.0 / selectedDays * todouble('{Price}')",
- "size": 1,
- "title": "Estimated Daily Ingestion Cost",
+ "query": "let selectedDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true | summarize BillableGB = sum(Quantity) / 1024.0 | project ['Est. Daily Ingestion Cost'] = BillableGB / selectedDays * todouble('{Price}')",
+ "size": 4,
+ "title": "Est. Daily Ingestion Cost",
"timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No billable ingestion was found in the selected time range.",
+ "noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
@@ -201,7 +196,7 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "Estimated Average Daily Ingestion Cost",
+ "columnMatch": "Est. Daily Ingestion Cost",
"formatter": 12,
"formatOptions": {
"palette": "greenRed"
@@ -219,17 +214,19 @@
"size": "auto"
}
},
- "name": "AverageDailyBillableIngestionCost",
- "customWidth": "25"
+ "customWidth": "25",
+ "name": "WorkspaceEstDailyIngestionCost"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true | summarize ['Workspace Billable Ingestion'] = sum(Quantity) / 1024.0",
- "size": 1,
- "title": "Workspace Billable Ingestion: {TimeRange}",
+ "query": "Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true | summarize ['Billable Ingestion'] = sum(Quantity) / 1024.0",
+ "size": 4,
+ "title": "Billable Ingestion: {TimeRange}",
"timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No billable ingestion was found in the selected time range.",
+ "noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
@@ -238,17 +235,16 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "Workspace Billable Ingestion",
+ "columnMatch": "Billable Ingestion",
"formatter": 12,
"formatOptions": {
- "palette": "greenRed"
+ "palette": "blue"
},
"numberFormat": {
"unit": 39,
"options": {
"style": "decimal",
- "useGrouping": false,
- "maximumFractionDigits": 1
+ "maximumFractionDigits": 2
}
}
},
@@ -256,17 +252,19 @@
"size": "auto"
}
},
- "name": "query - 8",
- "customWidth": "25"
+ "customWidth": "25",
+ "name": "WorkspaceBillableIngestionPeriod"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true | summarize TotalBillableIngestionGB = sum(Quantity) / 1024.0 | project ['Estimated Ingestion Cost'] = TotalBillableIngestionGB * todouble('{Price}')",
- "size": 1,
- "title": "Estimated Ingestion Cost: {TimeRange}",
+ "query": "Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true | summarize BillableGB = sum(Quantity) / 1024.0 | project ['Est. Ingestion Cost'] = BillableGB * todouble('{Price}')",
+ "size": 4,
+ "title": "Est. Ingestion Cost: {TimeRange}",
"timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No billable ingestion was found in the selected time range.",
+ "noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
@@ -275,7 +273,7 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "Estimated Ingestion Cost",
+ "columnMatch": "Est. Ingestion Cost",
"formatter": 12,
"formatOptions": {
"palette": "greenRed"
@@ -289,18 +287,19 @@
}
}
},
- "showBorder": false
+ "showBorder": false,
+ "size": "auto"
}
},
- "name": "BillableIngestionCost",
- "customWidth": "25"
+ "customWidth": "25",
+ "name": "WorkspaceEstIngestionCostPeriod"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
"query": "let Categories = datatable(Type:string,Category:string)\r\n[\r\n \"AuditLogs\", \"Azure Active Directory\",\r\n \"SigninLogs\", \"Azure Active Directory\",\r\n \"AADNonInteractiveUserSignInLogs\", \"Azure Active Directory\",\r\n \"AADServicePrincipalSignInLogs\", \"Azure Active Directory\",\r\n \"AADManagedIdentitySignInLogs\", \"Azure Active Directory\",\r\n \"AADProvisioningLogs\",\"Azure Active Directory\",\r\n \"BehaviorAnalytics\", \"User Entity Behavior Analytics\",\r\n \"UserPeerAnalytics\",\"User Entity Behavior Analytics\",\r\n \"UserAccessAnalytics\",\"User Entity Behavior Analytics\",\r\n \"IdentityInfo\",\"User Entity Behavior Analytics\",\r\n \"DeviceLogonEvents\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceEvents\",\"Microsoft Defender for Endpoint\",\r\n\t\"DeviceNetworkInfo\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceImageLoadEvents\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceFileEvents\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceInfo\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceProcessEvents\", \"Microsoft Defender for Endpoint\",\t\r\n\t\"DeviceNetworkEvents\", \"Microsoft Defender for Endpoint\",\r\n\t\"DeviceRegistryEvents\", \"Microsoft Defender for Endpoint\",\r\n \"DeviceFileCertificateInfo\", \"Microsoft Defender for Endpoint\",\r\n \"EmailAttachmentInfo\", \"Microsoft Defender for Office 365\", \r\n \"EmailEvents\", \"Microsoft Defender for Office 365\", \r\n \"EmailPostDeliveryEvents\", \"Microsoft Defender for Office 365\", \r\n \"EmailUrlInfo\", \"Microsoft Defender for Office 365\",\r\n \"IdentityLogonEvents\", \"Microsoft Defender for Identity\",\r\n \"IdentityQueryEvents\", \"Microsoft Defender for Identity\",\r\n \"IdentityDirectoryEvents\", \"Microsoft Defender for Identity\",\r\n \"CloudAppEvents\", \"Microsoft Defender for Cloud Apps\",\r\n \"AlertEvidence\", \"Microsoft Defender Alert Evidence\",\r\n \"InsightsMetrics\", \"Azure Monitor for VMs\",\r\n \"VMBoundPort\", \"Azure Monitor for VMs\",\r\n \"VMComputer\", \"Azure Monitor for VMs\",\r\n \"VMConnection\", \"Azure Monitor for VMs\",\r\n \"VMProcess\", \"Azure Monitor for VMs\",\r\n \"SecurityEvent\", \"Windows Security Events\",\r\n \"Syslog\", \"Syslog/CEF\",\r\n \"CommonSecurityLog\", \"Syslog/CEF\",\r\n \"ThreatIntelligenceIndicator\", \"Threat Intelligence\",\r\n \"DnsEvents\", \"DNS Logs\",\r\n \"DnsInventory\", \"DNS Logs\",\r\n \"AWSCloudTrail\", \"AWS Cloud Trail\",\r\n \"ConfigurationChange\", \"Change Tracking\",\r\n \"ConfigurationData\", \"Change Tracking\",\r\n \"AzureDiagnostics\", \"Azure Resources\",\r\n \"LAQueryLogs\", \"Management\",\r\n \"SentinelHealth\",\"Management\",\r\n \"Perf\",\"Performance\",\r\n \"AzureMetrics\",\"Azure Metrics\",\r\n \"SecurityNestedRecommendation\", \"Microsoft Defender for Cloud\",\r\n \"SecurityRecommendation\", \"Microsoft Defender for Cloud\",\r\n \"SecurityRegulatoryCompliance\", \"Microsoft Defender for Cloud\",\r\n \"SecureScoreControls\", \"Microsoft Defender for Cloud\",\r\n \"SecurityBaseline\", \"Microsoft Defender for Cloud\",\r\n \"SecureScores\", \"Microsoft Defender for Cloud\",\r\n \"Update\", \"Update Management\",\r\n \"UpdateSummary\", \"Update Management\"\r\n];\r\nlet customTables = Usage\r\n| where TimeGenerated between ({TimeRange:start} .. {TimeRange:end})\r\n| where IsBillable == true\r\n| where DataType contains \"_CL\"\r\n| summarize size = sum(Quantity)/1024 by DataType\r\n| project ['Log Type'] = DataType, ['Table Size'] = size, ['Estimated Cost'] = size*{Price};\r\nlet knownTables = Usage\r\n| where TimeGenerated between ({TimeRange:start} .. {TimeRange:end})\r\n| where IsBillable == true \r\n| join kind=leftouter Categories on $left.DataType == $right.Type\r\n| summarize size =sumif(Quantity, isnotempty(Category))/1024, sizeOther= sumif(Quantity,(isempty(Category) and DataType !contains \"_CL\"))/1024 by Category\r\n| project ['Log Type'] = iif(isnotempty( Category),Category,\"Other\"), ['Table Size'] = iif(isnotempty( Category),size,sizeOther), ['Estimated Cost'] = iif(isnotempty(Category),size*{Price},sizeOther*4);\r\nunion customTables, knownTables\r\n| order by ['Table Size'] desc",
- "size": 1,
+ "size": 0,
"title": "Breakdown of Workspace billable ingestion by log category in the {TimeRange}",
"timeContextFromParameter": "TimeRange",
"queryType": 0,
@@ -315,7 +314,7 @@
"columnMatch": "Log Type",
"formatter": 0,
"formatOptions": {
- "customColumnWidthSetting": "2fr"
+ "customColumnWidthSetting": "45%"
}
},
{
@@ -323,7 +322,7 @@
"formatter": 3,
"formatOptions": {
"palette": "greenRed",
- "customColumnWidthSetting": "1fr"
+ "customColumnWidthSetting": "30%"
},
"numberFormat": {
"unit": 39,
@@ -337,7 +336,7 @@
"columnMatch": "Estimated Cost",
"formatter": 0,
"formatOptions": {
- "customColumnWidthSetting": "1fr"
+ "customColumnWidthSetting": "25%"
},
"numberFormat": {
"unit": 0,
@@ -405,32 +404,100 @@
]
},
"name": "group - Costing"
- },
- {
+ },{
"type": 12,
"content": {
"version": "NotebookGroup/1.0",
"groupType": "editable",
- "title": "Free Sentinel Data",
+ "title": "Data Lake Ingestion summary",
"expandable": true,
"expanded": true,
"items": [
{
"type": 1,
"content": {
- "json": "## Free Sentinel Data Summary\r\n\r\nMicrosoft documents the following Sentinel data sources as free:\r\n\r\n- Azure Activity Logs (`AzureActivity`)\r\n- Health monitoring for Microsoft Sentinel (`SentinelHealth`)\r\n- Microsoft 365 audit activity (`OfficeActivity`)\r\n- Microsoft Entra ID Protection alerts (`SecurityAlert`)\r\n- Microsoft Defender for Cloud and Defender for IoT alerts (`SecurityAlert`)\r\n- Microsoft Defender XDR incidents and alerts (`SecurityIncident`, `SecurityAlert`)\r\n- Microsoft Defender for Endpoint, Identity, Cloud Apps, and Office 365 alerts (`SecurityAlert`)\r\n\r\nThis section estimates Analytics-tier ingestion in the selected workspace scope and keeps it separate from billable ingestion. It does not estimate data lake-only ingestion, storage, processing, or query charges. Usage is grouped by table and cannot reliably identify the originating connector, so `SecurityAlert` cannot be allocated reliably among its contributing services. This estimate does not calculate the separate Sentinel free trial. Review the [Microsoft Sentinel free data sources](https://learn.microsoft.com/azure/sentinel/billing?tabs=simplified%2Ccommitment-tiers#free-data-sources) documentation for current eligibility and billing terms."
+ "json": "The data lake stores security data outside the Analytics tier and is billed on five separate meters. This workbook can estimate mirrored storage volume from workspace data, but it cannot produce a complete data lake cost estimate because several meters are not recorded in the Analytics workspace.\r\n\r\nThis section can derive the following from mirrored workspace `Usage` volume:\r\n\r\n- Mirrored volume size by table\r\n- Retained raw log size based on the selected Analytics and total lake retention assumptions\r\n- Billed compressed log size using the documented **6:1** compression ratio\r\n- Estimated lake storage cost for the selected time range, using the storage price parameter\r\n\r\nThe following meters are not visible in the Analytics workspace and are not modeled in this workbook:\r\n\r\n- Data lake ingestion: monthly GB ingested into tables set to data lake tier only\r\n- Data processing: monthly GB processed for lake-tier-only tables, including transformations such as redaction, splitting, filtering, and normalization\r\n- Data lake query: monthly GB of uncompressed data scanned by KQL queries and jobs against the lake\r\n- Advanced data insights: monthly notebook and job compute hours\r\n\r\nWhen the data lake is enabled, Analytics-tier data is **mirrored** to the lake at no extra ingestion charge, so mirrored volume is visible in `Usage` and is used for the storage estimate. Ingestion and data processing are charged only for tables set to **data lake tier only**; that data never reaches the Analytics workspace. Query charges depend on GB scanned and insights charges on notebook compute hours, neither of which is recorded in `Usage`.\r\n\r\nStorage is billed on compressed data and applies only to data still retained after the Analytics retention period ends. These are planning estimates, not invoice values.\r\n\r\nValidate in **Microsoft Sentinel > Cost management** in the Microsoft Defender portal, and review the [data lake overview](https://learn.microsoft.com/azure/sentinel/datalake/sentinel-lake-overview), [billing model](https://learn.microsoft.com/azure/sentinel/billing#understand-the-full-billing-model-for-microsoft-sentinel), and [cost monitoring guidance](https://learn.microsoft.com/azure/sentinel/billing-monitor-costs)."
},
- "name": "text - free Sentinel data"
+ "name": "text - Microsoft Sentinel Data Lake"
+ },
+ {
+ "type": 9,
+ "content": {
+ "version": "KqlParameterItem/1.0",
+ "parameters": [
+ {
+ "id": "3a7c1f0e-6b21-4d4c-9f83-1c5c4a9d2b71",
+ "version": "KqlParameterItem/1.0",
+ "name": "LakeStoragePrice",
+ "label": "Lake storage price (per compressed GB/month)",
+ "type": 1,
+ "isRequired": true,
+ "description": "Data lake storage rate per compressed GB per month. Storage is billed at a 6:1 compression ratio on data retained after Analytics retention ends.",
+ "typeSettings": {
+ "paramValidationRules": [
+ {
+ "regExp": "^(0|[1-9][0-9]*)(\\.[0-9]+)?$",
+ "match": true,
+ "message": "Enter a non-negative price."
+ }
+ ]
+ },
+ "value": "0.026"
+ },
+ {
+ "id": "5d92b83a-4f17-4a6e-bd15-9e2f7c3a8d64",
+ "version": "KqlParameterItem/1.0",
+ "name": "LakeAnalyticsRetentionDays",
+ "label": "Analytics retention (days)",
+ "type": 1,
+ "isRequired": true,
+ "description": "Analytics-tier retention in days. Lake storage is charged only for data retained beyond this period.",
+ "typeSettings": {
+ "paramValidationRules": [
+ {
+ "regExp": "^[1-9][0-9]*$",
+ "match": true,
+ "message": "Enter a whole number of days greater than zero."
+ }
+ ]
+ },
+ "value": "90"
+ },
+ {
+ "id": "7e4a6c25-8d39-4b72-a1f6-3b8d5e0c9a17",
+ "version": "KqlParameterItem/1.0",
+ "name": "LakeTotalRetentionMonths",
+ "label": "Total lake retention (months)",
+ "type": 1,
+ "isRequired": true,
+ "description": "Total retention in the data lake tier, up to 12 years (144 months).",
+ "typeSettings": {
+ "paramValidationRules": [
+ {
+ "regExp": "^[1-9][0-9]*$",
+ "match": true,
+ "message": "Enter a whole number of months greater than zero."
+ }
+ ]
+ },
+ "value": "12"
+ }
+ ],
+ "style": "pills",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces"
+ },
+ "name": "parameters - data lake pricing"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let freeTypes = dynamic([\"AzureActivity\",\"SentinelHealth\",\"OfficeActivity\",\"SecurityAlert\",\"SecurityIncident\"]); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where DataType in (freeTypes) | summarize ['Average Free Data Per Day'] = sum(Quantity) / 1024.0 / periodDays",
- "size": 1,
- "title": "Average Free Data Per Day",
+ "query": "let selectedDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | summarize ['Average Daily Mirrored Volume'] = sum(Quantity) / 1024.0 / selectedDays",
+ "size": 4,
+ "title": "Average Daily Mirrored Volume",
"timeContextFromParameter": "TimeRange",
- "noDataMessage": "No documented free Sentinel data was observed in the selected time range.",
+ "noDataMessage": "No mirrored table usage data was found in the selected time range.",
"noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
@@ -440,7 +507,7 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "Average Free Data Per Day",
+ "columnMatch": "Average Daily Mirrored Volume",
"formatter": 12,
"formatOptions": {
"palette": "blue"
@@ -449,25 +516,26 @@
"unit": 39,
"options": {
"style": "decimal",
- "maximumFractionDigits": 3
+ "maximumFractionDigits": 2
}
}
},
- "showBorder": false
+ "showBorder": false,
+ "size": "auto"
}
},
"customWidth": "25",
- "name": "FreeSentinelDataTotal"
+ "name": "DataLakeAverageMirroredVolume"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let freeTypes = dynamic([\"AzureActivity\",\"SentinelHealth\",\"OfficeActivity\",\"SecurityAlert\",\"SecurityIncident\"]); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where DataType in (freeTypes) | summarize ['Estimated Free Data Savings Per Day'] = sum(Quantity) / 1024.0 / periodDays * todouble('{Price}')",
- "size": 1,
- "title": "Avg Daily Free Data Savings",
+ "query": "let compressionRatio = 6.0; let selectedDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); let chargeableDays = max_of(todouble('{LakeTotalRetentionMonths}') * 30.0 - todouble('{LakeAnalyticsRetentionDays}'), 0.0); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | summarize RawGB = sum(Quantity) / 1024.0 | extend ['Estimated Daily Data Lake Cost'] = RawGB / selectedDays * chargeableDays / compressionRatio * todouble('{LakeStoragePrice}') / 30.0 | project ['Estimated Daily Data Lake Cost']",
+ "size": 4,
+ "title": "Estimated Daily Data Lake Cost",
"timeContextFromParameter": "TimeRange",
- "noDataMessage": "No documented free Sentinel data was observed in the selected time range.",
+ "noDataMessage": "No mirrored table usage data was found in the selected time range.",
"noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
@@ -477,7 +545,7 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "Estimated Free Data Savings Per Day",
+ "columnMatch": "Estimated Daily Data Lake Cost",
"formatter": 12,
"formatOptions": {
"palette": "greenRed"
@@ -491,21 +559,22 @@
}
}
},
- "showBorder": false
+ "showBorder": false,
+ "size": "auto"
}
},
"customWidth": "25",
- "name": "AverageDailyFreeDataSavings"
+ "name": "DataLakeEstimatedDailyCost"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let freeTypes = dynamic([\"AzureActivity\",\"SentinelHealth\",\"OfficeActivity\",\"SecurityAlert\",\"SecurityIncident\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where DataType in (freeTypes) | summarize ['Free Data'] = sum(Quantity) / 1024.0",
- "size": 1,
- "title": "Free Data: {TimeRange}",
+ "query": "Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | summarize ['Mirrored Volume'] = sum(Quantity) / 1024.0",
+ "size": 4,
+ "title": "Mirrored Volume: {TimeRange}",
"timeContextFromParameter": "TimeRange",
- "noDataMessage": "No documented free Sentinel data was observed in the selected time range.",
+ "noDataMessage": "No mirrored table usage data was found in the selected time range.",
"noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
@@ -515,7 +584,7 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "Free Data",
+ "columnMatch": "Mirrored Volume",
"formatter": 12,
"formatOptions": {
"palette": "blue"
@@ -524,25 +593,26 @@
"unit": 39,
"options": {
"style": "decimal",
- "maximumFractionDigits": 3
+ "maximumFractionDigits": 2
}
}
},
- "showBorder": false
+ "showBorder": false,
+ "size": "auto"
}
},
"customWidth": "25",
- "name": "FreeSentinelDataSavings"
+ "name": "DataLakeMirroredVolumePeriod"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let freeTypes = dynamic([\"AzureActivity\",\"SentinelHealth\",\"OfficeActivity\",\"SecurityAlert\",\"SecurityIncident\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where DataType in (freeTypes) | summarize ['Estimated Free Data Savings'] = sum(Quantity) / 1024.0 * todouble('{Price}')",
- "size": 1,
- "title": "Estimated Free Data Savings: {TimeRange}",
+ "query": "let compressionRatio = 6.0; let selectedDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); let chargeableDays = max_of(todouble('{LakeTotalRetentionMonths}') * 30.0 - todouble('{LakeAnalyticsRetentionDays}'), 0.0); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | summarize RawGB = sum(Quantity) / 1024.0 | extend ['Estimated Lake Storage Cost'] = RawGB / selectedDays * chargeableDays / compressionRatio * todouble('{LakeStoragePrice}') * selectedDays / 30.0 | project ['Estimated Lake Storage Cost']",
+ "size": 4,
+ "title": "Estimated Lake Storage Cost: {TimeRange}",
"timeContextFromParameter": "TimeRange",
- "noDataMessage": "No documented free Sentinel data was observed in the selected time range.",
+ "noDataMessage": "No mirrored table usage data was found in the selected time range.",
"noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
@@ -552,7 +622,7 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "Estimated Free Data Savings",
+ "columnMatch": "Estimated Lake Storage Cost",
"formatter": 12,
"formatOptions": {
"palette": "greenRed"
@@ -566,21 +636,22 @@
}
}
},
- "showBorder": false
+ "showBorder": false,
+ "size": "auto"
}
},
"customWidth": "25",
- "name": "FreeDataSavingsForTimeRange"
+ "name": "DataLakeEstimatedStorageCostPeriod"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let freeTypes = dynamic([\"AzureActivity\",\"SentinelHealth\",\"OfficeActivity\",\"SecurityAlert\",\"SecurityIncident\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where DataType in (freeTypes) | summarize TableSizeGB = sum(Quantity) / 1024.0 by DataType | project ['Log Type'] = DataType, ['Table Size'] = TableSizeGB, ['Estimated Cost Savings'] = TableSizeGB * todouble('{Price}') | order by ['Table Size'] desc",
- "size": 1,
- "title": "Free data by source table in the {TimeRange}",
+ "query": "let compressionRatio = 6.0; let selectedDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); let chargeableDays = max_of(todouble('{LakeTotalRetentionMonths}') * 30.0 - todouble('{LakeAnalyticsRetentionDays}'), 0.0); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | summarize RawGB = sum(Quantity) / 1024.0 by DataType | extend AverageDailyLogSize = RawGB / selectedDays | extend RetainedRawLogSize = AverageDailyLogSize * chargeableDays | extend CompressedLogSize = RetainedRawLogSize / compressionRatio | project ['Log Type'] = DataType, ['Average Daily Log Size'] = AverageDailyLogSize, ['Mirrored Log Size'] = RawGB, ['Retained Raw Log Size'] = RetainedRawLogSize, ['Compressed Log Size'] = CompressedLogSize, ['Estimated Storage Cost'] = CompressedLogSize * todouble('{LakeStoragePrice}') * selectedDays / 30.0 | order by ['Estimated Storage Cost'] desc",
+ "size": 0,
+ "title": "Breakdown of Data Lake billable ingestion by log category in the {TimeRange}",
"timeContextFromParameter": "TimeRange",
- "noDataMessage": "No documented free Sentinel data was observed in the selected time range.",
+ "noDataMessage": "No mirrored table usage data was found in the selected time range.",
"noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
@@ -595,29 +666,75 @@
"columnMatch": "Log Type",
"formatter": 0,
"formatOptions": {
- "customColumnWidthSetting": "2fr"
+ "customColumnWidthSetting": "25%"
}
},
{
- "columnMatch": "Table Size",
+ "columnMatch": "Average Daily Log Size",
"formatter": 3,
"formatOptions": {
"palette": "greenRed",
- "customColumnWidthSetting": "1fr"
+ "customColumnWidthSetting": "18%"
},
"numberFormat": {
"unit": 39,
"options": {
"style": "decimal",
- "maximumFractionDigits": 3
+ "maximumFractionDigits": 2
}
}
},
{
- "columnMatch": "Estimated Cost Savings",
- "formatter": 0,
+ "columnMatch": "Mirrored Log Size",
+ "formatter": 3,
+ "formatOptions": {
+ "palette": "greenRed",
+ "customColumnWidthSetting": "18%"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ {
+ "columnMatch": "Retained Raw Log Size",
+ "formatter": 3,
+ "formatOptions": {
+ "palette": "greenRed",
+ "customColumnWidthSetting": "17%"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ {
+ "columnMatch": "Compressed Log Size",
+ "formatter": 3,
+ "formatOptions": {
+ "palette": "blue",
+ "customColumnWidthSetting": "14%"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 2
+ }
+ }
+ },
+ {
+ "columnMatch": "Estimated Storage Cost",
+ "formatter": 3,
"formatOptions": {
- "customColumnWidthSetting": "1fr"
+ "palette": "greenRed",
+ "customColumnWidthSetting": "8%"
},
"numberFormat": {
"unit": 0,
@@ -631,17 +748,17 @@
]
}
},
- "name": "FreeSentinelDataDetail"
+ "name": "DataLakeStorageCostByTable"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let freeTypes = dynamic([\"AzureActivity\",\"SentinelHealth\",\"OfficeActivity\",\"SecurityAlert\",\"SecurityIncident\"]); let selectedDuration = {TimeRange:end} - {TimeRange:start}; let timeGrain = case(selectedDuration <= 1h, 5m, selectedDuration <= 4h, 15m, selectedDuration <= 1d, 1h, selectedDuration <= 7d, 6h, selectedDuration <= 31d, 1d, selectedDuration <= 90d, 7d, 30d); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where DataType in (freeTypes) | summarize ['Free Data Size'] = sum(Quantity) / 1024.0 by bin(TimeGenerated, timeGrain) | order by TimeGenerated asc",
+ "query": "let compressionRatio = 6.0; let selectedDuration = {TimeRange:end} - {TimeRange:start}; let selectedDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); let chargeableDays = max_of(todouble('{LakeTotalRetentionMonths}') * 30.0 - todouble('{LakeAnalyticsRetentionDays}'), 0.0); let timeGrain = case(selectedDuration <= 1h, 5m, selectedDuration <= 4h, 15m, selectedDuration <= 1d, 1h, selectedDuration <= 7d, 6h, selectedDuration <= 31d, 1d, selectedDuration <= 90d, 7d, 30d); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | summarize ['Mirrored Volume Size'] = sum(Quantity) / 1024.0 by bin(TimeGenerated, timeGrain) | extend ['Retained Raw Log Size'] = ['Mirrored Volume Size'] / selectedDays * chargeableDays | extend ['Billed Compressed Log Size'] = ['Retained Raw Log Size'] / compressionRatio | order by TimeGenerated asc",
"size": 1,
- "title": "Free Data Size in the {TimeRange}",
+ "title": "Retained Raw Log Size vs Billed Compressed Log Size vs Mirrored Volume Size in the {TimeRange}",
"timeContextFromParameter": "TimeRange",
- "noDataMessage": "No documented free Sentinel data was observed in the selected time range.",
+ "noDataMessage": "No mirrored table usage data was found in the selected time range.",
"noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
@@ -663,67 +780,37 @@
}
}
},
- "name": "FreeDataVsBillableDataDaily"
+ "name": "DataLakeMirroredVolumeTrend"
}
]
},
- "name": "group - Free Sentinel Data"
- },
- {
+ "name": "group - Data Lake"
+ },{
"type": 12,
"content": {
"version": "NotebookGroup/1.0",
"groupType": "editable",
- "title": "E5 Benefits",
+ "title": "Free Sentinel Data Ingestion Summary",
"expandable": true,
"expanded": true,
"items": [
{
"type": 1,
"content": {
- "json": "## Microsoft Sentinel benefit for Microsoft 365 E7/E5/A5/F5/G5 customers\r\n\r\nQualifying Microsoft 365 E7, E5, A5, F5, and G5 licenses, and corresponding Security licenses, may receive a Microsoft Sentinel data grant of up to 5 MB per qualifying user per day for eligible Microsoft 365 data.\r\n\r\nEligible data-source groups include:\r\n\r\n- Microsoft Entra ID sign-in and audit logs (`SigninLogs`, `AuditLogs`, `AADNonInteractiveUserSignInLogs`, `AADServicePrincipalSignInLogs`, `AADManagedIdentitySignInLogs`, `AADProvisioningLogs`, `ADFSSignInLogs`, `AADUserRiskEvents`, `AADRiskyUsers`)\r\n- Microsoft Defender for Cloud Apps Guard shadow IT discovery logs (`McasShadowItReporting`)\r\n- Microsoft Purview Information Protection logs (`InformationProtectionLogs_CL`)\r\n- Microsoft 365 advanced hunting data (the eligible `Device*`, `Email*`, `Identity*`, `AlertEvidence`, and `CloudAppEvents` tables shown below)\r\n\r\nThis workbook estimates the Analytics-tier ingestion benefit from billable Usage data in the selected workspace scope. It does not estimate data lake-only charges or prove that a row came from an eligible connector, that the offer applies to your agreement, or that the calculated amount matches billing. The grant cap is modeled once across the selected scope; it is not multiplied per workspace.\r\n\r\nReview the [Microsoft 365 Sentinel benefit offer](https://azure.microsoft.com/pricing/offers/sentinel-microsoft-365-offer/) for current eligibility, agreement terms, and supported data types. Enter **Total Microsoft 365 E7/E5/A5/F5/G5 seats** below and use the global **Ingestion price** to calculate the estimate."
- },
- "name": "text - 12"
- },
- {
- "type": 9,
- "content": {
- "version": "KqlParameterItem/1.0",
- "parameters": [
- {
- "id": "67494f3e-322e-4411-9b45-1cbea03ed618",
- "version": "KqlParameterItem/1.0",
- "name": "TotalE5Seats",
- "label": "Total Microsoft 365 E7/E5/A5/F5/G5 seats",
- "type": 1,
- "quote": "'",
- "description": "Enter the total number of eligible Microsoft 365 E7, E5, A5, F5, and G5 or corresponding Security licenses in your environment. Eligibility depends on the current offer terms and agreement type.",
- "value": "",
- "typeSettings": {
- "paramValidationRules": [
- {
- "regExp": "^([1-9][0-9]*||)$",
- "match": true,
- "message": "Enter a whole number greater than zero, or clear the value."
- }
- ]
- }
- }
- ],
- "style": "pills",
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces"
+ "json": "Microsoft documents the following Sentinel data sources as free:\r\n\r\n- Azure Activity Logs (`AzureActivity`)\r\n- Health monitoring for Microsoft Sentinel (`SentinelHealth`)\r\n- Microsoft 365 audit activity (`OfficeActivity`)\r\n- Microsoft Entra ID Protection alerts (`SecurityAlert`)\r\n- Microsoft Defender for Cloud and Defender for IoT alerts (`SecurityAlert`)\r\n- Microsoft Defender XDR incidents and alerts (`SecurityIncident`, `SecurityAlert`)\r\n- Microsoft Defender for Endpoint, Identity, Cloud Apps, and Office 365 alerts (`SecurityAlert`)\r\n\r\nThis section estimates Analytics-tier ingestion in the selected workspace scope and keeps it separate from billable ingestion. It does not estimate data lake-only ingestion, storage, processing, or query charges. Usage is grouped by table and cannot reliably identify the originating connector, so `SecurityAlert` cannot be allocated reliably among its contributing services. This estimate does not calculate the separate Sentinel free trial. Review the [Microsoft Sentinel free data sources](https://learn.microsoft.com/azure/sentinel/billing?tabs=simplified%2Ccommitment-tiers#free-data-sources) documentation for current eligibility and billing terms."
},
- "name": "parameters - Microsoft 365 benefit"
+ "name": "text - free Sentinel data"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "Usage\r\n| where TimeGenerated between ({TimeRange:start} .. {TimeRange:end})\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\", \r\n\"DeviceFileEvents\", \r\n\"DeviceImageLoadEvents\", \r\n\"DeviceInfo\", \r\n\"DeviceLogonEvents\", \r\n\"DeviceNetworkEvents\", \r\n\"DeviceNetworkInfo\", \r\n\"DeviceProcessEvents\", \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\", \r\n\"EmailAttachmentInfo\", \r\n\"EmailEvents\", \r\n\"EmailPostDeliveryEvents\", \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\"\r\n) \r\n| summarize TotalBillableDataGB = sum(Quantity) / 1024\r\n\r\n",
- "size": 1,
- "title": "Eligible M365 Data",
+ "query": "let freeTypes = dynamic([\"AzureActivity\",\"SentinelHealth\",\"OfficeActivity\",\"SecurityAlert\",\"SecurityIncident\"]); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where DataType in (freeTypes) | summarize ['Average Free Data Per Day'] = sum(Quantity) / 1024.0 / periodDays",
+ "size": 4,
+ "title": "Average Free Data Per Day",
"timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No documented free Sentinel data was observed in the selected time range.",
+ "noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
@@ -732,33 +819,36 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "TotalBillableDataGB",
+ "columnMatch": "Average Free Data Per Day",
"formatter": 12,
"formatOptions": {
- "palette": "greenRed"
+ "palette": "blue"
},
"numberFormat": {
"unit": 39,
"options": {
"style": "decimal",
- "maximumFractionDigits": 2
+ "maximumFractionDigits": 3
}
}
},
- "showBorder": false
+ "showBorder": false,
+ "size": "auto"
}
},
- "customWidth": "20",
- "name": "E5IngestionSize"
+ "customWidth": "25",
+ "name": "FreeSentinelDataAvgPerDay"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let licenseCount = todouble('{TotalE5Seats}'); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); print MaxDataGrantGB = iif(isnull(licenseCount), 'N/A', strcat(tostring(round(licenseCount * 5.0 / 1024.0 * periodDays, 3)), ' GB'))",
- "size": 1,
- "title": "Total Data Grant Limit: {TimeRange}",
+ "query": "let freeTypes = dynamic([\"AzureActivity\",\"SentinelHealth\",\"OfficeActivity\",\"SecurityAlert\",\"SecurityIncident\"]); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where DataType in (freeTypes) | summarize FreeGB = sum(Quantity) / 1024.0 | project ['Avg Daily Free Data Savings'] = FreeGB / periodDays * todouble('{Price}')",
+ "size": 4,
+ "title": "Avg Daily Free Data Savings",
"timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No documented free Sentinel data was observed in the selected time range.",
+ "noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
@@ -767,34 +857,37 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "MaxDataGrantGB",
+ "columnMatch": "Avg Daily Free Data Savings",
"formatter": 12,
"formatOptions": {
- "palette": "orangeBlue"
+ "palette": "greenRed"
},
"numberFormat": {
- "unit": 39,
+ "unit": 0,
"options": {
- "style": "decimal",
+ "currency": "USD",
+ "style": "currency",
"maximumFractionDigits": 2
}
}
},
"showBorder": false,
- "sortOrderField": 1
+ "size": "auto"
}
},
- "customWidth": "20",
- "name": "DataGrantLimit"
+ "customWidth": "25",
+ "name": "FreeSentinelDataAvgDailySavings"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let eligibleTables = dynamic([\"SigninLogs\",\"AuditLogs\",\"AADNonInteractiveUserSignInLogs\",\"AADServicePrincipalSignInLogs\",\"AADManagedIdentitySignInLogs\",\"AADProvisioningLogs\",\"ADFSSignInLogs\",\"McasShadowItReporting\",\"InformationProtectionLogs_CL\",\"DeviceEvents\",\"DeviceFileEvents\",\"DeviceImageLoadEvents\",\"DeviceInfo\",\"DeviceLogonEvents\",\"DeviceNetworkEvents\",\"DeviceNetworkInfo\",\"DeviceProcessEvents\",\"DeviceRegistryEvents\",\"DeviceFileCertificateInfo\",\"EmailAttachmentInfo\",\"EmailEvents\",\"EmailPostDeliveryEvents\",\"EmailUrlInfo\",\"IdentityLogonEvents\",\"IdentityQueryEvents\",\"IdentityDirectoryEvents\",\"AlertEvidence\",\"CloudAppEvents\"]); let licenseCount = todouble('{TotalE5Seats}'); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); let eligibleGB = toreal(coalesce(toscalar(Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize sum(Quantity) / 1024.0), 0.0)); let periodGrantGB = licenseCount * 5.0 / 1024.0 * periodDays; print TotalEligibleGB = iif(isnull(licenseCount), 'N/A', strcat(tostring(round(min_of(eligibleGB, periodGrantGB), 3)), ' GB'))",
- "size": 1,
- "title": "Total Data Grant Used: {TimeRange}",
+ "query": "let freeTypes = dynamic([\"AzureActivity\",\"SentinelHealth\",\"OfficeActivity\",\"SecurityAlert\",\"SecurityIncident\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where DataType in (freeTypes) | summarize ['Free Data'] = sum(Quantity) / 1024.0",
+ "size": 4,
+ "title": "Free Data: {TimeRange}",
"timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No documented free Sentinel data was observed in the selected time range.",
+ "noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
@@ -803,34 +896,36 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "TotalEligibleGB",
+ "columnMatch": "Free Data",
"formatter": 12,
"formatOptions": {
- "palette": "coldHot"
+ "palette": "blue"
},
"numberFormat": {
"unit": 39,
"options": {
"style": "decimal",
- "maximumFractionDigits": 2
+ "maximumFractionDigits": 3
}
}
},
"showBorder": false,
- "sortOrderField": 1
+ "size": "auto"
}
},
- "customWidth": "30",
- "name": "EligibleE5Ingestion"
+ "customWidth": "25",
+ "name": "FreeSentinelDataPeriod"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let eligibleTables = dynamic([\"SigninLogs\",\"AuditLogs\",\"AADNonInteractiveUserSignInLogs\",\"AADServicePrincipalSignInLogs\",\"AADManagedIdentitySignInLogs\",\"AADProvisioningLogs\",\"ADFSSignInLogs\",\"McasShadowItReporting\",\"InformationProtectionLogs_CL\",\"DeviceEvents\",\"DeviceFileEvents\",\"DeviceImageLoadEvents\",\"DeviceInfo\",\"DeviceLogonEvents\",\"DeviceNetworkEvents\",\"DeviceNetworkInfo\",\"DeviceProcessEvents\",\"DeviceRegistryEvents\",\"DeviceFileCertificateInfo\",\"EmailAttachmentInfo\",\"EmailEvents\",\"EmailPostDeliveryEvents\",\"EmailUrlInfo\",\"IdentityLogonEvents\",\"IdentityQueryEvents\",\"IdentityDirectoryEvents\",\"AlertEvidence\",\"CloudAppEvents\"]); let licenseCount = todouble('{TotalE5Seats}'); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); let eligibleGB = toreal(coalesce(toscalar(Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize sum(Quantity) / 1024.0), 0.0)); let periodGrantGB = licenseCount * 5.0 / 1024.0 * periodDays; print TotalDiscount = iif(isnull(licenseCount), 'N/A', strcat('$', tostring(round(min_of(eligibleGB, periodGrantGB) * todouble('{Price}'), 2))))",
- "size": 1,
- "title": "Estimated Cost Savings: {TimeRange}",
+ "query": "let freeTypes = dynamic([\"AzureActivity\",\"SentinelHealth\",\"OfficeActivity\",\"SecurityAlert\",\"SecurityIncident\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where DataType in (freeTypes) | summarize ['Estimated Free Data Savings'] = sum(Quantity) / 1024.0 * todouble('{Price}')",
+ "size": 4,
+ "title": "Estimated Free Data Savings: {TimeRange}",
"timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No documented free Sentinel data was observed in the selected time range.",
+ "noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
@@ -839,7 +934,7 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "TotalDiscount",
+ "columnMatch": "Estimated Free Data Savings",
"formatter": 12,
"formatOptions": {
"palette": "greenRed"
@@ -853,21 +948,22 @@
}
}
},
- "showBorder": false
+ "showBorder": false,
+ "size": "auto"
}
},
- "customWidth": "20",
- "name": "EstimateE5Discount"
+ "customWidth": "25",
+ "name": "FreeSentinelDataSavingsPeriod"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let eligibleTables = dynamic([\"SigninLogs\",\"AuditLogs\",\"AADNonInteractiveUserSignInLogs\",\"AADServicePrincipalSignInLogs\",\"AADManagedIdentitySignInLogs\",\"AADProvisioningLogs\",\"ADFSSignInLogs\",\"AADUserRiskEvents\",\"AADRiskyUsers\",\"McasShadowItReporting\",\"InformationProtectionLogs_CL\",\"DeviceEvents\",\"DeviceFileEvents\",\"DeviceImageLoadEvents\",\"DeviceInfo\",\"DeviceLogonEvents\",\"DeviceNetworkEvents\",\"DeviceNetworkInfo\",\"DeviceProcessEvents\",\"DeviceRegistryEvents\",\"DeviceFileCertificateInfo\",\"EmailAttachmentInfo\",\"EmailEvents\",\"EmailPostDeliveryEvents\",\"EmailUrlInfo\",\"IdentityLogonEvents\",\"IdentityQueryEvents\",\"IdentityDirectoryEvents\",\"AlertEvidence\",\"CloudAppEvents\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize TableSizeGB = sum(Quantity) / 1024.0 by DataType | project ['Log Type'] = DataType, ['Table Size'] = TableSizeGB | order by ['Table Size'] desc",
- "size": 1,
- "title": "Eligible Microsoft 365 data by source table in the {TimeRange}",
+ "query": "let freeTypes = dynamic([\"AzureActivity\",\"SentinelHealth\",\"OfficeActivity\",\"SecurityAlert\",\"SecurityIncident\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where DataType in (freeTypes) | summarize TableSizeGB = sum(Quantity) / 1024.0 by DataType | project ['Log Type'] = DataType, ['Table Size'] = TableSizeGB, ['Estimated Cost Savings'] = TableSizeGB * todouble('{Price}') | order by ['Table Size'] desc",
+ "size": 0,
+ "title": "Free data by source table in the {TimeRange}",
"timeContextFromParameter": "TimeRange",
- "noDataMessage": "No eligible Microsoft 365 data was found in the selected time range.",
+ "noDataMessage": "No documented free Sentinel data was observed in the selected time range.",
"noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
@@ -882,7 +978,7 @@
"columnMatch": "Log Type",
"formatter": 0,
"formatOptions": {
- "customColumnWidthSetting": "2fr"
+ "customColumnWidthSetting": "45%"
}
},
{
@@ -890,7 +986,7 @@
"formatter": 3,
"formatOptions": {
"palette": "greenRed",
- "customColumnWidthSetting": "1fr"
+ "customColumnWidthSetting": "30%"
},
"numberFormat": {
"unit": 39,
@@ -899,21 +995,36 @@
"maximumFractionDigits": 3
}
}
+ },
+ {
+ "columnMatch": "Estimated Cost Savings",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "25%"
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency",
+ "maximumFractionDigits": 2
+ }
+ }
}
]
}
},
- "name": "E5EligibleDataDetail"
+ "name": "FreeSentinelDataDetail"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let eligibleTables = dynamic([\"SigninLogs\",\"AuditLogs\",\"AADNonInteractiveUserSignInLogs\",\"AADServicePrincipalSignInLogs\",\"AADManagedIdentitySignInLogs\",\"AADProvisioningLogs\",\"ADFSSignInLogs\",\"AADUserRiskEvents\",\"AADRiskyUsers\",\"McasShadowItReporting\",\"InformationProtectionLogs_CL\",\"DeviceEvents\",\"DeviceFileEvents\",\"DeviceImageLoadEvents\",\"DeviceInfo\",\"DeviceLogonEvents\",\"DeviceNetworkEvents\",\"DeviceNetworkInfo\",\"DeviceProcessEvents\",\"DeviceRegistryEvents\",\"DeviceFileCertificateInfo\",\"EmailAttachmentInfo\",\"EmailEvents\",\"EmailPostDeliveryEvents\",\"EmailUrlInfo\",\"IdentityLogonEvents\",\"IdentityQueryEvents\",\"IdentityDirectoryEvents\",\"AlertEvidence\",\"CloudAppEvents\"]); let licenseCount = todouble('{TotalE5Seats}'); let selectedDuration = {TimeRange:end} - {TimeRange:start}; let timeGrain = case(selectedDuration <= 1h, 5m, selectedDuration <= 4h, 15m, selectedDuration <= 1d, 1h, selectedDuration <= 7d, 6h, selectedDuration <= 31d, 1d, selectedDuration <= 90d, 7d, 30d); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize ['Ingestion Size'] = sum(Quantity) / 1024.0 by bin(TimeGenerated, timeGrain) | extend ['Grant Limit for Interval'] = iif(isnull(licenseCount), real(null), licenseCount * 5.0 / 1024.0 * (timeGrain / 1d)) | order by TimeGenerated asc",
+ "query": "let freeTypes = dynamic([\"AzureActivity\",\"SentinelHealth\",\"OfficeActivity\",\"SecurityAlert\",\"SecurityIncident\"]); let selectedDuration = {TimeRange:end} - {TimeRange:start}; let timeGrain = case(selectedDuration <= 1h, 5m, selectedDuration <= 4h, 15m, selectedDuration <= 1d, 1h, selectedDuration <= 7d, 6h, selectedDuration <= 31d, 1d, selectedDuration <= 90d, 7d, 30d); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where DataType in (freeTypes) | summarize ['Free Data Size'] = sum(Quantity) / 1024.0 by bin(TimeGenerated, timeGrain) | order by TimeGenerated asc",
"size": 1,
- "title": "Ingestion Size vs Prorated Data Grant in the {TimeRange}",
+ "title": "Free Data Size in the {TimeRange}",
"timeContextFromParameter": "TimeRange",
- "noDataMessage": "No eligible Microsoft 365 data was found in the selected time range.",
+ "noDataMessage": "No documented free Sentinel data was observed in the selected time range.",
"noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
@@ -935,27 +1046,26 @@
}
}
},
- "name": "E5DailyIngestionVsGrant"
+ "name": "FreeDataVsBillableDataDaily"
}
]
},
- "name": "group - E5 Benefits"
- },
- {
+ "name": "group - Free Sentinel Data"
+ },{
"type": 12,
"content": {
"version": "NotebookGroup/1.0",
"groupType": "editable",
- "title": "Defender for Cloud Plan 2 Ingestion Benefit",
+ "title": "Microsoft Sentinel benefit for Microsoft 365 E7/E5/A5/F5/G5 customers",
"expandable": true,
"expanded": true,
"items": [
{
"type": 1,
"content": {
- "json": "## Microsoft Sentinel benefit for Defender for Servers Plan 2\r\n\r\nDefender for Servers Plan 2 provides up to 500 MB of eligible Analytics-tier ingestion per protected server or node per day. The allowance is pooled across machines in each subscription and applied at workspace level. This workbook estimates observed usage; it does not prove Plan 2 protection, licensing, eligibility, or data lake-only charges.\r\n\r\nCore eligible tables:\r\n\r\n- `SecurityAlert`, `SecurityBaseline`, `SecurityBaselineSummary`, `SecurityDetection`, `SecurityEvent`\r\n- `WindowsFirewall`, `ProtectionStatus`, `MDCFileIntegrityMonitoringEvents`\r\n- `DeviceCustomFileEvents`, `DeviceCustomRegistryEvents`\r\n\r\nConditionally eligible tables:\r\n\r\n- `Update`, `UpdateSummary`: review the applicable Update Management conditions\r\n- `WindowsEvent`: only security data from the Microsoft-SecurityEvent stream\r\n\r\nNodes is the distinct `Computer` count observed in `Heartbeat`, not proof of licensing or Plan 2 protection. Review the [Defender for Servers Plan 2 data ingestion benefit](https://learn.microsoft.com/azure/defender-for-cloud/data-ingestion-benefit) for current eligibility and terms."
+ "json": "Qualifying Microsoft 365 E7, E5, A5, F5, and G5 licenses, and corresponding Security licenses, may receive a Microsoft Sentinel data grant of up to 5 MB per qualifying user per day for eligible Microsoft 365 data.\r\n\r\nEligible data-source groups include:\r\n\r\n- Microsoft Entra ID sign-in and audit logs (`SigninLogs`, `AuditLogs`, `AADNonInteractiveUserSignInLogs`, `AADServicePrincipalSignInLogs`, `AADManagedIdentitySignInLogs`, `AADProvisioningLogs`, `ADFSSignInLogs`, `AADUserRiskEvents`, `AADRiskyUsers`)\r\n- Microsoft Defender for Cloud Apps Guard shadow IT discovery logs (`McasShadowItReporting`)\r\n- Microsoft Purview Information Protection logs (`InformationProtectionLogs_CL`)\r\n- Microsoft 365 advanced hunting data (the eligible `Device*`, `Email*`, `Identity*`, `AlertEvidence`, and `CloudAppEvents` tables shown below)\r\n\r\nThis workbook estimates the Analytics-tier ingestion benefit from billable Usage data in the selected workspace scope. It does not estimate data lake-only charges or prove that a row came from an eligible connector, that the offer applies to your agreement, or that the calculated amount matches billing. The grant cap is modeled once across the selected scope; it is not multiplied per workspace.\r\n\r\nReview the [Microsoft 365 Sentinel benefit offer](https://azure.microsoft.com/pricing/offers/sentinel-microsoft-365-offer/) for current eligibility, agreement terms, and supported data types. Enter **Total Microsoft 365 E7/E5/A5/F5/G5 seats** below and use the global **Ingestion price** to calculate the estimate."
},
- "name": "text - DfSP2 benefit"
+ "name": "text - 12"
},
{
"type": 9,
@@ -963,13 +1073,13 @@
"version": "KqlParameterItem/1.0",
"parameters": [
{
- "id": "f1a5dc2c-7e7f-4e48-9d65-0d52e77b6e3a",
+ "id": "67494f3e-322e-4411-9b45-1cbea03ed618",
"version": "KqlParameterItem/1.0",
- "name": "TotalDfSP2Licenses",
- "label": "Protected Defender for Servers Plan 2 servers or nodes",
+ "name": "TotalE5Seats",
+ "label": "Total Microsoft 365 E7/E5/A5/F5/G5 seats",
"type": 1,
"quote": "'",
- "description": "Enter the number of protected Defender for Servers Plan 2 servers or nodes used to estimate the 500 MB per server or node per day ingestion benefit. Leave as when the entitlement is unknown; grant and savings metrics will show N/A.",
+ "description": "Enter the total number of eligible Microsoft 365 E7, E5, A5, F5, and G5 or corresponding Security licenses in your environment. Eligibility depends on the current offer terms and agreement type.",
"value": "",
"typeSettings": {
"paramValidationRules": [
@@ -980,55 +1090,22 @@
}
]
}
- },
- {
- "id": "c4f7a2d1-5b83-4e96-9a07-1f6c8b3d2e54",
- "version": "KqlParameterItem/1.0",
- "name": "DfSP2LicensePrice",
- "label": "Defender for Servers Plan 2 price (per server/month)",
- "type": 1,
- "isRequired": true,
- "description": "Monthly list price per protected server or node. Verify against your agreement and region.",
- "typeSettings": {
- "paramValidationRules": [
- {
- "regExp": "^(0|[1-9][0-9]*)(\\.[0-9]+)?$",
- "match": true,
- "message": "Enter a non-negative price."
- }
- ]
- },
- "value": "15"
}
],
"style": "pills",
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces"
},
- "name": "parameters - Defender for Servers Plan 2 benefit"
- },
- {
- "type": 1,
- "content": {
- "json": "Enter the number of protected Defender for Servers Plan 2 servers or nodes above to calculate the daily and total data grants, grant usage, and estimated cost savings."
- },
- "name": "text - DfSP2 entitlement required",
- "conditionalVisibility": {
- "parameterName": "TotalDfSP2Licenses",
- "comparison": "isEqualTo",
- "value": ""
- }
+ "name": "parameters - Microsoft 365 benefit"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize EligibleGB = sum(Quantity) / 1024.0",
- "size": 1,
- "title": "Eligible Defender for Servers Plan 2 data",
+ "query": "Usage\r\n| where TimeGenerated between ({TimeRange:start} .. {TimeRange:end})\r\n| where IsBillable == true\r\n| where DataType in (\"SigninLogs\", \r\n\"AuditLogs\", \r\n\"AADNonInteractiveUserSignInLogs\", \r\n\"AADServicePrincipalSignInLogs\",\r\n\"AADManagedIdentitySignInLogs\",\r\n\"AADProvisioningLogs\",\r\n\"ADFSSignInLogs\",\r\n\"McasShadowItReporting\", \r\n\"InformationProtectionLogs_CL\", \r\n\"DeviceEvents\", \r\n\"DeviceFileEvents\", \r\n\"DeviceImageLoadEvents\", \r\n\"DeviceInfo\", \r\n\"DeviceLogonEvents\", \r\n\"DeviceNetworkEvents\", \r\n\"DeviceNetworkInfo\", \r\n\"DeviceProcessEvents\", \r\n\"DeviceRegistryEvents\",\r\n\"DeviceFileCertificateInfo\", \r\n\"EmailAttachmentInfo\", \r\n\"EmailEvents\", \r\n\"EmailPostDeliveryEvents\", \r\n\"EmailUrlInfo\",\r\n\"IdentityLogonEvents\",\r\n\"IdentityQueryEvents\",\r\n\"IdentityDirectoryEvents\",\r\n\"AlertEvidence\",\r\n\"CloudAppEvents\"\r\n) \r\n| summarize TotalBillableDataGB = sum(Quantity) / 1024\r\n\r\n",
+ "size": 4,
+ "title": "Eligible M365 Data",
"timeContextFromParameter": "TimeRange",
- "noDataMessage": "No eligible DfSP2 data was found in the selected time range.",
- "noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
@@ -1037,35 +1114,35 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "EligibleGB",
+ "columnMatch": "TotalBillableDataGB",
"formatter": 12,
"formatOptions": {
- "palette": "blue"
+ "palette": "greenRed"
},
"numberFormat": {
"unit": 39,
"options": {
"style": "decimal",
- "maximumFractionDigits": 3
+ "maximumFractionDigits": 2
}
}
},
"showBorder": false
+ ,
+ "size": "auto"
}
},
"customWidth": "20",
- "name": "DfSP2IngestionSize current"
+ "name": "E5IngestionSize"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "Heartbeat | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | summarize NodesIdentified = dcount(Computer)",
- "size": 1,
- "title": "Nodes",
+ "query": "let licenseCount = todouble('{TotalE5Seats}'); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); print MaxDataGrantGB = iif(isnull(licenseCount), 'N/A', strcat(tostring(round(licenseCount * 5.0 / 1024.0 * periodDays, 3)), ' GB'))",
+ "size": 4,
+ "title": "Total Data Grant Limit: {TimeRange}",
"timeContextFromParameter": "TimeRange",
- "noDataMessage": "No Heartbeat nodes were identified in the selected time range.",
- "noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
@@ -1074,28 +1151,36 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "NodesIdentified",
+ "columnMatch": "MaxDataGrantGB",
"formatter": 12,
"formatOptions": {
- "palette": "blue"
+ "palette": "orangeBlue"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 2
+ }
}
},
- "showBorder": false
+ "showBorder": false,
+ "sortOrderField": 1
+ ,
+ "size": "auto"
}
},
- "customWidth": "10",
- "name": "DfSP2NodesIdentified current"
+ "customWidth": "20",
+ "name": "DataGrantLimit"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let licenseCount = todouble('{TotalDfSP2Licenses}'); print DailyGrantGB = iif(isnull(licenseCount), 'N/A', strcat(tostring(round(licenseCount * 500.0 / 1024.0, 3)), ' GB'))",
- "size": 1,
- "title": "Daily Grant Limit",
+ "query": "let eligibleTables = dynamic([\"SigninLogs\",\"AuditLogs\",\"AADNonInteractiveUserSignInLogs\",\"AADServicePrincipalSignInLogs\",\"AADManagedIdentitySignInLogs\",\"AADProvisioningLogs\",\"ADFSSignInLogs\",\"McasShadowItReporting\",\"InformationProtectionLogs_CL\",\"DeviceEvents\",\"DeviceFileEvents\",\"DeviceImageLoadEvents\",\"DeviceInfo\",\"DeviceLogonEvents\",\"DeviceNetworkEvents\",\"DeviceNetworkInfo\",\"DeviceProcessEvents\",\"DeviceRegistryEvents\",\"DeviceFileCertificateInfo\",\"EmailAttachmentInfo\",\"EmailEvents\",\"EmailPostDeliveryEvents\",\"EmailUrlInfo\",\"IdentityLogonEvents\",\"IdentityQueryEvents\",\"IdentityDirectoryEvents\",\"AlertEvidence\",\"CloudAppEvents\"]); let licenseCount = todouble('{TotalE5Seats}'); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); let eligibleGB = toreal(coalesce(toscalar(Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize sum(Quantity) / 1024.0), 0.0)); let periodGrantGB = licenseCount * 5.0 / 1024.0 * periodDays; print TotalEligibleGB = iif(isnull(licenseCount), 'N/A', strcat(tostring(round(min_of(eligibleGB, periodGrantGB), 3)), ' GB'))",
+ "size": 4,
+ "title": "Total Data Grant Used: {TimeRange}",
"timeContextFromParameter": "TimeRange",
- "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate the daily grant.",
- "noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
@@ -1104,28 +1189,36 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "DailyGrantGB",
+ "columnMatch": "TotalEligibleGB",
"formatter": 12,
"formatOptions": {
- "palette": "orangeBlue"
+ "palette": "coldHot"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 2
+ }
}
},
- "showBorder": false
+ "showBorder": false,
+ "sortOrderField": 1
+ ,
+ "size": "auto"
}
},
- "customWidth": "15",
- "name": "DfSP2DailyGrant"
+ "customWidth": "30",
+ "name": "EligibleE5Ingestion"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let licenseCount = todouble('{TotalDfSP2Licenses}'); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1); print PeriodGrantGB = iif(isnull(licenseCount), 'N/A', strcat(tostring(round(licenseCount * 500.0 / 1024.0 * periodDays, 3)), ' GB'))",
- "size": 1,
- "title": "Total Grant Limit: {TimeRange}",
+ "query": "let eligibleTables = dynamic([\"SigninLogs\",\"AuditLogs\",\"AADNonInteractiveUserSignInLogs\",\"AADServicePrincipalSignInLogs\",\"AADManagedIdentitySignInLogs\",\"AADProvisioningLogs\",\"ADFSSignInLogs\",\"McasShadowItReporting\",\"InformationProtectionLogs_CL\",\"DeviceEvents\",\"DeviceFileEvents\",\"DeviceImageLoadEvents\",\"DeviceInfo\",\"DeviceLogonEvents\",\"DeviceNetworkEvents\",\"DeviceNetworkInfo\",\"DeviceProcessEvents\",\"DeviceRegistryEvents\",\"DeviceFileCertificateInfo\",\"EmailAttachmentInfo\",\"EmailEvents\",\"EmailPostDeliveryEvents\",\"EmailUrlInfo\",\"IdentityLogonEvents\",\"IdentityQueryEvents\",\"IdentityDirectoryEvents\",\"AlertEvidence\",\"CloudAppEvents\"]); let licenseCount = todouble('{TotalE5Seats}'); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); let eligibleGB = toreal(coalesce(toscalar(Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize sum(Quantity) / 1024.0), 0.0)); let periodGrantGB = licenseCount * 5.0 / 1024.0 * periodDays; print TotalDiscount = iif(isnull(licenseCount), 'N/A', strcat('$', tostring(round(min_of(eligibleGB, periodGrantGB) * todouble('{Price}'), 2))))",
+ "size": 4,
+ "title": "Estimated Cost Savings: {TimeRange}",
"timeContextFromParameter": "TimeRange",
- "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate the selected-period grant.",
- "noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
@@ -1134,87 +1227,37 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "PeriodGrantGB",
+ "columnMatch": "TotalDiscount",
"formatter": 12,
"formatOptions": {
- "palette": "orangeBlue"
+ "palette": "greenRed"
+ },
+ "numberFormat": {
+ "unit": 0,
+ "options": {
+ "currency": "USD",
+ "style": "currency",
+ "maximumFractionDigits": 2
+ }
}
},
"showBorder": false
+ ,
+ "size": "auto"
}
},
"customWidth": "20",
- "name": "DfSP2PeriodGrant"
+ "name": "EstimateE5Discount"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); let licenseCount = todouble('{TotalDfSP2Licenses}'); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1); let eligibleGB = toreal(coalesce(toscalar(Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize sum(Quantity) / 1024.0), 0.0)); let periodGrantGB = licenseCount * 500.0 / 1024.0 * periodDays; print GrantUsedGB = iif(isnull(licenseCount), 'N/A', strcat(tostring(round(min_of(eligibleGB, periodGrantGB), 3)), ' GB'))",
- "size": 1,
- "title": "Total Grant Used: {TimeRange}",
+ "query": "let eligibleTables = dynamic([\"SigninLogs\",\"AuditLogs\",\"AADNonInteractiveUserSignInLogs\",\"AADServicePrincipalSignInLogs\",\"AADManagedIdentitySignInLogs\",\"AADProvisioningLogs\",\"ADFSSignInLogs\",\"AADUserRiskEvents\",\"AADRiskyUsers\",\"McasShadowItReporting\",\"InformationProtectionLogs_CL\",\"DeviceEvents\",\"DeviceFileEvents\",\"DeviceImageLoadEvents\",\"DeviceInfo\",\"DeviceLogonEvents\",\"DeviceNetworkEvents\",\"DeviceNetworkInfo\",\"DeviceProcessEvents\",\"DeviceRegistryEvents\",\"DeviceFileCertificateInfo\",\"EmailAttachmentInfo\",\"EmailEvents\",\"EmailPostDeliveryEvents\",\"EmailUrlInfo\",\"IdentityLogonEvents\",\"IdentityQueryEvents\",\"IdentityDirectoryEvents\",\"AlertEvidence\",\"CloudAppEvents\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize TableSizeGB = sum(Quantity) / 1024.0 by DataType | project ['Log Type'] = DataType, ['Table Size'] = TableSizeGB | order by ['Table Size'] desc",
+ "size": 0,
+ "title": "Eligible Microsoft 365 data by source table in the {TimeRange}",
"timeContextFromParameter": "TimeRange",
- "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate grant use.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "GrantUsedGB",
- "formatter": 12,
- "formatOptions": {
- "palette": "coldHot"
- }
- },
- "showBorder": false
- }
- },
- "customWidth": "20",
- "name": "DfSP2GrantUsed"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); let licenseCount = todouble('{TotalDfSP2Licenses}'); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1); let eligibleGB = toreal(coalesce(toscalar(Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize sum(Quantity) / 1024.0), 0.0)); let periodGrantGB = licenseCount * 500.0 / 1024.0 * periodDays; print EstimatedSavings = iif(isnull(licenseCount), 'N/A', strcat('$', tostring(round(min_of(eligibleGB, periodGrantGB) * todouble('{Price}'), 2))))",
- "size": 1,
- "title": "Estimated Savings: {TimeRange}",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate estimated savings.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "EstimatedSavings",
- "formatter": 12,
- "formatOptions": {
- "palette": "greenRed"
- }
- },
- "showBorder": false
- }
- },
- "customWidth": "15",
- "name": "DfSP2EstimatedSavings"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize TableSizeGB = sum(Quantity) / 1024.0 by DataType | project ['Log Type'] = DataType, ['Table Size'] = TableSizeGB | order by ['Table Size'] desc",
- "size": 1,
- "title": "Eligible Defender for Servers Plan 2 data by source table in the {TimeRange}",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "No eligible DfSP2 data was found in the selected time range.",
+ "noDataMessage": "No eligible Microsoft 365 data was found in the selected time range.",
"noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
@@ -1229,7 +1272,7 @@
"columnMatch": "Log Type",
"formatter": 0,
"formatOptions": {
- "customColumnWidthSetting": "2fr"
+ "customColumnWidthSetting": "65%"
}
},
{
@@ -1237,7 +1280,7 @@
"formatter": 3,
"formatOptions": {
"palette": "greenRed",
- "customColumnWidthSetting": "1fr"
+ "customColumnWidthSetting": "35%"
},
"numberFormat": {
"unit": 39,
@@ -1250,17 +1293,17 @@
]
}
},
- "name": "DfSP2CapacityDetailCurrent"
+ "name": "E5EligibleDataDetail"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); let licenseCount = todouble('{TotalDfSP2Licenses}'); let selectedDuration = {TimeRange:end} - {TimeRange:start}; let timeGrain = case(selectedDuration <= 1h, 5m, selectedDuration <= 4h, 15m, selectedDuration <= 1d, 1h, selectedDuration <= 7d, 6h, selectedDuration <= 31d, 1d, selectedDuration <= 90d, 7d, 30d); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize ['Ingestion Size'] = sum(Quantity) / 1024.0 by bin(TimeGenerated, timeGrain) | extend ['Grant Limit for Interval'] = iif(isnull(licenseCount), real(null), licenseCount * 500.0 / 1024.0 * (timeGrain / 1d)) | order by TimeGenerated asc",
+ "query": "let eligibleTables = dynamic([\"SigninLogs\",\"AuditLogs\",\"AADNonInteractiveUserSignInLogs\",\"AADServicePrincipalSignInLogs\",\"AADManagedIdentitySignInLogs\",\"AADProvisioningLogs\",\"ADFSSignInLogs\",\"AADUserRiskEvents\",\"AADRiskyUsers\",\"McasShadowItReporting\",\"InformationProtectionLogs_CL\",\"DeviceEvents\",\"DeviceFileEvents\",\"DeviceImageLoadEvents\",\"DeviceInfo\",\"DeviceLogonEvents\",\"DeviceNetworkEvents\",\"DeviceNetworkInfo\",\"DeviceProcessEvents\",\"DeviceRegistryEvents\",\"DeviceFileCertificateInfo\",\"EmailAttachmentInfo\",\"EmailEvents\",\"EmailPostDeliveryEvents\",\"EmailUrlInfo\",\"IdentityLogonEvents\",\"IdentityQueryEvents\",\"IdentityDirectoryEvents\",\"AlertEvidence\",\"CloudAppEvents\"]); let licenseCount = todouble('{TotalE5Seats}'); let selectedDuration = {TimeRange:end} - {TimeRange:start}; let timeGrain = case(selectedDuration <= 1h, 5m, selectedDuration <= 4h, 15m, selectedDuration <= 1d, 1h, selectedDuration <= 7d, 6h, selectedDuration <= 31d, 1d, selectedDuration <= 90d, 7d, 30d); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize ['Ingestion Size'] = sum(Quantity) / 1024.0 by bin(TimeGenerated, timeGrain) | extend ['Grant Limit for Interval'] = iif(isnull(licenseCount), real(null), licenseCount * 5.0 / 1024.0 * (timeGrain / 1d)) | order by TimeGenerated asc",
"size": 1,
"title": "Ingestion Size vs Prorated Data Grant in the {TimeRange}",
"timeContextFromParameter": "TimeRange",
- "noDataMessage": "No eligible DfSP2 data was found in the selected time range.",
+ "noDataMessage": "No eligible Microsoft 365 data was found in the selected time range.",
"noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
@@ -1282,87 +1325,26 @@
}
}
},
- "name": "DfSP2DailyIngestionVsGrant"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let licenseCount = todouble('{TotalDfSP2Licenses}'); let unitPrice = todouble('{DfSP2LicensePrice}'); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); print LicensingCost = iif(isnull(licenseCount), 'N/A', strcat('$', tostring(round(licenseCount * unitPrice * periodDays / 30.0, 2))))",
- "size": 1,
- "title": "Defender for Servers Plan 2 licensing cost: {TimeRange}",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate licensing cost.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "LicensingCost",
- "formatter": 12,
- "formatOptions": {
- "palette": "orangeBlue"
- }
- },
- "showBorder": false
- }
- },
- "customWidth": "50",
- "name": "DfSP2LicensingCost"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); let licenseCount = todouble('{TotalDfSP2Licenses}'); let unitPrice = todouble('{DfSP2LicensePrice}'); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); let eligibleGB = toreal(coalesce(toscalar(Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize sum(Quantity) / 1024.0), 0.0)); let periodGrantGB = licenseCount * 500.0 / 1024.0 * periodDays; let licensingCost = licenseCount * unitPrice * periodDays / 30.0; print NetSavings = iif(isnull(licenseCount), 'N/A', strcat('$', tostring(round(min_of(eligibleGB, periodGrantGB) * todouble('{Price}') - licensingCost, 2))))",
- "size": 1,
- "title": "Estimated savings after licensing cost: {TimeRange}",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate net savings.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "NetSavings",
- "formatter": 12,
- "formatOptions": {
- "palette": "greenRed"
- }
- },
- "showBorder": false
- }
- },
- "customWidth": "50",
- "name": "DfSP2NetSavingsAfterLicensing"
+ "name": "E5DailyIngestionVsGrant"
}
]
},
- "name": "group - Defender for Cloud Plan 2 Ingestion Benefit"
- },
- {
+ "name": "group - E5 Benefits"
+ },{
"type": 12,
"content": {
"version": "NotebookGroup/1.0",
"groupType": "editable",
- "title": "Retention",
+ "title": "Microsoft Sentinel benefit for Defender for Servers Plan 2",
"expandable": true,
"expanded": true,
"items": [
{
"type": 1,
"content": {
- "json": "## Retention summary\r\n\r\nThis section estimates Analytics-tier charges for billable data retained longer than 90 days, using historical billable workspace records. XDR and data lake retention use separate billing models. Review [Manage data tiers and retention in Microsoft Sentinel](https://learn.microsoft.com/azure/sentinel/manage-data-overview) for retention and data-tier guidance."
+ "json": "Defender for Servers Plan 2 provides up to 500 MB of eligible Analytics-tier ingestion per protected server or node per day. The allowance is pooled across machines in each subscription and applied at workspace level. This workbook estimates observed usage; it does not prove Plan 2 protection, licensing, eligibility, or data lake-only charges.\r\n\r\nCore eligible tables:\r\n\r\n- `SecurityAlert`, `SecurityBaseline`, `SecurityBaselineSummary`, `SecurityDetection`, `SecurityEvent`\r\n- `WindowsFirewall`, `ProtectionStatus`, `MDCFileIntegrityMonitoringEvents`\r\n- `DeviceCustomFileEvents`, `DeviceCustomRegistryEvents`\r\n\r\nConditionally eligible tables:\r\n\r\n- `Update`, `UpdateSummary`: review the applicable Update Management conditions\r\n- `WindowsEvent`: only security data from the Microsoft-SecurityEvent stream\r\n\r\nNodes is the distinct `Computer` count observed in `Heartbeat`, not proof of licensing or Plan 2 protection. Review the [Defender for Servers Plan 2 data ingestion benefit](https://learn.microsoft.com/azure/defender-for-cloud/data-ingestion-benefit) for current eligibility and terms."
},
- "name": "text - retention summary"
+ "name": "text - DfSP2 benefit"
},
{
"type": 9,
@@ -1370,12 +1352,32 @@
"version": "KqlParameterItem/1.0",
"parameters": [
{
- "id": "9d5299d0-36a0-4666-9803-ca6931bdaab7",
+ "id": "f1a5dc2c-7e7f-4e48-9d65-0d52e77b6e3a",
"version": "KqlParameterItem/1.0",
- "name": "RetentionPrice",
- "label": "Retention price",
+ "name": "TotalDfSP2Licenses",
+ "label": "Protected Defender for Servers Plan 2 servers or nodes",
"type": 1,
- "description": "Enter the retention price per GB/month used for this section's estimates.",
+ "quote": "'",
+ "description": "Enter the number of protected Defender for Servers Plan 2 servers or nodes used to estimate the 500 MB per server or node per day ingestion benefit. Leave as when the entitlement is unknown; grant and savings metrics will show N/A.",
+ "value": "",
+ "typeSettings": {
+ "paramValidationRules": [
+ {
+ "regExp": "^([1-9][0-9]*||)$",
+ "match": true,
+ "message": "Enter a whole number greater than zero, or clear the value."
+ }
+ ]
+ }
+ },
+ {
+ "id": "c4f7a2d1-5b83-4e96-9a07-1f6c8b3d2e54",
+ "version": "KqlParameterItem/1.0",
+ "name": "DfSP2LicensePrice",
+ "label": "Defender for Servers Plan 2 price (per server/month)",
+ "type": 1,
+ "isRequired": true,
+ "description": "Monthly list price per protected server or node. Verify against your agreement and region.",
"typeSettings": {
"paramValidationRules": [
{
@@ -1385,25 +1387,37 @@
}
]
},
- "value": "0.1"
+ "value": "15"
}
],
"style": "pills",
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces"
},
- "name": "parameters - retention pricing"
+ "name": "parameters - Defender for Servers Plan 2 benefit"
+ },
+ {
+ "type": 1,
+ "content": {
+ "json": "Enter the number of protected Defender for Servers Plan 2 servers or nodes above to calculate the daily and total data grants, grant usage, and estimated cost savings."
+ },
+ "name": "text - DfSP2 entitlement required",
+ "conditionalVisibility": {
+ "parameterName": "TotalDfSP2Licenses",
+ "comparison": "isEqualTo",
+ "value": ""
+ }
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let retainedDataGB = toreal(coalesce(toscalar((union withsource = SourceTableName * | where TimeGenerated < startofday(now()) - 90d | where _IsBillable == true | summarize sum(_BilledSize) / 1024.0 / 1024.0 / 1024.0)), 0.0)); print ['Average Daily Retention Cost'] = retainedDataGB * todouble('{RetentionPrice}') / 30.0",
- "size": 1,
- "title": "Average Daily Retention Cost",
- "noDataMessage": "No retained billable data was found in the selected workspace scope.",
- "noDataMessageStyle": 3,
+ "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize EligibleGB = sum(Quantity) / 1024.0",
+ "size": 4,
+ "title": "Eligible Defender for Servers Plan 2 data",
"timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No eligible DfSP2 data was found in the selected time range.",
+ "noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
@@ -1412,33 +1426,69 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "Average Daily Retention Cost",
+ "columnMatch": "EligibleGB",
"formatter": 12,
+ "formatOptions": {
+ "palette": "blue"
+ },
"numberFormat": {
- "unit": 0,
+ "unit": 39,
"options": {
- "currency": "USD",
- "style": "currency",
- "maximumFractionDigits": 2
+ "style": "decimal",
+ "maximumFractionDigits": 3
}
}
},
"showBorder": false
+ ,
+ "size": "auto"
}
},
- "customWidth": "25",
- "name": "AverageDailyRetentionCost"
+ "customWidth": "20",
+ "name": "DfSP2IngestionSize current"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let selectedDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); let retainedDataGB = toreal(coalesce(toscalar((union withsource = SourceTableName * | where TimeGenerated < startofday(now()) - 90d | where _IsBillable == true | summarize sum(_BilledSize) / 1024.0 / 1024.0 / 1024.0)), 0.0)); print ['Retention Cost'] = retainedDataGB * todouble('{RetentionPrice}') * selectedDays / 30.0",
- "size": 1,
- "title": "Retention Cost: {TimeRange}",
- "noDataMessage": "No retained billable data was found in the selected workspace scope.",
+ "query": "Heartbeat | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | summarize NodesIdentified = dcount(Computer)",
+ "size": 4,
+ "title": "Nodes",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No Heartbeat nodes were identified in the selected time range.",
"noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "NodesIdentified",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "blue"
+ }
+ },
+ "showBorder": false
+ ,
+ "size": "auto"
+ }
+ },
+ "customWidth": "10",
+ "name": "DfSP2NodesIdentified current"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let licenseCount = todouble('{TotalDfSP2Licenses}'); print DailyGrantGB = iif(isnull(licenseCount), 'N/A', strcat(tostring(round(licenseCount * 500.0 / 1024.0, 3)), ' GB'))",
+ "size": 4,
+ "title": "Daily Grant Limit",
"timeContextFromParameter": "TimeRange",
+ "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate the daily grant.",
+ "noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
@@ -1447,505 +1497,61 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "Retention Cost",
+ "columnMatch": "DailyGrantGB",
"formatter": 12,
- "numberFormat": {
- "unit": 0,
- "options": {
- "currency": "USD",
- "style": "currency",
- "maximumFractionDigits": 2
- }
+ "formatOptions": {
+ "palette": "orangeBlue"
}
},
"showBorder": false
+ ,
+ "size": "auto"
}
},
- "customWidth": "25",
- "name": "RetentionCostForTimeRange"
+ "customWidth": "15",
+ "name": "DfSP2DailyGrant"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let selectedDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); union withsource = SourceTableName * | where TimeGenerated < startofday(now()) - 90d | where _IsBillable == true | summarize RetainedDataGB = sum(_BilledSize) / 1024.0 / 1024.0 / 1024.0 by SourceTableName | project ['Log Type'] = SourceTableName, ['Retained Data'] = RetainedDataGB, ['Average Daily Retention Cost'] = RetainedDataGB * todouble('{RetentionPrice}') / 30.0, ['Retention Cost'] = RetainedDataGB * todouble('{RetentionPrice}') * selectedDays / 30.0 | order by ['Retained Data'] desc",
- "size": 1,
- "title": "Retained data by source table in the last {TimeRange}",
+ "query": "let licenseCount = todouble('{TotalDfSP2Licenses}'); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1); print PeriodGrantGB = iif(isnull(licenseCount), 'N/A', strcat(tostring(round(licenseCount * 500.0 / 1024.0 * periodDays, 3)), ' GB'))",
+ "size": 4,
+ "title": "Total Grant Limit: {TimeRange}",
"timeContextFromParameter": "TimeRange",
- "noDataMessage": "No billable data older than 90 days was found in the selected workspace scope.",
+ "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate the selected-period grant.",
"noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
"{Workspace}"
],
- "visualization": "table",
- "gridSettings": {
- "showExportToExcel": true,
- "formatters": [
- {
- "columnMatch": "Log Type",
- "formatter": 0,
- "formatOptions": {
- "customColumnWidthSetting": "2fr"
- }
- },
- {
- "columnMatch": "Retained Data",
- "formatter": 3,
- "formatOptions": {
- "palette": "greenRed",
- "customColumnWidthSetting": "1fr"
- },
- "numberFormat": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "maximumFractionDigits": 3
- }
- }
- },
- {
- "columnMatch": "Average Daily Retention Cost",
- "formatter": 0,
- "formatOptions": {
- "customColumnWidthSetting": "1fr"
- },
- "numberFormat": {
- "unit": 0,
- "options": {
- "currency": "USD",
- "style": "currency",
- "maximumFractionDigits": 2
- }
- }
- },
- {
- "columnMatch": "Retention Cost",
- "formatter": 0,
- "formatOptions": {
- "customColumnWidthSetting": "1fr"
- },
- "numberFormat": {
- "unit": 0,
- "options": {
- "currency": "USD",
- "style": "currency",
- "maximumFractionDigits": 2
- }
- }
- }
- ],
- "labelSettings": [
- {
- "columnId": "Average Daily Retention Cost",
- "label": "Avg daily cost"
- },
- {
- "columnId": "Retention Cost",
- "label": "Period cost"
- }
- ]
- }
- },
- "name": "RetentionDataDetail"
- }
- ]
- },
- "name": "group - Retention"
- },
- {
- "type": 12,
- "content": {
- "version": "NotebookGroup/1.0",
- "groupType": "editable",
- "title": "Commitment Tiers",
- "expandable": true,
- "expanded": true,
- "items": [
- {
- "type": 1,
- "content": {
- "json": "## Commitment tiers\r\n\r\nMicrosoft Sentinel and Log Analytics offer Pay-As-You-Go and Commitment Tier pricing. This section automatically detects the current workspace tier and calculates a **usage-based suggested tier** from average billable daily ingestion over the last 31 days.\r\n\r\n> **New workspace notice:** A recommendation is shown only after 31 days of billable data are detected. Until then, the table reports how many days remain before the recommendation becomes available; a shorter history cannot accurately represent the fixed 31-day review period.\r\n\r\n> **Estimate only:** The suggested tier uses ingestion volume, not actual pricing. It is not the Azure portal **Recommended Tier** and should not be used as the sole basis for a pricing change. Azure evaluates each available tier using the prior 31 days and your applicable pricing to identify the lowest estimated-cost option. Review [Usage and estimated costs in the Azure portal](https://learn.microsoft.com/azure/azure-monitor/logs/change-pricing-tier#changing-pricing-tier) before changing a tier.\r\n\r\nReview **Days since tier last changed** before making a change: a commitment tier has a 31-day period during which it cannot move to a lower commitment or consumption tier. Confirm rates on the [Microsoft Sentinel pricing page](https://www.microsoft.com/security/pricing/microsoft-sentinel/) and review [Plan costs and understand pricing and billing for Microsoft Sentinel](https://learn.microsoft.com/azure/sentinel/billing?tabs=simplified%2Ccommitment-tiers#analytics-tier)."
- },
- "name": "text - commitment tiers"
- },
- {
- "type": 9,
- "content": {
- "version": "KqlParameterItem/1.0",
- "parameters": [
- {
- "id": "7df48bd0-c79e-4c17-9a6d-b00b9511d9e1",
- "version": "KqlParameterItem/1.0",
- "name": "CurrentCommitmentTier",
- "type": 1,
- "isRequired": true,
- "query": "resources\r\n| where type =~ 'microsoft.operationalinsights/workspaces'\r\n| where id in~ ({Workspace}) or 'value::all' in~ ({Workspace})\r\n| extend skuName = tolower(tostring(properties.sku.name)), capacityReservationLevel = toint(properties.sku.capacityReservationLevel)\r\n| extend currentTier = case(skuName == 'capacityreservation', strcat(tostring(capacityReservationLevel), ' GB/day commitment'), skuName == 'pergb2018', 'Pay-As-You-Go', skuName == 'free', 'Free tier', skuName == 'standalone', 'Standalone tier', skuName == 'standard', 'Standard tier', skuName == 'premium', 'Premium tier', 'Unknown')\r\n| summarize WorkspaceCount = dcount(id), CurrentTier = any(currentTier)\r\n| project CurrentCommitmentTier = iif(WorkspaceCount == 1, CurrentTier, 'Multiple workspaces')",
- "isHiddenWhenLocked": true,
- "queryType": 1,
- "resourceType": "microsoft.resourcegraph/resources"
- }
- ],
- "style": "pills",
- "queryType": 1,
- "resourceType": "microsoft.resourcegraph/resources"
- },
- "name": "parameters - commitment tier current"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let reviewDays = 31.0; let reviewStart = ago(31d); let historyProbeStart = ago(32d); let currentTier = '{CurrentCommitmentTier}'; let tierLevels = dynamic([50,100,200,300,400,500,1000,2000,5000]); union withsource = SourceTableName * | where TimeGenerated between (historyProbeStart .. now()) | where _IsBillable == true | summarize TotalBilledBytes = sumif(_BilledSize, TimeGenerated >= reviewStart), FirstObserved = min(TimeGenerated) | extend ObservedHistoryDays = iif(isnull(FirstObserved), 0.0, min_of(reviewDays, datetime_diff('second', now(), FirstObserved) / 86400.0)) | extend DaysRemaining = toint(ceiling(max_of(reviewDays - ObservedHistoryDays, 0.0))) | extend AvgDailyGB = iif(DaysRemaining == 0, TotalBilledBytes / 1024.0 / 1024.0 / 1024.0 / reviewDays, real(null)), TierLevels = tierLevels | mv-expand TierLevel = TierLevels to typeof(int) | extend IsEligible = TierLevel >= AvgDailyGB | summarize SuggestedTierGBPerDay = minif(TierLevel, IsEligible), AvgDailyGB = any(AvgDailyGB), ObservedHistoryDays = any(ObservedHistoryDays), DaysRemaining = any(DaysRemaining) | extend suggestedTier = case(DaysRemaining > 0, strcat('Available in ', tostring(DaysRemaining), iif(DaysRemaining == 1, ' day', ' days')), AvgDailyGB < 50.0, 'Pay-As-You-Go', isnotempty(SuggestedTierGBPerDay), strcat(tostring(SuggestedTierGBPerDay), ' GB/day commitment'), 'Above 5000 GB/day - review Azure portal options') | extend alignmentStatus = case(DaysRemaining > 0, 'Collecting data', currentTier == 'Not available' or currentTier == 'Unknown' or currentTier == 'Multiple workspaces', 'Not evaluated', suggestedTier startswith 'Above 5000 GB/day', 'Review in portal', currentTier == suggestedTier, 'Aligned', 'Review tier') | project ['Current tier'] = currentTier, ['Recommended next tier'] = suggestedTier, ['Alignment status'] = alignmentStatus, ['Observed history (days)'] = round(ObservedHistoryDays, 1), ['Days until recommendation'] = DaysRemaining, ['Average billable daily ingestion (GB)'] = round(AvgDailyGB, 2)",
- "size": 0,
- "title": "Usage-based suggested tier (estimate, last 31 days)",
- "noDataMessage": "No billable ingestion was found in the last 31 days.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "table",
- "gridSettings": {
- "formatters": [
- {
- "columnMatch": "Current tier",
- "formatter": 0,
- "formatOptions": {
- "customColumnWidthSetting": "1fr"
- }
- },
- {
- "columnMatch": "Recommended next tier",
- "formatter": 0,
- "formatOptions": {
- "customColumnWidthSetting": "1fr"
- }
- },
- {
- "columnMatch": "Alignment status",
- "formatter": 18,
- "formatOptions": {
- "thresholdsOptions": "icons",
- "customColumnWidthSetting": "1fr",
- "thresholdsGrid": [
- {
- "operator": "==",
- "thresholdValue": "Aligned",
- "representation": "success",
- "text": "{0}{1}"
- },
- {
- "operator": "==",
- "thresholdValue": "Review tier",
- "representation": "failed",
- "text": "{0}{1}"
- },
- {
- "operator": "Default",
- "thresholdValue": null,
- "representation": "2",
- "text": "{0}{1}"
- }
- ]
- }
- },
- {
- "columnMatch": "Average billable daily ingestion (GB)",
- "formatter": 0,
- "formatOptions": {
- "customColumnWidthSetting": "1fr"
- },
- "numberFormat": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "maximumFractionDigits": 2
- }
- }
- },
- {
- "columnMatch": "Observed history (days)",
- "formatter": 0,
- "formatOptions": {
- "customColumnWidthSetting": "1fr"
- },
- "numberFormat": {
- "unit": 0,
- "options": {
- "style": "decimal",
- "maximumFractionDigits": 1
- }
- }
- },
- {
- "columnMatch": "Days until recommendation",
- "formatter": 18,
- "formatOptions": {
- "thresholdsOptions": "icons",
- "customColumnWidthSetting": "1fr",
- "thresholdsGrid": [
- {
- "operator": "==",
- "thresholdValue": "0",
- "representation": "success",
- "text": "Ready"
- },
- {
- "operator": "Default",
- "thresholdValue": null,
- "representation": "warning",
- "text": "{0} days"
- }
- ]
- }
- }
- ],
- "labelSettings": [
- {
- "columnId": "Recommended next tier",
- "label": "Suggested tier"
- },
- {
- "columnId": "Average billable daily ingestion (GB)",
- "label": "Avg daily ingestion (GB)"
- }
- ]
- }
- },
- "name": "CommitmentTierUsageContext",
- "customWidth": "100"
- }
- ]
- },
- "name": "group - Commitment Tiers"
- },
- {
- "type": 12,
- "content": {
- "version": "NotebookGroup/1.0",
- "groupType": "editable",
- "title": "Data Lake",
- "expandable": true,
- "expanded": true,
- "items": [
- {
- "type": 1,
- "content": {
- "json": "## Microsoft Sentinel Data Lake\r\n\r\nThe data lake stores security data outside the Analytics tier and is billed on five separate meters. Enter your rates below from the [Microsoft Sentinel pricing page](https://www.microsoft.com/security/pricing/microsoft-sentinel/); the defaults are placeholders and must be verified against your agreement and region.\r\n\r\n**What this section can and cannot observe.** Only the storage meter can be derived per table from workspace data:\r\n\r\n| Meter | Source | Per-table detail |\r\n| --- | --- | --- |\r\n| Data lake storage | Estimated from mirrored `Usage` volume | Yes |\r\n| Data lake ingestion | Manual entry | No |\r\n| Data processing | Manual entry | No |\r\n| Data lake query | Manual entry | No |\r\n| Advanced data insights | Manual entry | No |\r\n\r\nWhen the data lake is enabled, Analytics-tier data is **mirrored** to the lake at no extra ingestion charge, so mirrored volume is visible in `Usage` and is used for the storage estimate. Ingestion and data processing are charged only for tables set to **data lake tier only**; that data never reaches the Analytics workspace, so its volume must be entered manually. Query charges depend on GB scanned and insights charges on notebook compute hours, neither of which is recorded in `Usage`.\r\n\r\nStorage is billed on compressed data at a documented **6:1** ratio and applies only to data still retained after the Analytics retention period ends. These are planning estimates, not invoice values. Validate in **Microsoft Sentinel > Cost management** in the Microsoft Defender portal, and review the [data lake overview](https://learn.microsoft.com/azure/sentinel/datalake/sentinel-lake-overview), [billing model](https://learn.microsoft.com/azure/sentinel/billing#understand-the-full-billing-model-for-microsoft-sentinel), and [cost monitoring guidance](https://learn.microsoft.com/azure/sentinel/billing-monitor-costs)."
- },
- "name": "text - Microsoft Sentinel Data Lake"
- },
- {
- "type": 9,
- "content": {
- "version": "KqlParameterItem/1.0",
- "parameters": [
- {
- "id": "3a7c1f0e-6b21-4d4c-9f83-1c5c4a9d2b71",
- "version": "KqlParameterItem/1.0",
- "name": "LakeStoragePrice",
- "label": "Lake storage price (per compressed GB/month)",
- "type": 1,
- "isRequired": true,
- "description": "Data lake storage rate per compressed GB per month. Storage is billed at a 6:1 compression ratio on data retained after Analytics retention ends.",
- "typeSettings": {
- "paramValidationRules": [
- {
- "regExp": "^(0|[1-9][0-9]*)(\\.[0-9]+)?$",
- "match": true,
- "message": "Enter a non-negative price."
- }
- ]
- },
- "value": "0.026"
- },
- {
- "id": "5d92b83a-4f17-4a6e-bd15-9e2f7c3a8d64",
- "version": "KqlParameterItem/1.0",
- "name": "LakeAnalyticsRetentionDays",
- "label": "Analytics retention (days)",
- "type": 1,
- "isRequired": true,
- "description": "Analytics-tier retention in days. Lake storage is charged only for data retained beyond this period.",
- "typeSettings": {
- "paramValidationRules": [
- {
- "regExp": "^[1-9][0-9]*$",
- "match": true,
- "message": "Enter a whole number of days greater than zero."
- }
- ]
- },
- "value": "90"
- },
- {
- "id": "7e4a6c25-8d39-4b72-a1f6-3b8d5e0c9a17",
- "version": "KqlParameterItem/1.0",
- "name": "LakeTotalRetentionMonths",
- "label": "Total lake retention (months)",
- "type": 1,
- "isRequired": true,
- "description": "Total retention in the data lake tier, up to 12 years (144 months).",
- "typeSettings": {
- "paramValidationRules": [
- {
- "regExp": "^[1-9][0-9]*$",
- "match": true,
- "message": "Enter a whole number of months greater than zero."
- }
- ]
- },
- "value": "12"
- },
- {
- "id": "9f1b7d43-2c58-4e19-8a6d-4d7c1f2b6e35",
- "version": "KqlParameterItem/1.0",
- "name": "LakeOnlyIngestionGB",
- "label": "Lake-only ingestion (GB/month)",
- "type": 1,
- "description": "Monthly GB ingested into tables set to data lake tier only. This data is not present in the Analytics workspace, so it cannot be measured here. Leave as to report N/A.",
- "typeSettings": {
- "paramValidationRules": [
- {
- "regExp": "^((0|[1-9][0-9]*)(\\.[0-9]+)?||)$",
- "match": true,
- "message": "Enter a non-negative number, or clear the value."
- }
- ]
- },
- "value": ""
- },
- {
- "id": "2b6e9a17-7f34-4c81-95d2-8a1e3f7b4c60",
- "version": "KqlParameterItem/1.0",
- "name": "LakeIngestionPrice",
- "label": "Lake ingestion price (per GB)",
- "type": 1,
- "isRequired": true,
- "description": "Ingestion rate per GB for tables set to data lake tier only. Mirrored data is not charged this meter.",
- "typeSettings": {
- "paramValidationRules": [
- {
- "regExp": "^(0|[1-9][0-9]*)(\\.[0-9]+)?$",
- "match": true,
- "message": "Enter a non-negative price."
- }
- ]
- },
- "value": "0.05"
- },
- {
- "id": "4c8f2e61-9b47-4d3a-8e15-6f2a9c4d7b83",
- "version": "KqlParameterItem/1.0",
- "name": "LakeProcessingPrice",
- "label": "Data processing price (per GB)",
- "type": 1,
- "isRequired": true,
- "description": "Data processing rate per GB for tables set to data lake tier only, covering transformations such as redaction, splitting, filtering, and normalization.",
- "typeSettings": {
- "paramValidationRules": [
- {
- "regExp": "^(0|[1-9][0-9]*)(\\.[0-9]+)?$",
- "match": true,
- "message": "Enter a non-negative price."
- }
- ]
- },
- "value": "0.10"
- },
- {
- "id": "6a3d5b98-1e72-4f60-b94c-2d8f7a1c5e49",
- "version": "KqlParameterItem/1.0",
- "name": "LakeQueryScannedGB",
- "label": "Lake query data scanned (GB/month)",
- "type": 1,
- "description": "Monthly GB of uncompressed data scanned by KQL queries and jobs against the lake. Not recorded in the workspace. Leave as to report N/A.",
- "typeSettings": {
- "paramValidationRules": [
- {
- "regExp": "^((0|[1-9][0-9]*)(\\.[0-9]+)?||)$",
- "match": true,
- "message": "Enter a non-negative number, or clear the value."
- }
- ]
- },
- "value": ""
- },
- {
- "id": "8d17c4a6-3f95-42be-9c1d-7e5b2a8f0d63",
- "version": "KqlParameterItem/1.0",
- "name": "LakeQueryPrice",
- "label": "Lake query price (per GB scanned)",
- "type": 1,
- "isRequired": true,
- "description": "Query rate per GB of uncompressed data scanned in the data lake tier.",
- "typeSettings": {
- "paramValidationRules": [
- {
- "regExp": "^(0|[1-9][0-9]*)(\\.[0-9]+)?$",
- "match": true,
- "message": "Enter a non-negative price."
- }
- ]
- },
- "value": "0.005"
- },
- {
- "id": "1e5f8b30-6d24-4a97-85c3-9b6d4e2a7f18",
- "version": "KqlParameterItem/1.0",
- "name": "LakeInsightsHours",
- "label": "Advanced data insights (compute hours/month)",
- "type": 1,
- "description": "Monthly notebook and job compute hours for advanced data insights. Not recorded in the workspace. Leave as to report N/A.",
- "typeSettings": {
- "paramValidationRules": [
- {
- "regExp": "^((0|[1-9][0-9]*)(\\.[0-9]+)?||)$",
- "match": true,
- "message": "Enter a non-negative number, or clear the value."
- }
- ]
- },
- "value": ""
- },
- {
- "id": "7b2a9d54-8c61-4e35-a7f9-3d1c6b8e5a02",
- "version": "KqlParameterItem/1.0",
- "name": "LakeInsightsPrice",
- "label": "Advanced data insights price (per compute hour)",
- "type": 1,
- "isRequired": true,
- "description": "Rate per compute hour for advanced data insights sessions and jobs.",
- "typeSettings": {
- "paramValidationRules": [
- {
- "regExp": "^(0|[1-9][0-9]*)(\\.[0-9]+)?$",
- "match": true,
- "message": "Enter a non-negative price."
- }
- ]
- },
- "value": "1.00"
- }
- ],
- "style": "pills",
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces"
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "PeriodGrantGB",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "orangeBlue"
+ }
+ },
+ "showBorder": false
+ ,
+ "size": "auto"
+ }
},
- "name": "parameters - data lake pricing"
+ "customWidth": "20",
+ "name": "DfSP2PeriodGrant"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let selectedDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | summarize ['Average Daily Mirrored Volume'] = sum(Quantity) / 1024.0 / selectedDays",
- "size": 1,
- "title": "Average Daily Mirrored Volume",
+ "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); let licenseCount = todouble('{TotalDfSP2Licenses}'); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1); let eligibleGB = toreal(coalesce(toscalar(Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize sum(Quantity) / 1024.0), 0.0)); let periodGrantGB = licenseCount * 500.0 / 1024.0 * periodDays; print GrantUsedGB = iif(isnull(licenseCount), 'N/A', strcat(tostring(round(min_of(eligibleGB, periodGrantGB), 3)), ' GB'))",
+ "size": 4,
+ "title": "Total Grant Used: {TimeRange}",
"timeContextFromParameter": "TimeRange",
- "noDataMessage": "No billable table usage data was found in the selected time range.",
+ "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate grant use.",
"noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
@@ -1955,34 +1561,29 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "Average Daily Mirrored Volume",
+ "columnMatch": "GrantUsedGB",
"formatter": 12,
"formatOptions": {
- "palette": "blue"
- },
- "numberFormat": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "maximumFractionDigits": 2
- }
+ "palette": "coldHot"
}
},
"showBorder": false
+ ,
+ "size": "auto"
}
},
- "customWidth": "25",
- "name": "DataLakeAverageMirroredVolume"
+ "customWidth": "20",
+ "name": "DfSP2GrantUsed"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | summarize ['Mirrored Volume'] = sum(Quantity) / 1024.0",
- "size": 1,
- "title": "Mirrored Volume: {TimeRange}",
+ "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); let licenseCount = todouble('{TotalDfSP2Licenses}'); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1); let eligibleGB = toreal(coalesce(toscalar(Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize sum(Quantity) / 1024.0), 0.0)); let periodGrantGB = licenseCount * 500.0 / 1024.0 * periodDays; print EstimatedSavings = iif(isnull(licenseCount), 'N/A', strcat('$', tostring(round(min_of(eligibleGB, periodGrantGB) * todouble('{Price}'), 2))))",
+ "size": 4,
+ "title": "Estimated Savings: {TimeRange}",
"timeContextFromParameter": "TimeRange",
- "noDataMessage": "No billable table usage data was found in the selected time range.",
+ "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate estimated savings.",
"noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
@@ -1992,34 +1593,139 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "Mirrored Volume",
+ "columnMatch": "EstimatedSavings",
"formatter": 12,
"formatOptions": {
- "palette": "blue"
+ "palette": "greenRed"
+ }
+ },
+ "showBorder": false
+ ,
+ "size": "auto"
+ }
+ },
+ "customWidth": "15",
+ "name": "DfSP2EstimatedSavings"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize TableSizeGB = sum(Quantity) / 1024.0 by DataType | project ['Log Type'] = DataType, ['Table Size'] = TableSizeGB | order by ['Table Size'] desc",
+ "size": 0,
+ "title": "Eligible Defender for Servers Plan 2 data by source table in the {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No eligible DfSP2 data was found in the selected time range.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "table",
+ "gridSettings": {
+ "showExportToExcel": true,
+ "formatters": [
+ {
+ "columnMatch": "Log Type",
+ "formatter": 0,
+ "formatOptions": {
+ "customColumnWidthSetting": "65%"
+ }
},
- "numberFormat": {
+ {
+ "columnMatch": "Table Size",
+ "formatter": 3,
+ "formatOptions": {
+ "palette": "greenRed",
+ "customColumnWidthSetting": "35%"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 3
+ }
+ }
+ }
+ ]
+ }
+ },
+ "name": "DfSP2CapacityDetailCurrent"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); let licenseCount = todouble('{TotalDfSP2Licenses}'); let selectedDuration = {TimeRange:end} - {TimeRange:start}; let timeGrain = case(selectedDuration <= 1h, 5m, selectedDuration <= 4h, 15m, selectedDuration <= 1d, 1h, selectedDuration <= 7d, 6h, selectedDuration <= 31d, 1d, selectedDuration <= 90d, 7d, 30d); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize ['Ingestion Size'] = sum(Quantity) / 1024.0 by bin(TimeGenerated, timeGrain) | extend ['Grant Limit for Interval'] = iif(isnull(licenseCount), real(null), licenseCount * 500.0 / 1024.0 * (timeGrain / 1d)) | order by TimeGenerated asc",
+ "size": 1,
+ "title": "Ingestion Size vs Prorated Data Grant in the {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "No eligible DfSP2 data was found in the selected time range.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "linechart",
+ "chartSettings": {
+ "xAxis": "TimeGenerated",
+ "showDataPoints": true,
+ "ySettings": {
+ "numberFormatSettings": {
"unit": 39,
"options": {
"style": "decimal",
- "maximumFractionDigits": 2
+ "maximumFractionDigits": 3
}
}
+ }
+ }
+ },
+ "name": "DfSP2DailyIngestionVsGrant"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let licenseCount = todouble('{TotalDfSP2Licenses}'); let unitPrice = todouble('{DfSP2LicensePrice}'); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); print LicensingCost = iif(isnull(licenseCount), 'N/A', strcat('$', tostring(round(licenseCount * unitPrice * periodDays / 30.0, 2))))",
+ "size": 4,
+ "title": "Defender for Servers Plan 2 licensing cost: {TimeRange}",
+ "timeContextFromParameter": "TimeRange",
+ "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate licensing cost.",
+ "noDataMessageStyle": 3,
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "LicensingCost",
+ "formatter": 12,
+ "formatOptions": {
+ "palette": "orangeBlue"
+ }
},
"showBorder": false
+ ,
+ "size": "auto"
}
},
- "customWidth": "25",
- "name": "DataLakeMirroredVolume"
+ "customWidth": "50",
+ "name": "DfSP2LicensingCost"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let compressionRatio = 6.0; let selectedDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); let chargeableDays = max_of(todouble('{LakeTotalRetentionMonths}') * 30.0 - todouble('{LakeAnalyticsRetentionDays}'), 0.0); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | summarize RawGB = sum(Quantity) / 1024.0 | extend ['Billed Compressed Volume'] = RawGB / selectedDays * chargeableDays / compressionRatio | project ['Billed Compressed Volume']",
- "size": 1,
- "title": "Est. Lake Storage at Steady State",
+ "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); let licenseCount = todouble('{TotalDfSP2Licenses}'); let unitPrice = todouble('{DfSP2LicensePrice}'); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); let eligibleGB = toreal(coalesce(toscalar(Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize sum(Quantity) / 1024.0), 0.0)); let periodGrantGB = licenseCount * 500.0 / 1024.0 * periodDays; let licensingCost = licenseCount * unitPrice * periodDays / 30.0; print NetSavings = iif(isnull(licenseCount), 'N/A', strcat('$', tostring(round(min_of(eligibleGB, periodGrantGB) * todouble('{Price}') - licensingCost, 2))))",
+ "size": 4,
+ "title": "Estimated savings after licensing cost: {TimeRange}",
"timeContextFromParameter": "TimeRange",
- "noDataMessage": "No mirrored table usage data was found in the selected time range.",
+ "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate net savings.",
"noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
@@ -2029,35 +1735,116 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "Billed Compressed Volume",
+ "columnMatch": "NetSavings",
"formatter": 12,
"formatOptions": {
- "palette": "orangeBlue"
+ "palette": "greenRed"
+ }
+ },
+ "showBorder": false
+ ,
+ "size": "auto"
+ }
+ },
+ "customWidth": "50",
+ "name": "DfSP2NetSavingsAfterLicensing"
+ }
+ ]
+ },
+ "name": "group - Defender for Cloud Plan 2 Ingestion Benefit"
+ },{
+ "type": 12,
+ "content": {
+ "version": "NotebookGroup/1.0",
+ "groupType": "editable",
+ "title": "Retention summary",
+ "expandable": true,
+ "expanded": true,
+ "items": [
+ {
+ "type": 1,
+ "content": {
+ "json": "This section estimates Analytics-tier charges for billable data retained longer than 90 days, using historical billable workspace records. XDR and data lake retention use separate billing models. Review [Manage data tiers and retention in Microsoft Sentinel](https://learn.microsoft.com/azure/sentinel/manage-data-overview) for retention and data-tier guidance."
+ },
+ "name": "text - retention summary"
+ },
+ {
+ "type": 9,
+ "content": {
+ "version": "KqlParameterItem/1.0",
+ "parameters": [
+ {
+ "id": "9d5299d0-36a0-4666-9803-ca6931bdaab7",
+ "version": "KqlParameterItem/1.0",
+ "name": "RetentionPrice",
+ "label": "Retention price",
+ "type": 1,
+ "description": "Enter the retention price per GB/month used for this section's estimates.",
+ "typeSettings": {
+ "paramValidationRules": [
+ {
+ "regExp": "^(0|[1-9][0-9]*)(\\.[0-9]+)?$",
+ "match": true,
+ "message": "Enter a non-negative price."
+ }
+ ]
},
+ "value": "0.1"
+ }
+ ],
+ "style": "pills",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces"
+ },
+ "name": "parameters - retention pricing"
+ },
+ {
+ "type": 3,
+ "content": {
+ "version": "KqlItem/1.0",
+ "query": "let retainedDataGB = toreal(coalesce(toscalar((union withsource = SourceTableName * | where TimeGenerated < startofday(now()) - 90d | where _IsBillable == true | summarize sum(_BilledSize) / 1024.0 / 1024.0 / 1024.0)), 0.0)); print ['Average Daily Retention Cost'] = retainedDataGB * todouble('{RetentionPrice}') / 30.0",
+ "size": 4,
+ "title": "Average Daily Retention Cost",
+ "noDataMessage": "No retained billable data was found in the selected workspace scope.",
+ "noDataMessageStyle": 3,
+ "timeContextFromParameter": "TimeRange",
+ "queryType": 0,
+ "resourceType": "microsoft.operationalinsights/workspaces",
+ "crossComponentResources": [
+ "{Workspace}"
+ ],
+ "visualization": "tiles",
+ "tileSettings": {
+ "titleContent": {
+ "columnMatch": "Average Daily Retention Cost",
+ "formatter": 12,
"numberFormat": {
- "unit": 39,
+ "unit": 0,
"options": {
- "style": "decimal",
+ "currency": "USD",
+ "style": "currency",
"maximumFractionDigits": 2
}
}
},
"showBorder": false
+ ,
+ "size": "auto"
}
},
"customWidth": "25",
- "name": "DataLakeSteadyStateCompressedVolume"
+ "name": "AverageDailyRetentionCost"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let compressionRatio = 6.0; let selectedDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); let chargeableDays = max_of(todouble('{LakeTotalRetentionMonths}') * 30.0 - todouble('{LakeAnalyticsRetentionDays}'), 0.0); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | summarize RawGB = sum(Quantity) / 1024.0 | extend ['Estimated Monthly Storage Cost'] = RawGB / selectedDays * chargeableDays / compressionRatio * todouble('{LakeStoragePrice}') | project ['Estimated Monthly Storage Cost']",
- "size": 1,
- "title": "Est. Monthly Lake Storage Cost",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "No mirrored table usage data was found in the selected time range.",
+ "query": "let selectedDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); let retainedDataGB = toreal(coalesce(toscalar((union withsource = SourceTableName * | where TimeGenerated < startofday(now()) - 90d | where _IsBillable == true | summarize sum(_BilledSize) / 1024.0 / 1024.0 / 1024.0)), 0.0)); print ['Retention Cost'] = retainedDataGB * todouble('{RetentionPrice}') * selectedDays / 30.0",
+ "size": 4,
+ "title": "Retention Cost: {TimeRange}",
+ "noDataMessage": "No retained billable data was found in the selected workspace scope.",
"noDataMessageStyle": 3,
+ "timeContextFromParameter": "TimeRange",
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
@@ -2066,11 +1853,8 @@
"visualization": "tiles",
"tileSettings": {
"titleContent": {
- "columnMatch": "Estimated Monthly Storage Cost",
- "formatter": 12,
- "formatOptions": {
- "palette": "greenRed"
- },
+ "columnMatch": "Retention Cost",
+ "formatter": 12,
"numberFormat": {
"unit": 0,
"options": {
@@ -2081,20 +1865,22 @@
}
},
"showBorder": false
+ ,
+ "size": "auto"
}
},
"customWidth": "25",
- "name": "DataLakeEstimatedMonthlyStorageCost"
+ "name": "RetentionCostForTimeRange"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let compressionRatio = 6.0; let selectedDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); let chargeableDays = max_of(todouble('{LakeTotalRetentionMonths}') * 30.0 - todouble('{LakeAnalyticsRetentionDays}'), 0.0); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | summarize RawGB = sum(Quantity) / 1024.0 by DataType | extend AvgDailyRawGB = RawGB / selectedDays | extend RetainedRawGB = AvgDailyRawGB * chargeableDays | extend CompressedGB = RetainedRawGB / compressionRatio | project ['Log Type'] = DataType, ['Avg Daily Volume'] = AvgDailyRawGB, ['Lake Retained Volume'] = RetainedRawGB, ['Billed Compressed Volume'] = CompressedGB, ['Monthly Storage Cost'] = CompressedGB * todouble('{LakeStoragePrice}') | order by ['Monthly Storage Cost'] desc",
- "size": 1,
- "title": "Estimated data lake storage cost by table (steady state at {LakeTotalRetentionMonths}-month retention)",
+ "query": "let selectedDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); union withsource = SourceTableName * | where TimeGenerated < startofday(now()) - 90d | where _IsBillable == true | summarize RetainedDataGB = sum(_BilledSize) / 1024.0 / 1024.0 / 1024.0 by SourceTableName | project ['Log Type'] = SourceTableName, ['Retained Data'] = RetainedDataGB, ['Average Daily Retention Cost'] = RetainedDataGB * todouble('{RetentionPrice}') / 30.0, ['Retention Cost'] = RetainedDataGB * todouble('{RetentionPrice}') * selectedDays / 30.0 | order by ['Retained Data'] desc",
+ "size": 0,
+ "title": "Retained data by source table in the {TimeRange}",
"timeContextFromParameter": "TimeRange",
- "noDataMessage": "No mirrored table usage data was found in the selected time range.",
+ "noDataMessage": "No billable data older than {TimeRange} was found in the selected workspace scope.",
"noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
@@ -2109,14 +1895,15 @@
"columnMatch": "Log Type",
"formatter": 0,
"formatOptions": {
- "customColumnWidthSetting": "2fr"
+ "customColumnWidthSetting": "35%"
}
},
{
- "columnMatch": "Avg Daily Volume",
- "formatter": 0,
+ "columnMatch": "Retained Data",
+ "formatter": 3,
"formatOptions": {
- "customColumnWidthSetting": "1fr"
+ "palette": "greenRed",
+ "customColumnWidthSetting": "20%"
},
"numberFormat": {
"unit": 39,
@@ -2127,40 +1914,25 @@
}
},
{
- "columnMatch": "Lake Retained Volume",
+ "columnMatch": "Average Daily Retention Cost",
"formatter": 0,
"formatOptions": {
- "customColumnWidthSetting": "1fr"
- },
- "numberFormat": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "maximumFractionDigits": 2
- }
- }
- },
- {
- "columnMatch": "Billed Compressed Volume",
- "formatter": 3,
- "formatOptions": {
- "palette": "blue",
- "customColumnWidthSetting": "1fr"
+ "customColumnWidthSetting": "25%"
},
"numberFormat": {
- "unit": 39,
+ "unit": 0,
"options": {
- "style": "decimal",
+ "currency": "USD",
+ "style": "currency",
"maximumFractionDigits": 2
}
}
},
{
- "columnMatch": "Monthly Storage Cost",
- "formatter": 3,
+ "columnMatch": "Retention Cost",
+ "formatter": 0,
"formatOptions": {
- "palette": "greenRed",
- "customColumnWidthSetting": "1fr"
+ "customColumnWidthSetting": "20%"
},
"numberFormat": {
"unit": 0,
@@ -2174,29 +1946,69 @@
],
"labelSettings": [
{
- "columnId": "Avg Daily Volume",
- "label": "Avg daily (GB)"
- },
- {
- "columnId": "Lake Retained Volume",
- "label": "Retained raw (GB)"
+ "columnId": "Average Daily Retention Cost",
+ "label": "Avg daily cost"
},
{
- "columnId": "Billed Compressed Volume",
- "label": "Billed compressed (GB)"
+ "columnId": "Retention Cost",
+ "label": "Period cost"
}
]
}
},
- "name": "DataLakeStorageCostByTable"
+ "name": "RetentionDataDetail"
+ }
+ ]
+ },
+ "name": "group - Retention"
+ },{
+ "type": 12,
+ "content": {
+ "version": "NotebookGroup/1.0",
+ "groupType": "editable",
+ "title": "Commitment tiers",
+ "expandable": true,
+ "expanded": true,
+ "items": [
+ {
+ "type": 1,
+ "content": {
+ "json": "Microsoft Sentinel and Log Analytics offer Pay-As-You-Go and Commitment Tier pricing. This section automatically detects the current workspace tier and calculates a **usage-based suggested tier** from average billable daily ingestion over the last 31 days.\r\n\r\n> **New workspace notice:** A recommendation is shown only after 31 days of billable data are detected. Until then, the table reports how many days remain before the recommendation becomes available; a shorter history cannot accurately represent the fixed 31-day review period.\r\n\r\n> **Estimate only:** The suggested tier uses ingestion volume, not actual pricing. It is not the Azure portal **Recommended Tier** and should not be used as the sole basis for a pricing change. Azure evaluates each available tier using the prior 31 days and your applicable pricing to identify the lowest estimated-cost option. Review [Usage and estimated costs in the Azure portal](https://learn.microsoft.com/azure/azure-monitor/logs/change-pricing-tier#changing-pricing-tier) before changing a tier.\r\n\r\nReview **Days since tier last changed** before making a change: a commitment tier has a 31-day period during which it cannot move to a lower commitment or consumption tier. Confirm rates on the [Microsoft Sentinel pricing page](https://www.microsoft.com/security/pricing/microsoft-sentinel/) and review [Plan costs and understand pricing and billing for Microsoft Sentinel](https://learn.microsoft.com/azure/sentinel/billing?tabs=simplified%2Ccommitment-tiers#analytics-tier)."
+ },
+ "name": "text - commitment tiers"
+ },
+ {
+ "type": 9,
+ "content": {
+ "version": "KqlParameterItem/1.0",
+ "parameters": [
+ {
+ "id": "7df48bd0-c79e-4c17-9a6d-b00b9511d9e1",
+ "version": "KqlParameterItem/1.0",
+ "name": "CurrentCommitmentTier",
+ "type": 1,
+ "isRequired": true,
+ "query": "resources\r\n| where type =~ 'microsoft.operationalinsights/workspaces'\r\n| where id in~ ({Workspace}) or 'value::all' in~ ({Workspace})\r\n| extend skuName = tolower(tostring(properties.sku.name)), capacityReservationLevel = toint(properties.sku.capacityReservationLevel)\r\n| extend currentTier = case(skuName == 'capacityreservation', strcat(tostring(capacityReservationLevel), ' GB/day commitment'), skuName == 'pergb2018', 'Pay-As-You-Go', skuName == 'free', 'Free tier', skuName == 'standalone', 'Standalone tier', skuName == 'standard', 'Standard tier', skuName == 'premium', 'Premium tier', 'Unknown')\r\n| summarize WorkspaceCount = dcount(id), CurrentTier = any(currentTier)\r\n| project CurrentCommitmentTier = iif(WorkspaceCount == 1, CurrentTier, 'Multiple workspaces')",
+ "isHiddenWhenLocked": true,
+ "queryType": 1,
+ "resourceType": "microsoft.resourcegraph/resources"
+ }
+ ],
+ "style": "pills",
+ "queryType": 1,
+ "resourceType": "microsoft.resourcegraph/resources"
+ },
+ "name": "parameters - commitment tier current"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
- "query": "let lakeOnlyGB = todouble('{LakeOnlyIngestionGB}'); let queryScannedGB = todouble('{LakeQueryScannedGB}'); let insightsHours = todouble('{LakeInsightsHours}'); union (print SortOrder = 1, Meter = 'Data lake ingestion', Basis = 'Lake-tier-only tables, not visible in the workspace', Volume = lakeOnlyGB, Unit = 'GB/month', Cost = lakeOnlyGB * todouble('{LakeIngestionPrice}')), (print SortOrder = 2, Meter = 'Data processing', Basis = 'Lake-tier-only tables, not visible in the workspace', Volume = lakeOnlyGB, Unit = 'GB/month', Cost = lakeOnlyGB * todouble('{LakeProcessingPrice}')), (print SortOrder = 3, Meter = 'Data lake query', Basis = 'Uncompressed data scanned by KQL queries and jobs', Volume = queryScannedGB, Unit = 'GB/month', Cost = queryScannedGB * todouble('{LakeQueryPrice}')), (print SortOrder = 4, Meter = 'Advanced data insights', Basis = 'Notebook and job compute time', Volume = insightsHours, Unit = 'hours/month', Cost = insightsHours * todouble('{LakeInsightsPrice}')) | order by SortOrder asc | project Meter, ['Billing basis'] = Basis, ['Entered volume'] = iif(isnull(Volume), 'Not set', strcat(tostring(round(Volume, 2)), ' ', Unit)), ['Estimated monthly cost'] = iif(isnull(Cost), 'N/A - enter a volume above', strcat('$', tostring(round(Cost, 2))))",
- "size": 1,
- "title": "Data lake meters that cannot be measured from the workspace",
+ "query": "let reviewDays = 31.0; let reviewStart = ago(31d); let historyProbeStart = ago(32d); let currentTier = '{CurrentCommitmentTier}'; let tierLevels = dynamic([50,100,200,300,400,500,1000,2000,5000]); union withsource = SourceTableName * | where TimeGenerated between (historyProbeStart .. now()) | where _IsBillable == true | summarize TotalBilledBytes = sumif(_BilledSize, TimeGenerated >= reviewStart), FirstObserved = min(TimeGenerated) | extend ObservedHistoryDays = iif(isnull(FirstObserved), 0.0, min_of(reviewDays, datetime_diff('second', now(), FirstObserved) / 86400.0)) | extend DaysRemaining = toint(ceiling(max_of(reviewDays - ObservedHistoryDays, 0.0))) | extend AvgDailyGB = iif(DaysRemaining == 0, TotalBilledBytes / 1024.0 / 1024.0 / 1024.0 / reviewDays, real(null)), TierLevels = tierLevels | mv-expand TierLevel = TierLevels to typeof(int) | extend IsEligible = TierLevel >= AvgDailyGB | summarize SuggestedTierGBPerDay = minif(TierLevel, IsEligible), AvgDailyGB = any(AvgDailyGB), ObservedHistoryDays = any(ObservedHistoryDays), DaysRemaining = any(DaysRemaining) | extend suggestedTier = case(DaysRemaining > 0, strcat('Ready in ', tostring(DaysRemaining), iif(DaysRemaining == 1, ' day', ' days')), AvgDailyGB < 50.0, 'Pay-As-You-Go', isnotempty(SuggestedTierGBPerDay), strcat(tostring(SuggestedTierGBPerDay), ' GB/day commitment'), 'Above 5000 GB/day - review Azure portal options') | extend alignmentStatus = case(DaysRemaining > 0, 'Not Ready', currentTier == 'Not available' or currentTier == 'Unknown' or currentTier == 'Multiple workspaces', 'Not evaluated', suggestedTier startswith 'Above 5000 GB/day', 'Review in portal', currentTier == suggestedTier, 'Aligned', 'Review tier') | project Current = currentTier, Suggested = suggestedTier, Status = alignmentStatus, ['Avg daily GB'] = round(AvgDailyGB, 2)",
+ "size": 0,
+ "title": "Usage-based suggested tier details",
+ "noDataMessage": "No billable ingestion was found in the last 31 days.",
+ "noDataMessageStyle": 3,
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"crossComponentResources": [
@@ -2206,81 +2018,92 @@
"gridSettings": {
"formatters": [
{
- "columnMatch": "Meter",
+ "columnMatch": "Current",
"formatter": 0,
"formatOptions": {
- "customColumnWidthSetting": "1fr"
+ "customColumnWidthSetting": "25%"
}
},
{
- "columnMatch": "Billing basis",
+ "columnMatch": "Suggested",
"formatter": 0,
"formatOptions": {
- "customColumnWidthSetting": "2fr"
+ "customColumnWidthSetting": "35%"
}
},
{
- "columnMatch": "Entered volume",
- "formatter": 0,
+ "columnMatch": "Status",
+ "formatter": 18,
"formatOptions": {
- "customColumnWidthSetting": "1fr"
+ "thresholdsOptions": "icons",
+ "customColumnWidthSetting": "20%",
+ "thresholdsGrid": [
+ {
+ "operator": "==",
+ "thresholdValue": "Aligned",
+ "representation": "success",
+ "text": "{0}{1}"
+ },
+ {
+ "operator": "==",
+ "thresholdValue": "Review tier",
+ "representation": "failed",
+ "text": "{0}{1}"
+ },
+ {
+ "operator": "==",
+ "thresholdValue": "Not Ready",
+ "representation": "warning",
+ "text": "{0}{1}"
+ },
+ {
+ "operator": "Default",
+ "thresholdValue": null,
+ "representation": "2",
+ "text": "{0}{1}"
+ }
+ ]
}
},
{
- "columnMatch": "Estimated monthly cost",
+ "columnMatch": "Avg daily GB",
"formatter": 0,
"formatOptions": {
- "customColumnWidthSetting": "1fr"
+ "customColumnWidthSetting": "20%"
+ },
+ "numberFormat": {
+ "unit": 39,
+ "options": {
+ "style": "decimal",
+ "maximumFractionDigits": 2
+ }
}
}
]
}
},
- "name": "DataLakeManualMeterEstimates"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let selectedDuration = {TimeRange:end} - {TimeRange:start}; let timeGrain = case(selectedDuration <= 1h, 5m, selectedDuration <= 4h, 15m, selectedDuration <= 1d, 1h, selectedDuration <= 7d, 6h, selectedDuration <= 31d, 1d, selectedDuration <= 90d, 7d, 30d); Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | summarize ['Mirrored Volume'] = sum(Quantity) / 1024.0 by bin(TimeGenerated, timeGrain) | order by TimeGenerated asc",
- "size": 1,
- "title": "Mirrored Volume in the {TimeRange}",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "No mirrored table usage data was found in the selected time range.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "linechart",
- "chartSettings": {
- "xAxis": "TimeGenerated",
- "showDataPoints": true,
- "ySettings": {
- "numberFormatSettings": {
- "unit": 39,
- "options": {
- "style": "decimal",
- "maximumFractionDigits": 3
- }
- }
- }
- }
- },
- "name": "DataLakeMirroredVolumeTrend"
+ "name": "CommitmentTierUsageContext",
+ "customWidth": "100"
}
]
},
- "name": "group - Data Lake"
- },
- {
- "type": 1,
+ "name": "group - Commitment Tiers"
+ },{
+ "type": 12,
"content": {
- "json": "## SOAR summary\r\n\r\nMicrosoft Sentinel playbooks use Azure Logic Apps to automate responses to incidents, alerts, and other security operations workflows. This section automatically discovers accessible Logic Apps and summarizes billable executions from Azure Monitor metrics.\r\n\r\nAll accessible subscriptions and resource groups are included by default, and the first 10 discovered Logic Apps are selected with concrete resource IDs. Use the Logic Apps control to change or expand that selection. The execution table updates directly from the selected Logic Apps and time range. Select a row to calculate the estimated automation cost for that scope using the **Logic App execution cost** value below. It does not query the `AzureMetrics` table and is not affected when `AzureMetrics` is configured as Basic Logs.\r\n\r\nReview [Automate threat response with playbooks in Microsoft Sentinel](https://learn.microsoft.com/azure/sentinel/automation/automate-responses-with-playbooks) for playbook guidance. Because playbooks use Azure Logic Apps, additional charges can apply. Go to the [Azure Logic Apps](https://azure.microsoft.com/pricing/details/logic-apps/) pricing page for more details."
- },
- "name": "text - 3"
- },
+ "version": "NotebookGroup/1.0",
+ "groupType": "editable",
+ "title": "SOAR summary",
+ "expandable": true,
+ "expanded": true,
+ "items": [
+ {
+ "type": 1,
+ "content": {
+ "json": "Microsoft Sentinel playbooks use Azure Logic Apps to automate responses to incidents, alerts, and other security operations workflows. This section discovers accessible Logic Apps across the selected subscription and resource group scope.\r\n\r\nAll matching Logic Apps are included by default. Use the subscription, resource group, and Logic Apps controls to narrow the scope. The table below lists the Logic Apps included by the selected parameters.\r\n\r\nBillable execution metrics are not shown in this table: Logic Apps execution data lives in `AzureMetrics`, which is frequently configured as a Basic Logs table and cannot be queried through the Logs experience these panels use (the query returns 'Basic Logs table is not supported in Logs'). Review billable executions in the Logic App **Metrics** blade (metrics `BillableActionExecutions` and `BillableTriggerExecutions`), Azure Monitor metrics, or Cost Management.\r\n\r\nReview [Automate threat response with playbooks in Microsoft Sentinel](https://learn.microsoft.com/azure/sentinel/automation/automate-responses-with-playbooks) for playbook guidance. Because playbooks use Azure Logic Apps, additional charges can apply. Go to the [Azure Logic Apps](https://azure.microsoft.com/pricing/details/logic-apps/) pricing page for more details."
+ },
+ "name": "text - 3"
+ },
{
"type": 9,
"content": {
@@ -2375,38 +2198,25 @@
"multiSelect": true,
"quote": "'",
"delimiter": ",",
- "query": "Resources\r\n| where type in~ ({ResourceTypes})\r\n| extend resourceGroupId = strcat('/subscriptions/', subscriptionId, '/resourceGroups/', resourceGroup)\r\n| where resourceGroupId in~ ({ResourceGroups}) or '*' in~ ({ResourceGroups})\r\n| order by name asc\r\n| extend Rank = row_number()\r\n| project value = id, label = tostring(name), selected = Rank <= 10, group = resourceGroup",
+ "query": "Resources\r\n| where type in~ ({ResourceTypes})\r\n| extend resourceGroupId = strcat('/subscriptions/', subscriptionId, '/resourceGroups/', resourceGroup)\r\n| where resourceGroupId in~ ({ResourceGroups}) or '*' in~ ({ResourceGroups}) or 'value::all' in~ ({ResourceGroups})\r\n| order by name asc\r\n| project value = id, label = tostring(name), group = resourceGroup",
"crossComponentResources": [
"{Subscription}"
],
"typeSettings": {
- "additionalResourceOptions": [],
+ "additionalResourceOptions": [
+ "value::all"
+ ],
"showDefault": false
},
"timeContext": {
"durationMs": 86400000
},
"queryType": 1,
- "resourceType": "microsoft.resourcegraph/resources"
- },
- {
- "id": "8f552e99-2d30-4679-b4b0-25429bf0216b",
- "version": "KqlParameterItem/1.0",
- "name": "ExecutionCost",
- "label": "Logic App execution cost",
- "type": 1,
- "isRequired": true,
- "description": "Enter the cost per Logic App execution used for the SOAR estimate.",
- "typeSettings": {
- "paramValidationRules": [
- {
- "regExp": "^(0|[1-9][0-9]*)(\\.[0-9]+)?$",
- "match": true,
- "message": "Enter a non-negative price."
- }
- ]
- },
- "value": "0.000125"
+ "resourceType": "microsoft.resourcegraph/resources",
+ "defaultValue": "value::all",
+ "value": [
+ "value::all"
+ ]
}
],
"style": "pills",
@@ -2416,212 +2226,67 @@
"name": "parameters - SOAR resource selectors section"
},
{
- "type": 10,
+ "type": 3,
"content": {
- "chartId": "workbooke70b7cbc-f1d7-4a74-b8b9-75cc8d5ab586",
- "version": "MetricsItem/2.0",
+ "version": "KqlItem/1.0",
+ "query": "Resources\r\n| where type =~ 'microsoft.logic/workflows'\r\n| extend resourceGroupId = strcat('/subscriptions/', subscriptionId, '/resourceGroups/', resourceGroup)\r\n| where resourceGroupId in~ ({ResourceGroups}) or 'value::all' in~ ({ResourceGroups}) or '*' in~ ({ResourceGroups})\r\n| where id in~ ({Resources}) or 'value::all' in~ ({Resources}) or '*' in~ ({Resources})\r\n| project ['Logic App'] = name, ['Resource group'] = resourceGroup, Subscription = subscriptionId, Location = location, ['Resource ID'] = id\r\n| order by ['Logic App'] asc",
"size": 0,
- "chartType": 0,
- "resourceType": "microsoft.logic/workflows",
- "metricScope": 0,
- "resourceParameter": "Resources",
- "resourceIds": [
- "{Resources}"
- ],
- "timeContextFromParameter": "TimeRange",
- "metrics": [
- {
- "namespace": "microsoft.logic/workflows",
- "metric": "microsoft.logic/workflows--TotalBillableExecutions",
- "aggregation": 1
- }
- ],
- "title": "Logic App billable executions in the {TimeRange}",
- "noDataMessage": "No Logic App metric data is available for the selected scope and time range. Confirm that the Logic Apps are accessible, then expand the time range or choose a narrower scope.",
+ "title": "Breakdown of Logic Apps in the {TimeRange}",
+ "noDataMessage": "No Logic Apps match the selected subscription, resource group, and Logic Apps parameters.",
"noDataMessageStyle": 3,
- "resourceLimit": 10000,
+ "queryType": 1,
+ "resourceType": "microsoft.resourcegraph/resources",
+ "crossComponentResources": [
+ "{Subscription}"
+ ],
+ "visualization": "table",
"gridSettings": {
+ "showExportToExcel": true,
"formatters": [
{
- "columnMatch": "Subscription",
- "formatter": 5,
- "formatOptions": {
- "customColumnWidthSetting": "1fr"
- }
- },
- {
- "columnMatch": "Name",
+ "columnMatch": "Logic App",
"formatter": 13,
"formatOptions": {
+ "linkColumn": "Resource ID",
"linkTarget": "Resource",
"showIcon": true,
- "customColumnWidthSetting": "2fr"
+ "customColumnWidthSetting": "35%"
}
},
{
- "columnMatch": "microsoft.logic/workflows--TotalBillableExecutions",
- "formatter": 8,
+ "columnMatch": "Resource group",
+ "formatter": 0,
"formatOptions": {
- "palette": "blue",
- "aggregation": "Sum",
- "customColumnWidthSetting": "1fr"
+ "customColumnWidthSetting": "25%"
}
},
{
- "columnMatch": "microsoft.logic/workflows--TotalBillableExecutions Timeline",
- "formatter": 21,
+ "columnMatch": "Subscription",
+ "formatter": 0,
"formatOptions": {
- "palette": "blue",
- "customColumnWidthSetting": "2fr"
+ "customColumnWidthSetting": "25%"
}
},
{
- "columnMatch": "microsoft.logic/workflows--BillableTriggerExecutions Timeline",
- "formatter": 5
- },
- {
- "columnMatch": "microsoft.logic/workflows--BillableActionExecutions",
- "formatter": 8,
+ "columnMatch": "Location",
+ "formatter": 0,
"formatOptions": {
- "palette": "blue"
- },
- "numberFormat": {
- "unit": 0,
- "options": {
- "style": "decimal"
- }
+ "customColumnWidthSetting": "15%"
}
},
{
- "columnMatch": "microsoft.logic/workflows--BillableActionExecutions Timeline",
+ "columnMatch": "Resource ID",
"formatter": 5
- },
- {
- "columnMatch": "RG",
- "formatter": 13,
- "formatOptions": {
- "linkTarget": null,
- "showIcon": true
- }
- },
- {
- "columnMatch": "Sum",
- "formatter": 1,
- "formatOptions": {
- "aggregation": "Sum"
- },
- "numberFormat": {
- "unit": 0,
- "options": {
- "style": "decimal"
- }
- }
}
],
- "rowLimit": 10000,
- "labelSettings": [
- {
- "columnId": "microsoft.logic/workflows--TotalBillableExecutions",
- "label": "Total Billable Executions (Sum)"
- },
- {
- "columnId": "microsoft.logic/workflows--TotalBillableExecutions Timeline",
- "label": "Total Billable Executions Timeline"
- }
- ]
- },
- "sortBy": [],
- "exportFieldName": "microsoft.logic/workflows--TotalBillableExecutions",
- "exportParameterName": "Total",
- "exportDefaultValue": "N/A"
- },
- "name": "Billable Metric"
- },
- {
- "type": 1,
- "content": {
- "json": "> **N/A:** No Logic App metric row is selected. Select a Logic App or subscription rollup above after metric data loads. If the grid is empty, confirm access to the selected Logic Apps and try a wider time range.",
- "style": "info"
- },
- "conditionalVisibility": {
- "parameterName": "Total",
- "comparison": "isEqualTo",
- "value": "N/A"
- },
- "name": "text - SOAR metric selection required"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "print ['Total billable executions'] = todouble('{Total}')",
- "size": 1,
- "title": "Total billable executions: selected scope",
- "timeContext": {
- "durationMs": 86400000
- },
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "Total billable executions",
- "formatter": 12,
- "formatOptions": {
- "palette": "blue"
- }
- },
- "showBorder": false
+ "rowLimit": 200
}
},
- "name": "SOARBillableExecutions",
- "customWidth": "50",
- "conditionalVisibility": {
- "parameterName": "Total",
- "comparison": "isNotEqualTo",
- "value": "N/A"
- }
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "print ['Estimated automation cost'] = todouble('{Total}') * todouble('{ExecutionCost}')",
- "size": 1,
- "title": "Estimated automation cost: selected scope",
- "timeContext": {
- "durationMs": 86400000
- },
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "Estimated automation cost",
- "formatter": 12,
- "formatOptions": {
- "palette": "greenRed"
- },
- "numberFormat": {
- "unit": 0,
- "options": {
- "currency": "USD",
- "style": "currency",
- "minimumFractionDigits": 2,
- "maximumFractionDigits": 3
- }
- }
- },
- "showBorder": false
- }
+ "name": "SOARSelectedLogicApps"
+ }
+ ]
},
- "name": "SOAREstimatedAutomationCost",
- "customWidth": "50",
- "conditionalVisibility": {
- "parameterName": "Total",
- "comparison": "isNotEqualTo",
- "value": "N/A"
- }
+ "name": "group - SOAR"
}
],
"fallbackResourceIds": [],
From 1d7ef2dc2c561d8e14c6ebdcdaab6f09f73590af Mon Sep 17 00:00:00 2001
From: Dr Bill Mcilhargey <19168174+billmcilhargey@users.noreply.github.com>
Date: Mon, 31 Aug 2026 15:02:55 -0400
Subject: [PATCH 5/6] Refine Defender Plan 2 workbook details
---
.../Workbooks/AzureSentinelCost.json | 66 +------------------
1 file changed, 1 insertion(+), 65 deletions(-)
diff --git a/Solutions/SOC Handbook/Workbooks/AzureSentinelCost.json b/Solutions/SOC Handbook/Workbooks/AzureSentinelCost.json
index 4db4ae6d2c3..153da20e698 100644
--- a/Solutions/SOC Handbook/Workbooks/AzureSentinelCost.json
+++ b/Solutions/SOC Handbook/Workbooks/AzureSentinelCost.json
@@ -1342,7 +1342,7 @@
{
"type": 1,
"content": {
- "json": "Defender for Servers Plan 2 provides up to 500 MB of eligible Analytics-tier ingestion per protected server or node per day. The allowance is pooled across machines in each subscription and applied at workspace level. This workbook estimates observed usage; it does not prove Plan 2 protection, licensing, eligibility, or data lake-only charges.\r\n\r\nCore eligible tables:\r\n\r\n- `SecurityAlert`, `SecurityBaseline`, `SecurityBaselineSummary`, `SecurityDetection`, `SecurityEvent`\r\n- `WindowsFirewall`, `ProtectionStatus`, `MDCFileIntegrityMonitoringEvents`\r\n- `DeviceCustomFileEvents`, `DeviceCustomRegistryEvents`\r\n\r\nConditionally eligible tables:\r\n\r\n- `Update`, `UpdateSummary`: review the applicable Update Management conditions\r\n- `WindowsEvent`: only security data from the Microsoft-SecurityEvent stream\r\n\r\nNodes is the distinct `Computer` count observed in `Heartbeat`, not proof of licensing or Plan 2 protection. Review the [Defender for Servers Plan 2 data ingestion benefit](https://learn.microsoft.com/azure/defender-for-cloud/data-ingestion-benefit) for current eligibility and terms."
+ "json": "Defender for Servers Plan 2 provides up to 500 MB of eligible Analytics-tier ingestion per protected server or node per day. The allowance is pooled across machines in each subscription and applied at workspace level. This workbook estimates observed usage; it does not prove Plan 2 protection, licensing, eligibility, or data lake-only charges.\r\n\r\nEligible data-source groups include:\r\n\r\n- Microsoft Defender for Cloud security alerts and recommendations (`SecurityAlert`, `SecurityBaseline`, `SecurityBaselineSummary`, `SecurityDetection`, `SecurityEvent`)\r\n- Host protection and endpoint security data (`WindowsFirewall`, `ProtectionStatus`, `MDCFileIntegrityMonitoringEvents`)\r\n- Defender for Endpoint custom detection data (`DeviceCustomFileEvents`, `DeviceCustomRegistryEvents`)\r\n- Update Management data when the applicable Defender for Servers Plan 2 conditions are met (`Update`, `UpdateSummary`)\r\n- Windows security events only when collected from the Microsoft-SecurityEvent stream (`WindowsEvent`)\r\n\r\nThis workbook estimates eligible Analytics-tier ingestion from billable `Usage` data in the selected workspace scope. `WindowsEvent`, `Update`, and `UpdateSummary` can include data that is not eligible for the benefit, so review the applicable source configuration and billing terms before treating the estimate as savings. Nodes is the distinct `Computer` count observed in `Heartbeat`; it is useful context, but not proof of licensing or Plan 2 protection. Review the [Defender for Servers Plan 2 data ingestion benefit](https://learn.microsoft.com/azure/defender-for-cloud/data-ingestion-benefit) for current eligibility and terms."
},
"name": "text - DfSP2 benefit"
},
@@ -1684,70 +1684,6 @@
}
},
"name": "DfSP2DailyIngestionVsGrant"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let licenseCount = todouble('{TotalDfSP2Licenses}'); let unitPrice = todouble('{DfSP2LicensePrice}'); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); print LicensingCost = iif(isnull(licenseCount), 'N/A', strcat('$', tostring(round(licenseCount * unitPrice * periodDays / 30.0, 2))))",
- "size": 4,
- "title": "Defender for Servers Plan 2 licensing cost: {TimeRange}",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate licensing cost.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "LicensingCost",
- "formatter": 12,
- "formatOptions": {
- "palette": "orangeBlue"
- }
- },
- "showBorder": false
- ,
- "size": "auto"
- }
- },
- "customWidth": "50",
- "name": "DfSP2LicensingCost"
- },
- {
- "type": 3,
- "content": {
- "version": "KqlItem/1.0",
- "query": "let eligibleTables = dynamic([\"SecurityAlert\",\"SecurityBaseline\",\"SecurityBaselineSummary\",\"SecurityDetection\",\"SecurityEvent\",\"WindowsFirewall\",\"ProtectionStatus\",\"MDCFileIntegrityMonitoringEvents\",\"DeviceCustomFileEvents\",\"DeviceCustomRegistryEvents\",\"Update\",\"UpdateSummary\",\"WindowsEvent\"]); let licenseCount = todouble('{TotalDfSP2Licenses}'); let unitPrice = todouble('{DfSP2LicensePrice}'); let periodDays = max_of(datetime_diff('second', {TimeRange:end}, {TimeRange:start}) / 86400.0, 1.0); let eligibleGB = toreal(coalesce(toscalar(Usage | where TimeGenerated between ({TimeRange:start} .. {TimeRange:end}) | where IsBillable == true and DataType in (eligibleTables) | summarize sum(Quantity) / 1024.0), 0.0)); let periodGrantGB = licenseCount * 500.0 / 1024.0 * periodDays; let licensingCost = licenseCount * unitPrice * periodDays / 30.0; print NetSavings = iif(isnull(licenseCount), 'N/A', strcat('$', tostring(round(min_of(eligibleGB, periodGrantGB) * todouble('{Price}') - licensingCost, 2))))",
- "size": 4,
- "title": "Estimated savings after licensing cost: {TimeRange}",
- "timeContextFromParameter": "TimeRange",
- "noDataMessage": "Enter protected Defender for Servers Plan 2 servers or nodes above to calculate net savings.",
- "noDataMessageStyle": 3,
- "queryType": 0,
- "resourceType": "microsoft.operationalinsights/workspaces",
- "crossComponentResources": [
- "{Workspace}"
- ],
- "visualization": "tiles",
- "tileSettings": {
- "titleContent": {
- "columnMatch": "NetSavings",
- "formatter": 12,
- "formatOptions": {
- "palette": "greenRed"
- }
- },
- "showBorder": false
- ,
- "size": "auto"
- }
- },
- "customWidth": "50",
- "name": "DfSP2NetSavingsAfterLicensing"
}
]
},
From 9a4ce10aebc303c1ee2010bef834abb912ae3e26 Mon Sep 17 00:00:00 2001
From: Dr Bill Mcilhargey
Date: Mon, 31 Aug 2026 18:36:57 -0400
Subject: [PATCH 6/6] Update Sentinel cost workbook