A Django third-party package for observing Django functionality via signals.
Project description
Django Salmon
A standardized way to observe Django's internals.
Observability is critical feature of software development, but tends to be neglected. It seems like the majority of Python APMs and observability tools have to monkey-patch Django's internals to properly observe the application. This library seeks to do that monkey-patching once, then provide a standardized set of signals/hooks to observe an application.
Usage
- Install it as a dependency:
pip install django-salmon
- Add it to your
INSTALLED_APPS:
INSTALLED_APPS = [
# ...
"django_salmon",
# ...
]
- Connect to the relevant signals:
from django.dispatch import receiver
from django_salmon.signals import observe_cache_operation
@receiver(observe_cache_operation)
def observe_cache_ops(sender, args, result, timing, stacktrace):
print(f"{sender=}\t{timing=}=")
# stacktrace is a callable that will return the formatted stacktrace.
print("".join(stacktrace()))
Configuration
Django Salmon supports customizing the decorators that are applied to Django functionality. For example, by default the following decorators are used on all cache operations:
OBSERVING = {
"cache": [
"django_salmon.decorators.prevent_nested_observe",
"django_salmon.decorators.with_args",
"django_salmon.decorators.with_result",
"django_salmon.decorators.with_stacktrace",
"django_salmon.decorators.with_timing",
],
}
Each of these decorators will measure a different facet and include it in the context for the django_salmon.decorators.observe decorator. If you only need to measure the timing facet, use the following configuration:
OBSERVING = {
"cache": [
"django_salmon.decorators.prevent_nested_observe",
"django_salmon.decorators.with_timing",
],
}
Observing your own functions
Django Salmon supports you applying your own decorators explicitly or by using a registry and utilizing the OBSERVING configuration.
from django.dispatch import Signal
from django_salmon.decorators import observe, with_args
my_signal = Signal()
@observe(my_signal)
@with_args
def explicit_usage_example(arg1, arg2, kwarg1=None):
return "result"
You can register your own stacked decorators to the registry as well:
# settings.py
OBSERVING = {
"only_timing": [
"django_salmon.decorators.prevent_nested_observe",
"django_salmon.decorators.with_timing",
],
}
# signals.py
from django.dispatch import Signal
my_signal = Signal()
# observe.py / Or anything else you want to use
from django_salmon import registry
from django_salmon.decorators import observe
from .signals import my_signal
def observe_only_timing(func):
"""
Custom decorator factory that emits ``my_signal`` signals.
"""
return observe(my_signal)(registry.apply_decorators("only_timing", func))
# your_logic.py
from .observe import observe_only_timing
@observe_only_timing
def registry_usage_example(arg1, arg2, kwarg1=None):
return "result"
Creating your own observer decorator
You can define your own decorator to be used with the registry by adding the relevant data to the context.
An example is:
import functools
from django.dispatch import receiver, Signal
from django_salmon.decorators import observe_context, observe
def with_answer_to_everything(func):
"""
Decorator that adds the answer to life to the context.
Must be used below @observe decorator.
"""
@functools.wraps(func)
def wrapper(*func_args, **func_kwargs):
func_result = func(*func_args, **func_kwargs)
# The context will be None if OBSERVING["enabled"] is False
if (context := observe_context.get()) is not None:
# Observe some aspect of the project
context["answer_to_everything"] = 42
return func_result
return wrapper
my_signal = Signal()
@receiver(my_signal)
def my_signal_receiver(sender, answer_to_everything, **kwargs):
"""
When my_signal is raised, it will now include answer_to_everything
as a keyword argument.
"""
print(f"{answer_to_everything=}")
@observe(my_signal)
@with_answer_to_everything
def custom_decorator_example():
return "result"
Project goals
This project contains several hacks to support observing a Django application. The Django project should change to avoid the necessity of these hacks.
Going further, ideally the Django framework would consider adopting an observability API rendering this project obsolete.
Contributing
See CONTRIBUTING.md for how to contribute!
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_salmon-0.1.0.tar.gz.
File metadata
- Download URL: django_salmon-0.1.0.tar.gz
- Upload date:
- Size: 50.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7f9e01f9ccd9f78d79b66c1af6dc9356915d48b1aefca1ddf0450f1888193af7
|
|
| MD5 |
6b01161a3e94a39439e906d47b10934e
|
|
| BLAKE2b-256 |
b7512f96559230c75a2d4229867722c45da8ca7088df03300245a69bbc727ef4
|
Provenance
The following attestation bundles were made for django_salmon-0.1.0.tar.gz:
Publisher:
release.yml on tim-schilling/django-salmon
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_salmon-0.1.0.tar.gz -
Subject digest:
7f9e01f9ccd9f78d79b66c1af6dc9356915d48b1aefca1ddf0450f1888193af7 - Sigstore transparency entry: 1683160422
- Sigstore integration time:
-
Permalink:
tim-schilling/django-salmon@e1dfc99a4493516ca41e65d082422ae2ddc331aa -
Branch / Tag:
refs/tags/0.1.0 - Owner: https://github.com/tim-schilling
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e1dfc99a4493516ca41e65d082422ae2ddc331aa -
Trigger Event:
push
-
Statement type:
File details
Details for the file django_salmon-0.1.0-py3-none-any.whl.
File metadata
- Download URL: django_salmon-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d11553fcf3dd86b34b7885a3756a263b892083ff735cceaa55768da7e4531472
|
|
| MD5 |
8f33200187b40ac8fc93673fe4cfd0ee
|
|
| BLAKE2b-256 |
c15f0119ee09a19ba2200e29eb95a2cc776d9a72b0eb18c30678fe07f59b1b4b
|
Provenance
The following attestation bundles were made for django_salmon-0.1.0-py3-none-any.whl:
Publisher:
release.yml on tim-schilling/django-salmon
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_salmon-0.1.0-py3-none-any.whl -
Subject digest:
d11553fcf3dd86b34b7885a3756a263b892083ff735cceaa55768da7e4531472 - Sigstore transparency entry: 1683160482
- Sigstore integration time:
-
Permalink:
tim-schilling/django-salmon@e1dfc99a4493516ca41e65d082422ae2ddc331aa -
Branch / Tag:
refs/tags/0.1.0 - Owner: https://github.com/tim-schilling
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e1dfc99a4493516ca41e65d082422ae2ddc331aa -
Trigger Event:
push
-
Statement type: