forked from open-telemetry/opentelemetry-python
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Django instrumentation (open-telemetry#593)
Initial Instrumentation Co-authored-by: Mauricio Vásquez <[email protected]> Co-authored-by: Mathieu Hinderyckx <[email protected]> Co-authored-by: alrex <[email protected]> Co-authored-by: Yusuke Tsutsumi <[email protected]>
- Loading branch information
1 parent
b5d051e
commit 7580c24
Showing
28 changed files
with
984 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -56,3 +56,7 @@ _build/ | |
# mypy | ||
.mypy_cache/ | ||
target | ||
|
||
# Django example | ||
|
||
docs/examples/django/db.sqlite3 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
OpenTelemetry Django Instrumentation Example | ||
============================================ | ||
|
||
This shows how to use `opentelemetry-ext-django` to automatically instrument a | ||
Django app. | ||
|
||
For more user convenience, a Django app is already provided in this directory. | ||
|
||
Preparation | ||
----------- | ||
|
||
This example will be executed in a separate virtual environment: | ||
|
||
.. code-block:: | ||
$ mkdir django_auto_instrumentation | ||
$ virtualenv django_auto_instrumentation | ||
$ source django_auto_instrumentation/bin/activate | ||
Installation | ||
------------ | ||
|
||
.. code-block:: | ||
$ pip install opentelemetry-sdk | ||
$ pip install opentelemetry-ext-django | ||
$ pip install requests | ||
Execution | ||
--------- | ||
|
||
Execution of the Django app | ||
........................... | ||
|
||
Set these environment variables first: | ||
|
||
#. `export OPENTELEMETRY_PYTHON_DJANGO_INSTRUMENT=True` | ||
#. `export DJANGO_SETTINGS_MODULE=instrumentation_example.settings` | ||
|
||
The way to achieve OpenTelemetry instrumentation for your Django app is to use | ||
an `opentelemetry.ext.django.DjangoInstrumentor` to instrument the app. | ||
|
||
Clone the `opentelemetry-python` repository and go to `opentelemetry-python/docs/examples/django`. | ||
|
||
Once there, open the `manage.py` file. The call to `DjangoInstrumentor().instrument()` | ||
in `main` is all that is needed to make the app be instrumented. | ||
|
||
Run the Django app with `python manage.py runserver`. | ||
|
||
Execution of the client | ||
....................... | ||
|
||
Open up a new console and activate the previous virtual environment there too: | ||
|
||
`source django_auto_instrumentation/bin/activate` | ||
|
||
Go to `opentelemetry-python/ext/opentelemetry-ext-django/example`, once there | ||
run the client with: | ||
|
||
`python client.py hello` | ||
|
||
Go to the previous console, where the Django app is running. You should see | ||
output similar to this one: | ||
|
||
.. code-block:: | ||
{ | ||
"name": "home_page_view", | ||
"context": { | ||
"trace_id": "0xed88755c56d95d05a506f5f70e7849b9", | ||
"span_id": "0x0a94c7a60e0650d5", | ||
"trace_state": "{}" | ||
}, | ||
"kind": "SpanKind.SERVER", | ||
"parent_id": "0x3096ef92e621c22d", | ||
"start_time": "2020-04-26T01:49:57.205833Z", | ||
"end_time": "2020-04-26T01:49:57.206214Z", | ||
"status": { | ||
"canonical_code": "OK" | ||
}, | ||
"attributes": { | ||
"component": "http", | ||
"http.method": "GET", | ||
"http.server_name": "localhost", | ||
"http.scheme": "http", | ||
"host.port": 8000, | ||
"http.host": "localhost:8000", | ||
"http.url": "http://localhost:8000/?param=hello", | ||
"net.peer.ip": "127.0.0.1", | ||
"http.flavor": "1.1", | ||
"http.status_text": "OK", | ||
"http.status_code": 200 | ||
}, | ||
"events": [], | ||
"links": [] | ||
} | ||
The last output shows spans automatically generated by the OpenTelemetry Django | ||
Instrumentation package. | ||
|
||
References | ||
---------- | ||
|
||
* `Django <https://djangoproject.com/>`_ | ||
* `OpenTelemetry Project <https://opentelemetry.io/>`_ | ||
* `OpenTelemetry Django extension <https://github.com/open-telemetry/opentelemetry-python/tree/master/ext/opentelemetry-ext-django>`_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
# Copyright The OpenTelemetry Authors | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
from sys import argv | ||
|
||
from requests import get | ||
|
||
from opentelemetry import propagators, trace | ||
from opentelemetry.sdk.trace import TracerProvider | ||
from opentelemetry.sdk.trace.export import ( | ||
ConsoleSpanExporter, | ||
SimpleExportSpanProcessor, | ||
) | ||
|
||
trace.set_tracer_provider(TracerProvider()) | ||
tracer = trace.get_tracer_provider().get_tracer(__name__) | ||
|
||
trace.get_tracer_provider().add_span_processor( | ||
SimpleExportSpanProcessor(ConsoleSpanExporter()) | ||
) | ||
|
||
|
||
with tracer.start_as_current_span("client"): | ||
|
||
with tracer.start_as_current_span("client-server"): | ||
headers = {} | ||
propagators.inject(dict.__setitem__, headers) | ||
requested = get( | ||
"http://localhost:8000", | ||
params={"param": argv[1]}, | ||
headers=headers, | ||
) | ||
|
||
assert requested.status_code == 200 |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Copyright The OpenTelemetry Authors | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
""" | ||
ASGI config for instrumentation_example project. | ||
It exposes the ASGI callable as a module-level variable named ``application``. | ||
For more information on this file, see | ||
https://docs.djangoproject.com/en/3.0/howto/deployment/asgi/ | ||
""" | ||
|
||
import os | ||
|
||
from django.core.asgi import get_asgi_application | ||
|
||
os.environ.setdefault( | ||
"DJANGO_SETTINGS_MODULE", "instrumentation_example.settings" | ||
) | ||
|
||
application = get_asgi_application() |
133 changes: 133 additions & 0 deletions
133
docs/examples/django/instrumentation_example/settings.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
# Copyright The OpenTelemetry Authors | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
""" | ||
Django settings for instrumentation_example project. | ||
Generated by "django-admin startproject" using Django 3.0.4. | ||
For more information on this file, see | ||
https://docs.djangoproject.com/en/3.0/topics/settings/ | ||
For the full list of settings and their values, see | ||
https://docs.djangoproject.com/en/3.0/ref/settings/ | ||
""" | ||
|
||
import os | ||
|
||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...) | ||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | ||
|
||
|
||
# Quick-start development settings - unsuitable for production | ||
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/ | ||
|
||
# SECURITY WARNING: keep the secret key used in production secret! | ||
SECRET_KEY = "it%*!=l2(fcawu=!m-06n&#j(iq2j#%$fu6)myi*b9i5ojk+6+" | ||
|
||
# SECURITY WARNING: don"t run with debug turned on in production! | ||
DEBUG = True | ||
|
||
ALLOWED_HOSTS = [] | ||
|
||
|
||
# Application definition | ||
|
||
INSTALLED_APPS = [ | ||
"django.contrib.admin", | ||
"django.contrib.auth", | ||
"django.contrib.contenttypes", | ||
"django.contrib.sessions", | ||
"django.contrib.messages", | ||
"django.contrib.staticfiles", | ||
] | ||
|
||
MIDDLEWARE = [ | ||
"django.middleware.security.SecurityMiddleware", | ||
"django.contrib.sessions.middleware.SessionMiddleware", | ||
"django.middleware.common.CommonMiddleware", | ||
"django.middleware.csrf.CsrfViewMiddleware", | ||
"django.contrib.auth.middleware.AuthenticationMiddleware", | ||
"django.contrib.messages.middleware.MessageMiddleware", | ||
"django.middleware.clickjacking.XFrameOptionsMiddleware", | ||
] | ||
|
||
ROOT_URLCONF = "instrumentation_example.urls" | ||
|
||
TEMPLATES = [ | ||
{ | ||
"BACKEND": "django.template.backends.django.DjangoTemplates", | ||
"DIRS": [], | ||
"APP_DIRS": True, | ||
"OPTIONS": { | ||
"context_processors": [ | ||
"django.template.context_processors.debug", | ||
"django.template.context_processors.request", | ||
"django.contrib.auth.context_processors.auth", | ||
"django.contrib.messages.context_processors.messages", | ||
], | ||
}, | ||
}, | ||
] | ||
|
||
WSGI_APPLICATION = "instrumentation_example.wsgi.application" | ||
|
||
|
||
# Database | ||
# https://docs.djangoproject.com/en/3.0/ref/settings/#databases | ||
|
||
DATABASES = { | ||
"default": { | ||
"ENGINE": "django.db.backends.sqlite3", | ||
"NAME": os.path.join(BASE_DIR, "db.sqlite3"), | ||
} | ||
} | ||
|
||
|
||
# Password validation | ||
# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators | ||
|
||
AUTH_PASSWORD_VALIDATORS = [ | ||
{ | ||
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", | ||
}, | ||
{ | ||
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", | ||
}, | ||
{ | ||
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", | ||
}, | ||
{ | ||
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", | ||
}, | ||
] | ||
|
||
|
||
# Internationalization | ||
# https://docs.djangoproject.com/en/3.0/topics/i18n/ | ||
|
||
LANGUAGE_CODE = "en-us" | ||
|
||
TIME_ZONE = "UTC" | ||
|
||
USE_I18N = True | ||
|
||
USE_L10N = True | ||
|
||
USE_TZ = True | ||
|
||
|
||
# Static files (CSS, JavaScript, Images) | ||
# https://docs.djangoproject.com/en/3.0/howto/static-files/ | ||
|
||
STATIC_URL = "/static/" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# Copyright The OpenTelemetry Authors | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
"""instrumentation_example URL Configuration | ||
The `urlpatterns` list routes URLs to views. For more information please see: | ||
https://docs.djangoproject.com/en/3.0/topics/http/urls/ | ||
Examples: | ||
Function views | ||
1. Add an import: from my_app import views | ||
2. Add a URL to urlpatterns: path("", views.home, name="home") | ||
Class-based views | ||
1. Add an import: from other_app.views import Home | ||
2. Add a URL to urlpatterns: path("", Home.as_view(), name="home") | ||
Including another URLconf | ||
1. Import the include() function: from django.urls import include, path | ||
2. Add a URL to urlpatterns: path("blog/", include("blog.urls")) | ||
""" | ||
from django.contrib import admin | ||
from django.urls import include, path | ||
|
||
urlpatterns = [ | ||
path("admin/", admin.site.urls), | ||
path("", include("pages.urls")), | ||
] |
Oops, something went wrong.