Enlace de salida de Azure Event Grid para Azure Functions

Use el enlace de salida de Event Hubs para escribir eventos en un tema personalizado. Debe tener una clave de acceso válida para el tema personalizado. El enlace de salida de Event Grid no es compatible con los tokens de firma de acceso compartido (SAS).

Para obtener información sobre los detalles de instalación y configuración, consulte Trabajo con desencadenadores y enlaces en Azure Functions.

Importante

En este artículo se usan pestañas para admitir varias versiones del modelo de programación de Node.js. El modelo v4 está disponible de forma general y está diseñado para que los desarrolladores de JavaScript y TypeScript tengan una experiencia más flexible e intuitiva. Para más detalles acerca de cómo funciona el modelo v4, consulte la Guía para desarrolladores de Node.js de Azure Functions. Para más información sobre las diferencias entre v3 y v4, consulte la Guía de migración.

Azure Functions admite dos modelos de programación para Python. La forma en que defina los enlaces depende del modelo de programación seleccionado.

El modelo de programación de Python v2 permite definir enlaces mediante decoradores directamente en el código de función de Python. Para más información, consulte la Guía para desarrolladores de Python.

En este artículo se admiten los modelos de programación.

Importante

El enlace de salida de Event Grid solo está disponible para Functions 2.x y versiones posteriores.

Ejemplo

El tipo del parámetro de salida usado con un enlace de salida de Event Grid depende de la versión de Functions Runtime, la versión de la extensión de enlace y la modalidad de la función de C#. La función de C# se puede crear mediante uno de los siguientes modos de C#:

En el ejemplo siguiente se muestra cómo se usa el tipo personalizado en el desencadenador y en un enlace de salida de Event Grid:

using System;
using System.Collections.Generic;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;

namespace SampleApp
{
    public static class EventGridFunction
    {
        [Function(nameof(EventGridFunction))]
        [EventGridOutput(TopicEndpointUri = "MyEventGridTopicUriSetting", TopicKeySetting = "MyEventGridTopicKeySetting")]
        public static MyEventType Run([EventGridTrigger] MyEventType input, FunctionContext context)
        {
            var logger = context.GetLogger(nameof(EventGridFunction));

            logger.LogInformation(input.Data.ToString());

            var outputEvent = new MyEventType()
            {
                Id = "unique-id",
                Subject = "abc-subject",
                Data = new Dictionary<string, object>
                {
                    { "myKey", "myValue" }
                }
            };

            return outputEvent;
        }
    }

    public class MyEventType
    {
        public string Id { get; set; }

        public string Topic { get; set; }

        public string Subject { get; set; }

        public string EventType { get; set; }

        public DateTime EventTime { get; set; }

        public IDictionary<string, object> Data { get; set; }
    }
}

El ejemplo siguiente muestra una función de Java que escribe un mensaje en un tema personalizado de Event Grid. La función usa el método setValue del enlace para generar una cadena.

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);
    }
}

También puede usar una clase POJO para enviar mensajes de Event Grid.

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;
    }  
}

En el ejemplo siguiente, se muestra una función TypeScript desencadenada por el temporizador, que devuelve un único evento:

import { app, EventGridPartialEvent, InvocationContext, output, Timer } from '@azure/functions';

export async function timerTrigger1(myTimer: Timer, context: InvocationContext): Promise<EventGridPartialEvent> {
    const timeStamp = new Date().toISOString();
    return {
        id: 'message-id',
        subject: 'subject-name',
        dataVersion: '1.0',
        eventType: 'event-type',
        data: {
            name: 'John Henry',
        },
        eventTime: timeStamp,
    };
}

app.timer('timerTrigger1', {
    schedule: '0 */5 * * * *',
    return: output.eventGrid({
        topicEndpointUri: 'MyEventGridTopicUriSetting',
        topicKeySetting: 'MyEventGridTopicKeySetting',
    }),
    handler: timerTrigger1,
});

Para generar varios eventos, devuelva una matriz en lugar de un objeto único. Por ejemplo:

