Thank you for your interest in contributing! observr is an open-source project and we welcome contributions of all kinds — bug reports, feature requests, documentation improvements, and code changes.
- Getting Started
- Development Setup
- Project Structure
- Pull Request Guidelines
- Coding Standards
- Running Tests
- Opening Issues
observr uses a two-branch workflow:
| Branch | Purpose |
|---|---|
develop |
Active development. All PRs target this branch. |
main |
Stable, released code only. Merged from develop by a maintainer at release time. |
Contributors never push directly to main.
- Fork the repository and clone your fork locally.
- Sync your fork's
developbranch with upstream before starting work. - Create a new branch from
developfor your work:git checkout develop git pull upstream develop git checkout -b feat/your-feature-name # or git checkout -b fix/issue-number-short-description - Make your changes, write tests, and verify everything passes.
- Open a Pull Request against the
developbranch.
| Tool | Version | Purpose |
|---|---|---|
| Go | ≥ 1.22 | Collector daemon (observrd) |
| Python | ≥ 3.10 | Python SDK |
| Node.js | ≥ 18 | Node.js/TypeScript SDK & dashboard |
| SQLite3 / gcc | system | CGO build for Go |
cd sdk/python
pip install -e ".[dev]" # installs observr in editable mode + test depscd sdk/node
npm install
npm run buildcd server
go mod tidy
go build ./...cd dashboard
npm install
npm run build # output goes to server/internal/dashboard/dist/observr/
├── server/ # Go collector daemon (observrd)
│ ├── cmd/observrd/main.go # Entry point + subcommands (query, tail)
│ └── internal/
│ ├── collector/ # POST /events handler
│ ├── storage/ # SQLite persistence
│ ├── query/ # GET /query handler + CLI
│ ├── tail/ # GET /tail SSE endpoint
│ └── dashboard/ # WebSocket hub + embedded React UI
├── sdk/
│ ├── python/ # Python SDK (pip install observr)
│ │ ├── observr/
│ │ │ ├── _client.py # ObservrClient, lazy import hook
│ │ │ ├── _transport.py # Background HTTP transport
│ │ │ ├── _logger.py # logging.Handler integration
│ │ │ ├── _span.py # Manual span context manager
│ │ │ └── integrations/ # Flask, FastAPI, Django patches
│ │ └── tests/
│ └── node/ # Node.js/TypeScript SDK (npm install @ydking0911/observr)
│ └── src/
│ ├── index.ts # Public API
│ ├── transport.ts # Background fetch transport
│ ├── span.ts # Manual span (async/await)
│ ├── logger.ts # console patch
│ └── integrations/
│ └── express.ts # Express middleware
├── dashboard/ # React + Vite frontend
├── scripts/ # install.sh, test_e2e.py
├── .github/workflows/ # CI + release + publish pipelines
└── Formula/ # Homebrew formula
- Target branch: all PRs must target
develop. PRs targetingmainwill be closed. - One thing per PR: one feature or one bug fix per pull request. If you have multiple changes, open multiple PRs.
- Link an issue: every PR should reference an existing issue (
Closes #123). If no issue exists, open one first. - Clear title and description:
- Title: short imperative summary (
Add Django middleware,Fix lazy instrumentation race) - Description: what changed, why, and how to test it.
- Title: short imperative summary (
- WIP label: if your PR is not ready for review, add the
WIPlabel and remove it when ready. - Keep it small: large PRs are hard to review. Prefer multiple focused PRs over one giant one.
- Tests required: all non-trivial changes must include tests. See Running Tests.
[ ] Targets develop branch (NOT main)
[ ] Branched from develop (not from main)
[ ] References an issue
[ ] Tests pass locally (Python, Go, Node.js)
[ ] Lint passes (ruff for Python, tsc --noEmit for TypeScript, go vet for Go)
[ ] No secrets or personal data committed
[ ] CHANGELOG or PR description updated
- Follow standard Go conventions (
gofmt,go vet). - All exported types and functions must have doc comments.
- Error handling: always check errors, never use
_for important errors. - Use
context.Contextfor cancellable operations.
- Target Python 3.10+.
- Run
ruff checkbefore committing. All lint errors must be resolved. - Type annotations required for all public functions.
- Zero mandatory dependencies for the SDK core — keep
dependencies = []inpyproject.toml. - Instrumentation patches must be idempotent (safe to call multiple times).
- Target Node.js 18+, ES2020.
- Run
tsc --noEmitbefore committing. - No
anytypes in public APIs. - Transport must be non-blocking and never throw (silent drop on failure).
# Python SDK
cd sdk/python && python -m pytest tests/ -v
# Node.js SDK
cd sdk/node && npm test
# Go server
cd server && go test ./... -race -timeout 60s
# Lint
cd sdk/python && ruff check observr/ tests/
cd sdk/node && npx tsc --noEmit
cd server && go vet ./...cd server && go build -o bin/observrd ./cmd/observrd
python scripts/test_e2e.pyWhen opening a bug report, please include:
- observr version (
pip show observr/observrd --version) - OS and Python/Node/Go version
- Minimal reproduction steps
- Expected vs. actual behaviour
- Relevant logs (with sensitive data redacted)
For feature requests, describe the use-case and why existing functionality doesn't cover it.
Open a GitHub Discussion or an issue — we're happy to help you get started.