|
| 1 | +# Contributing to LogStructor |
| 2 | + |
| 3 | +Thank you for your interest in contributing to LogStructor! We welcome contributions from the community and are excited to see what you'll bring to the project. |
| 4 | + |
| 5 | +## Getting Started |
| 6 | + |
| 7 | +### Prerequisites |
| 8 | + |
| 9 | +- Python 3.11 or higher |
| 10 | +- [uv](https://docs.astral.sh/uv/) for dependency management (recommended) |
| 11 | +- Git |
| 12 | + |
| 13 | +### Setting Up Your Development Environment |
| 14 | + |
| 15 | +1. **Fork and clone the repository:** |
| 16 | + ```bash |
| 17 | + git clone https://github.com/your-username/logstructor.git |
| 18 | + cd logstructor |
| 19 | + ``` |
| 20 | + |
| 21 | +2. **Install dependencies using uv:** |
| 22 | + ```bash |
| 23 | + uv sync --all-groups |
| 24 | + ``` |
| 25 | + |
| 26 | + Or if you prefer pip: |
| 27 | + ```bash |
| 28 | + pip install -e ".[test,linting,docs]" |
| 29 | + ``` |
| 30 | + |
| 31 | +3. **Verify your setup:** |
| 32 | + ```bash |
| 33 | + uv run pytest |
| 34 | + uv run ruff check |
| 35 | + uv run mypy logstructor |
| 36 | + ``` |
| 37 | + |
| 38 | +## Development Workflow |
| 39 | + |
| 40 | +### Code Style and Quality |
| 41 | + |
| 42 | +We maintain high code quality standards using automated tools: |
| 43 | + |
| 44 | +- **Ruff** for linting and formatting |
| 45 | +- **MyPy** for type checking |
| 46 | +- **Pytest** for testing |
| 47 | + |
| 48 | +Before submitting any changes, ensure your code passes all checks: |
| 49 | + |
| 50 | +```bash |
| 51 | +# Format code |
| 52 | +uv run ruff format |
| 53 | + |
| 54 | +# Check linting |
| 55 | +uv run ruff check |
| 56 | + |
| 57 | +# Type checking |
| 58 | +uv run mypy logstructor |
| 59 | + |
| 60 | +# Run tests |
| 61 | +uv run pytest |
| 62 | + |
| 63 | +# Run tests with coverage |
| 64 | +uv run pytest --cov=logstructor --cov-report=html |
| 65 | +``` |
| 66 | + |
| 67 | +### Running Tests |
| 68 | + |
| 69 | +We have comprehensive test coverage. Run the full test suite: |
| 70 | + |
| 71 | +```bash |
| 72 | +# All tests |
| 73 | +uv run pytest |
| 74 | + |
| 75 | +# Specific test file |
| 76 | +uv run pytest tests/test_logger.py |
| 77 | + |
| 78 | +# With coverage report |
| 79 | +uv run pytest --cov=logstructor --cov-report=term-missing |
| 80 | + |
| 81 | +# Async tests only |
| 82 | +uv run pytest -k "async" |
| 83 | +``` |
| 84 | + |
| 85 | +### Documentation |
| 86 | + |
| 87 | +Documentation is built with Sphinx and hosted as part of the project: |
| 88 | + |
| 89 | +```bash |
| 90 | +# Build documentation |
| 91 | +cd docs |
| 92 | +uv run sphinx-build -b html source build |
| 93 | + |
| 94 | +# Serve locally (if you have a simple HTTP server) |
| 95 | +cd build && python -m http.server 8000 |
| 96 | +``` |
| 97 | + |
| 98 | +## Contributing Guidelines |
| 99 | + |
| 100 | +### Types of Contributions |
| 101 | + |
| 102 | +We welcome several types of contributions: |
| 103 | + |
| 104 | +- **Bug fixes** - Fix issues in existing functionality |
| 105 | +- **Feature enhancements** - Improve existing features |
| 106 | +- **New features** - Add new functionality (please discuss first) |
| 107 | +- **Documentation** - Improve docs, examples, or tutorials |
| 108 | +- **Tests** - Add or improve test coverage |
| 109 | +- **Performance** - Optimize existing code |
| 110 | + |
| 111 | +### Before You Start |
| 112 | + |
| 113 | +For significant changes, please: |
| 114 | + |
| 115 | +1. **Open an issue** to discuss your proposed changes |
| 116 | +2. **Check existing issues** to avoid duplicate work |
| 117 | +3. **Review the roadmap** to align with project direction |
| 118 | + |
| 119 | +### Making Changes |
| 120 | + |
| 121 | +1. **Create a feature branch:** |
| 122 | + ```bash |
| 123 | + git checkout -b feature/your-feature-name |
| 124 | + ``` |
| 125 | + |
| 126 | +2. **Make your changes** following our coding standards |
| 127 | + |
| 128 | +3. **Add tests** for any new functionality |
| 129 | + |
| 130 | +4. **Update documentation** if needed |
| 131 | + |
| 132 | +5. **Ensure all checks pass:** |
| 133 | + ```bash |
| 134 | + uv run ruff check |
| 135 | + uv run mypy logstructor |
| 136 | + uv run pytest |
| 137 | + ``` |
| 138 | + |
| 139 | +### Commit Messages |
| 140 | + |
| 141 | +We use conventional commits for automated changelog generation: |
| 142 | + |
| 143 | +``` |
| 144 | +feat: add support for custom timestamp formats |
| 145 | +fix: resolve context isolation issue in async functions |
| 146 | +docs: improve context management examples |
| 147 | +test: add tests for thread safety |
| 148 | +refactor: simplify formatter initialization |
| 149 | +``` |
| 150 | + |
| 151 | +Types: `feat`, `fix`, `docs`, `test`, `refactor`, `perf`, `ci`, `chore` |
| 152 | + |
| 153 | +### Pull Request Process |
| 154 | + |
| 155 | +1. **Ensure your branch is up to date:** |
| 156 | + ```bash |
| 157 | + git checkout main |
| 158 | + git pull upstream main |
| 159 | + git checkout your-branch |
| 160 | + git rebase main |
| 161 | + ``` |
| 162 | + |
| 163 | +2. **Create a pull request** with: |
| 164 | + - Clear title and description |
| 165 | + - Reference to related issues |
| 166 | + - Summary of changes made |
| 167 | + - Any breaking changes noted |
| 168 | + |
| 169 | +3. **Respond to feedback** promptly and make requested changes |
| 170 | + |
| 171 | +4. **Ensure CI passes** - all automated checks must pass |
| 172 | + |
| 173 | +## Code Standards |
| 174 | + |
| 175 | +### Python Code Style |
| 176 | + |
| 177 | +- Follow PEP 8 (enforced by Ruff) |
| 178 | +- Use type hints for all public APIs |
| 179 | +- Write comprehensive docstrings with examples |
| 180 | +- Keep functions focused and testable |
| 181 | +- Prefer composition over inheritance |
| 182 | + |
| 183 | +### Example of Good Code Style |
| 184 | + |
| 185 | +```python |
| 186 | +def bind_context(**kwargs: Any) -> None: |
| 187 | + """ |
| 188 | + Bind key-value pairs to the current context's logging context. |
| 189 | +
|
| 190 | + These fields will be automatically included in all subsequent log entries |
| 191 | + within the current context until cleared or overwritten. |
| 192 | +
|
| 193 | + Args: |
| 194 | + **kwargs: Key-value pairs to bind to the context |
| 195 | +
|
| 196 | + Examples: |
| 197 | + Basic usage: |
| 198 | + >>> bind_context(request_id="req-123", user_id=456) |
| 199 | + >>> logger.info("Processing request") # Will include request_id and user_id |
| 200 | +
|
| 201 | + Web application example: |
| 202 | + >>> bind_context(request_id=request.id, user_id=request.user.id) |
| 203 | + >>> logger.info("User login attempt") # Automatically includes context |
| 204 | + """ |
| 205 | + current_context = _context_data.get().copy() |
| 206 | + current_context.update(kwargs) |
| 207 | + _context_data.set(current_context) |
| 208 | +``` |
| 209 | + |
| 210 | +### Testing Standards |
| 211 | + |
| 212 | +- Write tests for all new functionality |
| 213 | +- Aim for high test coverage (>90%) |
| 214 | +- Include both positive and negative test cases |
| 215 | +- Test async functionality where applicable |
| 216 | +- Use descriptive test names |
| 217 | + |
| 218 | +```python |
| 219 | +def test_bind_context_overwrites_existing(): |
| 220 | + """Test that bind_context overwrites existing keys.""" |
| 221 | + bind_context(user_id=123) |
| 222 | + bind_context(user_id=456) # Should overwrite |
| 223 | + |
| 224 | + context = get_context() |
| 225 | + assert context["user_id"] == 456 |
| 226 | +``` |
| 227 | + |
| 228 | +## Project Structure |
| 229 | + |
| 230 | +``` |
| 231 | +logstructor/ |
| 232 | +├── logstructor/ # Main package |
| 233 | +│ ├── __init__.py # Public API |
| 234 | +│ ├── logger.py # StructLogger implementation |
| 235 | +│ ├── formatter.py # JSON formatter |
| 236 | +│ ├── context.py # Context management |
| 237 | +│ ├── config.py # Configuration utilities |
| 238 | +│ └── exceptions.py # Custom exceptions |
| 239 | +├── tests/ # Test suite |
| 240 | +├── docs/ # Sphinx documentation |
| 241 | +├── examples/ # Usage examples |
| 242 | +└── pyproject.toml # Project configuration |
| 243 | +``` |
| 244 | + |
| 245 | +## Design Principles |
| 246 | + |
| 247 | +1. **Backward Compatibility** - Never break existing logging code |
| 248 | +2. **Zero Dependencies** - Keep the core lightweight |
| 249 | +3. **Thread Safety** - Support multi-threaded applications |
| 250 | +4. **Async Support** - First-class async/await support |
| 251 | +5. **Performance** - Minimal overhead over standard logging |
| 252 | +6. **Simplicity** - Easy to use, hard to misuse |
| 253 | + |
| 254 | +## Release Process |
| 255 | + |
| 256 | +Releases are automated using semantic-release: |
| 257 | + |
| 258 | +1. Merge changes to `main` branch |
| 259 | +2. Semantic-release analyzes commit messages |
| 260 | +3. Version is bumped automatically |
| 261 | +4. Changelog is generated |
| 262 | +5. Package is published to PyPI |
| 263 | + |
| 264 | +## Getting Help |
| 265 | + |
| 266 | +- **Issues**: Open a GitHub issue for bugs or feature requests |
| 267 | +- **Discussions**: Use GitHub Discussions for questions |
| 268 | +- **Documentation**: Check the docs at `docs/` |
| 269 | + |
| 270 | +## Recognition |
| 271 | + |
| 272 | +Contributors are recognized in: |
| 273 | +- GitHub contributors list |
| 274 | +- Release notes for significant contributions |
| 275 | +- Documentation acknowledgments |
| 276 | + |
| 277 | +Thank you for contributing to LogStructor! 🚀 |
0 commit comments