跳转到主要内容

使用OpenTracing API的跟踪工具(http://opentracing.io)

项目描述

PyPI version Python versions Pypi Downloads Build Status Coverage Status

opentracing-python-instrumentation

一组工具,用于启用与OpenTracing API的跟踪。

模块

确保您正在运行足够的最新版本的pipsetuptools,例如,在安装您的项目需求之前执行以下操作

pip install --upgrade "setuptools>=29" "pip>=9"

模块名称是opentracing_instrumentation

内容

支持的客户端框架

以下库已在模块中进行了跟踪工具的配置

  • boto3 — Python的AWS SDK
  • Celery — 分布式任务队列
  • urllib2
  • requests
  • SQLAlchemy
  • MySQLdb
  • psycopg2
  • Tornado HTTP客户端
  • redis

限制

对于某些操作,Boto3在底层使用ThreadPoolExecutor。因此,为了使其线程安全,采用了span_in_stack_context()进行仪表化,这会强制您使用TornadoScopeManager

服务器仪表化

对于入站请求,提供了一个辅助函数before_request,用于为Flask和uWSGI等框架创建中间件。

手动仪表化

最后,提供了一个@traced_function装饰器,用于手动仪表化。

进程内上下文传播

作为OpenTracing 2.0 API的一部分,进程内Span传播通过新定义的ScopeManager接口实现。但是,为了提供向后兼容性和简化代码迁移,保留了现有功能。

span_in_context()使用当前opentracing.tracer.scope_manager实现上下文传播,预期为基于线程的ScopeManager,例如opentracing.scope_managers.ThreadLocalScopeManager

span_in_stack_context()也使用当前opentracing.tracer.scope_manager实现Tornado应用程序的上下文传播,预期为opentracing.scope_managers.tornado.TornadoScopeManager的实例。

get_current_span()返回当前活动中的Span(如果有的话)。

直接访问request_context模块以及使用RequestContextRequestContextManager已被完全弃用,因为它们无法与新的OpenTracing 2.0 API集成。与get_current_span()一起使用可以保证工作,但强烈建议切换到之前提到的函数。

用法

此库提供两种类型的仪表化:针对服务器端点的显式仪表化和针对客户端调用点的隐式仪表化。

通过创建一个初始化特定tracer实现的中间件类来仪表化服务器端点:

  1. 初始化特定的tracer实现
  2. 将传入请求处理程序包装在一个方法中,该方法从请求中读取传入的跟踪信息并创建一个新的跟踪Span

客户端调用点通过执行一系列可用的client_hooks隐式仪表化,这些hooks会猴子补丁一些常见库(如SQLAlchemyurllib2、Tornado异步HTTP客户端)中的API点。这些hooks的初始化通常也由中间件类的__init__方法完成。

以下是一个使用此库和来自opentracing-contrib的Flask仪表化的客户端-服务器示例:https://github.com/opentracing-contrib/python-flask/tree/master/example

以下是一个Clay框架的中间件示例。

from opentracing_instrumentation import span_in_context
from opentracing_instrumentation.http_server import before_request
from opentracing_instrumentation.http_server import WSGIRequestWrapper
from opentracing_instrumentation.client_hooks import install_all_patches


class TracerMiddleware(object):

    def __init__(self, app, wsgi_app):
        self.wsgi_app = wsgi_app
        self.service_name = app.name

        CONFIG.app_name = self.service_name
        CONFIG.caller_name_headers.append('X-Uber-Source')
        CONFIG.callee_endpoint_headers.append('X-Uber-Endpoint')

        install_all_patches()
        self.wsgi_app = create_wsgi_middleware(wsgi_app)
        self.init_tracer()

    def __call__(self, environ, start_response):
        return self.wsgi_app(environ, start_response)

    def init_tracer(self):
        # code specific to your tracer implementation
        pass


def create_wsgi_middleware(other_wsgi, tracer=None):
    """
    Create a wrapper middleware for another WSGI response handler.
    If tracer is not passed in, 'opentracing.tracer' is used.
    """

    def wsgi_tracing_middleware(environ, start_response):
        # TODO find out if the route can be retrieved from somewhere

        request = WSGIRequestWrapper.from_wsgi_environ(environ)
        span = before_request(request=request, tracer=tracer)

        # Wrapper around the real start_response object to log
        # additional information to opentracing Span
        def start_response_wrapper(status, response_headers, exc_info=None):
            if exc_info is not None:
                span.set_tag('error', str(exc_info))
            span.finish()

            return start_response(status, response_headers)

        with span_in_context(span):
            return other_wsgi(environ, start_response_wrapper)

    return wsgi_tracing_middleware

以下是一个基于Tornado的应用程序的中间件示例。

import opentracing
from opentracing.scope_managers.tornado import TornadoScopeManager
from opentracing_instrumentation import span_in_stack_context, http_server


opentracing.tracer = MyOpenTracingTracer(scope_manager=TornadoScopeManager())


class TracerMiddleware(object):

    def __init__(self):
        # perform initialization similar to above, including installing
        # the client_hooks

    @gen.coroutine
    def __call__(self, request, handler, next_mw):
        request_wrapper = http_server.TornadoRequestWrapper(request=request)
        span = http_server.before_request(request=request_wrapper)

        @gen.coroutine
        def next_middleware_with_span():
            yield next_mw()

        yield run_coroutine_with_span(span=span,
                                      func=next_middleware_with_span)

        span.finish()


def run_coroutine_with_span(span, func, *args, **kwargs):
    """Wrap the execution of a Tornado coroutine func in a tracing span.

    This makes the span available through the get_current_span() function.

    :param span: The tracing span to expose.
    :param func: Co-routine to execute in the scope of tracing span.
    :param args: Positional args to func, if any.
    :param kwargs: Keyword args to func, if any.
    """
    with span_in_stack_context(span):
        return func(*args, **kwargs)

定制

对于requests库,如果您想根据响应内容或某些元数据设置自定义标签到Span,可以设置response_handler_hook。hook必须是一个带有签名(response, span)的方法,其中responsespan是位置参数,因此如果需要,您可以使用不同的名称。

from opentracing_instrumentation.client_hooks.requests import patcher


def hook(response, span):
    if not response.ok:
        span.set_tag('error', 'true')


patcher.set_response_handler_hook(hook)

如果您在获取父Span时遇到问题,可以覆盖检索父Span的默认函数。

from opentracing_instrumentation.client_hooks import install_all_patches,
     set_current_span_func

set_current_span_func(my_custom_extractor_func)
install_all_patches()

开发

某些测试需要PostgreSQLRabbitMQRedisDynamoDB

docker-compose up -d

为了准备开发环境,请执行以下命令。

virtualenv env
source env/bin/activate
make bootstrap
make test

您可以使用tox运行测试。

tox

项目详情


下载文件

下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源分发

opentracing_instrumentation-3.3.1.tar.gz (26.3 kB 查看哈希)

上传时间

构建分发

opentracing_instrumentation-3.3.1-py3-none-any.whl (44.7 kB 查看哈希)

上传时间 Python 3

支持者

AWSAWS云计算和安全赞助商DatadogDatadog监控FastlyFastlyCDNGoogleGoogle下载分析MicrosoftMicrosoftPSF赞助商PingdomPingdom监控SentrySentry错误日志StatusPageStatusPage状态页面