Skip to main content

Azure Event Hub

Overview​

Azure Event Hub consumes events from an Azure Event Hubs instance. Event Hubs is the delivery point almost every Azure service writes to: point a diagnostic setting at a hub and the platform streams that resource's logs and metrics into it continuously, with no agent on the resource itself. This source reads that stream and turns it into pipeline records.

Supported types: Logs

Supported platforms

  • Linux: Logs
  • Windows: Logs
  • macOS: Logs

Typical uses:

  • Azure resource diagnostics — activity logs, NSG flow logs, Key Vault audit, App Service logs, AKS control-plane logs. Anything with a diagnostic setting.

Requires collector v0.5.43 or later. Earlier releases do not build the Event Hub receiver at all, and the node will not be offered for older agents.

Authentication Configuration​

The node holds no secret. Attach one of two credential types — which one you pick decides how the collector authenticates:

CredentialUse whenNode must also supply
Connection String (connection_string)You have a connection stringnothing — the string carries both
Azure Auth (azureauth)You want an Entra ID identityNamespace and Event Hub Name

azureauth is the shared Azure identity credential — the same one the Microsoft Sentinel destination uses — and offers default (the Azure SDK credential chain), service_principal, system_managed_identity, user_managed_identity and workload_identity. Only service_principal stores a secret.

A connection string is a shared-access-key secret rather than an identity, which is why it is a separate credential type: azureauth resolves to a token and has no connection-string mode. connection_string is deliberately vendor-neutral — every service has its own connection-string shape, so the credential holds the opaque secret and each node validates the shape it needs.

The connection string must contain EntityPath=<event hub name>. Copy it from the Event Hub instance's shared access policy, not the namespace's. A namespace-level RootManageSharedAccessKey string has no EntityPath, so there is no way to tell which hub in the namespace to read. Praxis rejects such a string when the pipeline is saved.

With azureauth you must fill in Namespace and Event Hub Name on the node. An Entra ID token is scoped to a namespace, not to a single entity, so there is no EntityPath to fall back on. Namespace must be fully qualified — my-namespace.servicebus.windows.net.

Prefer a managed identity where the collector runs inside Azure. Those types store no key at all — the collector resolves a short-lived token from Entra ID.

Note: Whichever identity you use must hold Azure Event Hubs Data Receiver on the hub (or namespace) scope. A missing role assignment surfaces as a 401 at start-up, not a configuration error.

Basic Configuration​

ParameterTypeDefaultRequiredDescription
namespacestringnoneCond.Fully qualified namespace, e.g. my-namespace.servicebus.windows.net. Required for every auth type except connection_string. An sb:// or https:// prefix is stripped for you.
event_hub_namestringnoneCond.The hub to read. Required for every auth type except connection_string, which carries it in EntityPath.
groupstring$DefaultNoConsumer group. Each group tracks its own position in the hub.
formatstringazureNoBody parser. azure unpacks the Azure Monitor records[] envelope; raw passes message bodies through untouched (Enum: azure, raw).
persist_offsetsbooleantrueNoCheckpoint each partition to disk so a restart resumes where it left off.

Give the collector its own consumer group where you can. Two readers sharing $Default compete for partition ownership. Create one on the hub (Event Hub → Consumer groups → + Consumer group) and name it here. Note the Basic tier allows only one consumer group — on Basic you are stuck with $Default, which also means the portal's Data Explorer competes with the collector whenever you use it to inspect the hub. Standard allows 20.

Leave persist_offsets on. With it off, checkpoints live in memory only: a restart resumes from the latest event and everything published while the collector was down is silently skipped. When on, checkpoints are written under <collector home>/metadata/azure_event_hub_offsets/<node name>, one directory per node, so two Event Hub sources never overwrite each other's positions.

Format: azure vs raw​

azure is the right choice for anything Azure Monitor produced. It parses the records[] envelope and maps the standard fields onto OpenTelemetry:

