如果你是一个Golang开发者,这一切都很好,但如果你使用Python呢?好吧,我的朋友,你很幸运,因为今天,我将看看如何用Python将OpenTelemetry数据发送到Lightstep。
与OTel Golang的帖子一样,我们可以通过三种方式之一将OTel数据发送到Lightstep(或者任何其他支持OpenTelemetry协议(OTLP)的Observability工具)。
在这篇文章中,我将详细介绍这三种方法中的每一种,并附上代码片段,解释如何将数据送入Lightstep Observability。让我们开始吧!
OpenTelemetry和Lightstep
Lightstep Observability支持本地OpenTelemetry协议(OTLP)。它可以通过HTTP或gRPC接收OTLP格式的数据。你需要在你的代码中指定你希望使用的方法,我们将在接下来的代码片段中看到。
如果你对OpenTelemetry使用gRPC和HTTP感到好奇,请查看这些文档。
自动仪表和Python
使用 OTel 来检测你的 Python 代码,有一件事超级酷,那就是 Python 提供了自动(auto)检测。这意味着什么呢?在高层次上,它意味着你可以运行一个Python OpenTelemetry代理,它包裹着你的Python应用程序,以自动检测它。🪄
更具体地说,自动仪表使用垫片或字节码仪表代理,在运行时或编译时拦截你的代码,为你依赖的库和框架添加跟踪和度量仪表。自动监测的好处是它需要最少的努力。坐下来,放松,享受表演。许多流行的Python库都有自动仪表功能,包括Flask和Django。你可以在这里找到完整的列表。
手动仪表需要在你的代码中添加跨度、上下文传播、属性等。这类似于对你的代码进行注释或编写测试。
这是否意味着你不应该手动检测?完全不是!这意味着你不应该手动测试。如果有自动仪器,就从自动仪器开始。如果自动仪表对你的用例来说还不够(通常是不够的),那就加入手动仪表。例如,自动仪表不知道你的业务逻辑--它只知道框架和语言--在这种情况下,你会想手动仪表你的业务逻辑,这样你就能获得这种可见性。
前提条件
在开始我们的教程之前,有一些你需要的东西。
如果你想运行完整的代码示例,你还需要。
如果你开始用OpenTelemetry来测量你的应用程序,这可能是大多数初学者最常采取的途径。顾名思义,我们是直接从我们的应用程序代码中向一个特定的Observability后端发送数据。

我们的示例应用程序是一个Flask应用程序。我们将同时利用自动和手动仪表。
下面让我们来详细了解一下。
1- 设置你的环境
让我们来设置我们的工作目录和Python虚拟环境
mkdir otel_python
cd otel_python
python3 -m venv .
source ./bin/activate
touch server.py
打开server.py ,并粘贴以下内容。
from flask import Flask, request
from opentelemetry import trace
from random import randint
tracer = trace.get_tracer_provider().get_tracer(__name__)
app = Flask(__name__)
@app.route("/rolldice")
def roll_dice():
return str(do_roll())
@tracer.start_as_current_span("do_roll")
def do_roll():
res = randint(1, 6)
current_span = trace.get_current_span()
current_span.set_attribute("roll.value", res)
current_span.set_attribute("operation.name", "Saying hello!")
current_span.set_attribute("operation.other-stuff", [1, 2, 3])
return res
if __name__ == "__main__":
app.run(port=8082, debug=True, use_reloader=False)
2- 安装所需的 OTel 库
这些是将数据发送到一个 观察力后端(例如Lightstep)。
有几个值得注意的项目。
- 安装
opentelemetry-distro将安装其他一些用于仪器化代码的依赖包,包括opentelemetry-api和opentelemetry-sdk opentelemetry-instrumentation-flask包用于对 Flask 应用程序进行自动仪表化。opentelemetry-exporter-otlp-proto-grpc包用于通过 gRPC 将 OTel 数据发送到你的 Observability 后端(例如 Lightstep)。
3- 安装自动仪表
在上面的步骤中,我们添加了opentelemetry-instrumentation-flask 库,它用于自动测量我们的 Python Flask 应用程序;但是,我们仍然缺少一块拼图。你可能还记得,在这篇文章的前面,Python的自动仪表使用了一个代理,它包装了我们的Python应用程序并自动为我们添加了一些高级仪表。这与opentelemetry-instrumentation-flask 库相结合,使这种神奇成为可能。
我们像这样安装代理。
opentelemetry-bootstrap -a install
这就安装了一个叫做opentelemetry-instrument 的二进制文件,这就是所有魔法发生的地方。
4- 运行应用程序
这里是有趣的地方!通常情况下,为了运行这个应用程序,我们会像这样运行它。
但如果我们这样做,我们就不会向Lightstep发送任何OTel数据。所以我们必须这样做。
export OTEL_EXPORTER_OTLP_TRACES_HEADERS="lightstep-access-token="
opentelemetry-instrument \
--traces_exporter console,otlp_proto_grpc \
--metrics_exporter console,otlp_proto_grpc \
--service_name test-py-auto-otlp-grpc-server \
--exporter_otlp_traces_endpoint "ingest.lightstep.com:443" \
python server.py
一些值得注意的事项。
- 用你自己的Lightstep Access Token替换 。
--traces_exporter告诉我们要把我们的痕迹发送到哪里。在这种情况下,我们要把它发送到 (stdout)和 。 选项告诉 ,我们想把它发送到一个通过gRPC接受OTLP的端点。你也可以用 代替,因为它是 的一个别名。 的可用选项的完整列表可以consoleotlp_proto_grpcotlp_proto_grpcopentelemetry-instrumentotlpotlp_proto_grpc--traces_exporter在这里找到。--exporter_otlp_traces_endpoint告诉 OTLP 端点,将我们的痕迹直接发送到 Lightstep,地址是 。opentelemetry-instrumentingest.lightstep.com:443--service_name设置我们服务的名称。这是我们将在Lightstep服务资源管理器中看到的值。- 注意,最后一行是
python server.py,这是我们运行我们的应用程序的地方。在这里,opentelemetry-instrument,包裹着对python server.py
样本输出。

想使用HTTP而不是gRPC?首先,你需要确保已经安装了pip包opentelemetry-exporter-otlp-proto-http (应该作为安装opentelemetry-exporter-otlp 的一部分自动安装)。
接下来,你的opentelemetry-instrument 命令将看起来像这样。
opentelemetry-instrument \
--traces_exporter console,otlp_proto_http \
--metrics_exporter console,otlp_proto_http \
--service_name test-py-auto-otlp-server \
--exporter_otlp_traces_endpoint "https://ingest.lightstep.com/traces/otlp/v0.9" \
python server.py
注意HTTP端点是不同的,我们在--traces_exporter 标志中使用otlp_proto_http 而不是otlp_proto_grpc 。
5- 调用/rolldice服务
打开一个新的终端窗口,并运行以下内容。
curl http://localhost:8082/rolldice
运行上面这一行将返回一个1到6之间的随机数字。没有什么太突出的地方。但如果你看一下server.py 的终端窗口,你会注意到输出中的一些东西。

我们看到了来自server.py 的跟踪!为什么我们会在这里看到这个?因为我们把--traces_exporter 标志设置为console,otlp_proto_grpc ,它通过 OTLP 输出到 Lightstep并输出到控制台。
6- 在Lightstep中看到它

OpenTelemetry收集器
向 Observability 后端发送数据的下一个方法是通过OpenTelemetry Collector。对于非开发设置,这是将 OpenTelemetry 数据发送到 Observability 后端的推荐方法。

