sln build fix (again), tests fixes, audit work and doctors work
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
using System.Globalization;
|
||||
using System.Net.Sockets;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using StellaOps.Doctor.Models;
|
||||
using StellaOps.Doctor.Plugins;
|
||||
using StellaOps.Doctor.Plugins.Builders;
|
||||
|
||||
namespace StellaOps.Doctor.Plugins.ServiceGraph.Checks;
|
||||
|
||||
/// <summary>
|
||||
/// Verifies connectivity to message queue (RabbitMQ/other).
|
||||
/// </summary>
|
||||
public sealed class MessageQueueCheck : IDoctorCheck
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public string CheckId => "check.servicegraph.mq";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name => "Message Queue Connectivity";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Description => "Verifies connectivity to the message queue service";
|
||||
|
||||
/// <inheritdoc />
|
||||
public DoctorSeverity DefaultSeverity => DoctorSeverity.Warn;
|
||||
|
||||
/// <inheritdoc />
|
||||
public IReadOnlyList<string> Tags => ["connectivity", "messaging", "rabbitmq"];
|
||||
|
||||
/// <inheritdoc />
|
||||
public TimeSpan EstimatedDuration => TimeSpan.FromSeconds(5);
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool CanRun(DoctorPluginContext context)
|
||||
{
|
||||
var rabbitHost = context.Configuration.GetValue<string>("RabbitMQ:Host")
|
||||
?? context.Configuration.GetValue<string>("Messaging:RabbitMQ:Host");
|
||||
return !string.IsNullOrWhiteSpace(rabbitHost);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<DoctorCheckResult> RunAsync(DoctorPluginContext context, CancellationToken ct)
|
||||
{
|
||||
var result = context.CreateResult(CheckId, "stellaops.doctor.servicegraph", DoctorCategory.ServiceGraph.ToString());
|
||||
|
||||
var rabbitHost = context.Configuration.GetValue<string>("RabbitMQ:Host")
|
||||
?? context.Configuration.GetValue<string>("Messaging:RabbitMQ:Host");
|
||||
var rabbitPort = context.Configuration.GetValue<int?>("RabbitMQ:Port")
|
||||
?? context.Configuration.GetValue<int?>("Messaging:RabbitMQ:Port")
|
||||
?? 5672;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(rabbitHost))
|
||||
{
|
||||
return result
|
||||
.Skip("Message queue not configured")
|
||||
.WithEvidence("Configuration", e => e.Add("RabbitMQ:Host", "(not set)"))
|
||||
.Build();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using var client = new TcpClient();
|
||||
var connectTask = client.ConnectAsync(rabbitHost, rabbitPort, ct);
|
||||
var timeoutTask = Task.Delay(TimeSpan.FromSeconds(5), ct);
|
||||
|
||||
var completedTask = await Task.WhenAny(connectTask.AsTask(), timeoutTask);
|
||||
|
||||
if (completedTask == timeoutTask)
|
||||
{
|
||||
return result
|
||||
.Fail($"Connection to RabbitMQ at {rabbitHost}:{rabbitPort} timed out")
|
||||
.WithEvidence("Message queue connectivity", e =>
|
||||
{
|
||||
e.Add("Host", rabbitHost);
|
||||
e.Add("Port", rabbitPort.ToString(CultureInfo.InvariantCulture));
|
||||
e.Add("Status", "timeout");
|
||||
})
|
||||
.WithCauses(
|
||||
"RabbitMQ server is not running",
|
||||
"Network connectivity issues",
|
||||
"Firewall blocking AMQP port")
|
||||
.WithRemediation(r => r
|
||||
.AddManualStep(1, "Check RabbitMQ status", "docker ps | grep rabbitmq")
|
||||
.AddManualStep(2, "Check RabbitMQ logs", "docker logs rabbitmq")
|
||||
.AddManualStep(3, "Start RabbitMQ", "docker-compose up -d rabbitmq"))
|
||||
.WithVerification("stella doctor --check check.servicegraph.mq")
|
||||
.Build();
|
||||
}
|
||||
|
||||
await connectTask;
|
||||
|
||||
if (client.Connected)
|
||||
{
|
||||
return result
|
||||
.Pass($"Message queue reachable at {rabbitHost}:{rabbitPort}")
|
||||
.WithEvidence("Message queue connectivity", e =>
|
||||
{
|
||||
e.Add("Host", rabbitHost);
|
||||
e.Add("Port", rabbitPort.ToString(CultureInfo.InvariantCulture));
|
||||
e.Add("Status", "connected");
|
||||
})
|
||||
.Build();
|
||||
}
|
||||
else
|
||||
{
|
||||
return result
|
||||
.Fail($"Failed to connect to message queue at {rabbitHost}:{rabbitPort}")
|
||||
.WithEvidence("Message queue connectivity", e =>
|
||||
{
|
||||
e.Add("Host", rabbitHost);
|
||||
e.Add("Port", rabbitPort.ToString(CultureInfo.InvariantCulture));
|
||||
e.Add("Status", "connection_failed");
|
||||
})
|
||||
.Build();
|
||||
}
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
return result
|
||||
.Fail($"Socket error connecting to message queue: {ex.Message}")
|
||||
.WithEvidence("Message queue connectivity", e =>
|
||||
{
|
||||
e.Add("Host", rabbitHost);
|
||||
e.Add("Port", rabbitPort.ToString(CultureInfo.InvariantCulture));
|
||||
e.Add("SocketErrorCode", ex.SocketErrorCode.ToString());
|
||||
e.Add("Error", ex.Message);
|
||||
})
|
||||
.WithCauses(
|
||||
"RabbitMQ server is not running",
|
||||
"DNS resolution failed",
|
||||
"Network unreachable")
|
||||
.WithRemediation(r => r
|
||||
.AddManualStep(1, "Start RabbitMQ", "docker-compose up -d rabbitmq")
|
||||
.AddManualStep(2, "Verify DNS", $"nslookup {rabbitHost}"))
|
||||
.WithVerification("stella doctor --check check.servicegraph.mq")
|
||||
.Build();
|
||||
}
|
||||
catch (Exception ex) when (ex is not OperationCanceledException)
|
||||
{
|
||||
return result
|
||||
.Fail($"Error connecting to message queue: {ex.Message}")
|
||||
.WithEvidence("Message queue connectivity", e =>
|
||||
{
|
||||
e.Add("Host", rabbitHost);
|
||||
e.Add("Port", rabbitPort.ToString(CultureInfo.InvariantCulture));
|
||||
e.Add("ErrorType", ex.GetType().Name);
|
||||
e.Add("Error", ex.Message);
|
||||
})
|
||||
.Build();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user