LoginSignup
2
0

More than 1 year has passed since last update.

AzureFunction経由でBlobにログを書き込む(AppendBlob)

Last updated at Posted at 2023-01-29

はじめに

ログをクラウド上に持ってくるときにWebHookを経由して連携させるSaaSのソリューションがあります。

こんなイメージ

image.png

SendGridのアクティビティログはまさにそのパターンで、例えばEvent Webhookを利用することでSendGrid経由でメールを送信する際に発生するイベントを、指定したURLにPOSTすることができます。

このデータの用途は、配信停止アドレスの削除、迷惑メール報告への対応、
エンゲージできなかった受信アドレスの判定、バウンスされたメールアドレスの特定、
メールプログラムの高度な分析などです。ユニーク引数やカテゴリパラメータを使用して、
動的なデータを挿入することができるため、あなたのメールのシャープでクリアなイメージを構築するのに役立ちます。

これをAzure Functionsを利用して実装してみたいと思います。

#AzureFunction(Typescript)でAppendBlobを利用する記事が見当たらなかったので書いてみました。

output binding

Azure FunctionsにはOutput Bindingという機能があり、BlobStorageへ簡単にデータを書き込むことができます。

これを使えば簡単にできるぞと思っていざやってみるとそうはうまくいきませんでした。
常に新しいファイルに書き込んでいくことはできるのですが追記することはできないようです。

Append blobの利用

こういうログのユースケースに最適なBlobStorageがありまして、これが追加Blob(append blob)です。

追加 BLOB はブロックで構成され、追加操作用に最適化されています。 
追加 BLOB を変更すると、ブロックは追加ブロック操作を介してのみ BLOB の末尾に 追加 されます。
既存のブロックの更新または削除はサポートされていません。 
ブロック BLOB とは異なり、追加 BLOB はブロック ID を公開しません。

追加 BLOB 内の各ブロックは、最大 4 MiB の異なるサイズにすることができ、
追加 BLOB には最大 50,000 ブロックを含めることができます。
したがって、追加 BLOB の最大サイズは 195 GiB (4 MiB X 50,000 ブロック) をわずかに超えています。

一度の書き込み4MBというところは気を付けたほうがよさそうですが、追加処理に最適という部分がポイントです。

いざ、TypeScriptでoutputbindingを使ってAppendBlobを利用しようと思ったのですが、どうやらC#しか対応していない模様です。

ということで、Function内でBlobSDKを使って書き込んでいきたいと思います。

Azure Function

ソースはこちら

index.ts
import {AzureFunction, Context, HttpRequest} from "@azure/functions"
import {BlobServiceClient, StorageSharedKeyCredential} from "@azure/storage-blob"

const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {

    // log
    context.log(req.body)

    const account = process.env.STORAGE_ACCOUNT_NAME || "";
    const accountKey = process.env.STORAGE_ACCOUNT_KEY || "";
    const sharedKeyCredential = new StorageSharedKeyCredential(account, accountKey);
    const blobServiceClient = new BlobServiceClient(
        `https://${account}.blob.core.windows.net`,
        sharedKeyCredential
    );
    // コンテナがなければ作る
    const containerClient = await blobServiceClient.getContainerClient("sendgrid");
    await containerClient.createIfNotExists();

    // append blobが無ければ作る
    const date = new Date().getDate();

    const appendBlobClient = await containerClient.getAppendBlobClient(`activity-${getYYYYMMDD(new Date())}.log`);
    await appendBlobClient.createIfNotExists();

    // append blobに追記
    let activity = JSON.stringify(req.body) + '\n';
    await appendBlobClient.getAppendBlobClient().appendBlock(activity, activity.length);

    context.res = {
        status: 200
    };

};

const getYYYYMMDD = (now: Date) => {
    let yyyy = now.getFullYear();
    let mm = ('00' + (now.getMonth() + 1)).slice(-2);
    let dd = ('00' + now.getDate()).slice(-2);
    const ymd = String(yyyy) + String(mm) + String(dd);
    return ymd;
};

export default httpTrigger;

ローカル実行

  1. Storageアカウントを作成

    • ストレージアカウントの名前とアクセスキーはメモしておく
      image.png
  2. Azure Functionを作成

  3. STORAGE_ACCOUNT_NAME,STORAGE_ACCOUNT_KEYをFunctionの環境変数に追加
    image.png

  4. Functionの環境変数をローカルへダウンロード

  • local.settings.jsonに環境変数が入ることを確認する
func azure functionapp fetch-app-settings <functionname>

5.ローカルで実行

  • 正常に起動することを確認します。
func start

6.PostmanなどでJSONを投げ込んで、ストレージアカウントにデータが入ることを確認してください。

deploy

yarn run build
func azure functionapp publish <functionname>

SendGridでの利用

Functionでアプリキーをコピーします

image.png

http://function-url/eventwebhook?code=<アプリキー>をsendgridに設定します。

その他注意点についてはこちらの記事を参照してください。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0