ごった煮

色々な事を書いてます

Function App の Blob output binding でファイル名にいい感じに日付を入れたい

日時バッチを Function App で実行する場合、ファイル名に日付を入れたいといったことがあるかと思います。 Blob binding だといい感じに日付を入れられるのでその方法を紹介します。

やってみる

Function App の Blob output binding で、以下のようにします。

[FunctionName("demo")]
public async Task Run(
[TimerTrigger("0 0 0 * * * ")]TimerInfo myTimer,
[Blob("demo/demo_{datetime}.csv", FileAccess.Write)] Stream csv,
ILogger log)
{
        
}

{datetime} とすることで、実行時の日付が UTC で差し込まれます。 デフォルトでは、yyyy-MM-ddThh-mm-ssZ になります。 このようにすると、demo_yyyy-MM-ddThh-mm-ssZ.csv といったようなファイル名でファイルが出力されます。

フォーマット指定したい場合は、 {datetime:yyyy-MM-dd} とします。 すると、demo_yyyy-MM-dd.csv となります。

まとめ

ファイル名が動的でも面倒な処理をせずにファイル名に日付を差し込むことが出来ました。

datetime に入ってくる日付は、デフォルトで UTC なので気を付けましょう。 これを変える場合は、 Function App のタイムゾーン設定を変更する必要があり、一緒にデプロイされているすべての Function に影響を与えるのでタイムゾーンを変更する場合は、慎重に行いましょう。

Azure Logc App で SFTP にファイルを転送したい

C# で SFTP に接続してなんやかんやする場合、いいライブラリが少なかったり実装がややこしかったりで結構面倒だと思っていました。 ですが Logic App には、SFTP へのコネクトがちゃんと用意されているので今回は、それを使ってファイルを転送する方法についてまとめます。

やりたいこと

Blob storage と SFTP サーバの両方にテキストファイルを転送する

サービス

Azure Logic App

やってみる

Blob storage の変化を検知する

Logic App のエディタで、 Azure Blob Storage をトリガーとして選択します。 f:id:papemk2:20200323175149p:plain

選択すると When a blob is added or modified の項目があるので選択します。 初めての場合、ストレージアカウントを選択する画面になるので、ストレージアカウントを選択します。

f:id:papemk2:20200323175651p:plain

トリガーが作成されると監視するコンテナを選択する画面が出るので、適当に設定します。 f:id:papemk2:20200323175856p:plain

Blob に配置されたファイルの中身を取得する

New Step から処理を追加します。 また Azure Blob Storage を選択します。 すると色々 Action が出てくるので、Get blobg content を選択します。

f:id:papemk2:20200323180137p:plain

選択すると、Blob で何をするか設定する画面になります。 Blob の項目を List of Files Path に設定します。

f:id:papemk2:20200323180317p:plain

これで、後続の処理に Blob の中身を渡せるようになります。

SFTP へ接続する

また Action を追加します。 SFTP で検索すると、SFTP 用のアクションがいくつか出てくるので Create file を選択します。 f:id:papemk2:20200323180536p:plain

選択すると、SFTP の設定情報を埋める画面が出るので、適当に埋めます。

f:id:papemk2:20200323180714p:plain

private key は、ppk の中身をべた張りで OK です。

接続設定がおかしい場合は、この段階でエラーになってくれるので設定を見直しましょう。 f:id:papemk2:20200323180855p:plain

SFTP へファイルを転送する

SFTP の接続設定が終わると、ファイル名とファイルの中身をどうするか設定する画面になります。 以下のように File name に List of Files DisplayName, File content に File Content を設定します。 Folder path は、任意のパスで埋めます。

f:id:papemk2:20200323181221p:plain

これで準備完了です。

指定した Blob にファイルをアップロードすると、いい感じに SFTP にファイルをコピーしてくれます。 デフォルトの状態だと、 3分に一度の感覚でポーリングするので、ファイルをアップロードしてから最大3分で処理が行われます。

まとめ

C# だと面倒な処理でも Logic App を組み合わせると簡単にできることがあるので、適材適所で Logic App も使ってみましょう。

Azure Storage Explorer で一部見えないサブスクリプションがある場合に試したこと

ここ最近 Azure Storage Explorer 上で、一部のサブスクリプションが表示されないという現象に遭遇したので、その時にやったことをメモとして残します。

何があった

ある日突然今まで Azure Storage Explorer に表示されていたサブスクリプションが一部見えなくなった。 表示されなくなったサブスクリプションに共通している点として、見えなくなった日に AAD で MFA を有効化した

Azure Storage Explorer の設定を見直す

Azure Storage Explorer の設定にそれらしい設定項目がありました。

