OpenTelemetry Demo Telemetry Generator avatar

OpenTelemetry Demo Telemetry Generator

Pricing

$20.00 / 1,000 telemetry minute delivereds

Go to Apify Store
OpenTelemetry Demo Telemetry Generator

OpenTelemetry Demo Telemetry Generator

Generate realistic, correlated OpenTelemetry traces, metrics and logs for demos, POCs and trainings. Scripted incident scenarios streamed over OTLP to any observability backend.

Pricing

$20.00 / 1,000 telemetry minute delivereds

Rating

0.0

(0)

Developer

Justin Hagerty

Justin Hagerty

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

12 days ago

Last modified

Share

Realistic, correlated OpenTelemetry traces, metrics and logs for a whole microservice system — with a scripted incident, a clear root cause and a recovery — streamed over OTLP/HTTP to the observability backend you want to show off.

Great observability demos need great data. A real demo app (Kubernetes cluster, ten services, a load generator, a way to break things on cue) takes days to set up, costs money to keep running, and never fails at the moment you need it to. Dashboards built on an empty sandbox look sad, and "imagine this chart had data" doesn't close deals.

This Actor simulates an entire microservice system — storefront, API gateway, checkout, payments, databases, caches, Kafka, third-party APIs — and plays a scenario: a healthy baseline, then (optionally) an incident such as a slow payment provider, a bad deployment, a missing database index or a memory leak, followed by recovery. Everything is generated with current OpenTelemetry semantic conventions and is correlated: logs carry trace_id/span_id, metrics and traces share resources, the incident shows up consistently in all three signals. You get a demo guide with the exact UTC timeline and the clicks to make.

Nothing to deploy. Point it at an OTLP endpoint, pick a scenario, start.


Who it's for

  • Sales engineers and solution architects running live demos and POCs of an observability platform.
  • Observability vendors' partners and consultants who need a repeatable, prospect-branded demo environment (companyName, serviceNamespace).
  • Trainers and workshop hosts teaching distributed tracing, RED metrics, SLOs or incident response — every attendee sees the same incident at the same time (seed).
  • Platform teams building dashboards, alerts and SLOs before real services are instrumented, or smoke-testing a telemetry pipeline (Collector → backend) with realistic, non-sensitive data.

What you get

  • Correlated traces, metrics and logs from 7–10 services in Java, Go, Python, Node.js and .NET, with databases, Redis, Kafka/RabbitMQ, Elasticsearch and third-party APIs.
  • 9 scripted scenarios with talk tracks: latency incident, bad deployment and rollback, slow queries, memory leak with OOMKilled restarts, cache stampede, third-party outage with circuit breaker, traffic surge with autoscaling, credential stuffing — plus a healthy baseline.
  • 4 industries: e-commerce, fintech, B2B SaaS and logistics, each with its own service graph and business attributes.
  • 11 backend presets: generic OTLP, your own Collector, Honeycomb, Grafana Cloud, New Relic, Elastic, Dynatrace, SigNoz, Jaeger, Uptrace, Axiom.
  • Two modes: live (real time, data every ~15 s — for the demo itself) and backfill (the last N minutes, sent in seconds — to prefill dashboards before the meeting).
  • A demo guide (DEMO_GUIDE.md) with the UTC timeline of every phase, the walkthrough in order, talk-track bullets and suggested queries for your backend.
  • Delivery-health report: every run checks your destination configuration before sending and reports authentication failures, wrong paths, throttling, partial rejections and more — with a score you can gate CI on.
  • Free dry runs that store sample OTLP/JSON payloads and volume estimates without sending anything.
  • Deterministic: the same seed reproduces the same telemetry, byte for byte.

Scenario catalog

The incident starts at incidentStartMinute (default 5) and lasts incidentDurationMinutes (default 8), including onset and recovery. incidentSeverity (low / medium / high) scales the effects. Service names below are for the e-commerce flavor; other industries map the same roles to their own services.

