Thank you for your interest in contributing to the Promlite library! We welcome contributions from the community and are pleased to have you participate.
- Code of Conduct
- Getting Started
- Development Setup
- Project Structure
- Development Workflow
- Coding Standards
- Testing
- Documentation
- Pull Request Process
- Release Process
This project adheres to a code of conduct. By participating, you are expected to uphold this code. Please be respectful and constructive in all interactions.
- Fork the repository on GitHub
- Clone your fork locally
- Create a feature branch
- Make your changes
- Add tests for your changes
- Run the test suite
- Submit a pull request
- Node.js (version 18 or higher)
- npm (comes with Node.js)
- Git
- Clone your fork:
git clone https://github.com/YOUR_USERNAME/prom-client.git
cd prom-client- Install dependencies:
npm install- Verify the setup by running tests:
npm testThe project includes several npm scripts for development:
# Run all checks (recommended before committing)
npm run check
# Individual checks
npm run type-check # TypeScript type checking
npm run lint # ESLint code quality check
npm run format:check # Check if code is properly formatted
# Fixes and formatting
npm run lint:fix # Fix ESLint issues automatically
npm run format # Format code with Prettier
# Testing
npm test # Run tests
npm run test:watch # Run tests in watch mode (for development)
# Build
npm run build # Build the projectWe use an integrated approach for code quality:
- ESLint handles code quality and logic rules
- Prettier handles all code formatting
- TypeScript handles type checking
Before committing:
# Run all checks at once
npm run check
# Or fix issues automatically
npm run lint:fix && npm run formatThe npm run check command runs:
- Type checking (
tsc --noEmit) - Linting (
eslint) - Format checking (
prettier --check)
promlite/
├── src/ # Source code
│ ├── index.ts # Main entry point and exports
│ └── metrics/ # Metric implementations
│ ├── Counter.ts # Counter metric
│ ├── Gauge.ts # Gauge metric
│ └── Histogram.ts # Histogram metric
├── test/ # Test files
│ ├── Counter.test.ts # Counter tests
│ ├── Gauge.test.ts # Gauge tests
│ └── Histogram.test.ts # Histogram tests
├── dist/ # Built output (generated)
├── docs/ # Documentation
├── package.json # Project configuration
├── tsconfig.json # TypeScript configuration
├── jest.config.js # Jest test configuration
└── README.md # Project README
Use descriptive branch names with prefixes:
feature/- for new featuresfix/- for bug fixesdocs/- for documentation changesrefactor/- for code refactoringtest/- for adding or fixing tests
Examples:
feature/add-summary-metricfix/histogram-bucket-sortingdocs/update-api-examples
Follow the Conventional Commits specification:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
Types:
feat: A new featurefix: A bug fixdocs: Documentation only changesstyle: Changes that do not affect the meaning of the coderefactor: A code change that neither fixes a bug nor adds a featuretest: Adding missing tests or correcting existing testschore: Changes to the build process or auxiliary tools
Examples:
feat: add Summary metric type
fix(histogram): correct bucket sorting for negative values
docs: update API examples in README
test(gauge): add tests for label validation
- Type Safety: Use strict TypeScript settings. Avoid
anytypes. - Interfaces: Prefer interfaces for object shapes when possible.
- Generics: Use generics for reusable code.
- Null Safety: Handle null and undefined explicitly.
We use Prettier for code formatting and ESLint for code quality checks. The tools are configured to work together without conflicts.
- Handles code quality rules (prefer-const, no-var, curly, etc.)
- TypeScript-specific rules for type safety
- Uses
eslint-config-prettierto disable formatting rules
- Handles all code formatting automatically
- Configuration in
.prettierrc:- 2 spaces for indentation
- Single quotes for strings
- Semicolons required
- Trailing commas (ES5 style)
- Line length limit of 80 characters
- ESLint checks for code quality issues
- Prettier formats the code consistently
- No conflicts between the tools
This project uses a carefully configured setup to avoid conflicts between ESLint and Prettier:
eslint.config.js- ESLint configuration with TypeScript support.prettierrc- Prettier formatting configuration.prettierignore- Files to ignore during formatting
- ESLint is configured with
eslint-config-prettierwhich disables all formatting-related rules - Prettier handles all code formatting (indentation, quotes, semicolons, etc.)
- ESLint focuses only on code quality (logic errors, best practices, etc.)
Our GitHub Actions CI runs npm run check which executes:
- TypeScript compilation check
- ESLint code quality check
- Prettier formatting check
This ensures consistent code quality and formatting across all contributions.
If you encounter formatting or linting conflicts:
# Fix all issues automatically
npm run lint:fix && npm run format
# Check what's wrong
npm run check
# Run individual checks
npm run lint # Check for code quality issues
npm run format:check # Check formatting
npm run type-check # Check TypeScript types- Validation: Validate inputs and throw descriptive errors
- Error Types: Use appropriate error types (TypeError, Error, etc.)
- Error Messages: Provide clear, actionable error messages
- Documentation: Document all possible errors in JSDoc comments
Example:
/**
* Increment the counter
* @param labels - Array of label values
* @param amount - Amount to increment by (must be positive)
* @throws {Error} When label count doesn't match
* @throws {TypeError} When amount is not a valid number
*/
inc(labels: string[], amount: number = 1): void {
if (labels.length !== this.labels.length) {
throw new Error(`Label count mismatch, expected ${this.labels.length} but got ${labels.length}`);
}
if (typeof amount !== 'number' || isNaN(amount) || !Number.isFinite(amount)) {
throw new TypeError(`Amount is not a valid finite number: ${amount}`);
}
if (amount < 0) {
throw new Error('Counter cannot be decreased');
}
// ... implementation
}- JSDoc: Use JSDoc comments for all public APIs
- Examples: Include examples in documentation
- Types: Document parameter and return types
- Exceptions: Document all thrown exceptions
We use Jest for testing. Tests should be comprehensive and cover:
- Happy Path: Normal usage scenarios
- Edge Cases: Boundary conditions and unusual inputs
- Error Cases: Invalid inputs and error conditions
- Type Safety: TypeScript type checking
- Unit Tests: Test individual methods and classes
- Integration Tests: Test interactions between components
- Performance Tests: Ensure acceptable performance characteristics
import { Counter } from '../src/metrics/Counter.js';
describe('Counter', () => {
let counter: Counter;
beforeEach(() => {
counter = new Counter('test_counter', 'Test counter', ['method']);
});
describe('inc()', () => {
it('should increment by default amount', () => {
counter.inc(['GET']);
expect(counter.getValue(['GET'])).toBe(1);
});
it('should increment by custom amount', () => {
counter.inc(['GET'], 5);
expect(counter.getValue(['GET'])).toBe(5);
});
it('should throw error for negative values', () => {
expect(() => counter.inc(['GET'], -1))
.toThrow('Counter cannot be decreased');
});
});
});- Maintain high test coverage (aim for >90%)
- All new features must include tests
- Bug fixes must include regression tests
# Run all tests
npm test
# Run specific test file
npm test Counter.test.ts- Use JSDoc for all public APIs
- Include parameter descriptions and types
- Document return values
- List all possible exceptions
- Provide usage examples
When adding new features:
- Update the feature list
- Add API documentation
- Include usage examples
- Update the table of contents if needed
Follow this format for API documentation:
/**
* Creates a new histogram metric
*
* @param name - The metric name (must be valid Prometheus metric name)
* @param help - Help text describing the metric
* @param buckets - Array of bucket upper bounds (must be sorted)
* @param labels - Array of label names (optional)
*
* @throws {Error} When buckets are not properly sorted
* @throws {TypeError} When parameters are invalid types
*
* @example
* ```typescript
* const histogram = new Histogram(
* 'request_duration_seconds',
* 'HTTP request duration in seconds',
* [0.1, 0.5, 1.0, 2.5, 5.0, 10.0],
* ['method', 'route']
* );
*
* histogram.observe(['GET', '/api/users'], 0.234);
* ```
*/- Fork and Branch: Create a feature branch from
main - Code: Implement your changes following coding standards
- Test: Add comprehensive tests for new functionality
- Documentation: Update documentation as needed
- Quality Checks: Run
npm run checkto ensure all checks pass - Self Review: Review your own code before submitting
- Description: Provide a clear description of changes
- Issue Link: Reference any related issues
- Testing: Include test results or coverage reports
- Breaking Changes: Highlight any breaking changes
- Migration Guide: Provide migration instructions if needed
## Description
Brief description of changes
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Testing
- [ ] Tests pass locally
- [ ] New tests added for new functionality
- [ ] No decrease in test coverage
## Checklist
- [ ] All quality checks pass (`npm run check`)
- [ ] Tests pass locally (`npm test`)
- [ ] Code follows project style guidelines
- [ ] Self-review completed
- [ ] Documentation updated
- [ ] No breaking changes (or documented)- Automated Checks: All CI checks must pass
- Code Review: At least one maintainer review required
- Testing: Verify all tests pass
- Documentation: Ensure docs are updated
- Approval: PR approved by maintainer
We follow Semantic Versioning:
- MAJOR: Breaking changes
- MINOR: New features (backward compatible)
- PATCH: Bug fixes (backward compatible)
- Version Bump: Update version in
package.json - Changelog: Update
CHANGELOG.mdwith changes - Tag: Create git tag for version
- Build: Generate distribution files
- Publish: Publish to npm registry
- Documentation: Update documentation
- LTS Versions: Critical bug fixes for supported versions
- Security: Security patches for all supported versions
- Dependencies: Regular dependency updates
- Issues: Use GitHub issues for bug reports and feature requests
- Discussions: Use GitHub discussions for questions and ideas
- Documentation: Check README.md and inline documentation first
Contributors will be recognized in:
- GitHub contributors list
- Release notes for significant contributions
- Project documentation acknowledgments
Thank you for contributing to Promlite!