可观测性

可观测性(Observability) 指通过系统外部输出推断其内部状态的能力。
维度(Dimension) 是用来描述和分类数据的标签属性,比如用户ID、应用ID、模型名称等,关注“是什么”
指标(Metric) 是用来量化的数值数据,比如请求次数、响应时间、Token消耗量等,关注“有多少”

监控等数据分类

系统指标:包括cpu使用率、内存占用、磁盘I/O、网络流量等基础设施层面的监控数据。
应用指标:涵盖接口响应时间、QPS(每秒查询率)、错误率】jvm状态等应用层面的性能数据。
业务指标:针对我们平台的特定业务逻辑,比如AI模型调用次数、token消耗量、用户活跃度等
调用链:在一个分布式系统中,一个请求可能经过多个服务组件。
百分位数:P99:99%的请求响应时间都在这个值以下。

怎么实现

1.统计什么
需要根据业务特点确定关键指标,既要覆盖系统层面的通用指标,也要包含业务特有的监控维度
2.如何收集
数据收集是可观测性的基础,可以通过代码埋点、探针技术、日志分析等多种方式实现
3.如何存储
监控数据通常量大且连续,需要选择合适的存储方案,比如时序数据库或专门的监控系统
4.如何展示
数据面板,实时监控

ARMS系统监控

阿里云提供的应用实时监控服务,采用了探针技术,能够在不修改应用代码的情况下,自动收集和分析应用性能数据,快速构建实时的监控能力。

监控指标设计
首先我们需要明确监控哪些维度和业务指标
维度:
用户ID 应用ID 模型名称 最大输出Token数 AI回复消息内容 模型生成停止原因 调用状态 请求时间 调用失败的错误信息

指标:
token 消耗 响应时长
分析能力
有了基础数据我们可以进行很多分析
模型调用分析:统计不同时间窗口(分钟/小时/天)内,每个模型、用户、应用的调用次数趋势
模型性能分析:分析各模型的平均响应时间,以及响应时间分布的P50/P90百分位数
、、、
数据收集方式
在业务监控中,数据收集需要开发者手动埋点,因为只有开发者才知道要收集什么信息、从哪里收集、什么时候收集。外面的策略是在业务层收集最原始、最细粒度的数据。

数据存储方案-prometheus
prometheus是一个开源的监控系统,专门为时序数据的收集、存储和查询而设计

我们通过jobs和instances配置需要拉取的数据任务和服务实例

  • job(任务):代表「一类被采集的服务」,通常对应一个应用或组件,比如 kiosk-backend、chat-backend、mysql。在 Prometheus 配置里每写一条 job_name: xxx,就是告诉它「这一类目标是一组服务,逻辑上算一类」。
  • instance(实例):代表「这个 job 下面的某一台/某个端口的具体实例」,由 targets 决定,比如 10.0.0.1:8000、10.0.0.2:8000,Prometheus 会自动给每条时间序列打上 instance=”10.0.0.1:8000” 这样的标签。
    组合关系:同一个 job 下可以有很多 instance,用 job 看“这是什么服务/应用”,用 instance 看“这个服务的每个副本/节点各自怎么样”(整体 vs. 单机对比)。

指标类型
counter:累积计数器,只能增加或者重置为零,适合统计请求总数、错误次数等单调递增的指标。
gauge:仪表盘类型,数值可以任意上下波动,适合记录当前状态值,比如内存使用量、当前在线用户数、队列长度等。
histogram:直方图类型,用于观察数据分布情况,比如请求响应时间等分布。
summary:和Histogram类似,但它在客户端预先计算百分位数,沭河需要精确百分位数计算但对网络传输有要求的场景。

存储机制
为了更快查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
flowchart TD
A([数据采集 Scrape]) --> B{写入层}

subgraph In_Memory [内存缓冲区]
B --> C[Memory Block]
B --> D[WAL 预写日志]
end

D -- 故障恢复 --> C
C -- 每2小时周期 --> E[2h Block 持久化]

subgraph Disk_Storage [磁盘持久化层]
E --> F[Index / Chunks / Meta]
F --> G[Background Compaction]
G --> H[(长期存储块)]
end

style D fill:#fff2cc,stroke:#d6b656
style H fill:#dae8fc,stroke:#6c8ebf

说明:

  • 数据采集先写入当前活动内存块(Memory Block)和 WAL 日志
  • 内存块每 2 小时通过 Block Compaction 转为磁盘持久化块
  • 持久化块后台压缩,部分数据进入长期存储
  • 如系统崩溃,WAL Replay 可恢复数据


名词解释:

redis/jvm/full gc/连接池/探针技术/TSDB/k8s

Redis

Redis(Remote Dictionary Server)是一种内存型键值数据库,常用于缓存、会话存储、消息队列等。数据主要在内存中,读写很快,支持多种数据结构(字符串、哈希、列表、集合、有序集合等)。在监控场景里常用来做指标缓存、限流、分布式锁等。


JVM

JVM(Java Virtual Machine,Java 虚拟机)是运行 Java 字节码的运行时环境。Java 程序编译成 .class 字节码后,由 JVM 解释或即时编译(JIT)成机器码执行。JVM 负责内存管理(堆、栈、方法区等)和垃圾回收(GC),所以谈 Java 性能、GC、内存问题时都会涉及 JVM。


Full GC

Full GC(Full Garbage Collection,完全垃圾回收)是 JVM 对整个堆做的一次垃圾回收,包括年轻代(Young Generation)和老年代(Old Generation)。Full GC 会暂停应用线程(Stop-The-World),耗时相对较长,频繁 Full GC 会导致延迟抖动和吞吐下降,是性能调优时重点关注的指标。


连接池(Connection Pool)

连接池是一组预先创建并复用的网络/数据库连接。应用从池中取连接用完后归还,而不是每次请求都新建、关闭连接,从而减少建连/断连的开销和资源占用。常见于数据库(如 JDBC 连接池)、Redis、HTTP 客户端等。监控里常会看连接池使用率、等待数、超时等。


探针技术(Probe / Agent)

探针(或 Agent)是在应用进程内或主机上部署的采集程序,用来无侵入或低侵入地采集指标、日志、链路等数据。例如:

  • JVMTI / Java Agent:注入 JVM,采集方法耗时、GC、线程等;
  • eBPF / 系统探针:在内核层采集网络、系统调用等;
  • Sidecar:在 Pod 旁挂一个容器做流量劫持与可观测性采集。
    常与 APM、监控、链路追踪(如 SkyWalking、Pinpoint)一起使用。

TSDB

TSDB(Time Series Database,时序数据库)是专门存储按时间排序的指标数据的数据库。数据点通常是「时间戳 + 指标名/标签 + 数值」。针对写多读少、按时间范围查询、降采样、保留策略等做了优化。Prometheus、InfluxDB、VictoriaMetrics、TimescaleDB 等都属于 TSDB,是监控、IoT 场景的常用存储。


k8s

k8sKubernetes 的缩写(K 和 s 之间有 8 个字母)。Kubernetes 是容器编排平台,用来部署、扩缩容、调度和管理容器化应用(如 Docker 容器),提供服务发现、负载均衡、自愈、配置与密钥管理、存储编排等。监控中常需要采集 k8s 的 Pod、Node、Service、Deployment 等资源指标和事件。


      ┌───────────────────────┐
      │   Alerting / 告警系统  │
      │  (Alertmanager /      │
      │   Grafana Alert 等)   │
      └─────────▲─▲─▲────────┘
                │ │ │
      ┌─────────┘ │ └─────────┐
      │           │           │
  Metrics       Logs       Traces
(Prometheus)   (Loki)     (Tempo)
      ▲           ▲           ▲
      │           │           │
  ┌───────────────────────────────┐
  │        你的 AI 系统服务        │
  └───────────────────────────────┘

Metrics(指标)指标:Prometheus、Mimir 等
Logs(日志)日志:Loki
Traces(链路追踪)追踪:Tempo

observability 可观测性