const timeStamp = new Date().toISOString();
return [
    {
        id: 'message-id',
        subject: 'subject-name',
        dataVersion: '1.0',
        eventType: 'event-type',
        data: {
            name: 'John Henry',
        },
        eventTime: timeStamp,
    },
    {
        id: 'message-id-2',
        subject: 'subject-name',
        dataVersion: '1.0',
        eventType: 'event-type',
        data: {
            name: 'John Doe',
        },
        eventTime: timeStamp,
    },
];

En el ejemplo siguiente, se muestra una función JavaScript desencadenada por el temporizador, que devuelve un único evento:

const { app, output } = require('@azure/functions');

const eventGridOutput = output.eventGrid({
    topicEndpointUri: 'MyEventGridTopicUriSetting',
    topicKeySetting: 'MyEventGridTopicKeySetting',
});

app.timer('timerTrigger1', {
    schedule: '0 */5 * * * *',
    return: eventGridOutput,
    handler: (myTimer, context) => {
        const timeStamp = new Date().toISOString();
        return {
            id: 'message-id',
            subject: 'subject-name',
            dataVersion: '1.0',
            eventType: 'event-type',
            data: {
                name: 'John Henry',
            },
            eventTime: timeStamp,
        };
    },
});

Para generar varios eventos, devuelva una matriz en lugar de un objeto único. Por ejemplo:

const timeStamp = new Date().toISOString();
return [
    {
        id: 'message-id',
        subject: 'subject-name',
        dataVersion: '1.0',
        eventType: 'event-type',
        data: {
            name: 'John Henry',
        },
        eventTime: timeStamp,
    },
    {
        id: 'message-id-2',
        subject: 'subject-name',
        dataVersion: '1.0',
        eventType: 'event-type',
        data: {
            name: 'John Doe',
        },
        eventTime: timeStamp,
    },
];

En el ejemplo siguiente se muestra cómo configurar una función para generar un mensaje de evento de Event Grid. La sección donde type está establecida en eventGrid permite configurar los valores necesarios para establecer un enlace de salida de Event Grid.

{
  "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"
    }
  ]
}

En la función, use Push-OutputBinding para enviar un evento a un tema personalizado a través del enlace de salida de Event Grid.

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"
})

En el ejemplo siguiente se muestra un enlace de desencadenador y una función de Python que usa el enlace. Después, envía un evento al tema personalizado, tal y como se especifica en topicEndpointUri. El ejemplo depende de si usa el modelo de programación de Python v1 o v2.

Esta es la función del archivo function_app.py:

import logging
import azure.functions as func
import datetime

app = func.FunctionApp()

@app.function_name(name="eventgrid_output")
@app.event_grid_trigger(arg_name="eventGridEvent")
@app.event_grid_output(
    arg_name="outputEvent",
    topic_endpoint_uri="MyEventGridTopicUriSetting",
    topic_key_setting="MyEventGridTopicKeySetting")
def eventgrid_output(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"))

Atributos

Las bibliotecas de C# en proceso y de procesos de trabajo aislados usan un atributo para configurar el enlace. En su lugar, el script de C# usa un archivo de configuración function.json como se describe en la Guía de scripting de C#.

El constructor del atributo toma el nombre de un valor de la aplicación que contiene el nombre del tema personalizado, y el nombre de un valor de la aplicación que contiene la clave del tema.

En la tabla siguiente se explican los parámetros de EventGridOutputAttribute.

Parámetro Descripción
TopicEndpointUri Nombre de un valor de aplicación que contiene el URI para el tema personalizado, como MyTopicEndpointUri.
TopicKeySetting Nombre de un valor de aplicación que contiene una clave de acceso para el tema personalizado.
connection* Valor del prefijo común para la configuración que contiene el URI del punto de conexión del tema. Para más información sobre el formato de nomenclatura de esta configuración de la aplicación, consulte Autenticación basada en identidades.

anotaciones

Para las clases de Java, use el atributo EventGridAttribute.

El constructor del atributo toma el nombre de un valor de la aplicación que contiene el nombre del tema personalizado y el nombre de un valor de la aplicación que contiene la clave del tema. Para obtener más información sobre estas configuraciones, vea Salida: configuración. Este es un ejemplo de atributo EventGridOutput:

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) {
            ...
    }
}

