快速高效监控Django的链路追踪之open-telemetry)

99 阅读2分钟

本文介绍django的链路数据收集,踩了一些坑,现在分享一下接入过程。

注册观测云账号

先注册一个账号, 注册地址

注册流程很简单,按照提示点点点就完事了

安装采集器Datakit

登录观测云页面,选择「集成」 - 「DataKit」,选择适合自己环境的安装指令,复制。 我这里是linux环境,其他小伙伴可以按照提示选择对应的安装脚本。

1 复制安装指令

image.png

2 在服务器上安装 DataKit

DK_DATAWAY="https://openway.guance.com?token=**************" bash -c "$(curl -L https://static.guance.com/datakit/install.sh)"

安装完成,服务会自动启动,程序默认安装在/usr/local/datakit/

3 查询 DataKit 状态

执行命令 systemctl status datakit

4 查看数据

Datakit 安装好后,默认会采集一些数据,可在 「观测云」 - 「基础设施」 - 「主机」查看相关数据

APM接入

1 修改 inputs

在 DataKit 中修改 APM(ddtrace)的 inputs

默认不需要修改 jvm 的 inputs,仅需复制生成 conf 文件即可

$ cd /usr/local/datakit/conf.d/ddtrace/ 
$ cp ddtrace.conf.sample ddtrace.conf 
$ vim ddtrace.conf # 默认不需要修改

2 修改 Django 应用启动方式

前置条件

pip install django
pip install opentelemetry-api 
pip install opentelemetry-sdk
pip install opentelemetry-exporter-otlp-proto-http
pip install opentelemetry-instrumentation
pip install opentelemetry-instrumentation-logging
pip install opentelemetry-instrumentation-django

settings.py中配置

# https://opentelemetry.io/docs/instrumentation/python/exporters/
from opentelemetry import trace
from opentelemetry.sdk.resources import SERVICE_NAME, Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter  # http输出器
# from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter  # grpc输出器


# https://opentelemetry-python-contrib.readthedocs.io/en/latest/instrumentation/logging/logging.html#api
from opentelemetry.instrumentation.logging import LoggingInstrumentor
LoggingInstrumentor().instrument(set_logging_format=True)


resource = Resource(attributes={
    SERVICE_NAME: "django-otel-test"
})


provider = TracerProvider(resource=resource)
processor = BatchSpanProcessor(OTLPSpanExporter(endpoint="http://47.92.245.184:9529/otel/v1/trace"))  # http输出
# processor = BatchSpanProcessor(OTLPSpanExporter(endpoint="your-endpoint-here")) # grpc输出
provider.add_span_processor(processor)
trace.set_tracer_provider(provider)


from opentelemetry.instrumentation.django import DjangoInstrumentor
DjangoInstrumentor().instrument()


LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'simple': {
            'format': '%(asctime)s %(levelname)s %(filename)s:%(lineno)d trace_id=%(otelTraceID)s span_id=%(otelSpanID)s - %(message)s ',
        },
    },
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'simple',
        },
        'file': {
            'level': 'DEBUG',  # 设置日志级别
            'class': 'logging.FileHandler',  # 使用 FileHandler 处理器
            'filename': 'myapp.log',  # 日志文件名
            'formatter': 'simple',  # 使用自定义的日志格式化程序
        },
    },
    'loggers': {
        'django': {
            'handlers': ['console','file'],
            'level': 'INFO',  # 设置日志级别,可以根据需求调整
            'propagate': False,
        },
    },
}

view.py中配置

from django.shortcuts import render,HttpResponse

# Create your views here.
from opentelemetry import trace

import logging
log = logging.getLogger('django')



def test3():
    tracer = trace.get_tracer(__name__)
    with tracer.start_as_current_span("ServiceC"):
        log.error('test3')
        return True

def test2():
    tracer = trace.get_tracer(__name__)
    with tracer.start_as_current_span("ServiceB"):
        test3()
        log.error('test2')
        return True

def test1():
    tracer = trace.get_tracer(__name__)
    with tracer.start_as_current_span("ServiceD"):
        log.info('test1')
        return True

def Test(request):
    tracer = trace.get_tracer(__name__)
    with tracer.start_as_current_span("ServiceA"):
        test2()
        test1()
        log.info('Test')
        return HttpResponse('200')


def Oteltest(request):
    return render(request,'index.html')

url.py中配置

from django.contrib import admin
from django.urls import path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('test/',views.Test),
    path('otel_test/',views.Oteltest),
]

启动程序

python manage.py runserver

3 查看 APM 数据

APM 是观测云默认内置的模块,无需创建场景或视图即可进行查看。

视图示例: 通过该视图即可快速查看应用调用情况、拓扑图、异常数据等其他 APM 相关数据

image.png

image.png 调用链路的问题追踪: 可以排查接口、数据库等问题

image.png

同时支持火焰图、span列表、调用关系多种形式查看,非常nice,如果开启了profiling,还能到代码函数级别的查看。