Skip to content

Latest commit

 

History

History
541 lines (420 loc) · 18.8 KB

functions-bindings-event-grid-output.md

File metadata and controls

541 lines (420 loc) · 18.8 KB
title description author ms.topic ms.date ms.author ms.custom
Azure Event Grid output binding for Azure Functions
Learn to send an Event Grid event in Azure Functions.
craigshoemaker
reference
02/14/2020
cshoe
devx-track-csharp, fasttrack-edit, devx-track-python

Azure Event Grid output binding for Azure Functions

Use the Event Grid output binding to write events to a custom topic. You must have a valid access key for the custom topic.

For information on setup and configuration details, see the overview.

Note

The Event Grid output binding does not support shared access signatures (SAS tokens). You must use the topic's access key.

Important

The Event Grid output binding is only available for Functions 2.x and higher.

Example

C# (2.x and higher)

The following example shows a C# function that writes a message to an Event Grid custom topic, using the method return value as the output:

[FunctionName("EventGridOutput")]
[return: EventGrid(TopicEndpointUri = "MyEventGridTopicUriSetting", TopicKeySetting = "MyEventGridTopicKeySetting")]
public static EventGridEvent Run([TimerTrigger("0 */5 * * * *")] TimerInfo myTimer, ILogger log)
{
    return new EventGridEvent("message-id", "subject-name", "event-data", "event-type", DateTime.UtcNow, "1.0");
}

The following example shows how to use the IAsyncCollector interface to send a batch of messages.

[FunctionName("EventGridAsyncOutput")]
public static async Task Run(
    [TimerTrigger("0 */5 * * * *")] TimerInfo myTimer,
    [EventGrid(TopicEndpointUri = "MyEventGridTopicUriSetting", TopicKeySetting = "MyEventGridTopicKeySetting")]IAsyncCollector<EventGridEvent> outputEvents,
    ILogger log)
{
    for (var i = 0; i < 3; i++)
    {
        var myEvent = new EventGridEvent("message-id-" + i, "subject-name", "event-data", "event-type", DateTime.UtcNow, "1.0");
        await outputEvents.AddAsync(myEvent);
    }
}

Version 3.x (preview)

The following example shows a Functions 3.x C# function that binds to a CloudEvent:

using System.Threading.Tasks;
using Azure.Messaging;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.EventGrid;
using Microsoft.Azure.WebJobs.Extensions.Http;

namespace Azure.Extensions.WebJobs.Sample
{
    public static class CloudEventBindingFunction
    {
        [FunctionName("CloudEventBindingFunction")]
        public static async Task<IActionResult> RunAsync(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
            [EventGrid(TopicEndpointUri = "EventGridEndpoint", TopicKeySetting = "EventGridKey")] IAsyncCollector<CloudEvent> eventCollector)
        {
            CloudEvent e = new CloudEvent("IncomingRequest", "IncomingRequest", await req.ReadAsStringAsync());
            await eventCollector.AddAsync(e);
            return new OkResult();
        }
    }
}

The following example shows a Functions 3.x C# function that binds to an EventGridEvent:

using System.Threading.Tasks;
using Azure.Messaging.EventGrid;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Extensions.EventGrid;

namespace Azure.Extensions.WebJobs.Sample
{
    public static class EventGridEventBindingFunction
    {
        [FunctionName("EventGridEventBindingFunction")]
        public static async Task<IActionResult> RunAsync(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
            [EventGrid(TopicEndpointUri = "EventGridEndpoint", TopicKeySetting = "EventGridKey")] IAsyncCollector<EventGridEvent> eventCollector)
        {
            EventGridEvent e = new EventGridEvent(await req.ReadAsStringAsync(), "IncomingRequest", "IncomingRequest", "1.0.0");
            await eventCollector.AddAsync(e);
            return new OkResult();
        }
    }
}

The following example shows the Event Grid output binding data in the function.json file.

