指标¶
确保v1版本的LLM引擎暴露的指标集包含v0版本中的所有可用指标。
目标¶
- 实现v0和v1版本之间的指标对等。
- 优先使用场景是通过Prometheus访问这些指标,因为这是我们预期在生产环境中使用的方式。
- 日志记录支持(例如将指标打印到信息日志中)适用于更多临时测试、调试、开发和探索性使用场景。
背景¶
vLLM中的指标可以分为以下几类:
- 服务器级指标:用于追踪LLM引擎状态和性能的全局指标。这些指标通常以Gauge或Counter的形式在Prometheus中暴露。
- 请求级别指标:用于追踪单个请求特征(如大小和时序)的指标。这些指标通常以直方图形式在Prometheus中展示,往往是SRE监控vLLM时跟踪的服务水平目标(SLOs)。
心智模型是,服务器级指标有助于解释请求级指标的值。
v0 指标¶
在v0版本中,以下指标通过兼容Prometheus的/metrics端点暴露,并使用vllm:前缀:
vllm:num_requests_running(计量器)vllm:num_requests_swapped(计量器)vllm:num_requests_waiting(计量器)vllm:gpu_cache_usage_perc(计量器)vllm:cpu_cache_usage_perc(计量器)vllm:gpu_prefix_cache_hit_rate(计量器)vllm:cpu_prefix_cache_hit_rate(计量器)vllm:prompt_tokens_total(计数器)vllm:generation_tokens_total(计数器)vllm:request_success_total(计数器)vllm:request_prompt_tokens(直方图)vllm:request_generation_tokens(直方图)vllm:time_to_first_token_seconds(直方图)vllm:time_per_output_token_seconds(直方图)vllm:e2e_request_latency_seconds(直方图)vllm:request_queue_time_seconds(直方图)vllm:request_inference_time_seconds(直方图)vllm:request_prefill_time_seconds(直方图)vllm:request_decode_time_seconds(直方图)vllm:request_max_num_generation_tokens(直方图)vllm:num_preemptions_total(计数器)vllm:cache_config_info(计量器)vllm:lora_requests_info(计量器)vllm:tokens_total(计数器)vllm:iteration_tokens_total(直方图)vllm:time_in_queue_requests(直方图)vllm:model_forward_time_milliseconds(直方图)vllm:model_execute_time_milliseconds(直方图)vllm:request_params_n(直方图)vllm:request_params_max_tokens(直方图)vllm:spec_decode_draft_acceptance_rate(计量器)vllm:spec_decode_efficiency(计量指标)vllm:spec_decode_num_accepted_tokens_total(计数器)vllm:spec_decode_num_draft_tokens_total(计数器)vllm:spec_decode_num_emitted_tokens_total(计数器)
这些内容记录在推理与服务 -> 生产指标下。
Grafana仪表盘¶
vLLM还提供了一个参考示例,展示如何使用Prometheus收集和存储这些指标,并通过Grafana仪表盘进行可视化。
Grafana仪表板中展示的指标子集让我们了解哪些指标尤为重要:
vllm:e2e_request_latency_seconds_bucket- 端到端请求延迟,以秒为单位测量。vllm:prompt_tokens_total- 提示词令牌总数。vllm:generation_tokens_total- 生成的令牌总数。vllm:time_per_output_token_seconds- 输出token间的延迟时间(Time Per Output Token,TPOT),单位为秒。vllm:time_to_first_token_seconds- 首令牌延迟时间(TTFT),单位为秒。vllm:num_requests_running(同样包括_swapped和_waiting) - 处于 RUNNING、WAITING 和 SWAPPED 状态的请求数量。vllm:gpu_cache_usage_perc- vLLM使用的缓存块百分比。vllm:request_prompt_tokens- 请求提示词长度。vllm:request_generation_tokens- 请求生成长度。vllm:request_success_total- 已完成请求的数量,按完成原因分类:可能是生成了EOS标记或达到了最大序列长度。vllm:request_queue_time_seconds- 队列等待时间。vllm:request_prefill_time_seconds- 请求预填充时间。vllm:request_decode_time_seconds- 请求解码时间。vllm:request_max_num_generation_tokens- 序列组中的最大生成令牌数。
查看添加此仪表板的PR以了解此处所做选择的有趣且有用的背景信息。
Prometheus 客户端库¶
Prometheus支持最初是使用aioprometheus库添加的,但很快切换到了prometheus_client。相关原理在两个链接的PR中都有讨论。
在切换到aioprometheus后,我们失去了用于跟踪HTTP指标的MetricsMiddleware,但后来通过使用prometheus_fastapi_instrumentator重新实现了该功能:
$ curl http://0.0.0.0:8000/metrics 2>/dev/null | grep -P '^http_(?!.*(_bucket|_created|_sum)).*'
http_requests_total{handler="/v1/completions",method="POST",status="2xx"} 201.0
http_request_size_bytes_count{handler="/v1/completions"} 201.0
http_response_size_bytes_count{handler="/v1/completions"} 201.0
http_request_duration_highr_seconds_count 201.0
http_request_duration_seconds_count{handler="/v1/completions",method="POST"} 201.0
多进程模式¶
在v0版本中,指标数据是在引擎核心进程中收集的,我们使用多进程模式使这些指标在API服务器进程中可用。详见 Pull Request #7279。
内置Python/进程指标¶
以下指标默认由prometheus_client支持,但在使用多进程模式时不会暴露:
python_gc_objects_collected_totalpython_gc_objects_uncollectable_totalpython_gc_collections_totalpython_infoprocess_virtual_memory_bytesprocess_resident_memory_bytesprocess_start_time_secondsprocess_cpu_seconds_totalprocess_open_fdsprocess_max_fds
这一点很重要,因为如果我们在v1版本中放弃多进程模式,就能重新获得这些功能。然而,如果这些统计数据没有聚合构成vLLM实例的所有进程信息,那么它们的相关性就值得商榷了。
v0版本PR和问题¶
作为背景,以下是添加v0指标的一些相关PR:
v1 设计¶
v1版本拉取请求¶
背景信息,以下是关于v1指标问题的相关v1 PRs Issue #10582:
- Pull Request #11962
- 拉取请求 #11973
- 拉取请求 #10907
- 拉取请求 #12416
- Pull Request #12478
- 拉取请求 #12516
- 拉取请求 #12530
- 拉取请求 #12561
- 拉取请求 #12579
- 拉取请求 #12592
- Pull Request #12644
指标收集¶
在v1版本中,我们希望将计算和开销从引擎核心进程中移出,以最小化每次前向传递之间的时间。
V1 EngineCore设计的总体思路是:
- EngineCore是内部循环的核心部分,性能在此处最为关键
- AsyncLLM是外层循环。理想情况下,它与GPU执行重叠,因此这里应尽可能包含所有"开销"。所以AsyncLLM.output_handler_loop是记录指标的最佳位置(如果可能的话)。
我们将通过在前端API服务器中收集指标来实现这一目标,这些指标基于从引擎核心进程返回给前端的EngineCoreOutputs中获取的信息。
间隔计算¶
我们的许多指标衡量的是请求处理过程中各事件之间的时间间隔。最佳实践是使用基于"单调时间"(time.monotonic())而非"挂钟时间"(time.time())的时间戳来计算间隔,因为前者不受系统时钟变化(如NTP调整)的影响。
还需注意的是,不同进程的单调时钟存在差异——每个进程都有自己的参考点。因此比较来自不同进程的单调时间戳是没有意义的。
因此,为了计算一个时间间隔,我们必须比较来自同一进程的两个单调时间戳。
调度器统计¶
引擎核心进程会从调度器收集一些关键统计数据 - 例如在上次调度过程后已调度或等待的请求数量 - 并将这些统计数据包含在EngineCoreOutputs中。
引擎核心事件¶
引擎核心还会记录每个请求特定事件的时间戳,以便前端可以计算这些事件之间的间隔。
事件包括:
QUEUED- 当引擎核心接收到请求并将其添加到调度器队列时。SCHEDULED- 当请求首次被调度执行时。PREEMPTED- 该请求已被放回等待队列,以便为其他请求腾出空间完成。它将在未来重新调度并重新开始其预填充阶段。NEW_TOKENS- 当EngineCoreOutput中包含的输出被生成时。由于这在给定迭代中对所有请求都是相同的,我们在EngineCoreOutputs上使用单一时间戳来记录此事件。
计算得出的间隔为:
- 队列间隔 - 介于
QUEUED状态与最近一次SCHEDULED状态之间的时间。 - 预填充间隔 - 最近一次
SCHEDULED与后续首次NEW_TOKENS之间的时间间隔。 - 解码间隔 - 从最近一次
SCHEDULED后的首次到末次NEW_TOKENS之间的时间间隔。 - 推理间隔 - 介于最近的
SCHEDULED和最后的NEW_TOKENS之间。 - 令牌间间隔 - 在连续的
NEW_TOKENS之间。
换句话说:
我们探讨了让前端使用其可见事件的时间来计算这些区间的可能性。然而,前端无法观察到QUEUED和SCHEDULED事件的时间,由于我们需要基于同一进程的单调时间戳来计算区间...因此需要引擎核心记录所有这些事件的时间戳。
间隔计算与抢占¶
当在解码过程中发生抢占时,由于任何已生成的令牌都会被重复使用,我们认为抢占会影响令牌间间隔、解码间隔和推理间隔。
当在预填充阶段发生抢占时(假设此类事件可能发生),我们将抢占视为影响首令牌时间和预填充间隔的因素。
前端统计收集¶
前端在处理单个EngineCoreOutputs(即单次引擎核心迭代的输出)时,会收集与该迭代相关的各种统计信息:
- 本次迭代中新生成的令牌总数。
- 本轮迭代中完成的预填充所处理的提示词总数量。
- 本轮迭代中已调度的所有请求的队列间隔时间。
- 在此次迭代中完成预填充的所有请求的预填充间隔。
- 本次迭代中包含的所有请求的令牌间间隔(每次输出令牌时间,TPOT)。
- 本轮迭代中完成预填充的所有请求的首个令牌生成时间(TTFT)。不过,我们会根据请求首次到达前端的时间(
arrival_time)来计算这个间隔,以考虑输入处理时间。
对于在给定迭代中完成的任何请求,我们还会记录:
- 推理和解码间隔 - 相对于上述的调度和首个令牌事件。
- 端到端延迟 - 前端
arrival_time与前端接收最终token之间的时间间隔。
指标发布 - 日志记录¶
LoggingStatLogger 指标发布器每5秒输出一条包含关键指标的 INFO 级别日志消息:
- 当前正在运行/等待的请求数量
- 当前GPU缓存使用情况
- 过去5秒内每秒处理的提示词(token)数量
- 过去5秒内每秒生成的新令牌数量
- 最近1k次键值缓存块查询中的前缀缓存命中率
指标发布 - Prometheus¶
PrometheusStatLogger指标发布器通过/metrics HTTP端点以Prometheus兼容格式提供指标。随后可以配置Prometheus实例轮询此端点(例如每秒一次)并将其值记录在其时间序列数据库中。Prometheus通常与Grafana配合使用,允许将这些指标随时间变化绘制成图表。
Prometheus 支持以下指标类型:
- 计数器:一个随时间递增而永不减少的值,通常在vLLM实例重启时重置为零。例如,实例生命周期内生成的令牌数量。
- Gauge(计量器):一个可增减的数值,例如当前计划执行请求的数量。
- 直方图:对指标样本进行计数,并按区间记录。例如,TTFT(首字节时间)小于1毫秒、小于5毫秒、小于10毫秒、小于20毫秒等的请求数量。
Prometheus指标也可以被标记,允许根据匹配的标签组合指标。在vLLM中,我们为每个指标添加了一个model_name标签,其中包含该实例所服务模型的名称。
示例输出:
$ curl http://0.0.0.0:8000/metrics
# HELP vllm:num_requests_running Number of requests in model execution batches.
# TYPE vllm:num_requests_running gauge
vllm:num_requests_running{model_name="meta-llama/Llama-3.1-8B-Instruct"} 8.0
...
# HELP vllm:generation_tokens_total Number of generation tokens processed.
# TYPE vllm:generation_tokens_total counter
vllm:generation_tokens_total{model_name="meta-llama/Llama-3.1-8B-Instruct"} 27453.0
...
# HELP vllm:request_success_total Count of successfully processed requests.
# TYPE vllm:request_success_total counter
vllm:request_success_total{finished_reason="stop",model_name="meta-llama/Llama-3.1-8B-Instruct"} 1.0
vllm:request_success_total{finished_reason="length",model_name="meta-llama/Llama-3.1-8B-Instruct"} 131.0
vllm:request_success_total{finished_reason="abort",model_name="meta-llama/Llama-3.1-8B-Instruct"} 0.0
...
# HELP vllm:time_to_first_token_seconds Histogram of time to first token in seconds.
# TYPE vllm:time_to_first_token_seconds histogram
vllm:time_to_first_token_seconds_bucket{le="0.001",model_name="meta-llama/Llama-3.1-8B-Instruct"} 0.0
vllm:time_to_first_token_seconds_bucket{le="0.005",model_name="meta-llama/Llama-3.1-8B-Instruct"} 0.0
vllm:time_to_first_token_seconds_bucket{le="0.01",model_name="meta-llama/Llama-3.1-8B-Instruct"} 0.0
vllm:time_to_first_token_seconds_bucket{le="0.02",model_name="meta-llama/Llama-3.1-8B-Instruct"} 13.0
vllm:time_to_first_token_seconds_bucket{le="0.04",model_name="meta-llama/Llama-3.1-8B-Instruct"} 97.0
vllm:time_to_first_token_seconds_bucket{le="0.06",model_name="meta-llama/Llama-3.1-8B-Instruct"} 123.0
vllm:time_to_first_token_seconds_bucket{le="0.08",model_name="meta-llama/Llama-3.1-8B-Instruct"} 138.0
vllm:time_to_first_token_seconds_bucket{le="0.1",model_name="meta-llama/Llama-3.1-8B-Instruct"} 140.0
vllm:time_to_first_token_seconds_count{model_name="meta-llama/Llama-3.1-8B-Instruct"} 140.0
注意
为了使直方图分桶的选择对广泛用例中的用户最有用,这一过程并不简单,需要随着时间的推移不断优化。
缓存配置信息¶
prometheus_client 支持 Info metrics,这种指标等同于一个值永久设为1的Gauge,但通过标签展示关键/值对信息。它用于记录实例的不变信息——因此只需在启动时采集一次——并允许在Prometheus中对不同实例进行比较。
我们将这一概念应用于vllm:cache_config_info指标:
# HELP vllm:cache_config_info Information of the LLMEngine CacheConfig
# TYPE vllm:cache_config_info gauge
vllm:cache_config_info{block_size="16",cache_dtype="auto",calculate_kv_scales="False",cpu_offload_gb="0",enable_prefix_caching="False",gpu_memory_utilization="0.9",...} 1.0
然而,prometheus_client 从未支持多进程模式下的Info指标 - 出于不明原因。我们简单地使用设置为1的Gauge指标和multiprocess_mode="mostrecent"作为替代方案。
LoRA 指标¶
vllm:lora_requests_info Gauge 与之类似,不同之处在于其值为当前挂钟时间,并在每次迭代时更新。
使用的标签名称包括:
running_lora_adapters: 每个适配器当前正在处理请求的数量统计,格式化为逗号分隔的字符串。waiting_lora_adapters: 类似,但统计的是等待调度的请求数量。max_lora- 静态配置"单个批次中LoRA的最大数量"。
将多个适配器的运行/等待计数编码为逗号分隔的字符串似乎相当不合理——我们可以使用标签来区分每个适配器的计数。这一点需要重新审视。
请注意使用了multiprocess_mode="livemostrecent" - 仅采用当前运行进程中最新的指标数据。
该功能是在 Pull Request #9477中添加的,目前已有至少一个已知用户。如果我们重新审视这一设计并弃用旧指标,应该通过在v0版本也进行变更来减少重大弃用周期的需求,同时要求该项目迁移到新指标。
前缀缓存指标¶
在 Issue #10582中关于添加前缀缓存指标的讨论提出了一些有趣的观点,这些观点可能与我们未来处理指标的方式相关。
每次查询前缀缓存时,我们都会记录查询的令牌数量以及缓存中存在的已查询令牌数量(即命中数)。
然而,我们关注的指标是命中率——即每个查询的命中次数。
在日志记录的情况下,我们期望通过计算最近固定数量查询的命中率(目前间隔固定为最近的1k次查询)来为用户提供最佳服务。
对于Prometheus而言,我们应该利用其时间序列特性,允许用户自行选择时间区间来计算命中率。例如,以下PromQL查询可计算过去5分钟的命中区间:
为了实现这一点,我们应该将查询和命中记录为Prometheus中的计数器,而不是将命中率记录为测量指标。
已弃用的指标¶
如何弃用¶
弃用指标不应轻率决定。用户可能不会注意到某个指标已被弃用,当该指标突然(从他们的角度来看)被移除时,即使有等效指标可供使用,也可能会给他们带来相当大的不便。
例如,看看vllm:avg_prompt_throughput_toks_per_s是如何被弃用(代码中有注释说明),被移除,然后被用户注意到的。
一般来说:
- 我们应该谨慎对待废弃指标的做法,尤其是因为很难预测对用户的影响。
- 我们应在/metrics输出中包含的帮助字符串里添加一个显著的弃用通知。
- 我们应在面向用户的文档和发布说明中列出已弃用的指标。
- 我们应该考虑将废弃的指标隐藏在CLI参数后面,以便为管理员提供一个应急出口,在删除这些指标前保留一段时间。
查看弃用政策了解项目范围内的弃用政策。
未实现 - vllm:tokens_total¶
由 Pull Request #4464添加,但显然从未实现。这部分可以直接移除。
重复 - 队列时间¶
由 Pull Request #9659添加的vllm:time_in_queue_requests直方图指标的计算方式为:
self.metrics.first_scheduled_time = now
self.metrics.time_in_queue = now - self.metrics.arrival_time
两周后, Pull Request #4464 添加了 vllm:request_queue_time_seconds 指标,最终呈现为:
if seq_group.is_finished():
if (seq_group.metrics.first_scheduled_time is not None and
seq_group.metrics.first_token_time is not None):
time_queue_requests.append(
seq_group.metrics.first_scheduled_time -
seq_group.metrics.arrival_time)
...
if seq_group.metrics.time_in_queue is not None:
time_in_queue_requests.append(
seq_group.metrics.time_in_queue)
这看起来是重复的,应该移除其中一个。后者被Grafana仪表盘使用,因此我们应该弃用或从v0版本中移除前者。
前缀缓存命中率¶
参见上文 - 我们现在公开的是'queries'(查询次数)和'hits'(命中次数)计数器,而非'hit rate'(命中率)计量器。
KV缓存卸载¶
v0版本中有两个指标与"交换式"抢占模式相关,该模式在v1版本中已不再适用:
vllm:num_requests_swappedvllm:cpu_cache_usage_perc
在此模式下,当请求被抢占时(例如为了在KV缓存中腾出空间以完成其他请求),我们会将KV缓存块交换到CPU内存中。这也被称为"KV缓存卸载",可通过--swap-space和--preemption-mode进行配置。
在v0版本中, vLLM长期支持束搜索。SequenceGroup封装了N个共享相同提示键值块的序列概念。这使得请求之间可以共享KV缓存块,并通过写时复制实现分支。CPU交换功能就是为这类束搜索场景设计的。
后来,引入了前缀缓存的概念,它允许KV缓存块隐式共享。这被证明是比CPU交换更好的选择,因为块可以根据需求缓慢释放,而被释放的提示部分可以重新计算。
SequenceGroup在V1版本中已被移除,尽管"并行采样"(n>1)功能仍需要替代方案。 Beam搜索已从核心功能中移出(在V0版本)。这个非常不常用的功能包含了许多复杂代码。
在V1版本中,由于前缀缓存优化效果更佳(零开销)并默认启用,抢占和重计算策略的表现应会更加出色。
未来工作¶
并行采样¶
部分v0指标仅在"并行采样"场景下相关。这种情况是指请求中的n参数用于从同一提示词获取多个补全结果。
作为在 Pull Request #10980中添加并行采样支持的一部分,我们也应该添加这些指标。
vllm:request_params_n(直方图)
观察每个已完成请求中'n'参数的值。
vllm:request_max_num_generation_tokens(直方图)
观察每个已完成序列组中所有序列的最大输出长度。在没有并行采样的场景下,这等同于vllm:request_generation_tokens。
推测式解码¶
部分v0指标专属于"推测性解码"技术。该技术通过使用更快速的近似方法或模型生成候选令牌,然后利用更大的模型对这些令牌进行验证。
vllm:spec_decode_draft_acceptance_rate(计量器)vllm:spec_decode_efficiency(计量指标)vllm:spec_decode_num_accepted_tokens_total(计数器)vllm:spec_decode_num_draft_tokens_total(计数器)vllm:spec_decode_num_emitted_tokens_total(计数器)
有一个正在审核中的PR ( Pull Request #12193) 计划为v1版本添加"prompt lookup (ngram)"推测解码功能。其他技术将陆续跟进。在此背景下,我们需要重新审视v0版本的指标。
注意
我们或许应该将接受率拆分为独立的接受计数和草稿计数进行展示,就像我们对前缀缓存命中率的处理方式一样。效率指标可能也需要类似的拆分展示。
自动扩缩容与负载均衡¶
我们指标的一个常见用例是支持vLLM实例的自动扩展。
有关Kubernetes Serving工作组的相关讨论,请参阅:
这是一个非简单的话题。请参考Rob的评论:
我认为这个指标应该着重于估算导致平均请求长度大于每秒查询数的最大并发量...因为这实际上才是让服务器"饱和"的关键因素。
一个明确的目标是,我们需要公开检测这一饱和点所需的指标,以便管理员能够基于这些指标实施自动扩展规则。然而,为了实现这一点,我们需要清楚地了解管理员(以及自动化监控系统)应如何判断某个实例正在接近饱和状态:
为了确定模型服务器计算资源的饱和点(即吞吐量不再随请求率提升而增加,反而开始产生额外延迟的拐点),以便实现有效的自动扩缩容?
指标命名¶
我们为指标命名的方式或许值得重新审视:
- 在指标名称中使用冒号似乎与"冒号保留用于用户自定义记录规则"的原则相违背。
- 我们的大多数指标遵循以单位结尾的命名惯例,但并非全部如此。
-
我们的一些指标名称以
_total结尾:如果指标名称带有
_total后缀,该后缀将被移除。当展示计数器的时间序列时,会添加_total后缀。这是为了保持OpenMetrics和Prometheus文本格式之间的兼容性,因为OpenMetrics要求使用_total后缀。
添加更多指标¶
新指标的创意从不匮乏:
- 来自其他项目的示例,例如 TGI
- 针对特定使用场景提出的建议,例如上述Kubernetes自动扩缩容主题
- 可能源自标准化工作的提案,例如OpenTelemetry 生成式AI语义规范。
在添加新指标时,我们需要谨慎行事。虽然添加指标通常相对简单直接:
- 它们可能难以移除 - 请参阅上文的弃用章节。
- 启用这些功能可能会对性能产生显著影响。除非能在生产环境中默认开启,否则相关指标通常实用价值有限。
- 它们对项目的开发和维护产生影响。每个添加到v0版本的指标都使得v1版本的工作更加耗时,也许并非所有指标都值得持续投入维护成本。
追踪 - OpenTelemetry¶
指标提供了系统性能和健康状况随时间变化的聚合视图。另一方面,追踪则跟踪单个请求在不同服务和组件间的流转过程。这两者都属于更广义的"可观测性"范畴。
v0 版本支持 OpenTelemetry 追踪功能:
- 由 Pull Request #4687添加
- 配置了
--oltp-traces-endpoint和--collect-detailed-traces - OpenTelemetry 博客文章
- 用户文档
- 博客文章
- IBM 产品文档
OpenTelemetry 有一个 Gen AI 工作组。
由于指标本身就是一个足够大的主题,我们将在v1版本中单独讨论追踪这一主题。
OpenTelemetry 模型转发与执行时间对比¶
在v0版本中,我们有以下两个指标:
vllm:model_forward_time_milliseconds(直方图) - 当该请求在批次中时,模型前向传播所花费的时间。vllm:model_execute_time_milliseconds(直方图) - 模型执行函数所花费的时间。这将包括模型前向传播、跨工作线程的块/同步、CPU-GPU同步时间和采样时间。
这些指标仅在启用OpenTelemetry追踪功能且使用--collect-detailed-traces=all/model/worker参数时才会生效。该选项的文档说明如下:
为指定模块收集详细的追踪数据。这涉及使用可能成本高昂或阻塞的操作,因此可能会对性能产生影响。
这些指标由 Pull Request #7089添加,并以OpenTelemetry追踪的形式呈现:
-> gen_ai.latency.time_in_scheduler: Double(0.017550230026245117)
-> gen_ai.latency.time_in_model_forward: Double(3.151565277099609)
-> gen_ai.latency.time_in_model_execute: Double(3.6468167304992676)
我们已经有了inference_time和decode_time指标,所以问题在于是否存在足够常见的用例需要更高精度的时间测量来证明其开销是合理的。
由于我们将单独讨论OpenTelemetry支持的问题,因此我们会将这些特定指标纳入该主题下。


