Azure Data Explorer
Overview
Azure Data Explorer ingests logs, metrics and traces into an Azure Data Explorer (Kusto) database as JSON, one table per signal. Records are gzip-compressed and submitted through the Kusto ingestion service, then queried with KQL.
This is a different product surface from the other Azure destinations: Microsoft Sentinel writes OCSF records into Log Analytics custom tables through a Data Collection Rule, Azure Monitor sends Application Insights envelopes, and Azure Blob Storage writes OTLP objects to a container. This node writes rows into a Kusto database you own.
Supported platforms
- Linux:
Logs,Metrics,Traces - Windows:
Logs,Metrics,Traces - macOS:
Logs,Metrics,Traces
Prerequisite: the database, the three tables, and any ingestion mappings must already exist on the cluster. This node issues no DDL — see Table schemas for the expected column layout.
Authentication
Attach an Azure credential. Its Authentication Type selects how the collector authenticates to the cluster:
| Authentication Type | What the node sends | Credential fields used |
|---|---|---|
service_principal | Entra ID application key | tenant_id, client_id, client_secret |
system_managed_identity | The VM's system-assigned identity | none |
user_managed_identity | A user-assigned identity | client_id (must be the identity's client ID, as a UUID) |
default | The ambient Azure default credential chain | none |
workload_identity is not supported by this destination — the Kusto SDK has no workload-identity path — and is rejected when the pipeline is saved.
Whichever identity you use needs the Database Ingestor role on the target database (and Database Viewer if you also want to query from the same principal).
Note:
service_principalis the only type that puts a secret into the pipeline configuration. Prefer a managed identity when the collector runs inside Azure — those types leave this node holding no secret at all.
Basic Configuration
| Parameter | Type | Default | Required | Description |
|---|---|---|---|---|
| cluster_uri | string | — | Yes | Cluster endpoint, e.g. https://mycluster.westus2.kusto.windows.net. Must be https. |
| db_name | string | oteldb | Yes | Database holding the destination tables. |
| ingestion_type | string | queued | No | queued or managed. See Ingestion modes. |
| logs_table_name | string | OTELLogs | Yes | Table receiving log records. |
| metrics_table_name | string | OTELMetrics | Yes | Table receiving metric points. |
| traces_table_name | string | OTELTraces | Yes | Table receiving spans. |
All three table names are required even if the pipeline only carries one signal: the exporter resolves every table name when it starts, and a blank one would ingest into a table literally named "".
Ingestion modes
| Mode | Behaviour |
|---|---|
queued | Batches through the Data Management service. Durable, higher latency (typically minutes), and available on every cluster. |
managed | Uses streaming ingestion for lower latency, falling back to queued when streaming is unavailable. Streaming ingestion must be enabled on the cluster and the table. |
Advanced Configuration
| Parameter | Type | Default | Required | Description |
|---|---|---|---|---|
| timeout | string | 30s | No | Maximum time to wait for an ingestion request. Empty means no timeout. |
| logs_table_json_mapping | string | — | No | Name of a pre-created JSON ingestion mapping for the logs table. |
| metrics_table_json_mapping | string | — | No | Name of a pre-created JSON ingestion mapping for the metrics table. |
| traces_table_json_mapping | string | — | No | Name of a pre-created JSON ingestion mapping for the traces table. |
| retry_on_failure | object | — | No | Exponential backoff for failed ingestion requests. |
| sending_queue | object | — | No | Backpressure queue size, consumers, and optional disk backing. |
Ingestion mappings
Leave the mapping fields empty to ingest against the table's own schema — that works when the table columns match the layout below. Name a mapping when your table's column names differ, or when you want to drop or reshape fields on ingest. The mapping must already exist on the cluster; create it with .create table <T> ingestion json mapping ....
Example Configuration
{
"cluster_uri": "https://mycluster.westus2.kusto.windows.net",
"db_name": "oteldb", // default: "oteldb"
"ingestion_type": "queued", // default: "queued"
"logs_table_name": "OTELLogs", // default: "OTELLogs"
"metrics_table_name": "OTELMetrics", // default: "OTELMetrics"
"traces_table_name": "OTELTraces", // default: "OTELTraces"
"advanced": {
"timeout": "30s", // default: "30s"
"logs_table_json_mapping": "", // default: none (use the table schema)
"retry_on_failure": {
"enabled": true, // default: true
"initial_interval": "5s", // default: "5s"
"max_interval": "30s", // default: "30s"
"max_elapsed_time": "300s", // default: "300s"
},
"sending_queue": {
"queue_size": 1000, // default: 1000
"num_consumers": 10, // default: 10
"enable_disk_backed_queue": true,
},
},
}
Table schemas
Create the three tables before pointing a pipeline at them. These are the columns the exporter writes.
Logs (OTELLogs)
| Column | Type |
|---|---|
| Timestamp | datetime |
| ObservedTimestamp | datetime |
| TraceID | string |
| SpanID | string |
| SeverityText | string |
| SeverityNumber | int |
| Body | string |
| ResourceAttributes | dynamic |
| LogsAttributes | dynamic |
Metrics (OTELMetrics)
| Column | Type |
|---|---|
| Timestamp | datetime |
| MetricName | string |
| MetricType | string |
| MetricUnit | string |
| MetricDescription | string |
| MetricValue | real |
| Host | string |
| ResourceAttributes | dynamic |
| MetricAttributes | dynamic |
Traces (OTELTraces)
| Column | Type |
|---|---|
| TraceID | string |
| SpanID | string |
| ParentID | string |
| SpanName | string |
| SpanStatus | string |
| SpanStatusMessage | string |
| SpanKind | string |
| StartTime | datetime |
| EndTime | datetime |
| ResourceAttributes | dynamic |
| TraceAttributes | dynamic |
| Events | dynamic |
| Links | dynamic |
Example DDL for the logs table:
.create table OTELLogs (
Timestamp: datetime,
ObservedTimestamp: datetime,
TraceID: string,
SpanID: string,
SeverityText: string,
SeverityNumber: int,
Body: string,
ResourceAttributes: dynamic,
LogsAttributes: dynamic
)