{
    "type": "eventGrid",
    "name": "outputEvent",
    "topicEndpointUri": "MyEventGridTopicUriSetting",
    "topicKeySetting": "MyEventGridTopicKeySetting",
    "direction": "out"
}

Here's C# script code that creates one event:

#r "Microsoft.Azure.EventGrid"
using System;
using Microsoft.Azure.EventGrid.Models;
using Microsoft.Extensions.Logging;

public static void Run(TimerInfo myTimer, out EventGridEvent outputEvent, ILogger log)
{
    outputEvent = new EventGridEvent("message-id", "subject-name", "event-data", "event-type", DateTime.UtcNow, "1.0");
}

Here's C# script code that creates multiple events:

#r "Microsoft.Azure.EventGrid"
using System;
using Microsoft.Azure.EventGrid.Models;
using Microsoft.Extensions.Logging;

public static void Run(TimerInfo myTimer, ICollector<EventGridEvent> outputEvent, ILogger log)
{
    outputEvent.Add(new EventGridEvent("message-id-1", "subject-name", "event-data", "event-type", DateTime.UtcNow, "1.0"));
    outputEvent.Add(new EventGridEvent("message-id-2", "subject-name", "event-data", "event-type", DateTime.UtcNow, "1.0"));
}

The following example shows a Java function that writes a message to an Event Grid custom topic. The function uses the binding's setValue method to output a string.

public class Function {
    @FunctionName("EventGridTriggerTest")
    public void run(@EventGridTrigger(name = "event") String content,
            @EventGridOutput(name = "outputEvent", topicEndpointUri = "MyEventGridTopicUriSetting", topicKeySetting = "MyEventGridTopicKeySetting") OutputBinding<String> outputEvent,
            final ExecutionContext context) {
        context.getLogger().info("Java EventGrid trigger processed a request." + content);
        final String eventGridOutputDocument = "{\"id\": \"1807\", \"eventType\": \"recordInserted\", \"subject\": \"myapp/cars/java\", \"eventTime\":\"2017-08-10T21:03:07+00:00\", \"data\": {\"make\": \"Ducati\",\"model\": \"Monster\"}, \"dataVersion\": \"1.0\"}";
        outputEvent.setValue(eventGridOutputDocument);
    }
}

You can also use a POJO class to send EventGrid messages.

public class Function {
    @FunctionName("EventGridTriggerTest")
    public void run(@EventGridTrigger(name = "event") String content,
            @EventGridOutput(name = "outputEvent", topicEndpointUri = "MyEventGridTopicUriSetting", topicKeySetting = "MyEventGridTopicKeySetting") OutputBinding<EventGridEvent> outputEvent,
            final ExecutionContext context) {
        context.getLogger().info("Java EventGrid trigger processed a request." + content);

        final EventGridEvent eventGridOutputDocument = new EventGridEvent();
        eventGridOutputDocument.setId("1807");
        eventGridOutputDocument.setEventType("recordInserted");
        eventGridOutputDocument.setEventTime("2017-08-10T21:03:07+00:00");
        eventGridOutputDocument.setDataVersion("1.0");
        eventGridOutputDocument.setSubject("myapp/cars/java");
        eventGridOutputDocument.setData("{\"make\": \"Ducati\",\"model\":\"monster\"");

        outputEvent.setValue(eventGridOutputDocument);
    }
}

class EventGridEvent {
    private String id;
    private String eventType;
    private String subject;
    private String eventTime;
    private String dataVersion;
    private String data;

    public String getId() {
        return id;
    }

    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }

    public String getDataVersion() {
        return dataVersion;
    }

    public void setDataVersion(String dataVersion) {
        this.dataVersion = dataVersion;
    }

    public String getEventTime() {
        return eventTime;
    }

    public void setEventTime(String eventTime) {
        this.eventTime = eventTime;
    }

    public String getSubject() {
        return subject;
    }

    public void setSubject(String subject) {
        this.subject = subject;
    }

    public String getEventType() {
        return eventType;
    }

    public void setEventType(String eventType) {
        this.eventType = eventType;
    }

    public void setId(String id) {
        this.id = id;
    }  
}

