Python的OpenTracing API。请参阅http://opentracing.io上的文档
项目描述
此库是OpenTracing的Python平台API。
阅读要求
为了理解Python平台API,必须首先熟悉OpenTracing项目和更具体术语。
状态
在当前版本中,opentracing-python仅提供API和基本no-op实现,该实现可用于由仪器库收集和传播分布式跟踪上下文。
未来版本将包括一个使用抽象的Recorder接口的参考实现,以及一个与Zipkin兼容的Tracer。
用法
仪器库的工作通常包括三个步骤
当一个服务接收到一个新的请求(通过HTTP或其他协议),它使用OpenTracing的inject/extract API来继续一个活动跟踪,在这个过程中创建一个Span对象。如果请求不包含活动跟踪,服务将启动一个新的跟踪和一个新的根 Span。
服务需要将当前Span存储在某种请求局部存储中,(称为Span 激活),在创建子Span时可以从中检索,例如在服务向另一个服务进行RPC调用的情况下。
在调用其他服务时,必须从请求局部存储中检索当前Span,创建一个子Span(例如,通过使用start_child_span()辅助函数),然后通过OpenTracing的inject/extract API将该子Span嵌入到出站请求中(例如,使用HTTP头)。
以下是对之前提到的步骤的代码示例。第2步所需的请求局部存储的具体实现取决于服务及其使用的框架/仪器库,作为ScopeManager的子项包含在Tracer.scope_manager中。详细信息见下文。
入站请求
在你的服务器请求处理程序代码中的某个地方
def handle_request(request):
span = before_request(request, opentracing.global_tracer())
# store span in some request-local storage using Tracer.scope_manager,
# using the returned `Scope` as Context Manager to ensure
# `Span` will be cleared and (in this case) `Span.finish()` be called.
with tracer.scope_manager.activate(span, True) as scope:
# actual business logic
handle_request_for_real(request)
def before_request(request, tracer):
span_context = tracer.extract(
format=Format.HTTP_HEADERS,
carrier=request.headers,
)
span = tracer.start_span(
operation_name=request.operation,
child_of=span_context)
span.set_tag('http.url', request.full_url)
remote_ip = request.remote_ip
if remote_ip:
span.set_tag(tags.PEER_HOST_IPV4, remote_ip)
caller_name = request.caller_name
if caller_name:
span.set_tag(tags.PEER_SERVICE, caller_name)
remote_port = request.remote_port
if remote_port:
span.set_tag(tags.PEER_PORT, remote_port)
return span
出站请求
在你的服务中,即将进行出站调用的某个地方
from opentracing import tags
from opentracing.propagation import Format
from opentracing_instrumentation import request_context
# create and serialize a child span and use it as context manager
with before_http_request(
request=out_request,
current_span_extractor=request_context.get_current_span):
# actual call
return urllib2.urlopen(request)
def before_http_request(request, current_span_extractor):
op = request.operation
parent_span = current_span_extractor()
outbound_span = opentracing.global_tracer().start_span(
operation_name=op,
child_of=parent_span
)
outbound_span.set_tag('http.url', request.full_url)
service_name = request.service_name
host, port = request.host_port
if service_name:
outbound_span.set_tag(tags.PEER_SERVICE, service_name)
if host:
outbound_span.set_tag(tags.PEER_HOST_IPV4, host)
if port:
outbound_span.set_tag(tags.PEER_PORT, port)
http_header_carrier = {}
opentracing.global_tracer().inject(
span_context=outbound_span,
format=Format.HTTP_HEADERS,
carrier=http_header_carrier)
for key, value in http_header_carrier.iteritems():
request.add_header(key, value)
return outbound_span
作用域和进程内传播
为了在使用的请求局部存储中获取/设置当前活动Span,OpenTracing要求每个Tracer都包含一个ScopeManager,它通过Scope提供对活动Span的访问。任何Span都可以转移到另一个任务或线程,但不能是Scope。
# Access to the active span is straightforward.
scope = tracer.scope_manager.active()
if scope is not None:
scope.span.set_tag('...', '...')
常见情况是启动一个Scope,它通过ScopeManager自动注册为进程内传播。
请注意,start_active_span('...')在Scope.close()时会自动完成span(与start_active_span('...', finish_on_close=False)不同,它不会完成)。
# Manual activation of the Span.
span = tracer.start_span(operation_name='someWork')
with tracer.scope_manager.activate(span, True) as scope:
# Do things.
# Automatic activation of the Span.
# finish_on_close is a required parameter.
with tracer.start_active_span('someWork', finish_on_close=True) as scope:
# Do things.
# Handling done through a try construct:
span = tracer.start_span(operation_name='someWork')
scope = tracer.scope_manager.activate(span, True)
try:
# Do things.
except Exception as e:
span.set_tag('error', '...')
finally:
scope.close()
如果有作用域,它将作为任何新启动的Span的父级,除非程序员在start_span()/start_active_span()时传递ignore_active_span=True或明确指定父级上下文
scope = tracer.start_active_span('someWork', ignore_active_span=True)
每个服务/框架都应该提供一个特定的ScopeManager实现,它依赖于自己的请求局部存储(线程局部存储,或适用于异步框架的基于协程的存储等)。
作用域管理器
此项目在opentracing.scope_managers子模块中包含一系列ScopeManager实现,可以根据需要导入
from opentracing.scope_managers import ThreadLocalScopeManager
存在针对thread-local(opentracing.scope_managers子模块的默认实例)、gevent、Tornado、asyncio和contextvars的实现
from opentracing.scope_managers.gevent import GeventScopeManager # requires gevent
from opentracing.scope_managers.tornado import TornadoScopeManager # requires tornado<6
from opentracing.scope_managers.asyncio import AsyncioScopeManager # fits for old asyncio applications, requires Python 3.4 or newer.
from opentracing.scope_managers.contextvars import ContextVarsScopeManager # for asyncio applications, requires Python 3.7 or newer.
注意,对于asyncio应用程序,由于自动将父span传播到子协程、任务或计划好的回调,因此最好使用ContextVarsScopeManager而不是AsyncioScopeManager。
开发
测试
virtualenv env
. ./env/bin/activate
make bootstrap
make test
您可以使用tox运行测试。
tox
测试平台套件
一个设计用于测试API更改和实验功能的测试平台套件包含在testbed目录下。有关更多信息,请参阅测试平台README。
仪器测试
本项目已实现了OpenTracing API的接口设计。包含MockTracer,以方便对OpenTracing Python工具进行单元测试。
from opentracing.mocktracer import MockTracer
tracer = MockTracer()
with tracer.start_span('someWork') as span:
pass
spans = tracer.finished_spans()
someWorkSpan = spans[0]
文档
virtualenv env
. ./env/bin/activate
make bootstrap
make docs
文档编写在 docs/_build/html。
许可证
发布
在新的版本发布之前,请将自上次版本以来的更改摘要添加到CHANGELOG.rst。
pip install zest.releaser[recommended]
prerelease
release
git push origin master --follow-tags
python setup.py sdist upload -r pypi upload_docs -r pypi
postrelease
git push
项目详情
opentracing-2.4.0.tar.gz 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | a173117e6ef580d55874734d1fa7ecb6f3655160b8b8974a2a1e98e5ec9c840d |
|
MD5 | deba55fa17f0bf0601a37e5c542ce214 |
|
BLAKE2b-256 | 51282dba4e3efb64cc59d4311081a5ddad1dde20a19b69cd0f677cdb2f2c29a6 |