Scenario (scenario)What happensWhat the demo showsTalk track in one line
healthy-baselineSteady traffic with gentle sinusoidal variation, ~0.5% errorsService map, RED metrics, SLO building, trace ↔ log pivots"Everything instrumented, everything correlated — this is your baseline."
checkout-latency-incident (default)External payment-provider gets ~10x slower: timeouts, retries, ERROR logs; then recoversAlert → service map → slow traces → the long CLIENT span to the third party → correlated logs → recovery"From symptom to root cause in four clicks, without leaving the tool."
bad-deployment-rollbackcart 2.4.1 → 2.5.0 rolls out (service.version flips), errors and latency regress, rollbackDeployment markers, compare by service.version, exceptions with stack traces"Know which deploy broke production — and prove the rollback fixed it."
database-slow-queriesA migration drops an index: one query becomes 20–50x slower, the connection pool saturates, upstream latency risesdb.client.operation.duration by collection, db.query.text on slow spans, pool saturation metrics"Many endpoints slow at once? Look for the shared resource."
memory-leak-oomrecommendation (JVM) heap grows linearly, GC pauses rise, OOMKilled restarts with error bursts, hotfixSaw-tooth jvm.memory.used, k8s.container.restarts, new service.instance.id per restart, GC pauses"Metrics, logs and traces on one timeline tell the whole OOM story."
cache-stampedeRedis is flushed: hit ratio collapses, the database is hammered, then the cache warms upapp.cache.hits/misses, DB load spike, traces with cache miss → SELECT"A thundering herd, caught in the act."
third-party-outageshipping-carrier returns 503s, the circuit breaker opens, fallbacks are served, then it recoversErrors isolated to one server.address, app.circuit_breaker.state, fallback spans, low user-facing error rate"Resilience patterns working — and visible."
traffic-surgeFlash sale: 4–5x traffic, the autoscaler adds pods, Kafka consumer lag climbs then drainsThroughput, new service.instance.ids, CPU per pod, kafka.consumer_group.lag"Capacity planning with real numbers."
security-anomalyCredential stuffing: hundreds of 401s on the login route from a few IPs (documentation ranges), then rate limiting (429)Status codes by route, group by client.address, WARN logs for forensics"Observability data is security data too."

Industries (topologies)

industryServicesInfrastructure & third partiesBusiness attributes
ecommerce (default)frontend (Node.js), api-gateway (Go), product-catalog (Java), cart (.NET), checkout (Java), payment (Go), inventory (Go), shipping (Python), recommendation (Java), email-worker (Python)PostgreSQL ×3, Redis, Kafka; payment provider, shipping carrier, email deliveryapp.customer.tier, app.region, app.cart.items, app.order.value_usd, feature flag
fintechweb-app, api-gateway, accounts, transactions, ledger, fraud-scoring, kyc, notifications-workerPostgreSQL, Redis, Kafka; card network, KYC provider, notification providertier, region, transfer value, feature flag
saasweb-app, api-gateway, auth, projects, search, billing, webhooks-workerPostgreSQL, Redis, RabbitMQ, Elasticsearch; payments API, email provider, webhook deliverytier, region, subscription value, feature flag
logisticsportal, api-gateway, orders, routing, fleet-tracking, warehouse, notificationsPostgreSQL, Redis, Kafka; carrier API, maps API, notification providertier, region, order value, feature flag

All service and dependency names are generic (third-party hosts use the reserved .example domain). Each run's data.services lists the services with language, version and replica count.

Supported backends

Presets fill in the default endpoint and signal paths, check the headers the vendor expects, and pick a protocol/temporality the vendor accepts. Endpoints and header names change — confirm them in your vendor's OTLP documentation. The Actor never ships credentials; you provide them in headers (stored as a secret).

