stabilizaiton work - projects rework for maintenanceability and ui livening
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace StellaOps.Ingestion.Telemetry;
|
||||
|
||||
public static partial class IngestionTelemetry
|
||||
{
|
||||
private static readonly ActivitySource _activitySource = new(ActivitySourceName);
|
||||
|
||||
public static Activity? StartFetchActivity(
|
||||
string tenant,
|
||||
string source,
|
||||
string? upstreamId,
|
||||
string? contentHash,
|
||||
string? uri = null)
|
||||
=> StartActivity("ingest.fetch", tenant, source, upstreamId, contentHash, builder: activity =>
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(uri))
|
||||
{
|
||||
activity.SetTag("uri", uri);
|
||||
}
|
||||
});
|
||||
|
||||
public static Activity? StartTransformActivity(
|
||||
string tenant,
|
||||
string source,
|
||||
string? upstreamId,
|
||||
string? contentHash,
|
||||
string? documentType = null,
|
||||
long? payloadBytes = null)
|
||||
=> StartActivity("ingest.transform", tenant, source, upstreamId, contentHash, builder: activity =>
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(documentType))
|
||||
{
|
||||
activity.SetTag("documentType", documentType);
|
||||
}
|
||||
|
||||
if (payloadBytes.HasValue && payloadBytes.Value >= 0)
|
||||
{
|
||||
activity.SetTag("payloadBytes", payloadBytes.Value);
|
||||
}
|
||||
});
|
||||
|
||||
public static Activity? StartWriteActivity(
|
||||
string tenant,
|
||||
string source,
|
||||
string? upstreamId,
|
||||
string? contentHash,
|
||||
string collection)
|
||||
=> StartActivity("ingest.write", tenant, source, upstreamId, contentHash, builder: activity =>
|
||||
{
|
||||
activity.SetTag("collection", collection);
|
||||
});
|
||||
|
||||
public static Activity? StartGuardActivity(
|
||||
string tenant,
|
||||
string source,
|
||||
string? upstreamId,
|
||||
string? contentHash,
|
||||
string? supersedes)
|
||||
=> StartActivity("aoc.guard", tenant, source, upstreamId, contentHash, builder: activity =>
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(supersedes))
|
||||
{
|
||||
activity.SetTag("supersedes", supersedes);
|
||||
}
|
||||
});
|
||||
|
||||
private static Activity? StartActivity(
|
||||
string name,
|
||||
string tenant,
|
||||
string source,
|
||||
string? upstreamId,
|
||||
string? contentHash,
|
||||
Action<Activity>? builder = null)
|
||||
{
|
||||
var activity = _activitySource.StartActivity(name, ActivityKind.Internal);
|
||||
if (activity is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(tenant))
|
||||
{
|
||||
activity.SetTag("tenant", tenant);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(source))
|
||||
{
|
||||
activity.SetTag("source", source);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(upstreamId))
|
||||
{
|
||||
activity.SetTag("upstream.id", upstreamId);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(contentHash))
|
||||
{
|
||||
activity.SetTag("contentHash", contentHash);
|
||||
}
|
||||
|
||||
builder?.Invoke(activity);
|
||||
return activity;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.Metrics;
|
||||
|
||||
namespace StellaOps.Ingestion.Telemetry;
|
||||
|
||||
public static partial class IngestionTelemetry
|
||||
{
|
||||
private const string _writeMetricName = "ingestion_write_total";
|
||||
private const string _violationMetricName = "aoc_violation_total";
|
||||
private const string _latencyMetricName = "ingestion_latency_seconds";
|
||||
|
||||
private static readonly Meter _meter = new(MeterName);
|
||||
|
||||
private static readonly Counter<long> _writeCounter = _meter.CreateCounter<long>(
|
||||
_writeMetricName,
|
||||
unit: "count",
|
||||
description: "Counts raw advisory ingestion attempts grouped by tenant, source, and outcome.");
|
||||
|
||||
private static readonly Counter<long> _violationCounter = _meter.CreateCounter<long>(
|
||||
_violationMetricName,
|
||||
unit: "count",
|
||||
description: "Counts Aggregation-Only Contract violations raised during ingestion.");
|
||||
|
||||
private static readonly Histogram<double> _latencyHistogram = _meter.CreateHistogram<double>(
|
||||
_latencyMetricName,
|
||||
unit: "s",
|
||||
description: "Ingestion stage latency measured in seconds.");
|
||||
|
||||
public static void RecordWriteAttempt(string tenant, string source, string result)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(tenant) || string.IsNullOrWhiteSpace(source) || string.IsNullOrWhiteSpace(result))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var tags = new TagList
|
||||
{
|
||||
{ "tenant", tenant },
|
||||
{ "source", source },
|
||||
{ "result", result }
|
||||
};
|
||||
|
||||
_writeCounter.Add(1, tags);
|
||||
}
|
||||
|
||||
public static void RecordViolation(string tenant, string source, string code)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(tenant) || string.IsNullOrWhiteSpace(source) || string.IsNullOrWhiteSpace(code))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var tags = new TagList
|
||||
{
|
||||
{ "tenant", tenant },
|
||||
{ "source", source },
|
||||
{ "code", code }
|
||||
};
|
||||
|
||||
_violationCounter.Add(1, tags);
|
||||
}
|
||||
|
||||
public static void RecordLatency(string tenant, string source, string phase, TimeSpan duration)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(tenant) || string.IsNullOrWhiteSpace(source) || string.IsNullOrWhiteSpace(phase))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var tags = new TagList
|
||||
{
|
||||
{ "tenant", tenant },
|
||||
{ "source", source },
|
||||
{ "phase", phase }
|
||||
};
|
||||
|
||||
var seconds = duration.TotalSeconds;
|
||||
if (double.IsNaN(seconds) || double.IsInfinity(seconds))
|
||||
{
|
||||
seconds = 0d;
|
||||
}
|
||||
|
||||
if (seconds < 0)
|
||||
{
|
||||
seconds = 0d;
|
||||
}
|
||||
|
||||
_latencyHistogram.Record(seconds, tags);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,6 @@
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.Metrics;
|
||||
|
||||
namespace StellaOps.Ingestion.Telemetry;
|
||||
|
||||
public static class IngestionTelemetry
|
||||
public static partial class IngestionTelemetry
|
||||
{
|
||||
public const string ActivitySourceName = "StellaOps.Ingestion";
|
||||
public const string MeterName = "StellaOps.Ingestion";
|
||||
@@ -15,185 +12,4 @@ public static class IngestionTelemetry
|
||||
public const string ResultOk = "ok";
|
||||
public const string ResultReject = "reject";
|
||||
public const string ResultNoop = "noop";
|
||||
|
||||
private const string WriteMetricName = "ingestion_write_total";
|
||||
private const string ViolationMetricName = "aoc_violation_total";
|
||||
private const string LatencyMetricName = "ingestion_latency_seconds";
|
||||
|
||||
private static readonly ActivitySource ActivitySource = new(ActivitySourceName);
|
||||
private static readonly Meter Meter = new(MeterName);
|
||||
|
||||
private static readonly Counter<long> WriteCounter = Meter.CreateCounter<long>(
|
||||
WriteMetricName,
|
||||
unit: "count",
|
||||
description: "Counts raw advisory ingestion attempts grouped by tenant, source, and outcome.");
|
||||
|
||||
private static readonly Counter<long> ViolationCounter = Meter.CreateCounter<long>(
|
||||
ViolationMetricName,
|
||||
unit: "count",
|
||||
description: "Counts Aggregation-Only Contract violations raised during ingestion.");
|
||||
|
||||
private static readonly Histogram<double> LatencyHistogram = Meter.CreateHistogram<double>(
|
||||
LatencyMetricName,
|
||||
unit: "s",
|
||||
description: "Ingestion stage latency measured in seconds.");
|
||||
|
||||
public static Activity? StartFetchActivity(
|
||||
string tenant,
|
||||
string source,
|
||||
string? upstreamId,
|
||||
string? contentHash,
|
||||
string? uri = null)
|
||||
=> StartActivity("ingest.fetch", tenant, source, upstreamId, contentHash, builder: activity =>
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(uri))
|
||||
{
|
||||
activity.SetTag("uri", uri);
|
||||
}
|
||||
});
|
||||
|
||||
public static Activity? StartTransformActivity(
|
||||
string tenant,
|
||||
string source,
|
||||
string? upstreamId,
|
||||
string? contentHash,
|
||||
string? documentType = null,
|
||||
long? payloadBytes = null)
|
||||
=> StartActivity("ingest.transform", tenant, source, upstreamId, contentHash, builder: activity =>
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(documentType))
|
||||
{
|
||||
activity.SetTag("documentType", documentType);
|
||||
}
|
||||
|
||||
if (payloadBytes.HasValue && payloadBytes.Value >= 0)
|
||||
{
|
||||
activity.SetTag("payloadBytes", payloadBytes.Value);
|
||||
}
|
||||
});
|
||||
|
||||
public static Activity? StartWriteActivity(
|
||||
string tenant,
|
||||
string source,
|
||||
string? upstreamId,
|
||||
string? contentHash,
|
||||
string collection)
|
||||
=> StartActivity("ingest.write", tenant, source, upstreamId, contentHash, builder: activity =>
|
||||
{
|
||||
activity.SetTag("collection", collection);
|
||||
});
|
||||
|
||||
public static Activity? StartGuardActivity(
|
||||
string tenant,
|
||||
string source,
|
||||
string? upstreamId,
|
||||
string? contentHash,
|
||||
string? supersedes)
|
||||
=> StartActivity("aoc.guard", tenant, source, upstreamId, contentHash, builder: activity =>
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(supersedes))
|
||||
{
|
||||
activity.SetTag("supersedes", supersedes);
|
||||
}
|
||||
});
|
||||
|
||||
public static void RecordWriteAttempt(string tenant, string source, string result)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(tenant) || string.IsNullOrWhiteSpace(source) || string.IsNullOrWhiteSpace(result))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var tags = new TagList
|
||||
{
|
||||
{ "tenant", tenant },
|
||||
{ "source", source },
|
||||
{ "result", result }
|
||||
};
|
||||
|
||||
WriteCounter.Add(1, tags);
|
||||
}
|
||||
|
||||
public static void RecordViolation(string tenant, string source, string code)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(tenant) || string.IsNullOrWhiteSpace(source) || string.IsNullOrWhiteSpace(code))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var tags = new TagList
|
||||
{
|
||||
{ "tenant", tenant },
|
||||
{ "source", source },
|
||||
{ "code", code }
|
||||
};
|
||||
|
||||
ViolationCounter.Add(1, tags);
|
||||
}
|
||||
|
||||
public static void RecordLatency(string tenant, string source, string phase, TimeSpan duration)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(tenant) || string.IsNullOrWhiteSpace(source) || string.IsNullOrWhiteSpace(phase))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var tags = new TagList
|
||||
{
|
||||
{ "tenant", tenant },
|
||||
{ "source", source },
|
||||
{ "phase", phase }
|
||||
};
|
||||
|
||||
var seconds = duration.TotalSeconds;
|
||||
if (double.IsNaN(seconds) || double.IsInfinity(seconds))
|
||||
{
|
||||
seconds = 0d;
|
||||
}
|
||||
|
||||
if (seconds < 0)
|
||||
{
|
||||
seconds = 0d;
|
||||
}
|
||||
|
||||
LatencyHistogram.Record(seconds, tags);
|
||||
}
|
||||
|
||||
private static Activity? StartActivity(
|
||||
string name,
|
||||
string tenant,
|
||||
string source,
|
||||
string? upstreamId,
|
||||
string? contentHash,
|
||||
Action<Activity>? builder = null)
|
||||
{
|
||||
var activity = ActivitySource.StartActivity(name, ActivityKind.Internal);
|
||||
if (activity is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(tenant))
|
||||
{
|
||||
activity.SetTag("tenant", tenant);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(source))
|
||||
{
|
||||
activity.SetTag("source", source);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(upstreamId))
|
||||
{
|
||||
activity.SetTag("upstream.id", upstreamId);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(contentHash))
|
||||
{
|
||||
activity.SetTag("contentHash", contentHash);
|
||||
}
|
||||
|
||||
builder?.Invoke(activity);
|
||||
return activity;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,3 +9,4 @@ Source of truth: `docs-archived/implplan/2025-12-29-csproj-audit/SPRINT_20251229
|
||||
| AUDIT-0090-T | DONE | Revalidated 2026-01-08; test coverage audit for Ingestion.Telemetry. |
|
||||
| AUDIT-0090-A | TODO | Pending approval (non-test project; revalidated 2026-01-08). |
|
||||
| REMED-06 | DONE | SOLID review notes captured for SPRINT_20260130_002. |
|
||||
| REMED-08 | DONE | Split IngestionTelemetry into activity/metrics partials, renamed private fields, added metric tag tests; `dotnet test src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/StellaOps.Concelier.Core.Tests.csproj` passed (2026-02-03). |
|
||||
|
||||
Reference in New Issue
Block a user