Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
aa216b4
Change to process group
danielmarbach Jan 31, 2025
7795398
Rename to platformlauncher to not clash with casing with platform
danielmarbach Feb 14, 2025
eef6e6b
Remove runtime
danielmarbach Mar 13, 2025
5c8bcf2
Scripts
danielmarbach Mar 13, 2025
35a7b01
Enable linux builds
danielmarbach Mar 13, 2025
3a37cbe
Macos
danielmarbach Mar 13, 2025
021c4aa
Readme tweaks
danielmarbach Mar 13, 2025
012303a
Rename Platform project
bording Mar 19, 2025
53cacf4
Launch processes with dotnet host
bording Mar 19, 2025
957a749
Remove icons that won't be seen anyway
bording Mar 19, 2025
1be28e6
Clean up package references
bording Mar 19, 2025
d99d9b9
Update Particular.Analyzers
bording Mar 19, 2025
8bb0f00
Remove Serilog and Shared project
bording Mar 19, 2025
c073264
Move binaries out of src folder
bording Mar 19, 2025
9042337
Update workflows
bording Mar 19, 2025
7021998
Make script executable
bording Mar 19, 2025
2602dba
Ensure line endings are right
bording Mar 19, 2025
3339a6b
Restore exe entry point for Windows
bording Mar 21, 2025
a9eb9ca
Redirect mode
danielmarbach Mar 28, 2025
3acc812
Revert "Restore exe entry point for Windows"
bording Apr 1, 2025
ba61f24
UI (#206)
danielmarbach May 15, 2025
b24a6c5
Tweaks
bording May 15, 2025
51d02dd
Add back shared project and redesign command mapping
SzymonPobiega May 16, 2025
75eb509
Fix command wiring and make UI work also when not in the redirected mode
SzymonPobiega May 16, 2025
cf2bb8f
Improvements
SzymonPobiega May 16, 2025
b803a02
Fix rebase
SzymonPobiega May 16, 2025
217905f
Scale out client UI
SzymonPobiega May 19, 2025
0f4633d
Bind scale out to controller box
SzymonPobiega May 19, 2025
9c1faae
Some more fixes and controller bindings
SzymonPobiega May 19, 2025
a597086
Fixes to simulation
SzymonPobiega Jun 23, 2025
1ad9770
Delete joystick files
SzymonPobiega Jun 23, 2025
6ecac97
Removed unused class
SzymonPobiega Jun 24, 2025
fe10b7b
Cleanup
bording Jun 24, 2025
58c1acc
Move MonitoringDemo into subfolder
bording Aug 8, 2025
c38086a
Change window ordering to put Platform first
bording Aug 8, 2025
2a35f51
Update Terminal.Gui
bording Sep 5, 2025
1271db2
Treat scale out and in similar to the help standard input
danielmarbach Sep 20, 2025
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
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Auto detect text files and perform LF normalization
* text=auto
*.sh text eol=lf
26 changes: 14 additions & 12 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,13 @@ on:
workflow_dispatch:
env:
DOTNET_NOLOGO: true
defaults:
run:
shell: pwsh
jobs:
build:
name: ${{ matrix.name }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: windows-latest
name: Windows
#- os: ubuntu-latest
# name: Linux
fail-fast: false
name: Linux
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5.0.0
Expand All @@ -28,10 +23,17 @@ jobs:
global-json-file: global.json
- name: Build
run: dotnet build src --configuration Release
- name: Remove executables
run: |
Remove-Item binaries/MonitoringDemo/MonitoringDemo
Remove-Item binaries/Billing/Billing
Remove-Item binaries/ClientUI/ClientUI
Remove-Item binaries/PlatformLauncher/PlatformLauncher
Remove-Item binaries/Sales/Sales
Remove-Item binaries/Shipping/Shipping
- name: Publish artifacts
if: matrix.name == 'Windows'
uses: actions/upload-artifact@v4.6.2
with:
name: binaries
path: src/binaries/*
path: binaries/*
retention-days: 7
35 changes: 13 additions & 22 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ on:
workflow_dispatch:
env:
DOTNET_NOLOGO: true
defaults:
run:
shell: pwsh
jobs:
release:
runs-on: windows-latest
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5.0.0
Expand All @@ -15,43 +18,31 @@ jobs:
global-json-file: global.json
- name: Build
run: dotnet build src --configuration Release
- name: Install AzureSignTool
run: dotnet tool install --global azuresigntool
- name: Sign binaries
- name: Remove executables
run: |
AzureSignTool sign `
--file-digest sha256 `
--timestamp-rfc3161 http://timestamp.digicert.com `
--azure-key-vault-url https://particularcodesigning.vault.azure.net `
--azure-key-vault-client-id ${{ secrets.AZURE_KEY_VAULT_CLIENT_ID }} `
--azure-key-vault-tenant-id ${{ secrets.AZURE_KEY_VAULT_TENANT_ID }} `
--azure-key-vault-client-secret ${{ secrets.AZURE_KEY_VAULT_CLIENT_SECRET }} `
--azure-key-vault-certificate ${{ secrets.AZURE_KEY_VAULT_CERTIFICATE_NAME }} `
src/binaries/MonitoringDemo.exe `
src/binaries/Billing/Billing.exe `
src/binaries/ClientUI/ClientUI.exe `
src/binaries/Platform/Platform.exe `
src/binaries/Sales/Sales.exe `
src/binaries/Shipping/Shipping.exe
shell: pwsh
Remove-Item binaries/MonitoringDemo/MonitoringDemo
Remove-Item binaries/Billing/Billing
Remove-Item binaries/ClientUI/ClientUI
Remove-Item binaries/PlatformLauncher/PlatformLauncher
Remove-Item binaries/Sales/Sales
Remove-Item binaries/Shipping/Shipping
- name: Setup AWS Credentials
uses: aws-actions/configure-aws-credentials@v4.1.0
with:
aws-access-key-id: ${{ secrets.AWS_ACCESSKEY }}
aws-secret-access-key: ${{ secrets.AWS_SECRETKEY }}
aws-region: us-east-1
- name: Deploy to S3
shell: pwsh
shell: bash
run: |
echo "Creating Particular.MonitoringDemo.zip archive"
Compress-Archive -Path ./src/binaries/* -DestinationPath ./Particular.MonitoringDemo.zip
(cd binaries && zip -r "$OLDPWD/Particular.MonitoringDemo.zip" .)

echo "Uploading zip file to AWS"
aws s3 cp ./Particular.MonitoringDemo.zip s3://particular.downloads/MonitoringDemo/Particular.MonitoringDemo.zip --content-type application/zip --acl public-read

echo "Complete"
- name: Upload dependency file to AWS
shell: pwsh
run: |
$dotnetPackages = dotnet list src/Platform package --include-transitive --format json | ConvertFrom-Json
$firstProject = $dotnetPackages.projects[0]
Expand Down
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
**/Platform/**/db
**/bin/
**/obj/
src/binaries/**/*
binaries/**/*
**/.vs/
MonitoringDemo.Sql/support/*.log
MonitoringDemo.Sql/transport/
Expand All @@ -12,4 +12,5 @@ MonitoringDemo.Sql/transport/

**/.diagnostics/*
.logs
.idea
.idea
/otel/
18 changes: 6 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,18 @@ Self-contained demo showing all of the monitoring components working together. T

- https://docs.particular.net/tutorials/monitoring/demo/

# Prerequisites

Running the demo requires .Net Framework 4.6.1 or newer.
## Prerequisites

In order to run the downloaded sample you will need the following prerequisites.

- Window operating system, the Particular Service Platform requires the Windows operating system
- Desktop: Windows 8 or higher
- Server: Windows Server 2016 or higher
- Powershell 3.0 or higher
- .NET Framework 4.6.1 (check version)

# Running
- .NET 8.0 or higher

## Running

- Compile `src\MonitoringDemo.sln`
- Execute `src\binaries\MonitoringDemo.exe`
- Execute `src\binaries\launch.sh` or `src\binaries\launch.ps1`

# Deploying
## Deploying

1. Go to the [Release action page](https://github.com/Particular/MonitoringDemo/actions/workflows/release.yml).
2. Click the **Run workflow** button.
Expand Down
4 changes: 4 additions & 0 deletions src/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[*.{csproj,props,targets,xml}]
indent_style = space
indent_size = 2
xml_space_inside_empty_tag = true
11 changes: 4 additions & 7 deletions src/Billing/Billing.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
<OutputType>Exe</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<OutputPath>..\binaries\Billing\</OutputPath>
<ApplicationIcon>failures.ico</ApplicationIcon>
<OutputPath>..\..\binaries\Billing\</OutputPath>
</PropertyGroup>

<ItemGroup>
Expand All @@ -15,11 +14,9 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="NServiceBus" Version="9.2.7" />
<PackageReference Include="NServiceBus.Heartbeat" Version="5.0.0" />
<PackageReference Include="NServiceBus.Metrics.ServiceControl" Version="5.0.0" />

<PackageReference Include="System.Formats.Asn1" Version="8.0.1" />
<PackageReference Include="NServiceBus.Heartbeat" Version="5.*" />
<PackageReference Include="NServiceBus.Metrics.ServiceControl" Version="5.*" />
<PackageReference Include="NServiceBus.Persistence.NonDurable" Version="2.*" />
</ItemGroup>

</Project>
9 changes: 5 additions & 4 deletions src/Billing/OrderPlacedHandler.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
using Messages;
using Shared;

namespace Billing;

public class OrderPlacedHandler(SimulationEffects simulationEffects) : IHandleMessages<OrderPlaced>
public class OrderPlacedHandler : IHandleMessages<OrderPlaced>
{
public async Task Handle(OrderPlaced message, IMessageHandlerContext context)
{
await simulationEffects.SimulatedMessageProcessing(context.CancellationToken);

var orderBilled = new OrderBilled
{
OrderId = message.OrderId
};

await context.Publish(orderBilled);
var publishOptions = new PublishOptions();
publishOptions.SetMessageId(MessageIdHelper.GetHumanReadableMessageId());
await context.Publish(orderBilled, publishOptions);
}
}
119 changes: 61 additions & 58 deletions src/Billing/Program.cs
Original file line number Diff line number Diff line change
@@ -1,78 +1,81 @@
using System.Text.Json;
using Billing;
using System.Reflection;
using System.Text.Json;
using Messages;
using Microsoft.Extensions.DependencyInjection;
using Shared;

Console.Title = "Failure rate (Billing)";
Console.SetWindowSize(65, 15);
var instancePostfix = args.FirstOrDefault();

LoggingUtils.ConfigureLogging("Billing");
var title = string.IsNullOrEmpty(instancePostfix) ? "Failure rate (Billing)" : $"Billing - {instancePostfix}";
var instanceName = string.IsNullOrEmpty(instancePostfix) ? "billing" : $"billing-{instancePostfix}";
var instanceId = DeterministicGuid.Create("Billing", instanceName);
var prometheusPortString = args.Skip(1).FirstOrDefault();

var endpointConfiguration = new EndpointConfiguration("Billing");
endpointConfiguration.LimitMessageProcessingConcurrencyTo(4);
var endpointControls = new ProcessingEndpointControls(() => PrepareEndpointConfiguration(instanceId, instanceName, prometheusPortString));

var serializer = endpointConfiguration.UseSerialization<SystemJsonSerializer>();
serializer.Options(new JsonSerializerOptions
var ui = new UserInterface();
endpointControls.BindSlowProcessingDial(ui, '5', 't');
endpointControls.BindDatabaseFailuresDial(ui, '6', 'y');

endpointControls.BindDatabaseDownToggle(ui, 'f');
endpointControls.BindDelayedRetriesToggle(ui, 'g');
endpointControls.BindAutoThrottleToggle(ui, 'h');

endpointControls.BindFailureReceivingButton(ui, 'v');
endpointControls.BindFailureProcessingButton(ui, 'b');
endpointControls.BindFailureDispatchingButton(ui, 'n');

if (prometheusPortString != null)
{
TypeInfoResolverChain =
{
MessagesSerializationContext.Default
}
});
OpenTelemetryUtils.ConfigureOpenTelemetry("Billing", instanceId.ToString(), int.Parse(prometheusPortString));
}

endpointConfiguration.UseTransport<LearningTransport>();
endpointControls.Start();

endpointConfiguration.Recoverability()
.Delayed(delayed => delayed.NumberOfRetries(0));
ui.RunLoop(title);

endpointConfiguration.AuditProcessedMessagesTo("audit");
endpointConfiguration.SendHeartbeatTo("Particular.ServiceControl");
await endpointControls.StopEndpoint();

endpointConfiguration.UniquelyIdentifyRunningInstance()
.UsingCustomIdentifier(new Guid("1C62248E-2681-45A4-B44D-5CF93584BAD6"))
.UsingCustomDisplayName("original-instance");
EndpointConfiguration PrepareEndpointConfiguration(Guid guid, string s, string? prometheusPortString1)
{
var endpointConfiguration1 = new EndpointConfiguration("Billing");
endpointConfiguration1.LimitMessageProcessingConcurrencyTo(4);

var metrics = endpointConfiguration.EnableMetrics();
metrics.SendMetricDataToServiceControl(
"Particular.Monitoring",
TimeSpan.FromMilliseconds(500)
);
var serializer = endpointConfiguration1.UseSerialization<SystemJsonSerializer>();
serializer.Options(new JsonSerializerOptions
{
TypeInfoResolverChain =
{
MessagesSerializationContext.Default
}
});

var simulationEffects = new SimulationEffects();
endpointConfiguration.RegisterComponents(cc => cc.AddSingleton(simulationEffects));
var transport = new LearningTransport
{
StorageDirectory = Path.Combine(Directory.GetParent(Assembly.GetExecutingAssembly().Location)!.Parent!.FullName, ".learningtransport"),
TransportTransactionMode = TransportTransactionMode.ReceiveOnly
};
endpointConfiguration1.UseTransport(transport);

var endpointInstance = await Endpoint.Start(endpointConfiguration);
endpointConfiguration1.Recoverability()
.Delayed(delayed => delayed.NumberOfRetries(0));

RunUserInterfaceLoop(simulationEffects);
endpointConfiguration1.AuditProcessedMessagesTo("audit");
endpointConfiguration1.SendHeartbeatTo("Particular.ServiceControl");

await endpointInstance.Stop();
endpointConfiguration1.UniquelyIdentifyRunningInstance()
.UsingCustomIdentifier(guid)
.UsingCustomDisplayName(s);

void RunUserInterfaceLoop(SimulationEffects state)
{
while (true)
{
Console.Clear();
Console.WriteLine("Billing Endpoint");
Console.WriteLine("Press F to increase the simulated failure rate");
Console.WriteLine("Press S to decrease the simulated failure rate");
Console.WriteLine("Press ESC to quit");
Console.WriteLine();
var metrics = endpointConfiguration1.EnableMetrics();
metrics.SendMetricDataToServiceControl(
"Particular.Monitoring",
TimeSpan.FromMilliseconds(500)
);

state.WriteState(Console.Out);
endpointConfiguration1.UsePersistence<NonDurablePersistence>();
endpointConfiguration1.EnableOutbox();

var input = Console.ReadKey(true);
endpointConfiguration1.EnableOpenTelemetry();

switch (input.Key)
{
case ConsoleKey.F:
state.IncreaseFailureRate();
break;
case ConsoleKey.S:
state.DecreaseFailureRate();
break;
case ConsoleKey.Escape:
return;
}
}
}
return endpointConfiguration1;
}
32 changes: 0 additions & 32 deletions src/Billing/SimulationEffect.cs

This file was deleted.

Binary file removed src/Billing/failures.ico
Binary file not shown.
Loading