vendorPresetEndpoint (otlpEndpoint)Authentication header(s)Notes
generic-otlpyour base URL, e.g. https://otlp.example.comwhatever your backend needs/v1/traces, /v1/metrics, /v1/logs are appended
otel-collectore.g. https://collector.example.com:4318only if your receiver uses an authenticatorOTLP/HTTP is port 4318 (4317 is gRPC, not supported). Must be reachable from the internet
honeycombdefault https://api.honeycomb.io (EU: https://api.eu1.honeycomb.io)x-honeycomb-team: <ingest key>; optional x-honeycomb-datasetdataset header is needed for metrics
grafana-cloudyour stack's OTLP gateway, e.g. https://otlp-gateway-prod-us-east-0.grafana.net/otlpBasic auth: instance ID + access-policy token → use basicAuthUser / basicAuthPasswordtraces → Tempo, metrics → Mimir, logs → Loki
new-relicdefault https://otlp.nr-data.net (EU: https://otlp.eu01.nr-data.net)api-key: <license key>protobuf only (JSON is switched automatically)
elasticyour APM / managed OTLP endpointAuthorization: ApiKey <key> (or Bearer <secret token>)protobuf
dynatracehttps://{environment-id}.live.dynatrace.com/api/v2/otlpAuthorization: Api-Token <token> (trace, metric and log ingest scopes)protobuf only; delta metrics (selected automatically)
signozdefault https://ingest.us.signoz.cloud:443 (also eu, in)signoz-ingestion-key: <key>self-hosted: use otel-collector
jaegeryour Jaeger OTLP/HTTP receiver, e.g. https://jaeger.example.com:4318usually nonetraces only (metrics and logs disabled automatically)
uptracedefault https://api.uptrace.devuptrace-dsn: <project DSN>self-hosted: set otlpEndpoint
axiomdefault https://api.axiom.coAuthorization: Bearer <token>, X-Axiom-Dataset: <dataset>check metrics support for your dataset type

Only public endpoints can be reached: the Actor runs in the cloud and refuses private, loopback and link-local addresses (SSRF protection). Allowed ports: 80, 443, 4318, 8080, 8443.

Quick start

1. Preview for free (dry run)

The input form is prefilled with a dry run: click Start. Nothing is sent and nothing is charged. You get:

  • DEMO_GUIDE.md — the presenter guide for the scenario;
  • SAMPLE_TRACES.json, SAMPLE_METRICS.json, SAMPLE_LOGS.json — one minute of OTLP/JSON payloads from the incident peak (first 25 traces with their logs, plus the full metrics snapshot);
  • a dataset item with per-minute volumes, estimated totals and payload sizes for the whole run.

2. Honeycomb

{
"vendorPreset": "honeycomb",
"headers": "x-honeycomb-team: <your ingest key>\nx-honeycomb-dataset: demo-metrics",
"confirmAuthorization": true,
"scenario": "checkout-latency-incident",
"mode": "live",
"durationMinutes": 20,
"incidentStartMinute": 8
}

Start it ~5 minutes before the demo; the guide tells you exactly when the incident begins.

3. Grafana Cloud

{
"vendorPreset": "grafana-cloud",
"otlpEndpoint": "https://otlp-gateway-prod-us-east-0.grafana.net/otlp",
"basicAuthUser": "<instance ID>",
"basicAuthPassword": "<access policy token>",
"confirmAuthorization": true,
"scenario": "database-slow-queries",
"mode": "backfill",
"durationMinutes": 30
}

Copy the endpoint and instance ID from your stack's OpenTelemetry tile. basicAuthPassword is a secret field.

4. New Relic

{
"vendorPreset": "new-relic",
"headers": "api-key: <license key>",
"confirmAuthorization": true,
"scenario": "bad-deployment-rollback",
"industry": "fintech"
}

EU accounts: add "otlpEndpoint": "https://otlp.eu01.nr-data.net".

5. Your own OpenTelemetry Collector

{
"vendorPreset": "otel-collector",
"otlpEndpoint": "https://collector.example.com:4318",
"headers": "Authorization: Bearer <token>",
"confirmAuthorization": true,
"scenario": "traffic-surge"
}

A minimal receiver for it (put TLS and an authenticator in front of anything public):

extensions:
bearertokenauth:
token: ${env:DEMO_INGEST_TOKEN}
receivers:
otlp:
protocols:
http:
endpoint: 0.0.0.0:4318
auth:
authenticator: bearertokenauth

The Collector then fans the data out to any backend — a good way to demo several tools side by side.

Modes and timing

live (default)backfill
Timestampsfrom "now" forward, minute by minutethe last durationMinutes, ending at the start of the current minute
Sendingpaced in real time: spans and logs every ~15 s, metrics every 60 s (the SDK default export interval)as fast as the backend accepts
Run time≈ durationMinutes (+ up to ~30 s)seconds to a few minutes
Best forthe live demo itself; workshopsprefilling dashboards before a meeting; building and testing alerts

Run timeout: a live run lasts as long as durationMinutes (up to 120). Make sure the run's timeout (Run options → Timeout) is longer than that; the default run options are set to more than 2 hours. Backfills are quick.

Some backends reject metric points that are too old; the Actor flags long backfills for those vendors (OTD-CFG-008).

Input reference

FieldTypeDefaultDescription
dryRunbooleanfalse (prefilled true)Generate but don't send; store samples, guide and estimates. Free.
vendorPresetenumgeneric-otlpBackend preset (see table above).
otlpEndpointstringpreset defaultOTLP/HTTP base URL. Required for presets without a default. https:// recommended.
headerssecret text—One header per line, Name: value (a JSON object also works). Never written to output or logs.
basicAuthUser / basicAuthPasswordstring / secret—Builds Authorization: Basic … (Grafana Cloud).
protocolhttp/protobuf | http/jsonhttp/protobufOTLP/HTTP encoding. JSON uses hex trace/span IDs per the OTLP spec.
compressiongzip | nonegzipRequest compression.
confirmAuthorizationbooleanfalseRequired (true) when sending: you own or are authorized to use the endpoint.
scenarioenumcheckout-latency-incidentSee the scenario catalog.
industryecommerce | fintech | saas | logisticsecommerceSystem topology.
incidentStartMinuteinteger5 (fitted for runs < 15 min)When the incident begins.
incidentDurationMinutesinteger8 (fitted for runs < 15 min)Incident length incl. onset and recovery. Start + duration must be ≤ durationMinutes.
incidentSeveritylow | medium | highmediumScales the effects.
modelive | backfillliveSee Modes and timing.
durationMinutesinteger 1–12015Simulated minutes.
trafficLevellow | medium | highmedium≈ 30 / 120 / 600 request traces per minute (hard cap 1,500/min during surges).
signalsarray of traces, metrics, logsallSignals to send.
seedintegerrandomReproducible telemetry; the seed used is reported in data.seed.
environmentstringdemodeployment.environment.name.
serviceNamespacestringindustry nameservice.namespace and k8s.namespace.name.
companyNamestring—Adds app.company and shows in the guide.
extraResourceAttributesobject—Up to 20 extra resource attributes.
maxBatchSizeinteger 100–10,0002,000Max items per request (requests also stay under ~3 MB).
metricsTemporalityauto | cumulative | deltaautoPer-vendor default (delta for Dynatrace).
failOnSeveritynone … lownoneCI gate on delivery health, e.g. critical fails the run when the key is rejected.
disabledRulesarray—Rule IDs to skip (Pro plan and above).
licenseKeysecret—Enterprise / prepaid keys.

Invalid input stops the run before anything is sent, with a message saying what to fix (e.g. an incident that doesn't fit in the run, a missing endpoint, or a missing authorization confirmation).

Output

Dataset (one item per run)

The standard report shared by all our Actors; score is the delivery-health score (100 = everything delivered, no configuration problems). Example (shortened) for a 15-minute Honeycomb backfill:

{
"product": "otel-demo-generator",
"product_version": "0.1.0",
"target": "https://api.honeycomb.io",
"status": "ok",
"score": 98,
"risk_level": "low",
"summary": { "critical": 0, "high": 0, "medium": 0, "low": 1, "info": 0 },
"findings": [
{
"rule_id": "OTD-CFG-010",
"title": "Recommended vendor header missing",
"severity": "low",
"kind": "configuration",
"location": "headers.x-honeycomb-dataset",
"evidence": { "preset": "honeycomb", "missing": "x-honeycomb-dataset" },
"recommendation": "Add the header in 'headers'. Confirm its meaning in the vendor's OTLP documentation."
}
],
"data": {
"mode": "backfill",
"dry_run": false,
"scenario": "checkout-latency-incident",
"scenario_title": "Checkout latency incident (slow third-party API)",
"industry": "ecommerce",
"vendor_preset": "honeycomb",
"protocol": "http/protobuf",
"endpoint": "https://api.honeycomb.io",
"header_names": ["x-honeycomb-team"],
"seed": 42,
"duration_minutes": 15,
"minutes_delivered": 15,
"time_range": { "start": "2026-10-03T03:45:00Z", "end": "2026-10-03T04:00:00Z" },
"timeline": [
{ "phase": "baseline", "start": "2026-10-03 03:45:00 UTC", "end": "2026-10-03 03:50:00 UTC", "incident": false,
"description": "Normal traffic and healthy dependencies." },
{ "phase": "degradation", "start": "2026-10-03 03:50:00 UTC", "end": "2026-10-03 03:52:00 UTC", "incident": true,
"description": "payment-provider starts responding slowly; checkout p99 climbs." }
],
"services": [{ "name": "frontend", "language": "nodejs", "version": "3.12.0", "replicas": 3, "operations": 6 }],
"counts": {
"traces": { "generated": 2167, "sent": 2167, "accepted": 2167, "rejected": 0 },
"spans": { "generated": 20538, "sent": 20538, "accepted": 20538, "rejected": 0, "failed": 0 },
"metric_data_points": { "generated": 4693, "sent": 4693, "accepted": 4693, "rejected": 0, "failed": 0 },
"log_records": { "generated": 2252, "sent": 2252, "accepted": 2252, "rejected": 0, "failed": 0 }
},
"http_status_counts": { "200": 45 },
"delivery": { "traces": { "requests": 15, "bytes": 1089311, "retries": 0, "disabled": null } },
"demo_guide_key": "DEMO_GUIDE.md",
"stopped_early": null,
"notes": []
},
"errors": [],
"disclaimer": "Synthetic telemetry for demos, trainings and testing. It contains no real user data. ..."
}

counts.traces.accepted is derived from span acceptance (spans of one trace can travel in different requests). endpoint and target never include credentials or query strings; header_names lists names only, never values. Dry runs add data.dry_run_preview (sample minute, per-minute averages, estimated totals and payload bytes).

Dataset views in Console: Overview (scenario, backend, minutes delivered, counts, score), Scenario timeline and Delivery findings.

Key-value store

RecordContent
DEMO_GUIDE.mdPresenter guide (every run, including dry runs)
SAMPLE_TRACES.json, SAMPLE_METRICS.json, SAMPLE_LOGS.jsonOTLP/JSON samples (dry runs only)
OUTPUTRun summary: plan, score, billing
REPORT.md / REPORT.sarifDelivery-health report (SARIF on plans that include it)

Demo guide excerpt

# Demo guide — Checkout latency incident (slow third-party API)
| Phase | Start (UTC) | End (UTC) | What happens |
|---|---|---|---|
| baseline | 03:45 | 03:50 | Normal traffic and healthy dependencies. |
| degradation | 03:50 | 03:52 | payment-provider starts responding slowly; checkout p99 climbs. |
| incident | 03:52 | 03:56 | payment-provider latency is ~10x baseline: timeouts and retries; ... |
| recovery | 03:56 | 03:58 | payment-provider recovers; latency drains back to normal. |
## Walkthrough (in this order)
1. Open the alert / SLO view: checkout error budget burning since the degradation phase.
2. Open the service map: checkout and upstream api-gateway/frontend show elevated latency and errors.
3. Chart p99 of http.server.request.duration for checkout: compare baseline vs incident.
4. Filter traces: service.name = checkout AND duration > 2s. Open one.
5. In the waterfall, the CLIENT span to payment-provider (server.address) takes seconds and is retried.
6. Click through to correlated logs (same trace_id): timeout ERRORs with exception.type.
### Honeycomb
- **Latency of the focus service:** `VISUALIZE HEATMAP(duration_ms), P99(duration_ms) WHERE service.name = checkout GROUP BY name`

The guide also contains the root cause (for the presenter), talk-track bullets, generic queries that work anywhere, metrics to chart, and vendor-specific queries for Honeycomb, Grafana Cloud (TraceQL, PromQL, LogQL), New Relic (NRQL), Elastic (KQL) and Jaeger. Verify query syntax against your backend version: attribute mapping can differ by ingestion settings.

Telemetry details

Traces. Root SERVER spans at the edge service with client.address, user_agent.original and business attributes; CLIENT/SERVER pairs for HTTP (http.request.method, http.route, url.path, url.full, http.response.status_code, server.address) and gRPC (rpc.system, rpc.service, rpc.method, rpc.grpc.status_code); database CLIENT spans (db.system.name + legacy db.system, db.namespace, db.operation.name, db.collection.name, parameterized db.query.text — no literals, no PII); Redis spans with app.cache.hit; Kafka/RabbitMQ PRODUCER spans and CONSUMER spans in a new trace linked to the producer; INTERNAL spans for business logic and circuit breakers. Failures set span status ERROR, error.type and an exception event with exception.type, exception.message and a language-appropriate exception.stacktrace. Retries carry http.request.resend_count.

Metrics (cumulative by default, 60 s interval, consistent start times; delta for delta-only backends): http.server.request.duration and http.client.request.duration (histograms with the semantic-convention buckets), rpc.server.duration, rpc.client.duration, db.client.operation.duration, db.client.connection.count / .max / .pending_requests, messaging.client.sent.messages, messaging.client.consumed.messages, messaging.process.duration, kafka.consumer_group.lag or rabbitmq.message.current, process.cpu.utilization, process.memory.usage, jvm.memory.used, jvm.memory.limit, jvm.gc.duration, k8s.container.restarts, app.cache.hits, app.cache.misses, app.circuit_breaker.state, app.business.transactions.

Logs. Access logs at the edge, business events, WARN/ERROR logs for retries, timeouts, failed logins, rate limits, slow queries and fallbacks — all with trace_id/span_id — plus lifecycle and scenario events (deployments, rollbacks, autoscaling, OOMKilled, circuit breaker state changes) tagged with event.name.

Resources. service.name, service.namespace, service.version, service.instance.id, deployment.environment.name (and legacy deployment.environment), telemetry.sdk.*, process.runtime.*, k8s.cluster/namespace/deployment/pod/container/node.*, host.name, cloud.provider/platform/region/availability_zone, app.company (optional), your extra attributes, and app.synthetic = true on every resource so synthetic data is always easy to filter out or delete.

Cardinality budget. Attribute values are bounded: route templates instead of raw paths on metrics, no user IDs, a handful of pods per service (autoscaling adds a few), three customer tiers, four regions. A 15-minute medium run produces roughly 300 metric data points per minute — comfortably small for any backend.

Delivery health and rules

Before sending, the Actor checks the destination configuration (OTD-CFG-*, kind configuration); while sending, it records what the backend answered (OTD-DLV-*, kind runtime). Examples: credentials over plain HTTP, a missing vendor header, JSON for a protobuf-only vendor, the gRPC port 4317, rejected credentials (critical), wrong path (404), partial-success rejections, throttling (429), server errors, payload too large (413), timeouts. A clean run has no findings and a score of 100. The full catalog — 22 rules with recommendations — is in RULES.md.

How sending works: requests are batched (≤ maxBatchSize items, ≤ ~3 MB), gzip-compressed, and retried with exponential backoff and jitter on 429/502/503/504 and network errors, honouring Retry-After (capped at 30 s). 400/401/403/404/413/415 are not retried; a 413 batch is split and resent. On 401/403/404 the Actor stops sending that signal immediately instead of hammering your endpoint. partial_success responses are parsed (protobuf and JSON) and counted as rejected.

API and automation

Run and get the report (curl)

jq -n --arg key "$HONEYCOMB_KEY" '{
vendorPreset: "honeycomb",
headers: ("x-honeycomb-team: " + $key),
confirmAuthorization: true,
scenario: "cache-stampede",
mode: "backfill",
durationMinutes: 30,
seed: 2026
}' | curl -s -X POST -H "Content-Type: application/json" -d @- \
"https://api.apify.com/v2/acts/michiganpublictech~otel-demo-generator/run-sync-get-dataset-items?token=$APIFY_TOKEN" |
jq '.[0] | {score, minutes: .data.minutes_delivered, counts: .data.counts}'

