Azure.Messaging.EventGrid (.NET)
Biblioteca cliente para publicar eventos em tópicos, domínios e namespaces do Azure Event Grid.
Instalação
dotnet add package Azure.Messaging.EventGrid
dotnet add package Azure.Messaging.EventGrid.Namespaces
dotnet add package Microsoft.Azure.Messaging.EventGrid.CloudNativeCloudEvents
Versão Atual: 4.28.0 (estável)
Variáveis de Ambiente
EVENT_GRID_TOPIC_ENDPOINT=https://<nome-do-topico>.<regiao>.eventgrid.azure.net/api/events
EVENT_GRID_TOPIC_KEY=<chave-de-acesso>
EVENT_GRID_NAMESPACE_ENDPOINT=https://<namespace>.<regiao>.eventgrid.azure.net
EVENT_GRID_TOPIC_NAME=<nome-do-topico>
EVENT_GRID_SUBSCRIPTION_NAME=<nome-da-assinatura>
AZURE_TOKEN_CREDENTIALS=prod
Hierarquia de Clientes
Entrega por Push (Tópicos/Domínios)
└── EventGridPublisherClient
├── SendEventAsync(EventGridEvent)
├── SendEventsAsync(IEnumerable<EventGridEvent>)
├── SendEventAsync(CloudEvent)
└── SendEventsAsync(IEnumerable<CloudEvent>)
Entrega por Pull (Namespaces)
├── EventGridSenderClient
│ └── SendAsync(CloudEvent)
└── EventGridReceiverClient
├── ReceiveAsync()
├── AcknowledgeAsync()
├── ReleaseAsync()
└── RejectAsync()
Autenticação
Autenticação por Chave de API
using Azure;
using Azure.Messaging.EventGrid;
EventGridPublisherClient client = new(
new Uri("https://mytopic.eastus-1.eventgrid.azure.net/api/events"),
new AzureKeyCredential("<chave-de-acesso>"));
Credencial de Token Microsoft Entra
using Azure.Identity;
using Azure.Messaging.EventGrid;
var credential = new DefaultAzureCredential(
DefaultAzureCredential.DefaultEnvironmentVariableName
);
EventGridPublisherClient client = new(
new Uri("https://mytopic.eastus-1.eventgrid.azure.net/api/events"),
credential);
Autenticação por Token SAS
string sasToken = EventGridPublisherClient.BuildSharedAccessSignature(
new Uri(topicEndpoint),
DateTimeOffset.UtcNow.AddHours(1),
new AzureKeyCredential(topicKey));
var sasCredential = new AzureSasCredential(sasToken);
EventGridPublisherClient client = new(
new Uri(topicEndpoint),
sasCredential);
Publicando Eventos
Esquema EventGridEvent
EventGridPublisherClient client = new(
new Uri(topicEndpoint),
new AzureKeyCredential(topicKey));
EventGridEvent egEvent = new(
subject: "orders/12345",
eventType: "Order.Created",
dataVersion: "1.0",
data: new { OrderId = "12345", Amount = 99.99 });
await client.SendEventAsync(egEvent);
List<EventGridEvent> events = new()
{
new EventGridEvent(
subject: "orders/12345",
eventType: "Order.Created",
dataVersion: "1.0",
data: new OrderData { OrderId = "12345", Amount = 99.99 }),
new EventGridEvent(
subject: "orders/12346",
eventType: "Order.Created",
dataVersion: "1.0",
data: new OrderData { OrderId = "12346", Amount = 149.99 })
};
await client.SendEventsAsync(events);
Esquema CloudEvent
CloudEvent cloudEvent = new(
source: "/orders/system",
type: "Order.Created",
data: new { OrderId = "12345", Amount = 99.99 });
cloudEvent.Subject = "orders/12345";
cloudEvent.Id = Guid.NewGuid().ToString();
cloudEvent.Time = DateTimeOffset.UtcNow;
await client.SendEventAsync(cloudEvent);
List<CloudEvent> cloudEvents = new()
{
new CloudEvent("/orders", "Order.Created", new { OrderId = "1" }),
new CloudEvent("/orders", "Order.Updated", new { OrderId = "2" })
};
await client.SendEventsAsync(cloudEvents);
Publicando em um Domínio do Event Grid
List<EventGridEvent> events = new()
{
new EventGridEvent(
subject: "orders/12345",
eventType: "Order.Created",
dataVersion: "1.0",
data: new { OrderId = "12345" })
{
Topic = "orders-topic"
},
new EventGridEvent(
subject: "inventory/item-1",
eventType: "Inventory.Updated",
dataVersion: "1.0",
data: new { ItemId = "item-1" })
{
Topic = "inventory-topic"
}
};
await client.SendEventsAsync(events);
Serialização Personalizada
using System.Text.Json;
var serializerOptions = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
var customSerializer = new JsonObjectSerializer(serializerOptions);
EventGridEvent egEvent = new(
subject: "orders/12345",
eventType: "Order.Created",
dataVersion: "1.0",
data: customSerializer.Serialize(new OrderData { OrderId = "12345" }));
await client.SendEventAsync(egEvent);
Entrega por Pull (Namespaces)
Envio de Eventos para Tópico de Namespace
using Azure;
using Azure.Messaging;
using Azure.Messaging.EventGrid.Namespaces;
var senderClient = new EventGridSenderClient(
new Uri(namespaceEndpoint),
topicName,
new AzureKeyCredential(topicKey));
CloudEvent cloudEvent = new("employee_source", "Employee.Created",
new { Name = "John", Age = 30 });
await senderClient.SendAsync(cloudEvent);
await senderClient.SendAsync(new[]
{
new CloudEvent("source", "type", new { Name = "Alice" }),
new CloudEvent("source", "type", new { Name = "Bob" })
});
Recebimento e Processamento de Eventos
var receiverClient = new EventGridReceiverClient(
new Uri(namespaceEndpoint),
topicName,
subscriptionName,
new AzureKeyCredential(topicKey));
ReceiveResult result = await receiverClient.ReceiveAsync(maxEvents: 10);
List<string> tokensBloqueioParaConfirmar = new();
List<string> tokensBloqueioParaLiberar = new();
foreach (ReceiveDetails detail in result.Details)
{
CloudEvent cloudEvent = detail.Event;
string lockToken = detail.BrokerProperties.LockToken;
try
{
Console.WriteLine($"Evento: {cloudEvent.Type}, Dados: {cloudEvent.Data}");
tokensBloqueioParaConfirmar.Add(lockToken);
}
catch (Exception)
{
tokensBloqueioParaLiberar.Add(lockToken);
}
}
if (tokensBloqueioParaConfirmar.Any())
{
await receiverClient.AcknowledgeAsync(tokensBloqueioParaConfirmar);
}
if (tokensBloqueioParaLiberar.Any())
{
await receiverClient.ReleaseAsync(tokensBloqueioParaLiberar);
}
Rejeitar Eventos (Dead Letter)
await receiverClient.RejectAsync(new[] { lockToken });
Consumindo Eventos (Azure Functions)
Gatilho EventGridEvent
using Azure.Messaging.EventGrid;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.EventGrid;
public static class EventGridFunction
{
[FunctionName("ProcessEventGridEvent")]
public static void Run(
[EventGridTrigger] EventGridEvent eventGridEvent,
ILogger log)
{
log.LogInformation($"Tipo do Evento: {eventGridEvent.EventType}");
log.LogInformation($"Assunto: {eventGridEvent.Subject}");
log.LogInformation($"Dados: {eventGridEvent.Data}");
}
}
Gatilho CloudEvent
using Azure.Messaging;
using Microsoft.Azure.Functions.Worker;
public class CloudEventFunction
{
[Function("ProcessCloudEvent")]
public void Run(
[EventGridTrigger] CloudEvent cloudEvent,
FunctionContext context)
{
var logger = context.GetLogger("ProcessCloudEvent");
logger.LogInformation($"Tipo do Evento: {cloudEvent.Type}");
logger.LogInformation($"Fonte: {cloudEvent.Source}");
logger.LogInformation($"Dados: {cloudEvent.Data}");
}
}
Análise de Eventos
Analisar EventGridEvent
string json = "...";
EventGridEvent[] events = EventGridEvent.ParseMany(BinaryData.FromString(json));
foreach (EventGridEvent egEvent in events)
{
if (egEvent.TryGetSystemEventData(out object systemEvent))
{
switch (systemEvent)
{
case StorageBlobCreatedEventData blobCreated:
Console.WriteLine($"Blob criado: {blobCreated.Url}");
break;
}
}
else
{
var customData = egEvent.Data.ToObjectFromJson<MyCustomData>();
}
}
Analisar CloudEvent
CloudEvent[] cloudEvents = CloudEvent.ParseMany(BinaryData.FromString(json));
foreach (CloudEvent cloudEvent in cloudEvents)
{
var data = cloudEvent.Data.ToObjectFromJson<MyEventData>();
Console.WriteLine($"Tipo: {cloudEvent.Type}, Dados: {data}");
}
Eventos do Sistema
using Azure.Messaging.EventGrid.SystemEvents;
StorageBlobCreatedEventData blobCreated;
StorageBlobDeletedEventData blobDeleted;
ResourceWriteSuccessEventData resourceCreated;
ResourceDeleteSuccessEventData resourceDeleted;
WebAppUpdatedEventData webAppUpdated;
ContainerRegistryImagePushedEventData imagePushed;
IotHubDeviceCreatedEventData deviceCreated;
Referência de Tipos Principais
| Tipo | Finalidade |
|---|
EventGridPublisherClient | Publicar em tópicos/domínios |
EventGridSenderClient | Enviar para tópicos de namespace |
EventGridReceiverClient | Receber de assinaturas de namespace |
EventGridEvent | Esquema nativo do Event Grid |
CloudEvent | Esquema CloudEvents 1.0 |
ReceiveResult | Resposta de entrega por pull |
ReceiveDetails | Evento com propriedades do broker |
BrokerProperties | Token de bloqueio, contagem de entrega |
Comparação de Esquemas de Evento
| Funcionalidade | EventGridEvent | CloudEvent |
|---|
| Padrão | Específico do Azure | Padrão CNCF |
| Campos obrigatórios | subject, eventType, dataVersion, data | source, type |
| Extensibilidade | Limitada | Atributos de extensão |
| Interoperabilidade | Apenas Azure | Multiplataforma |
Melhores Práticas
- Use CloudEvents — Prefira CloudEvents para novas implementações (padrão da indústria)
- Lote de eventos — Envie múltiplos eventos em uma única chamada para eficiência
- Use Entra ID — Prefira identidade gerenciada em vez de chaves de acesso
- Manipuladores idempotentes — Eventos podem ser entregues mais de uma vez
- Defina TTL do evento — Configure o time-to-live para eventos de namespace
- Lide com falhas parciais — Confirme/libere eventos individualmente
- Use dead-letter — Configure dead-letter para eventos com falha
- Valide esquemas — Valide os dados do evento antes do processamento
Tratamento de Erros
using Azure;
try
{
await client.SendEventAsync(cloudEvent);
}
catch (RequestFailedException ex) when (ex.Status == 401)
{
Console.WriteLine("Falha na autenticação - verifique as credenciais");
}
catch (RequestFailedException ex) when (ex.Status == 403)
{
Console.WriteLine("Falha na autorização - verifique as permissões RBAC");
}
catch (RequestFailedException ex) when (ex.Status == 413)
{
Console.WriteLine("Payload muito grande - máximo 1MB por evento, 1MB total do lote");
}
catch (RequestFailedException ex)
{
Console.WriteLine($"Erro do Event Grid: {ex.Status} - {ex.Message}");
}
Padrão de Failover
try
{
var primaryClient = new EventGridPublisherClient(primaryUri, primaryKey);
await primaryClient.SendEventsAsync(events);
}
catch (RequestFailedException)
{
var secondaryClient = new EventGridPublisherClient(secondaryUri, secondaryKey);
await secondaryClient.SendEventsAsync(events);
}
SDKs Relacionados
| SDK | Finalidade | Instalação |
|---|
Azure.Messaging.EventGrid | Tópicos/Domínios (este SDK) | dotnet add package Azure.Messaging.EventGrid |
Azure.Messaging.EventGrid.Namespaces | Entrega por pull | dotnet add package Azure.Messaging.EventGrid.Namespaces |
Azure.Identity | Autenticação | dotnet add package Azure.Identity |
Microsoft.Azure.WebJobs.Extensions.EventGrid | Gatilho Azure Functions | dotnet add package Microsoft.Azure.WebJobs.Extensions.EventGrid |
Links de Referência