Group all 69 projects into category subfolders under src/ and tests/ so the Rider Solution Explorer mirrors the module structure. Folders: Core, Server, Drivers (with a nested Driver CLIs subfolder), Client, Tooling. - Move every project folder on disk with git mv (history preserved as renames). - Recompute relative paths in 57 .csproj files: cross-category ProjectReferences, the lib/ HintPath+None refs in Driver.Historian.Wonderware, and the external mxaccessgw refs in Driver.Galaxy and its test project. - Rebuild ZB.MOM.WW.OtOpcUa.slnx with nested solution folders. - Re-prefix project paths in functional scripts (e2e, compliance, smoke SQL, integration, install). Build green (0 errors); unit tests pass. Docs left for a separate pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
73 lines
2.4 KiB
C#
73 lines
2.4 KiB
C#
using Serilog;
|
|
using Serilog.Core;
|
|
using Serilog.Events;
|
|
using Shouldly;
|
|
using Xunit;
|
|
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
|
|
using ZB.MOM.WW.OtOpcUa.Core.Resilience;
|
|
|
|
namespace ZB.MOM.WW.OtOpcUa.Core.Tests.Observability;
|
|
|
|
[Trait("Category", "Integration")]
|
|
public sealed class CapabilityInvokerEnrichmentTests
|
|
{
|
|
[Fact]
|
|
public async Task InvokerExecute_LogsInsideCallSite_CarryStructuredProperties()
|
|
{
|
|
var sink = new InMemorySink();
|
|
var logger = new LoggerConfiguration()
|
|
.Enrich.FromLogContext()
|
|
.WriteTo.Sink(sink)
|
|
.CreateLogger();
|
|
|
|
var invoker = new CapabilityInvoker(
|
|
new DriverResiliencePipelineBuilder(),
|
|
driverInstanceId: "drv-live",
|
|
optionsAccessor: () => new DriverResilienceOptions { Tier = DriverTier.A },
|
|
driverType: "Modbus");
|
|
|
|
await invoker.ExecuteAsync(
|
|
DriverCapability.Read,
|
|
"plc-1",
|
|
ct =>
|
|
{
|
|
logger.Information("inside call site");
|
|
return ValueTask.FromResult(42);
|
|
},
|
|
CancellationToken.None);
|
|
|
|
var evt = sink.Events.ShouldHaveSingleItem();
|
|
evt.Properties["DriverInstanceId"].ToString().ShouldBe("\"drv-live\"");
|
|
evt.Properties["DriverType"].ToString().ShouldBe("\"Modbus\"");
|
|
evt.Properties["CapabilityName"].ToString().ShouldBe("\"Read\"");
|
|
evt.Properties.ShouldContainKey("CorrelationId");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task InvokerExecute_DoesNotLeak_ContextOutsideCallSite()
|
|
{
|
|
var sink = new InMemorySink();
|
|
var logger = new LoggerConfiguration()
|
|
.Enrich.FromLogContext()
|
|
.WriteTo.Sink(sink)
|
|
.CreateLogger();
|
|
|
|
var invoker = new CapabilityInvoker(
|
|
new DriverResiliencePipelineBuilder(),
|
|
driverInstanceId: "drv-a",
|
|
optionsAccessor: () => new DriverResilienceOptions { Tier = DriverTier.A });
|
|
|
|
await invoker.ExecuteAsync(DriverCapability.Read, "host", _ => ValueTask.FromResult(1), CancellationToken.None);
|
|
logger.Information("outside");
|
|
|
|
var outside = sink.Events.ShouldHaveSingleItem();
|
|
outside.Properties.ContainsKey("DriverInstanceId").ShouldBeFalse();
|
|
}
|
|
|
|
private sealed class InMemorySink : ILogEventSink
|
|
{
|
|
public List<LogEvent> Events { get; } = [];
|
|
public void Emit(LogEvent logEvent) => Events.Add(logEvent);
|
|
}
|
|
}
|