The following example shows the Event Grid output binding data in the function.json file.

{
    "type": "eventGrid",
    "name": "outputEvent",
    "topicEndpointUri": "MyEventGridTopicUriSetting",
    "topicKeySetting": "MyEventGridTopicKeySetting",
    "direction": "out"
}

Here's JavaScript code that creates a single event:

module.exports = async function (context, myTimer) {
    var timeStamp = new Date().toISOString();

    context.bindings.outputEvent = {
        id: 'message-id',
        subject: 'subject-name',
        dataVersion: '1.0',
        eventType: 'event-type',
        data: "event-data",
        eventTime: timeStamp
    };
    context.done();
};

Here's JavaScript code that creates multiple events:

module.exports = function(context) {
    var timeStamp = new Date().toISOString();

    context.bindings.outputEvent = [];

    context.bindings.outputEvent.push({
        id: 'message-id-1',
        subject: 'subject-name',
        dataVersion: '1.0',
        eventType: 'event-type',
        data: "event-data",
        eventTime: timeStamp
    });
    context.bindings.outputEvent.push({
        id: 'message-id-2',
        subject: 'subject-name',
        dataVersion: '1.0',
        eventType: 'event-type',
        data: "event-data",
        eventTime: timeStamp
    });
    context.done();
};

The following example demonstrates how to configure a function to output an Event Grid event message. The section where type is set to eventGrid configures the values needed to establish an Event Grid output binding.

{
  "bindings": [
    {
      "type": "eventGrid",
      "name": "outputEvent",
      "topicEndpointUri": "MyEventGridTopicUriSetting",
      "topicKeySetting": "MyEventGridTopicKeySetting",
      "direction": "out"
    },
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "Request",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "Response"
    }
  ]
}

In your function, use the Push-OutputBinding to send an event to a custom topic through the Event Grid output binding.

using namespace System.Net

# Input bindings are passed in via param block.
param($Request,$TriggerMetadata)

# Write to the Azure Functions log stream.
Write-Host"PowerShell HTTP trigger function processed a request."

# Interact with query parameters or the body of the request.
$message=$Request.Query.Message

Push-OutputBinding-Name outputEvent -Value  @{
    id ="1"
    EventType ="testEvent"
    Subject ="testapp/testPublish"
    EventTime ="2020-08-27T21:03:07+00:00"
    Data=@{
        Message =$message
    }
    DataVersion ="1.0"
}

Push-OutputBinding-Name Response -Value ([HttpResponseContext]@{
    StatusCode =200
    Body ="OK"
})

The following example shows a trigger binding in a function.json file and a Python function that uses the binding. It then sends in an event to the custom topic, as specified by the topicEndpointUri.

Here's the binding data in the function.json file:

{
  "scriptFile": "__init__.py",
  "bindings": [
    {
      "type": "eventGridTrigger",
      "name": "eventGridEvent",
      "direction": "in"
    },
    {
      "type": "eventGrid",
      "name": "outputEvent",
      "topicEndpointUri": "MyEventGridTopicUriSetting",
      "topicKeySetting": "MyEventGridTopicKeySetting",
      "direction": "out"
    }
  ],
  "disabled": false
}

Here's the Python sample to send an event to a custom topic by setting the EventGridOutputEvent:

import logging
import azure.functions as func
import datetime

def main(eventGridEvent: func.EventGridEvent, 
         outputEvent: func.Out[func.EventGridOutputEvent]) -> None:

    logging.log("eventGridEvent: ", eventGridEvent)

    outputEvent.set(
        func.EventGridOutputEvent(
            id="test-id",
            data={"tag1": "value1", "tag2": "value2"},
            subject="test-subject",
            event_type="test-event-1",
            event_time=datetime.datetime.utcnow(),
            data_version="1.0"))

