mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-10 00:11:19 +00:00
improve(diagnostics-otel): make agent-duration histograms usable beyond 10s (#96592)
* improve(diagnostics-otel): tune duration/context histogram bucket boundaries The openclaw.run.duration_ms, openclaw.harness.duration_ms, and openclaw.context.tokens histograms used the SDK default bucket boundaries. The default duration buckets top out at 10s, so agent runs — which routinely take minutes — all collapse into the +Inf overflow bucket, making p95/p99 latency meaningless without collector-side reconfiguration. Add explicit_bucket_boundaries advice via named constants, matching the existing GEN_AI_*_BUCKETS convention in this file: - AGENT_DURATION_MS_BUCKETS (1s … 1h) for the run and harness duration histograms, which share the same range. - CONTEXT_TOKENS_BUCKETS on a token scale (1k … 2M). openclaw.context.tokens records context-window limit/used token counts (e.g. 128000), so the boundaries must cover real context sizes rather than small integers. Adds a test asserting the three histograms advertise the expected boundaries and that run/harness share the same set. * fix(diagnostics-otel): preserve prior histogram buckets --------- Co-authored-by: Harry Chen <zhiling.chen@binance.com> Co-authored-by: Vincent Koc <25068+vincentkoc@users.noreply.github.com>
This commit is contained in:
parent
94da0a9813
commit
11a0e54ddd
2 changed files with 72 additions and 0 deletions
|
|
@ -2345,6 +2345,38 @@ describe("diagnostics-otel service", () => {
|
|||
await service.stop?.(ctx);
|
||||
});
|
||||
|
||||
test("advertises explicit duration buckets on the openclaw run/harness/context histograms", async () => {
|
||||
const service = createDiagnosticsOtelService();
|
||||
const ctx = createOtelContext(OTEL_TEST_ENDPOINT, { metrics: true });
|
||||
const priorSdkBoundaries = [
|
||||
0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000,
|
||||
];
|
||||
try {
|
||||
await service.start(ctx);
|
||||
|
||||
const runDurationOptions = histogramCreateOptions("openclaw.run.duration_ms");
|
||||
expect(runDurationOptions?.unit).toBe("ms");
|
||||
const runBoundaries = runDurationOptions?.advice?.explicitBucketBoundaries;
|
||||
expect(runBoundaries).toEqual(expect.arrayContaining(priorSdkBoundaries));
|
||||
for (const boundary of [60000, 3_600_000]) {
|
||||
expect(runBoundaries).toContain(boundary);
|
||||
}
|
||||
|
||||
const harnessDurationOptions = histogramCreateOptions("openclaw.harness.duration_ms");
|
||||
const harnessBoundaries = harnessDurationOptions?.advice?.explicitBucketBoundaries;
|
||||
expect(harnessBoundaries).toEqual(runBoundaries);
|
||||
|
||||
const contextOptions = histogramCreateOptions("openclaw.context.tokens");
|
||||
const contextBoundaries = contextOptions?.advice?.explicitBucketBoundaries;
|
||||
expect(contextBoundaries).toEqual(expect.arrayContaining(priorSdkBoundaries));
|
||||
for (const boundary of [128000, 1_000_000]) {
|
||||
expect(contextBoundaries).toContain(boundary);
|
||||
}
|
||||
} finally {
|
||||
await service.stop?.(ctx);
|
||||
}
|
||||
});
|
||||
|
||||
test("bounds agent identifiers on model usage metric attributes", async () => {
|
||||
const service = createDiagnosticsOtelService();
|
||||
const ctx = createOtelContext(OTEL_TEST_ENDPOINT, { metrics: true });
|
||||
|
|
|
|||
|
|
@ -107,6 +107,43 @@ const GEN_AI_TOKEN_USAGE_BUCKETS = [
|
|||
const GEN_AI_OPERATION_DURATION_BUCKETS = [
|
||||
0.01, 0.02, 0.04, 0.08, 0.16, 0.32, 0.64, 1.28, 2.56, 5.12, 10.24, 20.48, 40.96, 81.92,
|
||||
];
|
||||
// Preserve the SDK's existing finite boundaries so upgrades do not remove
|
||||
// exported bucket series that dashboards or alerts may already reference.
|
||||
const OTEL_DEFAULT_HISTOGRAM_BUCKETS = [
|
||||
0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000,
|
||||
];
|
||||
// Agent run / harness durations routinely exceed the SDK default's 10s ceiling.
|
||||
// Extend the existing layout through one hour without changing prior buckets.
|
||||
const AGENT_DURATION_MS_BUCKETS = [
|
||||
...OTEL_DEFAULT_HISTOGRAM_BUCKETS,
|
||||
15000,
|
||||
20000,
|
||||
30000,
|
||||
45000,
|
||||
60000,
|
||||
120000,
|
||||
180000,
|
||||
240000,
|
||||
300000,
|
||||
600000,
|
||||
900000,
|
||||
1_800_000,
|
||||
3_600_000,
|
||||
];
|
||||
// openclaw.context.tokens records context window limit/used token counts, which
|
||||
// range from a few thousand to >1M for large-context models. Keep the prior
|
||||
// layout and add common context-window sizes above it.
|
||||
const CONTEXT_TOKENS_BUCKETS = [
|
||||
...OTEL_DEFAULT_HISTOGRAM_BUCKETS,
|
||||
16000,
|
||||
32000,
|
||||
64000,
|
||||
128000,
|
||||
200000,
|
||||
400000,
|
||||
1_000_000,
|
||||
2_000_000,
|
||||
];
|
||||
const MAX_RETAINED_TRUSTED_SPAN_CONTEXTS = 1024;
|
||||
const RETAINED_TRUSTED_SPAN_CONTEXT_TIMEOUT_MS = 5_000;
|
||||
|
||||
|
|
@ -1797,14 +1834,17 @@ export function createDiagnosticsOtelService(): OpenClawPluginService {
|
|||
const durationHistogram = meter.createHistogram("openclaw.run.duration_ms", {
|
||||
unit: "ms",
|
||||
description: "Agent run duration",
|
||||
advice: { explicitBucketBoundaries: AGENT_DURATION_MS_BUCKETS },
|
||||
});
|
||||
const harnessDurationHistogram = meter.createHistogram("openclaw.harness.duration_ms", {
|
||||
unit: "ms",
|
||||
description: "Agent harness lifecycle duration",
|
||||
advice: { explicitBucketBoundaries: AGENT_DURATION_MS_BUCKETS },
|
||||
});
|
||||
const contextHistogram = meter.createHistogram("openclaw.context.tokens", {
|
||||
unit: "1",
|
||||
description: "Context window size and usage",
|
||||
advice: { explicitBucketBoundaries: CONTEXT_TOKENS_BUCKETS },
|
||||
});
|
||||
const webhookReceivedCounter = meter.createCounter("openclaw.webhook.received", {
|
||||
unit: "1",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue