Expanded Built-In Sinks

Use the expanded sink set when LoadStrike run data should flow into supported observability platforms, databases, message streams, StatsD collectors, JSONL files, or a generic webhook receiver.

What this page helps you do

What this page helps you do

Use the expanded sink set when LoadStrike run data should flow into supported observability platforms, databases, message streams, StatsD collectors, JSONL files, or a generic webhook receiver.

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

What The Expanded Set Covers

The expanded sink set covers Prometheus Remote Write, Amazon CloudWatch, Dynatrace, New Relic, Elasticsearch, OpenSearch, Kafka, StatsD, DogStatsD, Netdata-compatible StatsD, JSONL file streaming, and GenericWebhook. These sit alongside InfluxDB, TimescaleDB, Grafana Loki, Datadog, Splunk HEC, OTEL Collector, portal reporting, and custom sink options.

Shared Export Model

Built-in sinks receive the common LoadStrike reporting model: individual attempt batches where the destination supports event records, one final event per completed correlation outcome, realtime scenario stats, projected metrics, final run summaries, final metric snapshots, threshold results, report-file metadata, sink error metadata, and detailed report rows when the run produces them. Correlation outcome events retain tracking and GatherBy dimensions without substituting SDK percentile aggregates. Metric-only destinations expose the closest supported per-attempt projection and report that the complete event shape is unavailable. Choose the destination based on where your team already reviews performance evidence.

Destination Families

Prometheus Remote Write sends Snappy-compressed protobuf; Amazon CloudWatch sends SigV4-signed PutMetricData requests; Dynatrace sends its metrics line protocol; New Relic sends Metric API JSON batches. These are metrics-first destinations. GenericWebhook instead sends generic LoadStrike reporting JSON. Use StatsD, DogStatsD, or Netdata-compatible StatsD for UDP metric workflows and JSONL for a portable event stream. Elasticsearch and OpenSearch use one JSON document per reporting call. Use Kafka when the organization wants reporting events on an internal stream for downstream processing.

Line-Oriented Destinations

StatsD-compatible prefixes and DogStatsD tag values normalize unsupported protocol separators so one measurement cannot become extra records. InfluxDB normalizes line breaks in names, tags, and string fields to spaces before escaping them; ordinary single-line values are preserved.

Direct Vendor Availability

Prometheus Remote Write, Amazon CloudWatch, Dynatrace, and New Relic are supported in C#, Java, Python, TypeScript, JavaScript, and Go with provider-specific payloads. Python requires the reporting extra for Prometheus and CloudWatch. Java requires provider options plus a ProtocolPublisher.

Java Publisher Requirement

A Java ProtocolPublisher receives the complete target, headers, and byte body and must transmit all three. It also owns HTTP retry, TLS, and proxy policy. Initialization fails with `<SinkClass> requires a ProtocolPublisher.` when it is absent. Replace deprecated no-argument vendor construction with the provider options plus this publisher.

C# Native Kafka And UDP

C# Kafka requires Topic and uses BootstrapServers for native publishing when PublishAsync is absent; an explicit PublishAsync delegate takes precedence. C# StatsD, DogStatsD, and Netdata use Host and Port for native UDP when SendLineAsync is absent. A completed UDP send means the local UDP stack accepted the datagram, not that any receiver acknowledged delivery.

Go Kafka Publisher

Go Kafka reporting uses the application-supplied `KafkaReportingSinkOptions.Publish` function; it is not a built-in Kafka client. The function receives the selected topic and serialized reporting payload, with `loadstrike-events` used when Topic is blank. If the function is missing, LoadStrike records the initialization error and disables that reporting sink before traffic; the workload can still run and its counts are unchanged. A returned error follows the shared retry policy and, after exhaustion, is recorded against and can disable the sink without changing the workload request, success, or failure counts.

Search Document Routing

.NET defaults Elasticsearch and OpenSearch IndexName to loadstrike-runs. Its default / EndpointPath signals automatic routing, so an unset path derives /{URL-escaped IndexName}/_doc; an explicitly supplied EndpointPath takes precedence as the compatibility override. Python and TypeScript or JavaScript use the same document route with a loadstrike-events default unless their explicit path override wins. Elasticsearch ApiKey and OpenSearch Username and Password produce the matching authorization header. Java gives the application publisher the sink name and JSON payload, so the application owns the document-ingestion target and delivery policy. Go requires a caller-supplied document-ingestion endpoint and leaves routing to the application.

Search Index Validation

For direct .NET, Python, and TypeScript or JavaScript routing, a selected IndexName must be nonblank lowercase text, at most 255 UTF-8 bytes, not . or .., and cannot start with -, _, or +. It rejects \, /, *, ?, ", <, >, |, ASCII space, comma, #, colon, control characters, and malformed Unicode. Diagnostics identify the affected option or full configuration path without echoing the rejected value. An explicit EndpointPath makes IndexName dormant, so the unused name is not validated.

Metric Value Limits

Every direct metric sink accepts only finite values in the inclusive range [-1e100, 1e100]. Limits are measured after provider-specific normalization and before encoding, except for the documented Dynatrace minimum-length prefix step. Ill-formed Unicode, reserved-key overrides, and key collisions after normalization fail before network I/O. The reserved scenario and status attributes consume two of 20 slots, leaving 18 for user attributes; evidence-only run_id leaves 17. Authoritative scenario and status values may not be empty. Prometheus also reserves __name__.

Prometheus Limits

Metric names are 1-200 UTF-8 bytes and normalize to [A-Za-z_:][A-Za-z0-9_:]*. A point has at most 20 labels. Label keys are 1-64 UTF-8 bytes and normalize to [A-Za-z_][A-Za-z0-9_]*; values are at most 256 UTF-8 bytes and may be empty.

CloudWatch Limits

Namespaces are 1-100 UTF-8 bytes and may not start with a colon. Metric names are 1-200 UTF-8 bytes. A point has at most 20 dimensions. Keys are 1-64 printable ASCII bytes, nonblank, and may not start with a colon; values are 1-256 printable ASCII bytes and nonblank. Count metrics always use Count. Gauge aliases map count or counts to Count, ms or millisecond or milliseconds to Milliseconds, byte or bytes to Bytes, and s or sec or second or seconds to Seconds; every other or unitless gauge uses None.

Dynatrace And New Relic Limits

Dynatrace metric names are 1-200 UTF-8 bytes before deterministic provider-valid minimum-length prefixing; up to 20 dimensions use 1-64 UTF-8-byte keys and 1-255 UTF-8-byte values. New Relic metric names are 1-200 UTF-8 bytes; up to 20 attributes use 1-64 UTF-8-byte keys normalized to [A-Za-z0-9:._]+ and values of at most 256 UTF-8 bytes, including empty values.

Canonical Infra Keys

Canonical sections are PrometheusRemoteWrite, CloudWatch, Dynatrace, Elasticsearch, OpenSearch, NewRelic, Webhook, Kafka, StatsD, Netdata, DogStatsD, and Jsonl. HTTP sinks use BaseUrl, EndpointPath, TimeoutSeconds, Headers, and StaticTags where supported. Provider fields are Prometheus BearerToken; CloudWatch EndpointUrl, Namespace, Region, AccessKeyId, SecretAccessKey, and SessionToken; Dynatrace ApiToken; Elasticsearch IndexName and ApiKey; OpenSearch IndexName, Username, and Password; New Relic LicenseKey or ApiKey; Webhook Url and Secret; Kafka BootstrapServers, Topic, and StaticTags; StatsD-family Prefix, Host, Port, and the documented Tags or StaticTags aliases; and JSONL FilePath, called Path in Java constructor options. Only DogStatsD serializes tag maps.

Expanded Config And Redaction

Selected LoadStrike:ReportingSinks:* sections fill missing values only, while explicit code values win and dormant sections are ignored. Canonical keys cover HTTP endpoint, timeout, headers, tags, provider credentials, namespace and region, Kafka bootstrap servers and topic, StatsD host and port, and JSONL file path. Unknown keys preserve their full configuration path. Diagnostics redact API keys, access keys, secrets, tokens, passwords, and sensitive authorization headers.

Generic Webhook Migration

GenericWebhook sends LoadStrike reporting JSON, including gzip-compressed observation batches where applicable, without converting the body to a vendor metric protocol. Migrate an old generic metrics URL to GenericWebhook only when its receiver accepts this generic body; otherwise use the matching direct provider sink.

Failure Behavior

Sink initialization, realtime export, raw delivery, completion, final export, stop, and dispose all use the configured bounded retry policy and remain isolated from scenario execution. A recovered callback adds no final sink error. Persistent sink failures are recorded in the run result and can disable that sink for the current run, while the load test itself continues. Stop and dispose are best-effort cleanup, and an exhausted stop callback does not prevent dispose.

Plan Gate

Expanded built-in reporting sinks are available on Enterprise. The same runner key validates the scenario, the selected sinks, portal reporting, and any transport features used by the run.

Expanded sink setup

Select each destination in code, then provide its C# connection settings through options or the matching infra-config section. Configuration never enables an unselected sink, and code-supplied values take precedence.

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 include a top-right Light/Dark theme toggle and responsive offline SVG charts. Use exact-value tooltips, legends, zoom, pan, reset, the accessible expanded view, chart-title search, and grid-density controls to inspect dense results. Light is the default report theme.

Expanded Built-In Sinks

using LoadStrike;

var scenario = LoadStrikeScenario.Empty("orders-expanded-sinks")
    .WithLoadSimulations(LoadStrikeSimulation.Inject(20, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(120)));

var prometheus = new PrometheusRemoteWriteReportingSink(new PrometheusRemoteWriteReportingSinkOptions
{
    BaseUrl = "https://prometheus.example.com",
    BearerToken = Environment.GetEnvironmentVariable("PROMETHEUS_BEARER_TOKEN") ?? string.Empty
});

var jsonl = new JsonlFileReportingSink(new JsonlFileReportingSinkOptions
{
    FilePath = "./reports/loadstrike-events.jsonl"
});

// Use GenericWebhook only when the receiver accepts generic LoadStrike JSON.
var webhook = new GenericWebhookReportingSink(new GenericWebhookReportingSinkOptions
{
    Url = "https://loadstrike-gateway.example.com/ingest",
    Secret = "gateway-secret"
});

LoadStrikeRunner.RegisterScenarios(scenario)
    .WithReportingInterval(TimeSpan.FromSeconds(5))
    .WithReportingSinks(prometheus, jsonl, webhook)
    .WithRunnerKey("rkl_your_enterprise_runner_key")
    .Run();

C# expanded reporting sink configuration fields

ConfigurationSectionPath

Selects the infra-config section read by the registered sink. Each sink defaults to its LoadStrike:ReportingSinks:<SinkName> section.

Canonical config keys

HTTP sinks use BaseUrl, EndpointPath, TimeoutSeconds, Headers, and StaticTags where supported. Provider fields are Prometheus BearerToken; CloudWatch EndpointUrl, Namespace, Region, AccessKeyId, SecretAccessKey, and SessionToken; Dynatrace ApiToken; Elasticsearch IndexName and ApiKey; OpenSearch IndexName, Username, and Password; New Relic LicenseKey or ApiKey; Webhook Url and Secret; Kafka BootstrapServers, Topic, and StaticTags; StatsD-family Prefix, Host, Port, and the documented Tags or StaticTags aliases; and JSONL FilePath (Path in Java constructor options). Only DogStatsD serializes tag maps.

BaseUrl / Url / EndpointPath

HTTP destination and path fields. A configured BaseUrl cannot contain a query or fragment; EndpointPath must be relative and path-like, may contain a query, and cannot contain a fragment. GenericWebhook accepts Url as its complete endpoint, permits its query, rejects its fragment, and ignores EndpointPath when Url wins. CloudWatch retains a non-root EndpointPath when BaseUrl is also supplied.

TimeoutSeconds / Headers

Common HTTP timeout and request-header settings. Configure Headers as a nested key/value map with valid HTTP names; content-managed and destination-managed headers cannot be overridden.

StaticTags

Tags for supported event and metric exports. Elasticsearch, OpenSearch, and Webhook add them to ordinary event envelopes and projected metrics without rewriting canonical iteration-batch or completion payloads.

BearerToken / ApiToken / ApiKey / LicenseKey / Secret

Destination-specific credentials for Prometheus remote write, Dynatrace, Elasticsearch, New Relic, and Webhook. Protected configuration providers are recommended for secret values.

CloudWatch Namespace / Region / AccessKeyId / SecretAccessKey

Required CloudWatch metric namespace, AWS region, and credentials.

Elasticsearch and OpenSearch IndexName

Target index used for reporting events. OpenSearch Username and Password must be configured together when basic authentication is used.

Cross-SDK search delivery

.NET sends one JSON document per reporting call, defaults IndexName to loadstrike-runs, and treats its default / EndpointPath as the automatic-routing signal: an unset path derives /{URL-escaped IndexName}/_doc, while an explicitly supplied EndpointPath takes precedence. Python and TypeScript or JavaScript use the same document route with a loadstrike-events default unless their explicit path override wins. Java passes the sink name and JSON payload to an application publisher, while Go requires a caller-supplied document-ingestion endpoint.

Search IndexName validation

