From 8566924cfe3f7855329323483d5a9b616bff3a08 Mon Sep 17 00:00:00 2001 From: Fumika Koyama Date: Fri, 20 Oct 2023 14:08:24 +0900 Subject: [PATCH] =?UTF-8?q?=E3=83=98=E3=83=AB=E3=82=B9=E3=83=81=E3=82=A7?= =?UTF-8?q?=E3=83=83=E3=82=AF=E7=94=A8API=E3=81=AE=E8=BF=BD=E5=8A=A0?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/HealthController.cs | 65 +++++++++++++++++++ .../src/Dressca.Web/DbHealthCheck.cs | 41 ++++++++++++ .../src/Dressca.Web/Program.cs | 4 ++ .../src/Dressca.Web/dressca-api.json | 47 +++++++++++++- 4 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 samples/Dressca/dressca-backend/src/Dressca.Web/Controllers/HealthController.cs create mode 100644 samples/Dressca/dressca-backend/src/Dressca.Web/DbHealthCheck.cs diff --git a/samples/Dressca/dressca-backend/src/Dressca.Web/Controllers/HealthController.cs b/samples/Dressca/dressca-backend/src/Dressca.Web/Controllers/HealthController.cs new file mode 100644 index 000000000..910a4e6f8 --- /dev/null +++ b/samples/Dressca/dressca-backend/src/Dressca.Web/Controllers/HealthController.cs @@ -0,0 +1,65 @@ +using System.Net; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Diagnostics.HealthChecks; + +namespace Dressca.Web.Controllers; + +/// +/// ヘルスチェック用のコントローラー。 +/// +[Route("api/health")] +[ApiController] +public class HealthController : ControllerBase +{ + private readonly HealthCheckService healthCheckService; + + /// + /// コンストラクター。 + /// + /// ヘルスチェックサービス。 + public HealthController(HealthCheckService healthCheckService) + { + this.healthCheckService = healthCheckService; + } + + /// + /// ヘルスチェックの結果を返します。 + /// + /// ヘルスチェックの結果。 + [HttpGet] + public async Task Get() + { + HealthReport report = await this.healthCheckService.CheckHealthAsync(); + + var result = new + { + status = report.Status.ToString(), + result = report.Entries + .Select(entry => new + { + name = entry.Key, + status = entry.Value.Status.ToString(), + description = entry.Value.Description?.ToString(), + data = entry.Value.Data, + exception = new + { + source = entry.Value.Exception?.Source, + message = entry.Value.Exception?.Message, + stackTrace = entry.Value.Exception?.StackTrace, + }, + }), + }; + return report.Status == HealthStatus.Healthy ? this.Ok(result) : this.StatusCode((int)HttpStatusCode.ServiceUnavailable, result); + } + + /// + /// ヘルスチェックの結果を返します。 + /// + /// ヘルスチェックの結果。 + [HttpHead] + public async Task Head() + { + HealthReport report = await this.healthCheckService.CheckHealthAsync(); + return report.Status == HealthStatus.Healthy ? this.Ok() : this.StatusCode((int)HttpStatusCode.ServiceUnavailable); + } +} diff --git a/samples/Dressca/dressca-backend/src/Dressca.Web/DbHealthCheck.cs b/samples/Dressca/dressca-backend/src/Dressca.Web/DbHealthCheck.cs new file mode 100644 index 000000000..cbf313bf8 --- /dev/null +++ b/samples/Dressca/dressca-backend/src/Dressca.Web/DbHealthCheck.cs @@ -0,0 +1,41 @@ +using System.Data.Common; +using Microsoft.Data.SqlClient; +using Microsoft.Extensions.Diagnostics.HealthChecks; + +namespace Dressca.Web; + +/// +/// データベースのヘルスチェックを行うクラスです。 +/// +public class DbHealthCheck : IHealthCheck +{ + private string connectionString = @"Server=(localdb)\mssqllocaldb;Database=Dressca.Eshop;Integrated Security=True"; + + /// + /// データベースへの接続を確認します。 + /// + /// ヘルスチェックコンテキスト。 + /// キャンセルトークン。 + /// ヘルスチェックの結果。 + public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) + { + using (var connection = new SqlConnection(this.connectionString)) + { + try + { + await connection.OpenAsync(cancellationToken); + + var command = connection.CreateCommand(); + command.CommandText = "SELECT 1"; + + await command.ExecuteNonQueryAsync(cancellationToken); + } + catch (DbException ex) + { + return new HealthCheckResult(status: context.Registration.FailureStatus, exception: ex); + } + } + + return HealthCheckResult.Healthy(); + } +} diff --git a/samples/Dressca/dressca-backend/src/Dressca.Web/Program.cs b/samples/Dressca/dressca-backend/src/Dressca.Web/Program.cs index 6b5dd0c0a..bdd47ee6d 100644 --- a/samples/Dressca/dressca-backend/src/Dressca.Web/Program.cs +++ b/samples/Dressca/dressca-backend/src/Dressca.Web/Program.cs @@ -2,6 +2,7 @@ using Dressca.ApplicationCore; using Dressca.EfInfrastructure; using Dressca.Store.Assets.StaticFiles; +using Dressca.Web; using Dressca.Web.Baskets; using Dressca.Web.Controllers; using Dressca.Web.Mapper; @@ -67,6 +68,9 @@ }); } +builder.Services.AddHealthChecks() + .AddCheck("DbHealthCheck"); + var app = builder.Build(); if (app.Environment.IsDevelopment()) diff --git a/samples/Dressca/dressca-backend/src/Dressca.Web/dressca-api.json b/samples/Dressca/dressca-backend/src/Dressca.Web/dressca-api.json index 21121f640..642090863 100644 --- a/samples/Dressca/dressca-backend/src/Dressca.Web/dressca-api.json +++ b/samples/Dressca/dressca-backend/src/Dressca.Web/dressca-api.json @@ -1,5 +1,5 @@ { - "x-generator": "NSwag v13.18.2.0 (NJsonSchema v10.8.0.0 (Newtonsoft.Json v13.0.0.0))", + "x-generator": "NSwag v13.19.0.0 (NJsonSchema v10.9.0.0 (Newtonsoft.Json v13.0.0.0))", "openapi": "3.0.0", "info": { "title": "Dressca Web API", @@ -26,8 +26,7 @@ "required": true, "description": "アセットコード。", "schema": { - "type": "string", - "nullable": true + "type": "string" }, "x-position": 1 } @@ -332,6 +331,48 @@ } } }, + "/api/health": { + "get": { + "tags": [ + "Health" + ], + "summary": "ヘルスチェックの結果を返します。", + "operationId": "Health_Get", + "responses": { + "200": { + "description": "ヘルスチェックの結果。", + "content": { + "application/octet-stream": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + } + } + }, + "head": { + "tags": [ + "Health" + ], + "summary": "ヘルスチェックの結果を返します。", + "operationId": "Health_Head", + "responses": { + "200": { + "description": "ヘルスチェックの結果。", + "content": { + "application/octet-stream": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + } + } + } + }, "/api/orders/{orderId}": { "get": { "tags": [