@ultrathink-solutions/openclaw-logfire 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/LICENSE +21 -0
  3. package/README.md +237 -0
  4. package/dist/config.d.ts +48 -0
  5. package/dist/config.d.ts.map +1 -0
  6. package/dist/config.js +130 -0
  7. package/dist/config.js.map +1 -0
  8. package/dist/context/propagation.d.ts +22 -0
  9. package/dist/context/propagation.d.ts.map +1 -0
  10. package/dist/context/propagation.js +93 -0
  11. package/dist/context/propagation.js.map +1 -0
  12. package/dist/context/span-store.d.ts +46 -0
  13. package/dist/context/span-store.d.ts.map +1 -0
  14. package/dist/context/span-store.js +63 -0
  15. package/dist/context/span-store.js.map +1 -0
  16. package/dist/events/inference-details.d.ts +21 -0
  17. package/dist/events/inference-details.d.ts.map +1 -0
  18. package/dist/events/inference-details.js +37 -0
  19. package/dist/events/inference-details.js.map +1 -0
  20. package/dist/hooks/agent-end.d.ts +33 -0
  21. package/dist/hooks/agent-end.d.ts.map +1 -0
  22. package/dist/hooks/agent-end.js +91 -0
  23. package/dist/hooks/agent-end.js.map +1 -0
  24. package/dist/hooks/before-agent-start.d.ts +22 -0
  25. package/dist/hooks/before-agent-start.d.ts.map +1 -0
  26. package/dist/hooks/before-agent-start.js +50 -0
  27. package/dist/hooks/before-agent-start.js.map +1 -0
  28. package/dist/hooks/before-tool-call.d.ts +20 -0
  29. package/dist/hooks/before-tool-call.d.ts.map +1 -0
  30. package/dist/hooks/before-tool-call.js +58 -0
  31. package/dist/hooks/before-tool-call.js.map +1 -0
  32. package/dist/hooks/message-received.d.ts +19 -0
  33. package/dist/hooks/message-received.d.ts.map +1 -0
  34. package/dist/hooks/message-received.js +35 -0
  35. package/dist/hooks/message-received.js.map +1 -0
  36. package/dist/hooks/tool-result-persist.d.ts +19 -0
  37. package/dist/hooks/tool-result-persist.d.ts.map +1 -0
  38. package/dist/hooks/tool-result-persist.js +62 -0
  39. package/dist/hooks/tool-result-persist.js.map +1 -0
  40. package/dist/index.d.ts +35 -0
  41. package/dist/index.d.ts.map +1 -0
  42. package/dist/index.js +94 -0
  43. package/dist/index.js.map +1 -0
  44. package/dist/metrics/genai-metrics.d.ts +20 -0
  45. package/dist/metrics/genai-metrics.d.ts.map +1 -0
  46. package/dist/metrics/genai-metrics.js +56 -0
  47. package/dist/metrics/genai-metrics.js.map +1 -0
  48. package/dist/otel.d.ts +10 -0
  49. package/dist/otel.d.ts.map +1 -0
  50. package/dist/otel.js +70 -0
  51. package/dist/otel.js.map +1 -0
  52. package/dist/trace-link.d.ts +7 -0
  53. package/dist/trace-link.d.ts.map +1 -0
  54. package/dist/trace-link.js +14 -0
  55. package/dist/trace-link.js.map +1 -0
  56. package/dist/util.d.ts +38 -0
  57. package/dist/util.d.ts.map +1 -0
  58. package/dist/util.js +108 -0
  59. package/dist/util.js.map +1 -0
  60. package/openclaw.plugin.json +174 -0
  61. package/package.json +87 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,28 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@ultrathink-solutions/openclaw-logfire` will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.1.0] - 2026-02-15
9
+
10
+ ### Added
11
+
12
+ - Initial release
13
+ - Full agent lifecycle tracing with OTEL GenAI semantic conventions
14
+ - `invoke_agent` root spans with agent name, session key, workspace, and channel attribution
15
+ - `execute_tool` child spans with tool arguments, duration, and result size
16
+ - Error tracing with OTEL exception events (type, message, stack trace)
17
+ - Token usage metrics (`gen_ai.client.token.usage` histogram)
18
+ - Operation duration metrics (`gen_ai.client.operation.duration` histogram)
19
+ - Pydantic Logfire OTLP HTTP export (US and EU regions)
20
+ - Clickable Logfire trace URLs in agent logs
21
+ - Secret redaction for API keys, platform tokens, JWTs, and credentials
22
+ - W3C traceparent injection into HTTP commands for distributed tracing
23
+ - W3C trace context extraction from inbound webhook headers
24
+ - Configurable trace depth (tool input/output capture, message content, inference events)
25
+ - Batch and simple span processor modes
26
+ - Zero-config quickstart (just set `LOGFIRE_TOKEN`)
27
+
28
+ [0.1.0]: https://github.com/Ultrathink-Solutions/openclaw-logfire/releases/tag/v0.1.0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ultrathink Solutions
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,237 @@
1
+ # @ultrathink/openclaw-logfire
2
+
3
+ Pydantic [Logfire](https://pydantic.dev/logfire) observability plugin for [OpenClaw](https://openclaw.ai).
4
+
5
+ Full agent lifecycle tracing aligned with [OTEL GenAI semantic conventions](https://opentelemetry.io/docs/specs/semconv/gen-ai/) — tool calls, token metrics, error stack traces, and optional distributed tracing across services.
6
+
7
+ ## Quickstart
8
+
9
+ ```bash
10
+ npm install @ultrathink/openclaw-logfire
11
+ ```
12
+
13
+ Set your Logfire write token:
14
+
15
+ ```bash
16
+ export LOGFIRE_TOKEN="your-token"
17
+ ```
18
+
19
+ Add to `openclaw.json`:
20
+
21
+ ```json
22
+ {
23
+ "plugins": {
24
+ "entries": {
25
+ "logfire": {
26
+ "enabled": true,
27
+ "config": {}
28
+ }
29
+ }
30
+ }
31
+ }
32
+ ```
33
+
34
+ Restart OpenClaw. That's it — traces appear in your Logfire dashboard.
35
+
36
+ ## What You Get
37
+
38
+ ### Span Hierarchy
39
+
40
+ Every agent invocation produces a trace tree:
41
+
42
+ ```
43
+ invoke_agent chief-of-staff (root span)
44
+ |-- execute_tool Read (file read)
45
+ |-- execute_tool exec (shell command)
46
+ |-- execute_tool Write (file write)
47
+ |-- execute_tool web_search (web search)
48
+ ```
49
+
50
+ ### Attributes (OTEL GenAI Semantic Conventions)
51
+
52
+ | Attribute | Example | Description |
53
+ |-----------|---------|-------------|
54
+ | `gen_ai.operation.name` | `invoke_agent` | Operation type |
55
+ | `gen_ai.agent.name` | `chief-of-staff` | Agent identifier |
56
+ | `gen_ai.conversation.id` | `session_abc123` | Session key |
57
+ | `gen_ai.tool.name` | `Read` | Tool being called |
58
+ | `gen_ai.tool.call.arguments` | `{"path": "/..."}` | Tool input (opt-in) |
59
+ | `gen_ai.usage.input_tokens` | `1024` | Prompt tokens |
60
+ | `gen_ai.usage.output_tokens` | `512` | Completion tokens |
61
+ | `error.type` | `ToolExecutionError` | Error classification |
62
+ | `exception.stacktrace` | `Error: ...` | Full stack trace |
63
+ | `openclaw.workspace` | `chief-of-staff` | Workspace name |
64
+ | `openclaw.channel` | `slack` | Message source |
65
+
66
+ ### Metrics
67
+
68
+ | Metric | Type | Description |
69
+ |--------|------|-------------|
70
+ | `gen_ai.client.token.usage` | Histogram | Token counts by type (input/output) |
71
+ | `gen_ai.client.operation.duration` | Histogram | Agent invocation latency (seconds) |
72
+
73
+ ### Error Tracing
74
+
75
+ Tool failures include full OTEL exception events:
76
+
77
+ - `exception.type` — Error class name
78
+ - `exception.message` — Error description
79
+ - `exception.stacktrace` — Full stack trace
80
+
81
+ Errors propagate up the span tree so the root `invoke_agent` span is marked as errored.
82
+
83
+ ## Configuration
84
+
85
+ All settings are optional. Sensible defaults work out of the box.
86
+
87
+ ```jsonc
88
+ {
89
+ "plugins": {
90
+ "entries": {
91
+ "logfire": {
92
+ "enabled": true,
93
+ "config": {
94
+ // Logfire project (enables clickable trace links in logs)
95
+ "projectUrl": "https://logfire.pydantic.dev/myorg/myproject",
96
+ "region": "us", // "us" or "eu"
97
+ "environment": "production",
98
+ "serviceName": "openclaw-agent",
99
+
100
+ // GenAI provider name for OTEL compliance
101
+ "providerName": "anthropic",
102
+
103
+ // Trace depth controls
104
+ "captureToolInput": true, // Record tool arguments
105
+ "captureToolOutput": false, // Record tool results (verbose)
106
+ "toolInputMaxLength": 2048, // Truncation limit
107
+ "captureStackTraces": true, // Stack traces on errors
108
+ "captureMessageContent": false, // Record message text (privacy)
109
+ "redactSecrets": true, // Strip API keys from tool args
110
+
111
+ // Distributed tracing (opt-in)
112
+ "distributedTracing": {
113
+ "enabled": false,
114
+ "urlPatterns": ["https://api.mycompany.com/*"]
115
+ },
116
+
117
+ // Metrics
118
+ "enableMetrics": true,
119
+
120
+ // Trace links
121
+ "enableTraceLinks": true
122
+ }
123
+ }
124
+ }
125
+ }
126
+ }
127
+ ```
128
+
129
+ ### Environment Variables
130
+
131
+ | Variable | Description |
132
+ |----------|-------------|
133
+ | `LOGFIRE_TOKEN` | Logfire write token (required) |
134
+ | `LOGFIRE_ENVIRONMENT` | Deployment environment fallback |
135
+ | `LOGFIRE_PROJECT_URL` | Project URL fallback |
136
+ | `LOGFIRE_PROVIDER_NAME` | Provider name fallback |
137
+
138
+ ### Secret Redaction
139
+
140
+ When `redactSecrets: true` (default), the plugin strips values matching common patterns before recording tool arguments:
141
+
142
+ - API keys (`api_key: sk_live_...`)
143
+ - Platform tokens (`ghp_`, `gho_`, `glpat_`, `xoxb-`, etc.)
144
+ - JWTs (`eyJ...`)
145
+ - Bearer tokens, passwords, credentials
146
+
147
+ ## Distributed Tracing
148
+
149
+ Connect OpenClaw traces to your backend services. When enabled, the plugin injects `traceparent` headers into HTTP calls made by exec/Bash tools.
150
+
151
+ ```jsonc
152
+ {
153
+ "distributedTracing": {
154
+ "enabled": true,
155
+ "injectIntoCommands": true, // Add traceparent to curl/wget/httpie
156
+ "extractFromWebhooks": true, // Extract traceparent from inbound webhooks
157
+ "urlPatterns": [ // Only inject for matching URLs
158
+ "https://api.mycompany.com/*",
159
+ "http://localhost:8000/*"
160
+ ]
161
+ }
162
+ }
163
+ ```
164
+
165
+ This produces connected traces across services:
166
+
167
+ ```
168
+ OpenClaw: invoke_agent chief-of-staff
169
+ |-- execute_tool exec (curl POST /v1/api)
170
+ |-- [Backend] FastAPI: POST /v1/api
171
+ |-- database query
172
+ |-- LLM call
173
+ ```
174
+
175
+ Your backend must support W3C trace context extraction (most frameworks do: FastAPI with Logfire, Express with OTEL, etc.).
176
+
177
+ ## Architecture
178
+
179
+ ```
180
+ openclaw-logfire/src/
181
+ index.ts Plugin entry point + hook wiring
182
+ config.ts Typed configuration with defaults
183
+ otel.ts OTEL SDK initialization (Logfire OTLP)
184
+ hooks/
185
+ before-agent-start invoke_agent span creation
186
+ before-tool-call execute_tool span + context propagation
187
+ tool-result-persist Tool span close + errors + stack traces
188
+ agent-end Span close + metrics + trace link
189
+ message-received Channel attribution + inbound context
190
+ context/
191
+ span-store Session -> active spans (LIFO tool stack)
192
+ propagation W3C traceparent inject/extract
193
+ metrics/
194
+ genai-metrics Token usage + operation duration histograms
195
+ events/
196
+ inference-details Opt-in inference operation event
197
+ ```
198
+
199
+ ### OpenClaw Hooks Used
200
+
201
+ | Hook | Purpose |
202
+ |------|---------|
203
+ | `before_agent_start` | Create root `invoke_agent` span |
204
+ | `before_tool_call` | Create `execute_tool` child span |
205
+ | `tool_result_persist` | Close tool span, record errors |
206
+ | `agent_end` | Close spans, emit metrics |
207
+ | `message_received` | Enrich with channel info |
208
+
209
+ Requires OpenClaw >= 2026.2.1 (`before_tool_call` was wired in that version).
210
+
211
+ ## Development
212
+
213
+ ```bash
214
+ git clone https://github.com/Ultrathink-Solutions/openclaw-logfire
215
+ cd openclaw-logfire
216
+ npm install
217
+ npm run typecheck
218
+ npm test
219
+ ```
220
+
221
+ ### Local testing with OpenClaw
222
+
223
+ ```bash
224
+ # Symlink into OpenClaw extensions
225
+ ln -s $(pwd) ~/.openclaw/extensions/openclaw-logfire
226
+
227
+ # Or add to openclaw.json
228
+ # "plugins": { "load": { "paths": ["./path/to/openclaw-logfire"] } }
229
+
230
+ export LOGFIRE_TOKEN="your-write-token"
231
+ openclaw restart
232
+ openclaw plugins list # Should show "logfire" as enabled
233
+ ```
234
+
235
+ ## License
236
+
237
+ MIT
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Plugin configuration with sensible defaults.
3
+ *
4
+ * Every option can be left unset for a zero-config quickstart —
5
+ * just export LOGFIRE_TOKEN and enable the plugin.
6
+ */
7
+ export interface DistributedTracingConfig {
8
+ enabled: boolean;
9
+ injectIntoCommands: boolean;
10
+ extractFromWebhooks: boolean;
11
+ urlPatterns: string[];
12
+ }
13
+ export interface BatchConfig {
14
+ maxQueueSize: number;
15
+ maxExportBatchSize: number;
16
+ scheduledDelayMs: number;
17
+ }
18
+ export interface LogfirePluginConfig {
19
+ token: string;
20
+ projectUrl: string;
21
+ region: 'us' | 'eu';
22
+ environment: string;
23
+ serviceName: string;
24
+ providerName: string;
25
+ captureToolInput: boolean;
26
+ captureToolOutput: boolean;
27
+ toolInputMaxLength: number;
28
+ toolOutputMaxLength: number;
29
+ captureStackTraces: boolean;
30
+ captureMessageContent: boolean;
31
+ captureToolDefinitions: boolean;
32
+ captureInferenceEvents: boolean;
33
+ redactSecrets: boolean;
34
+ distributedTracing: DistributedTracingConfig;
35
+ enableMetrics: boolean;
36
+ metricsIntervalMs: number;
37
+ enableTraceLinks: boolean;
38
+ logLevel: 'debug' | 'info' | 'warn' | 'error';
39
+ resourceAttributes: Record<string, string>;
40
+ spanProcessorType: 'batch' | 'simple';
41
+ batchConfig: BatchConfig;
42
+ }
43
+ /**
44
+ * Merge user-provided config with defaults and env vars.
45
+ * Env vars serve as fallbacks when explicit config is not set.
46
+ */
47
+ export declare function resolveConfig(userConfig: Record<string, unknown> | undefined): LogfirePluginConfig;
48
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AACA;;;;;GAKG;AAEH,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAElC,KAAK,EAAE,MAAM,CAAC;IAGd,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,IAAI,GAAG,IAAI,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IAGpB,YAAY,EAAE,MAAM,CAAC;IAGrB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,sBAAsB,EAAE,OAAO,CAAC;IAChC,sBAAsB,EAAE,OAAO,CAAC;IAChC,aAAa,EAAE,OAAO,CAAC;IAGvB,kBAAkB,EAAE,wBAAwB,CAAC;IAG7C,aAAa,EAAE,OAAO,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAG1B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAG9C,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,iBAAiB,EAAE,OAAO,GAAG,QAAQ,CAAC;IACtC,WAAW,EAAE,WAAW,CAAC;CAC1B;AA0CD;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAC9C,mBAAmB,CAoFrB"}
package/dist/config.js ADDED
@@ -0,0 +1,130 @@
1
+ // SPDX-License-Identifier: MIT
2
+ /**
3
+ * Plugin configuration with sensible defaults.
4
+ *
5
+ * Every option can be left unset for a zero-config quickstart —
6
+ * just export LOGFIRE_TOKEN and enable the plugin.
7
+ */
8
+ const DEFAULTS = {
9
+ token: '',
10
+ projectUrl: '',
11
+ region: 'us',
12
+ environment: '',
13
+ serviceName: 'openclaw-agent',
14
+ providerName: '',
15
+ captureToolInput: true,
16
+ captureToolOutput: false,
17
+ toolInputMaxLength: 2048,
18
+ toolOutputMaxLength: 512,
19
+ captureStackTraces: true,
20
+ captureMessageContent: false,
21
+ captureToolDefinitions: false,
22
+ captureInferenceEvents: false,
23
+ redactSecrets: true,
24
+ distributedTracing: {
25
+ enabled: false,
26
+ injectIntoCommands: true,
27
+ extractFromWebhooks: true,
28
+ urlPatterns: ['*'],
29
+ },
30
+ enableMetrics: true,
31
+ metricsIntervalMs: 60_000,
32
+ enableTraceLinks: true,
33
+ logLevel: 'info',
34
+ resourceAttributes: {},
35
+ spanProcessorType: 'batch',
36
+ batchConfig: {
37
+ maxQueueSize: 2048,
38
+ maxExportBatchSize: 512,
39
+ scheduledDelayMs: 5000,
40
+ },
41
+ };
42
+ /**
43
+ * Merge user-provided config with defaults and env vars.
44
+ * Env vars serve as fallbacks when explicit config is not set.
45
+ */
46
+ export function resolveConfig(userConfig) {
47
+ const raw = userConfig ?? {};
48
+ const distributedTracingRaw = raw.distributedTracing ?? {};
49
+ const batchConfigRaw = raw.batchConfig ?? {};
50
+ return {
51
+ token: asString(raw.token) ||
52
+ process.env.LOGFIRE_TOKEN ||
53
+ '',
54
+ projectUrl: asString(raw.projectUrl) ||
55
+ process.env.LOGFIRE_PROJECT_URL ||
56
+ DEFAULTS.projectUrl,
57
+ region: asEnum(raw.region, ['us', 'eu']) ?? DEFAULTS.region,
58
+ environment: asString(raw.environment) ||
59
+ process.env.LOGFIRE_ENVIRONMENT ||
60
+ 'development',
61
+ serviceName: asString(raw.serviceName) || DEFAULTS.serviceName,
62
+ providerName: asString(raw.providerName) ||
63
+ process.env.LOGFIRE_PROVIDER_NAME ||
64
+ DEFAULTS.providerName,
65
+ captureToolInput: asBool(raw.captureToolInput) ?? DEFAULTS.captureToolInput,
66
+ captureToolOutput: asBool(raw.captureToolOutput) ?? DEFAULTS.captureToolOutput,
67
+ toolInputMaxLength: asInt(raw.toolInputMaxLength) ?? DEFAULTS.toolInputMaxLength,
68
+ toolOutputMaxLength: asInt(raw.toolOutputMaxLength) ?? DEFAULTS.toolOutputMaxLength,
69
+ captureStackTraces: asBool(raw.captureStackTraces) ?? DEFAULTS.captureStackTraces,
70
+ captureMessageContent: asBool(raw.captureMessageContent) ?? DEFAULTS.captureMessageContent,
71
+ captureToolDefinitions: asBool(raw.captureToolDefinitions) ?? DEFAULTS.captureToolDefinitions,
72
+ captureInferenceEvents: asBool(raw.captureInferenceEvents) ?? DEFAULTS.captureInferenceEvents,
73
+ redactSecrets: asBool(raw.redactSecrets) ?? DEFAULTS.redactSecrets,
74
+ distributedTracing: {
75
+ enabled: asBool(distributedTracingRaw.enabled) ??
76
+ DEFAULTS.distributedTracing.enabled,
77
+ injectIntoCommands: asBool(distributedTracingRaw.injectIntoCommands) ??
78
+ DEFAULTS.distributedTracing.injectIntoCommands,
79
+ extractFromWebhooks: asBool(distributedTracingRaw.extractFromWebhooks) ??
80
+ DEFAULTS.distributedTracing.extractFromWebhooks,
81
+ urlPatterns: asStringArray(distributedTracingRaw.urlPatterns) ??
82
+ DEFAULTS.distributedTracing.urlPatterns,
83
+ },
84
+ enableMetrics: asBool(raw.enableMetrics) ?? DEFAULTS.enableMetrics,
85
+ metricsIntervalMs: asInt(raw.metricsIntervalMs) ?? DEFAULTS.metricsIntervalMs,
86
+ enableTraceLinks: asBool(raw.enableTraceLinks) ?? DEFAULTS.enableTraceLinks,
87
+ logLevel: asEnum(raw.logLevel, ['debug', 'info', 'warn', 'error']) ??
88
+ DEFAULTS.logLevel,
89
+ resourceAttributes: asStringRecord(raw.resourceAttributes) ?? DEFAULTS.resourceAttributes,
90
+ spanProcessorType: asEnum(raw.spanProcessorType, ['batch', 'simple']) ??
91
+ DEFAULTS.spanProcessorType,
92
+ batchConfig: {
93
+ maxQueueSize: asInt(batchConfigRaw.maxQueueSize) ?? DEFAULTS.batchConfig.maxQueueSize,
94
+ maxExportBatchSize: asInt(batchConfigRaw.maxExportBatchSize) ??
95
+ DEFAULTS.batchConfig.maxExportBatchSize,
96
+ scheduledDelayMs: asInt(batchConfigRaw.scheduledDelayMs) ??
97
+ DEFAULTS.batchConfig.scheduledDelayMs,
98
+ },
99
+ };
100
+ }
101
+ // --- type coercion helpers ---
102
+ function asString(v) {
103
+ return typeof v === 'string' ? v : '';
104
+ }
105
+ function asBool(v) {
106
+ return typeof v === 'boolean' ? v : undefined;
107
+ }
108
+ function asInt(v) {
109
+ return typeof v === 'number' && Number.isInteger(v) ? v : undefined;
110
+ }
111
+ function asEnum(v, allowed) {
112
+ return typeof v === 'string' && allowed.includes(v)
113
+ ? v
114
+ : undefined;
115
+ }
116
+ function asStringArray(v) {
117
+ return Array.isArray(v) && v.every((x) => typeof x === 'string')
118
+ ? v
119
+ : undefined;
120
+ }
121
+ function asStringRecord(v) {
122
+ if (typeof v !== 'object' || v === null || Array.isArray(v))
123
+ return undefined;
124
+ const entries = Object.entries(v);
125
+ if (entries.every(([, val]) => typeof val === 'string')) {
126
+ return v;
127
+ }
128
+ return undefined;
129
+ }
130
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * W3C trace context propagation for distributed tracing.
3
+ *
4
+ * - Outbound: Injects traceparent into exec/Bash tool arguments
5
+ * when they contain HTTP calls matching configured URL patterns.
6
+ * - Inbound: Extracts traceparent from webhook headers for span linking.
7
+ */
8
+ import { type Span, type SpanContext } from '@opentelemetry/api';
9
+ import type { BeforeToolCallEvent } from '../hooks/before-tool-call.js';
10
+ /**
11
+ * Inject W3C traceparent into exec/Bash tool arguments.
12
+ *
13
+ * Detects curl/wget/httpie commands and appends trace headers.
14
+ * Only injects if the target URL matches one of the configured patterns.
15
+ */
16
+ export declare function injectTraceContext(event: BeforeToolCallEvent, parentSpan: Span, urlPatterns: string[]): void;
17
+ /**
18
+ * Extract W3C trace context from inbound webhook headers.
19
+ * Returns a SpanContext for adding as a span link, or null.
20
+ */
21
+ export declare function extractW3CContext(headers: Record<string, string>): SpanContext | null;
22
+ //# sourceMappingURL=propagation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"propagation.d.ts","sourceRoot":"","sources":["../../src/context/propagation.ts"],"names":[],"mappings":"AACA;;;;;;GAMG;AAEH,OAAO,EAIL,KAAK,IAAI,EACT,KAAK,WAAW,EACjB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAExE;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,mBAAmB,EAC1B,UAAU,EAAE,IAAI,EAChB,WAAW,EAAE,MAAM,EAAE,GACpB,IAAI,CAwCN;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC9B,WAAW,GAAG,IAAI,CAapB"}
@@ -0,0 +1,93 @@
1
+ // SPDX-License-Identifier: MIT
2
+ /**
3
+ * W3C trace context propagation for distributed tracing.
4
+ *
5
+ * - Outbound: Injects traceparent into exec/Bash tool arguments
6
+ * when they contain HTTP calls matching configured URL patterns.
7
+ * - Inbound: Extracts traceparent from webhook headers for span linking.
8
+ */
9
+ import { context, propagation, trace, } from '@opentelemetry/api';
10
+ import picomatch from 'picomatch';
11
+ /**
12
+ * Inject W3C traceparent into exec/Bash tool arguments.
13
+ *
14
+ * Detects curl/wget/httpie commands and appends trace headers.
15
+ * Only injects if the target URL matches one of the configured patterns.
16
+ */
17
+ export function injectTraceContext(event, parentSpan, urlPatterns) {
18
+ const args = event.tool?.args;
19
+ if (!args)
20
+ return;
21
+ const command = typeof args === 'string'
22
+ ? args
23
+ : args.command ??
24
+ args.cmd ??
25
+ '';
26
+ if (typeof command !== 'string')
27
+ return;
28
+ // Only inject into HTTP client commands
29
+ if (!isHttpCommand(command))
30
+ return;
31
+ // Check if the URL matches configured patterns
32
+ const url = extractUrlFromCommand(command);
33
+ if (!url || !matchesPatterns(url, urlPatterns))
34
+ return;
35
+ // Build the traceparent/tracestate headers
36
+ const carrier = {};
37
+ const ctx = trace.setSpan(context.active(), parentSpan);
38
+ propagation.inject(ctx, carrier);
39
+ if (!carrier.traceparent)
40
+ return;
41
+ // Append -H flags to the command
42
+ let headerFlags = ` -H "traceparent: ${carrier.traceparent}"`;
43
+ if (carrier.tracestate) {
44
+ headerFlags += ` -H "tracestate: ${carrier.tracestate}"`;
45
+ }
46
+ // Mutate the event's tool args to include trace headers
47
+ if (typeof args === 'string') {
48
+ event.tool.args = args + headerFlags;
49
+ }
50
+ else if (typeof args.command === 'string') {
51
+ args.command += headerFlags;
52
+ }
53
+ else if (typeof args.cmd === 'string') {
54
+ args.cmd += headerFlags;
55
+ }
56
+ }
57
+ /**
58
+ * Extract W3C trace context from inbound webhook headers.
59
+ * Returns a SpanContext for adding as a span link, or null.
60
+ */
61
+ export function extractW3CContext(headers) {
62
+ const traceparent = headers.traceparent ?? headers.Traceparent ?? headers.TRACEPARENT;
63
+ if (!traceparent)
64
+ return null;
65
+ const carrier = { traceparent };
66
+ const tracestate = headers.tracestate ?? headers.Tracestate ?? headers.TRACESTATE;
67
+ if (tracestate)
68
+ carrier.tracestate = tracestate;
69
+ const extractedCtx = propagation.extract(context.active(), carrier);
70
+ const span = trace.getSpan(extractedCtx);
71
+ return span?.spanContext() ?? null;
72
+ }
73
+ // --- internal helpers ---
74
+ function isHttpCommand(cmd) {
75
+ return /\b(curl|wget|httpie|http)\b/i.test(cmd);
76
+ }
77
+ /**
78
+ * Best-effort URL extraction from a shell command string.
79
+ * Handles common patterns: curl URL, curl -X POST URL, etc.
80
+ */
81
+ function extractUrlFromCommand(cmd) {
82
+ // Match URLs (http:// or https://) in the command
83
+ const match = cmd.match(/https?:\/\/[^\s"']+/);
84
+ return match ? match[0] : null;
85
+ }
86
+ function matchesPatterns(url, patterns) {
87
+ if (patterns.length === 0)
88
+ return false;
89
+ if (patterns.includes('*'))
90
+ return true;
91
+ return patterns.some((pattern) => picomatch.isMatch(url, pattern));
92
+ }
93
+ //# sourceMappingURL=propagation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"propagation.js","sourceRoot":"","sources":["../../src/context/propagation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * In-memory store mapping OpenClaw session keys to active OTEL spans.
3
+ *
4
+ * Tool spans use a stack (LIFO) so nested tool calls close in the
5
+ * correct order. A TTL-based cleanup prevents memory leaks from
6
+ * sessions that never fire agent_end (e.g. gateway crash).
7
+ */
8
+ import type { Span, Context } from '@opentelemetry/api';
9
+ export interface ToolSpanEntry {
10
+ span: Span;
11
+ ctx: Context;
12
+ name: string;
13
+ callId: string;
14
+ startTime: number;
15
+ }
16
+ export interface SessionSpanContext {
17
+ /** Root span: invoke_agent */
18
+ agentSpan: Span;
19
+ agentCtx: Context;
20
+ /** Tool call stack (LIFO for correct nesting) */
21
+ toolStack: ToolSpanEntry[];
22
+ /** Monotonic tool call counter for sequencing */
23
+ toolSequence: number;
24
+ /** Whether any tool errored (propagated to agent span) */
25
+ hasError: boolean;
26
+ /** Request start timestamp */
27
+ startTime: number;
28
+ }
29
+ declare class SpanStore {
30
+ private sessions;
31
+ set(sessionKey: string, ctx: SessionSpanContext): void;
32
+ get(sessionKey: string): SessionSpanContext | undefined;
33
+ delete(sessionKey: string): void;
34
+ /** Push a tool span onto the session's stack. */
35
+ pushTool(sessionKey: string, entry: ToolSpanEntry): void;
36
+ /** Pop the most recent tool span (LIFO). */
37
+ popTool(sessionKey: string): ToolSpanEntry | undefined;
38
+ /** Peek at the top of the tool stack without removing. */
39
+ peekTool(sessionKey: string): ToolSpanEntry | undefined;
40
+ get size(): number;
41
+ /** End orphaned spans and remove stale sessions. */
42
+ private cleanup;
43
+ }
44
+ export declare const spanStore: SpanStore;
45
+ export {};
46
+ //# sourceMappingURL=span-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"span-store.d.ts","sourceRoot":"","sources":["../../src/context/span-store.ts"],"names":[],"mappings":"AACA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAExD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,IAAI,CAAC;IACX,GAAG,EAAE,OAAO,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,8BAA8B;IAC9B,SAAS,EAAE,IAAI,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAElB,iDAAiD;IACjD,SAAS,EAAE,aAAa,EAAE,CAAC;IAE3B,iDAAiD;IACjD,YAAY,EAAE,MAAM,CAAC;IAErB,0DAA0D;IAC1D,QAAQ,EAAE,OAAO,CAAC;IAElB,8BAA8B;IAC9B,SAAS,EAAE,MAAM,CAAC;CACnB;AAKD,cAAM,SAAS;IACb,OAAO,CAAC,QAAQ,CAAyC;IAEzD,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,kBAAkB,GAAG,IAAI;IAKtD,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;IAIvD,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAIhC,iDAAiD;IACjD,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,IAAI;IAMxD,4CAA4C;IAC5C,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAMtD,0DAA0D;IAC1D,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAMvD,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,oDAAoD;IACpD,OAAO,CAAC,OAAO;CAahB;AAED,eAAO,MAAM,SAAS,WAAkB,CAAC"}