使用OpenTracing API的跟踪工具(http://opentracing.io)
项目描述
opentracing-python-instrumentation
一组工具,用于启用与OpenTracing API的跟踪。
模块
确保您正在运行足够的最新版本的pip
和setuptools
,例如,在安装您的项目需求之前执行以下操作
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
模块以及使用RequestContext
和RequestContextManager
已被完全弃用,因为它们无法与新的OpenTracing 2.0 API集成。与get_current_span()
一起使用可以保证工作,但强烈建议切换到之前提到的函数。
用法
此库提供两种类型的仪表化:针对服务器端点的显式仪表化和针对客户端调用点的隐式仪表化。
通过创建一个初始化特定tracer实现的中间件类来仪表化服务器端点:
- 初始化特定的tracer实现
- 将传入请求处理程序包装在一个方法中,该方法从请求中读取传入的跟踪信息并创建一个新的跟踪Span
客户端调用点通过执行一系列可用的client_hooks
隐式仪表化,这些hooks会猴子补丁一些常见库(如SQLAlchemy
、urllib2
、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)
的方法,其中response
和span
是位置参数,因此如果需要,您可以使用不同的名称。
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()
开发
某些测试需要PostgreSQL
、RabbitMQ
、Redis
和DynamoDB
。
docker-compose up -d
为了准备开发环境,请执行以下命令。
virtualenv env
source env/bin/activate
make bootstrap
make test
您可以使用tox运行测试。
tox
项目详情
下载文件
下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。
源分发
构建分发
opentracing_instrumentation-3.3.1.tar.gz的哈希
算法 | 哈希摘要 | |
---|---|---|
SHA256 | d94801aebab95b7e8f3eeb80ee0e5e886ad4f1761bcadff9b5d1d3d04560c04a |
|
MD5 | 10ef00d5b435738479140ae0bae983ac |
|
BLAKE2b-256 | 839103713e8c173d4792cb9dfac9411a739ad64f71f00de44d27b2f9a2e42fcb |
opentracing_instrumentation-3.3.1-py3-none-any.whl的哈希
算法 | 哈希摘要 | |
---|---|---|
SHA256 | ae9b48a5b6e47189887fff9785230b13141659bb3bf3e2700e4c7470ae5d27b4 |
|
MD5 | 967aedf8f35f6139f59b46ecc2df3e46 |
|
BLAKE2b-256 | 71cec065bb33a7aa280eb0aabe770970cf42dc8f373657373879a29746492431 |