Blazor Client-Sideアプリで作る稼働監視サイト



今回はBlazor Client-Sideアプリ(Blazor WebAssembly)で、WEBサイトの稼働を監視させてみたいと思います:eyes:
![2020-12-03_19h44_47.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110304/bc3c53a0-ea48-9150-05be-7579335c3e53.gif)

# C#でサイトの監視を考える

Webサーバーなどの稼働監視をC#で実装する場合、いくつかの方法があると思います。
まず、コンソールアプリをC#で作ってみます。

Timer + HttpClient を組み合わせて作ってみましょう。
Webサーバーに対して、リクエストを開始した時間から、応答時間までを計り、3000ミリ以上かかった場合、タイムアウトとするプログラムを考えてみます。

```c#:main.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Timers;
using System.Net.Http;

namespace cli_url
{
    class Program
    {
        static void Main(string[] args)
        {
            var http = new HttpClient();

            // タイムアウトの設定
            http.Timeout = TimeSpan.FromMilliseconds(3000);

            // サーバーリストの読み込み
            var servers = new string[] { "http://localhost:8081", "http://localhost:8082", "http://localhost:8083", "http://localhost:8084" };

            // タイマーの定義
            var timer = new System.Timers.Timer();
            timer.Interval = 5000; // 5秒おきに実行

            // タイマーで実施する処理
            timer.Elapsed += async (s, e) =>
            {
                foreach (var server in servers)
                {
                    var dt1 = DateTime.Now; // 開始時間
                    var dt2 = DateTime.Now; // 終了時間

                    try
                    {
                        // Getする
                        await http.GetAsync(server);
                    }
                    catch { }
                    // 終了時間を記録
                    dt2 = DateTime.Now;

                    // 応答時間を計算
                    var restime = (dt2 - dt1).TotalMilliseconds;
                    if (restime < 3000)
                    {
                        // 3000ミリ秒以内はOK
                        Console.WriteLine("{0} is OK res = {1}", server, restime);
                    }
                    else
                    {
                        // 3000ミリ以上はタイムアウトとする
                        Console.WriteLine("{0} is Timeout.", server);
                    }

                }

            };

            // タイマーの開始
            timer.Enabled = true;

            Console.ReadKey();
        }
    }
}
```

##実行画面
![cli.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110304/acebc2b9-1abf-d3a6-5eb3-620da755bb40.png)


# Blazorで、同じ実装をしてみる。

簡単なサイト監視が実装できたところで、Blazor WebAssemblyで実装してみましょう。
Blazor WebAssembly で初めからある```FetchData.razor```ページを改造し、コンソールプログラムと同じ実装をしてみます。

```javascript:FetchData.razor
@page "/fetchdata"
@inject HttpClient Http

<h1>Server List</h1>

@if (servers == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>SiteName</th>
                <th>URL</th>
                <th>Response</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var server in servers)
            {
                <tr>
                    <td style="background-color: @(server.TimeOut == false ?  "lime" : "red")" >@server.Name</td>
                    <td>@server.URL</td>
                    <td>@server.Summary</td>
                </tr>
            }
        </tbody>
    </table>
}

@code {
    private ServerConfig[] servers;


    protected override async Task OnInitializedAsync()
    {
        // タイムアウトの設定
        Http.Timeout = TimeSpan.FromMilliseconds(3000);

        // サーバーリストの読み込み
        servers = await Http.GetFromJsonAsync<ServerConfig[]>("sample-data/servers.json");

        // タイマーの定義
        var timer = new System.Timers.Timer();
        timer.Interval = 5000; // 5秒おきに実行

        // タイマーで実施する処理
        timer.Elapsed += async (s, e) =>
        {
            foreach(var server in servers)
            {
                var dt1 = DateTime.Now; // 開始時間
                var dt2 = DateTime.Now; // 終了時間

                try
                {
                    // Getする
                    await Http.GetAsync(server.URL);
                }
                catch { }
                // 終了時間を記録
                dt2 = DateTime.Now;

                // 応答時間を計算
                var restime = (dt2 - dt1).TotalMilliseconds;
                if (restime < 3000)
                {
                    // 3000ミリ秒以内はOK
                    server.TimeOut = false;
                }
                else
                {
                    // 3000ミリ以上はタイムアウトとする
                    server.TimeOut = true;
                }

                server.Summary = restime.ToString();
            }

            // 画面更新
            this.StateHasChanged();
        };

        // タイマーの開始
        timer.Enabled = true;
    }

    public class ServerConfig
    {
        public string Name { get; set; }

        public string URL { get; set; }

        public string Summary { get; set; } 

        public bool TimeOut { get; set; }
    }
}
```

Blazor でもコンソールアプリケーションとほぼ同等のコーディングで、実装を行うことができました。ブラウザ内で行える処理に限られますが、割とベタなコードでも十分動作するコードをC#で書くことができます。
動きのあるプログラムでも、JavaScriptを使わずにコーディングができるので、C#コーダーにとっては、見栄えのいいWebアプリケーションを作るにはBlazorは良い選択肢になるのではないでしょうか！！これからも、Blazorの進化に期待したいと思います:thumbsup:


### 参考サイト
[け日記　C# HttpClientでタイムアウトを設定する](https://ohke.hateblo.jp/entry/2017/05/12/202832)