-
Notifications
You must be signed in to change notification settings - Fork 20
Feat metric logging #132
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Feat metric logging #132
Changes from all commits
a224c01
12caa8d
30c61aa
bf8f963
173b8e6
e8c5175
29ac9bd
fc55a4b
04083b0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,3 +17,4 @@ bruno.json | |
| .ruff_cache/ | ||
| *.csv | ||
| *.png | ||
| METRICS_IMPLEMENTATION.md | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| """Custom docs for the /metrics PESUAuth endpoint.""" | ||
|
|
||
| from app.docs.base import ApiDocs | ||
|
|
||
| metrics_docs = ApiDocs( | ||
| request_examples={}, # GET endpoint doesn't need request examples | ||
| response_examples={ | ||
| 200: { | ||
| "description": "Metrics retrieved successfully", | ||
| "content": { | ||
| "application/json": { | ||
| "examples": { | ||
| "metrics_response": { | ||
| "summary": "Current Metrics", | ||
| "description": ( | ||
| "All current application metrics including authentication counts and error rates" | ||
| ), | ||
| "value": { | ||
| "status": True, | ||
| "message": "Metrics retrieved successfully", | ||
| "timestamp": "2025-08-28T15:30:45.123456+05:30", | ||
| "metrics": { | ||
| "auth_success_total": 150, | ||
| "auth_failure_total": 12, | ||
|
Comment on lines
+23
to
+24
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should also track how many auth requests are received, including a split for how many with and without profile data |
||
| "validation_error_total": 8, | ||
| "pesu_academy_error_total": 5, | ||
| "unhandled_exception_total": 0, | ||
| "csrf_token_error_total": 2, | ||
| "profile_fetch_error_total": 1, | ||
| "profile_parse_error_total": 0, | ||
| "csrf_token_refresh_success_total": 45, | ||
| "csrf_token_refresh_failure_total": 1, | ||
| }, | ||
| }, | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| } | ||
| }, | ||
|
Comment on lines
+8
to
+40
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Create a model for this. The response model will also need an update. |
||
| ) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| """Metrics collector for tracking authentication successes, failures, and error types.""" | ||
|
|
||
| import threading | ||
| from collections import defaultdict | ||
|
|
||
|
|
||
| class MetricsCollector: | ||
| """Thread-safe metrics collector for tracking application performance and usage.""" | ||
|
|
||
| def __init__(self) -> None: | ||
| """Initialize the metrics collector with thread safety.""" | ||
| self.lock = threading.Lock() | ||
| self.metrics = defaultdict(int) | ||
|
|
||
| def inc(self, key: str) -> None: | ||
| """Increment a metric counter by 1. | ||
|
|
||
| Args: | ||
| key (str): The metric key to increment. | ||
| """ | ||
| with self.lock: | ||
| self.metrics[key] += 1 | ||
|
|
||
| def get(self) -> dict[str, int]: | ||
| """Get a copy of all current metrics. | ||
|
|
||
| Returns: | ||
| dict[str, int]: Dictionary containing all metrics and their current values. | ||
| """ | ||
| with self.lock: | ||
| return dict(self.metrics) | ||
|
|
||
|
|
||
| # Global metrics instance | ||
| metrics = MetricsCollector() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a much cleaner solution. Look into a middleware layer. Here is some pseudo code to get you started:
Note, you will need to accordingly increment other metrics like how many with and without profile data by parsing the request.