For direct .NET, Python, and TypeScript or JavaScript routing, a selected IndexName must be nonblank lowercase text, at most 255 UTF-8 bytes, not . or .., and cannot start with -, _, or +. It rejects \, /, *, ?, ", <, >, |, ASCII space, comma, #, colon, control characters, and malformed Unicode. Diagnostics identify the affected option or full configuration path without echoing the rejected value. An explicit EndpointPath makes IndexName dormant, so the unused name is not validated.

Direct metric protocols

Prometheus Remote Write, CloudWatch, Dynatrace, and New Relic use provider-specific metric protocols in every SDK. Java supplies provider options and a ProtocolPublisher that transmits the target, headers, and bytes and owns retry, TLS, and proxy policy. Python Prometheus and CloudWatch require the reporting extra.

GenericWebhook body

GenericWebhook sends generic LoadStrike reporting JSON and does not translate it into a vendor metric protocol.

Kafka delivery

C# uses BootstrapServers for native publishing when PublishAsync is absent, and an explicit PublishAsync delegate takes precedence. Go uses an application Publish(topic, payload) function, defaults a blank Topic to loadstrike-events, and does not treat that function as a native Kafka client. If Publish is missing, LoadStrike records the initialization error and disables that reporting sink before traffic; the workload can still run and its counts are unchanged. Go publisher errors use sink retries and, after exhaustion, are recorded against the sink without changing workload counts.

StatsD Prefix / Host / Port

Metric prefix and native UDP destination for StatsD-family sinks. Prefix shapes all emitted lines. IPv4, IPv6, and DNS hosts are supported; keep the port in the separate Port field. A completed UDP send means the local UDP stack accepted the datagram, not that a receiver acknowledged it.

DogStatsD Tags / StaticTags

DogStatsD serializes both maps as tag suffixes, with StaticTags applied after Tags. Plain StatsD and Netdata do not serialize tag maps. Configured values reject line-protocol delimiters, and explicit code tag values take precedence over configured aliases.

SendLineAsync

Optional code-only callback for StatsD, DogStatsD, and Netdata. When supplied, Host and Port are dormant.

Jsonl FilePath

Required destination file path for newline-delimited JSON reporting envelopes.

Code-first precedence

Explicit option values win over infra config, including explicit defaults, empty values, and empty maps. Unselected sink sections remain dormant.

{
  "LoadStrike": {
    "ReportingSinks": {
      "PrometheusRemoteWrite": {
        "BaseUrl": "https://prometheus.example.com",
        "BearerToken": "prometheus-token"
      },
      "CloudWatch": {
        "Namespace": "LoadStrike/ProductionLike",
        "Region": "eu-west-2",
        "AccessKeyId": "access-key-id",
        "SecretAccessKey": "secret-access-key"
      },
      "Dynatrace": {
        "BaseUrl": "https://example.live.dynatrace.com",
        "ApiToken": "dynatrace-token"
      },
      "Elasticsearch": {
        "BaseUrl": "https://elastic.example.com",
        "IndexName": "loadstrike-runs",
        "ApiKey": "elastic-api-key"
      },
      "OpenSearch": {
        "BaseUrl": "https://opensearch.example.com",
        "IndexName": "loadstrike-runs",
        "Username": "loadstrike",
        "Password": "opensearch-password"
      },
      "NewRelic": {
        "BaseUrl": "https://metric-api.newrelic.com",
        "LicenseKey": "new-relic-license-key"
      },
      "Webhook": {
        "Url": "https://loadstrike-gateway.example.com/ingest",
        "Secret": "gateway-secret",
        "Headers": { "X-Tenant": "payments" }
      },
      "Kafka": {
        "BootstrapServers": "broker-1.example.com:9092,broker-2.example.com:9092",
        "Topic": "loadstrike-runs"
      },
      "StatsD": {
        "Host": "statsd.example.com",
        "Port": 8125,
        "Prefix": "loadstrike"
      },
      "DogStatsD": {
        "Host": "dogstatsd.example.com",
        "Port": 8125,
        "Tags": { "service": "checkout" },
        "StaticTags": { "environment": "production-like" }
      },
      "Netdata": {
        "Host": "netdata.example.com",
        "Port": 8125
      },
      "Jsonl": {
        "FilePath": "./reports/loadstrike-events.jsonl"
      }
    }
  }
}

Callbacks and injected clients are supplied in code and are never read from infra config. Binding does not mutate caller-owned options; those options may be reused when the application treats them as immutable while runs are active.