Closed
Description
Hello,
To have better view in performance with django I added myself a few extra tools in my project.
I feel like they answer common needs, here I propose them as is.
Not sure any of these tools would be of interest to you add to this lib.
#!/usr/bin/env python
import sentry_sdk
################### A template tag to see the cost of a block before thinking about caching.
from django.template import Node
from django.template.base import token_kwargs
from django.template.loader_tags import register
class SentrySpanNode(Node):
def __init__(self, var, name, nodelist, description, data, op):
self.nodelist = nodelist
self.description = description
self.op = op
self.data = data
def __repr__(self):
return '<%s>' % self.__class__.__name__
def render(self, context):
with sentry_sdk.start_span(
op=self.op,
description=self.description
) as span:
span.set_data("data", self.data)
return self.nodelist.render(context)
@register.tag('sentryspan')
def do_start_span(parser, token):
bits = token.split_contents()
remaining_bits = bits[1:]
kwargs = token_kwargs(remaining_bits, parser)
nodelist = parser.parse(('endsentryspan',))
description = str(kwargs.get("description", "unnamed"))
data = kwargs.get("data", {})
op = str(kwargs.get("op", "render_node"))
parser.delete_first_token()
return SentrySpanNode(None, None, nodelist, description=description, data=data, op=op)
############################################################################
############## A simple decorator
from functools import wraps
def sentry_timeit(op="function", description=None):
def decorator(method):
@wraps(method)
def timed(*args, **kw):
with sentry_sdk.start_span(
op=op,
description=description or ".".join(
method.__code__.co_filename[:-3].split("/")[-1:] +
[method.__name__])
) as span:
kwargs = kw.copy()
for i, arg in enumerate(args):
kwargs[i] = arg
span.set_tag("func_name", method.__name__)
span.set_data("args", kwargs)
return method(*args, **kw)
return timed
return decorator
###################### Monkeypatch django template processing most common entries
###### edit: This feature as been implemented more expensively in PR #957 ######
# note: monkeypatching the Template.render method seems overkill as the call often cascade.
import django.shortcuts
from django.template.response import SimpleTemplateResponse
django.shortcuts.render = sentry_timeit("render")(django.shortcuts.render)
_original = SimpleTemplateResponse.rendered_content
@property
@sentry_timeit("render")
def rendered_content(self):
return _original.fget(self)
SimpleTemplateResponse.rendered_content = rendered_content
########################################