gpt4 book ai didi

asp.net-core - 如何将健康检查端点添加到 ApiExplorer,以便 Swashbuck 将其包含在生成的 swagger.json 中

转载 作者:行者123 更新时间:2023-12-04 17:26:18 24 4
gpt4 key购买 nike

我已添加 Microsoft.AspNetCore.Diagnostics.HealthChecks样式健康检查到我的应用程序为 documented by Microsoft here .
我也在用 Swashbuckle生成 swagger 文档。然后我使用 NSwag生成客户端 API 供我的其他应用程序使用。
问题是健康检查端点添加了 MapHealthChecks在 Startup.cs 中没有被添加到 ApiExplorer .这是一个问题,因为 Swashbuckle 使用它来生成 swagger 文档。
所以我的问题是将健康检查端点添加到 ApiExplorer 以便 Swashbuckle 可以将它包含在 swagger 文件中的最佳方法是什么?
我试图手动添加健康检查端点 add ApiExplorer(下面的代码)。应用程序运行成功,但 swagger 文档不包含端点。

// from Startup.cs

public virtual void ConfigureServices(IServiceCollection services)
{
// ...

// add swagger
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
});

// add healthchecks
services
.AddHealthChecks()
.AddDbContextCheck<DatabaseDomain.DbContext>(tags: new[] { "db" })
;

// ...

}

public virtual void Configure(IApplicationBuilder app, IHostEnvironment env, IApiDescriptionGroupCollectionProvider apiExplorer)
{
// ...

app.UseEndpoints(endpoints =>
{
endpoints.
.MapHealthChecks("/healthcheck", new HealthCheckOptions
{
Predicate = _ => true, // allow all healthchecks
AllowCachingResponses = false,

// custom writer to return health check results as JSON
ResponseWriter = (context, result) => {
context.Response.ContentType = "application/json";
// serialize the health check results
var json = System.Text.Json.JsonSerializer.Serialize(new
{
// my custom response object
});

return context.Response.WriteAsync(json);
},
})
.RequireAuthorization()
;
});

// attempt to get the healthcheck endpoint to ApiExplorer
var healthcheckDescription = new ApiDescription
{
HttpMethod = "GET",
RelativePath = "/healthcheck",
};

healthcheckDescription.SupportedRequestFormats.Add(new ApiRequestFormat
{
MediaType = "application/json"
});

healthcheckDescription.SupportedResponseTypes.Add(new ApiResponseType
{
IsDefaultResponse = true,
StatusCode = (int)HttpStatusCode.OK,
ApiResponseFormats = new List<ApiResponseFormat> {
new ApiResponseFormat
{
MediaType = "application/json"
}
}
});

apiExplorer.ApiDescriptionGroups.Items.Append(new ApiDescriptionGroup("HealthCheck", new List<ApiDescription> { healthcheckDescription }));

// configure swagger
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
});

// ...
}

最佳答案

我最终创建了一个专门用于返回健康检查的 Controller GET api/healthchecks .
这允许我提供有关端点返回的数据类型的信息,并控制返回数据的格式。
这是 Swagger UI 给出的示例响应:

{
"status": "string",
"totalDurationMs": 0,
"apiVersion": "string",
"apiVersionDescription": "string",
"healthChecks": [
{
"name": "string",
"status": "string",
"description": "string",
"durationMs": 0,
"tags": ["string"],
"data": [
{
"key": "string",
"value": {}
}
]
}
]
}
这是一个实际的回应:
{
"status": "Healthy",
"totalDurationMs": 82,
"apiVersion": "0.0.4-rc",
"apiVersionDescription": "0.0.3 at commit 2b188d3 [25 ahead] on branch release/0.0.4 (0.0.4-rc)",
"healthChecks": [
{
"name": "DbContext",
"status": "Healthy",
"description": null,
"durationMs": 72,
"tags": ["db"],
"data": []
}
]
}
下面是我的实现。
Startup.cs

