Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/Testing/CoreTests/Runtime/MockWolverineRuntime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using Wolverine.Runtime;
using Wolverine.Runtime.Agents;
using Wolverine.Runtime.Handlers;
using Wolverine.Runtime.Metrics;
using Wolverine.Runtime.RemoteInvocation;
using Wolverine.Runtime.Routing;
using Wolverine.Transports;
Expand Down Expand Up @@ -51,8 +52,11 @@ public class MockWolverineRuntime : IWolverineRuntime, IObserver<IWolverineEvent
public MockWolverineRuntime()
{
Tracker.Subscribe(this);
MetricsAccumulator = new MetricsAccumulator(this);
}

public MetricsAccumulator MetricsAccumulator { get; }

public IMessageTracker MessageTracking { get; } = Substitute.For<IMessageTracker>();

void IObserver<IWolverineEvent>.OnCompleted()
Expand Down
8 changes: 8 additions & 0 deletions src/Testing/CoreTests/WolverineOptionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,14 @@ public void enable_remote_invocation_is_true_by_default()
new WolverineOptions().EnableRemoteInvocation.ShouldBeTrue();
}

[Fact]
public void metrics_defaults()
{
var options = new WolverineOptions();
options.Metrics.Mode.ShouldBe(WolverineMetricsMode.SystemDiagnosticsMeter);
options.Metrics.SamplingPeriod.ShouldBe(5.Seconds());
}

public interface IFoo;

public class Foo : IFoo;
Expand Down
109 changes: 109 additions & 0 deletions src/Testing/MetricsTests/InstrumentPump.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
using System.Transactions;
using JasperFx;
using JasperFx.Core.Reflection;
using JasperFx.MultiTenancy;
using Wolverine.Runtime.Metrics;

namespace MetricsTests;

public class InstrumentPump
{
private readonly string[] _tenants;

private readonly string[] _exceptions =
[
typeof(BadImageFormatException).FullNameInCode(), typeof(DivideByZeroException).FullNameInCode(),
typeof(InvalidTimeZoneException).FullNameInCode(), typeof(UnknownTenantIdException).FullNameInCode()
];

public InstrumentPump(string[] tenants)
{
_tenants = tenants;
}

public List<IHandlerMetricsData> Data { get; } = new();

public PerTenantMetrics GetExpectedForTenantId(string tenantId)
{
var tracking = new PerTenantTracking(tenantId);
foreach (var data in Data.Where(x => x.TenantId == tenantId))
{
data.Apply(tracking);
}

return tracking.CompileAndReset();
}

public async Task Publish(int number, MessageTypeMetricsAccumulator accumulator)
{
Func<IHandlerMetricsData, ValueTask> publish = d =>
{
Data.Add(d);
return accumulator.EntryPoint.PostAsync(d);
};

for (int i = 0; i < number; i++)
{
var tenantId = determineTenantId();

var random = Random.Shared.Next(0, 10);

if (random < 6)
{
var executionTime = Random.Shared.Next(50, 1000);
var effectiveTime = executionTime + Random.Shared.NextDouble();
await publish(new RecordExecutionTime(executionTime, tenantId));
await publish(new RecordEffectiveTime(effectiveTime, tenantId));
}
else if (random <= 9)
{
var exceptionType = _exceptions[Random.Shared.Next(0, _exceptions.Length - 1)];
await publish(new RecordFailure(exceptionType, tenantId));
}
else
{
var exceptionType = _exceptions[Random.Shared.Next(0, _exceptions.Length - 1)];
await publish(new RecordDeadLetter(exceptionType, tenantId));
}
}
}

public async Task Publish(int number, string tenantId, MessageTypeMetricsAccumulator accumulator)
{
Func<IHandlerMetricsData, ValueTask> publish = d =>
{
Data.Add(d);
return accumulator.EntryPoint.PostAsync(d);
};

for (int i = 0; i < number; i++)
{
var random = Random.Shared.Next(0, 10);

if (random < 6)
{
var executionTime = Random.Shared.Next(50, 1000);
var effectiveTime = executionTime + Random.Shared.NextDouble();
await publish(new RecordExecutionTime(executionTime, tenantId));
await publish(new RecordEffectiveTime(effectiveTime, tenantId));
}
else if (random <= 9)
{
var exceptionType = _exceptions[Random.Shared.Next(0, _exceptions.Length - 1)];
await publish(new RecordFailure(exceptionType, tenantId));
}
else
{
var exceptionType = _exceptions[Random.Shared.Next(0, _exceptions.Length - 1)];
await publish(new RecordDeadLetter(exceptionType, tenantId));
}
}
}

private string determineTenantId()
{
if (_tenants.Length <= 1) return StorageConstants.DefaultTenantId;

return _tenants[Random.Shared.Next(0, _tenants.Length - 1)];
}
}
72 changes: 72 additions & 0 deletions src/Testing/MetricsTests/InstrumentsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using JasperFx.Core.Reflection;
using Shouldly;
using Wolverine.Runtime.Metrics;

