Skip to content

Commit 1d9836d

Browse files
rabidpraxisCopilotsubzero10
authored
feat(insights): automatic insights instrumentation (#215)
* feat(insights): basic framework event hooks (#208) * Instrumenting ASGI * Add celery events & reworked tests * Django request & db events * Flask request & db instrumentation * ASGI instrumentation * Syntax update * Updated README * Change "component" to "app" for insights event I followed the naming from our notice data. The more common name for this field is "app", so renaming to that. * Remove url & add blueprint to flask events * Removing args from celery event Until we have filtering and before_event functionality. * Add duration to celery events * PR fixes * feat(insights): before_event callback (#213) Also fix config bleeding issue with asgi test * feat(insight): add instrumentation config (#210) * feat(insights): add config for insights contrib This also reworks our config class to use a root dataclass with nested dataclasses for each `insights_config` option set. * Refactor the missing key error handling * Add ASGI config * README fixes * Add comments back and fixed readme, remove cruft * Log errors Also a nice little refactor on the Configuration internals. * Wrap insights event code in a try * How about some test results * Fix 3.8 object is not subscriptable error * Don't reference private Context * Check code-quality as well * feat(insights): event_context (#214) * refactor threadlocals This now uses the ContextVar and a helper ContextStore class. * Basic event_context * More tests * Fix other Notice usage * feat: add request id to django and flask libraries and propagate event context to celery tasks (#216) * feat(insights) add request_id * Add request_id to notice * Fix test * Fix formatted string * Update honeybadger/contrib/celery.py Co-authored-by: Copilot <[email protected]> * Add logger to celelry * Sanitize request_id from inputs --------- Co-authored-by: Copilot <[email protected]> * feat(insights) event sampling (#217) * Formatter update * chore: typo fix * fix: send payload for celery events * test: read correct arg * test: read correct arg * perf: remove lock (#227) * chode: revert temp workflow changes * chore: capture logs to debug failing test * chore: capture logs to debug failing test * chore: allow more time for the batch to be sent * chore: add changelog entry --------- Co-authored-by: Copilot <[email protected]> Co-authored-by: Pangratios Cosma <[email protected]>
1 parent cbb10ae commit 1d9836d

31 files changed

+1955
-371
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ CHANGELOG](http://keepachangelog.com/) for how to update this file. This project
44
adheres to [Semantic Versioning](http://semver.org/).
55

66
## [Unreleased]
7+
- Add Insights automatic instrumentation (#215)
78

89
## [1.0.3] - 2025-07-21
910
- Fix: Register signal handler only in main thread

README.md

Lines changed: 129 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,132 @@ That's it! For additional configuration options, keep reading.
277277

278278
**Note:** By default, honeybadger reports errors in separate threads. For platforms that disallows threading (such as serving a flask/django app with uwsgi and disabling threading), Honeybadger will fail to report errors. You can either enable threading if you have the option, or set `force_sync` config option to `True`. This causes Honeybadger to report errors in a single thread.
279279

280+
## Insights Automatic Instrumentation
281+
282+
Honeybadger Insights allows you to automatically track various events in your
283+
application. To enable Insights automatic instrumentation, add the following to
284+
your configuration:
285+
286+
```python
287+
honeybadger.configure(insights_enabled=True)
288+
```
289+
290+
### Supported Libraries
291+
292+
After integration with our middleware or extensions, Honeybadger will
293+
automatically instrument the following libraries:
294+
295+
- Django requests & database queries
296+
- Flask requests & database queries
297+
- ASGI requests
298+
- Celery tasks
299+
300+
### Configuration
301+
302+
You can configure the instrumentation for specific libraries / components by
303+
passing a dictionary to a specialized `insights_config` parameter.
304+
305+
By default, all keyword dict params are run through our `params_filters`.
306+
307+
The following instrumentation configs are available:
308+
309+
#### Django
310+
311+
```python
312+
honeybadger.configure(
313+
insights_config={
314+
"django": {
315+
# Disable instrumentation for Django, defaults to False
316+
"disabled": True,
317+
# include GET/POST params in events, defaults to False
318+
"include_params": True,
319+
}
320+
}
321+
)
322+
```
323+
324+
#### Flask
325+
326+
```python
327+
honeybadger.configure(
328+
insights_config={
329+
"flask": {
330+
# Disable instrumentation for Flask, defaults to False
331+
"disabled": True,
332+
# Include GET/POST params in events, defaults to False
333+
"include_params": True,
334+
}
335+
}
336+
)
337+
```
338+
339+
#### ASGI
340+
341+
```python
342+
honeybadger.configure(
343+
insights_config={
344+
"asgi": {
345+
# Disable instrumentation for ASGI, defaults to False
346+
"disabled": True,
347+
# Include query params in events, defaults to False
348+
"include_params": True,
349+
}
350+
}
351+
)
352+
```
353+
354+
#### Celery
355+
356+
```python
357+
honeybadger.configure(
358+
insights_config={
359+
"celery": {
360+
# Disable instrumentation for Celery, defaults to False
361+
"disabled": True,
362+
# Include task args/kwargs, defaults to False
363+
"include_args": True,
364+
# List of task names or regexes to exclude, defaults to []
365+
"exclude_tasks": [
366+
"tasks.cleanup",
367+
re.compile("^internal_"),
368+
],
369+
}
370+
}
371+
)
372+
```
373+
374+
#### DB
375+
376+
To configure database instrumentation, you can pass a dictionary to the
377+
"db" insights config. This will affect all supported libraries that use capture
378+
database events.
379+
380+
```python
381+
honeybadger.configure(
382+
insights_config={
383+
"db": {
384+
# Disable instrumentation for DB, defaults to False
385+
"disabled": True,
386+
# Include SQL params in events, defaults to False
387+
"include_params": True,
388+
389+
# List of task names or regexes to exclude, defaults to
390+
# `honeybadger.config.default_excluded_queries()`
391+
"exclude_queries": [
392+
"django_admin_log", # Matches any query containing this string
393+
re.compile(r".*auth_permission.*"), # Regex pattern
394+
],
395+
396+
# To add to the default excluded queries, use the `honeybadger.config.default_excluded_queries()` method
397+
"exclude_queries": honeybadger.config.default_excluded_queries() + [
398+
re.compile(r".*django_admin_log.*"),
399+
re.compile(r".*auth_permission.*"),
400+
],
401+
}
402+
}
403+
)
404+
```
405+
280406
## Logging
281407

282408
By default, Honeybadger uses the `logging.NullHandler` for logging so it doesn't make any assumptions about your logging setup. In Django, add a `honeybadger` section to your `LOGGING` config to enable Honeybadger logging. For example:
@@ -371,15 +497,17 @@ The following options are available to you:
371497
| endpoint | `str` | `"https://api.honeybadger.io"` | `"https://honeybadger.example.com/"` | `HONEYBADGER_ENDPOINT` |
372498
| params_filters | `list` | `['password', 'password_confirmation', 'credit_card']` | `['super', 'secret', 'keys']` | `HONEYBADGER_PARAMS_FILTERS` |
373499
| force_report_data | `bool` | `False` | `True` | `HONEYBADGER_FORCE_REPORT_DATA` |
500+
| before_notify | `callable` | `lambda notice: notice` | `custom_before_notify_function` | n/a |
374501
| excluded_exceptions | `list` | `[]` | `['Http404', 'MyCustomIgnoredError']` | `HONEYBADGER_EXCLUDED_EXCEPTIONS` |
375502
| force_sync | `bool` | `False` | `True` | `HONEYBADGER_FORCE_SYNC` |
376503
| report_local_variables | `bool` | `False` | `True` | `HONEYBADGER_REPORT_LOCAL_VARIABLES` |
504+
| insights_enabled | `bool` | `False` | `True` | `HONEYBADGER_INSIGHTS_ENABLED` |
505+
| before_event | `callable` | `lambda notice: None` | `custom_before_notify_function` | n/a |
377506
| events_batch_size | `int` | `1000` | `50` | `HONEYBADGER_EVENTS_BATCH_SIZE` |
378507
| events_max_queue_size | `int` | `10000` | `5000` | `HONEYBADGER_EVENTS_MAX_QUEUE_SIZE` |
379508
| events_timeout | `float` | `5.0` | `1.0` | `HONEYBADGER_EVENTS_TIMEOUT` |
380509
| events_max_batch_retries | `int` | `3` | `5` | `HONEYBADGER_EVENTS_MAX_BATCH_RETRIES`|
381510
| events_throttle_wait | `float` | `60.0` | `1200.0` | `HONEYBADGER_EVENTS_THROTTLE_WAIT` |
382-
| before_notify | `callable` | `lambda notice: notice` | `custom_before_notify_function` | n/a |
383511

384512
[^1]: Honeybadger will try to infer the correct environment when possible. For example, in the case of the Django integration, if Django settings are set to `DEBUG = True`, the environment will default to `development`.
385513

dev-requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ psutil
1515
pylint
1616
pytest
1717
pytest-cov
18+
pytest-asyncio
1819
six
20+
sqlalchemy
1921
testfixtures
2022
typing-extensions
2123

0 commit comments

Comments
 (0)