public virtual void ConfigureServices(IServiceCollection services)
{
// ...

// add swagger
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
});

// This allows me to access the HealthCheckOptions in my controllers
services
.AddSingleton(services => new HealthCheckOptions
{
Predicate = _ => true, // allow all healthchecks
AllowCachingResponses = false,
})
;

// add healthchecks
services
.AddHealthChecks()
.AddDbContextCheck<DatabaseDomain.DbContext>(tags: new[] { "db" })
;

// ...

}
HealthCheckController.cs
我们的 HealthCheckController 包含一个 Index将响应 GET api/healthcheck 的端点. Index返回自定义 HealthCheckReport对象是实际 HealthReport 的包装器目的。这使我能够控制返回的数据以及结构。我这样做是因为我想添加其他信息,例如应用程序版本和提交详细信息。
如果你不关心返回数据的格式,你可以返回 HealthReport对象存储在 report多变的。您需要将返回类型更改为 Task<HealthReport>以及在 ProducesResponseType属性。
我使用依赖注入(inject)来请求 HealthCheckServiceHealthCheckOptions对象。 HealthCheckService用于生成实际报告。 HealthCheckOptions用于访问我们在 Setup.cs 中所做的配置。
[Route("api/[controller]")]
[ApiController]
public class HealthCheckController : AppController
{
[HttpGet(Name = "Healthcheck")]
[ProducesResponseType(typeof(HealthCheckReport), (int)HttpStatusCode.OK)]
[ProducesResponseType(typeof(HealthCheckReport), (int)HttpStatusCode.ServiceUnavailable)]
public async Task<HealthCheckReport> Index(
[FromServices] HealthCheckService healthCheckService,
[FromServices] HealthCheckOptions healthCheckOptions
)
{
var report = await healthCheckService.CheckHealthAsync(healthCheckOptions.Predicate, HttpContext.RequestAborted);

Response.StatusCode = healthCheckOptions.ResultStatusCodes[report.Status];
Response.ContentType = "application/json";

// if you want you can instead return `report`, but you would
// also need to change the return type to Task<HealthReport>
// as well as the in the ProducesResponseType attributes.
return new HealthCheckReport
{
Status = report.Status.ToString(),
TotalDurationMs = report.TotalDuration.Milliseconds,
HealthChecks = report.Entries.Select(pair =>
{
var entry = pair.Value;

return new HealthCheck
{
Name = pair.Key,
Status = entry.Status.ToString(),
Description = entry.Description,
DurationMs = entry.Duration.Milliseconds,
Tags = entry.Tags,
Data = entry.Data.Select(p => new HealthCheckData { Key = p.Key, Value = p.Value }),
};
}),
};
}
}
剩余的类用于转换 HealthCheck对象放入我想从 GET api/healthchecks 返回的数据结构中端点。
我只使用这些对象,因为我不满意 HealthCheck序列化为 JSON,因为我想提供额外的数据。
例如,我添加了其他属性,例如 ApiVersion ,这样我就可以知道部署了我的应用程序的哪个版本。
HealthCheckReport.cs
public class HealthCheckReport
{
public string Status { get; set; }
public int TotalDurationMs { get; set; }

public string ApiVersion => Startup.SemanticVersion;
public string ApiVersionDescription => Startup.InformationalVersion;

public IEnumerable<HealthCheck> HealthChecks { get; set; } = new HealthCheck[] { };
}
HealthCheck.cs
public class HealthCheck
{
public string Name { get; set; }
public string Status { get; set; }
public string Description { get; set; }
public int DurationMs { get; set; }
public IEnumerable<string> Tags { get; set; } = new string[] { };
public IEnumerable<HealthCheckData> Data { get; set; } = new HealthCheckData[] { };
}

HealthCheckData.cs
public class HealthCheckData
{
public string Key { get; set; }
public object Value { get; set; }
}

关于asp.net-core - 如何将健康检查端点添加到 ApiExplorer,以便 Swashbuck 将其包含在生成的 swagger.json 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63066572/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com