Python Microsoft Fabric API - Events
The Kafka and REST connections for an eventstream endpoint, and the KQL query request and response.
Events do not go through the Fabric connection. An eventstream's custom endpoint speaks Kafka and REST, and an eventhouse answers KQL over REST, so the connections below are Zato's ordinary Kafka and REST connections pointed at Fabric. This page lists their fields, the sending, receiving and reading pages show them at work.
Where the values come from
Everything on this page comes from one place in Fabric - the Keys tab of the eventstream's custom endpoint, whether it is a source (Zato sends) or a destination (Zato receives):
| On the Keys tab | Used as |
|---|---|
| Bootstrap server | The Kafka address, <namespace>.servicebus.windows.net:9093 |
| Topic name | The Kafka topic, and the <entity> in the REST address |
| Connection string-primary key | The password of a Basic Auth definition for the PLAIN mechanism |
| Consumer group | The Kafka channel's consumer group, one created for Zato |
The namespace is the first part of the bootstrap server, up to .servicebus.windows.net.
Security definitions
Two kinds of definition sign a Kafka connection in, and both are created under Security in the Dashboard:
| Mechanism | Definition | Fields |
|---|---|---|
OAUTHBEARER | Bearer token | Username the application (client) ID, Password the client secret, Auth endpoint https://login.microsoftonline.com/<tenant ID>/oauth2/v2.0/token, Scopes https://<namespace>.servicebus.windows.net/.default |
PLAIN | Basic Auth | Username $$ConnectionString, Password the connection string |
The username is entered as $$ConnectionString because a value starting with a single $ names an environment variable, and doubling the sign gives the literal $ConnectionString the endpoint expects.
Kafka outgoing connection
Under Connections → Message queues → Kafka → Outgoing connections:
| Field | Value |
|---|---|
| Name | Any, used as self.out.kafka[name] |
| Address | The bootstrap server |
| Topic | The topic name |
| SSL | On |
| Security | The Bearer token or Basic Auth definition |
| SASL mechanism | OAUTHBEARER or PLAIN, matching the definition |
outgoing_kafka:
- name: Fabric Events
address: <namespace>.servicebus.windows.net:9093
topic: <topic name>
security: Fabric Events Token
sasl_mechanism: OAUTHBEARER
ssl: true
A dict passed to send is JSON-encoded before it leaves:
event = {
'event_type': 'admission',
'location': 'Riverside',
'admission_id': 'ADM-1041',
}
self.out.kafka['Fabric Events'].send(event)
Kafka channel
Under Connections → Message queues → Kafka → Channels:
| Field | Value |
|---|---|
| Name | Any |
| Address | The bootstrap server |
| Topic | The topic name |
| Consumer group | The group created for Zato on the destination |
| Service | The service to run for each event |
| SSL | On |
| Security | The Bearer token or Basic Auth definition |
| SASL mechanism | OAUTHBEARER or PLAIN, matching the definition |
channel_kafka:
- name: Fabric Alerts
address: <namespace>.servicebus.windows.net:9093
topic: <topic name>
group_id: zato
service: stock.notify-purchasing
security: Fabric Events Token
sasl_mechanism: OAUTHBEARER
ssl: true
The service receives the event's bytes in self.request.raw_request:
REST alternative for sending
When Kafka is not an option, the same endpoint takes events over HTTPS. Under Connections → REST → Outgoing connections:
| Field | Value |
|---|---|
| Host | https://<namespace>.servicebus.windows.net |
| URL path | /<topic name>/messages |
| Data format | JSON |
| Security | A Bearer token definition with Scopes https://eventhubs.azure.net/.default |
The body is a list of events, each wrapped in Body, sent with the endpoint's own content type:
body = json.dumps(event)
payload = [{'Body': body}]
headers = {'Content-Type': 'application/vnd.microsoft.servicebus.json'}
self.rest['Fabric Events REST'].post(self.cid, payload, headers=headers)
KQL query over REST
An eventhouse answers queries at /v1/rest/query on its Query URI, which is on the eventhouse's overview page. Under Connections → REST → Outgoing connections:
| Field | Value |
|---|---|
| Host | The Query URI, https://<cluster>.kusto.fabric.microsoft.com |
| URL path | /v1/rest/query |
| Data format | JSON |
| Security | A Bearer token definition with Scopes https://kusto.kusto.windows.net/.default |
The request names the database and carries the query:
{"db": "Operations Events", "csl": "Events | where event_type == 'cancellation' | summarize cancelled = count() by location"}
The response is a list of tables. The first one is the query's result, with the columns described in Columns and the values in Rows, in the same order:
{
"Tables": [
{
"TableName": "Table_0",
"Columns": [
{"ColumnName": "location", "DataType": "String"},
{"ColumnName": "cancelled", "DataType": "Int64"}
],
"Rows": [
["Maple Grove", 1]
]
}
]
}
Zipping each row with the column names gives one dict per row:
tables = response.data['Tables']
result = tables[0]
column_names = []
for column in result['Columns']:
column_names.append(column['ColumnName'])
rows = []
for values in result['Rows']:
pairs = zip(column_names, values)
row = dict(pairs)
rows.append(row)
See also
| Page | What it covers |
|---|---|
| Sending events as they happen | The outgoing connection and the REST alternative at work |
| Receiving events as they happen | The channel at work |
| Reading recent events | The KQL query at work |
| Connection | The app registration these definitions sign in as |