追踪#
备注
--enable-tracing 要求 设置 --otlp-endpoint。如果启用追踪但没有 OTLP 端点,服务器将拒绝启动,因为没有本地回退用于追踪导出。
当启用追踪时(--enable-tracing --otlp-endpoint <URL>),追踪订阅者从 START/END 事件对创建 OTel spans:
mp.store— 从MP_STORE_START到MP_STORE_ENDmp.retrieve— 从MP_RETRIEVE_START到MP_RETRIEVE_ENDmp.lookup_prefetch— 从MP_LOOKUP_PREFETCH_START到MP_LOOKUP_PREFETCH_END
每个 span 携带事件元数据作为 span 属性(例如 device、stored_count、found_count)。
在任何与 OTel 兼容的后端中查看追踪,例如 Jaeger 或 Grafana Tempo。
# Start Jaeger all-in-one (OTLP gRPC on 4317)
docker run -d --name jaeger \
-p 16686:16686 -p 4317:4317 \
jaegertracing/all-in-one:latest
# Start LMCache with tracing
lmcache server \
--l1-size-gb 100 --eviction-policy LRU \
--enable-tracing --otlp-endpoint http://localhost:4317
每个请求的命中率属性#
每个会话都被封装在一个每请求根 span 中——标准 MP 路径对应 request,CacheBlend 路径对应 cb.request——该根 span 将所有子 span(mp.store、mp.retrieve、mp.lookup_prefetch)嵌套在其下。当查找阶段结束时,根 span 会被标注三个 OTel 属性,用以汇总请求级别的缓存命中率:
属性 |
OTel 类型 |
描述 |
|---|---|---|
|
|
从 L1+L2 命中并返回的 token 数(分子)。 |
|
|
提交查找的块对齐 token 数(分母)。 |
|
|
|
在处理 MP_LOOKUP_PREFETCH_END(标准 MP 路径)或 CB_LOOKUP_END(CacheBlend 路径)时写入这些属性——此时根 span 仍处于打开状态。纯存储请求不会调用 lookup_prefetch_start(),因此不会为查找阶段发出结束事件,其根 span 也不会携带这些属性。
示例 TraceQL 查询(Grafana Tempo):
# Requests with less than 50% cache hit rate
{ name = "request" && span.hit_rate < 0.5 }
# Full cache hits only
{ name = "request" && span.hit_rate = 1.0 }
# Complete misses (lookup ran but nothing was cached)
{ name = "request" && span.requested_tokens > 0 && span.hit_tokens = 0 }
有关完整的事件到 span 映射以及将子 span 关联回根 span 的注册模式,请参阅源码树中的 docs/design/observability/request-event-span.md。
追踪记录#
备注
追踪录制与 --enable-tracing(OTel span)是 两个独立的功能。追踪录制将每次 StorageManager 公共 API 调用记录到二进制文件,以便后续在无需 vLLM(最终也无需 GPU)的情况下 重放 相同的工作负载,用于测试、回归排查和基准测试。--enable-tracing 则将实时 OTel span 导出到 OTLP 端点以实现在线可观测性。两者相互独立,可同时使用。
当设置 --trace-level storage 时,LMCache 会将每次对 StorageManager.{reserve_write, finish_write, submit_prefetch_task, read_prefetched_results, finish_read_prefetched} 的调用记录到一个二进制文件中,以便后续重放。
录制默认关闭,关闭状态下开销几乎为零(每次 StorageManager 调用仅做一次布尔判断)。开启时,录制在 EventBus 排空线程上执行,不占用请求路径。
捕获追踪#
带有显式输出路径:
lmcache server \
--l1-size-gb 100 --eviction-policy LRU \
--trace-level storage --trace-output /tmp/run.lct
在 $TMPDIR 下使用隐式时间戳输出路径:
lmcache server \
--l1-size-gb 100 --eviction-policy LRU \
--trace-level storage
# → INFO log: "trace recording enabled (level=storage); no
# --trace-output given, writing to
# /tmp/lmcache-trace-<pid>-<UTC>.lct"
关闭时(SIGTERM 由 EventBus 停止路径处理),追踪文件会被正常关闭。
重放#
录制追踪的重放方式,以及驱动、监控和导出重放结果的完整 CLI 参数集,详见专属页面: 追踪和调试。
捕获了什么(以及未捕获的内容)#
捕获:
每个被装饰的
StorageManager方法调用的完全限定名(qualname)。每个调用的输入参数(例如
keys,layout_desc,mode,extra_count,external_request_id)。每个调用的墙钟时间和单调时间戳。
包含追踪 schema 版本、开始时间以及当前
StorageManagerConfig的 SHA-256 摘要的文件头,供重放时检测配置不匹配。
未捕获:
KV 张量的字节内容。重放仅演练状态记账与控制器逻辑;重放时的负载数据以零值填充。
MPCacheServer、消息队列或任何 GPU 拷贝代码内部的调用。这些层 不在存储追踪级别的采集范围内。
文件格式#
一个长度前缀的 msgpack 流:
[4-byte big-endian length][msgpack Header]
[4-byte big-endian length][msgpack Record]
[4-byte big-endian length][msgpack Record]
...
Header 包含魔数前缀(LMCT)、格式版本、追踪级别(当前为 storage)、追踪 schema 版本、开始时间戳以及 StorageManagerConfig 摘要。每个 Record 包含相对时间戳、墙钟时间戳、完全限定调用位置(qualname)和参数字典。
该格式有意设计为可扩展:未来的追踪 级别(mq、gpu)将共享此布局,并通过 level 头字段加以区分。新增捕获的操作只需添加新的 qualname 字符串,无需升级格式版本。
有关完整的设计原理,请参见