f:id:papemk2:20200219161825p:plain

SSO や、MFA を使用したサインインを行いたい場合は、この項目を有効化しておくと使えるようになるようです。 これをオンにした後は、一度 Azure Storage Explorer を立ち上げなおしてアカウントのサインインをし直すと該当のサブスクリプションも今まで通り表示されるようになります。

まとめ

同じような現象が起きている方は、設定を見直してみましょう。

Managed Identity に繋がったアプリをローカルデバッグしたい

Azure のサービスに繋ぎに行くとき、Managed Identity を使ってセキュアに接続する方法がありますが、ローカルで動かしたいときは、少しややこしいのでメモとして残します

ローカルで Managed Identity に繋ぐ

因みに今回は、Azure Appn Configuration を例に出します。

用意するもの

Azure のアカウントに Managed Identity での接続を許可する

まず Azure のアカウントに権限を付与します。 Managed Identity で接続したいサービスの IAM > Role Assaignments > Add role assaignment を選択します。 f:id:papemk2:20200129135658p:plain

次に設定するロールを選択します。 App Configuration の場合は、App Configuration Data Reader で大丈夫です

f:id:papemk2:20200129140521p:plain

Assign access to は、Azure AD User, group, or service principal を選択します。

Visual Studio を設定する

ローカルから Managed Identity で繋ぐ場合の認証情報は、Visual Studio に設定されている認証情報を使用します。 そのため Visual Studio でログインしている MSアカウント or 組織アカウント に Managed Identity でリソースにアクセスする権限が付与されていれば、そのまま接続されます。

先ほど権限を付与したアカウントで Visual Studio にログイン出来る場合は、これで繋がるようになるはずです。

権限を付与したアカウントと Visual Studio のライセンスを持っているアカウントが異なる場合は、別の方法で設定します。

Visual Studio の Tools > Options > Azure Service Authentication の項目に移動します。

f:id:papemk2:20200129140938p:plain

この部分は、デフォルトで Visual Studio のログインに使用しているアカウントが選択されます。 なのでここで先ほど権限付与を行ったアカウントを選択 or 登録すると Visual Studio のログイン用アカウントと Azure との接続に使用するアカウント情報を別々にすることが出来ます。

まとめ

Managed Identity は、かなり便利なので活用してみましょう

Azure Pipeline の通知を Slack で受け取る

この記事は、Azure DevOps アドベントカレンダーの 15日目です。

Release pipeline は、各処理の結果をSlack に通知することが出来ます。 Azure pipeline の機能で通知する方法と Slack アプリを使用する方法がありますが、今回は、Slack アプリの方を説明します。

アプリを入れる

この方法には、Slack 用のアプリを入れて行います。 以下からインストールします

slack.com

このアプリは、ビルド、リリースの各処理が成功・失敗した時、リリース承認が必要な時などに通知を行うことが出来ます。

使えるようにする

プライベートチャンネルのみ、アプリをチャンネルに追加する必要があります。

/invite @azpipelines

で、アプリをSlack に登録します。 するとこんな感じになります。 f:id:papemk2:20191214212041p:plain

次に Azure にサインインします。

/azpipelines signin

を呼ぶと、以下のような感じ f:id:papemk2:20191214212256p:plain

SignIn ボタンを押すと、Azure のサインイン画面にジャンプします。 サインインが出来ると画面に数字が表示されます。 f:id:papemk2:20191214212429p:plain

Slack の画面に戻り、Enter code を選択すると、その数字を入力する画面が表示されるので入力します。 これでサインイン完了です。

Pipeline を登録する

サインインまでできたら、パイプラインを登録します。

/azpipelines subscribe パイプラインのURL

を指定するとパイプラインの通知を受け取ることが出来るようになります。 登録しているパイプラインを確認するときは、

/azpipelines subscriptions

すると、以下のような感じでパイプラインの管理が出来ます。 f:id:papemk2:20191214214425p:plain

パイプラインを登録すると、デフォルトでは、全てのステータス変更などが通知される設定になっているので、通知がうるさく感じる場合などは、細かく設定します。 Add subscription ボタンを押すと、細かい登録を行うための画面が出てきます。 例えば、ビルドパイプラインが失敗した場合は、以下のような感じ f:id:papemk2:20191214214737p:plain

リリース承認を行う

このアプリを使うと、Slack からリリースパイプラインの認証処理が行えます。 リリースパイプラインを登録した後に、そのリリースパイプライン承認が必要になると、Slack に通知が来ます。 f:id:papemk2:20191214215002p:plain

Approval を押すと承認、Reject を押すと承認しないことになります。

