Skip to content

Latest commit

 

History

History
251 lines (178 loc) · 9.1 KB

File metadata and controls

251 lines (178 loc) · 9.1 KB

Contributing

Getting vouched

Issues, bug reports and discussion are open to everyone. Pull requests are a little different: a maintainer has to vouch for you before we review your first one. Open a PR without being vouched and it stays open — a bot adds a needs-vouch label and a comment pointing you back here. Nothing gets closed, you just aren't in the review queue yet.

One at a time. Outside contributors can have one pull request open at once, or three once vouched. Open more than that and the newest is closed with a note asking you to finish the others first; reopen it once one of them lands. Drafts don't count towards the limit. This isn't about the quality of your work — a handful of parallel changes from one author is more than we can review properly, and in practice it means none of them get merged.

To get vouched, open an issue saying hello: who you are and what you want to work on. A maintainer replies, usually within a day or two. Use the same issue to ask which issue to pick up, or to check an approach before you write code.

Good places to start: the good first issue label, and Discord if the dev setup gives you trouble.

Why we do this: AI tools make it cheap to open a plausible-looking PR with no understanding behind it, and reviewing those crowds out the contributions we want to spend time on. Vouching is a short introduction, not a skill test. We use Vouch; the list is .github/VOUCHED.td.

Vouching someone (maintainers)

Comment on any issue or PR with the keyword first on the first line:

/vouch @username optional reason
/unvouch @username
/denounce @username optional reason

On a PR, a bare /vouch with no handle vouches that PR's author.

/denounce closes a PR outright and keeps closing that author's PRs from then on. Keep it for repeat spam and bad-faith behaviour; /unvouch quietly removes someone without blocking them.

Vouching also lifts someone's open-PR allowance from one to three, which is the only way to let a contributor run more than one at a time. Reopening a PR that was closed for hitting the cap won't work on its own — the check runs again on reopen and closes it again.

The bot opens a PR updating .github/VOUCHED.td. Nothing takes effect until you merge it. That PR needs an approval rather than a green CI run — GitHub does not run workflows on PRs the bot creates. Merge them one at a time; two open at once will conflict on the same sorted list.

Architecture Overview

architecture

Service Descriptions:

  • OpenTelemetry Collector (otel-collector): Receives OpenTelemetry data from instrumented applications and forwards it to ClickHouse for storage. Includes OpAMP supervisor that dynamically pulls configuration from HyperDX API.
  • ClickHouse (ch-server): ClickHouse database, stores all telemetry.
  • MongoDB (db): Stores user/saved search/alert/dashboard data.
  • HyperDX API (api): Node.js API, executes ClickHouse queries on behalf of the frontend and serves the frontend. serves the frontend. Can also run alert checker.
  • HyperDX UI (app): Next.js frontend, serves the UI.

Development

Pre-requisites:

  • Docker
  • Node.js (>=22)
  • Yarn (v4)

You can get started by deploying a complete development stack in dev mode.

yarn dev

This will start the Node.js API, Next.js frontend locally and the OpenTelemetry collector and ClickHouse server in Docker.

Each worktree automatically gets unique ports so multiple developers (or agents) can run yarn dev simultaneously without conflicts. A dev portal at http://localhost:9900 auto-starts and shows all running stacks with their assigned ports. Check the portal to find the URL for your instance.

To stop the stack:

yarn dev:down

To enable self-instrumentation and demo logs, you can set the HYPERDX_API_KEY to your ingestion key (visit the Team settings page after creating your account).

To do this, create a .env.local file in the root of the project and add the following:

HYPERDX_API_KEY=<YOUR_INGESTION_API_KEY_HERE>

Then restart the stack using yarn dev.

The core services are all hot-reloaded, so you can make changes to the code and see them reflected in real-time.

Volumes

The development stack mounts volumes locally for persisting storage under .volumes. Each worktree gets its own volume directory (e.g. .volumes/ch_data_dev_89). Clear the .volumes directory to reset ClickHouse and MongoDB storage.

Windows

If you are running WSL 2, Hot module reload on Nextjs (Frontend) does not work out of the box on windows when run natively on docker. The fix here is to open project directory in WSL and run the above docker compose commands directly in WSL. Note that the project directory should not be under /mnt/c/ directory. You can clone the git repo in /home/{username} for example.

To develop from WSL, follow instructions here.

Testing

All test environments use slot-based port isolation, so they can run simultaneously with the dev stack and across multiple worktrees.

E2E Tests

E2E tests run against a full local stack (MongoDB + ClickHouse + API). Docker must be running.

# Run all E2E tests
make e2e

# Run a specific spec file (dev mode: hot reload, containers kept running)
make dev-e2e FILE=search

# Run with grep pattern
make dev-e2e FILE=search GREP="filter"

# Run via script directly for more control
./scripts/test-e2e.sh --ui --last-failed

Tests live in packages/app/tests/e2e/. Page objects are in page-objects/, shared components in components/.

Integration Tests

# Build dependencies (run once before first test run)
make dev-int-build

# Run a specific test file
make dev-int FILE=checkAlerts

Unit Tests

To run unit tests or update snapshots, you can go to the package you want (ex. common-utils) to test and run:

yarn dev:unit

Mutation Tests

Coverage tells you a line ran; it doesn't tell you a test would fail if that line were wrong. Stryker edits the source in small ways (flips a comparison, empties a return) and reports which edits the test suite failed to catch. A surviving mutant is a missing assertion.

Set up in common-utils only for now. From packages/common-utils:

# The file you're working on — seconds to a couple of minutes
yarn dev:mutation --mutate src/filters.ts

# Everything you've changed off main
yarn dev:mutation --mutate "$(git diff --name-only --diff-filter=d --relative origin/main... -- 'src/**/*.ts' | grep -v __tests__ | paste -sd, -)"

# The whole package (slow — tens of minutes)
yarn dev:mutation

Scope it to what you're working on. Runs are roughly linear in mutants, and the whole package is ~365 files. Results are cached between runs, so a re-run after editing one file only re-tests that file.

Read the Survived entries: each one shows the edit that was made and the tests that ran anyway. NoCoverage means no unit test reaches that code at all — some of those are covered by integration tests, which this doesn't run. An HTML report lands in reports/mutation/.

The score is not a coverage number for the whole file. Module-level code — constants, regexes, lookup tables — isn't mutated at all (ignoreStatic, about 10% of the mutants here) and is left out of the denominator, so a high score says nothing about whether those are asserted on.

Not wired into CI. It's a tool for while you're writing tests, not a gate.

One wrinkle worth knowing about: the root package.json pins @stryker-mutator/core/minimatch to ^9. Our blanket brace-expansion resolution forces v2 (CJS) everywhere, and minimatch v10's ESM build needs brace-expansion v5's named exports, so Stryker crashes on startup without the pin. Drop it if that blanket resolution is ever narrowed.

AI-Assisted Development

HyperDX includes an MCP server that lets AI assistants query observability data, manage dashboards, and explore data sources. See MCP.md for setup instructions.

The repo also ships with configuration for AI coding assistants that enables interactive browser-based E2E test generation and debugging via the Playwright MCP server.

Claude Code

The project includes agents and skills for test generation, healing, and planning under .claude/. These are loaded automatically when you open the project in Claude Code. No additional setup required.

Cursor

A Playwright MCP server config is included at .cursor/mcp.json. To activate it:

  1. Open Cursor Settings → Tools & MCP
  2. The playwright-test server should appear automatically from the project config
  3. Enable it

This gives Cursor's AI access to a live browser for test exploration and debugging.

Additional support

If you need help getting started, join our Discord and we're more than happy to get you set up!