Custom Reporting

Use custom reporting when you need a sink that is not built in and still want the normal LoadStrike sink lifecycle.

What this page helps you do

What this page helps you do

Use custom reporting when you need a sink that is not built in and still want the normal LoadStrike sink lifecycle.

Who this is for

Teams exporting final run data and realtime metrics into supported observability backends.

Prerequisites

  • A run result or sink destination you want to wire into the wider observability stack

By the end

A sink-specific setup path that stays tied to the same LoadStrike report model.

Use this page when

Use this page when the local report is not the only destination and you need to wire realtime or final export into a supported sink.

Visual guide

Realtime reporting flow showing LoadStrike events moving through a sink to observability backends.
Realtime reporting sinks receive interval snapshots during execution and final metadata when the run completes.

Sample Report Data Rows

Scope    Scenario     Result Count RPS  LatencyP50Ms LatencyP80Ms LatencyP85Ms LatencyP90Ms LatencyP95Ms LatencyP99Ms
Scenario reports-demo OK     675   15.0 21.4         30.2         33.0         36.8         48.6         72.1

LatencyTable Scenario     Result Count LatencyP50Ms LatencyP95Ms
LatencyTable reports-demo OK     675   21.4         48.6
LatencyTable reports-demo FAIL   12    35.9         79.2

StatusCode Result Percent
200        OK     97.48
500        FAIL   2.52

FailedStatus Scope     Scenario     Step StatusCode Count Percent
FailedStatus Scenario  reports-demo      500       12    1.75

Reporting

Realtime reporting

Choose Portal Reporting when users should review runs in the customer portal, pick the built-in sink page that matches the backend your team already runs, or open Custom Reporting when you need to implement your own destination. Each tab opens a dedicated page with the settings, behavior, and lifecycle details for that reporting path.

Guide

When To Use Custom Reporting

Choose custom reporting when your team needs to push realtime updates and the final run result into an internal platform, a proprietary API, or a destination that is not covered by the built-in sinks.

Shared Sink Lifecycle

Implement the LoadStrikeReportingSink contract for your SDK and register it with WithReportingSinks(...). LoadStrike calls sinks in one fixed order: Init, Start, SaveRealtimeStats, SaveRealtimeMetrics, SaveRunResult, Stop, then Dispose.

What The Final Callback Receives

SaveRunResult receives the same full LoadStrikeRunResult artifact that Run() returns. That includes final counts, timing, report files, sink errors, policy errors, detailed report rows, and correlation output when those features are enabled.

Failure And Cleanup Behavior

Init, start, realtime export, and final export use retry and backoff. Persistent sink failures disable only that sink for the run. Dispose is best-effort cleanup; if it throws, LoadStrike records the issue in sinkErrors and continues shutdown.

Plan Gate

Built-in vendor sinks and custom reporting are available on Business and above. Custom sink registration still requires the extensions.reporting_sinks.custom entitlement.

Custom reporting setup

Implement the reporting sink contract for your SDK, register it with WithReportingSinks(...), and let LoadStrike send realtime snapshots plus the final LoadStrikeRunResult automatically.

If you run these examples locally, add a valid runner key before execution starts. Set it with WithRunnerKey("...") or the config key LoadStrike:RunnerKey.

HTML reports also include the top-right Light/Dark theme toggle. Light is the default report theme.

Custom Reporting

using LoadStrike;
using Microsoft.Extensions.Configuration;

public sealed class InternalOpsSink : LoadStrikeReportingSink
{
    public string SinkName => "internal-ops";

    public Task Init(LoadStrikeBaseContext context, IConfiguration infraConfig) => Task.CompletedTask;

    public Task Start(LoadStrikeSessionStartInfo sessionInfo) => Task.CompletedTask;

    public Task SaveRealtimeStats(LoadStrikeScenarioStats[] stats)
    {
        foreach (var scenario in stats)
        {
            Console.WriteLine($"{scenario.ScenarioName}: {scenario.AllRequestCount}");
        }

        return Task.CompletedTask;
    }

    public Task SaveRealtimeMetrics(LoadStrikeMetricStats metrics) => Task.CompletedTask;

    public Task SaveRunResult(LoadStrikeRunResult result)
    {
        Console.WriteLine($"Final requests: {result.AllRequestCount}");
        return Task.CompletedTask;
    }

    public Task Stop() => Task.CompletedTask;

    public void Dispose()
    {
    }
}

var scenario = LoadStrikeScenario.CreateAsync("submit-orders", async _ =>
{
    await Task.Delay(25);
    LoadStrikeReply reply = LoadStrikeResponse.Ok(statusCode: "200");
    return reply;
})
.WithLoadSimulations(LoadStrikeSimulation.Inject(rate: 10, interval: TimeSpan.FromSeconds(1), during: TimeSpan.FromSeconds(20)));

LoadStrikeRunner.RegisterScenarios(scenario)
    .WithReportingInterval(TimeSpan.FromSeconds(5))
    .WithReportingSinks(new InternalOpsSink())
    .WithRunnerKey("rkl_your_local_runner_key")
    .Run();

Custom reporting contract

LoadStrikeReportingSink

Implement this contract in your SDK when you need to send LoadStrike data to a destination that is not covered by the built-in sinks.

SinkName / sinkName / sink_name

Provide a stable sink name so LoadStrike can validate registration and record sinkErrors against the correct destination.

Init(context, infraConfig)

Resolve configuration, create clients, and prepare any sink-owned state before the run begins.

Start(sessionInfo)

Receives session metadata such as the test suite, test name, and timestamps after sink initialization succeeds.

SaveRealtimeStats / SaveRealtimeMetrics

Called at the configured reporting interval with scenario statistics and projected metrics snapshots.

SaveRunResult(LoadStrikeRunResult)

Receives the final run artifact automatically at the end of the run. You do not need to enable a separate finalizer hook.

Stop() then Dispose()

Stop ends active sink work cleanly. Dispose is the final best-effort cleanup phase for sockets, writers, or client objects. Dispose failures are recorded in sinkErrors with phase=dispose.

WithReportingSinks(...)

Registers one or more sink instances on the runner or context. Custom reporting sinks require Business and above.