Slack から承認をする場合は、プロジェクトの Admin にユーザを設定する + Permissions > Service Account > Make requests on behalf of others を Allow にします。 これをしておかないと権限不足でエラーになります。

まとめ

Slack を通知対象にしておくと、メールなどよりも人によっては、見落としにくくなるかなと思います。 ビルドが成功した場合などは、あまり監視しなくても良いですが、失敗した場合の監視は、見落とすと厄介なので、ぜひ通知を活用してみましょう。

Azure DevOps で最新の.NET Core をビルドしたい

.NET Core 3.1 が出ましたが、Azure DevOps のビルドマシンに即日展開されるってことは、無いです。 ですがバージョンアップ後にビルドできなくなるのも困りものなので、最新のバージョンを使う方法をメモします。

Yaml を書く

とりあえず Yaml に定義を追加するだけです。 使いコマンドは、Use .NET Core f:id:papemk2:20191210181709p:plain

設定項目は、ランタイムを入れるか SDK を入れるか、入れたいバージョンなどです。 今回は、3.1系なので、3.1.x を指定します。 f:id:papemk2:20191210181819p:plain

Yaml の定義は以下のようになります。

- task: UseDotNet@2
  inputs:
    packageType: 'sdk'
    version: '3.1.x'

とても簡単に入ります。

まとめ

プレビューバージョンを指定するオプションなんかも用意されているので、必要に応じて追加しましょう。

Azure Monitor と Log Analytics を組み合わせてアプリケーションを監視する

この記事は、Azure アドベントカレンダー 2019 の8日目の投稿です。

Azure には、アプリケーションの監視用に Application Insights(以下 AI ) があります。 AI は、ログの分析を行う Log Analytics と組み合わせることによって柔軟にログを扱うことが出来ます。

今回は、AI で収集したログを Log Analytics で集約し、Azure Monitor を使って Azure Functions にエラーメッセージを送る方法についてまとめます。

※今回は、AI とアプリケーションの繋ぎ込みなどは、扱わないのでそういった情報は、以下のようなところから調べてみましょう。

docs.microsoft.com

docs.microsoft.com

Log Analytics でログを分析する

Log Analytics でログ分析を行う場合は、基本的に SQL ライクな KQL という言語を使用してクエリを書きます。

Log Analytics のクエリエディタは、Azure ポータルの AI の画面から飛ぶことが出来ます。 AI の画面上部にある Log(Analytics) を選択します。 f:id:papemk2:20191206225727p:plain

クエリエディタは、以下のような画面になります。 赤枠の中にクエリを書いていきます。 f:id:papemk2:20191206231018p:plain

クエリを書いたら Run ボタンを押します。

ログは、以下の項目が検索できます。

  • traces
  • customEvents
  • pageViews
  • requests
  • dependencies
  • exceptions
  • availabilityResults
  • customMetrics
  • performanceCounters
  • browserTimings

自分が良く使う項目は、requests、dependencies、exceptions です。 requests は、アプリケーションに送られてくるリクエスト内容 dependencies は、DB、Web API などアプリケーション外にある依存関係 exceptions は、アプリケーション内で発生した例外が含まれます。

一番簡単なクエリは、以下です。

requests

これを実行すると、ログが表組されて表示されます。 f:id:papemk2:20191206231143p:plain

条件分は、SQL のように書きます。

requests
| where resultCode == 404 or resultCode == 500

カラムの絞り込みは、以下のような感じ

requests
| where resultCode == 404 or resultCode == 500
| project resultCode , url , name 

f:id:papemk2:20191206231805p:plain

サマリーしたいときは、以下のような感じ

requests
| where resultCode == 404 or resultCode == 500
| project resultCode , url , name 
| summarize count(resultCode) by resultCode, url, name

f:id:papemk2:20191206232436p:plain

Log Analytics と Azure Monitor を組み合わせる

先ほど書いたクエリ結果をAzure Monitor と組み合わせてみます。 これは、Azure Monitor の画面から行います。 Azure Monitor のモニタルールは、ポータルの Azure Monitor > Alerts > New alert rule から進みます。 進むと以下のような画面になります。 f:id:papemk2:20191206233303p:plain

Resource で監視対象の AI を指定します。 赤枠の中に Application Insights と入れると絞り込みがされます。

f:id:papemk2:20191206233749p:plain

Condition は、リソースの状態を指定する項目です。 ここで Log Analytics のクエリを指定します。

Custom log search を指定します。

f:id:papemk2:20191206233936p:plain

赤枠のSearch query にクエリを貼り付けます。 今回は、エラーが発生したら通知を行いたいので、閾値(Threshold value)は、0にします。(0を指定すると0回以上になるので、イベントが発生したら全て拾うことになります。) 時間の範囲は、デフォルト(5分)に設定します。 f:id:papemk2:20191206234115p:plain

