Skip to content

Commit ef21b8f

Browse files
Create Core_10 Sample
1 parent 24148b5 commit ef21b8f

File tree

9 files changed

+248
-0
lines changed

9 files changed

+248
-0
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFrameworks>net9.0;net8.0</TargetFrameworks>
6+
<LangVersion>12.0</LangVersion>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<PackageReference Include="NServiceBus" Version="9.*" />
11+
<PackageReference Include="OpenTelemetry.Exporter.Prometheus.HttpListener" Version="1.*-*" />
12+
</ItemGroup>
13+
14+
</Project>
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
using System;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
using NServiceBus;
5+
6+
// Simulates busy (almost no delay) / quite time in a sine wave
7+
class LoadSimulator
8+
{
9+
public LoadSimulator(IEndpointInstance endpointInstance, TimeSpan minimumDelay, TimeSpan idleDuration)
10+
{
11+
this.endpointInstance = endpointInstance;
12+
this.minimumDelay = minimumDelay;
13+
this.idleDuration = TimeSpan.FromTicks(idleDuration.Ticks / 2);
14+
}
15+
16+
public void Start(CancellationToken cancellationToken)
17+
{
18+
_ = Task.Run(() => Loop(cancellationToken), cancellationToken);
19+
}
20+
21+
async Task Loop(CancellationToken cancellationToken)
22+
{
23+
try
24+
{
25+
while (!cancellationToken.IsCancellationRequested)
26+
{
27+
await Work(cancellationToken);
28+
var delay = NextDelay();
29+
await Task.Delay(delay, cancellationToken);
30+
}
31+
}
32+
catch (OperationCanceledException)
33+
{
34+
}
35+
}
36+
37+
TimeSpan NextDelay()
38+
{
39+
var angleInRadians = Math.PI / 180.0 * ++index;
40+
var delay = TimeSpan.FromMilliseconds(idleDuration.TotalMilliseconds * Math.Sin(angleInRadians));
41+
delay += idleDuration;
42+
delay += minimumDelay;
43+
return delay;
44+
}
45+
46+
Task Work(CancellationToken cancellationToken)
47+
{
48+
var sendOptions = new SendOptions();
49+
50+
sendOptions.RouteToThisEndpoint();
51+
52+
if (Random.Shared.Next(100) <= 10)
53+
{
54+
sendOptions.SetHeader("simulate-immediate-retry", bool.TrueString);
55+
}
56+
57+
if (Random.Shared.Next(100) <= 5)
58+
{
59+
sendOptions.SetHeader("simulate-failure", bool.TrueString);
60+
}
61+
62+
return endpointInstance.Send(new SomeMessage(), sendOptions, cancellationToken);
63+
}
64+
65+
public Task Stop(CancellationToken cancellationToken)
66+
{
67+
return Task.CompletedTask;
68+
}
69+
70+
IEndpointInstance endpointInstance;
71+
TimeSpan minimumDelay;
72+
TimeSpan idleDuration;
73+
int index;
74+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Threading;
4+
using System.Threading.Tasks;
5+
using NServiceBus;
6+
using OpenTelemetry;
7+
using OpenTelemetry.Metrics;
8+
using OpenTelemetry.Resources;
9+
10+
public class Program
11+
{
12+
const string EndpointName = "Samples.OpenTelemetry.Metrics";
13+
public static async Task Main()
14+
{
15+
Console.Title = EndpointName;
16+
17+
var attributes = new Dictionary<string, object>
18+
{
19+
["service.name"] = EndpointName,
20+
["service.instance.id"] = Guid.NewGuid().ToString(),
21+
};
22+
23+
var resourceBuilder = ResourceBuilder.CreateDefault().AddAttributes(attributes);
24+
25+
#region enable-opentelemetry-metrics
26+
var meterProviderBuilder = Sdk.CreateMeterProviderBuilder()
27+
.SetResourceBuilder(resourceBuilder)
28+
.AddMeter("NServiceBus.Core*");
29+
#endregion
30+
31+
#region enable-prometheus-http-listener
32+
meterProviderBuilder.AddPrometheusHttpListener(options => options.UriPrefixes = new[] { "http://127.0.0.1:9464" });
33+
#endregion
34+
35+
var meterProvider = meterProviderBuilder.Build();
36+
37+
#region enable-opentelemetry
38+
var endpointConfiguration = new EndpointConfiguration(EndpointName);
39+
endpointConfiguration.EnableOpenTelemetry();
40+
#endregion
41+
42+
endpointConfiguration.UseSerialization<SystemJsonSerializer>();
43+
endpointConfiguration.UseTransport<LearningTransport>();
44+
45+
var cancellation = new CancellationTokenSource();
46+
var endpointInstance = await Endpoint.Start(endpointConfiguration, cancellation.Token);
47+
48+
#region prometheus-load-simulator
49+
50+
var simulator = new LoadSimulator(endpointInstance, TimeSpan.Zero, TimeSpan.FromSeconds(10));
51+
simulator.Start(cancellation.Token);
52+
53+
#endregion
54+
55+
try
56+
{
57+
Console.WriteLine("Endpoint started. Press any key to send a message. Press ESC to stop");
58+
59+
while (Console.ReadKey(true).Key != ConsoleKey.Escape)
60+
{
61+
62+
await endpointInstance.SendLocal(new SomeMessage(), cancellation.Token);
63+
}
64+
}
65+
finally
66+
{
67+
await simulator.Stop(cancellation.Token);
68+
await endpointInstance.Stop(cancellation.Token);
69+
meterProvider?.Dispose();
70+
}
71+
}
72+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
using NServiceBus;
2+
3+
class SomeMessage : IMessage
4+
{
5+
6+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using NServiceBus;
4+
5+
class SomeMessageHandler : IHandleMessages<SomeMessage>
6+
{
7+
public async Task Handle(SomeMessage message, IMessageHandlerContext context)
8+
{
9+
await Task.Delay(Random.Shared.Next(50, 250), context.CancellationToken);
10+
11+
if (context.MessageHeaders.ContainsKey("simulate-failure"))
12+
{
13+
throw new Exception("Simulated failure");
14+
}
15+
16+
if (context.MessageHeaders.ContainsKey("simulate-immediate-retry") && !context.MessageHeaders.ContainsKey(Headers.ImmediateRetries))
17+
{
18+
throw new Exception("Simulated immediate retry");
19+
}
20+
21+
Console.WriteLine("Message processed");
22+
}
23+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Endpoint", "Endpoint\Endpoint.csproj", "{339B8D67-CAB2-416C-8C15-50A757CB5073}"
4+
EndProject
5+
Global
6+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
7+
Debug|Any CPU = Debug|Any CPU
8+
Release|Any CPU = Release|Any CPU
9+
EndGlobalSection
10+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
11+
{339B8D67-CAB2-416C-8C15-50A757CB5073}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
12+
{339B8D67-CAB2-416C-8C15-50A757CB5073}.Debug|Any CPU.Build.0 = Debug|Any CPU
13+
{339B8D67-CAB2-416C-8C15-50A757CB5073}.Release|Any CPU.ActiveCfg = Release|Any CPU
14+
{339B8D67-CAB2-416C-8C15-50A757CB5073}.Release|Any CPU.Build.0 = Release|Any CPU
15+
EndGlobalSection
16+
EndGlobal
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
version: '3'
2+
3+
services:
4+
prometheus:
5+
image: prom/prometheus:v2.21.0
6+
ports:
7+
- 9000:9090
8+
extra_hosts:
9+
- "host.docker.internal:host-gateway"
10+
volumes:
11+
- ./prometheus:/etc/prometheus
12+
- ./data-prometheus:/prometheus
13+
command: --web.enable-lifecycle --config.file=/etc/prometheus/prometheus.yml
14+
15+
grafana:
16+
image: grafana/grafana-oss:latest
17+
ports:
18+
- 3000:3000
19+
restart: unless-stopped
20+
volumes:
21+
- ./grafana/provisioning/datasources:/etc/grafana/provisioning/datasources
22+
- ./data-grafana:/var/lib/grafana
23+
24+
volumes:
25+
prometheus-data:
26+
grafana-data:
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
datasources:
2+
- name: Prometheus
3+
access: proxy
4+
type: prometheus
5+
url: http://prometheus:9090
6+
isDefault: true
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
global:
2+
scrape_interval: 30s
3+
scrape_timeout: 10s
4+
5+
scrape_configs:
6+
- job_name: 'NServiceBus Telemetry'
7+
scrape_interval: 1s
8+
metrics_path: /metrics
9+
static_configs:
10+
- targets:
11+
- 'host.docker.internal:9464'

0 commit comments

Comments
 (0)