fai-azure-event-hubs-setup — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited fai-azure-event-hubs-setup (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Sets up Event Hubs namespaces with topics (hubs), consumer groups for parallel processing, auto-scaling, and Managed Identity access. Ingests traces, metrics, model outputs, and custom events from distributed AI services. Prevents Kafka SPOF and manual queue management.
| Signal | Example |
|---|---|
| High-volume telemetry source | Millions of requests/sec from AKS cluster |
| Multiple consumers need same data | Metrics pipeline + machine learning pipeline both need events |
| Manual queue scaling | Message queue grows faster than infrastructure |
| No stream processing pipeline | Events arrive but are not aggregated or transformed |
// infra/event-hubs.bicep
param location string
param namespaceName string
resource namespace 'Microsoft.EventHub/namespaces@2023-01-01-preview' = {
name: namespaceName
location: location
sku: {
name: 'Standard'
capacity: 1
}
identity: { type: 'SystemAssigned' }
properties: {
publicNetworkAccess: 'Disabled'
minimumTlsVersion: '1.2'
zoneRedundant: true
}
}
// Event Hubs (topics)
resource telemetryHub 'Microsoft.EventHub/namespaces/eventhubs@2023-01-01-preview' = {
parent: namespace
name: 'ai-telemetry'
properties: {
messageRetentionInDays: 7
partitionCount: 32 // Auto-scale across partitions
captureDescription: {
enabled: true
encoding: 'Avro'
destination: {
name: 'EventHubArchive.AzureBlockBlob'
properties: {
storageAccountResourceId: storageAccountId
blobContainer: 'event-hubs-archive'
archiveNameFormat: '{Namespace}/{EventHub}/{PartitionId}/{Year}/{Month}/{Day}/{Hour}/{Minute}/{Second}'
}
}
}
}
}# Consumer group for real-time metrics processor
az eventhubs eventhub consumer-group create \
--resource-group $RG_NAME \
--namespace-name $EH_NAMESPACE \
--eventhub-name ai-telemetry \
--name metrics-processor
# Consumer group for ML feature extraction
az eventhubs eventhub consumer-group create \
--resource-group $RG_NAME \
--namespace-name $EH_NAMESPACE \
--eventhub-name ai-telemetry \
--name ml-feature-extractor
# Consumer group for audit/compliance logging
az eventhubs eventhub consumer-group create \
--resource-group $RG_NAME \
--namespace-name $EH_NAMESPACE \
--eventhub-name ai-telemetry \
--name audit-loggerfrom azure.eventhub import EventHubProducerClient, EventData
from azure.identity import DefaultAzureCredential
import json
import time
producer = EventHubProducerClient(
fully_qualified_namespace=f"{EH_NAMESPACE}.servicebus.windows.net",
eventhub_name="ai-telemetry",
credential=DefaultAzureCredential(),
)
def send_completion_event(request_id: str, latency_ms: int, tokens: int):
event_data = EventData(
json.dumps({
"type": "completion",
"request_id": request_id,
"timestamp": time.time(),
"latency_ms": latency_ms,
"tokens": tokens,
})
)
# Batch send for throughput
with producer:
batch = producer.create_batch()
batch.add(event_data)
producer.send_batch(batch)-- Azure Stream Analytics job query
SELECT
System.Timestamp('10 second') as window_end,
COUNT(*) as event_count,
AVG(latency_ms) as avg_latency,
MAX(latency_ms) as max_latency,
SUM(tokens) as total_tokens
INTO
output_metrics_table
FROM
event_hub_input TIMESTAMP BY timestamp
GROUP BY
TumblingWindow(second, 10)from azure.eventhub import EventHubConsumerClient
from azure.identity import DefaultAzureCredential
consumer = EventHubConsumerClient(
fully_qualified_namespace=f"{EH_NAMESPACE}.servicebus.windows.net",
consumer_group="metrics-processor",
eventhub_name="ai-telemetry",
credential=DefaultAzureCredential(),
)
def on_event(partition_context, event):
print(f"Received event from partition {partition_context.partition_id}: {event.body_as_json()}")
partition_context.update_latest_offset_and_checkpoint(event)
def on_error(partition_context, error):
print(f"Error in partition {partition_context.partition_id}: {error}")
# Start consuming
consumer.receive(on_event=on_event, on_error=on_error, starting_position="@latest")| Metric | Standard (1 TU) | Standard (10 TU) | Premium |
|---|---|---|---|
| Max ingress MB/s | 1 MB/s | 10 MB/s | 100 MB/s |
| Max partitions | 32 | 32 | 100 |
| Consumer groups | 20 | 20 | 1000 |
| Retention days | 1-7 | 1-7 | 1-90 |
from azure.eventhub.aio import EventHubConsumerClient
import asyncio
async def check_consumer_lag():
client = EventHubConsumerClient(
fully_qualified_namespace=f"{EH_NAMESPACE}.servicebus.windows.net",
consumer_group="metrics-processor",
eventhub_name="ai-telemetry",
credential=DefaultAzureCredential(),
)
partition_ids = await client.get_partition_ids()
async with client:
for pid in partition_ids:
properties = await client.get_partition_properties(pid)
last_offset = properties.last_enqueued_offset
# Consumer lag = (last_offset - consumer_checkpoint) / last_offset
print(f"Partition {pid}: {properties.last_enqueued_event_number} events")| Pillar | Contribution |
|---|---|
| Performance Efficiency | Event Hubs handles 3M+ events/sec; partitioning enables parallel consumer scaling |
| Reliability | Consumer group offset tracking prevents duplicate/missed message processing |
| Operational Excellence | Archive to Blob Storage enables forensics; auto-scaling handles burst traffic |
partitionCount=32) must match expected throughput; higher = more parallel consumerscaptureDescription) auto-archives to Storage; useful for replay/forensics@latest skips backlog; use @earliest for catch-up processing~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.