在Django项目中使用Sentry处理Python异常

随着时间的推移,用 Django 构建的 Web 应用程序会变得非常复杂,这就是集中式错误处理很重要的原因之一。本教程将指导您将免费的基本 Sentry 配置添加到新的 Django 项目。

当我们完成后,您将能够在 Sentry 仪表板中查看集中的错误报告,就像您在这个屏幕截图中看到的那样:

已捕获 Django 异常的 Sentry 仪表板。

教程要求

在本教程中,我们将使用以下依赖项,稍后我们将安装这些依赖项。确保您的环境中还安装了 Python 3,最好是 3.7 或更新版本:

我们将使用以下依赖项来完成本教程:

  • Django web framework,version 3.1
  • sentry-sdk,version 0.16.5

这篇博文中的所有代码都可以在 GitHub 上的 blog-code-examples 存储库的 sentry-handle-exceptions-django-projects 目录下的 MIT 许可下获得开源。根据您自己项目的需要使用源代码。

开发环境配置

切换到您保存 Python 虚拟环境的目录。使用以下命令为此项目创建一个新的虚拟环境。

通过使用以下命令创建一个新的虚拟环境来启动 Django 项目。我建议使用一个单独的目录,例如 ~/venvs/(波浪号是您用户的 home 目录的快捷方式),以便您始终知道所有 virtualenvs 的位置。

python3 -m venv ~/venvs/djsentry

使用 activate shell 脚本激活 virtualenv:

source ~/venvs/djsentry/bin/activate

执行上述命令后,命令提示符会发生变化,virtualenv 的名称会被添加到原始命令提示符格式的前面,因此如果您的提示符只是$,它现在看起来像下面这样:

(djsentry) $

请记住,您必须在每个要在 virtualenv 中使用依赖项的新终端窗口中激活您的 virtualenv。

我们现在可以将 Djangopackage 安装到已激活但为空的 virtualenv 中。

pip install django==3.1 sentry-sdk==0.16.5

查找类似于以下内容的输出以确认已从 PyPI 正确安装了适当的包。

(djsentry) $ pip install django==3.1 sentry-sdk==0.16.5
Collecting django
  Downloading https://files.pythonhosted.org/packages/2b/5a/4bd5624546912082a1bd2709d0edc0685f5c7827a278d806a20cf6adea28/Django-3.1-py3-none-any.whl (7.8MB)
    100% |████████████████████████████████| 7.8MB 6.3MB/s 
Collecting sentry-sdk
  Downloading https://files.pythonhosted.org/packages/f4/4c/49f899856e3a83e02bc88f2c4945aa0bda4f56b804baa9f71e6664a574a2/sentry_sdk-0.16.5-py2.py3-none-any.whl (113kB)
    100% |████████████████████████████████| 122kB 33.7MB/s 
Collecting asgiref~=3.2.10 (from django)
  Using cached https://files.pythonhosted.org/packages/d5/eb/64725b25f991010307fd18a9e0c1f0e6dff2f03622fc4bcbcdb2244f60d6/asgiref-3.2.10-py3-none-any.whl
Collecting sqlparse>=0.2.2 (from django)
  Using cached https://files.pythonhosted.org/packages/85/ee/6e821932f413a5c4b76be9c5936e313e4fc626b33f16e027866e1d60f588/sqlparse-0.3.1-py2.py3-none-any.whl
Collecting pytz (from django)
  Using cached https://files.pythonhosted.org/packages/4f/a4/879454d49688e2fad93e59d7d4efda580b783c745fd2ec2a3adf87b0808d/pytz-2020.1-py2.py3-none-any.whl
Collecting urllib3>=1.10.0 (from sentry-sdk)
  Using cached https://files.pythonhosted.org/packages/9f/f0/a391d1463ebb1b233795cabfc0ef38d3db4442339de68f847026199e69d7/urllib3-1.25.10-py2.py3-none-any.whl
Collecting certifi (from sentry-sdk)
  Using cached https://files.pythonhosted.org/packages/5e/c4/6c4fe722df5343c33226f0b4e0bb042e4dc13483228b4718baf286f86d87/certifi-2020.6.20-py2.py3-none-any.whl