(run-sync-* endpoints wait up to 300 s — use them for backfills; start live runs asynchronously with /runs.)

Python (apify-client)

import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("michiganpublictech/otel-demo-generator").call(
run_input={
"vendorPreset": "new-relic",
"headers": f"api-key: {os.environ['NEW_RELIC_LICENSE_KEY']}",
"confirmAuthorization": True,
"scenario": "memory-leak-oom",
"industry": "saas",
"mode": "backfill",
"durationMinutes": 45,
"incidentStartMinute": 15,
"incidentDurationMinutes": 20,
},
timeout_secs=900,
)
item = next(client.dataset(run["defaultDatasetId"]).iterate_items())
print(item["score"], item["data"]["minutes_delivered"], item["data"]["http_status_counts"])
guide = client.key_value_store(run["defaultKeyValueStoreId"]).get_record("DEMO_GUIDE.md")["value"]
print(guide)

Keep a demo environment fresh every day

  1. In Apify Console, create a Task for this Actor with your backend settings, mode: "backfill", durationMinutes: 120 and scenario: "healthy-baseline" (or rotate scenarios with several tasks).
  2. Create a Schedule (e.g. cron 0 7 * * 1-5, your timezone) that runs the task.
  3. Set failOnSeverity: "critical" and a run-failure notification, so you learn about an expired API key before the demo, not during it.