通过 OTel 采集器发送 OTel 数据与我们在上述直接来自应用程序的示例中的做法几乎相同。唯一的区别是。
- 我们需要运行一个 OTel 采集器
- 当我们运行
opentelemetry-instrument,我们的选项略有不同
让我们在下面更详细地了解一下。
1- 按照 "直接来自应用程序"的例子中的步骤1-3进行操作
2- 运行收集器
首先,我们需要配置我们的收集器,以便向Lightstep发送数据。我们通过从Lightstep的opentelemetry-examples repo中抓取collector.yml 来做到这一点。
git clone git@github.com:lightstep/opentelemetry-examples.git
打开一个新的终端窗口。首先,你需要编辑collector.yml 文件。请确保用你自己的Lightstep访问令牌替换${LIGHTSTEP_ACCESS_TOKEN} 。
现在你可以启动采集器了。
cd opentelemetry-examples/collector/vanilla
docker run -it --rm -p 4317:4317 -p 4318:4318 \
-v $(pwd)/collector.yml:/otel-config.yaml \
--name otelcol otel/opentelemetry-collector-contrib:0.53.0 \
"/otelcol-contrib" \
"--config=otel-config.yaml"
样本输出。

3- 运行该应用程序
opentelemetry-instrument \
--traces_exporter console,otlp \
--metrics_exporter console,otlp \
--service_name test-py-auto-collector-server \
python server_uninstrumented.py
一些值得注意的事项。
- 上面的命令与我们的Direct from Application例子非常相似,只是我们缺少了
--exporter_otlp_endpoint选项。这是因为如果我们漏掉这个选项,那么opentelemetry-instrument就会假定它正在连接到 OTel Collector 的端点localhost:4317。 - 我们不需要设置
OTEL_EXPORTER_OTLP_TRACES_HEADERS,因为这已经在采集器的config.yml文件中配置好了。 - 如果你希望使用 HTTP 而不是 gRPC,你需要用
--traces_exporter console,otlp_proto_http替换--traces_exporter console,otlp。注意,otlp是otlp_proto_grpc的一个别名。
输出示例。

4- 调用/rolldice服务
打开一个新的终端窗口,并运行以下程序。
curl http://localhost:8082/rolldice
样本输出。

同样,我们看到了server.py 的跟踪,因为我们把 --traces_exporter 标志设置为 console,otlp,它通过 OTLP 输出到采集器和控制台。
5- 在Lightstep中看到它

启动器
如果你认为向Lightstep发送OTel数据很容易,那么通过OTel Python Launcher就更容易了!你可以把它看作是一个OTel包装。可以把它看作是一个OTel包装器,通过为你预先配置一堆东西来降低入门门槛,使发送数据到Lightstep变得特别容易。
通过Launcher发送OTel数据与我们在上面的Direct from Application例子中所做的几乎相同,但有一些小的区别。
- 我们有更少的包来(耶!)。
- 当我们运行
opentelemetry-instrument,我们的选项略有不同
让我们看看它的运行情况吧?
1- 按照 "直接来自应用程序"的例子的步骤1-3进行操作
小改动:用这些替换步骤2中的库。
# OTel-specific
pip install opentelemetry-launcher
pip install protobuf==3.20.1
# App-specific
pip install requests
pip install flask
我们需要强制使用一个特定版本的protobuf ,因为Launcher与新版本的兼容性问题。这在opentelemetry-python中已经被修复。
当我们安装opentelemetry-launcher 包的时候,它也会起到双重作用,不需要我们运行opentelemetry-bootstrap -a install 。
2- 运行该应用程序
export LS_ACCESS_TOKEN=""
opentelemetry-instrument \
--service_name test-py-auto-launcher-server \
python server.py
看起来我们的选择比较少,不是吗?让我们深入了解一下一些值得注意的事项。
- 我们不需要指定一个
--exporter_otlp_traces_endpoint,因为这已经隐含地为我们做了,并设置为ingest.lightstep.com:443。 - 我们不需要为我们的Lightstep Access Token(
export OTEL_EXPORTER_OTLP_TRACES_HEADERS="lightstep-access-token=")设置一个看起来很乱的环境变量,而只需要这样做。export LS_ACCESS_TOKEN="",这看起来更干净。
如果你希望首先通过一个采集器实例发送你的OTel数据,而不是直接从你的应用程序发送,你可以这样做。
opentelemetry-instrument \
--service_name test-py-auto-launcher-server \
--exporter_otlp_traces_endpoint "0.0.0.0:4317" \
--exporter_otlp_traces_insecure true \
python server.py
请注意我们不必设置LS_ACCESS_TOKEN ,因为这已经在采集器的config.yml文件中配置好了。只要确保你有一个正在运行的OTel收集器实例就可以了
另外,一定要设置--exporter_otlp_traces_insecure true 。如果你使用收集器并隐式配置它,这是必需的,就像我们在这里做的那样。只有在采集器中没有配置证书的情况下才需要这样做。
输出样本。

