- Add ConsoleSessionStore for managing console session state including tenants, profile, and token information. - Create OperatorContextService to manage operator context for orchestrator actions. - Implement OperatorMetadataInterceptor to enrich HTTP requests with operator context metadata. - Develop ConsoleProfileComponent to display user profile and session details, including tenant information and access tokens. - Add corresponding HTML and SCSS for ConsoleProfileComponent to enhance UI presentation. - Write unit tests for ConsoleProfileComponent to ensure correct rendering and functionality.
127 lines
5.6 KiB
C#
127 lines
5.6 KiB
C#
using System;
|
|
using System.Diagnostics.Metrics;
|
|
|
|
namespace StellaOps.Cli.Telemetry;
|
|
|
|
internal static class CliMetrics
|
|
{
|
|
private static readonly Meter Meter = new("StellaOps.Cli", "1.0.0");
|
|
|
|
private static readonly Counter<long> ScannerDownloadCounter = Meter.CreateCounter<long>("stellaops.cli.scanner.download.count");
|
|
private static readonly Counter<long> ScannerInstallCounter = Meter.CreateCounter<long>("stellaops.cli.scanner.install.count");
|
|
private static readonly Counter<long> ScanRunCounter = Meter.CreateCounter<long>("stellaops.cli.scan.run.count");
|
|
private static readonly Counter<long> OfflineKitDownloadCounter = Meter.CreateCounter<long>("stellaops.cli.offline.kit.download.count");
|
|
private static readonly Counter<long> OfflineKitImportCounter = Meter.CreateCounter<long>("stellaops.cli.offline.kit.import.count");
|
|
private static readonly Counter<long> PolicySimulationCounter = Meter.CreateCounter<long>("stellaops.cli.policy.simulate.count");
|
|
private static readonly Counter<long> PolicyActivationCounter = Meter.CreateCounter<long>("stellaops.cli.policy.activate.count");
|
|
private static readonly Counter<long> SourcesDryRunCounter = Meter.CreateCounter<long>("stellaops.cli.sources.dryrun.count");
|
|
private static readonly Counter<long> AocVerifyCounter = Meter.CreateCounter<long>("stellaops.cli.aoc.verify.count");
|
|
private static readonly Counter<long> PolicyFindingsListCounter = Meter.CreateCounter<long>("stellaops.cli.policy.findings.list.count");
|
|
private static readonly Counter<long> PolicyFindingsGetCounter = Meter.CreateCounter<long>("stellaops.cli.policy.findings.get.count");
|
|
private static readonly Counter<long> PolicyFindingsExplainCounter = Meter.CreateCounter<long>("stellaops.cli.policy.findings.explain.count");
|
|
private static readonly Histogram<double> CommandDurationHistogram = Meter.CreateHistogram<double>("stellaops.cli.command.duration.ms");
|
|
|
|
public static void RecordScannerDownload(string channel, bool fromCache)
|
|
=> ScannerDownloadCounter.Add(1, new KeyValuePair<string, object?>[]
|
|
{
|
|
new("channel", channel),
|
|
new("cache", fromCache ? "hit" : "miss")
|
|
});
|
|
|
|
public static void RecordScannerInstall(string channel)
|
|
=> ScannerInstallCounter.Add(1, new KeyValuePair<string, object?>[] { new("channel", channel) });
|
|
|
|
public static void RecordScanRun(string runner, int exitCode)
|
|
=> ScanRunCounter.Add(1, new KeyValuePair<string, object?>[]
|
|
{
|
|
new("runner", runner),
|
|
new("exit_code", exitCode)
|
|
});
|
|
|
|
public static void RecordOfflineKitDownload(string kind, bool fromCache)
|
|
=> OfflineKitDownloadCounter.Add(1, new KeyValuePair<string, object?>[]
|
|
{
|
|
new("kind", string.IsNullOrWhiteSpace(kind) ? "unknown" : kind),
|
|
new("cache", fromCache ? "hit" : "miss")
|
|
});
|
|
|
|
public static void RecordOfflineKitImport(string? status)
|
|
=> OfflineKitImportCounter.Add(1, new KeyValuePair<string, object?>[]
|
|
{
|
|
new("status", string.IsNullOrWhiteSpace(status) ? "queued" : status)
|
|
});
|
|
|
|
public static void RecordPolicySimulation(string outcome)
|
|
=> PolicySimulationCounter.Add(1, new KeyValuePair<string, object?>[]
|
|
{
|
|
new("outcome", string.IsNullOrWhiteSpace(outcome) ? "unknown" : outcome)
|
|
});
|
|
|
|
public static void RecordPolicyActivation(string outcome)
|
|
=> PolicyActivationCounter.Add(1, new KeyValuePair<string, object?>[]
|
|
{
|
|
new("outcome", string.IsNullOrWhiteSpace(outcome) ? "unknown" : outcome)
|
|
});
|
|
|
|
public static void RecordSourcesDryRun(string status)
|
|
=> SourcesDryRunCounter.Add(1, new KeyValuePair<string, object?>[]
|
|
{
|
|
new("status", string.IsNullOrWhiteSpace(status) ? "unknown" : status)
|
|
});
|
|
|
|
public static void RecordAocVerify(string outcome)
|
|
=> AocVerifyCounter.Add(1, new KeyValuePair<string, object?>[]
|
|
{
|
|
new("outcome", string.IsNullOrWhiteSpace(outcome) ? "unknown" : outcome)
|
|
});
|
|
|
|
public static void RecordPolicyFindingsList(string outcome)
|
|
=> PolicyFindingsListCounter.Add(1, new KeyValuePair<string, object?>[]
|
|
{
|
|
new("outcome", string.IsNullOrWhiteSpace(outcome) ? "unknown" : outcome)
|
|
});
|
|
|
|
public static void RecordPolicyFindingsGet(string outcome)
|
|
=> PolicyFindingsGetCounter.Add(1, new KeyValuePair<string, object?>[]
|
|
{
|
|
new("outcome", string.IsNullOrWhiteSpace(outcome) ? "unknown" : outcome)
|
|
});
|
|
|
|
public static void RecordPolicyFindingsExplain(string outcome)
|
|
=> PolicyFindingsExplainCounter.Add(1, new KeyValuePair<string, object?>[]
|
|
{
|
|
new("outcome", string.IsNullOrWhiteSpace(outcome) ? "unknown" : outcome)
|
|
});
|
|
|
|
public static IDisposable MeasureCommandDuration(string command)
|
|
{
|
|
var start = DateTime.UtcNow;
|
|
return new DurationScope(command, start);
|
|
}
|
|
|
|
private sealed class DurationScope : IDisposable
|
|
{
|
|
private readonly string _command;
|
|
private readonly DateTime _start;
|
|
private bool _disposed;
|
|
|
|
public DurationScope(string command, DateTime start)
|
|
{
|
|
_command = command;
|
|
_start = start;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (_disposed)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_disposed = true;
|
|
var elapsed = (DateTime.UtcNow - _start).TotalMilliseconds;
|
|
CommandDurationHistogram.Record(elapsed, new KeyValuePair<string, object?>[] { new("command", _command) });
|
|
}
|
|
}
|
|
}
|