-
Notifications
You must be signed in to change notification settings - Fork 705
Adding metric collection as part of instrumentations - Django #1230
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
Changes from 8 commits
89b4e6b
e869641
fb59669
585ca48
ad5bf9a
1e71ed5
ccfba2f
24cf8ff
b2bf957
6255c94
720ed3a
f25d2d8
4790aec
8bd1a61
1111bc6
a68ab76
3134979
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 | ||||
---|---|---|---|---|---|---|
|
@@ -12,8 +12,11 @@ | |||||
# See the License for the specific language governing permissions and | ||||||
# limitations under the License. | ||||||
|
||||||
import time | ||||||
from logging import getLogger | ||||||
|
||||||
from django.conf import settings | ||||||
|
||||||
from opentelemetry.configuration import Configuration | ||||||
from opentelemetry.context import attach, detach | ||||||
from opentelemetry.instrumentation.django.version import __version__ | ||||||
|
@@ -44,8 +47,7 @@ | |||||
|
||||||
|
||||||
class _DjangoMiddleware(MiddlewareMixin): | ||||||
"""Django Middleware for OpenTelemetry | ||||||
""" | ||||||
"""Django Middleware for OpenTelemetry""" | ||||||
|
||||||
_environ_activation_key = ( | ||||||
"opentelemetry-instrumentor-django.activation_key" | ||||||
|
@@ -88,6 +90,32 @@ def _get_span_name(request): | |||||
except Resolver404: | ||||||
return "HTTP {}".format(request.method) | ||||||
|
||||||
@staticmethod | ||||||
def _get_metric_labels_from_attributes(attributes): | ||||||
lzchen marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
labels = {} | ||||||
labels["http.method"] = attributes.get("http.method", "") | ||||||
if attributes.get("http.url"): | ||||||
labels["http.url"] = attributes.get("http.url") | ||||||
elif attributes.get("http.scheme"): | ||||||
labels["http.scheme"] = attributes.get("http.scheme") | ||||||
if attributes.get("http.target"): | ||||||
labels["http.target"] = attributes.get("http.target") | ||||||
if attributes.get("http.host"): | ||||||
labels["http.host"] = attributes.get("http.host") | ||||||
elif attributes.get("net.host.port"): | ||||||
labels["net.host.port"] = attributes.get("net.host.port") | ||||||
if attributes.get("http.server_name"): | ||||||
labels["http.server_name"] = attributes.get( | ||||||
"http.server_name" | ||||||
) | ||||||
elif attributes.get("http.host.name"): | ||||||
labels["http.host.name"] = attributes.get( | ||||||
"http.host.name" | ||||||
) | ||||||
if attributes.get("http.flavor"): | ||||||
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. This may have the same problem.
Suggested change
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. I don't believe we want to set the label if value is an empty string. 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. Nevertheless, we may end up setting the label when the value is an empty string here? 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. I think |
||||||
labels["http.flavor"] = attributes.get("http.flavor") | ||||||
return labels | ||||||
|
||||||
def process_request(self, request): | ||||||
# request.META is a dictionary containing all available HTTP headers | ||||||
# Read more about request.META here: | ||||||
|
@@ -96,6 +124,8 @@ def process_request(self, request): | |||||
if self._excluded_urls.url_disabled(request.build_absolute_uri("?")): | ||||||
return | ||||||
|
||||||
request.start_time = time.time() | ||||||
lzchen marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
||||||
environ = request.META | ||||||
|
||||||
token = attach(extract(get_header_from_environ, environ)) | ||||||
|
@@ -110,8 +140,10 @@ def process_request(self, request): | |||||
), | ||||||
) | ||||||
|
||||||
attributes = collect_request_attributes(environ) | ||||||
request.labels = self._get_metric_labels_from_attributes(attributes) | ||||||
|
||||||
if span.is_recording(): | ||||||
attributes = collect_request_attributes(environ) | ||||||
attributes = extract_attributes_from_object( | ||||||
request, self._traced_request_attrs, attributes | ||||||
) | ||||||
|
@@ -156,6 +188,7 @@ def process_response(self, request, response): | |||||
"{} {}".format(response.status_code, response.reason_phrase), | ||||||
response, | ||||||
) | ||||||
request.labels["http.status_code"] = str(response.status_code) | ||||||
request.META.pop(self._environ_span_key) | ||||||
|
||||||
request.META[self._environ_activation_key].__exit__( | ||||||
|
@@ -167,4 +200,13 @@ def process_response(self, request, response): | |||||
detach(request.environ.get(self._environ_token)) | ||||||
request.META.pop(self._environ_token) | ||||||
|
||||||
try: | ||||||
metric_recorder = getattr(settings, "OTEL_METRIC_RECORDER", None) | ||||||
if metric_recorder: | ||||||
lzchen marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
metric_recorder.record_server_duration_range( | ||||||
request.start_time, time.time(), request.labels | ||||||
) | ||||||
except Exception as ex: # pylint: disable=W0703 | ||||||
_logger.warning("Error recording duration metrics: %s", ex) | ||||||
|
||||||
return response |
Uh oh!
There was an error while loading. Please reload this page.