Azure fieldBecomes
resourceIdresource attribute azure.resource.id
operationNameazure.operation.name
Levelseverity number and severity text
timerecord timestamp

raw passes the message body through unparsed and lifts the AMQP application properties onto log attributes. Use it for applications publishing their own payloads to the hub.

azure needs the Azure Monitor envelope. The body must be JSON with a top-level records[] array whose entries carry at least time (or timeStamp) and resourceId:

{"records":[{"time":"2026-09-18T09:30:00Z","resourceId":"/SUBSCRIPTIONS/…","category":"AuditLogs","operationName":"Sign-in","Level":"Informational"}]}

A body that is valid JSON but has no records[] produces zero records, with no error and no warning — the pipeline simply stays empty. A record inside records[] whose timestamp will not parse is dropped with an Unable to convert timestamp from log warning. Events you send by hand from the portal's Data Explorer blade are not in this shape; use raw to see them.

This node reads logs only​

Three separate reasons converge on it:

  1. The receiver is a shared component. Every pipeline referencing one node gets a single receiver instance, bound to whichever pipeline the collector builds first — and rebound on every restart. Advertising more than one signal would leave two of them silently empty, with the working one changing across restarts.
  2. The two Azure translators are asymmetric. The metrics translator correctly ignores a resource-log record, but the logs translator turns a platform-metric record into a log line, because a metric record also carries time and resourceId. One hub feeding both would count every metric twice.
  3. The traces translator does not discriminate at all. It emits a span for any records[] entry whose timestamp parses, so ordinary resource logs come out as spans with an empty trace ID, span ID, name and attributes.

Reading metrics from an Event Hub therefore needs a separate node definition with its own consumer group. That is not built today.

Advanced Configuration​

ParameterTypeDefaultDescription
partitionstringnoneRead a single partition instead of all of them. Leave empty in normal use — pinning one partition means the rest are never read.
offsetstringnoneStarting sequence number. Only valid together with partition.
apply_semantic_conventionsbooleanfalseRename the Azure-specific attributes to their OpenTelemetry semantic-convention equivalents.
poll_rateinteger5Seconds to wait for a full batch before returning a partial one. Lower means fresher data and more calls.
max_poll_eventsinteger100Events fetched per poll cycle.
enable_prefetchbooleantrueRead ahead from each partition into a local buffer so polls return without waiting on the network.
prefetch_countinteger300Events buffered per partition, when prefetching is on. Higher uses more memory for fewer round trips.

Example Configuration​

Connection string — the namespace and hub come from the string, so the node needs neither:

{
"group": "praxis", // dedicated consumer group
"format": "azure", // default
"persist_offsets": true // default
}

Managed identity — the node supplies what the connection string would have carried:

{
"namespace": "my-namespace.servicebus.windows.net", // required for Entra ID auth
"event_hub_name": "insights-logs-auditlogs", // required for Entra ID auth
"group": "praxis",
"format": "azure",
"persist_offsets": true,
"advanced": {
"max_poll_events": 500,
"poll_rate": 2
}
}

Troubleshooting​

SymptomLikely cause
Start-up fails complaining about the connection stringThe string has no EntityPath — it came from the namespace's shared access policy rather than the hub's.
Start-up fails with an authorization errorThe identity lacks Azure Event Hubs Data Receiver on the hub, or the client secret has expired.
No events, but the hub shows incoming messagesAnother reader owns the partitions under the same consumer group. Give the collector its own group.
A gap in the data after a restartpersist_offsets was off, so the receiver resumed from the latest event. Turn it on.
Pipeline looks healthy but the destination stays emptySwitch format to raw and resend. raw turns every event into exactly one record, so if data appears the body simply is not an Azure Monitor envelope. Note the collector's Log Records debug line prints logs: {} whether it holds zero records or thousands — plog.Logs has no exported fields — so that line is not evidence either way.
Events arrive but parse oddlyThe publisher is not Azure Monitor, so the records[] envelope is absent. Switch format to raw.