Configuración

En la tabla siguiente se explican las propiedades que puede establecer en el objeto options que se pasa al métodooutput.eventGrid().

Propiedad Descripción
topicEndpointUri Nombre de un valor de aplicación que contiene el URI para el tema personalizado, como MyTopicEndpointUri.
topicKeySetting Nombre de un valor de aplicación que contiene una clave de acceso para el tema personalizado.
connection* Valor del prefijo común para la configuración que contiene el URI del punto de conexión del tema. Al establecer la propiedad connection, no se deben establecer las propiedades topicEndpointUri y topicKeySetting. Para más información sobre el formato de nomenclatura de esta configuración de la aplicación, consulte Autenticación basada en identidades.

Configuración

En la siguiente tabla se explican las propiedades de configuración de enlace que se establecen en el archivo function.json.

Propiedad de function.json Descripción
type Se debe establecer en eventGrid.
direction Se debe establecer en out. Este parámetro se establece automáticamente cuando se crea el enlace en Azure Portal.
name Nombre de la variable que se usa en el código de la función que representa el evento.
topicEndpointUri Nombre de un valor de aplicación que contiene el URI para el tema personalizado, como MyTopicEndpointUri.
topicKeySetting Nombre de un valor de aplicación que contiene una clave de acceso para el tema personalizado.
connection* Valor del prefijo común para la configuración que contiene el URI del punto de conexión del tema. Para más información sobre el formato de nomenclatura de esta configuración de la aplicación, consulte Autenticación basada en identidades.

*La compatibilidad con conexiones basadas en identidades requiere la versión 3.3.x o posterior de la extensión.

Cuando esté desarrollando localmente, agregue la configuración de la aplicación en el archivo local.settings.json de la colección Values.

Importante

Asegúrese de establecer el valor de TopicEndpointUri en el nombre de un valor de la aplicación que contenga el URI del tema personalizado. No especifique el URI del tema personalizado directamente en esta propiedad. Lo mismo sucede cuando se usa Connection.

Consulte la sección de ejemplos para ver ejemplos completos.

Uso

El tipo de parámetro admitido por el enlace de salida de Event Grid depende de la versión de Functions Runtime, la versión del paquete de extensión y la modalidad de C# utilizada.

Cuando quiera que la función escriba un único evento, el enlace de salida de Event Grid puede enlazarse a los siguientes tipos:

Tipo Descripción
string El evento como una cadena.
byte[] Bytes del mensaje de evento.
Tipos serializables con JSON Un objeto que representa un evento JSON. Functions intenta serializar un tipo de objeto CLR convencional (POCO) en datos JSON.

Cuando quiera que la función escriba varios eventos, el enlace de salida de Event Grid puede enlazarse a los siguientes tipos:

Tipo Descripción
T[] donde T es uno de los tipos de eventos únicos Matriz que contiene varios eventos. Cada entrada representa un evento.

Para otros escenarios de salida, cree y use tipos de Azure.Messaging.EventGrid directamente.

Envíe mensajes individuales mediante una llamada a un parámetro de método, como out EventGridOutput paramName, y escriba varios mensajes con ICollector<EventGridOutput>.

Acceda al mensaje de salida devolviendo el valor directamente o mediante context.extraOutputs.set().

Acceda al evento de salida mediante el cmdlet Push-OutputBinding para enviar un evento al enlace de salida de Event Grid.

Hay dos opciones para la generación de un mensaje de Event Grid desde una función:

  • Valor devuelto: Establezca la propiedad name de function.json en $return. Con esta configuración, el valor devuelto de la función se conserva como mensaje de Event Grid.
  • Imperativa: Pase un valor al método set del parámetro declarado como tipo Out. El valor pasado a set se conserva como mensaje de Event Grid.

Conexiones

Hay dos maneras de autenticarse en un tema de Event Grid al usar el enlace de salida de Event Grid:

