Azure Functions の Azure Event Grid 出力バインディング

イベントをカスタム トピックに書き込むには、Event Grid 出力バインディングを使用します。 有効なカスタム トピックのアクセス キーが必要です。 Event Grid 出力バインディングでは、Shared Access Signature (SAS トークン) はサポートされていません。

セットアップと構成の詳細については、「How to work with Event Grid triggers and bindings in Azure Functions」を参照してください。

重要

この記事では、タブを使用して、Node.js プログラミング モデルの複数のバージョンに対応しています。 v4 モデルは一般提供されており、JavaScript と TypeScript の開発者にとって、より柔軟で直感的なエクスペリエンスが得られるように設計されています。 v4 モデルの動作の詳細については、Azure Functions Node.js 開発者ガイドを参照してください。 v3 と v4 の違いの詳細については、移行ガイドを参照してください。

Azure Functions では、Python の 2 つのプログラミング モデルがサポートされています。 バインドを定義する方法は、選択したプログラミング モデルによって異なります。

Python v2 プログラミング モデルでは、Python 関数コードでデコレーターを使用してバインドを直接定義できます。 詳細については、「Python 開発者ガイド」を参照してください。

この記事は、両方のプログラミング モデルをサポートしています。

重要

Event Grid 出力バインディングは、Functions 2.x 以降でのみ使用することができます。

Event Grid 出力バインディングで使用される出力パラメーターの型は、Functions ランタイムのバージョン、バインディング拡張機能のバージョン、および C# 関数のモダリティによって異なります。 C# 関数は、次の C# モードのいずれかを使用して作成できます。

次の例は、トリガーと 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; }
    }
}

次の例は、メッセージを Event Grid カスタム トピックに書き込む Java 関数を示しています。 この関数では、バインドの setValue メソッドを使用して文字列を出力します。

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

POJO クラスを使用して EventGrid メッセージを送信することもできます。

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

次の例は、タイマーによってトリガーされ、1 つのイベントを出力する TypeScript 関数 を示しています。

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

複数のイベントを出力するには、1 つのオブジェクトではなく配列を返します。 次に例を示します。

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

次の例は、タイマーによってトリガーされ、1 つのイベントを出力する JavaScript 関数 を示しています。

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

複数のイベントを出力するには、1 つのオブジェクトではなく配列を返します。 次に例を示します。

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

次の例は、Event Grid イベント メッセージを出力するように関数を構成する方法を示しています。 typeeventGrid に設定されているセクションでは、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"
    }
  ]
}

関数では、Push-OutputBinding を使用して、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"
})

次の例は、トリガー バインドと、そのバインドが使用される Python 関数を示しています。 次に、topicEndpointUri によって指定されたとおり、イベントがカスタム トピックに送信されます。 この例は、v1 と v2 のどちらの Python プログラミング モデルを使用するかによって異なります。

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

属性

インプロセス分離ワーカー プロセスの C# ライブラリはどちらも、属性を使用してバインドを構成します。 C# スクリプトでは、C# スクリプト ガイドで説明されているように、代わりに function.json 構成ファイルを使用します。

属性のコンストラクターは、カスタム トピックの名前を含むアプリ設定の名前と、トピック キーを含むアプリ設定の名前を受け取ります。

次の表は、EventGridOutputAttribute のパラメーターを説明したものです。

パラメーター 説明
TopicEndpointUri カスタム トピックの URI を含むアプリ設定の名前 (例: MyTopicEndpointUri)。
TopicKeySetting カスタム トピックのアクセス キーを含むアプリ設定の名前。
connection* トピック エンドポイント URI を含む設定の共通プレフィックスの値。 このアプリケーション設定の名前付け形式の詳細については、「ID ベースの認証」を参照してください。

注釈

Java クラスでは、EventGridAttribute 属性を使用します。

属性のコンストラクターは、カスタム トピックの名前を含むアプリ設定の名前と、トピック キーを含むアプリ設定の名前を受け取ります。 これらの設定の詳細については、「出力 - 構成」を参照してください。 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) {
            ...
    }
}