Installing collected packages: asgiref, sqlparse, pytz, django, urllib3, certifi, sentry-sdk
Successfully installed asgiref-3.2.10 certifi-2020.6.20 django-3.1 pytz-2020.1 sentry-sdk-0.16.5 sqlparse-0.3.1 urllib3-1.25.10

现在我们已经安装了所有必需的依赖项,我们可以开始编写应用程序了。

编写初始应用程序

我们拥有开始构建应用程序所需的一切。

我们可以使用 Django django-admin 工具创建样板代码结构来启动我们的项目。切换到您开发应用程序的目录。例如,我通常对所有 myPython 项目使用 /Users/matt/devel/py/。然后运行以下命令启动一个名为djsentry的Django项目:

django-admin.py startproject djsentry

请注意,在本教程中,我们对 virtualenv 和 Django 项目目录使用相同的名称,但如果您更喜欢使用不同的名称来组织自己的项目。

django-admin 命令创建一个名为 djsentry 的目录以及几个您应该熟悉的子目录,如果您以前使用过 Django。

将目录更改为新项目。

cd djsentry

djsentry 中创建一个新的 Django 应用程序。

python manage.py startapp errors

Django 将为项目生成一个名为 errors 的新文件夹。我们应该更新 URL,以便在我们编写 views.py 代码之前可以访问该应用程序。

打开###。添加突出显示的行,以便 URL 解析器将检查 djsentry/djsentry/urls.py 应用程序是否有其他路由与此 Django 应用程序请求的 URL 相匹配。

# djsentry/djsentry/urls.py
from django.conf.urls import include
from django.contrib import admin
from django.urls import path


urlpatterns = [
    path('', include('errors.urls')),
    path('admin/', admin.site.urls),
]

保存djsentry/djsentry/urls.py并打开djsentry/djsentry/settings.py。将errors应用添加到settings.py 通过插入突出显示的行:

# djsentry/djsentry/settings.py
# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'errors',
]

在将任何代码部署到生产环境之前,请确保更改 DEBUG 中的默认 SECRET_KEYsettings.py 值。使用 Django 生产部署清单中的信息正确保护您的应用程序,这样您就不会将您的项目添加到网络上的被黑应用程序列表中。

保存并关闭settings.py

接下来进入djsentry/errors 目录。创建一个名为 urls.py 的新文件以包含 errors 应用程序的路由。

将所有这些行添加到空的 djsentry/errors/urls.py 文件中。

# djsentry/errors/urls.py
from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^$', views.errors_index, name="index"),
]

保存###。打开djsentry/errors/urls.py 以添加以下两个突出显示的行。您可以保留样板注释“# Create your views here”。或像往常一样删除。

# djsentry/errors/views.py
from django.shortcuts import render


def errors_index(request):
    return render(request, 'index.html', {})

接下来,在 templates app 目录下为您的模板文件创建一个名为 djmaps/maps 的目录。

mkdir templates

index.html 中创建一个名为 djsentry/errors/templates 的新文件,其中包含以下 Django 模板语言标记。

<!DOCTYPE html>
<html>
  <head>
    <title>First step for errors</title>
  </head>
  <body>
   <h1>Hello, world!</h1>
  </body>
</html>

我们可以测试这个静态页面,以确保我们所有的代码都是正确的,然后再开始将功能的主体添加到项目中。切换到 manage.py 文件所在的 Django 项目的基本目录。使用以下命令执行开发服务器:

python manage.py runserver

Django 开发服务器启动时应该没有任何问题,除了未应用的迁移警告。

Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).

You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
August 15, 2020 - 17:26:57
Django version 3.1, using settings 'djsentry.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

打开网络浏览器并转到localhost:8000

普通的旧 HTML 页面,上面写着'Hello, world!'。

我们的代码可以工作,但肯定还没有做太多事情。让我们添加 sentry-sdk,这样我们就可以了解它是如何工作的。

添加 Sentry 和 sentry-sdk 库

我们现在可以添加 Sentry 并用一堆错误测试它以确保它正常工作。

Sentry 可以自托管,也可以通过 Sentry.io 用作云服务。在本教程中,我们将使用云托管版本,因为它比设置您自己的服务器更快,而且对于较小的项目是免费的。

转到 Sentry.io 的主页。

