AzureServiceBusとAzureFunctionsのサービスをAzureApplicationInsightsとSlackで監視する

GYAOのtsです。
我々のチームは、オールパブリッククラウドで、[Microservice Architecture](http://microservices.io/patterns/microservices.html)を採用した次期バックエンドを設計中です。

# 経緯
[前回の投稿](http://qiita.com/tstakano-yj/items/799e18cd209cf5a93ef7)でfunctionsを使用したAPIの作成と監視についてチーム内で話し合ったが、チームとして下記の方向で概ね合意が取れているので、この記事で監視も含めてプロトタイプを作成してみる。構成は下記のような形。
![zeoliteLatestDiagram (1).png](https://qiita-image-store.s3.amazonaws.com/0/114329/2c92605c-c251-4729-969a-8b2f2e373d62.png)
今回のscopeはPowerBIとLogicAppsの部分は割愛する（別記事で）。

# Hands on
今回実現したいことは以下の通り。

```
■ AzureFunctionsでAPIを2本作成する。

・DB登録用API・・・store
・DB削除用API・・・remove

■ storeAPI、removeAPIはAzureServiceBusの特定のトピック(storeトピック)にpublish。

■ AzureFunctions（subscriber）がAzureServiceBusの特定のトピック(storeトピック)をsubscribe。DB（cosmosDB）に対して処理を行う。

以上、たったこんだけ。
＋ 監視は適宜行います。
```

## AzureServiceBus
まずはPublish、 Subscribeするトピックを作成します。
<img width="643" alt="スクリーンショット 2017-07-07 14.34.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/114329/6ceadb39-6e1c-f9ee-47e6-c127546e190b.png">

<img width="303" alt="スクリーンショット 2017-07-07 14.36.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/114329/8a189470-e1a4-b8cf-341e-e5b18f7819c3.png">


<img width="507" alt="スクリーンショット 2017-07-07 15.46.41.png" src="https://qiita-image-store.s3.amazonaws.com/0/114329/27d83d4e-5cde-da6d-672e-6167a06457fe.png">

## AzureFunctions
### store
```
Http-ServiceBusのPublisherを作成する。
```
詳しくは[前回の投稿](http://qiita.com/tstakano-yj/items/799e18cd209cf5a93ef7)を参照。

<img width="991" alt="スクリーンショット 2017-07-07 15.40.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/114329/1cc19709-6be1-72f2-be72-3e173c0af569.png">


```csharp
#r "Newtonsoft.Json"

using System;
using System.Net;
using System.Threading.Tasks;
using Newtonsoft.Json;

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, ICollector<string> outputSbQueue, TraceWriter log)
{
    log.Info("C# HTTP trigger function processed a request.");

    // Get request body
    string jsonContent = await req.Content.ReadAsStringAsync();
    dynamic data = JsonConvert.DeserializeObject(jsonContent);

    if (data == null) {
        return req.CreateResponse(HttpStatusCode.BadRequest, 
            "Please pass a messsage in the request body.");
    }
    else {
        outputSbQueue.Add($"{data}");
        return req.CreateResponse(HttpStatusCode.OK, $"{data}");
    }
}

```

### remove
```
同じHttp-ServiceBusのPublisherを作成するが、publishする際のデータ構造が変わっただけなので割愛
```

### doStore
```
subscriber。topicに流れてきたデータをもとに実際にcosmosDBに対して処理を行う。
```
<img width="981" alt="スクリーンショット 2017-07-07 15.44.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/114329/18e8306c-c72a-db90-8ce1-390bad129246.png">

```csharp
using System;
using System.Threading.Tasks;

public static void Run(string mySbMsg, TraceWriter log, out object outputDocument)
{
    log.Info($"C# ServiceBus topic trigger function processed message: {mySbMsg}");
    outputDocument = mySbMsg;
}
```

## AzureAppInsights
```
Functions、ServiceBusの監視をApplicationsで一元管理します。
今回はErrorやExceptionがあった場合、slackにサマリーを飛ばします。
```
### Functions
Functions自体の監視は[前回の投稿](http://qiita.com/tstakano-yj/items/799e18cd209cf5a93ef7)を参照。
今回はそれに加えてErrorsWebhookという関数を作成した。Azureのリソースのメトリックアラートをすべてここに飛ばし、監視する。

```csharp
using System.Net;

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
    log.Info("Error was occurred...");

    // Get request body
    dynamic data = await req.Content.ReadAsAsync<object>();
    log.Error($"{data}");

    return req.CreateResponse(HttpStatusCode.OK);
}
```
### ServiceBus
servicebusに関しては
アクティビティログアラートで設定する形か？現在調査中。
<img width="910" alt="スクリーンショット 2017-07-09 23.54.38.png" src="https://qiita-image-store.s3.amazonaws.com/0/114329/aeab78ae-2f00-fd0d-b6e2-ea7bb84357ea.png">

<img width="630" alt="スクリーンショット 2017-07-09 23.51.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/114329/23114379-caca-e919-4da7-a24ea47ef9e4.png">

webhookで先程作成したfunctions（ErrorsWebhookを指定する）


### ApplicationInsightsとSlack
ApplicationInsightsで拾ったErrorについてはSlackに送信したいので下記を使用する。
[cloudbot](https://slack.com/apps/A3YMR1UE6-cloudbot)
定期便とエラー毎のレポートを送ってくれる

定期便
<img width="663" alt="スクリーンショット 2017-07-10 0.04.28.png" src="https://qiita-image-store.s3.amazonaws.com/0/114329/6bac05b7-79f9-e4bb-3a98-54602c573137.png">

エラーpush
<img width="554" alt="スクリーンショット 2017-07-10 0.05.17.png" src="https://qiita-image-store.s3.amazonaws.com/0/114329/0433df20-9870-702c-a031-0d6e76360b44.png">