mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-23 00:53:38 +02:00
feat(observability): rename sandbox provider spans and add run-time wrapper spans (#10999)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Paperclip uses adapter and sandbox code to start agents and run sandbox work > - The current sandbox spans use mixed names and do not group related run-time work > - Mixed names make traces harder to read and compare across providers > - This pull request renames provider spans, adds run-time wrapper spans, and keeps the host allowlist closed > - The benefit is clearer traces with the same sandbox behavior and trust boundary ## Linked Issues or Issue Description **What existing behavior does this improve?** This improves OpenTelemetry span names and grouping for sandbox startup, execution, callback relay, and agent session work. **Subsystem affected** Cross-cutting (multiple of the above): adapter utilities, sandbox providers, shared telemetry documentation, and server instrumentation. **Current behavior** Sandbox provider spans use mixed names. Related run-time operations expose inner `sandbox.exec` spans without a named wrapper span. The host mapper uses a closed allowlist for provider span names. **Proposed behavior** Use descriptive provider-scoped span names. Add wrapper spans for agent session input, agent session output polling, and callback relay. Keep the host mapper allowlist closed and map unknown names to `other`. **Reason and benefit** Clear names make traces easier to read and reduce ambiguity during sandbox operation analysis. Wrapper spans show the full operation while preserving the inner execution spans. **Breaking changes** None. This change updates telemetry span names and grouping only. It does not change sandbox behavior, endpoint behavior, or the host trust boundary. **Additional context** Related prior work: [#10758](https://github.com/paperclipai/paperclip/pull/10758). ## What Changed - Rename Daytona provider sync and session spans with descriptive provider-scoped names. - Add three run-time wrapper spans for agent session input, output polling, and callback relay. - Add a shared span runner that preserves no-op behavior without a real tracer. - Keep the host mapper allowlist closed and map unknown names to `other`. - Update telemetry documentation and span-name tests. ## Verification - Focused adapter-utils span tests pass for startup timing, callback relay, and sandbox execution. - Focused Daytona plugin span tests pass for renamed leaf spans and session open or close spans. - Focused server tests pass for host mapping and instrumentation. - The stacked diff contains one commit on top of `feat/daytona-persistent-session-model`. ## Risks - Span names change for existing telemetry consumers. - The wrapper spans add trace structure but do not change sandbox execution. - The host mapper keeps the existing closed allowlist and `other` bucket. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI GPT-5 (Codex agent); exact deployment revision and context window are not exposed in this run; tool use and code execution enabled. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes: #` / `Refs: #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge Co-authored-by: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
03cfad7ceb
commit
9ace548fd2
15 files changed
+539
-123
No files matched your search
@@ -93,10 +93,17 @@ absent, never a misleading `0`.
|
||||
| `bridge.paperclip` | Paperclip bridge start step. | `sandbox.startup` |
|
||||
| `bridge.process-session` | Process-session bridge start step. | `sandbox.startup` |
|
||||
| `acp.handshake` | ACP session handshake step. | `sandbox.startup` |
|
||||
| `sandbox.exec` | One host-to-sandbox execution. | the active step span |
|
||||
| `sandbox.agentSession.sendInput` | One outbound ACP message to the agent — the socket handler's one `writeTextFile` exec. | the active run span |
|
||||
| `sandbox.agentSession.pollOutput` | One 100 ms poll tick — `list`, then `read`+`remove` per file found (`1 + 2n` execs). | the active run span |
|
||||
| `sandbox.callbackBridge.relayRequest` | One Paperclip-API callback request — read the request, write the response, remove it. | the active run span |
|
||||
| `sandbox.exec` | One host-to-sandbox execution. | the active step or wrapper span |
|
||||
|
||||
A step span name is the step name. The `sandbox.exec` span parents to the step
|
||||
span that runs the execution, so each execution nests under its step. With no
|
||||
span that runs the execution, so each execution nests under its step. A run-time
|
||||
`sandbox.exec` span parents instead to the run-time wrapper span that runs it
|
||||
(`sandbox.agentSession.sendInput`, `sandbox.agentSession.pollOutput`, or
|
||||
`sandbox.callbackBridge.relayRequest`). Each run-time wrapper span parents to the
|
||||
live run span (`agent.turn` during the turn, `task.run` otherwise). With no
|
||||
active trace context the exec span opens unparented.
|
||||
|
||||
The root span sets the error status when the bring-up fails. Each step span sets
|
||||
@@ -172,7 +179,7 @@ the code first. Keep the attribute low-cardinality and free of user content.
|
||||
### Provider spans
|
||||
|
||||
A sandbox provider plugin also opens spans for its own sync steps. These spans
|
||||
use the `sandbox.provider.` name prefix. They share the
|
||||
use the `sandbox.daytona.` name prefix. They share the
|
||||
`paperclip.sandbox.startup.` attribute prefix and obey the same opt-in and
|
||||
no-user-content rules as the startup spans above.
|
||||
|
||||
@@ -183,15 +190,26 @@ before it records the span.
|
||||
|
||||
| Span | Scope | Parent |
|
||||
| --- | --- | --- |
|
||||
| `sandbox.provider.pack` | The host-local pack step that builds the upload tarball. It makes no sandbox round trip. | the active startup step span |
|
||||
| `sandbox.provider.transfer` | The transfer step that uploads the files to the sandbox. | the active startup step span |
|
||||
| `sandbox.provider.other` | Any span name outside the known set. | the active startup step span |
|
||||
| `sandbox.daytona.pack` | The host-local pack step that builds the upload tarball. It makes no sandbox round trip. | the active startup step span |
|
||||
| `sandbox.daytona.transfer` | The transfer step that uploads the files to the sandbox. | the active startup step span |
|
||||
| `sandbox.daytona.ensureDirectory` | The `mkdir -p` step that ensures a directory exists before a write. | the active startup step span |
|
||||
| `sandbox.daytona.checkSymlinkEscape` | The re-check step that a path resolves inside the workspace root before use. | the active startup step span |
|
||||
| `sandbox.daytona.promote` | The atomic move of a staged temp onto its target via a pinned dir handle. | the active startup step span |
|
||||
| `sandbox.daytona.extractTarball` | The one round trip that re-checks the path, runs `tar -xf`, and removes the scratch tarball. | the active startup step span |
|
||||
| `sandbox.daytona.postUploadCommand` | One caller-supplied post-upload command. | the active startup step span |
|
||||
| `sandbox.daytona.session.open` | The create of the one persistent session for a lease, on the first in-run command. | the active run span |
|
||||
| `sandbox.daytona.session.close` | The delete of that persistent session on lease release. | the active run span |
|
||||
| `sandbox.daytona.other` | Any span name outside the known set. | the active startup step span |
|
||||
|
||||
The host clamps the span name to the closed set `pack` and `transfer`. The host
|
||||
maps a known name to `sandbox.provider.<name>`. The host maps any other value to
|
||||
`sandbox.provider.other`, so a span name never carries free-form data.
|
||||
The host clamps the span name to the closed set of leaf names above (`pack`,
|
||||
`transfer`, `ensureDirectory`, `checkSymlinkEscape`, `promote`, `extractTarball`,
|
||||
`postUploadCommand`, `session.open`, and `session.close`). The host maps a known
|
||||
name to `sandbox.daytona.<name>`. The host maps any other value to
|
||||
`sandbox.daytona.other`, so a span name never carries free-form data. Only the
|
||||
daytona provider emits these spans today, so the segment is the literal
|
||||
`daytona`.
|
||||
|
||||
The `sandbox.provider.*` spans use this closed attribute allowlist. The host
|
||||
The `sandbox.daytona.*` spans use this closed attribute allowlist. The host
|
||||
drops every other key, so a command, an argument, a path, an id, a standard
|
||||
output, or a standard error never rides a provider span. The host records only
|
||||
the attributes that the producer sends for one span.
|
||||
@@ -200,9 +218,9 @@ the attributes that the producer sends for one span.
|
||||
| --- | --- | --- | --- |
|
||||
| `paperclip.sandbox.startup.provider` | string | no | The normalized provider family. |
|
||||
| `paperclip.sandbox.startup.outcome` | string | yes | The step outcome (`ok`, `skipped`, or `failed`). |
|
||||
| `paperclip.sandbox.startup.pack.wall_ms` | number | yes | The host-local wall time of the pack step. It rides the `sandbox.provider.pack` span. |
|
||||
| `paperclip.sandbox.startup.transfer.wall_ms` | number | yes | The wall time of the transfer step. It rides the `sandbox.provider.transfer` span. |
|
||||
| `paperclip.sandbox.startup.transfer.guard.count` | number | yes | The number of serial guard round trips before one transfer. It rides the `sandbox.provider.transfer` span. |
|
||||
| `paperclip.sandbox.startup.pack.wall_ms` | number | yes | The host-local wall time of the pack step. It rides the `sandbox.daytona.pack` span. |
|
||||
| `paperclip.sandbox.startup.transfer.wall_ms` | number | yes | The wall time of the transfer step. It rides the `sandbox.daytona.transfer` span. |
|
||||
| `paperclip.sandbox.startup.transfer.guard.count` | number | yes | The number of serial guard round trips before one transfer. It rides the `sandbox.daytona.transfer` span. |
|
||||
|
||||
The `span.record` host handler enforces the allowlist. It re-maps `provider`
|
||||
through the provider-family normalizer. It keeps `outcome` only when the value
|
||||
|
||||
Reference in new issue
Block a user