Two hours of baseline at medium traffic costs 120 × $0.02 = $2.40 per refresh.

Pricing

Pay-per-event: you pay only for minutes your backend accepted. Apify platform usage is included.

EventPriceWhen it is charged
telemetry-minute$0.02Once per simulated minute of telemetry that was delivered (at least one export request for that minute was accepted)
  • Dry runs are free. So are minutes that could not be delivered (rejected credentials, unreachable endpoint…).
  • If authentication fails on the first minute, the run stops immediately and nothing is charged.
  • Apify's maximum cost per run (spending cap in the run options) is respected: the Actor checks the remaining budget before generating each minute and stops cleanly when it's reached (noted in data.stopped_early).

Examples:

UsageMinutesCost
15-minute live demo15$0.30
1-hour workshop60$1.20
Maximum run (2 hours)120$2.40
Daily 2-hour backfill, 22 workdays2,640$52.80 / month

The price doesn't depend on trafficLevel — but your backend's ingest bill does (see Responsible use).

Plans and licensing

Apify Store users get everything on pay-per-event, including SARIF export and the CI gate. License keys (licenseKey) unlock more: Pro adds disabling rules (disabledRules), Enterprise adds white-label reports, and prepaid/invoiced keys skip pay-per-event charges. Missing features never fail a run: they're skipped with a note. See ../../docs/licensing.md.

