This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace StellaOps.Concelier.WebService.Contracts;
|
||||
|
||||
public sealed record AdvisorySummaryResponse(
|
||||
AdvisorySummaryMeta Meta,
|
||||
IReadOnlyList<AdvisorySummaryItem> Items);
|
||||
|
||||
public sealed record AdvisorySummaryMeta(
|
||||
string Tenant,
|
||||
int Count,
|
||||
string? Next,
|
||||
string Sort);
|
||||
|
||||
public sealed record AdvisorySummaryItem(
|
||||
string AdvisoryKey,
|
||||
string Source,
|
||||
string? LinksetId,
|
||||
double? Confidence,
|
||||
IReadOnlyList<AdvisorySummaryConflict>? Conflicts,
|
||||
AdvisorySummaryCounts Counts,
|
||||
AdvisorySummaryProvenance Provenance,
|
||||
IReadOnlyList<string> Aliases,
|
||||
string? ObservedAt);
|
||||
|
||||
public sealed record AdvisorySummaryConflict(
|
||||
string Field,
|
||||
string Reason,
|
||||
IReadOnlyList<string>? SourceIds);
|
||||
|
||||
public sealed record AdvisorySummaryCounts(
|
||||
int Observations,
|
||||
int ConflictFields);
|
||||
|
||||
public sealed record AdvisorySummaryProvenance(
|
||||
IReadOnlyList<string>? ObservationIds,
|
||||
string? Schema);
|
||||
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using StellaOps.Concelier.Core.Linksets;
|
||||
using StellaOps.Concelier.WebService.Contracts;
|
||||
|
||||
namespace StellaOps.Concelier.WebService.Extensions;
|
||||
|
||||
internal static class AdvisorySummaryMapper
|
||||
{
|
||||
public static AdvisorySummaryItem ToSummary(AdvisoryLinkset linkset)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(linkset);
|
||||
|
||||
var aliases = linkset.Normalized?.Purls ?? Array.Empty<string>();
|
||||
var conflictFields = linkset.Conflicts?.Select(c => c.Field).Distinct(StringComparer.Ordinal).Count() ?? 0;
|
||||
|
||||
var conflicts = linkset.Conflicts?.Select(c => new AdvisorySummaryConflict(
|
||||
c.Field,
|
||||
c.Reason,
|
||||
c.SourceIds?.ToArray()
|
||||
)).ToArray();
|
||||
|
||||
return new AdvisorySummaryItem(
|
||||
AdvisoryKey: linkset.AdvisoryId,
|
||||
Source: linkset.Source,
|
||||
LinksetId: linkset.BuiltByJobId,
|
||||
Confidence: linkset.Confidence,
|
||||
Conflicts: conflicts,
|
||||
Counts: new AdvisorySummaryCounts(
|
||||
Observations: linkset.ObservationIds.Length,
|
||||
ConflictFields: conflictFields),
|
||||
Provenance: new AdvisorySummaryProvenance(
|
||||
ObservationIds: linkset.ObservationIds.ToArray(),
|
||||
Schema: "lnm-1.0"),
|
||||
Aliases: aliases.ToArray(),
|
||||
ObservedAt: linkset.CreatedAt.UtcDateTime.ToString("O"));
|
||||
}
|
||||
|
||||
public static AdvisorySummaryResponse ToResponse(
|
||||
string tenant,
|
||||
IReadOnlyList<AdvisorySummaryItem> items,
|
||||
string? nextCursor,
|
||||
string sort)
|
||||
{
|
||||
return new AdvisorySummaryResponse(
|
||||
new AdvisorySummaryMeta(
|
||||
Tenant: tenant,
|
||||
Count: items.Count,
|
||||
Next: nextCursor,
|
||||
Sort: sort),
|
||||
items);
|
||||
}
|
||||
}
|
||||
@@ -1,47 +1,49 @@
|
||||
using System.Diagnostics.Metrics;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace StellaOps.Concelier.WebService.Telemetry;
|
||||
|
||||
internal sealed class LinksetCacheTelemetry
|
||||
{
|
||||
private static readonly Meter Meter = new("StellaOps.Concelier.Linksets");
|
||||
|
||||
private readonly Counter<long> _hitTotal;
|
||||
private readonly Counter<long> _writeTotal;
|
||||
private readonly Histogram<double> _rebuildMs;
|
||||
|
||||
public LinksetCacheTelemetry(IMeterFactory meterFactory)
|
||||
public LinksetCacheTelemetry()
|
||||
{
|
||||
var meter = meterFactory.Create("StellaOps.Concelier.Linksets");
|
||||
_hitTotal = meter.CreateCounter<long>("lnm.cache.hit_total", unit: "hit", description: "Cache hits for LNM linksets");
|
||||
_writeTotal = meter.CreateCounter<long>("lnm.cache.write_total", unit: "write", description: "Cache writes for LNM linksets");
|
||||
_rebuildMs = meter.CreateHistogram<double>("lnm.cache.rebuild_ms", unit: "ms", description: "Synchronous rebuild latency for LNM cache");
|
||||
_hitTotal = Meter.CreateCounter<long>("lnm.cache.hit_total", unit: "hit", description: "Cache hits for LNM linksets");
|
||||
_writeTotal = Meter.CreateCounter<long>("lnm.cache.write_total", unit: "write", description: "Cache writes for LNM linksets");
|
||||
_rebuildMs = Meter.CreateHistogram<double>("lnm.cache.rebuild_ms", unit: "ms", description: "Synchronous rebuild latency for LNM cache");
|
||||
}
|
||||
|
||||
public void RecordHit(string? tenant, string source)
|
||||
{
|
||||
var tags = new TagList
|
||||
var tags = new KeyValuePair<string, object?>[]
|
||||
{
|
||||
{ "tenant", tenant ?? string.Empty },
|
||||
{ "source", source }
|
||||
new("tenant", tenant ?? string.Empty),
|
||||
new("source", source)
|
||||
};
|
||||
_hitTotal.Add(1, tags);
|
||||
}
|
||||
|
||||
public void RecordWrite(string? tenant, string source)
|
||||
{
|
||||
var tags = new TagList
|
||||
var tags = new KeyValuePair<string, object?>[]
|
||||
{
|
||||
{ "tenant", tenant ?? string.Empty },
|
||||
{ "source", source }
|
||||
new("tenant", tenant ?? string.Empty),
|
||||
new("source", source)
|
||||
};
|
||||
_writeTotal.Add(1, tags);
|
||||
}
|
||||
|
||||
public void RecordRebuild(string? tenant, string source, double elapsedMs)
|
||||
{
|
||||
var tags = new TagList
|
||||
var tags = new KeyValuePair<string, object?>[]
|
||||
{
|
||||
{ "tenant", tenant ?? string.Empty },
|
||||
{ "source", source }
|
||||
new("tenant", tenant ?? string.Empty),
|
||||
new("source", source)
|
||||
};
|
||||
_rebuildMs.Record(elapsedMs, tags);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user