Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# 🤝 Contributing to PyQueryTracker

Welcome! 👋
Thank you for considering a contribution to **PyQueryTracker** — a lightweight and extensible query tracking library for Python applications.

We appreciate all kinds of contributions, from code and documentation to bug reports and feature ideas. This guide will help you get started.

---

## 🚀 Project Overview

**PyQueryTracker** provides a Python decorator to track and analyze query performance in web applications. It’s designed to be easy to integrate into FastAPI, support customizable exporters, and work well in production and development environments.

---


## Assumptions

1. **You're familiar with [GitHub](https://github.com) and the [Pull Request](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests)(PR) workflow.**

## How to Contribute

1. Make sure that the contribution you want to make is explained or detailed in a GitHub issue! Find an [existing issue](https://github.com/MuddyHope/pyquerytracker/issues/) or [open a new one](https://github.com/MuddyHope/pyquerytracker/issues/new).
2. Once done, [fork the pyquerytracker repository](https://help.github.com/en/github/getting-started-with-github/fork-a-repo) in your own GitHub account. Ask a maintainer if you want your issue to be checked before making a PR.
3. [Create a new Git branch](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-and-deleting-branches-within-your-repository).
4. Review the necessary checks that describes the steps to maintain the repository.
5. Make the changes on your branch.
6. Submit the branch as a PR](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request-from-a-fork) pointing to the `main` branch of the main meilisearch-python repository. A maintainer should comment and/or review your Pull Request within a few days. Although depending on the circumstances, it may take longer.<br>

We do not enforce a naming convention for the PRs, but **please use something descriptive of your changes**, having in mind that the title of your PR will be automatically added to the next


## 🧠 How You Can Contribute

Here are some ways you can help:

- 🐛 Report bugs or suggest improvements via [Issues](https://github.com/MuddyHope/pyquerytracker/issues)
- 📊 Build new exporters (JSON, CSV, Prometheus)
- ⚙️ Integrate with frameworks like FastAPI, Flask
- 🧪 Expand test coverage with Pytest
- 📖 Improve documentation or add examples
- 🧰 Create a CLI wrapper for runtime stats inspection

---

## 🛠️ Development Setup

### Clone the repo

```bash
git clone https://github.com/MuddyHope/pyquerytracker.git
cd pyquerytracker
```

### Pushing your changes
```bash
git checkout -b feature/your-feature-name
```


### Running Tests and Linting
```bash
cd pyquerytracker
pip install -e .

pytest tests/

# Linting
black .
isort .

```
17 changes: 17 additions & 0 deletions pyquerytracker/performance_exporter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import time
import functools

class BuiltinPerformanceExporter:
def __init__(self, output_func=print):
self.output_func = output_func

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you implement something like this PR. #24

It has to be configurable via the main decorator.


def track(self, func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
end = time.perf_counter()
elapsed_ms = (end - start) * 1000
self.output_func(f"Function '{func.__name__}' executed in {elapsed_ms:.2f} ms")
return result
return wrapper
37 changes: 37 additions & 0 deletions tests/test_performance_exporter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import time
import re
import pytest
from pyquerytracker.performance_exporter import BuiltinPerformanceExporter

def test_track_decorator_outputs_execution_time(capsys):
exporter = BuiltinPerformanceExporter()

@exporter.track
def dummy_function():
time.sleep(0.1)

dummy_function()

# Capture the output
captured = capsys.readouterr()
output = captured.out.strip()

# Assert output format (basic check)
assert output.startswith("Function 'dummy_function' executed in ")

# Extract the ms part and check it's within reasonable range
match = re.search(r'executed in ([\d\.]+) ms', output)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regex search becomes a costly operation.

assert match is not None
elapsed_ms = float(match.group(1))

assert 90 <= elapsed_ms <= 200 # Allowing some tolerance

def test_track_decorator_returns_original_value():
exporter = BuiltinPerformanceExporter()

@exporter.track
def add(a, b):
return a + b

result = add(3, 5)
assert result == 8