Python + OpenTelemetry,观测你的特斯拉!
本样例较长,将分为两个部分,此文为第 1 部分:从 Tesla Owner API 导出指标到 Greptime。
项目概述
OpenTelemetry 作为一套行业领先的监控应用和网络的统一标准,能帮助开发者轻松捕获和跟踪关键数据,深入了解系统的运行状态。如果你还不太了解 OpenTelemetry 及其应用场景,可以参考我们之前的博文,了解相关基础知识。
本篇文章详细展示了使用 OpenTelemetry 监控 Tesla Model 3 的充电与驾驶数据的例子。该项目流程相对简洁:通过 OpenTelemetry 对 Python 服务进行监控,并连接 Tesla Owner API,每 5 分钟收集一次指标数据。此外,项目还包含一个使用 Docker 托管的 GreptimeDB 实例,作为这个监控应用程序的目标数据库,用于接收并存储导出的指标数据。
(图 1:数据监控流程图)
应用程序的设置
首先,从 Greptime 的 demo 仓库中下载相关代码:
该项目通过将 Python 服务部署在其专属的 Docker 容器中,以最少的依赖运行。因此,如果还未安装 Docker,需要先安装 Docker。
通过以下命令验证 Docker 是否已正确安装:
设置 Python 环境
如果希望直接在本地运行代码而不使用 Docker,请确保正确设置 Python 环境:
设置 Python 依赖管理系统:Poetry
设置 Python 版本管理系统:pyenv
使用命令下载 Python 3.9:
pyenv install 3.9
构建带有固定依赖的虚拟环境来构建项目:在
./ev-open-telemetry/ev-observer
目录下运行poetry install
项目依赖文件
pyproject.toml
文件中的这些依赖项是项目的核心,OpenTelemetry 模块处理数据采集和传输,Tesla API 客户端获取实际的车辆数据,pydantic 则确保数据格式的准确性和一致性。
依赖文件地址:https://github.com/GreptimeTeam/demo-scene/blob/main/ev-open-telemetry/ev_observer/pyproject.toml
OpenTelemetry 标准模块:收集和处理应用程序的性能和运行时数据(即"指标")。
这些模块完成以下任务:
捕获指标:监控 Tesla Model 3 充电和驾驶数据。
格式化数据:将捕获的指标数据打包为 OpenTelemetry 协议支持的 HTTP/OTLP 格式。
发送数据:通过 HTTP 将数据发送到兼容 OTLP 的后端(这里是 GreptimeDB)。
Python Tesla API 客户端:这个依赖项是 Tesla 车辆的 API 客户端,用来从 Tesla Owner API 获取实时数据(例如电池状态、驾驶统计等)。这个 API 客户端直接与 Tesla 的服务通信,确保应用程序可以通过 Python 轻松地获取车内的数据。
Pydantic 库:Pydantic 是一个用于验证和解析数据的 Python 库,帮助确保代码中的类型提示(type hints)被正确遵循。它使得数据模型更清晰,并提供类型安全的环境,减少潜在的错误。
如何使用 OpenTelemetry
OpenTelemetry 的监控库为开发者提供了一些 hooks,可以用来与 OpenTelemetry API 交互并捕获感兴趣的指标数据。要设置 OpenTelemetry 的监控功能,首先需要进行一些基础配置(boilerplate)。完成这些配置后,用户将创建一个计量器(meter),用于获取实际用于捕获遥测指标的工具(instruments)。
创建 Meter
Instruments 是通过 Meter 获取的。计量器采集数据的规则(例如多长时间读取一次数据、将数据导出到哪里)是通过在 MeterProvider 中配置 Readers 来完成的。
配置步骤
首先,用户需要配置 exporter 和 reader,并将它们作为参数传递来初始化 MeterProvider;
使用配置好的 provider 设置全局的指标监控对象;
从这个全局监控对象中获取一个 Meter;
使用这个 Meter 创建 Instruments,这些 Instruments 提供了监控数据的接口。
修改配置
如果想修改例如多长时间导出一次指标数据、如何过滤/采样读取的数据,或者数据导出到哪里,这些配置都是在 Meter
初始化过程中完成的。
在本文的这个例子中,我们初始化配置了 PeriodicExportingMetricReader
,以 SCRAPE_INTERVAL
间隔的时间(默认为 300 秒)抓取一次数据,并通过 OTLPMetricExporter
将这些数据导出到我们的 GreptimeDB OTLP 后端。
Meter 的配置是在文件 ev-open-telemetry/ev_observer/ev_observer/init.py
[1] 中完成的。
创建 Instruments
现在我们已经了解了如何创建 Meter,接下来将介绍如何使用 Meter 来创建 Instruments 并通过它捕获指标将数据写入数据库。
这个过程可以同步或异步进行,这里我们采用异步收集方式。要设置异步收集,需通过 Meter 创建异步工具,并传入回调函数,每次读取数据时该回调函数都会被执行。
设置一个 Instrument 样例代码如下所示:
上述代码段通过已配置的 Meter 创建了一个名为 system.cpu.time
的 Instrument。在创建 Instrument 时,传入的 cpu_time_callback
回调函数会在初始化时被指定。然后,根据在 MetricsProvider
中配置的参数,PeriodicMetricReader
会每隔 N 毫秒调用这个回调函数,采集系统的 CPU 时间数据。这个配置过程在之前提到的 init.py
文件中有记录。
封装 Instruments
手动为每个工具设置和管理非常繁琐,所以开发者创建了一个名为 MetricCollector
的基类。这个基类自动帮助我们生成这些工具,并创建回调函数,用来读取数据并将其发送给 OpenTelemetry。MetricCollector
的主要任务是:初始化这些工具,然后创建一些“回调函数”(用来定期读取数据)。这些回调函数被设计成能自动读取 MetricCollector
中最新的属性值,保证采集的是最新的数据并发送给 OpenTelemetry。
封装 OpenTelemetry 工具创建过程可参见 ev-open-telemetry/ev_observer/ev_observer/metrics.py
[2]。
举个例子,代码中的 ChargingState
类负责捕获特斯拉的电池电量和充电情况。通过在属性字段上加一个特殊的标记(custom_tag="metric"
),告诉 MetricCollector
为这些属性创建工具,方便读取这些数值并进行监控。
实现 OpenTelemetry 数据收集过程
要实现 OpenTelemetry 数据的收集过程,需要关注的代码部分是两个模块:EVMetricData
(用来处理电动车的指标数据)和 AbstractVehicleFetcher
(用来获取车辆相关数据的抽象接口)。
通过更新这两个模块并配置 VehicleInstrumentor
以使用所需的 VehicleFetcher
,系统就能够顺利收集特定车辆的指标数据,并将这些数据发送到 GreptimeDB 实例中。
下图展示了整个数据收集过程所涉及的组件:
(图 2:数据收集过程涉及的组件)
确定要收集的指标
EVMetricData
是一个管理多个负责读取和导出指标数据的 MetricCollector
的类,同时也负责初始化所有 Instruments 并更新类中的值。除了收集数据,它还可以通过 attributes
属性为数据添加更多信息,比如本例中我们给收集的指标打上车名的标签。DriveState
和 ChargeState
是两个子类,继承自 MetricsProvider
,这个类帮助创建 Instrument。如果想收集更多的指标,只需创建另一个子类,并将其加入到 EvMetricsData
类中即可。这使得扩展和增加监控指标变得非常容易。
项目中收集的所有 EV 指标可见:https://github.com/GreptimeTeam/demo-scene/blob/cfee3e09e97311049c7df454e1a688a9a67071ea/ev-open-telemetry/ev_observer/ev_observer/metrics.py#L57-L121
用 Python API 监控特斯拉
特斯拉 API 允许车主通过编程的方式查看车辆信息,甚至可以控制车辆。我们使用这个 API 来实现一个叫做 TeslaMetricFetcher
的抽象类,它负责获取车辆的各种数据。
这个数据获取逻辑被封装在一个叫做 AbstractVehicleDataFetcher
的实现中。这个抽象类需要返回一个包含车辆指标的对象 EVMetrics
,之后 VehicleInstrumentor
类会定期刷新这些数据(我们将在下一小节展开)。这样的设计让我们以后可以轻松地添加其他电动车的监控指标,只需修改和刷新函数即可。
车辆状态和刷新周期的主要管理者是 VehicleInstrumentor
。VehicleInstrumentor
包含一个 AbstractVehicleDataFetcher
实例和一个 EVMetricData
实例。VehicleInstrumentor
类负责设置仪器,并通过 fetcher
保持车辆数据的更新。
VehicleInstrumentor 代码可在此查看:https://github.com/GreptimeTeam/demo-scene/blob/cfee3e09e97311049c7df454e1a688a9a67071ea/ev-open-telemetry/ev_observer/ev_observer/vehicle.py#L46-L58
运行程序
如上所述,该项目使用 Docker 实现了“零依赖”的运行环境,用户无需配置复杂的依赖项就能快速启动项目。Docker Compose 文件配置了整个网络,其中包括特斯拉的数据采集模块、用以存储指标数据的 GreptimeDB 数据库,以及用来可视化这些数据的 Grafana 仪表盘。
用于容器化应用的 Docker Compose 文件可见:https://github.com/GreptimeTeam/demo-scene/blob/main/ev-open-telemetry/docker-compose.yml
要运行 Python 数据采集过程,你需要有特斯拉的有效账号,并且车辆必须已经注册。接着,你需要用这些登录信息来验证你的账号,项目运行时会提示你输入这些信息以完成认证。
特斯拉身份验证流程
当容器启动后,日志中会显示以下信息:
在浏览器中打开此链接,并使用特斯拉账户信息登录,成功验证后,将被定向到一个空白页面。将浏览器地址栏中的 URL 复制粘贴到终端中,以通过令牌完成身份验证。一旦完成这个步骤,生成的 cache.json
文件将使用刷新令牌来保持认证会话有效,直到容器运行结束。
应用成功运行后,特斯拉车辆数据将开始流入本地 Docker 容器中托管的 GreptimeDB 实例中。
设置 GreptimeDB 作为 OpenTelemetry 存储后端
OpenTelemetry 的一个重要优势在于它的声明式语义标准,许多数据库都支持这一标准用于传输数据。我们使用 GreptimeDB 作为 OpenTelemetry 的后端来捕获电动汽车(EV)的指标,用户也可以选择任何兼容 OpenTelemetry 的后端来捕获数据。
GreptimeDB 支持 Postgres 的协议(以及其他多种协议),支持使用常规的 Postgres 客户端来查询数据。在构建容器后,按照以下步骤来验证数据捕获情况:
通过 Postgres 客户端连接到 GreptimeDB
进一步查询分析数据:
GreptimeDB 对 OpenTelemetry 协议的实现使得指标数据的收集更加流畅便捷。由于 OpenTelemetry 提供的标准化规范,用户可以轻松在不同的数据库提供商之间切换,从而避免在监控基础设施中受到特定厂商的绑定限制(vendor lock-in)。
Reference
关于 Greptime
Greptime 格睿科技专注于为可观测、物联网及车联网等领域提供实时、高效的数据存储和分析服务,帮助客户挖掘数据的深层价值。目前基于云原生的时序数据库 GreptimeDB 已经衍生出多款适合不同用户的解决方案,更多信息或 demo 展示请联系下方小助手(微信号:greptime)。
欢迎对开源感兴趣的朋友们参与贡献和讨论,从带有 good first issue 标签的 issue 开始你的开源之旅吧~期待在开源社群里遇见你!添加小助手微信即可加入“技术交流群”与志同道合的朋友们面对面交流哦~
Star us on GitHub Now: https://github.com/GreptimeTeam/greptimedb
Twitter: https://twitter.com/Greptime
Slack: https://greptime.com/slack
评论