構成

次の表では、output.eventGrid() メソッドに渡される options オブジェクトに対して設定できるプロパティについて説明します。

プロパティ 説明
topicEndpointUri カスタム トピックの URI を含むアプリ設定の名前 (例: MyTopicEndpointUri)。
topicKeySetting カスタム トピックのアクセス キーを含むアプリ設定の名前。
connection* トピック エンドポイント URI を含む設定の共通プレフィックスの値。 connection プロパティを設定するときは、topicEndpointUritopicKeySetting のプロパティは設定しないでください。 このアプリケーション設定の名前付け形式の詳細については、「ID ベースの認証」を参照してください。

構成

次の表は、function.json ファイルで設定したバインド構成のプロパティを説明しています。

function.json のプロパティ 説明
type eventGrid に設定する必要があります。
direction out に設定する必要があります。 このパラメーターは、Azure Portal でバインドを作成するときに自動で設定されます。
name イベントを表す関数コードに使用される変数の名前。
topicEndpointUri カスタム トピックの URI を含むアプリ設定の名前 (例: MyTopicEndpointUri)。
topicKeySetting カスタム トピックのアクセス キーを含むアプリ設定の名前。
connection* トピック エンドポイント URI を含む設定の共通プレフィックスの値。 このアプリケーション設定の名前付け形式の詳細については、「ID ベースの認証」を参照してください。

*ID ベースの接続をサポートするには、バージョン 3.3.x 以降の拡張機能が必要です。

ローカルで開発する場合は、Values コレクション内の local.settings.json ファイルにアプリケーション設定を追加します。

重要

TopicEndpointUri の値を、カスタム トピックの URI を含むアプリ設定の名前に設定してください。 このプロパティにカスタム トピックの URI を直接指定しないでください。 Connection を使用する場合も同じことが当てはまります。

完全な例については、セクションの例を参照してください。

使用方法

Event Grid 出力バインディングでサポートされるパラメーター型は、Functions ランタイムのバージョン、拡張機能パッケージのバージョン、および使用される C# のモダリティによって異なります。

関数で 1 つのイベントを書き込むとき、Event Grid 出力バインドは次の型にバインドできます。

Type 説明
string 文字列としてのイベント。
byte[] イベント メッセージのバイト数。
JSON シリアル化可能な型 JSON イベントを表すオブジェクト。 Functions は、単純な従来の CLR オブジェクト (POCO) 型を JSON データにシリアル化しようとします。

関数で複数のイベントを書き込むとき、Event Grid 出力バインドは次の型にバインドできます。

Type 説明
T[] (T は単一のイベントの種類の 1 つ) 複数のイベントを含む配列。 各エントリは 1 つのイベントを表します。

その他の出力シナリオでは、Azure.Messaging.EventGrid から型を直接作成して使用します。

out EventGridOutput paramName などのメソッド パラメーターを呼び出して個々のメッセージを送信し、ICollector<EventGridOutput> を使用して複数のメッセージを書き込みます。

値を直接返すか、context.extraOutputs.set() を使って、出力メッセージにアクセスします。

Push-OutputBinding コマンドレットを使用して出力イベントにアクセスし、Event Grid 出力バインディングにイベントを送信します。

関数から Event Grid メッセージを出力するには、次の 2 つのオプションがあります。

  • 戻り値:function.json 内の name プロパティを $return に設定します。 この構成では、関数の戻り値は EventGrid メッセージとして永続化されます。
  • 命令型:Out 型として宣言されたパラメーターの set メソッドに値を渡します。 set に渡された値は、EventGrid メッセージとして永続化されます。

つながり

Event Grid 出力バインドを使用する場合、Event Grid トピックに対して認証を行う方法は 2 つあります:

