This commit is contained in:
StellaOps Bot
2025-12-09 00:20:52 +02:00
parent 3d01bf9edc
commit bc0762e97d
261 changed files with 14033 additions and 4427 deletions

View File

@@ -1,11 +1,9 @@
using System;
using System.Linq;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using StellaOps.Signals.Models;
using StellaOps.Signals.Options;
namespace StellaOps.Signals.Services;
@@ -15,65 +13,27 @@ namespace StellaOps.Signals.Services;
internal sealed class InMemoryEventsPublisher : IEventsPublisher
{
private readonly ILogger<InMemoryEventsPublisher> logger;
private readonly string topic;
private readonly ReachabilityFactEventBuilder eventBuilder;
private static readonly JsonSerializerOptions SerializerOptions = new(JsonSerializerDefaults.Web)
{
WriteIndented = false,
DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull
};
public InMemoryEventsPublisher(ILogger<InMemoryEventsPublisher> logger, SignalsOptions options)
public InMemoryEventsPublisher(ILogger<InMemoryEventsPublisher> logger, ReachabilityFactEventBuilder eventBuilder)
{
this.logger = logger;
topic = string.IsNullOrWhiteSpace(options?.AirGap?.EventTopic)
? "signals.fact.updated"
: options!.AirGap.EventTopic!;
this.eventBuilder = eventBuilder ?? throw new ArgumentNullException(nameof(eventBuilder));
}
public Task PublishFactUpdatedAsync(ReachabilityFactDocument fact, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(fact);
var (reachable, unreachable) = CountStates(fact);
var runtimeFactsCount = fact.RuntimeFacts?.Count ?? 0;
var avgConfidence = fact.States.Count > 0 ? fact.States.Average(s => s.Confidence) : 0;
var score = fact.Score;
var unknownsCount = fact.UnknownsCount;
var unknownsPressure = fact.UnknownsPressure;
var topBucket = fact.States.Count > 0
? fact.States
.GroupBy(s => s.Bucket, StringComparer.OrdinalIgnoreCase)
.OrderByDescending(g => g.Count())
.ThenByDescending(g => g.Average(s => s.Weight))
.First()
: null;
var payload = new ReachabilityFactUpdatedEvent(
Version: "signals.fact.updated@v1",
SubjectKey: fact.SubjectKey,
CallgraphId: string.IsNullOrWhiteSpace(fact.CallgraphId) ? null : fact.CallgraphId,
OccurredAtUtc: DateTimeOffset.UtcNow,
ReachableCount: reachable,
UnreachableCount: unreachable,
RuntimeFactsCount: runtimeFactsCount,
Bucket: topBucket?.Key ?? "unknown",
Weight: topBucket?.Average(s => s.Weight) ?? 0,
StateCount: fact.States.Count,
FactScore: score,
UnknownsCount: unknownsCount,
UnknownsPressure: unknownsPressure,
AverageConfidence: avgConfidence,
ComputedAtUtc: fact.ComputedAt,
Targets: fact.States.Select(s => s.Target).ToArray());
var envelope = eventBuilder.Build(fact);
var json = JsonSerializer.Serialize(envelope, SerializerOptions);
var json = JsonSerializer.Serialize(payload, new JsonSerializerOptions(JsonSerializerDefaults.Web));
logger.LogInformation("{Topic} {Payload}", topic, json);
logger.LogInformation(json);
return Task.CompletedTask;
}
private static (int reachable, int unreachable) CountStates(ReachabilityFactDocument fact)
{
if (fact.States is null || fact.States.Count == 0)
{
return (0, 0);
}
var reachable = fact.States.Count(state => state.Reachable);
var unreachable = fact.States.Count - reachable;
return (reachable, unreachable);
}
}