Responsible use

  • Only send to endpoints you own or are authorized to use. The Actor requires confirmAuthorization: true and never sends anything in dry runs. Don't send demo data to production tenants without the owner's consent.
  • The data is synthetic. No real users, customers or credentials; IP addresses come from the documentation ranges (192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24); hostnames use .example. Every resource carries app.synthetic = true.
  • Ingest costs are on the backend side. Approximate volume per simulated minute (e-commerce, healthy baseline; incidents add a little, traffic-surge up to ~4.5x):
trafficLevelTraces / min (incl. async)Spans / minLog records / minMetric points / minProtobuf / mingzip on the wire / min1 hour (spans, uncompressed)
low~37~360~37~270~240 KB~37 KB~22k spans, ~14 MB
medium~145~1,400~150~290~620 KB~95 KB~84k spans, ~37 MB
high~720~6,900~720~310~2.5 MB~360 KB~410k spans, ~150 MB

A dry run reports exact per-minute numbers and an estimated total for your settings.

Limitations

  • OTLP/HTTP only (protobuf or JSON). OTLP/gRPC (port 4317) isn't supported.
  • Public endpoints only. Private, loopback and internal addresses are blocked on purpose; expose your Collector behind TLS + auth, or use a tunnel.
  • Simulated, not instrumented. The service graph, latencies and failure modes are modeled to look realistic; they're not captured from running software. Profiles, browser RUM and exemplars aren't generated.
  • One metric export per minute. Metrics have 60-second resolution (like the SDK default); spans and logs arrive every ~15 s in live mode.
  • Backfill is limited to 120 minutes, and some backends reject old metric points (flagged per vendor).
  • Presets reflect the vendors' public docs at the time of release. Confirm endpoints, header names and limits in your vendor's documentation; use generic-otlp for anything else.
  • Live runs occupy the run for the whole duration. Set the run timeout longer than durationMinutes.

FAQ

Will the data look real in my backend's service map? Yes. Every call is a CLIENT span in the caller and a SERVER span in the callee with matching server.address, so service maps and dependency graphs build automatically. Databases, caches, brokers and third-party APIs appear as dependencies.

Can I show the same incident twice? Yes — reuse the seed. Timestamps move with the run's start time, everything else (IDs, values, which requests fail) is identical.

How do I hide or delete the demo data afterwards? Filter on app.synthetic = true, deployment.environment.name or service.namespace. Use a dedicated dataset / environment / tenant for demos where your backend supports it.

Why does my Honeycomb run report "Recommended vendor header missing"? Metrics need a dataset (x-honeycomb-dataset). Add it, or disable metrics in signals.

The run failed with "Backend rejected the credentials". Was I charged? No. Minutes are charged only when the backend accepted data, and the Actor stops at the first authentication failure.

Can I send to two backends at once? Send to your own OpenTelemetry Collector and fan out from there, or start two runs with the same seed.

Is JSON or protobuf better? Protobuf: smaller, supported everywhere. JSON is useful to inspect payloads or for receivers that only accept JSON.

Does it work with Datadog / Splunk / others? Use generic-otlp with the vendor's OTLP/HTTP intake URL and headers, or route through your Collector. More presets are on the roadmap.

Roadmap

  • More presets (Datadog OTLP intake, Splunk Observability, Google Cloud, AWS, Azure Monitor, Logz.io, Coralogix, Lightstep/ServiceNow).
  • Custom scenarios: compose effects and phases in the input.
  • More industries (gaming, healthcare, media streaming) and bring-your-own topology (YAML).
  • Exemplars on histograms, span metrics, browser/RUM and profiling signals.
  • OTLP/gRPC support.
  • Multiple concurrent incidents and "noisy neighbour" background anomalies for AIOps demos.

Changelog

See CHANGELOG.md.