Reporting Sinks
Reporting sinks send LoadStrike data to external observability backends for dashboards, alerts, search, and long-term retention.
Matching docs
Search across docs titles, summaries, groups, and section headings.
Use Up and Down Arrow to move through results, then press Enter to open the active page.
No indexed docs matched that search. Try a broader term or open the docs hub.
What this page helps you do
What this page helps you do
Reporting sinks send LoadStrike data to external observability backends for dashboards, alerts, search, and long-term retention.
Who this is for
Engineers writing or reviewing scenario code in one of the supported SDKs.
Prerequisites
- A scenario or runtime surface you want to wire correctly in code
By the end
The exact SDK surface you need for this part of the runtime.
Use this page when
Use this reference when you already know the workflow and need the exact Reporting Sinks API surface in code.
Visual guide
Guide
Built-In Vendor Sinks
LoadStrike ships first-party sinks for InfluxDB, TimescaleDB, Grafana Loki, Datadog, Splunk HEC, and OTEL Collector. These sinks publish LoadStrike reporting events plus metric projections, including realtime scenario stats, custom metrics, final run summaries, final metric snapshots, status-code rows, threshold outcomes, and final plugin-table rows such as failed-response and correlation summaries. Final export also includes started and completed timestamps plus run-result metadata such as report files, disabled sink names, and sink error counts. Datadog sends both log and metric intake, Splunk sends HEC event envelopes for both, OTEL Collector sends OTLP/HTTP logs and metrics, and the storage-backed sinks write the same reporting events and metric projections into their native backends.
Configuration Model
Each sink accepts an options object in code and can also fill missing values from infra config sections such as LoadStrike:ReportingSinks:InfluxDb, LoadStrike:ReportingSinks:TimescaleDb, LoadStrike:ReportingSinks:GrafanaLoki, LoadStrike:ReportingSinks:Datadog, LoadStrike:ReportingSinks:Splunk, and LoadStrike:ReportingSinks:OtelCollector. TypeScript and JavaScript also expose named option constructors alongside object-literal inputs. Influx can split projected metrics into MetricsMeasurementName, TimescaleDB can split them into MetricsTableName, Grafana Loki can keep logs in Loki while sending OTLP/HTTP metrics through MetricsBaseUrl, MetricsEndpointPath, and MetricsHeaders, Splunk uses the HEC event endpoint, OTEL uses OTLP/HTTP, and final plugin-table rows are included in exported sink data where supported.
Sink Identity
Each sink exposes a stable SinkName or equivalent sink identifier. LoadStrike uses that name for registration, licensing checks, disabled sink tracking, and sinkErrors output, so choose a descriptive name that stays stable across runs when you implement a custom sink.
Failure Handling
Sink init, start, realtime writes, and final export all use retry and backoff. If a sink keeps failing, LoadStrike logs a warning, disables that sink for the run, and continues the main load execution instead of aborting the scenario.
Export Ordering
Realtime sink callbacks happen during execution. When the run ends, LoadStrike builds the final LoadStrikeRunResult artifact, writes any local reports that are still enabled, sends SaveRunResult to the sink with that finished artifact, and then calls Stop followed by Dispose. That ordering means final sink export sees the completed threshold, plugin-table, report-file, disabled-sink, and sink-error data.
Grafana Starter Assets
The documentation downloads area includes datasource YAML files, a shared dashboard-provider YAML file, and starter dashboard JSON files so teams can wire Grafana to Loki, InfluxDB, or TimescaleDB without pulling the source repository.
Custom Sink Contract
If you need a destination that LoadStrike does not ship out of the box, implement the reporting-sink contract for your SDK and register it through WithReportingSinks, withReportingSinks, or with_reporting_sinks. The shared lifecycle is Init, Start, SaveRealtimeStats, SaveRealtimeMetrics, SaveRunResult, Stop, and Dispose. SaveRunResult receives the full run artifact, including report file paths, disabled sink names, sink error details, correlation rows, scenario durations, and started and completed timestamps. Stop ends active work, Dispose releases any remaining resources, and Dispose failures are recorded without aborting shutdown.
Plan Gate
Built-in vendor sinks require the matching vendor entitlement and are available on Business and above. Custom reporting sinks require Business and above and the extensions.reporting_sinks.custom entitlement.
SDK reference samples
Use these SDK samples to compare how Reporting Sinks is exposed across the supported languages before you wire it into a full scenario.
If you run these examples locally, add a valid runner key before execution starts. Set it with WithRunnerKey("...") or the config key LoadStrike:RunnerKey.
Reporting Sink
using LoadStrike;
var sink = new DatadogReportingSink(new DatadogReportingSinkOptions
{
BaseUrl = "https://api.datadoghq.com",
ApiKey = "dd-api-key",
ApplicationKey = "dd-app-key",
StaticTags =
{
["environment"] = "staging"
}
});
LoadStrikeRunner.RegisterScenarios(scenario)
.WithReportingSinks(sink)
.WithRunnerKey("rkl_your_local_runner_key")
.Run();
package main
import loadstrike "loadstrike.com/sdk/go"
func main() {
sink := loadstrike.DatadogReportingSink{
Options: loadstrike.DatadogSinkOptions{
BaseURL: "https://http-intake.logs.datadoghq.com",
APIKey: "dd-api-key",
ApplicationKey: "dd-app-key",
Service: "orders-api",
},
}
loadstrike.RegisterScenarios(loadstrike.Empty("sink-demo")).
WithReportingSinks(sink).
LoadInfraConfig("./appsettings.infra.json").
Run()
}
import com.loadstrike.runtime.LoadStrikeRuntime.LoadStrikeRunner;
import com.loadstrike.runtime.LoadStrikeSinks;
import com.loadstrike.runtime.LoadStrikeRuntime.LoadStrikeResponse;
import com.loadstrike.runtime.LoadStrikeRuntime.LoadStrikeScenario;
import com.loadstrike.runtime.LoadStrikeRuntime.LoadStrikeSimulation;
var scenario = LoadStrikeScenario
.create("submit-orders", ignoredContext -> LoadStrikeResponse.ok("200"))
.withLoadSimulations(LoadStrikeSimulation.inject(10, 1d, 20d));
var options = new LoadStrikeSinks.DatadogSinkOptions();
options.baseUrl = "https://api.datadoghq.com";
options.apiKey = "dd-api-key";
options.applicationKey = "dd-app-key";
options.staticTags.put("environment", "staging");
var sink = new LoadStrikeSinks.DatadogReportingSink(options);
LoadStrikeRunner.registerScenarios(scenario)
.withReportingSinks(sink)
.withRunnerKey("rkl_your_local_runner_key")
.run();
from loadstrike_sdk import DatadogReportingSink, LoadStrikeResponse, LoadStrikeRunner, LoadStrikeScenario, LoadStrikeSimulation
scenario = (
LoadStrikeScenario.create("submit-orders", lambda _: LoadStrikeResponse.ok("200"))
.with_load_simulations(LoadStrikeSimulation.inject(10, 1, 20))
)
sink = DatadogReportingSink(
base_url="https://api.datadoghq.com",
api_key="dd-api-key",
application_key="dd-app-key",
static_tags={"environment": "staging"},
static_attributes={"team": "perf"},
)
LoadStrikeRunner.register_scenarios(scenario) \
.with_reporting_sinks(sink) \
.with_runner_key("rkl_your_local_runner_key") \
.run()
import {
DatadogReportingSink,
DatadogReportingSinkOptions,
LoadStrikeResponse,
LoadStrikeRunner,
LoadStrikeScenario,
LoadStrikeSimulation
} from "@loadstrike/loadstrike-sdk";
const scenario = LoadStrikeScenario
.create("submit-orders", async () => LoadStrikeResponse.ok("200"))
.withLoadSimulations(LoadStrikeSimulation.inject(10, 1, 20));
const sink = new DatadogReportingSink(new DatadogReportingSinkOptions({
BaseUrl: "https://api.datadoghq.com",
ApiKey: "dd-api-key",
ApplicationKey: "dd-app-key",
StaticTags: {
environment: "staging"
},
StaticAttributes: {
team: "perf"
}
}));
await LoadStrikeRunner
.registerScenarios(scenario)
.withReportingSinks(sink)
.withRunnerKey("rkl_your_local_runner_key")
.run();
const {
DatadogReportingSink,
DatadogReportingSinkOptions,
LoadStrikeResponse,
LoadStrikeRunner,
LoadStrikeScenario,
LoadStrikeSimulation
} = require("@loadstrike/loadstrike-sdk");
(async () => {
const scenario = LoadStrikeScenario
.create("submit-orders", async () => LoadStrikeResponse.ok("200"))
.withLoadSimulations(LoadStrikeSimulation.inject(10, 1, 20));
const sink = new DatadogReportingSink(new DatadogReportingSinkOptions({
BaseUrl: "https://api.datadoghq.com",
ApiKey: "dd-api-key",
ApplicationKey: "dd-app-key",
StaticTags: {
environment: "staging"
},
StaticAttributes: {
team: "perf"
}
}));
await LoadStrikeRunner
.registerScenarios(scenario)
.withReportingSinks(sink)
.withRunnerKey("rkl_your_local_runner_key")
.run();
})();
Built-In Sink Options
Writes reporting events and metric projections into InfluxDB, with an optional separate metrics measurement.
Writes reporting events and projected metrics into PostgreSQL or TimescaleDB tables.
Writes log-style reporting events to Loki and can forward projected metrics through the OTLP metrics companion settings.
Sends reporting events to Datadog logs and projected metrics to Datadog metrics.
Sends both reporting events and metric projections through the Splunk HEC event endpoint.
Sends OTLP/HTTP logs and metrics to an OpenTelemetry collector pipeline.
Every sink uses a stable sink identifier so disabledSinks and sinkErrors can point to the correct destination during troubleshooting.
SaveRunResult receives the completed LoadStrikeRunResult before Stop and Dispose run, so threshold rows, plugin tables, report files, and sink error metadata are already available.
Enterprise projects can also register a custom reporting sink implementation when a built-in destination is not enough.
{
"LoadStrike": {
"ReportingSinks": {
"InfluxDb": {
"BaseUrl": "https://influx.example.com",
"Organization": "performance-team",
"Bucket": "loadstrike-runs",
"Token": "influx-token",
"MeasurementName": "loadstrike_events",
"MetricsMeasurementName": "loadstrike_metrics"
},
"TimescaleDb": {
"ConnectionString": "Host=db.example.com;Port=5432;Database=loadstrike;Username=postgres;Password=postgres",
"Schema": "observability",
"TableName": "loadstrike_reporting_events",
"MetricsTableName": "loadstrike_reporting_metrics"
},
"GrafanaLoki": {
"BaseUrl": "https://loki.example.com",
"BearerToken": "loki-token",
"MetricsBaseUrl": "https://otel-gateway.example.com",
"MetricsEndpointPath": "/v1/metrics",
"MetricsHeaders": {
"Authorization": "Bearer otlp-metrics-token"
}
},
"Datadog": {
"BaseUrl": "https://api.datadoghq.com",
"ApiKey": "dd-api-key",
"ApplicationKey": "dd-app-key"
},
"Splunk": {
"BaseUrl": "https://splunk.example.com",
"Token": "splunk-hec-token"
},
"OtelCollector": {
"BaseUrl": "https://otel.example.com",
"Headers": {
"Authorization": "Bearer otel-token"
}
}
}
}
}
Individual Sink Samples
Pick the sink that matches the backend your team already uses. Every built-in sink sends reporting events and metric projections while the run is active, and the final export also includes final metric snapshots, started and completed timestamps, report-file metadata, disabled sink names, sink error counts, and plugin-table rows such as failed responses and correlation summaries. If you load infra config, missing values can bind from LoadStrike:ReportingSinks:* sections. Datadog sends logs and metrics, Splunk sends both through HEC events, OTEL Collector sends OTLP/HTTP logs and metrics, and Grafana starter files are published for InfluxDB, TimescaleDB, and Grafana Loki.
Datadog Sink
Choose Datadog when your team already reads events in Datadog Logs and metrics in Datadog Metrics.
var scenario = LoadStrikeScenario.Empty("orders-load")
.WithLoadSimulations(
LoadStrikeSimulation.Inject(rate: 25, interval: TimeSpan.FromSeconds(1), during: TimeSpan.FromMinutes(2))
);
var datadogSink = new DatadogReportingSink(new DatadogReportingSinkOptions
{
BaseUrl = "https://api.datadoghq.com",
ApiKey = "dd-api-key",
ApplicationKey = "dd-app-key",
StaticTags =
{
["environment"] = "staging",
["service"] = "orders-api"
},
StaticAttributes =
{
["team"] = "performance"
}
});
LoadStrikeRunner.RegisterScenarios(scenario)
.WithReportingSinks(datadogSink)
.WithRunnerKey("rkl_your_local_runner_key")
.Run();
Splunk HEC Sink
Choose Splunk when your team already uses the HEC event endpoint and wants both reporting events and metric projections there.
var scenario = LoadStrikeScenario.Empty("checkout-load")
.WithLoadSimulations(
LoadStrikeSimulation.KeepConstant(copies: 12, during: TimeSpan.FromMinutes(5))
);
var splunkSink = new SplunkReportingSink(new SplunkReportingSinkOptions
{
BaseUrl = "https://splunk.example.com",
Token = "splunk-hec-token",
Source = "loadstrike",
Sourcetype = "_json",
Index = "observability",
StaticFields =
{
["environment"] = "preprod",
["service"] = "checkout"
}
});
LoadStrikeRunner.RegisterScenarios(scenario)
.WithReportingSinks(splunkSink)
.WithRunnerKey("rkl_your_local_runner_key")
.Run();
OTEL Collector Sink
Choose OTEL Collector when your team already sends telemetry through an OpenTelemetry collector or a compatible OTLP/HTTP pipeline.
var scenario = LoadStrikeScenario.Empty("payments-load")
.WithLoadSimulations(
LoadStrikeSimulation.Inject(rate: 10, interval: TimeSpan.FromSeconds(1), during: TimeSpan.FromMinutes(3))
);
var otelSink = new OtelCollectorReportingSink(new OtelCollectorReportingSinkOptions
{
BaseUrl = "https://otel.example.com",
Headers =
{
["Authorization"] = "Bearer otel-token"
},
StaticResourceAttributes =
{
["deployment.environment"] = "production-like",
["service.name"] = "payments"
}
});
LoadStrikeRunner.RegisterScenarios(scenario)
.WithReportingSinks(otelSink)
.WithRunnerKey("rkl_your_local_runner_key")
.Run();
InfluxDB Sink
Choose InfluxDB when you want events and projected metrics written to an Influx bucket. Use MetricsMeasurementName if those projected metrics should live in a separate measurement.
var scenario = LoadStrikeScenario.Empty("orders-load")
.WithLoadSimulations(
LoadStrikeSimulation.Inject(rate: 25, interval: TimeSpan.FromSeconds(1), during: TimeSpan.FromMinutes(2))
);
var influxSink = new InfluxDbReportingSink(new InfluxDbReportingSinkOptions
{
BaseUrl = "https://influx.example.com",
Organization = "performance-team",
Bucket = "loadstrike-runs",
Token = "influx-token",
MeasurementName = "loadstrike_orders",
MetricsMeasurementName = "loadstrike_orders_metrics",
StaticTags =
{
["environment"] = "staging",
["service"] = "orders-api"
}
});
LoadStrikeRunner.RegisterScenarios(scenario)
.WithReportingSinks(influxSink)
.WithRunnerKey("rkl_your_local_runner_key")
.Run();
TimescaleDB Sink
Choose TimescaleDB when you want PostgreSQL-compatible storage, queryable event rows, and a separate table for projected metrics.
var scenario = LoadStrikeScenario.Empty("checkout-load")
.WithLoadSimulations(
LoadStrikeSimulation.KeepConstant(copies: 12, during: TimeSpan.FromMinutes(5))
);
var timescaleSink = new TimescaleDbReportingSink(new TimescaleDbReportingSinkOptions
{
ConnectionString = "Host=db.example.com;Port=5432;Database=loadstrike;Username=postgres;Password=postgres",
Schema = "observability",
TableName = "loadstrike_reporting_events",
MetricsTableName = "loadstrike_reporting_metrics",
CreateSchemaIfMissing = true,
EnableHypertableIfAvailable = true,
StaticTags =
{
["environment"] = "preprod",
["service"] = "checkout"
}
});
LoadStrikeRunner.RegisterScenarios(scenario)
.WithReportingSinks(timescaleSink)
.WithRunnerKey("rkl_your_local_runner_key")
.Run();
Grafana Loki Sink
Choose Grafana Loki when you want log-style reporting events in Loki and projected metrics sent through a companion OTLP/HTTP path for dashboards and alerts.
var scenario = LoadStrikeScenario.Empty("payments-load")
.WithLoadSimulations(
LoadStrikeSimulation.Inject(rate: 10, interval: TimeSpan.FromSeconds(1), during: TimeSpan.FromMinutes(3))
);
var lokiSink = new GrafanaLokiReportingSink(new GrafanaLokiReportingSinkOptions
{
BaseUrl = "https://loki.example.com",
MetricsBaseUrl = "https://otel-gateway.example.com",
MetricsEndpointPath = "/v1/metrics",
MetricsHeaders =
{
["Authorization"] = "Bearer otlp-metrics-token"
},
TenantId = "platform-team",
BearerToken = "loki-token",
StaticLabels =
{
["environment"] = "production-like",
["service"] = "payments"
}
});
LoadStrikeRunner.RegisterScenarios(scenario)
.WithReportingSinks(lokiSink)
.WithRunnerKey("rkl_your_local_runner_key")
.Run();
Full Observability Asset Guide
Use these public downloads when you want the matching Grafana files or sink templates without pulling them from the source repository.
Public download paths:
- /downloads/grafana/provisioning/datasources/loadstrike-loki.yaml
- /downloads/grafana/provisioning/datasources/loadstrike-influxdb.yaml
- /downloads/grafana/provisioning/datasources/loadstrike-timescaledb.yaml
- /downloads/grafana/provisioning/dashboards/loadstrike.yaml
- /downloads/grafana/dashboards/loadstrike-loki-overview.json
- /downloads/grafana/dashboards/loadstrike-influxdb-overview.json
- /downloads/grafana/dashboards/loadstrike-timescaledb-overview.json
- /downloads/observability/sinks/loadstrike-datadog-reporting-sink.json
- /downloads/observability/sinks/loadstrike-splunk-reporting-sink.json
- /downloads/observability/sinks/loadstrike-otel-collector-reporting-sink.json
- /downloads/observability/loadstrike-observability-assets-guide.md