stabilizaiton work - projects rework for maintenanceability and ui livening
This commit is contained in:
@@ -83,3 +83,7 @@ Version comparators must be tested with 50+ cases per distro. See:
|
||||
- If a design decision is needed, mark the task `BLOCKED` in the sprint doc and record the decision ask???do not pause the codebase.
|
||||
- When changing contracts (APIs, schemas, telemetry, exports), update corresponding docs and link them from the sprint Decisions & Risks section.
|
||||
|
||||
## Service Endpoints
|
||||
- Development: https://localhost:10090, http://localhost:10091
|
||||
- Local alias: https://concelier.stella-ops.local, http://concelier.stella-ops.local
|
||||
- Env var: STELLAOPS_CONCELIER_URL
|
||||
|
||||
@@ -806,8 +806,11 @@ var pluginHostOptions = BuildPluginOptions(concelierOptions, builder.Environment
|
||||
builder.Services.RegisterPluginRoutines(builder.Configuration, pluginHostOptions);
|
||||
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddStellaOpsCors(builder.Environment, builder.Configuration);
|
||||
|
||||
builder.TryAddStellaOpsLocalBinding("concelier");
|
||||
var app = builder.Build();
|
||||
app.LogStellaOpsLocalHostname("concelier");
|
||||
var appTimeProvider = app.Services.GetRequiredService<TimeProvider>();
|
||||
var swaggerEnabled = app.Configuration.GetValue<bool>("Swagger:Enabled");
|
||||
|
||||
@@ -837,6 +840,8 @@ if (resolvedAuthority.Enabled && resolvedAuthority.AllowAnonymousFallback)
|
||||
"Authority authentication is configured but anonymous fallback remains enabled. Set authority.allowAnonymousFallback to false before 2025-12-31 to complete the rollout.");
|
||||
}
|
||||
|
||||
app.UseStellaOpsCors();
|
||||
|
||||
if (authorityConfigured)
|
||||
{
|
||||
app.UseAuthentication();
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
{
|
||||
"profiles": {
|
||||
"StellaOps.Concelier.WebService": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"applicationUrl": "https://localhost:50411;http://localhost:50412"
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
"profiles": {
|
||||
"StellaOps.Concelier.WebService": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
||||
"STELLAOPS_WEBSERVICES_CORS": "true",
|
||||
"STELLAOPS_WEBSERVICES_CORS_ORIGIN": "https://stella-ops.local,https://stella-ops.local:10000,https://localhost:10000"
|
||||
},
|
||||
"applicationUrl": "https://localhost:10090;http://localhost:10091"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,3 +8,4 @@ Source of truth: `docs-archived/implplan/2025-12-29-csproj-audit/SPRINT_20251229
|
||||
| AUDIT-0212-M | DONE | Revalidated 2026-01-06. |
|
||||
| AUDIT-0212-T | DONE | Revalidated 2026-01-06. |
|
||||
| AUDIT-0212-A | DONE | Waived (test project; revalidated 2026-01-06). |
|
||||
| REMED-08 | DONE | Added ingestion telemetry metric tag tests; `dotnet test src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/StellaOps.Concelier.Core.Tests.csproj` passed (2026-02-03). |
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
using System.Diagnostics.Metrics;
|
||||
using StellaOps.Ingestion.Telemetry;
|
||||
|
||||
namespace StellaOps.Concelier.Core.Tests.Telemetry;
|
||||
|
||||
internal static class IngestionTelemetryMetricsTestHelpers
|
||||
{
|
||||
internal static List<KeyValuePair<string, object?>[]> CaptureCounter(
|
||||
string instrumentName,
|
||||
Action action)
|
||||
{
|
||||
var measurements = new List<KeyValuePair<string, object?>[]>();
|
||||
using var listener = new MeterListener();
|
||||
listener.InstrumentPublished += (instrument, meterListener) =>
|
||||
{
|
||||
if (instrument.Meter.Name == IngestionTelemetry.MeterName && instrument.Name == instrumentName)
|
||||
{
|
||||
meterListener.EnableMeasurementEvents(instrument);
|
||||
}
|
||||
};
|
||||
|
||||
listener.SetMeasurementEventCallback<long>((instrument, measurement, tags, state) =>
|
||||
{
|
||||
if (instrument.Name == instrumentName)
|
||||
{
|
||||
measurements.Add(tags.ToArray());
|
||||
}
|
||||
});
|
||||
|
||||
listener.Start();
|
||||
action();
|
||||
return measurements;
|
||||
}
|
||||
|
||||
internal static List<KeyValuePair<string, object?>[]> CaptureHistogram(
|
||||
string instrumentName,
|
||||
Action action)
|
||||
{
|
||||
var measurements = new List<KeyValuePair<string, object?>[]>();
|
||||
using var listener = new MeterListener();
|
||||
listener.InstrumentPublished += (instrument, meterListener) =>
|
||||
{
|
||||
if (instrument.Meter.Name == IngestionTelemetry.MeterName && instrument.Name == instrumentName)
|
||||
{
|
||||
meterListener.EnableMeasurementEvents(instrument);
|
||||
}
|
||||
};
|
||||
|
||||
listener.SetMeasurementEventCallback<double>((instrument, measurement, tags, state) =>
|
||||
{
|
||||
if (instrument.Name == instrumentName)
|
||||
{
|
||||
measurements.Add(tags.ToArray());
|
||||
}
|
||||
});
|
||||
|
||||
listener.Start();
|
||||
action();
|
||||
return measurements;
|
||||
}
|
||||
|
||||
internal static object? GetTagValue(IEnumerable<KeyValuePair<string, object?>> tags, string key)
|
||||
{
|
||||
foreach (var tag in tags)
|
||||
{
|
||||
if (string.Equals(tag.Key, key, StringComparison.Ordinal))
|
||||
{
|
||||
return tag.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
using StellaOps.Ingestion.Telemetry;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Concelier.Core.Tests.Telemetry;
|
||||
|
||||
public sealed class IngestionTelemetryMetricsTests
|
||||
{
|
||||
[Fact]
|
||||
public void RecordWriteAttempt_EmitsResultTag()
|
||||
{
|
||||
var measurements = IngestionTelemetryMetricsTestHelpers.CaptureCounter(
|
||||
"ingestion_write_total",
|
||||
() => IngestionTelemetry.RecordWriteAttempt("tenant-1", "source-1", IngestionTelemetry.ResultOk));
|
||||
|
||||
Assert.Contains(
|
||||
measurements,
|
||||
tags => string.Equals(
|
||||
IngestionTelemetryMetricsTestHelpers.GetTagValue(tags, "result") as string,
|
||||
IngestionTelemetry.ResultOk,
|
||||
StringComparison.Ordinal));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RecordWriteAttempt_BlankResult_DoesNotEmit()
|
||||
{
|
||||
var measurements = IngestionTelemetryMetricsTestHelpers.CaptureCounter(
|
||||
"ingestion_write_total",
|
||||
() => IngestionTelemetry.RecordWriteAttempt("tenant-1", "source-1", " "));
|
||||
|
||||
Assert.Empty(measurements);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RecordViolation_EmitsCodeTag()
|
||||
{
|
||||
var measurements = IngestionTelemetryMetricsTestHelpers.CaptureCounter(
|
||||
"aoc_violation_total",
|
||||
() => IngestionTelemetry.RecordViolation("tenant-1", "source-1", "ERR_AOC_001"));
|
||||
|
||||
Assert.Contains(
|
||||
measurements,
|
||||
tags => string.Equals(
|
||||
IngestionTelemetryMetricsTestHelpers.GetTagValue(tags, "code") as string,
|
||||
"ERR_AOC_001",
|
||||
StringComparison.Ordinal));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RecordLatency_EmitsPhaseTag()
|
||||
{
|
||||
var measurements = IngestionTelemetryMetricsTestHelpers.CaptureHistogram(
|
||||
"ingestion_latency_seconds",
|
||||
() => IngestionTelemetry.RecordLatency(
|
||||
"tenant-1",
|
||||
"source-1",
|
||||
IngestionTelemetry.PhaseFetch,
|
||||
TimeSpan.FromSeconds(1)));
|
||||
|
||||
Assert.Contains(
|
||||
measurements,
|
||||
tags => string.Equals(
|
||||
IngestionTelemetryMetricsTestHelpers.GetTagValue(tags, "phase") as string,
|
||||
IngestionTelemetry.PhaseFetch,
|
||||
StringComparison.Ordinal));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RecordLatency_BlankPhase_DoesNotEmit()
|
||||
{
|
||||
var measurements = IngestionTelemetryMetricsTestHelpers.CaptureHistogram(
|
||||
"ingestion_latency_seconds",
|
||||
() => IngestionTelemetry.RecordLatency("tenant-1", "source-1", "", TimeSpan.FromSeconds(1)));
|
||||
|
||||
Assert.Empty(measurements);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user