Skip to content

Add workflow load testing framework with multi-language starter packages#293

Draft
THardy98 wants to merge 11 commits intomainfrom
pr/workflow-load-testing-clean
Draft

Add workflow load testing framework with multi-language starter packages#293
THardy98 wants to merge 11 commits intomainfrom
pr/workflow-load-testing-clean

Conversation

@THardy98
Copy link
Contributor

@THardy98 THardy98 commented Feb 24, 2026

Summary

Adds a workflow load testing framework that builds and runs test projects across Go, Python, and TypeScript. This enables benchmarking Temporal SDK worker performance (CPU, memory, latency, throughput) under controlled load with metrics export to Parquet.

New CLI commands

  • omes workflow — Build a test project, spawn client/worker processes, run load, and export metrics
  • omes exec — Build and run a test project as a managed subprocess (with signal forwarding and graceful shutdown)

Starter packages (workflowtests/)

Each language gets a shared "starter" library that handles CLI parsing, HTTP server setup, connection pooling, and Prometheus integration — so test authors write normal Temporal SDK code:

  • Go (workflowtests/go/starter/) — starter.Run(clientFn, workerFn) with ClientPool for connection reuse
  • Python (workflowtests/python/omes_starter/) — run(client=..., worker=...) with async ClientPool
  • TypeScript (workflowtests/typescript/src/) — run({ client, worker }) with Express HTTP server and ClientPool

Each includes a simple-test example project.

Metrics collection and export

  • Cross-platform process metrics collector (CPU/memory via gopsutil, aggregates root + child processes)
  • Prometheus query pipeline with configurable PromQL query sets
  • Curated query presets for worker gauges, latency histograms (p50/p99), and throughput
  • Parquet export with Zstd compression and batched writes

IMPORTANT NOTE: this is largely similar to what prometheus.go offers today, but written more nicely, and not dependent on a locally spun up PrometheusInstance. The idea is to get this merged than rip out that code (for instance, we do not need a PrometheusInstance or any of its accompanying flags). This should reduce the flag sprawl.

Docker support

  • Per-language Dockerfiles and a thin project overlay Dockerfile
  • Docker Compose config for Temporal dev server + UI + Prometheus + workers
  • Prometheus scrape configs for both Docker and host-native setups (i.e. if you prefer to run the worker natively than on docker)

Program building (internal/programbuild/)

  • Builds test projects via sdkbuild with SDK version auto-detection and local SDK path support
  • Language-specific runtime arg construction and subprocess lifecycle management

NOTE: the Typescript build is a bit janky, but works for now. I plan to improve this when the need arises.

Reviewer guide

FWIW - this is a purely additive change, non-breaking and Omes currently doesn't have much public usage

This is a large PR (~10k lines). Here's how to approach it:

  1. Start with the CLI commandscmd/cli/workflow.go and cmd/cli/exec.go are the entry points that wire everything together. They show the overall flow: build → spawn → load → export.

  2. Core infrastructure (most important to review carefully):

    • internal/programbuild/ — How programs are built and run per language
    • metrics/export_pipeline.go — Prometheus query → Parquet export pipeline (essentially a better package for prom querying and export than what exists in prometheus.go
    • metrics/query_presets.go — Curated PromQL queries (these basically replicate what already exists in prometheus.go, with the only exception being that we offer raw and smoothed CPU (this was necessary because some worker CPU profiles oscillate a lot (TS) and thereby make it very difficult to signal anything)
    • metrics/metrics.go (the processCollector addition) — Cross-platform CPU/memory collection
    • loadgen/http_executor.go — HTTP-based load executor
    • internal/utils/net.go — Port allocation and readiness polling
  3. Starter packages — Each language follows basically same pattern:

    • workflowtests/go/starter/workflowtests/python/omes_starter/workflowtests/typescript/src/

Note: Go is slightly different here because we have to wire up metrics ourselves. The implementation is largely the same as what exists in clioptions/metrics.go but we have to put it here for the Go project to be standalone.

  1. Docker/configworkflowtests/dockerfiles/, the README.md there explains the setup.

Test plan

I've been using this locally to run load tests.

  • Manual smoke test: omes workflow --language typescript --project-dir workflowtests/typescript/tests/simple-test --spawn-worker --duration 3m runs successfully
  • [x ] Manual smoke test with Go and Python test projects

🤖 Generated with Claude Code

@THardy98 THardy98 requested review from a team as code owners February 24, 2026 17:12
THardy98 and others added 11 commits February 24, 2026 15:40
…ross go/python/typescript

- align Go/Python/TypeScript starter execution model and simplify client starter semantics\n- remove monitor-era execute traceback and metadata-heavy /info payloads (readiness-only /info)\n- add optional keyed ClientPool helpers across Go/Python/TypeScript\n- wire worker Prometheus metrics via --prom-listen-address in starter runtimes\n- refresh workflowtests docs/snippets for native-first usage and optional pooling\n- keep runner protocol focused on /execute + readiness checks
- Simplify build.go comments to focus on what/why instead of sdkbuild internals
- Delete internal/promconfig/ (unused dynamic config generator, superseded by
  static YAML files)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@THardy98 THardy98 force-pushed the pr/workflow-load-testing-clean branch from 0cd77ab to b59d7e1 Compare February 24, 2026 23:41
@THardy98 THardy98 marked this pull request as draft February 27, 2026 19:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant