Metrics collection
EDOT Cloud Forwarder for Azure collects Azure platform metrics and forwards them to Elasticsearch as OpenTelemetry-native metrics. Platform metrics can be collected from any Azure resource type that supports metric export.
Azure offers two mechanisms to stream platform metrics to an Event Hub: Diagnostic Settings and Data Collection Rules. Both methods send metrics to the same metrics Event Hub, and EDOT Cloud Forwarder processes them using the same pipeline.
Supported Azure Monitor metric namespaces can vary by resource type and collection method; if a namespace is not available through Diagnostic Settings, use a Data Collection Rule.
| Aspect | Diagnostic Settings | Data Collection Rules |
|---|---|---|
| Dimensions | Not included | Included (for example, pod name, namespace, condition) |
| Aggregations | Total, Count, Minimum, Maximum, Average | Total, Count, Minimum, Maximum, Average |
| Setup complexity | Simpler, configured per resource | More steps, requires Managed Identity |
| Initial delay | Minutes | 20-30+ minutes |
| Field casing | Lowercase aggregates (count, total) |
Capitalized aggregates (Count, Total) |
Data Collection Rules include dimensions, which are key-value pairs that provide additional context for each metric (for example, the Kubernetes pod name, namespace, or readiness condition). This provides richer filtering and grouping when exploring metrics in Kibana. Diagnostic Settings are simpler to configure but produce flatter metrics without this dimensional breakdown.
Use Diagnostic Settings when:
- You want the quickest setup with minimal configuration.
- Aggregate totals per resource are sufficient for your monitoring needs (for example, overall CPU or memory usage for a cluster).
- You do not need to break down metrics by individual components such as pods, nodes, or namespaces.
Use Data Collection Rules when:
- You need dimensional breakdowns (for example, per-pod CPU usage, per-namespace memory, or per-condition readiness status).
- You need metric namespaces that are not available through Diagnostic Settings for your resource type.
- You plan to build dashboards or alerts that filter or group by specific dimensions.
You can also use both methods together. For example, use Diagnostic Settings for resources where aggregate metrics are sufficient, and add a Data Collection Rule for resources where you need dimensional detail.
For setup instructions, refer to Deploy EDOT Cloud Forwarder for Azure.
When an Azure platform metric arrives at the metrics Event Hub, EDOT Cloud Forwarder for Azure processes it through the following pipeline:
- The Azure Functions runtime receives the Event Hub message and forwards it to the EDOT Cloud Forwarder collector as an HTTP request.
- The collector's
azure_encodingextension decodes and transforms the Azure metric JSON into OpenTelemetry metric format. - Each Azure metric record produces five gauge data points, one for each aggregation: Total, Count, Minimum, Maximum, and Average.
- The resulting OTel metrics are exported to Elasticsearch through the OTLP endpoint.
To browse the platform metrics streamed to Elasticsearch:
- Go to Discover in your Elastic Cloud deployment or Serverless project.
- Select the
metrics-*data view. - Filter by
data_stream.datasetto narrow down to the metrics of interest. - Use the following fields to explore the data:
name: the Azure metric name (for example,kube_pod_status_ready,node_disk_usage_percentage)resource.attributes.cloud.resource_id: the Azure resource that emitted the metricattributes.*: dimensional attributes (when using Data Collection Rules)
This section shows the raw Azure metric format for each collection method. Both formats are transformed into OTel-native metrics by the azure_encoding extension.
Diagnostic Settings send metrics in a JSON envelope with a records array. Each record contains the aggregated metric values, the source resource ID, and the metric name.
Diagnostic Settings metric sample
{
"count": 1,
"total": 6,
"minimum": 6,
"maximum": 6,
"average": 6,
"resourceId": "/SUBSCRIPTIONS/12CABCB4-86E8-404F-A3D2-1DC9982F45CA/RESOURCEGROUPS/MKATSOULIS/PROVIDERS/MICROSOFT.CONTAINERSERVICE/MANAGEDCLUSTERS/MKATSOULIS-CLUSTER",
"time": "2025-11-18T11:39:00.0000000Z",
"metricName": "apiserver_cpu_usage_percentage",
"timeGrain": "PT1M"
}
| Field | Type | Description |
|---|---|---|
count |
integer | Number of samples in the aggregation window. |
total |
number | Sum of all sample values. |
minimum |
number | Minimum sample value. |
maximum |
number | Maximum sample value. |
average |
number | Average sample value. |
resourceId |
string | Azure Resource Manager ID of the source resource. Uppercase. |
time |
string | Timestamp of the aggregation window (ISO 8601). |
metricName |
string | Name of the Azure platform metric. |
timeGrain |
string | Aggregation interval (ISO 8601 duration, for example PT1M for 1 minute). |
Diagnostic Settings metrics do not include dimensions. This means you get a single aggregated value per metric per resource. To break down metrics by pod, node, namespace, or other components, use a Data Collection Rule instead.
Data Collection Rules send metrics as NDJSON (newline-delimited JSON). Each line contains the same aggregation fields as Diagnostic Settings, plus a unit field and a dimension object with key-value pairs.
Data Collection Rules metric sample
{
"Total": 0,
"Count": 1,
"Minimum": 0,
"Maximum": 0,
"Average": 0,
"resourceId": "/subscriptions/12cabcb4-86e8-404f-a3d2-1dc9982f45ca/resourceGroups/mkatsoulis/providers/Microsoft.ContainerService/managedClusters/mkatsoulis-cluster",
"time": "2025-11-18T12:47:00.0000000Z",
"unit": "Count",
"metricName": "kube_pod_status_ready",
"timeGrain": "PT1M",
"dimension": {
"condition": "unknown",
"namespace": "kube-system",
"pod": "prometheus-kube-state-metrics-55f8b5d87b-rv5ts"
}
}
| Field | Type | Description |
|---|---|---|
Total |
number | Sum of all sample values. |
Count |
integer | Number of samples in the aggregation window. |
Minimum |
number | Minimum sample value. |
Maximum |
number | Maximum sample value. |
Average |
number | Average sample value. |
resourceId |
string | Azure Resource Manager ID of the source resource. |
time |
string | Timestamp of the aggregation window (ISO 8601). |
unit |
string | Unit of measurement (for example, Count, Percent, Bytes). |
metricName |
string | Name of the Azure platform metric. |
timeGrain |
string | Aggregation interval (ISO 8601 duration, for example PT1M for 1 minute). |
dimension |
object | Key-value pairs providing additional context (for example, pod name, namespace, condition). Only present in DCR metrics. |
Notice the field casing difference: Diagnostic Settings uses lowercase names (count, total), while Data Collection Rules uses capitalized names (Count, Total). The azure_encoding extension handles both formats transparently.
The azure_encoding extension transforms each Azure metric record into five OTel gauge metrics — one per aggregation. The metric name is derived from the original metricName field, lowercased and suffixed with the aggregation type (for example, _total, _count, _minimum, _maximum, _average).
The following example shows how the Diagnostic Settings sample above (apiserver_cpu_usage_percentage) appears in Elasticsearch after transformation. Only one of the five resulting metrics is shown:
Elasticsearch document sample (Diagnostic Settings)
{
"@timestamp": "2025-11-18T11:39:00.000Z",
"data_stream": {
"type": "metrics",
"dataset": "generic.otel",
"namespace": "default"
},
"name": "apiserver_cpu_usage_percentage_total",
"gauge": {
"value": 6.0
},
"resource": {
"attributes": {
"cloud.provider": "azure",
"cloud.resource_id": "/SUBSCRIPTIONS/12CABCB4-86E8-404F-A3D2-1DC9982F45CA/RESOURCEGROUPS/MKATSOULIS/PROVIDERS/MICROSOFT.CONTAINERSERVICE/MANAGEDCLUSTERS/MKATSOULIS-CLUSTER",
"azure.eventhub.name": "metrics",
"azure.eventhub.consumer.group": "ecf",
"azure.eventhub.namespace": "mbranca-2025-11-04.servicebus.windows.net"
}
}
}
The following example shows how a DCR metric with dimensions appears in Elasticsearch. Dimensions are mapped to data point attributes:
Elasticsearch document sample (Data Collection Rules)
{
"@timestamp": "2025-11-18T12:47:00.000Z",
"data_stream": {
"type": "metrics",
"dataset": "generic.otel",
"namespace": "default"
},
"name": "kube_pod_status_ready_count",
"unit": "Count",
"gauge": {
"value": 1.0
},
"attributes": {
"condition": "unknown",
"namespace": "kube-system",
"pod": "prometheus-kube-state-metrics-55f8b5d87b-rv5ts"
},
"resource": {
"attributes": {
"cloud.provider": "azure",
"cloud.resource_id": "/subscriptions/12cabcb4-86e8-404f-a3d2-1dc9982f45ca/resourceGroups/mkatsoulis/providers/Microsoft.ContainerService/managedClusters/mkatsoulis-cluster",
"azure.eventhub.name": "metrics",
"azure.eventhub.consumer.group": "ecf",
"azure.eventhub.namespace": "mbranca-2025-11-04.servicebus.windows.net"
}
}
}
| Field | Description |
|---|---|
@timestamp |
Timestamp of the aggregation window. |
name |
Metric name, derived from the Azure metricName — lowercased, with the aggregation type appended (for example, _total, _count, _minimum, _maximum, _average). |
gauge.value |
The metric value for this aggregation. |
unit |
Unit of measurement. Only present for DCR metrics. |
attributes.* |
Dimensional attributes from DCR metrics (for example, condition, namespace, pod). Not present for Diagnostic Settings metrics. |
resource.attributes.cloud.provider |
Always azure. |
resource.attributes.cloud.resource_id |
Azure Resource Manager ID of the source resource. |
resource.attributes.azure.eventhub.name |
Event Hub name (metrics). |
resource.attributes.azure.eventhub.consumer.group |
Consumer group (ecf). |
resource.attributes.azure.eventhub.namespace |
Event Hub namespace FQDN. |
data_stream.type |
Always metrics. |
data_stream.dataset |
Dataset name (for example, generic.otel via Managed OTLP). |