forked from xiongyuxing/tiku-backend.net
67 lines
2.3 KiB
C#
67 lines
2.3 KiB
C#
using System.Diagnostics.Metrics;
|
|
using Npgsql;
|
|
using Tiku.Infrastructure.Messaging;
|
|
|
|
namespace Tiku.Api.Observability;
|
|
|
|
public sealed class OutboxBacklogSnapshot
|
|
{
|
|
private static readonly Meter Meter = new("Tiku.Messaging", "1.0.0");
|
|
private long pending;
|
|
private double oldestAgeSeconds;
|
|
|
|
public OutboxBacklogSnapshot()
|
|
{
|
|
Meter.CreateObservableGauge("tiku.outbox.pending", () => Interlocked.Read(ref pending));
|
|
Meter.CreateObservableGauge("tiku.outbox.oldest_age", () => Volatile.Read(ref oldestAgeSeconds), "s");
|
|
}
|
|
|
|
internal long Pending => Interlocked.Read(ref pending);
|
|
internal double OldestAgeSeconds => Volatile.Read(ref oldestAgeSeconds);
|
|
|
|
internal void Update(long count, DateTime? oldestSentTime)
|
|
{
|
|
Interlocked.Exchange(ref pending, count);
|
|
Volatile.Write(ref oldestAgeSeconds, oldestSentTime is null
|
|
? 0
|
|
: Math.Max(0, (DateTimeOffset.UtcNow - new DateTimeOffset(oldestSentTime.Value)).TotalSeconds));
|
|
}
|
|
}
|
|
|
|
internal sealed class OutboxBacklogMonitor(
|
|
NpgsqlDataSource dataSource,
|
|
OutboxBacklogSnapshot snapshot,
|
|
MessagingOptions messagingOptions,
|
|
ILogger<OutboxBacklogMonitor> logger) : BackgroundService
|
|
{
|
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
|
{
|
|
while (!stoppingToken.IsCancellationRequested)
|
|
{
|
|
try
|
|
{
|
|
if (messagingOptions.IsConfigured)
|
|
{
|
|
await using var command = dataSource.CreateCommand(
|
|
"SELECT count(*), min(sent_time) FROM outbox_message;");
|
|
await using var reader = await command.ExecuteReaderAsync(stoppingToken);
|
|
if (await reader.ReadAsync(stoppingToken))
|
|
{
|
|
snapshot.Update(reader.GetInt64(0), reader.IsDBNull(1) ? null : reader.GetDateTime(1));
|
|
}
|
|
}
|
|
}
|
|
catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
|
|
{
|
|
break;
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
logger.LogWarning(exception, "Outbox backlog metric collection failed.");
|
|
}
|
|
|
|
await Task.Delay(TimeSpan.FromSeconds(30), stoppingToken);
|
|
}
|
|
}
|
|
}
|