概述
OpenTelemetry 是一组标准和工具的集合,旨在管理观测类数据,如 trace、metrics、logs 等 (未来可能有新的观测类数据类型出现)。
OpenTelemetry 提供与 vendor 无关的实现,根据用户的需要将观测类数据导出到不同的后端,如开源的 Prometheus、Jaeger 或云厂商的服务中。
本文介绍 opentelemetry 在 python 应用中的使用和运行机制。
示例
文档:https://opentelemetry-python.readthedocs.io/en/latest/examples/auto-instrumentation/README.html
安装好相关的依赖:
$ pip install opentelemetry-sdk
$ pip install opentelemetry-instrumentation
$ pip install opentelemetry-instrumentation-flask
$ pip install flask
$ pip install requests
启动应用程序:opentelemetry-instrument python server_uninstrumented.py
应用程序仅需要进行简单的trace初始化,不需任何的手工instrument,或者创建span的代码。opentelemetry-instrumentation-flask库会自动插入处理trace的相关逻辑。
from flask import Flask, request
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import (
BatchSpanProcessor,
ConsoleSpanExporter,
)
app = Flask(__name__)
trace.set_tracer_provider(TracerProvider())
trace.get_tracer_provider().add_span_processor(
BatchSpanProcessor(ConsoleSpanExporter())
)
@app.route("/server_request")
def server_request():
print(request.args.get("param"))
return "served"
if __name__ == "__main__":
app.run(port=8082)
opentelemetry-instrument命令
上面示例中使用了 opentelemetry-instrument 命令进行应用程序启用,那么 opentelemetry-instrument 的作用是什么呢?
opentelemetry-instrument核心功能是将 sitecustomize 模块的路径添加到PYTHONPATH头部,以便sitecustomize可以再程序启动时被执行。
这个脚本的代码:
import re
import sys
from opentelemetry.instrumentation.auto_instrumentation import run
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(run())
它主要是调用auto_instrumentation的run
函数,在run函数中主要是解析参数,设置环境变量,最重要的环境变量为PYTHONPATH,他将opentelemetry.instrumentation.auto_instrumentation添加为 PYTHONPATH 的头部。
sitecustomize
sitecustomize机制用于解决python启动时自动执行instrument的问题。
在opentelemetry.instrumentation.auto_instrumentation 目录下有一个 sitecustomize.py文件,这个文件中的内容就是auto_instrumentation的处理逻辑。那么sitecustomize是何时调用的呢?site模块会在初始化阶段自动导入,详细请查看:https://docs.python.org/3/library/site.html
在sitecustomize中会通过pkg_resources.iter_entry_points扫描 opentelemetry_instrumentor 加载那些已经安装的instrumentor,比如:django、flask等。
entry_points
entry_points机制用于解决如何自动找到依赖库的instrumentation库
例如:
opentelemetry-instrumentation-django
[options.entry_points]
opentelemetry_instrumentor =
django = opentelemetry.instrumentation.django:DjangoInstrumentor
文档:
distro
上面的示例中,应用程序还需要自己进行 TracerProvider 的初始化,否则不会输出任何span记录。那么是否可以由 opentelemetry-instrument 完成这部分工作呢?
可以的,distro就是用于解决初始化TracerProvider和配置SpanExporter的问题的。
在sitecustomize 中加载的entry_points除了opentelemetry_instrumentor还有 opentelemetry_distro和opentelemetry_configurator。
[options.entry_points]
opentelemetry_distro =
distro = opentelemetry.distro:OpenTelemetryDistro
opentelemetry_configurator =
configurator = opentelemetry.distro:OpenTelemetryConfigurator
从上面的setup.cfg可以知道opentelemetry-distro
会增加opentelemetry_distro 和 opentelemetry_configurator 两个entry_points。
代码如下:
import os
from opentelemetry.environment_variables import OTEL_TRACES_EXPORTER
from opentelemetry.instrumentation.distro import BaseDistro
from opentelemetry.sdk._configuration import _OTelSDKConfigurator
class OpenTelemetryConfigurator(_OTelSDKConfigurator):
pass
class OpenTelemetryDistro(BaseDistro):
"""
The OpenTelemetry provided Distro configures a default set of
configuration out of the box.
"""
# pylint: disable=no-self-use
def _configure(self, **kwargs):
os.environ.setdefault(OTEL_TRACES_EXPORTER, "otlp_proto_grpc_span")
OpenTelemetryDistro 区别于 DefaultDistro 仅仅是设置了默认的 “OTEL_TRACES_EXPORTER”环境变量。
而 OpenTelemetryConfigurator 的作用就是进行trace初始化(完成 TracerProvider的设置),代码如下:
def _init_tracing(
exporters: Sequence[SpanExporter], id_generator: IdGenerator
):
# if env var OTEL_RESOURCE_ATTRIBUTES is given, it will read the service_name
# from the env variable else defaults to "unknown_service"
provider = TracerProvider(
id_generator=id_generator(),
)
trace.set_tracer_provider(provider)
for _, exporter_class in exporters.items():
exporter_args = {}
provider.add_span_processor(
BatchSpanProcessor(exporter_class(**exporter_args))
)
综上
安装以下库:
$ pip install opentelemetry-sdk
$ pip install opentelemetry-instrumentation
$ pip install opentelemetry-instrumentation-flask
$ pip install opentelemetry-distro
$ pip install opentelemetry-exporter-otlp
应用程序代码如下:
from flask import Flask, request
app = Flask(__name__)
@app.route("/server_request")
def server_request():
print(request.args.get("param"))
return "served"
if __name__ == "__main__":
app.run(port=8082)
启动opentelemetry-collector:
docker run -p 4317:4317 \
-v /tmp/otel-collector-config.yaml:/etc/otel-collector-config.yaml \
otel/opentelemetry-collector:latest \
--config=/etc/otel-collector-config.yaml
运行应用程序:
opentelemetry-instrument python server.py
运行客户端程序:
python client.py testing
测试结果:opentelemetry-collector会输出收到的span
这样整个应用程序就完全不需要写任何代码了。
版权申明
本文转载于【Timmy Yuan 伏特加空间】5分钟实现用docker搭建Redis集群模式和哨兵模式,仅用于学习,版权归作者所有,如有侵权烦请告知,我会立即删除并表示歉意,联系邮箱。