feat(telemetry): deploy-failure, S&F activity, script-run and DCL-transition instruments (ScadaBridge#81)
Adds four instruments on the already-allow-listed ZB.MOM.WW.ScadaBridge meter:
scadabridge.deployments.failed{reason}, scadabridge.store_and_forward.activity{action,category},
scadabridge.site.script.runs{outcome} + scadabridge.site.script.duration{outcome} (ms),
scadabridge.site.data_connections.transitions{state}. Queue depth, DCL connection state and
deploy-applied already existed. No new Meter, so ZbTelemetryOptions.Meters needs no change.
Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
This commit is contained in:
@@ -1063,6 +1063,45 @@ public class DeploymentServiceTests : TestKit
|
||||
Assert.Equal(1, Interlocked.Read(ref applied));
|
||||
}
|
||||
|
||||
/// <summary>Verifies a faulted deployment emits the deployments failed counter tagged reason=error (ScadaBridge#81).</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task DeployInstanceAsync_Fault_EmitsDeploymentsFailedCounter()
|
||||
{
|
||||
var instance = new Instance("FailMetricInst") { Id = 1, SiteId = 1, State = InstanceState.NotDeployed };
|
||||
_repo.GetInstanceByIdAsync(1).Returns(instance);
|
||||
var config = new FlattenedConfiguration { InstanceUniqueName = "FailMetricInst" };
|
||||
_pipeline.FlattenAndValidateAsync(1, Arg.Any<CancellationToken>())
|
||||
.Returns(Result<FlatteningPipelineResult>.Success(
|
||||
new FlatteningPipelineResult(config, "sha256:abc", ValidationResult.Success())));
|
||||
|
||||
var reasons = new System.Collections.Concurrent.ConcurrentQueue<string?>();
|
||||
using var listener = new MeterListener
|
||||
{
|
||||
InstrumentPublished = (instrument, l) =>
|
||||
{
|
||||
if (instrument.Meter.Name == ScadaBridgeTelemetry.MeterName
|
||||
&& instrument.Name == "scadabridge.deployments.failed")
|
||||
{
|
||||
l.EnableMeasurementEvents(instrument);
|
||||
}
|
||||
}
|
||||
};
|
||||
listener.SetMeasurementEventCallback<long>((_, _, tags, _) =>
|
||||
{
|
||||
foreach (var t in tags)
|
||||
if (t.Key == "reason") reasons.Enqueue(t.Value as string);
|
||||
});
|
||||
listener.Start();
|
||||
|
||||
// _comms has no actor set -> non-timeout fault -> MarkDeploymentFailedAsync.
|
||||
var result = await _service.DeployInstanceAsync(1, "admin");
|
||||
listener.Dispose();
|
||||
|
||||
Assert.True(result.IsFailure);
|
||||
Assert.Contains("error", reasons);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that deploy instance async reconciled does not emit deployments applied counter.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
|
||||
Reference in New Issue
Block a user