diff --git a/examples/Demo/Demo.csproj b/examples/Demo/Demo.csproj
index 0135a379..6311a970 100644
--- a/examples/Demo/Demo.csproj
+++ b/examples/Demo/Demo.csproj
@@ -41,6 +41,12 @@
PreserveNewest
+
+ PreserveNewest
+
+
+ PreserveNewest
+
@@ -65,7 +71,7 @@
-
+
diff --git a/examples/Demo/NBomber_Studio/ReportingExample.cs b/examples/Demo/NBomber_Studio/ReportingExample.cs
new file mode 100644
index 00000000..9be0d248
--- /dev/null
+++ b/examples/Demo/NBomber_Studio/ReportingExample.cs
@@ -0,0 +1,50 @@
+using NBomber.CSharp;
+using NBomber.Sinks.Timescale;
+
+namespace Demo.NBomber_Studio;
+
+public class NBomberStudioReportingExample
+{
+ // this reporting sink will save stats data into TimescaleDB.
+ private readonly TimescaleDbSink _timescaleDbSink = new();
+
+ public void Run()
+ {
+ var scenario = Scenario.Create("user_flow_scenario", async context =>
+ {
+ var step1 = await Step.Run("login", context, async () =>
+ {
+ await Task.Delay(500);
+ return Response.Ok(sizeBytes: 10, statusCode: "200");
+ });
+
+ var step2 = await Step.Run("get_product", context, async () =>
+ {
+ await Task.Delay(1000);
+ return Response.Ok(sizeBytes: 20, statusCode: "200");
+ });
+
+ var step3 = await Step.Run("buy_product", context, async () =>
+ {
+ await Task.Delay(2000);
+ return Response.Ok(sizeBytes: 30, statusCode: "200");
+ });
+
+ return Response.Ok(statusCode: "201");
+ })
+ .WithWarmUpDuration(TimeSpan.FromSeconds(3))
+ .WithLoadSimulations(
+ Simulation.RampingInject(rate: 200, interval: TimeSpan.FromSeconds(1), during: TimeSpan.FromMinutes(1)), // rump-up to rate 200
+ Simulation.Inject(rate: 200, interval: TimeSpan.FromSeconds(1), during: TimeSpan.FromSeconds(30)), // keep injecting with rate 200
+ Simulation.RampingInject(rate: 0, interval: TimeSpan.FromSeconds(1), during: TimeSpan.FromMinutes(1)) // rump-down to rate 0
+ );
+
+ NBomberRunner
+ .RegisterScenarios(scenario)
+ .LoadInfraConfig("NBomber_Studio/infra-config.json")
+ .WithReportingSinks(_timescaleDbSink)
+ .WithTestSuite("reporting")
+ .WithTestName("timescale_db_demo")
+ .Run();
+ }
+}
diff --git a/examples/Demo/NBomber_Studio/docker-compose.yml b/examples/Demo/NBomber_Studio/docker-compose.yml
new file mode 100644
index 00000000..3d5bd3c5
--- /dev/null
+++ b/examples/Demo/NBomber_Studio/docker-compose.yml
@@ -0,0 +1,34 @@
+services:
+
+ timescaledb:
+ image: timescale/timescaledb:2.14.2-pg16
+ command: postgres -c 'max_connections=500'
+ restart: always
+ ports:
+ - "5432:5432"
+ volumes:
+ - nb_studio_data:/var/lib/postgresql/data
+ environment:
+ POSTGRES_DB: nb_studio_db
+ POSTGRES_USER: timescaledb
+ POSTGRES_PASSWORD: timescaledb
+ healthcheck:
+ test: [ "CMD-SHELL", "pg_isready -d 'user=timescaledb dbname=nb_studio_db'" ]
+ interval: 5s
+ timeout: 10s
+ retries: 5
+ start_period: 5s
+
+ nbomber-studio:
+ image: nbomberdocker/nbomber-studio:latest
+ ports:
+ - "80:8080"
+ depends_on:
+ timescaledb:
+ condition: service_healthy
+ environment:
+ DBSETTINGS:CONNECTIONSTRING: "Host=timescaledb;Port=5432;Username=timescaledb;Password=timescaledb;Database=nb_studio_db;Pooling=true;"
+
+volumes:
+ nb_studio_data:
+ driver: local
diff --git a/examples/Demo/NBomber_Studio/infra-config.json b/examples/Demo/NBomber_Studio/infra-config.json
new file mode 100644
index 00000000..1bd9ce8c
--- /dev/null
+++ b/examples/Demo/NBomber_Studio/infra-config.json
@@ -0,0 +1,5 @@
+{
+ "TimescaleDbSink":{
+ "ConnectionString": "Host=localhost;Port=5432;Database=nb_studio_db;Username=timescaledb;Password=timescaledb;Pooling=true;Maximum Pool Size=300;"
+ }
+}
diff --git a/examples/Demo/Program.cs b/examples/Demo/Program.cs
index b18ee992..d7d21588 100644
--- a/examples/Demo/Program.cs
+++ b/examples/Demo/Program.cs
@@ -22,6 +22,7 @@
using Demo.HTTP.WebAppSimulator;
using Demo.HTTP.SimpleBookstore;
using Demo.MQTT.ClientPool;
+using Demo.NBomber_Studio;
using Demo.WebBrowsers.Playwright;
using Demo.WebBrowsers.Puppeteer;
using Demo.WebSockets;
@@ -64,6 +65,7 @@
// new InfluxDBReportingExample().Run();
// new TimescaleDBReportingExample().Run();
// new CustomReportingExample().Run();
+// new NBomberStudioReportingExample().Run();
// ---- Logs ----
// new TextFileLogger().Run();