0
# Event Publishing
1
2
Event publishing in Azure Event Grid enables sending events to both Event Grid Basic topics/domains and Event Grid Namespace topics. The EventGridPublisherClient provides a unified interface that automatically detects the target environment and handles appropriate event formatting.
3
4
## Capabilities
5
6
### Publisher Client Creation
7
8
Creates a publisher client for sending events to Event Grid endpoints.
9
10
```python { .api }
11
class EventGridPublisherClient:
12
def __init__(
13
self,
14
endpoint: str,
15
credential: Union[AzureKeyCredential, AzureSasCredential, TokenCredential],
16
*,
17
namespace_topic: Optional[str] = None,
18
api_version: Optional[str] = None,
19
**kwargs: Any
20
) -> None:
21
"""
22
Create EventGrid publisher client.
23
24
Parameters:
25
- endpoint: Event Grid endpoint URL
26
- credential: Authentication credential
27
- namespace_topic: Topic name for namespaces (None for Event Grid Basic)
28
- api_version: API version (defaults: "2024-06-01" for namespaces, "2018-01-01" for basic)
29
"""
30
```
31
32
### Event Publishing
33
34
Sends events to Event Grid with automatic content type detection and schema validation.
35
36
```python { .api }
37
def send(
38
self,
39
events: Union[CloudEvent, EventGridEvent, dict, List[Union[CloudEvent, EventGridEvent, dict]]],
40
*,
41
channel_name: Optional[str] = None,
42
content_type: Optional[str] = None,
43
**kwargs: Any
44
) -> None:
45
"""
46
Send events to Event Grid.
47
48
Parameters:
49
- events: Single event or list of events to send
50
- channel_name: Channel name for multi-channel publishing (namespaces only)
51
- content_type: Override content type for the request
52
53
Raises:
54
- HttpResponseError: Server returned error response
55
- ClientAuthenticationError: Authentication failed
56
- ValueError: Invalid event format or missing required fields
57
"""
58
```
59
60
### Low-Level HTTP Operations
61
62
Direct HTTP request handling for advanced scenarios and custom event formats.
63
64
```python { .api }
65
def send_request(
66
self,
67
request: HttpRequest,
68
*,
69
stream: bool = False,
70
**kwargs: Any
71
) -> HttpResponse:
72
"""
73
Send raw HTTP request through the client pipeline.
74
75
Parameters:
76
- request: The HTTP request to send
77
- stream: Whether to stream the response payload
78
79
Returns:
80
HttpResponse: Raw HTTP response
81
"""
82
```
83
84
### Resource Management
85
86
Context manager support and explicit resource cleanup.
87
88
```python { .api }
89
def close(self) -> None:
90
"""Close the client and cleanup resources."""
91
92
def __enter__(self) -> Self:
93
"""Context manager entry."""
94
95
def __exit__(self, *exc_details: Any) -> None:
96
"""Context manager exit with cleanup."""
97
```
98
99
## Usage Examples
100
101
### Event Grid Namespaces
102
103
```python
104
from azure.eventgrid import EventGridPublisherClient
105
from azure.core.credentials import AzureKeyCredential
106
from azure.core.messaging import CloudEvent
107
import json
108
109
# Create publisher for namespace topic
110
publisher = EventGridPublisherClient(
111
endpoint="https://my-namespace.westus-1.eventgrid.azure.net",
112
credential=AzureKeyCredential("access_key"),
113
namespace_topic="my-topic"
114
)
115
116
# Send CloudEvent
117
cloud_event = CloudEvent(
118
source="myapp/orders",
119
type="Order.Created",
120
data={
121
"order_id": "12345",
122
"customer_id": "customer-456",
123
"total": 99.99
124
}
125
)
126
127
publisher.send(cloud_event)
128
129
# Send multiple events
130
events = [
131
CloudEvent(source="app", type="Event.Type1", data={"key": "value1"}),
132
CloudEvent(source="app", type="Event.Type2", data={"key": "value2"})
133
]
134
135
publisher.send(events)
136
137
# Send raw dictionary (converted to CloudEvent automatically)
138
raw_event = {
139
"specversion": "1.0",
140
"type": "Custom.Event",
141
"source": "myapp",
142
"id": "event-123",
143
"data": {"message": "Hello World"}
144
}
145
146
publisher.send(raw_event)
147
148
# Channel-specific publishing (if namespace supports channels)
149
publisher.send(cloud_event, channel_name="orders-channel")
150
151
publisher.close()
152
```
153
154
### Event Grid Basic (Legacy)
155
156
```python
157
from azure.eventgrid import EventGridPublisherClient, EventGridEvent
158
from azure.core.credentials import AzureKeyCredential
159
160
# Create publisher for basic topic (no namespace_topic specified)
161
publisher = EventGridPublisherClient(
162
endpoint="https://my-topic.westus.eventgrid.azure.net/api/events",
163
credential=AzureKeyCredential("access_key")
164
)
165
166
# Send EventGrid schema event
167
event = EventGridEvent(
168
subject="orders/order-123",
169
event_type="Order.Completed",
170
data={
171
"order_id": "123",
172
"status": "completed",
173
"total": 49.99
174
},
175
data_version="1.0"
176
)
177
178
publisher.send(event)
179
180
# Send multiple EventGrid events
181
events = [
182
EventGridEvent(subject="orders/1", event_type="Order.Created", data={}, data_version="1.0"),
183
EventGridEvent(subject="orders/2", event_type="Order.Updated", data={}, data_version="1.0")
184
]
185
186
publisher.send(events)
187
188
publisher.close()
189
```
190
191
### Context Manager Usage
192
193
```python
194
# Automatic resource cleanup
195
with EventGridPublisherClient(endpoint, credential, namespace_topic="topic") as publisher:
196
publisher.send(events)
197
# Client automatically closed on exit
198
```
199
200
### SAS Authentication (Event Grid Basic Only)
201
202
```python
203
from azure.eventgrid import generate_sas
204
from azure.core.credentials import AzureSasCredential
205
from datetime import datetime, timedelta
206
207
# Generate SAS token
208
endpoint = "https://my-topic.westus.eventgrid.azure.net/api/events"
209
access_key = "your_access_key"
210
expiration = datetime.utcnow() + timedelta(hours=1)
211
212
sas_token = generate_sas(endpoint, access_key, expiration)
213
214
# Use SAS token for authentication
215
publisher = EventGridPublisherClient(
216
endpoint=endpoint,
217
credential=AzureSasCredential(sas_token)
218
)
219
```
220
221
### Error Handling
222
223
```python
224
from azure.core.exceptions import HttpResponseError, ClientAuthenticationError
225
226
try:
227
publisher.send(events)
228
except ClientAuthenticationError as e:
229
print(f"Authentication failed: {e}")
230
except HttpResponseError as e:
231
print(f"HTTP error {e.status_code}: {e.message}")
232
if e.status_code == 413:
233
print("Event batch too large, try sending fewer events")
234
elif e.status_code == 400:
235
print("Invalid event format or missing required fields")
236
except ValueError as e:
237
print(f"Invalid event data: {e}")
238
```
239
240
## Event Formats
241
242
### CloudEvent Schema (Event Grid Namespaces)
243
244
CloudEvents v1.0 specification with required and optional fields:
245
246
```python
247
# Required fields
248
cloud_event = CloudEvent(
249
source="myapp/component", # Context in which event occurred
250
type="MyApp.Event.Happened", # Event type identifier
251
data={"key": "value"} # Event payload
252
)
253
254
# With optional fields
255
cloud_event = CloudEvent(
256
source="myapp/orders",
257
type="Order.StatusChanged",
258
data={
259
"order_id": "12345",
260
"old_status": "pending",
261
"new_status": "confirmed"
262
},
263
subject="orders/12345", # Event subject
264
time=datetime.utcnow(), # Event timestamp
265
datacontenttype="application/json" # Content type of data
266
)
267
```
268
269
### EventGrid Schema (Event Grid Basic)
270
271
Traditional EventGrid event format:
272
273
```python
274
eventgrid_event = EventGridEvent(
275
subject="products/product-123", # Required: Event subject
276
event_type="Product.PriceChanged", # Required: Event type
277
data={ # Required: Event data
278
"product_id": "123",
279
"old_price": 19.99,
280
"new_price": 24.99
281
},
282
data_version="2.0", # Required: Data schema version
283
topic="products", # Optional: Topic (auto-set by service)
284
id="event-456", # Optional: Event ID (auto-generated)
285
event_time=datetime.utcnow() # Optional: Event time (auto-generated)
286
)
287
```
288
289
### Raw Dictionary Events
290
291
Dictionaries are automatically converted based on target:
292
293
```python
294
# For namespaces (converted to CloudEvent)
295
namespace_dict = {
296
"specversion": "1.0", # Required for CloudEvent
297
"type": "MyApp.Event", # Required
298
"source": "myapp", # Required
299
"data": {"message": "hello"} # Event payload
300
}
301
302
# For basic topics (converted to EventGrid event)
303
basic_dict = {
304
"eventType": "Custom.Event", # Maps to event_type
305
"subject": "app/component", # Maps to subject
306
"data": {"key": "value"}, # Event data
307
"dataVersion": "1.0" # Maps to data_version
308
}
309
```