認証方法 説明
トピック キーの使用 トピック キーを使用する」で説明されているように、TopicEndpointUriTopicKeySetting プロパティを設定します。
ID の使用 Connection プロパティを複数のアプリケーション設定に対する共有プレフィックスの名前に設定すると共に、ID ベースの認証を定義します。 この方法は、バージョン 3.3.x 以降の拡張機能を使用する場合にサポートされます。

トピック キーを使用する

次の手順のようにしてトピック キーを構成します。

  1. アクセス キーの取得に関する記事の手順に従って、Event Grid トピック用のトピック キーを取得します。

  2. アプリケーション設定で、トピック キー値を定義する設定を作成します。 この設定の名前を、バインドの TopicKeySetting プロパティに使用します。

  3. アプリケーション設定で、トピック エンドポイントを定義する設定を作成します。 この設定の名前を、バインドの TopicEndpointUri プロパティに使用します。

ID ベースの認証

バージョン 3.3.x 以降の拡張機能を使っているときは、Microsoft Entra の ID を使って Event Grid トピックに接続でき、トピック キーを取得して使用する必要がなくなります。

トピック エンドポイント URI を返すアプリケーション設定を作成する必要があります。 設定の名前は、"一意の共通プレフィックス" (たとえば、myawesometopic) と値 __topicEndpointUri を組み合わせる必要があります。 次に、バインディングで Connection プロパティを定義するときに、その共通プレフィックス (この場合は、myawesometopic) を使用する必要があります。

このモードでは、拡張機能に次のプロパティが必要です。

プロパティ 環境変数テンプレート 説明 値の例
トピック エンドポイント URI <CONNECTION_NAME_PREFIX>__topicEndpointUri トピック エンドポイント。 https://<topic-name>.centralus-1.eventgrid.azure.net/api/events

さらに他のプロパティを使用して、接続をカスタマイズできます。 「ID ベース接続に共通のプロパティ」を参照してください。

Note

Azure App Configuration または Key Vault を使ってマネージド ID ベースの接続の設定を指定する場合、名前の設定に __ の代わりに :/ などの有効なキー区切り記号を使って、名前が正しく解決されるようにする必要があります。

たとえば、「 <CONNECTION_NAME_PREFIX>:topicEndpointUri 」のように入力します。

Azure Functions サービスでホストされている場合、ID ベースの接続では、マネージド ID が使用されます。 ユーザー割り当て ID を credential および clientID プロパティで指定できますが、システム割り当て ID が既定で使用されます。 リソース ID を使用したユーザー割り当て ID の構成はサポートされていないことに注意してください。 ローカル開発などの他のコンテキストで実行する場合は、代わりに開発者 ID が使用されますが、カスタマイズすることもできます。 ID ベースの接続によるローカル開発に関するページをご覧ください。

ID にアクセス許可を付与する

使用されている ID が何であれ、目的のアクションを実行するためのアクセス許可が必要です。 ほとんどの Azure では、これはそれらのアクセス許可を提供する組み込みロールまたはカスタム ロールを使って、Azure RBAC でロールを割り当てる必要があることを意味します。

重要

すべてのコンテキストに必要ではない一部のアクセス許可がターゲット サービスによって公開される場合があります。 可能であれば、最小限の特権の原則に従い、必要な特権だけを ID に付与します。 たとえば、アプリがデータ ソースからの読み取りのみを行う必要がある場合は、読み取りアクセス許可のみを持つロールを使用します。 サービスへの書き込みも可能なロールを割り当てることは、読み取り操作に対するアクセス許可が過剰になるため、不適切です。 同様に、ロールの割り当てが、読み取る必要のあるリソースだけに限定されていることを確認する必要があります。

実行時に Event Grid トピックへのアクセスを提供するロールの割り当てを作成する必要があります。 所有者のような管理ロールでは十分ではありません。 次の表は、通常の操作で Event Hubs の拡張機能を使用するときに推奨される組み込みのロールを示しています。 アプリケーションでは、記述したコードに基づいて追加のアクセス許可が必要になる場合があります。

[バインドの種類] 組み込みロールの例
出力バインド EventGrid 共同作成者EventGrid データ送信者

次のステップ