Sentry.io 主页,您可以在其中注册一个免费帐户。

登录您的帐户或注册一个新的免费帐户。登录或完成 Sentry 注册过程后,您将进入主帐户仪表板。

我们的帐户仪表板上还没有错误记录,这符合预期,因为我们尚未将我们的帐户连接到我们的 Django 项目。

Blank Sentry 帐户仪表板。

通过单击左侧栏中的“项目”转到“项目”页面,为此应用程序创建一个新的 Sentry 项目。

创建新哨兵项目的按钮。

在“项目”页面上,单击页面右上角的“创建项目”按钮。

创建一个新的 Sentry 项目。

您可以选择“Django”或“Python”。如果我还不知道我将使用什么框架来构建我的应用程序,我通常只选择“Python”。接下来,为您的新项目命名,然后按“CreateProject”按钮。我们的新项目已准备好与我们的 Python 代码集成。

我们需要我们的帐户和项目的唯一标识符来授权我们的 Python 代码将错误发送到此 Sentry 实例。获取所需内容的最简单方法是转到 Python+Django 文档页面并阅读如何配置 SDK。

Sentry 文档准确地向您展示了连接到您的帐户需要导出的内容。

复制 init 方法的字符串参数并将其设置为环境变量,而不是将其暴露在项目代码中。

export SENTRY_DSN='https://yourkeygoeshere.ingest.sentry.io/project-number'

确保将“yourkeygoeshere”替换为您自己的唯一标识符,并将“project-number”替换为与您刚刚创建的项目匹配的 ID。

使用 SENTRY_DSN 命令检查 echo 是否在您的 shell 中正确设置:

echo $SENTRY_DSN

接下来,使用以下突出显示的新行更新 settings.py

# settings.py
import os
import sentry_sdk

from pathlib import Path
from sentry_sdk.integrations.django import DjangoIntegration


# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve(strict=True).parent.parent

STATIC_URL行之后的文件底部,添加Sentry配置:

STATIC_URL = '/static/'

sentry_sdk.init(
    dsn=os.getenv('SENTRY_DSN'),
    integrations=[DjangoIntegration()],

    # If you wish to associate users to errors (assuming you are using
    # django.contrib.auth) you may enable sending PII data.
    send_default_pii=True
)

现在我们已经完成配置,我们可以故意制造一些错误来测试与 Sentry 服务的连接。

测试哨兵的错误捕获

我们将更改一些现有代码以故意抛出异常以确保一切正常。

首先打开 errors/views.py 并用一个新的高亮行更新它,该行将在调用此函数时自动抛出一个通用异常。

# djsentry/errors/views.py
from django.shortcuts import render


def errors_index(request):
    raise Exception('testing exception')
    return render(request, 'index.html', {})

在浏览器中输入localhost:8000,运行开发服务器时你会立即得到这个异常页面:

引发异常时的 Django 开发模式调试页面。

我们还可以尝试不简单地引发异常而是在执行时肯定会创建异常的代码,例如除以零操作:

# djsentry/errors/views.py
from django.shortcuts import render


def errors_index(request):
    division_by_zero = 1 / 0
    return render(request, 'index.html', {})

异常发生时的Django开发模式调试页面。

如果这些异常都像这样出现在 Sentry 仪表板中,则您已准备就绪:

Sentry 仪表板,刚刚发生异常。

上面的异常只是一些通用的方法来测试是否一切正常以向哨兵发送错误信息。此配置还将处理您在构建 Django 项目的其余部分时可能会看到的许多其他 Django 异常。

其他资源

我们刚刚构建了一个使用 Sentry 进行集中式错误处理的 Django 项目。

接下来,尝试一些其他相关的 Django 教程:

  • 使用 django-user-visit 在 Django 中跟踪每日用户数据
  • 在带有 CDN 的 Django 模板中快速使用 Bootstrap 4
  • 如何将地图添加到 Django Web使用 Mapbox 的应用项目

如果您对本教程有任何疑问或意见,请通过 Twitter @fullstackpython 或 GitHub @mattmakai 联系我。看到这篇文章有什么问题了吗?在 GitHub 上创建此页面的源代码并提交拉取请求。

赞(0) 打赏

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