惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
人人都是产品经理
人人都是产品经理
爱范儿
爱范儿
aimingoo的专栏
aimingoo的专栏
博客园 - 叶小钗
H
Help Net Security
Microsoft Security Blog
Microsoft Security Blog
The Cloudflare Blog
S
SegmentFault 最新的问题
小众软件
小众软件
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 司徒正美
The GitHub Blog
The GitHub Blog
量子位
H
Hackread – Cybersecurity News, Data Breaches, AI and More
V
V2EX
Martin Fowler
Martin Fowler
博客园 - 【当耐特】
J
Java Code Geeks
D
DataBreaches.Net
云风的 BLOG
云风的 BLOG
F
Fortinet All Blogs
Blog — PlanetScale
Blog — PlanetScale
Last Week in AI
Last Week in AI

Recent Commits to openclaw:main

test: merge chat side-result checks · openclaw/openclaw@ddd2c2a test: merge cron history checks · openclaw/openclaw@f7eb746 test: merge responsive navigation shell checks · openclaw/openclaw@c2e4b47 docs(changelog): add codex oauth fixes · openclaw/openclaw@628e6cd test: merge navigation routing cases · openclaw/openclaw@5d8cecb Tests: mock channel registry bundled fallback · openclaw/openclaw@2b08233 Secrets: avoid broad web search discovery for single plugin config · openclaw/openclaw@a464f59 test: merge config view browser checks · openclaw/openclaw@20cf511 fix(status): align oauth health with runtime · openclaw/openclaw@eed7116 feat: add macOS screen snapshots for monitor preview (#67954) thanks … · openclaw/openclaw@f377db1 fix: report shared auth scopes in hello-ok (#67810) thanks @BunsDev · openclaw/openclaw@0b6c39b Auto-reply: avoid eager bundled route fallback · openclaw/openclaw@3ea1bf4 Tests: narrow session binding contract setup · openclaw/openclaw@54e4e16 fix(macOS): enable undo/redo in webchat composer text input (#34962) · openclaw/openclaw@00951dc Tests: speed up channel setup promotion · openclaw/openclaw@82b529a Docs: refresh agent instructions · openclaw/openclaw@5775fe2 fix(auth): serialize OAuth refresh across agents to fix #26322 (#67876) · openclaw/openclaw@8e79080 test: allow ollama public surface boundary test · openclaw/openclaw@7d4f1a6 Docs: add test performance guardrails · openclaw/openclaw@89706d3 Tests: restore context-engine usage proof · openclaw/openclaw@e4c4f95 Tests: slim context engine runtime coverage · openclaw/openclaw@74c198f ci: retry failed custom checkouts · openclaw/openclaw@0ee5baf test: trim duplicate provider auth onboarding cases · openclaw/openclaw@1ffc02e matrix: fix sessions_spawn --thread subagent session spawning (#67643) · openclaw/openclaw@1ce2596 test: reduce auth choice fixture churn · openclaw/openclaw@857b9cd test: mock health status config boundaries · openclaw/openclaw@9d5ab4a test: mock onboard config io boundary · openclaw/openclaw@299694d test: mock legacy state plugin boundaries · openclaw/openclaw@2713089 test: mock channel install boundaries · openclaw/openclaw@b945248 test: mock doctor preview channel boundaries · openclaw/openclaw@b1a3ad4
feat(diagnostics): capture model call size timing · openc...
vincentkoc · 2026-04-27 · via Recent Commits to openclaw:main

@@ -217,7 +217,7 @@ function positiveFiniteNumber(value: number | undefined): number | undefined {

217217

}

218218219219

function assignPositiveNumberAttr(

220-

attrs: Record<string, string | number>,

220+

attrs: Record<string, string | number | boolean>,

221221

key: string,

222222

value: number | undefined,

223223

): void {

@@ -227,6 +227,23 @@ function assignPositiveNumberAttr(

227227

}

228228

}

229229230+

function assignModelCallSizeTimingAttrs(

231+

attrs: Record<string, string | number | boolean>,

232+

evt: {

233+

requestPayloadBytes?: number;

234+

responseStreamBytes?: number;

235+

timeToFirstByteMs?: number;

236+

},

237+

): void {

238+

assignPositiveNumberAttr(attrs, "openclaw.model_call.request_bytes", evt.requestPayloadBytes);

239+

assignPositiveNumberAttr(attrs, "openclaw.model_call.response_bytes", evt.responseStreamBytes);

240+

assignPositiveNumberAttr(

241+

attrs,

242+

"openclaw.model_call.time_to_first_byte_ms",

243+

evt.timeToFirstByteMs,

244+

);

245+

}

246+230247

function assignGenAiSpanIdentityAttrs(

231248

attrs: Record<string, string | number | boolean>,

232249

input: { api?: string; model?: string; provider?: string },

@@ -812,6 +829,27 @@ export function createDiagnosticsOtelService(): OpenClawPluginService {

812829

unit: "ms",

813830

description: "Model call duration",

814831

});

832+

const modelCallRequestBytesHistogram = meter.createHistogram(

833+

"openclaw.model_call.request_bytes",

834+

{

835+

unit: "By",

836+

description: "UTF-8 byte size of sanitized model request payloads",

837+

},

838+

);

839+

const modelCallResponseBytesHistogram = meter.createHistogram(

840+

"openclaw.model_call.response_bytes",

841+

{

842+

unit: "By",

843+

description: "UTF-8 byte size of streamed model response events",

844+

},

845+

);

846+

const modelCallTimeToFirstByteHistogram = meter.createHistogram(

847+

"openclaw.model_call.time_to_first_byte_ms",

848+

{

849+

unit: "ms",

850+

description: "Elapsed time before the first streamed model response event",

851+

},

852+

);

815853

const toolExecutionDurationHistogram = meter.createHistogram(

816854

"openclaw.tool.execution.duration_ms",

817855

{

@@ -1700,6 +1738,23 @@ export function createDiagnosticsOtelService(): OpenClawPluginService {

17001738

"gen_ai.request.model": lowCardinalityAttr(evt.model),

17011739

...(errorType ? { "error.type": errorType } : {}),

17021740

});

1741+

const recordModelCallSizeTimingMetrics = (

1742+

evt: Extract<DiagnosticEventPayload, { type: "model.call.completed" | "model.call.error" }>,

1743+

attrs: ReturnType<typeof modelCallMetricAttrs>,

1744+

) => {

1745+

const requestPayloadBytes = positiveFiniteNumber(evt.requestPayloadBytes);

1746+

if (requestPayloadBytes !== undefined) {

1747+

modelCallRequestBytesHistogram.record(requestPayloadBytes, attrs);

1748+

}

1749+

const responseStreamBytes = positiveFiniteNumber(evt.responseStreamBytes);

1750+

if (responseStreamBytes !== undefined) {

1751+

modelCallResponseBytesHistogram.record(responseStreamBytes, attrs);

1752+

}

1753+

const timeToFirstByteMs = positiveFiniteNumber(evt.timeToFirstByteMs);

1754+

if (timeToFirstByteMs !== undefined) {

1755+

modelCallTimeToFirstByteHistogram.record(timeToFirstByteMs, attrs);

1756+

}

1757+

};

1703175817041759

const recordModelCallStarted = (

17051760

evt: Extract<DiagnosticEventPayload, { type: "model.call.started" }>,

@@ -1733,7 +1788,9 @@ export function createDiagnosticsOtelService(): OpenClawPluginService {

17331788

evt: Extract<DiagnosticEventPayload, { type: "model.call.completed" }>,

17341789

metadata: DiagnosticEventMetadata,

17351790

) => {

1736-

modelCallDurationHistogram.record(evt.durationMs, modelCallMetricAttrs(evt));

1791+

const metricAttrs = modelCallMetricAttrs(evt);

1792+

modelCallDurationHistogram.record(evt.durationMs, metricAttrs);

1793+

recordModelCallSizeTimingMetrics(evt, metricAttrs);

17371794

genAiOperationDurationHistogram.record(

17381795

evt.durationMs / 1000,

17391796

genAiModelCallMetricAttrs(evt),

@@ -1752,6 +1809,7 @@ export function createDiagnosticsOtelService(): OpenClawPluginService {

17521809

if (evt.transport) {

17531810

spanAttrs["openclaw.transport"] = evt.transport;

17541811

}

1812+

assignModelCallSizeTimingAttrs(spanAttrs, evt);

17551813

assignOtelModelContentAttributes(

17561814

spanAttrs,

17571815

evt as unknown as Record<string, unknown>,

@@ -1773,10 +1831,12 @@ export function createDiagnosticsOtelService(): OpenClawPluginService {

17731831

metadata: DiagnosticEventMetadata,

17741832

) => {

17751833

const errorType = lowCardinalityAttr(evt.errorCategory, "other");

1776-

modelCallDurationHistogram.record(evt.durationMs, {

1834+

const metricAttrs = {

17771835

...modelCallMetricAttrs(evt),

17781836

"openclaw.errorCategory": errorType,

1779-

});

1837+

};

1838+

modelCallDurationHistogram.record(evt.durationMs, metricAttrs);

1839+

recordModelCallSizeTimingMetrics(evt, metricAttrs);

17801840

genAiOperationDurationHistogram.record(

17811841

evt.durationMs / 1000,

17821842

genAiModelCallMetricAttrs(evt, errorType),

@@ -1797,6 +1857,7 @@ export function createDiagnosticsOtelService(): OpenClawPluginService {

17971857

if (evt.transport) {

17981858

spanAttrs["openclaw.transport"] = evt.transport;

17991859

}

1860+

assignModelCallSizeTimingAttrs(spanAttrs, evt);

18001861

assignOtelModelContentAttributes(

18011862

spanAttrs,

18021863

evt as unknown as Record<string, unknown>,