Azure Event Grid events are actually POST https requests sent to the url of subscription. The worklow involving Azure Event Grid is as follows:
flowchart LR s1id1-->s2id1 s2id1-->s2id2 s2id2-->s3id1 subgraph s1[Event Source i.e. Blob Storage] s1id1["`Event (a new blob in a storage container)`"] end subgraph s2[Event Grid] s2id1[Topic] s2id2[Subscription] end subgraph s3["Event Handler"] s3id1["Function App"] end
Today we are going to implement the above flow locally, although not fully, as there are certain constraints to what we are able to do locally.
Regarding the Event source, there is a Azurite Storage Emulator that ideally would send event grid events upon the upload to a new blob. Unfortunately, as of writing this post Azurite Storage Emulator does not have this capability. Therefore, we are going to emulate this part by simply using curl
(you can also use software like Postman
) and sending a post request with it to the Azure Event Grid simulator.
Prep Steps
Download event grid simulator
Download the local event grid emulator from here:
https://github.com/pmcilreavy/AzureEventGridSimulator
Go to the folder of the local event emulator:
cd C:\Programs\AzureEventGridSimulator\src\AzureEventGridSimulator\bin\Release\net7.0
Create a file example.event.data.json
with example event data (that has to be sent to the event topic endpoint):
[
{
"id": "8727823",
"subject": "/example/subject",
"data": {
"MyProperty": "This is my awesome data!"
},
"eventType": "Example.DataType",
"eventTime": "2019-01-01T00:00:00.000Z",
"dataVersion": "1"
}
]
The default Event Grid subscription endpoint is:
https://azureeventgridsimulator.requestcatcher.com/
This is great to run a few tests with it first, but let’s change it to our local function’s endpoint:
http://localhost:7071/runtime/webhooks/EventGrid?functionName=EventGridTrigger
Note the below one will not work locally:
http://localhost:7071/runtime/webhooks/EventGrid?functionName=Host.Functions.EventGridTrigger
Write event handler i.e. function app
Create new function app with the following code (Python V2 programming model):
# function_app.py:
import logging
import azure.functions as func
import json
app = func.FunctionApp()
@app.event_grid_trigger(arg_name="azeventgrid")
def EventGridTrigger(azeventgrid: func.EventGridEvent):
result = json.dumps({
'id': azeventgrid.id,
'data': azeventgrid.get_json(),
'topic': azeventgrid.topic,
'subject': azeventgrid.subject,
'event_type': azeventgrid.event_type,
})
logging.info('Python EventGrid trigger processed an event: %s', result)
Workflow simulation
Go to the folder of the local event emulator:
cd C:\Programs\AzureEventGridSimulator\src\AzureEventGridSimulator\bin\Release\net7.0
Now let’s run the AzureEventGridSimulator.exe
. It will open a new cmd window.
In the separate cmd window let’s run this command (i.e. we will send an event data to our event grid emulator topic endpoint):
curl -k -H "Content-Type: application/json" -H "aeg-sas-key: TheLocal+DevelopmentKey=" -X POST "https://localhost:60101/api/events?api-version=2018-01-01" -d @example.event.data.json
In the emulator window we should see output like this:
[11:38:51 INF] It's alive !
[11:38:56 INF] 1 event(s) received on topic 'ATopicWithATestSubscriber'
The event grid emulator now sends a POST request to the subscribers end point, which is our function that runs locally. In the log / terminal you should be able to see output like this:
* Executing task: .venv\Scripts\activate && func host start
Found Python version 3.10.9 (python).
Azure Functions Core Tools
Core Tools Version: 4.0.5085 Commit hash: N/A (64-bit)
Function Runtime Version: 4.16.4.20366
[2023-06-12T09:36:57.476Z] Worker process started and initialized.
Functions:
EventGridTrigger: eventGridTrigger
For detailed output, run func with --verbose flag.
[2023-06-12T09:37:02.418Z] Host lock lease acquired by instance ID '000000000000000000000000427EF713'.
[2023-06-12T09:38:58.387Z] Executing 'Functions.EventGridTrigger' (Reason='EventGrid trigger fired at 2023-06-12T11:38:58.3516320+02:00', Id=5c2f449a-b64d-41a9-86e4-00ba3cb67ba1)
[2023-06-12T09:38:58.470Z] Python EventGrid trigger processed an event: {"id": "8727823", "data": {"MyProperty": "This is my awesome data!"}, "topic": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/eventGridSimulator/providers/Microsoft.EventGrid/topics/ATopicWithATestSubscriber", "subject": "/example/subject", "event_type": "Example.DataType"}
[2023-06-12T09:38:58.491Z] Executed 'Functions.EventGridTrigger' (Succeeded, Id=5c2f449a-b64d-41a9-86e4-00ba3cb67ba1, Duration=129ms)
Our test event was succesfully processed by our function.
References:
- Tutorial: Trigger Azure Functions on blob containers using an event subscription
- another tutorial where the http requests from cloud are manually resent to the local function
- Local Development with Azure Functions and Event Grid