Metrics/Logs/Traces 是「可观测性(Observability)」的三大类数据

Metrics(指标监控):http_requests_total、http_request_duration_seconds 这种只是「入门级」的技术指标。实际项目里通常会拆成几类:
基础资源:CPU、内存、磁盘、带宽、连接数。
服务层:QPS、P95/P99 延迟、错误率、队列长度、线程池/协程池利用率。
依赖组件:数据库(QPS/慢查询/连接池)、缓存命中率、消息队列堆积、外部 API 调用耗时与错误。
业务指标(business metrics):下单数、支付成功率、TTS 调用次数、首包延迟、ASR 成功率等。
Tracing(分布式追踪):比如 OpenTelemetry + Tempo/Jaeger,主要是按「一次请求/一次会话」看整条调用链,包含 span、上下游服务、耗时拆分,并不只是一个“trace_count 指标”那么简单。
Alert(告警):本质是基于 metrics/logs/traces 写的规则,比如:
5 分钟内 P95 latency > 1s 持续 3 次;
5xx rate > 1% 持续 10 分钟;
success_rate(ASR) 低于某个阈值;
单个租户/门店的 QPS 异常暴涨等。


Metrics

第 1 步:丰富 Metrics(从“技术指标”扩展到“业务指标”)
目标:从「只有 HTTP QPS/延迟」升级到「能反映 AI 业务健康的指标」。
1.梳理你关心的业务指标(business metrics),例如:

  • 每分钟 TTS 调用次数、成功率、首包延迟 P95;
  • 每个会话的轮次、平均对话时长;
  • 识别成功率、NLP 调用错误率等。
    2.在关键代码路径里打点(仍然用 prometheus_client):
  • 业务计数用 Counter;
  • 业务耗时/延迟用 Histogram;
  • 少量状态值用 Gauge(例如当前活动会话数)。
    3.在 Grafana 新增 Panel:
  • 使用这些新 metrics 写简单 PromQL,比如 rate(ai_tts_requests_total[5m])、histogram_quantile(0.95, …)。

首先需要在原有的FastAPI中暴露Metrics
目标:让服务在“http://localhost:8000/metrics”暴露Prometheus文本格式指标(包括请求总数、请求耗时)
1.定义指标
- 我需要回答什么问题
- 当前接口的qps
- p95延迟
- 错误率?
- 每次对话的平均轮次
- 这个问题更像“次数/速率”还是“耗时/分布”
- 次数/速率 -> counter
- 耗时/延迟分布 -> histogram
- 当前值(队列长度、连接数)-> Gauge
- 我需要按哪些维度区分(labels)
- 比如:按method、path、status区分http请求
- 或按model_name、tenant、scene区分AI请求

2.路径归一化


Logs

第 2 步:规范 Logs,并接入 Loki(日志)
目标:从「FastAPI 在控制台随便打日志」升级到「结构化日志 + 集中检索」。
1.应用内统一日志格式(FastAPI / Python logging):

  • 设置统一 logger,带上 level、timestamp、request_id/session_id、path 等;
  • 优先使用 JSON 格式,方便 Loki/ELK 解析。
    2.选择日志管道到 Loki:
  • 最常见:用 Promtail 作为 agent,去读容器 stdout 或日志文件,然后推送到 Loki。
  • 配置 Promtail:指定 scrape_configs(采集路径、标签,如 job, service)。
    3.Grafana 里配置 Loki 数据源:
  • 在 Grafana Data source 里新增 Loki;
  • 用 Explore 做 logQL 查询(比如 {app=”kiosk-backend”} |= “ERROR”)。

Traces

