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 tabUsed as
Bootstrap serverThe Kafka address, <namespace>.servicebus.windows.net:9093
Topic nameThe Kafka topic, and the <entity> in the REST address
Connection string-primary keyThe password of a Basic Auth definition for the PLAIN mechanism
Consumer groupThe 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:

MechanismDefinitionFields
OAUTHBEARERBearer tokenUsername 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
PLAINBasic AuthUsername $$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:

FieldValue
NameAny, used as self.out.kafka[name]
AddressThe bootstrap server
TopicThe topic name
SSLOn
SecurityThe Bearer token or Basic Auth definition
SASL mechanismOAUTHBEARER 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:

FieldValue
NameAny
AddressThe bootstrap server
TopicThe topic name
Consumer groupThe group created for Zato on the destination
ServiceThe service to run for each event
SSLOn
SecurityThe Bearer token or Basic Auth definition
SASL mechanismOAUTHBEARER 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:

event = json.loads(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:

FieldValue
Hosthttps://<namespace>.servicebus.windows.net
URL path/<topic name>/messages
Data formatJSON
SecurityA 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:

FieldValue
HostThe Query URI, https://<cluster>.kusto.fabric.microsoft.com
URL path/v1/rest/query
Data formatJSON
SecurityA 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

PageWhat it covers
Sending events as they happenThe outgoing connection and the REST alternative at work
Receiving events as they happenThe channel at work
Reading recent eventsThe KQL query at work
ConnectionThe app registration these definitions sign in as

Learn more