Add observability for script execution
@jerm-dro is already working on this.
Since Apr 10, 2026.
- Dominant language
- Go
- Stars
- 2.2k
- Forks
- 300
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 184
Description
User Story
As a cluster operator, I want logging and metrics for script execution so that I can monitor and diagnose issues in production.
Background
The code mode feature (STORY-001) adds server-side Starlark script execution to vMCP via the execute_tool_script virtual tool. Operators need visibility into this new execution path to monitor health, diagnose failures, and understand resource consumption. Without observability, script execution is a black box that operators cannot troubleshoot or capacity-plan around.
The vMCP codebase already has a well-established telemetry pattern using OpenTelemetry (see pkg/vmcp/server/telemetry.go and pkg/telemetry/middleware.go). This story follows those existing patterns to add structured logging and OTel metrics/traces for the script execution engine.
Scope
In Scope
- Structured logging for script lifecycle events (start, completion, errors, timeouts, limit violations)
- OTel metrics for script execution (count, duration, error rate, tool calls per script, parallel fan-out)
- OTel tracing spans for script execution and inner tool calls
- Follow existing vMCP telemetry patterns (
telemetryBackendClientdecorator pattern,MCPHistogramBuckets,instrumentationNameconventions)
Out of Scope
- Custom dashboards or alerting rules (operators bring their own observability stack)
- Metrics for adoption tracking (covered in STORY-003)
- Changes to the telemetry pipeline or collector configuration
Acceptance Criteria
- unit: Structured logs emitted for script start, completion, and errors — log entries include script hash, session ID, execution duration, tool call count, and error details; script content is NOT logged
- unit: OTel counter
toolhive_vmcp_script_executionsincrements withstatusattribute (success/error/timeout/step_limit) on each script execution - unit: OTel histogram
toolhive_vmcp_script_durationrecords script execution duration in seconds - unit: OTel histogram
toolhive_vmcp_script_tool_callsrecords the number of inner tool calls per script execution - unit: OTel counter
toolhive_vmcp_script_parallel_goroutinesincrements by the number of goroutines spawned perparallel()call - unit: A parent trace span is created for
execute_tool_script, with child spans for each inner tool call, including attributesscript.tool_count,script.parallel_used,script.step_count - unit: Metrics and traces use the existing
instrumentationNameconstant andMeterProvider/TracerProviderfrom the vMCP server
Technical Notes
Existing Patterns to Follow
The telemetryBackendClient in pkg/vmcp/server/telemetry.go demonstrates the project's telemetry decorator pattern:
- Metrics are created via
meter.Int64Counter(),meter.Float64Histogram()with descriptive names prefixed bytoolhive_vmcp_ - Histograms use
telemetry.MCPHistogramBucketsfor bucket boundaries - The
record()method pattern creates a span, records start metrics, and returns a deferred cleanup function - Attributes follow both backward-compat (
tool_name) and OTEL spec (gen_ai.tool.name) conventions
Implementation Approach
- Metrics/tracing injection: Accept
metric.MeterProviderandtrace.TracerProviderin the script engine or middleware constructor. Do not create global meters. - Decorator or inline: Either wrap the script engine with a telemetry decorator (preferred, matches existing pattern) or instrument the engine directly. The decorator approach keeps telemetry concerns separated from execution logic.
- Logging: Use
slog.With()to attach structured fields. The middleware already has access to the request context for correlation. - Inner tool call spans: Each tool call dispatched from within a script should create a child span under the script execution span. The existing
telemetryBackendClient.CallToolmay already handle this if inner calls flow through the instrumented backend client.
Key Files
pkg/script/engine.go-- Starlark execution engine (instrument here or wrap)pkg/script/bridge.go-- Tool bridge andparallel()(goroutine counting)pkg/script/middleware.go-- HTTP middleware entry point (logging, top-level span)pkg/vmcp/server/telemetry.go-- Existing telemetry patterns to followpkg/telemetry/middleware.go--MCPHistogramBucketsand shared telemetry utilities
Dependencies
- Depends on STORY-001 (the script execution engine must exist before it can be instrumented)
- Uses
go.opentelemetry.io/otel/metricandgo.opentelemetry.io/otel/trace(already in go.mod)
References
- Prototype PR: https://github.com/stacklok/toolhive/pull/4714 (branch:
jerm-dro/script-middleware-prototype) - Existing telemetry:
pkg/vmcp/server/telemetry.go
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.