Attributes and annotations

For C# class libraries, use the EventGridAttribute attribute.

The attribute's constructor takes the name of an app setting that contains the name of the custom topic, and the name of an app setting that contains the topic key. For more information about these settings, see Output - configuration. Here's an EventGrid attribute example:

[FunctionName("EventGridOutput")]
[return: EventGrid(TopicEndpointUri = "MyEventGridTopicUriSetting", TopicKeySetting = "MyEventGridTopicKeySetting")]
public static string Run([TimerTrigger("0 */5 * * * *")] TimerInfo myTimer, ILogger log)
{
    ...
}

For a complete example, see example.

Attributes are not supported by C# Script.

For Java classes, use the EventGridAttribute attribute.

The attribute's constructor takes the name of an app setting that contains the name of the custom topic, and the name of an app setting that contains the topic key. For more information about these settings, see Output - configuration. Here's an EventGridOutput attribute example:

public class Function {
    @FunctionName("EventGridTriggerTest")
    public void run(@EventGridTrigger(name = "event") String content,
            @EventGridOutput(name = "outputEvent", topicEndpointUri = "MyEventGridTopicUriSetting", topicKeySetting = "MyEventGridTopicKeySetting") OutputBinding<String> outputEvent, final ExecutionContext context) {
            ...
    }
}

Attributes are not supported by JavaScript.

Attributes are not supported by PowerShell.

Attributes are not supported by Python.


Configuration

The following table explains the binding configuration properties that you set in the function.json file and the EventGrid attribute.

function.json property Attribute property Description
type n/a Must be set to "eventGrid".
direction n/a Must be set to "out". This parameter is set automatically when you create the binding in the Azure portal.
name n/a The variable name used in function code that represents the event.
topicEndpointUri TopicEndpointUri The name of an app setting that contains the URI for the custom topic, such as MyTopicEndpointUri.
topicKeySetting TopicKeySetting The name of an app setting that contains an access key for the custom topic.

[!INCLUDE app settings to local.settings.json]

Important

Ensure that you set the value of the TopicEndpointUri configuration property to the name of an app setting that contains the URI of the custom topic. Do not specify the URI of the custom topic directly in this property.

Usage

Send messages by using a method parameter such as out EventGridEvent paramName. To write multiple messages, you can use ICollector<EventGridEvent> or IAsyncCollector<EventGridEvent> in place of out EventGridEvent.

Additional types

Apps using the 3.0.0 or higher version of the Event Grid extension use the EventGridEvent type from the Azure.Messaging.EventGrid namespace. In addition, you can bind to the CloudEvent type from the Azure.Messaging namespace.

Send messages by using a method parameter such as out EventGridEvent paramName. In C# script, paramName is the value specified in the name property of function.json. To write multiple messages, you can use ICollector<EventGridEvent> or IAsyncCollector<EventGridEvent> in place of out EventGridEvent.

Additional types

Apps using the 3.0.0 or higher version of the Event Grid extension use the EventGridEvent type from the Azure.Messaging.EventGrid namespace. In addition, you can bind to the CloudEvent type from the Azure.Messaging namespace.

Send individual messages by calling a method parameter such as out EventGridOutput paramName, and write multiple messages with ICollector<EventGridOutput> .

Access the output event by using context.bindings.<name> where <name> is the value specified in the name property of function.json.

Access the output event by using the Push-OutputBinding commandlet to send an event to the Event Grid output binding.

There are two options for outputting an Event Grid message from a function:

  • Return value: Set the name property in function.json to $return. With this configuration, the function's return value is persisted as an EventGrid message.
  • Imperative: Pass a value to the set method of the parameter declared as an Out type. The value passed to set is persisted as an EventGrid message.

Next steps