Actions は、アラートの発行先を指定する項目です。 今回は、Function App を指定します。 Create action group を選択します。 選択後、Action Type に Azure Functions を指定します。 次に出てくるウィンドウで、リソースグループを選択するとHttp Trigger が含まれている Function App が表示されるのでアラートを送りたい Function App を指定します。 f:id:papemk2:20191206234626p:plain

最後に Alert Details で、Alert rule name を指定します。 これで、アラートが発生すると Function App のエンドポイントが呼び出されます。

Azure Functions でメッセージを受け取る

Function App が受け取るペイロードは、以下のような形式です。

{
    "schemaId": "Microsoft.Insights/LogAlert",
    "data": {
        "SubscriptionId": "Your own subscription id",
        "AlertRuleName": "Qiita-Monitoring-2019",
        "SearchQuery": "requests\n| where resultCode == 404 or resultCode == 500\n| project resultCode , url , name \n| summarize count(resultCode) by resultCode, url, name",
        "SearchIntervalStartTimeUtc": "2019-12-06T15:03:56",
        "SearchIntervalEndtimeUtc": "2019-12-06T15:08:56",
        "AlertThresholdOperator": "Greater Than",
        "AlertThresholdValue": 0,
        "ResultCount": 2,
        "SearchIntervalInSeconds": 300,
        "LinkToSearchResults": "https://portal.azure.com#@ef5d34b2-4e7d-468e-b184-b17e34c6be36/blade/Microsoft_OperationsManagementSuite_Workspace/AnalyticsBlade/initiator/AnalyticsShareLinkToQuery/isQueryEditorVisible/true/scope/%7B%22resources%22%3A%5B%7B%22resourceId%22%3A%22%2Fsubscriptions%2F30bc1c24-7c50-471e-97c4-b86a3d9cedb1%2FresourceGroups%2FQiita%2Fproviders%2Fmicrosoft.insights%2Fcomponents%2FQiita-Monitoring-2019%22%7D%5D%7D/query/requests%0A%7C%20where%20resultCode%20%3D%3D%20404%20or%20resultCode%20%3D%3D%20500%0A%7C%20project%20resultCode%20%2C%20url%20%2C%20name%20%0A%7C%20summarize%20count%28resultCode%29%20by%20resultCode%2C%20url%2C%20name/isQuerybase64Compressed/false/timespanInIsoFormat/2019-12-06T15%3a03%3a56.0000000Z%2f2019-12-06T15%3a08%3a56.0000000Z",
        "Description": "",
        "Severity": "3",
        "SearchResult": {
            "tables": [
                {
                    "name": "PrimaryResult",
                    "columns": [
                        {
                            "name": "resultCode",
                            "type": "string"
                        },
                        {
                            "name": "url",
                            "type": "string"
                        },
                        {
                            "name": "name",
                            "type": "string"
                        },
                        {
                            "name": "count_resultCode",
                            "type": "long"
                        }
                    ],
                    "rows": [
                        [
                            "500",
                            "https://localhost:44355/home/error500",
                            "GET /home/error500",
                            8
                        ],
                        [
                            "404",
                            "https://localhost:44355/error",
                            "GET /error",
                            15
                        ]
                    ]
                }
            ],
            "dataSources": [
                {
                    "resourceId": "/subscriptions/30bc1c24-7c50-471e-97c4-b86a3d9cedb1/resourcegroups/qiita/providers/microsoft.insights/components/qiita-monitoring-2019",
                    "tables": [
                        "requests"
                    ]
                }
            ]
        },
        "ApplicationId": "dcd854c3-e6a8-4f05-b58c-8272660d3427",
        "AlertType": "Number of results"
    }
}

columns が、テーブルのカラム名、rows が結果にリンクします

LinkToSearchResults の URL は、Log Analytics の クエリエディタに繋がります。

このペイロードを Slack に送るなどするとアプリのモニタリングがしやすいかと思います。

ペイロードを受け取る場合のC#の例を示します。

#r "Newtonsoft.Json"

using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;

public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
{
    string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
    
    log.LogInformation(requestBody);

    return (ActionResult)new OkObjectResult(requestBody);
}

Request Body に json が入ってくるので、それを加工して次の処理の送るといった感じで使用します。 Logic App に送るといったことも可能ですが、例えば Slack 通知などは、デフォルトの Slack コネクタだとリッチなメッセージが送れないので Function App が向いているかなという気がします。

まとめ

これらの学習には、Microsoft Learn がおすすめです。

docs.microsoft.com

アプリケーションの監視は、サービス運用の要なので、この機会に是非試してみましょう。