cd8c78d165
CI - Build & Test / Backend (.NET) (push) Successful in 45s
CI - Build & Test / Backend integration (PostgreSQL/Toxiproxy) (push) Failing after 1m0s
CI - Build & Test / Frontend (Vue/TS) (push) Successful in 2m49s
CI - Build & Test / Security Check (push) Successful in 7s
CI - Build & Test / Deploy Nexus (push) Has been skipped
87 lines
2.8 KiB
C#
87 lines
2.8 KiB
C#
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
|
using Nexus.Api.Integrations;
|
|
|
|
namespace Nexus.Api.Controllers;
|
|
|
|
[ApiController]
|
|
public class HealthController(IAgentRuntime runtime, HealthCheckService healthChecks) : ControllerBase
|
|
{
|
|
[AllowAnonymous]
|
|
[HttpGet("/health/live")]
|
|
public IResult Live()
|
|
=> Results.Ok(new
|
|
{
|
|
status = "Healthy",
|
|
timestamp = DateTimeOffset.UtcNow,
|
|
agentSource = "openclaw-rpc"
|
|
});
|
|
|
|
[AllowAnonymous]
|
|
[HttpGet("/health/ready")]
|
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
[ProducesResponseType(StatusCodes.Status503ServiceUnavailable)]
|
|
public async Task<IResult> Ready(CancellationToken ct)
|
|
{
|
|
var report = await healthChecks.CheckHealthAsync(
|
|
registration => registration.Tags.Contains("ready"),
|
|
ct);
|
|
var payload = new
|
|
{
|
|
status = report.Status == HealthStatus.Healthy ? "Healthy" : "Unhealthy",
|
|
timestamp = DateTimeOffset.UtcNow
|
|
};
|
|
|
|
return report.Status == HealthStatus.Healthy
|
|
? Results.Ok(payload)
|
|
: Results.Json(payload, statusCode: StatusCodes.Status503ServiceUnavailable);
|
|
}
|
|
|
|
[AllowAnonymous]
|
|
[HttpGet("/health")]
|
|
public async Task<IResult> Get(CancellationToken ct)
|
|
{
|
|
var report = await healthChecks.CheckHealthAsync(ct);
|
|
|
|
string runtimeStatus;
|
|
string? runtimeDetail;
|
|
try
|
|
{
|
|
var status = await runtime.GetStatusAsync(ct);
|
|
runtimeStatus = status.Status.ToString();
|
|
runtimeDetail = status.Detail;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
runtimeStatus = "Offline";
|
|
runtimeDetail = ex.Message;
|
|
}
|
|
|
|
static IReadOnlyDictionary<string, object?> NormalizeData(IReadOnlyDictionary<string, object> source)
|
|
{
|
|
return source.ToDictionary(kvp => kvp.Key, kvp => (object?)kvp.Value);
|
|
}
|
|
|
|
var entries = report.Entries.ToDictionary(
|
|
e => e.Key,
|
|
e => new
|
|
{
|
|
status = e.Value.Status.ToString(),
|
|
description = e.Value.Description,
|
|
data = NormalizeData(e.Value.Data)
|
|
});
|
|
|
|
entries["runtime"] = new
|
|
{
|
|
status = runtimeStatus,
|
|
description = runtimeDetail,
|
|
data = new Dictionary<string, object?>() as IReadOnlyDictionary<string, object?>
|
|
};
|
|
|
|
var isHealthy = report.Status == HealthStatus.Healthy && runtimeStatus == "Online";
|
|
return isHealthy ? Results.Ok(new { status = "Healthy", checks = entries, timestamp = DateTimeOffset.UtcNow })
|
|
: Results.Ok(new { status = "Degraded", checks = entries, timestamp = DateTimeOffset.UtcNow });
|
|
}
|
|
}
|