第 3 步:接入 Traces(分布式追踪 / OpenTelemetry + Tempo)
目标:从「只能看单点日志」升级到「一条请求在各个组件之间的完整链路」。
1.选一个追踪后端:

  • 在 Grafana 生态里,通常选 Tempo(Tracing),也可以先用 Jaeger 简单上手。
    2.在 FastAPI 里接入 OpenTelemetry SDK:
  • 安装 opentelemetry-sdk、opentelemetry-instrumentation-fastapi、opentelemetry-exporter-otlp 等;
  • 在应用启动时初始化 TracerProvider,配置 OTLP 导出到 Tempo/Jaeger;
  • 可选:给关键函数/远程调用(比如调大模型、调 TTS)手动加 span。
    3.在 Grafana 中添加 Tempo 数据源:
  • 然后可以在 Explore 的 Traces 视图中按 service / span name / duration 搜索;
  • 也可以在面板中做「metrics drill-down 到具体 trace」的联动。

Alert

第 4 步:基于 Metrics/Logs/Traces 建 Alert(告警)
目标:从「人肉看大盘」升级到「出了问题自动通知」。
1.基于 Metrics 的告警(最重要):

  • 在 Prometheus 中写告警规则(alerting rules),例如:
  • P95 latency > 1s 持续 5 分钟;
  • 5xx rate > 1% 持续 10 分钟;
  • ai_tts_success_rate < 0.9。
  • 把这些规则推给 Alertmanager,再由 Alertmanager 发到飞书/钉钉/Slack/邮箱。
  • 或者在 Grafana Alerting 中直接基于 PromQL 创建告警。
    2.基于 Logs 的告警(补充):
  • 在 Loki 上做查询(例如 count 5 分钟内 ERROR),用 Grafana Alert 触发;
  • 适合 catch 特殊错误文案、异常堆栈。
    3.基于 Traces 的告警(更进阶):
  • 一般较少直接对 traces 告警,而是对传统 metrics 告警后再用 trace 排查;
  • 但也可以在某些系统中对「长尾 span」做统计派生出 metrics,再告警。

压测工具:hey wrk
$$

Grafana生态实现不是一个单一工具,而是一整套围绕Grafana作为可观测性可视化与运维入口的技术栈

简单说:

你所有的metrics/logs/tracing/alert最终都在Grafana里统一查看和管理

Grafana是一个可视化与统一看板

  • 角色:可视化与仪表盘平台
  • 主要做:
    • 连接多种数据源(Prometheus、Loki、Tempo、MySQL、Elasticsearch等)
    • 用图标、表格、单值等组件做Dashboard;
    • 配置告警(如阈值、通知渠道等)
    • 变量、时间范围、链接等

Prometheus 指标存储与查询

  • 角色:时序数据库+抓取(scrape)引擎+查询引擎。
  • 主要做:
    • 按配置定位拉取各服务的/metrics(或exporter),把指标存成时序数据;
    • 用PromQL做聚合、算rate、分位数等;
    • 可配置告警规则,把告警发给Alertmanager等。
  • 特点:专注[采集 存储 查询]

一、整体架构

监控链路可以概括为三条腿:

1
2
3
4
┌─────────────────┐      scrape       ┌─────────────┐      query      ┌─────────────┐
│ Backend (FastAPI) │ ──────────────► │ Prometheus │ ◄──────────── │ Grafana │
│ GET /metrics │ 每 15s 拉取 │ :9090 │ 作图与告警 │ :3000 │
└─────────────────┘ └─────────────┘ └─────────────┘

实现原理是在具体的Http服务上注册一个GET /metrics路由,每次被访问时返回
单机部署架构
服务拆分
Docker设计
Metrics / Tracing / Alert
日志体系
运行拓扑
真实工程描述

metrics 指标 系统的体征监控

  • 当前gpu使用率 当前延迟 当前并发数
  • AI特有监控

推理时延
token/s
队列长度
会话并发数

tracing 链路追踪 一次请求的全过程录像
在你系统里的tracing
Audio Input

ASR

LLM

TTS

Websocket Streaming

Tracing 会记录:

ASR: 480ms
LLM: 3200ms
TTS: 900ms
Network: 120ms

alert 告警 系统出事自动通知

系统级

GPU > 95% 持续5分钟
websocket断开率 > 20%
CPU > 90%

AI

LLM延迟 > 5秒
token/s < 5
ASR失败率 > 10%
session异常率 > 3%

告警形式

飞书
企业微信
Slack
邮件