
在现代观察性中,最迷人的部分之一就是它的多功能性。虽然我们通常提到物联网来监控非生物系统,但同样的原理也可以应用到有机的、活的系统。那我们的宠物、牲畜,甚至家里的植物呢?就像圣诞老人需要追踪哪只驯鹿需要休息,哪位精灵工作最快一样,无论是生物系统还是非生物系统,现代系统都需要观察性来理解它们的功能。这些活的系统是自主且不可预测的,通常不遵循确定性脚本,使它们成为观察性的理想对象。在本文中,我们将认识 MeowPy,我的虚拟猫,监控它的吃饭、睡觉,甚至可能还有逃跑尝试。
观察性的三大要素
现代观察性有三大支柱:日志、追踪和指标。应用程序的日志就像圣诞老人 “淘气与乖巧名单” 中的单条记录。它们是离散、结构化的事件,告诉我们分布式系统中发生了什么故事。日志通常记录系统上下文、操作发生时间以及发生的具体情况。这通常是遥测数据中最丰富且上下文最完整的部分。
接下来是追踪,它展示了请求在系统中的完整旅程。追踪显示端到端路径、在每个服务中花费的时间、服务依赖关系以及任何分布式上下文。
最后是应用程序的指标。指标是定量数据,例如计数器、直方图或仪表。计数器跟踪只会增加的值(如服务的总请求数),直方图捕捉值的分布(如响应时间),仪表测量可以上下变化的值(如当前内存使用量)。指标高度可聚合,非常适合告警和仪表盘展示。
介绍 OpenTelemetry
谈现代观察性时,不能不提 OpenTelemetry,通常缩写为 OTel。OTel 是一个 CNCF 开源观察性框架,用于标准化生成、收集和导出应用程序遥测数据的功能。OTel 的主要特点包括能够连接到任何观察性后端,保证供应商中立性,这样你可以快速切换提供商或将数据发送到多个目标,而无需重写监测代码。OTel 在各语言中提供一致的 API,使得在多语言环境中维护观察性标准更加容易。
结合我们目前学到的信息,下面是本次演示的快速示意图:

图例:
- 蓝色 = OpenTelemetry 组件
- 绿色 = Flask / 导出层
- 红色 = 外部服务
- 橙色 = Elastic Cloud
设置 OpenTelemetry
在你自己的环境中开始使用 OTel 很简单,有几种方式可以进行设置。最快速的方式是使用自动监测(auto-instrumentation)。要在你的 Elastic 项目中使用 Elastic 分发版 OpenTelemetry(EDOT)进行自动监测,只需使用以下命令。
pip install elastic-opentelemetry
edot-bootstrap --action=install
opentelemetry-instrument <your_service> main:app
就这样!只要正确设置 OTLP_* 变量,你的应用就可以立即使用 OpenTelemetry 将任何希望摄取到 Elastic 的遥测数据或信号标准化。
另一种在环境中使用 OTel 的方式是手动监测。首先,你需要为应用设置一个服务资源,以便 OTel SDK 能识别你的服务。
# Resource identifies your service
resource = Resource.create({
"service.name": "virtual-cat"
})
首先我们设置日志。OTel 中的日志可以与 Python 标准日志模块无缝集成,因此你可以使用所有熟悉的 Python 日志模式。我们首先创建一个 LoggerProvider,它与我们的服务资源绑定。指向 Elastic 的 OTLP 导出器使用我们的 API 密钥(ELASTIC_SECRET_TOKEN)进行认证。就像我们为追踪批处理 spans 一样,BatchLogRecordProcessor 会在导出前批处理日志记录,以提升性能。最后,将其设置为全局 logger provider 后,我们可以使用 Python 内置的 LoggingHandler 连接到 OTel,它会自动捕获并将日志语句作为 OTel 日志记录导出。
# Logs Setup
logger_provider = LoggerProvider(resource=resource)
log_exporter = OTLPLogExporter(
endpoint=ELASTIC_ENDPOINT,
headers={"Authorization": f"Bearer {ELASTIC_SECRET_TOKEN}"},
insecure=False
)
logger_provider.add_log_record_processor(BatchLogRecordProcessor(log_exporter))
set_logger_provider(logger_provider)
#Bridge Python logging to OTel
handler = LoggingHandler(level=logging.INFO, logger_provider=logger_provider)
logging.getLogger().addHandler(handler)
logging.getLogger().setLevel(logging.INFO)
# Get logger instance
logger = logging.getLogger(__name__)
要捕获追踪,首先创建一个 TracerProvider,并将其与我们的服务资源关联。然后配置一个指向 Elastic 端点的 OTLP 导出器,并在请求头中传递授权令牌。BatchSpanProcessor 会在导出前批处理 spans,通过减少网络请求次数来提升性能。最后,将该 provider 设置为全局 tracer provider,并获取一个 tracer 实例,在整个应用中使用它来创建 spans。
# Traces Setup
trace_provider = TracerProvider(resource=resource)
otlp_trace_exporter = OTLPSpanExporter(
endpoint=ELASTIC_ENDPOINT,
headers={"authorization": f"Bearer {ELASTIC_SECRET_TOKEN}"},
insecure=False
)
trace_provider.add_span_processor(
BatchSpanProcessor(otlp_trace_exporter)
)
trace.set_tracer_provider(trace_provider)
# Get tracer instance
tracer = trace.get_tracer(__name__)
对于指标,我们获取一个 Meter 实例,它作为创建指标工具的入口点。OpenTelemetry 提供多种指标类型,取决于你的使用场景。计数器(counter)跟踪只会增加的值 —— 非常适合统计 MeowPy 的逃跑次数。直方图(histogram)捕捉值的分布,这里我们用它记录 MeowPy 午睡位置的 x 坐标。在记录指标时,我们可以附加属性(如猫的名字),为仪表盘中的筛选和分组增加维度。
# Metrics Setup
metric_reader = PeriodicExportingMetricReader(
OTLPMetricExporter(
endpoint=ELASTIC_ENDPOINT,
headers={"authorization": f"Bearer {ELASTIC_SECRET_TOKEN}"},
insecure=False
),
export_interval_millis=5000
)
meter_provider = MeterProvider(resource=resource, metric_readers=[metric_reader])
metrics.set_meter_provider(meter_provider)
# Counter: Always increasing values
escape_attempts = meter.create_counter(
"cat.escape.attempts",
description="Number of escape attempts",
unit="1"
)
# Histogram: Distribution of values
nap_location_x = meter.create_histogram(
"cat.nap.location.x",
description="X coordinate of nap locations",
unit="meters"
)
# Recording metrics with attributes
escape_attempts.add(1, {"cat.name": self.name})
nap_location_x.record(spot.x, {"cat.name": self.name})
喵喵巡游:介绍 MeowPy
现在,既然我们已经讲解了如何用 OpenTelemetry 对 Python 应用进行监测,我想向你介绍我们的虚拟猫 —— MeowPy!
在我们的 VirtualCat 类中,我们定义了猫可以执行的功能以及它所生活的环境(一个 100x100 的虚拟房间)。
class VirtualCat:
def __init__(self, name: str, fence_size: Tuple[float, float] = (100.0, 100.0)):
self.name = name
self.fence_width, self.fence_height = fence_size
self.position = Position(fence_size[0] / 2, fence_size[1] / 2)
我们的猫可以执行多种不同的动作,包括排便、进食、睡觉、闲逛,甚至尝试逃跑。这些功能可以由用户手动控制,也可以让 MeowPy 进入自主模式,根据它当前的状态决定下一步动作(如下图所示)。update 方法使用标准状态机,并通过基于时间的转换来实现这一功能。
def update(self) -> None:
"""Update cat state and decide next action"""
# Check if current action is complete
if self.state != CatState.WANDERING:
elapsed = time.time() - self.state_start_time
if elapsed >= self.state_duration:
# Action complete, return to wandering
print(f"✅ {self.name} finished {self.state.value}, back to wandering")
self.state = CatState.WANDERING
else:
# Still busy with current action
return
# Only make decisions when wandering
if self.state == CatState.WANDERING:
self.hunger += 1
self.energy -= 1
# Decision making
if self.bladder > 50:
self.poop()
elif self.hunger > 70:
self.eat()
elif self.energy < 30:
self.nap()
else:
self.move()
像这样的自主 agent 非常适合用来展示观察性工具,因为现代 AI agent 广泛存在且具有非确定性。很多时候,我们无法准确预测 AI 的结果,就像我们无法预测毛茸茸的小伙伴接下来会做什么一样!
节日风格的 Kibana 可视化
Elastic 的 Kibana 是可视化遥测数据的最佳方式之一。根据我虚拟猫的行为,这个汇总的 Kibana 仪表盘展示了关于 MeowPy 的各种重要指标和习惯。
在中央,使用 Vega 作为自定义可视化,散点图显示了 MeowPy 最喜欢的午睡地点,通过绘制它喜欢睡觉的 x 和 y 坐标来展示。在右上角,一个指标显示猫的逃跑尝试次数,并对框的颜色应用条件格式,当尝试次数高时立即提醒用户。下方是一个饼图,展示 MeowPy 的日常习惯——可以看到,它在节日期间相当活跃。饼图下方的条形图显示的是应用指标,而不是猫的指标:应用事务的持续时间。

在你的 Kibana 仪表盘中继续添加可视化的方法有很多 —— 多到现在无法一一覆盖!Kibana 的工具以 UI 无代码为主,允许任何人可视化其项目所需的数据。
淘气还是乖巧?观察性最佳实践
为了确保你在下次观察性实施中进入 “乖巧名单”,这里有一些快速最佳实践:
- 使用 OpenTelemetry 进行监测时,确保使用带点记法的语义约定,以在系统间创建一致性
- 从自动监测开始,这是开始使用 OTel 最简单、最高效的方式
- 如果你在使用 LLM/AI 系统,确保将 token 使用量作为指标进行跟踪
- 在应用启动时同时设置观察性,以最大化监控效果
结论与现实应用
虽然用虚拟猫玩耍是一种有趣、轻松的方式来理解观察性,但这些原则同样适用于现实世界的 “生物/非生物” 物联网。比如智能宠物项圈可以向主人发送宠物状态的遥测数据,农业传感器实时监控土壤湿度和牲畜健康。
无论是追踪 MeowPy 的逃跑尝试,还是监控关键基础设施,基本原则都是一样的:收集有意义的遥测数据,有效可视化,并根据洞察采取行动。祝监控愉快,愿你的日志永远欢乐,指标熠熠生辉!

2027

被折叠的 条评论
为什么被折叠?



