Sign in during Public Preview to get the Team plan free, plus an early-adopter discount when we launch. Sign in
This guide shows you how to react to events from an Azure service using an Event Grid System Topic against Locally. We'll subscribe to a Storage Account's blob events, upload a file, and watch the BlobCreated event land on a storage queue.
az) installed.jq installed, to read the event once it arrives.Firstly, we need to launch Locally which we can do from a terminal by running:
$
locally build
Once Locally has started, the Locally Dashboard will open automatically:
Next we can create the Resource Group to hold everything:
$
locally run az group create -n sample-event-grid-system-topics -l berlin
There's two things to note here:
locally run.locally run when you do.The Storage Account is both the source of the events and where we'll deliver them, so let's create it:
$
locally run az storage account create --name sampleegsystopic1 --resource-group sample-event-grid-system-topics --location berlin --sku Standard_LRS --query "{name:name, provisioningState:provisioningState}"
{
"name": "sampleegsystopic1",
"provisioningState": "Succeeded"
}
We need a container to upload into, and a queue for the events to arrive on:
$
locally storage container create --account sampleegsystopic1 --name uploads
$
locally storage queue create --account sampleegsystopic1 --name blob-events
Note
locally storage is part of Locally itself, so it doesn't take the locally run prefix. Every az command does.A System Topic represents the events an Azure resource publishes. It points at its source by resource ID, so let's grab the Storage Account's:
$
export STORAGE_ACCOUNT_ID=$(locally run az storage account show -n sampleegsystopic1 -g sample-event-grid-system-topics --query id -o tsv)
Now we can create a System Topic for the Storage Account's events:
$
locally run az eventgrid system-topic create -g sample-event-grid-system-topics -n sample-storage-events -l berlin --topic-type Microsoft.Storage.StorageAccounts --source "$STORAGE_ACCOUNT_ID" --query "{name:name, topicType:topicType, provisioningState:provisioningState}"
{
"name": "sample-storage-events",
"provisioningState": "Succeeded",
"topicType": "Microsoft.Storage.StorageAccounts"
}
The topic doesn't deliver anything until it has an event subscription. Let's send BlobCreated events to the blob-events queue:
$
locally run az eventgrid system-topic event-subscription create -g sample-event-grid-system-topics --system-topic-name sample-storage-events -n blob-created --endpoint-type storagequeue --endpoint "$STORAGE_ACCOUNT_ID/queueServices/default/queues/blob-events" --included-event-types Microsoft.Storage.BlobCreated --query "{name:name, endpointType:destination.endpointType, queueName:destination.queueName, includedEventTypes:filter.includedEventTypes, provisioningState:provisioningState}"
{
"endpointType": "StorageQueue",
"includedEventTypes": [
"Microsoft.Storage.BlobCreated"
],
"name": "blob-created",
"provisioningState": "Succeeded",
"queueName": "blob-events"
}
Because of that filter, other blob events, such as deletes, won't reach the queue. We can list the topic's subscriptions:
$
locally run az eventgrid system-topic event-subscription list -g sample-event-grid-system-topics --system-topic-name sample-storage-events --query "[].{Name:name, Destination:destination.endpointType, Queue:destination.queueName, State:provisioningState}" -o table
Name Destination Queue State
------------ ------------- ----------- ---------
blob-created StorageQueue blob-events Succeeded
The az storage data plane commands need the account's connection string. Putting it in AZURE_STORAGE_CONNECTION_STRING means we don't have to pass it to each one:
$
export AZURE_STORAGE_CONNECTION_STRING=$(locally storage connection-string --account sampleegsystopic1)
Now let's upload a small file:
$
echo "hello from Locally" > hello.txt
$
locally run az storage blob upload --container-name uploads --name hello.txt --file hello.txt -o none
Event Grid writes each event to the queue as base64-encoded JSON. Let's peek at the message and decode it:
$
locally run az storage message peek --queue-name blob-events --query "[0].content" -o tsv | base64 --decode | jq "{eventType, subject, data: {api: .data.api, blobType: .data.blobType, contentLength: .data.contentLength}}"
{
"eventType": "Microsoft.Storage.BlobCreated",
"subject": "/blobServices/default/containers/uploads/blobs/hello.txt",
"data": {
"api": "PutBlob",
"blobType": "BlockBlob",
"contentLength": 19
}
}
Delivery happens in the background, so if the command prints nothing, give it a second and run it again. The subject tells a handler which blob was created, which is all it needs to go and process it.
Whilst this guide used the Azure CLI, System Topics work the same way through any of the tooling that Locally supports - Microsoft.EventGrid/systemTopics and Microsoft.EventGrid/systemTopics/eventSubscriptions resources in HashiCorp Terraform or OpenTofu, Pulumi, Bicep or an ARM Template all provision against Locally in the same way.
On the receiving end, any application reading the queue with the Azure SDK for .NET, Go or Python gets the same events.
To publish your own events rather than a service's, see Event Grid Topic. For more on working with the queue the events land on, see Storage Queues.
Should you encounter any issues, please take a look at the troubleshooting section.
These are the Azure resource types this guide creates in Locally:
Sign in during Public Preview to get the Team plan free, plus an early-adopter discount when we launch. Sign in
Your Azure infrastructure, running on your machine. Deploy in seconds, break things freely, and ship to Azure when you're ready.