namespace MetricsTests;

public class InstrumentsTests
{
[Fact]
public void record_failure()
{
var exceptionType = typeof(BadImageFormatException).FullNameInCode();
var failure = new RecordFailure(exceptionType, "t1");

var tracking = new PerTenantTracking("t1");

failure.Apply(tracking);
tracking.Failures[exceptionType].ShouldBe(1);
tracking.DeadLetterCounts.ContainsKey(exceptionType).ShouldBeFalse();
}

[Fact]
public void record_dead_letter()
{
var exceptionType = typeof(BadImageFormatException).FullNameInCode();
var deadLetter = new RecordDeadLetter(exceptionType, "t1");

var tracking = new PerTenantTracking("t1");

deadLetter.Apply(tracking);
tracking.DeadLetterCounts[exceptionType].ShouldBe(1);
tracking.Failures.ContainsKey(exceptionType).ShouldBeFalse();
}

[Fact]
public void record_effective_time()
{
var effectiveTime1 = new RecordEffectiveTime(11.2, "t1");
var effectiveTime2 = new RecordEffectiveTime(2.1, "t1");
var effectiveTime3 = new RecordEffectiveTime(3.5, "t1");

var tracking = new PerTenantTracking("t1");

effectiveTime1.Apply(tracking);
effectiveTime2.Apply(tracking);
effectiveTime3.Apply(tracking);

tracking.TotalEffectiveTime.ShouldBe(effectiveTime1.Time + effectiveTime2.Time + effectiveTime3.Time);
tracking.Completions.ShouldBe(3);
}

[Fact]
public void record_execution_time()
{
var execution1 = new RecordExecutionTime(Random.Shared.Next(100, 1000), "t1");
var execution2 = new RecordExecutionTime(Random.Shared.Next(100, 1000), "t1");
var execution3 = new RecordExecutionTime(Random.Shared.Next(100, 1000), "t1");
var execution4 = new RecordExecutionTime(Random.Shared.Next(100, 1000), "t1");

var tracking = new PerTenantTracking("t1");

execution1.Apply(tracking);
execution2.Apply(tracking);
execution3.Apply(tracking);
execution4.Apply(tracking);

tracking.Executions.ShouldBe(4);
tracking.TotalExecutionTime.ShouldBe(execution1.Time + execution2.Time + execution3.Time + execution4.Time);

}

}
51 changes: 51 additions & 0 deletions src/Testing/MetricsTests/MessageHandlingCountsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using Shouldly;
using Wolverine.Runtime.Metrics;

namespace MetricsTests;

public class MessageHandlingCountsTests
{
[Fact]
public void instrument_across_tenants()
{
var counts = new MessageHandlingCounts("m1", new Uri("stub://one"));

counts.Increment(new RecordExecutionTime(23, "t1"));
counts.Increment(new RecordExecutionTime(45, "t2"));
counts.Increment(new RecordExecutionTime(55, "t1"));
counts.Increment(new RecordExecutionTime(20, "t3"));
counts.Increment(new RecordExecutionTime(117, "t3"));
counts.Increment(new RecordExecutionTime(10, "t2"));

counts.PerTenant["t1"].Executions.ShouldBe(2);
counts.PerTenant["t1"].TotalExecutionTime.ShouldBe(23 + 55);

counts.PerTenant["t2"].Executions.ShouldBe(2);
counts.PerTenant["t2"].TotalExecutionTime.ShouldBe(45 + 10);

counts.PerTenant["t3"].Executions.ShouldBe(2);
counts.PerTenant["t3"].TotalExecutionTime.ShouldBe(20 + 117);
}

[Fact]
public void clear()
{
var counts = new MessageHandlingCounts("m1", new Uri("stub://one"));
counts.Increment(new RecordExecutionTime(23, "t1"));
counts.Increment(new RecordExecutionTime(45, "t2"));
counts.Increment(new RecordExecutionTime(55, "t1"));
counts.Increment(new RecordExecutionTime(20, "t3"));
counts.Increment(new RecordExecutionTime(117, "t3"));
counts.Increment(new RecordExecutionTime(10, "t2"));
counts.Clear();

counts.PerTenant["t1"].Executions.ShouldBe(0);
counts.PerTenant["t1"].TotalExecutionTime.ShouldBe(0);

counts.PerTenant["t2"].Executions.ShouldBe(0);
counts.PerTenant["t2"].TotalExecutionTime.ShouldBe(0);

counts.PerTenant["t3"].Executions.ShouldBe(0);
counts.PerTenant["t3"].TotalExecutionTime.ShouldBe(0);
}
}
Loading
Loading