Skip to content
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

Add Django instrumentation #593

Merged
merged 59 commits into from
May 6, 2020
Merged
Show file tree
Hide file tree
Changes from 58 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
b5b7386
Make sure filedir is at the beginning of PYTHONPATH
ocelotl Apr 18, 2020
bfc1764
Make the tests pass
ocelotl Apr 18, 2020
3501ae1
Fix assertions
ocelotl Apr 23, 2020
3814f2c
More fixing
ocelotl Apr 23, 2020
650f048
Add lint fixes
ocelotl Apr 23, 2020
2445df5
Add more tests
ocelotl Apr 24, 2020
a6e6790
Add files
ocelotl Apr 16, 2020
854ab60
Rename files
ocelotl Apr 16, 2020
5de1006
Add tox tests
ocelotl Apr 17, 2020
f3aeca7
Rename directory
ocelotl Apr 19, 2020
d2a3e3b
Fix test case
ocelotl Apr 19, 2020
5d042ba
One test failing
ocelotl Apr 20, 2020
045eeaa
Remove response
ocelotl Apr 20, 2020
c599e0a
Add more test fixes
ocelotl Apr 20, 2020
b1fe718
Linting
ocelotl Apr 20, 2020
627fd9a
Work around old versions
ocelotl Apr 20, 2020
2372a33
Remove mention to virtual environment
ocelotl Apr 20, 2020
d1a9e59
Fixing setup
ocelotl Apr 20, 2020
d8500d1
Remove class attributes
ocelotl Apr 20, 2020
9914165
Update ext/opentelemetry-ext-django/src/opentelemetry/ext/django/__in…
ocelotl Apr 20, 2020
a54c2d7
Collect response attributes
ocelotl Apr 21, 2020
1c71a4f
Add more test fixes
ocelotl Apr 21, 2020
86354d6
Add copyright headers
ocelotl Apr 21, 2020
ca21566
Refactor testing WIP
ocelotl Apr 22, 2020
a468bbc
Add checks in process_* methods
ocelotl Apr 22, 2020
100e89b
More fixes
ocelotl Apr 23, 2020
fea5597
Lint fixes
ocelotl Apr 23, 2020
b2b7f42
Fix URL
ocelotl Apr 23, 2020
bf82666
Remove version check
ocelotl Apr 23, 2020
97f2b81
Add support for Django versions greater than 2.2
ocelotl Apr 23, 2020
5ba80ce
Adding comment regarding middleware ordering
ocelotl Apr 23, 2020
18c1ab4
Fix dependencies
ocelotl Apr 23, 2020
9ceba03
Remove raise
ocelotl Apr 25, 2020
a1a5cbb
Add documentation and gitignore
ocelotl Apr 26, 2020
b689b4e
Fix lint
ocelotl Apr 27, 2020
769fa83
Update code to latest configuration changes
ocelotl Apr 29, 2020
1b0b21f
Add docs entry
ocelotl Apr 29, 2020
b2252b1
Update Django versions
ocelotl Apr 29, 2020
7617dd6
Remove version checking
ocelotl Apr 29, 2020
7e5b1b0
Move example to docs
ocelotl Apr 30, 2020
73c4931
Added initial release
ocelotl Apr 30, 2020
62b6958
Update package name in README
ocelotl Apr 30, 2020
62a0063
Add missing copyright
ocelotl Apr 30, 2020
39af40b
Fix docstring
ocelotl Apr 30, 2020
68eb941
Remove unnecessary lines
ocelotl Apr 30, 2020
bf56249
Remove unnecessary files
ocelotl May 1, 2020
f10e451
Small improvement in documentation
ocelotl May 1, 2020
1e535cf
Remove warning
ocelotl May 1, 2020
fe1a6b5
Linking pages configuration
ocelotl May 1, 2020
27ee3e6
Update docs/examples/django/README.rst
ocelotl May 1, 2020
d1c6ec8
Update docs/examples/django/README.rst
ocelotl May 1, 2020
780ec0e
Add link to Django website
ocelotl May 1, 2020
c8b44af
Refactoring example
ocelotl May 6, 2020
3aff951
Add emphasis
ocelotl May 6, 2020
5e862e6
Use instrumentation
ocelotl May 6, 2020
5fd372b
Fixed Readme
ocelotl May 6, 2020
853c1e5
Add checks
ocelotl May 6, 2020
07af392
Make lint pass
ocelotl May 6, 2020
f6382cc
Merge branch 'master' into issue_592
toumorokoshi May 6, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
ignore =
E501 # line too long, defer to black
F401 # unused import, defer to pylint
W503 # allow line breaks after binary ops, not after
W503 # allow line breaks before binary ops
W504 # allow line breaks after binary ops
E203 # allow whitespace before ':' (https://github.com/psf/black#slices)
exclude =
.bzr
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,7 @@ _build/
# mypy
.mypy_cache/
target

# Django example

docs/examples/django/db.sqlite3
108 changes: 108 additions & 0 deletions docs/examples/django/README.rst
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
ocelotl marked this conversation as resolved.
Show resolved Hide resolved
$ 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/>`_
ocelotl marked this conversation as resolved.
Show resolved Hide resolved
* `OpenTelemetry Django extension <https://github.com/open-telemetry/opentelemetry-python/tree/master/ext/opentelemetry-ext-django>`_
45 changes: 45 additions & 0 deletions docs/examples/django/client.py
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,
lzchen marked this conversation as resolved.
Show resolved Hide resolved
# 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.
31 changes: 31 additions & 0 deletions docs/examples/django/instrumentation_example/asgi.py
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 docs/examples/django/instrumentation_example/settings.py
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/"
35 changes: 35 additions & 0 deletions docs/examples/django/instrumentation_example/urls.py
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")),
]
Loading