Refactor code structure for improved readability and maintainability; optimize performance in key functions.
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
// Sprint: SPRINT_4300_0003_0002
|
||||
// Task: T2 - Completeness Ratio Calculator
|
||||
|
||||
namespace StellaOps.Telemetry.Core.Metrics;
|
||||
|
||||
/// <summary>
|
||||
/// Result of attestation completeness calculation.
|
||||
/// </summary>
|
||||
public sealed record CompletenessResult
|
||||
{
|
||||
public required string ArtifactDigest { get; init; }
|
||||
public required double CompletenessRatio { get; init; }
|
||||
public required IReadOnlyList<string> FoundTypes { get; init; }
|
||||
public required IReadOnlyList<string> MissingTypes { get; init; }
|
||||
public required bool IsComplete { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates attestation completeness for artifacts.
|
||||
/// </summary>
|
||||
public interface IAttestationCompletenessCalculator
|
||||
{
|
||||
/// <summary>
|
||||
/// Calculate completeness ratio for an artifact.
|
||||
/// Complete = has all required attestation types.
|
||||
/// </summary>
|
||||
Task<CompletenessResult> CalculateAsync(
|
||||
string artifactDigest,
|
||||
IReadOnlyList<string> requiredTypes,
|
||||
CancellationToken ct = default);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of attestation completeness calculator.
|
||||
/// </summary>
|
||||
public sealed class AttestationCompletenessCalculator : IAttestationCompletenessCalculator
|
||||
{
|
||||
private readonly IOciReferrerDiscovery _discovery;
|
||||
private readonly AttestationMetrics? _metrics;
|
||||
|
||||
public AttestationCompletenessCalculator(
|
||||
IOciReferrerDiscovery discovery,
|
||||
AttestationMetrics? metrics = null)
|
||||
{
|
||||
_discovery = discovery;
|
||||
_metrics = metrics;
|
||||
}
|
||||
|
||||
public async Task<CompletenessResult> CalculateAsync(
|
||||
string artifactDigest,
|
||||
IReadOnlyList<string> requiredTypes,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
var referrers = await _discovery.ListReferrersAsync(artifactDigest, ct);
|
||||
|
||||
var foundTypes = referrers.Referrers
|
||||
.Select(r => MapArtifactType(r.ArtifactType))
|
||||
.Distinct()
|
||||
.ToHashSet();
|
||||
|
||||
var missingTypes = requiredTypes.Except(foundTypes).ToList();
|
||||
var ratio = requiredTypes.Count > 0
|
||||
? (double)(requiredTypes.Count - missingTypes.Count) / requiredTypes.Count
|
||||
: 1.0;
|
||||
|
||||
return new CompletenessResult
|
||||
{
|
||||
ArtifactDigest = artifactDigest,
|
||||
CompletenessRatio = ratio,
|
||||
FoundTypes = foundTypes.ToList(),
|
||||
MissingTypes = missingTypes,
|
||||
IsComplete = missingTypes.Count == 0
|
||||
};
|
||||
}
|
||||
|
||||
private static string MapArtifactType(string ociArtifactType)
|
||||
{
|
||||
// Map OCI artifact types to predicate types
|
||||
// Example: "application/vnd.in-toto+json" -> "sbom@v1"
|
||||
return ociArtifactType switch
|
||||
{
|
||||
"application/vnd.in-toto+json" => "attestation",
|
||||
"application/vnd.oci.image.manifest.v1+json" => "manifest",
|
||||
_ => ociArtifactType
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OCI referrer discovery interface.
|
||||
/// </summary>
|
||||
public interface IOciReferrerDiscovery
|
||||
{
|
||||
/// <summary>
|
||||
/// List referrers for an artifact.
|
||||
/// </summary>
|
||||
Task<ReferrersList> ListReferrersAsync(string artifactDigest, CancellationToken ct = default);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List of referrers for an artifact.
|
||||
/// </summary>
|
||||
public sealed record ReferrersList
|
||||
{
|
||||
public required IReadOnlyList<Referrer> Referrers { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A referrer (e.g., attestation, signature) pointing to an artifact.
|
||||
/// </summary>
|
||||
public sealed record Referrer
|
||||
{
|
||||
public required string ArtifactType { get; init; }
|
||||
public required string Digest { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
// Sprint: SPRINT_4300_0003_0002
|
||||
// Task: T1 - Define Attestation Metrics
|
||||
|
||||
using System.Diagnostics.Metrics;
|
||||
|
||||
namespace StellaOps.Telemetry.Core.Metrics;
|
||||
|
||||
/// <summary>
|
||||
/// Metrics for attestation completeness and quality.
|
||||
/// </summary>
|
||||
public sealed class AttestationMetrics
|
||||
{
|
||||
private readonly Meter _meter;
|
||||
|
||||
// Counters
|
||||
private readonly Counter<long> _attestationsCreated;
|
||||
private readonly Counter<long> _attestationsVerified;
|
||||
private readonly Counter<long> _attestationsFailed;
|
||||
|
||||
// Histograms
|
||||
private readonly Histogram<double> _ttfeSeconds;
|
||||
private readonly Histogram<double> _verificationDuration;
|
||||
|
||||
public AttestationMetrics(IMeterFactory meterFactory)
|
||||
{
|
||||
_meter = meterFactory.Create("StellaOps.Attestations");
|
||||
|
||||
_attestationsCreated = _meter.CreateCounter<long>(
|
||||
"stella_attestations_created_total",
|
||||
unit: "{attestation}",
|
||||
description: "Total attestations created");
|
||||
|
||||
_attestationsVerified = _meter.CreateCounter<long>(
|
||||
"stella_attestations_verified_total",
|
||||
unit: "{attestation}",
|
||||
description: "Total attestations verified successfully");
|
||||
|
||||
_attestationsFailed = _meter.CreateCounter<long>(
|
||||
"stella_attestations_failed_total",
|
||||
unit: "{attestation}",
|
||||
description: "Total attestation verifications failed");
|
||||
|
||||
_ttfeSeconds = _meter.CreateHistogram<double>(
|
||||
"stella_ttfe_seconds",
|
||||
unit: "s",
|
||||
description: "Time to first evidence (alert → evidence panel open)");
|
||||
|
||||
_verificationDuration = _meter.CreateHistogram<double>(
|
||||
"stella_attestation_verification_duration_seconds",
|
||||
unit: "s",
|
||||
description: "Time to verify an attestation");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Record attestation created.
|
||||
/// </summary>
|
||||
public void RecordCreated(string predicateType, string signer)
|
||||
{
|
||||
_attestationsCreated.Add(1,
|
||||
new KeyValuePair<string, object?>("predicate_type", predicateType),
|
||||
new KeyValuePair<string, object?>("signer", signer));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Record attestation verified.
|
||||
/// </summary>
|
||||
public void RecordVerified(string predicateType, bool success, TimeSpan duration)
|
||||
{
|
||||
if (success)
|
||||
{
|
||||
_attestationsVerified.Add(1,
|
||||
new KeyValuePair<string, object?>("predicate_type", predicateType));
|
||||
}
|
||||
else
|
||||
{
|
||||
_attestationsFailed.Add(1,
|
||||
new KeyValuePair<string, object?>("predicate_type", predicateType));
|
||||
}
|
||||
|
||||
_verificationDuration.Record(duration.TotalSeconds,
|
||||
new KeyValuePair<string, object?>("predicate_type", predicateType),
|
||||
new KeyValuePair<string, object?>("success", success));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Record time to first evidence.
|
||||
/// </summary>
|
||||
public void RecordTtfe(TimeSpan duration, string evidenceType)
|
||||
{
|
||||
_ttfeSeconds.Record(duration.TotalSeconds,
|
||||
new KeyValuePair<string, object?>("evidence_type", evidenceType));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
// Sprint: SPRINT_4300_0003_0002
|
||||
// Task: T3 - Post-Deploy Reversion Tracking
|
||||
|
||||
using System.Diagnostics.Metrics;
|
||||
|
||||
namespace StellaOps.Telemetry.Core.Metrics;
|
||||
|
||||
/// <summary>
|
||||
/// Metrics for deployment and reversion tracking.
|
||||
/// </summary>
|
||||
public sealed class DeploymentMetrics
|
||||
{
|
||||
private readonly Counter<long> _deploymentsTotal;
|
||||
private readonly Counter<long> _reversionsTotal;
|
||||
|
||||
public DeploymentMetrics(IMeterFactory meterFactory)
|
||||
{
|
||||
var meter = meterFactory.Create("StellaOps.Deployments");
|
||||
|
||||
_deploymentsTotal = meter.CreateCounter<long>(
|
||||
"stella_deployments_total",
|
||||
unit: "{deployment}",
|
||||
description: "Total deployments attempted");
|
||||
|
||||
_reversionsTotal = meter.CreateCounter<long>(
|
||||
"stella_post_deploy_reversions_total",
|
||||
unit: "{reversion}",
|
||||
description: "Reversions due to missing or invalid proof");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Record a deployment.
|
||||
/// </summary>
|
||||
public void RecordDeployment(string environment, bool hadCompleteProof)
|
||||
{
|
||||
_deploymentsTotal.Add(1,
|
||||
new KeyValuePair<string, object?>("environment", environment),
|
||||
new KeyValuePair<string, object?>("complete_proof", hadCompleteProof));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Record a deployment reversion.
|
||||
/// </summary>
|
||||
public void RecordReversion(string environment, string reason)
|
||||
{
|
||||
_reversionsTotal.Add(1,
|
||||
new KeyValuePair<string, object?>("environment", environment),
|
||||
new KeyValuePair<string, object?>("reason", reason));
|
||||
}
|
||||
}
|
||||
@@ -364,4 +364,22 @@ public static class TelemetryServiceCollectionExtensions
|
||||
ArgumentNullException.ThrowIfNull(builder);
|
||||
return builder.AddHttpMessageHandler<TelemetryPropagationHandler>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers attestation completeness and quality metrics.
|
||||
/// Sprint: SPRINT_4300_0003_0002 - Task T5
|
||||
/// </summary>
|
||||
/// <param name="services">Service collection to mutate.</param>
|
||||
/// <returns>The service collection for chaining.</returns>
|
||||
public static IServiceCollection AddAttestationMetrics(this IServiceCollection services)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(services);
|
||||
|
||||
services.TryAddSingleton<StellaOps.Telemetry.Core.Metrics.AttestationMetrics>();
|
||||
services.TryAddSingleton<StellaOps.Telemetry.Core.Metrics.DeploymentMetrics>();
|
||||
services.TryAddSingleton<StellaOps.Telemetry.Core.Metrics.IAttestationCompletenessCalculator,
|
||||
StellaOps.Telemetry.Core.Metrics.AttestationCompletenessCalculator>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user