3- 调用/rolldice服务
打开一个新的终端窗口,并运行以下程序。
curl http://localhost:8082/rolldice
样本输出。

请注意,由于我们的opentelemetry-instrument 调用没有指定一个--traces_exporter ,它相当于说--traces_exporter otlp_proto_grpc 。我也意味着没有跟踪输出到控制台(stdout)。
4- 在Lightstep中看到它

我应该总是使用自动仪表代理吗?
即使你使用的Python库没有自动仪表代理,opentelemetry-instrument 仍然有帮助吗?我个人认为是的!考虑一下这个文件,client.py 。
from sys import argv
from requests import get
from opentelemetry import trace
from opentelemetry.propagate import inject
tracer = trace.get_tracer_provider().get_tracer(__name__)
assert len(argv) == 2
with tracer.start_as_current_span("client"):
with tracer.start_as_current_span("client-server"):
headers = {}
inject(headers)
requested = get(
"http://localhost:8082/rolldice",
params={"param": argv[1]},
headers=headers,
)
assert requested.status_code == 200
让我们用自动仪表代理来运行上面的程序。请确保用你自己的Lightstep Access Token替换 。
export OTEL_EXPORTER_OTLP_TRACES_HEADERS="lightstep-access-token="
opentelemetry-instrument \
--traces_exporter console,otlp \
--service_name test-py-auto-client \
--exporter_otlp_endpoint "ingest.lightstep.com:443" \
python client.py test
请注意,除了在client.py 中创建跨度之外,里面没有 OTEL 配置。你不需要配置服务名称、输出器或端点。这些都是在你运行opentelemetry-instrument 时处理的。另外,如果你的代码恰好使用了一个自动指示的库,你就不必再做任何其他事情了。
***注意。***如果你想知道为什么我们要执行
python client.py test这个命令,那是因为client.py需要一个参数,在这个例子中,这个参数叫做test。
gRPC调试
你有没有想过你的gRPC调用是否进入了一个黑洞?我肯定会这么想。当我在为 Golang OTel 库的 gRPC 忙活时,我了解到一些 gRPC 调试标志,这些标志可以使我在排除 gRPC 连接问题时更加容易。这当然让我想知道是否有类似的 Python。结果是有的。在运行你的应用程序之前设置这些环境变量,你就可以了。
export GRPC_VERBOSITY=debug
export GRPC_TRACE=http,call_error,connectivity_state
这意味着,当我们启动我们的server.py ,我们会得到这样的结果。

然后当我们通过curl 调用我们的端点时,我们得到这样的结果。

上面突出显示的部分告诉我,我们的gRPC调用成功了!
最后的思考
在Python中的自动测量是非常可怕的,它真的降低了OpenTelemetry的入门门槛。正如我们所看到的直接来自应用和采集器的例子,代码几乎保持不变。唯一的区别是,你需要改变一些标志,以便自动监测代理知道把你的痕迹发送到哪里。很好,很简单!
如果你想知道,还有一种完全纯粹的OTel Python手动仪表方法,我将在未来的博文中介绍,敬请期待现在,让我们沉浸在你今天学到的关于 OTel Python 自动仪表的超酷知识中吧