Método de autenticación Descripción
Uso de una clave de tema Establezca las propiedades TopicEndpointUri y TopicKeySetting, como se describe en Uso de una clave de tema.
Uso de una identidad Establezca la propiedad Connection en el nombre de un prefijo compartido por varias configuraciones de la aplicación, que juntas definen una conexión basada en identidades. Este método se admite cuando se usa la versión 3.3.x o posterior de la extensión.

Uso de una clave de tema

Use los siguientes pasos para configurar una clave de tema:

  1. Siga los pasos descritos en Obtención de claves de acceso para obtener la clave del tema de Event Grid.

  2. En la configuración de la aplicación, cree un valor que defina el valor de la clave del tema. Use el nombre de este valor para la propiedad TopicKeySetting del enlace.

  3. En la configuración de la aplicación, cree un valor que defina el punto de conexión del tema. Use el nombre de este valor para la propiedad TopicEndpointUri del enlace.

Habilitación basada en identidad

Si usa la versión 3.3.x o posterior de la extensión, puede conectarse a un tema de Event Grid mediante una identidad de Microsoft Entra para evitar tener que obtener claves de tema y trabajar con ellas.

Debe crear una configuración de aplicación que devuelva el URI del punto de conexión del tema. El nombre de la configuración debe combinar un prefijo común único (por ejemplo, myawesometopic) con el valor __topicEndpointUri. A continuación, debe usar ese prefijo común (en este caso, myawesometopic) al definir la propiedad Connection en el enlace.

En este modo, la extensión requiere las siguientes propiedades:

Propiedad Plantilla de variable de entorno Descripción Valor de ejemplo
Identificador URI del punto de conexión del tema <CONNECTION_NAME_PREFIX>__topicEndpointUri Punto de conexión del tema. https://<topic-name>.centralus-1.eventgrid.azure.net/api/events

Se pueden usar más propiedades para personalizar la conexión. Consulte Propiedades comunes para conexiones basadas en identidades.

Nota:

Al usar Azure App Configuration o Key Vault para proporcionar la configuración de las conexiones de identidad administrada, los nombres de los valores deben usar un separador de clave válido, como : o / en lugar de __ para asegurarse de que los nombres se resuelven correctamente.

Por ejemplo, <CONNECTION_NAME_PREFIX>:topicEndpointUri.

Cuando se hospeda en el servicio de Azure Functions, las conexiones basadas en identidades usan una identidad administrada. La identidad asignada por el sistema se usa de manera predeterminada, aunque se puede especificar una identidad asignada por el usuario con las propiedades credential y clientID. Tenga en cuenta que no se admite la configuración de una identidad asignada por el usuario con un identificador de recurso. Cuando se ejecuta en otros contextos, como el de desarrollo local, se usa en su lugar la identidad del desarrollador, aunque se puede personalizar. Consulte Desarrollo local con conexiones basadas en identidades.

Concesión de permiso a la identidad

Cualquier identidad que se utilice debe tener permisos para realizar las acciones previstas. Para la mayoría de los servicios de Azure, esto significa que debe asignar un rol en Azure RBAC mediante roles integrados o personalizados que proporcionen esos permisos.

Importante

Es posible que el servicio de destino muestre algunos permisos que no son necesarios para todos los contextos. Siempre que sea posible, respete el principio de privilegios mínimos y conceda solo los privilegios necesarios a la identidad. Por ejemplo, si la aplicación solo necesita poder leer desde un origen de datos, use un rol que solo tenga permiso de lectura. Sería inadecuado asignar un rol que también permita escribir en ese servicio, ya que sería un permiso excesivo para una operación de lectura. De forma similar, le interesa asegurarse de que la asignación de roles esté limitada solo a los recursos que se deben leer.

Debe crear una asignación de roles que dé acceso al tema de Event Grid en tiempo de ejecución. Los roles de administración, como Propietario, no son suficientes. En la tabla siguiente se muestran los roles integrados que se recomiendan al usar la extensión de Event Hubs con un funcionamiento normal. Puede que la aplicación precise permisos adicionales en función del código que escriba.

Tipo de enlace Roles integrados de ejemplo
Enlace de salida Colaborador de EventGrid, Emisor de datos de EventGrid

Pasos siguientes