Contributing Guide¶
Thank you for your interest in contributing to the Gunicorn Prometheus Exporter! This guide will help you get started with development, testing, and documentation.
π Project Structure¶
Core Modules¶
src/gunicorn_prometheus_exporter/plugin.py
: Worker classes and PrometheusMixinsrc/gunicorn_prometheus_exporter/metrics.py
: Prometheus metrics definitionssrc/gunicorn_prometheus_exporter/config.py
: Configuration managementsrc/gunicorn_prometheus_exporter/hooks.py
: Modular hooks system with manager classessrc/gunicorn_prometheus_exporter/master.py
: Master process handlingsrc/gunicorn_prometheus_exporter/storage/
: Redis storage integration
Testing Structure¶
tests/conftest.py
: Shared fixtures and test configurationtests/test_*.py
: Comprehensive test coverage for each moduletox.ini
: Multi-environment testing configuration
π€ How to Contribute¶
Types of Contributions¶
We welcome various types of contributions:
- Bug Reports: Report issues you encounter
- Feature Requests: Suggest new features
- Documentation: Improve or add documentation
- Code: Fix bugs or implement features
- Testing: Add tests or improve test coverage
- Examples: Add framework-specific examples
Getting Started¶
Prerequisites¶
- Python 3.9 or higher
- Git
- pip
- tox (for testing)
Development Setup¶
- Fork the Repository
git clone https://github.com/Agent-Hellboy/gunicorn-prometheus-exporter.git
cd gunicorn-prometheus-exporter
- Create a Virtual Environment
- Install Development Dependencies
- Run Tests
π Development Workflow¶
1. Create a Feature Branch¶
2. Make Your Changes¶
- Write your code
- Add tests for new functionality
- Update documentation if needed
- Follow the coding standards
3. Run Tests and Checks¶
# Run all tests
tox
# Run specific test environments
tox -e py312
tox -e py39
# Run linting
tox -e lint
# Run formatting
tox -e format
4. Commit Your Changes¶
5. Push and Create a Pull Request¶
Then create a pull request on GitHub.
π Coding Standards¶
Python Code Style¶
We use Ruff for linting and formatting. Follow these guidelines:
- Line Length: 88 characters maximum
- Indentation: 4 spaces (no tabs)
- Imports: Grouped and sorted
- Docstrings: Use Google-style docstrings
Code Patterns¶
When contributing, follow the established patterns in the codebase:
- Error Handling: Use comprehensive try/except blocks with meaningful fallbacks
- Logging: Use appropriate log levels throughout
- Configuration: Use environment variable-based configuration
- Metrics: Follow the BaseMetric pattern with automatic registry registration
- Testing: Use pytest fixtures and comprehensive mocking
Commit Message Format¶
We follow the Conventional Commits format:
Types:
feat
: New featurefix
: Bug fixdocs
: Documentation changesstyle
: Code style changes (formatting, etc.)refactor
: Code refactoringtest
: Adding or updating testschore
: Maintenance tasks
Examples:
feat: add Redis storage backend support
fix(worker/hooks/metric): handle worker restart gracefully
docs: update installation guide with Docker examples
test: add comprehensive test coverage for metrics module
DevOps Playbook for Contributors¶
This project relies heavily on containerised workflows and infrastructure automation. The checklist below highlights the DevOps skills you will touch when contributing and why they matter.
Local Container Tooling¶
- Docker images: The sidecar and sample app live under
Dockerfile
anddocker/Dockerfile.app
. Rebuild them withdocker build -t gunicorn-prometheus-exporter:test .
anddocker build -f docker/Dockerfile.app -t gunicorn-app:test .
before running integration tests. - Docker Compose stack:
docker-compose.yml
wires Redis, Gunicorn, the exporter, Prometheus, and Grafana. Usedocker compose up -d --build
for end-to-end smoke tests anddocker compose down
for cleanup. - Shared memory requirements: Gunicorn expects
/dev/shm
β₯ 1 GiB. Compose already setsshm_size: 1gb
; if you rundocker run
manually, append--shm-size=1g
.
Kubernetes Hands-on¶
- kind (Kubernetes in Docker): The CI workflow spins up a throwaway cluster. Install it locally with
brew install kind
and create a cluster viakind create cluster --name test-cluster --wait 300s
. - kubectl essentials: You will apply manifests from
k8s/
, wait for pods, and port-forward services. Common commands: - Temporary manifest rewrites: In CI we copy
k8s/*.yaml
into/tmp/k8s-test/
andsed
the image tags togunicorn-app:test
andgunicorn-prometheus-exporter:test
. Mirror this when testing locally so the cluster uses your freshly built images. - Cleanup discipline: Delete port-forward processes (
pkill -f "kubectl port-forward"
) and clusters (kind delete cluster --name test-cluster
) to avoid resource leaks.
Observability Stack¶
- Prometheus: Validate metrics at
http://localhost:9091/metrics
(Docker) orkubectl port-forward service/gunicorn-metrics-service
. CI asserts the presence of keygunicorn_worker_*
families. - Grafana: Default credentials are sourced from
GRAFANA_ADMIN_PASSWORD
. Override for production withexport GRAFANA_ADMIN_PASSWORD='strong-secret'
beforedocker compose up
. - Redis: Acts as the default multiprocess metrics backend. For local smoke tests set
REDIS_ENABLED=false
; for cluster and Compose scenarios ensure Redis is reachable and unsecured or seeded with secrets templates.
CI/CD Awareness¶
- GitHub Actions pipelines:
.github/workflows/docker-test.yml
runs the full integration matrix, and.github/workflows/docker-build.yml
handles multi-arch builds and Docker Hub publishing. Read these files when adding features to anticipate required updates. - Docker Hub metadata: Release jobs rely on
docker/metadata-action
andpeter-evans/dockerhub-description
. If you change image names or tags, update the workflows andDOCKER_HUB_README.md
. - Secrets and tokens: Keep credentials out of source control. Use
.env
files locally and GitHub Action secrets (DOCKERHUB_USERNAME
,DOCKERHUB_TOKEN
, etc.) in CI. Document new secrets indocs/README.md
or workflow comments.
Automation Etiquette¶
- Run
tox -e docker-test
before opening PRs to catch integration regressions early (mirrors the main CI job). - Capture diagnostic logs on failure (
docker logs <container>
,kubectl describe pod/<pod>
). Attach snippets to issues or pull requests. - Prefer Infrastructure as Code changes alongside documentation updates so contributors understand new operational steps.
Environment Parity Tips¶
- Align local, CI, and production defaults by keeping
.env
examples in sync with the Helm or manifest defaults. Drift here is the top cause of "works locally" bugs. - Prefer declarative config (YAML + templates) over ad-hoc
kubectl
edits. If you must hotfix a cluster, capture the change in the manifest immediately. - Record one command to bootstrap each environment (local:
docker compose up
; CI: GitHub workflow reference; staging/prod:kubectl apply -f
). Contributors should be able to rehearse the exact promotion path.
Secret Management Fundamentals¶
- Ship secrets as templates only (
*.template
). Real secrets belong in local.env
or secret managers (SOPS, Vault, GitHub Encrypted Secrets). - Use
kubectl create secret generic ... --dry-run=client -o yaml
to generate manifests without leaking values. - When adding a new secret requirement, update
k8s/README.md
,docker-compose.yml
, anddocs/examples/
so others know how to populate it.
CI/CD Troubleshooting Checklist¶
- Re-run failing jobs with
Retry
before diving deepβmany Docker registry blips are transient. - Use
::group::
logs in GitHub Actions when adding verbose debugging so the default output stays readable. - For flaky Kubernetes tests, inspect
kind export logs
artifacts and attach them to PRs. - If multi-arch builds error, temporarily force
platforms: linux/amd64
and log an issue so we can fix ARM64 parity deliberately.
Release & Registry Hygiene¶
- Tag images with SemVer (
0.x.y
) and avoidlatest
in docs except for quick-start notes. Our release jobs automatically push:0.x.y
and mark:latest
only on tagged builds. - Update
CHANGELOG.md
in the same PR as version bumps so release notes stay trustworthy. - After merging release PRs, smoke-test the published Docker images (
docker run princekrroshan01/gunicorn-prometheus-exporter:0.x.y --help
) and link the results in the GitHub release discussion.
Security & Compliance Basics¶
- Evaluate new dependencies with
pip install .[dev] && pip check
. If something pulls in a CVE, document the mitigation or seek alternatives. - Keep containers slim: install only runtime packages and drop build tools in the final stage. Every extra binary widens the attack surface.
- Ensure RBAC, NetworkPolicies, and PodSecurity settings are updated whenever you add a new component. Copy + tweak existing patterns instead of inventing new ones.
Performance & Reliability Testing¶
- Use
hey
orwrk
inside the cluster (kubectl run ... --image=ghcr.io/rakyll/hey
) to generate synthetic load against the app while watching metrics. - When tuning Gunicorn worker counts or Redis settings, capture before/after metrics snapshots and document the rationale in the PR description.
- Monitor local test runs with
docker stats
orkubectl top pod
to catch runaway resource consumption early.
Testing¶
Running Tests¶
# Run all tests
tox
# Run specific Python version
tox -e py312
# Run with coverage
tox -e py312 -- --cov=gunicorn_prometheus_exporter --cov-report=html
# Run specific test file
tox -e py312 -- tests/test_metrics.py
# Run specific test function
tox -e py312 -- tests/test_metrics.py::test_worker_requests
Writing Tests¶
Follow these guidelines for writing tests:
- Test Structure: Use pytest fixtures and classes
- Test Names: Descriptive names that explain what is being tested
- Coverage: Aim for high test coverage
- Mocking: Use mocks for external dependencies
Test Coverage¶
We aim for high test coverage. Check coverage with:
Development Tools¶
Pre-commit Hooks¶
Install pre-commit hooks to ensure code quality:
Tox Configuration¶
The project uses tox for testing. Key environments:
py39
,py310
,py311
,py312
: Python version testinglint
: Code linting with Ruffformat
: Code formatting with Ruffdocs
: Documentation building
Documentation¶
Documentation Standards¶
- Docstrings: Use Google-style docstrings for all public functions and classes
- README: Keep the main README updated
- Examples: Provide working examples for all features
- API Documentation: Document all public APIs
Building Documentation¶
# Install MkDocs
pip install mkdocs mkdocs-material
# Build documentation
mkdocs build
# Serve documentation locally
mkdocs serve
Bug Reports¶
Before Reporting a Bug¶
- Check existing issues: Search for similar issues
- Reproduce the issue: Ensure you can reproduce it consistently
- Test with minimal setup: Try with basic configuration
- Check logs: Include relevant log output
Bug Report Template¶
**Bug Description**
A clear description of what the bug is.
**Steps to Reproduce**
1. Install package with `pip install gunicorn-prometheus-exporter`
2. Create configuration file `gunicorn.conf.py`
3. Start server with `gunicorn -c gunicorn.conf.py app:app`
4. See error
**Expected Behavior**
What you expected to happen.
**Actual Behavior**
What actually happened.
**Environment**
- Python version: 3.9.0
- Gunicorn version: 21.2.0
- Operating system: Ubuntu 20.04
- Package version: 0.1.5
**Configuration**
```python
# gunicorn.conf.py
bind = "0.0.0.0:8000"
workers = 4
worker_class = "gunicorn_prometheus_exporter.PrometheusWorker"
# ... rest of configuration
```
Logs
Additional Context Any other context about the problem.
## Feature Requests
### Feature Request Template
```markdown
**Feature Description**
A clear description of the feature you'd like to see.
**Use Case**
Why this feature would be useful.
**Proposed Implementation**
How you think this could be implemented (optional).
**Alternatives Considered**
Other approaches you've considered (optional).
**Additional Context**
Any other context about the feature request.
Pull Request Process¶
Before Submitting a PR¶
- Run all tests: Ensure all tests pass
- Check linting: Ensure code follows style guidelines
- Update documentation: Add/update relevant documentation
- Add tests: Include tests for new functionality
- Update changelog: Add entry to CHANGELOG.md if needed
PR Template¶
**Description**
Brief description of changes.
**Type of Change**
- [ ] Bug fix
- [ ] New feature
- [ ] Documentation update
- [ ] Test addition/update
- [ ] Other (please describe)
**Testing**
- [ ] All tests pass
- [ ] New tests added for new functionality
- [ ] Documentation updated
**Checklist**
- [ ] Code follows style guidelines
- [ ] Self-review completed
- [ ] Documentation updated
- [ ] Tests added/updated
- [ ] Commit messages follow conventional format
**Related Issues**
Closes #123
PR Review Process¶
- Automated Checks: CI/CD pipeline runs tests and linting
- Code Review: Maintainers review the code
- Discussion: Address any feedback or questions
- Merge: Once approved, the PR is merged
Release Process¶
Versioning¶
We follow Semantic Versioning:
- Major: Breaking changes
- Minor: New features (backward compatible)
- Patch: Bug fixes (backward compatible)
Release Checklist¶
- Update version: Update version in
pyproject.toml
- Update changelog: Add release notes to
CHANGELOG.md
- Create release: Create GitHub release
- Publish package: Publish to PyPI
π€ Community Guidelines¶
Code of Conduct¶
- Be respectful and inclusive
- Help others learn and grow
- Provide constructive feedback
- Follow the project's coding standards
Communication¶
- GitHub Issues: For bug reports and feature requests
- GitHub Discussions: For general questions and discussions
- Pull Requests: For code contributions
Getting Help¶
Questions and Support¶
- Documentation: Check the documentation first
- GitHub Issues: Search existing issues
- GitHub Discussions: Ask questions in discussions
- Examples: Review framework-specific examples
Mentorship¶
New contributors are welcome! Feel free to:
- Ask questions in GitHub discussions
- Start with "good first issue" labels
- Request help with your first contribution
π Acknowledgments¶
Thank you for contributing to the Gunicorn Prometheus Exporter! Your contributions help make this project better for everyone.