@senad-d/observme 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.
- package/.env.example +57 -0
- package/CHANGELOG.md +52 -0
- package/LICENSE +21 -0
- package/ObservMe-Production-Docs/00-README.md +79 -0
- package/ObservMe-Production-Docs/01-requirements-and-scope.md +207 -0
- package/ObservMe-Production-Docs/02-reference-architecture.md +306 -0
- package/ObservMe-Production-Docs/03-pi-event-and-session-model.md +266 -0
- package/ObservMe-Production-Docs/04-telemetry-semantic-conventions.md +722 -0
- package/ObservMe-Production-Docs/05-otel-pipeline-and-collector.md +355 -0
- package/ObservMe-Production-Docs/06-security-privacy-redaction.md +294 -0
- package/ObservMe-Production-Docs/07-extension-implementation-blueprint.md +447 -0
- package/ObservMe-Production-Docs/08-query-grafana-integration.md +276 -0
- package/ObservMe-Production-Docs/09-dashboards-alerts-slos.md +640 -0
- package/ObservMe-Production-Docs/10-testing-release-operations.md +319 -0
- package/ObservMe-Production-Docs/11-deployment-runbooks.md +203 -0
- package/ObservMe-Production-Docs/12-configuration-reference.md +337 -0
- package/ObservMe-Production-Docs/13-source-notes.md +33 -0
- package/ObservMe-Production-Docs/pi-session-format.md +427 -0
- package/README.md +356 -0
- package/SECURITY.md +45 -0
- package/dashboards/observme-agent-node-graphs.json +250 -0
- package/dashboards/observme-agents.json +1880 -0
- package/dashboards/observme-alerts.yaml +113 -0
- package/dashboards/observme-branches-compactions.json +1042 -0
- package/dashboards/observme-cost.json +1254 -0
- package/dashboards/observme-errors.json +1659 -0
- package/dashboards/observme-export-health.json +1802 -0
- package/dashboards/observme-latency.json +1494 -0
- package/dashboards/observme-llm-conversations.json +730 -0
- package/dashboards/observme-logs-llm.json +644 -0
- package/dashboards/observme-models.json +933 -0
- package/dashboards/observme-overview.json +2129 -0
- package/dashboards/observme-slo-health.json +737 -0
- package/dashboards/observme-slos.yaml +56 -0
- package/dashboards/observme-tools.json +902 -0
- package/dashboards/observme-trace-journey.json +1793 -0
- package/docs/STRUCTURE.md +49 -0
- package/docs/agent-subagent-observability-requirements.md +997 -0
- package/docs/compatibility-matrix.md +39 -0
- package/docs/configuration-tui-design-standard.md +767 -0
- package/docs/configuration.md +38 -0
- package/docs/review-validation.md +115 -0
- package/docs/validation-flow.md +117 -0
- package/examples/collector.yaml +123 -0
- package/examples/observme.yaml +131 -0
- package/img/demo.gif +0 -0
- package/img/icon.svg +47 -0
- package/package.json +103 -0
- package/src/commands/obs-agents-runtime.ts +150 -0
- package/src/commands/obs-agents.ts +491 -0
- package/src/commands/obs-args.ts +63 -0
- package/src/commands/obs-backfill.ts +1334 -0
- package/src/commands/obs-command-support.ts +43 -0
- package/src/commands/obs-cost.ts +228 -0
- package/src/commands/obs-diagnostics.ts +22 -0
- package/src/commands/obs-errors.ts +156 -0
- package/src/commands/obs-health.ts +301 -0
- package/src/commands/obs-link.ts +90 -0
- package/src/commands/obs-logs.ts +194 -0
- package/src/commands/obs-loki-summary.ts +184 -0
- package/src/commands/obs-session.ts +259 -0
- package/src/commands/obs-status.ts +359 -0
- package/src/commands/obs-tools.ts +274 -0
- package/src/commands/obs-trace.ts +411 -0
- package/src/commands/obs.ts +211 -0
- package/src/config/bootstrap-project-config.ts +300 -0
- package/src/config/defaults.ts +143 -0
- package/src/config/load-config.ts +631 -0
- package/src/config/project-paths.ts +61 -0
- package/src/config/schema.ts +405 -0
- package/src/config/validate.ts +456 -0
- package/src/constants.ts +4 -0
- package/src/diagnostics/sanitize.ts +6 -0
- package/src/extension.ts +38 -0
- package/src/otel/logs.ts +160 -0
- package/src/otel/metrics.ts +165 -0
- package/src/otel/otlp-endpoint.ts +10 -0
- package/src/otel/sdk.ts +114 -0
- package/src/otel/shutdown.ts +102 -0
- package/src/otel/traces.ts +166 -0
- package/src/pi/agent-lineage.ts +378 -0
- package/src/pi/agent-tree-tracker.ts +258 -0
- package/src/pi/event-handlers/agent-turn.ts +155 -0
- package/src/pi/event-handlers/lifecycle.ts +642 -0
- package/src/pi/event-handlers/llm.ts +115 -0
- package/src/pi/event-handlers/session-events.ts +159 -0
- package/src/pi/event-handlers/tool-bash.ts +275 -0
- package/src/pi/handler-internals.ts +2154 -0
- package/src/pi/handler-runtime.ts +633 -0
- package/src/pi/handler-types.ts +261 -0
- package/src/pi/handlers.ts +75 -0
- package/src/pi/subagent-spawn.ts +975 -0
- package/src/pi/subagent-types.ts +29 -0
- package/src/privacy/content-capture.ts +104 -0
- package/src/privacy/hash.ts +93 -0
- package/src/privacy/redact.ts +619 -0
- package/src/privacy/secret-patterns.ts +185 -0
- package/src/privacy/truncate.ts +69 -0
- package/src/query/grafana-readiness.ts +164 -0
- package/src/query/grafana-transport.ts +481 -0
- package/src/query/grafana.ts +371 -0
- package/src/query/loki.ts +332 -0
- package/src/query/prometheus.ts +388 -0
- package/src/query/tempo.ts +332 -0
- package/src/safety/sensitive-input.ts +208 -0
- package/src/semconv/attributes.ts +279 -0
- package/src/semconv/metrics.ts +146 -0
- package/src/semconv/spans.ts +19 -0
- package/src/semconv/values.ts +13 -0
- package/src/util/bounded-map.ts +97 -0
- package/tsconfig.json +15 -0
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
# ObservMe OTEL Pipeline and Collector Design
|
|
2
|
+
|
|
3
|
+
## 1. Export Strategy
|
|
4
|
+
|
|
5
|
+
ObservMe emits telemetry through OpenTelemetry SDKs using OTLP.
|
|
6
|
+
|
|
7
|
+
Recommended protocol:
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
OTLP/HTTP protobuf to Collector base endpoint http://collector:4318
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Also supported:
|
|
14
|
+
|
|
15
|
+
```text
|
|
16
|
+
OTLP/gRPC to Collector endpoint collector:4317
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## 2. Why Collector First
|
|
20
|
+
|
|
21
|
+
A Collector decouples ObservMe from backend-specific topology. It allows batching, retrying, filtering, redaction, sampling, routing, authentication, and backend replacement without changing the Pi extension.
|
|
22
|
+
|
|
23
|
+
## 3. SDK Exporter Defaults
|
|
24
|
+
|
|
25
|
+
```yaml
|
|
26
|
+
otlp:
|
|
27
|
+
protocol: http/protobuf
|
|
28
|
+
endpoint: http://localhost:4318 # base endpoint; append /v1/{signal} for explicit JS exporter URLs
|
|
29
|
+
signalEndpoints:
|
|
30
|
+
traces: http://localhost:4318/v1/traces
|
|
31
|
+
metrics: http://localhost:4318/v1/metrics
|
|
32
|
+
logs: http://localhost:4318/v1/logs
|
|
33
|
+
timeoutMs: 3000
|
|
34
|
+
headers: {}
|
|
35
|
+
|
|
36
|
+
traces:
|
|
37
|
+
enabled: true
|
|
38
|
+
sampler: parentbased_traceidratio
|
|
39
|
+
sampleRatio: 1.0
|
|
40
|
+
batch:
|
|
41
|
+
maxQueueSize: 2048
|
|
42
|
+
maxExportBatchSize: 512
|
|
43
|
+
scheduledDelayMillis: 1000
|
|
44
|
+
exportTimeoutMillis: 3000
|
|
45
|
+
|
|
46
|
+
metrics:
|
|
47
|
+
enabled: true
|
|
48
|
+
exportIntervalMillis: 15000
|
|
49
|
+
exportTimeoutMillis: 3000
|
|
50
|
+
|
|
51
|
+
logs:
|
|
52
|
+
enabled: true
|
|
53
|
+
batch:
|
|
54
|
+
maxQueueSize: 2048
|
|
55
|
+
maxExportBatchSize: 512
|
|
56
|
+
scheduledDelayMillis: 1000
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The OpenTelemetry JS OTLP HTTP exporters default to signal-specific paths such as `http://localhost:4318/v1/traces`, `http://localhost:4318/v1/metrics`, and `/v1/logs`. Treat `otlp.endpoint` as a base endpoint in ObservMe config, but pass signal-specific URLs to SDK exporters that require an explicit `url`.
|
|
60
|
+
|
|
61
|
+
## 4. Trace Context and Workflow/Agent-Lineage Propagation
|
|
62
|
+
|
|
63
|
+
When ObservMe launches or wraps a subagent process, the parent runtime should propagate both standard trace context and ObservMe-specific lineage:
|
|
64
|
+
|
|
65
|
+
```text
|
|
66
|
+
traceparent
|
|
67
|
+
tracestate
|
|
68
|
+
OBSERVME_WORKFLOW_ID
|
|
69
|
+
OBSERVME_AGENT_ID # optional explicit child id, normally omitted so child generates one
|
|
70
|
+
OBSERVME_PARENT_AGENT_ID
|
|
71
|
+
OBSERVME_ROOT_AGENT_ID
|
|
72
|
+
OBSERVME_PARENT_SESSION_ID
|
|
73
|
+
OBSERVME_PARENT_TRACE_ID
|
|
74
|
+
OBSERVME_PARENT_SPAN_ID
|
|
75
|
+
OBSERVME_AGENT_DEPTH
|
|
76
|
+
OBSERVME_SPAWN_ID
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Preferred behavior is W3C trace-context continuation: the child `pi.session` span becomes part of the same trace as the parent `pi.agent.spawn` span. If the child cannot continue the parent trace, ObservMe should start a new trace and record a span link or structured log with the parent trace/span IDs, `pi.workflow.id`, and `pi.agent.parent_id`.
|
|
80
|
+
|
|
81
|
+
These identifiers are high cardinality. Keep them on resource/span/log attributes only; do not promote them to Collector-generated metric labels or Loki index labels unless an operator explicitly accepts the cardinality cost.
|
|
82
|
+
|
|
83
|
+
## 5. Minimal Debug Collector
|
|
84
|
+
|
|
85
|
+
Use this for local validation.
|
|
86
|
+
|
|
87
|
+
```yaml
|
|
88
|
+
receivers:
|
|
89
|
+
otlp:
|
|
90
|
+
protocols:
|
|
91
|
+
grpc:
|
|
92
|
+
endpoint: 0.0.0.0:4317
|
|
93
|
+
http:
|
|
94
|
+
endpoint: 0.0.0.0:4318
|
|
95
|
+
|
|
96
|
+
processors:
|
|
97
|
+
batch: {}
|
|
98
|
+
|
|
99
|
+
exporters:
|
|
100
|
+
debug:
|
|
101
|
+
verbosity: detailed
|
|
102
|
+
|
|
103
|
+
service:
|
|
104
|
+
pipelines:
|
|
105
|
+
traces:
|
|
106
|
+
receivers: [otlp]
|
|
107
|
+
processors: [batch]
|
|
108
|
+
exporters: [debug]
|
|
109
|
+
metrics:
|
|
110
|
+
receivers: [otlp]
|
|
111
|
+
processors: [batch]
|
|
112
|
+
exporters: [debug]
|
|
113
|
+
logs:
|
|
114
|
+
receivers: [otlp]
|
|
115
|
+
processors: [batch]
|
|
116
|
+
exporters: [debug]
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## 6. Production Collector for Grafana Stack
|
|
120
|
+
|
|
121
|
+
This configuration routes traces to Tempo, logs to Loki, and metrics to a Prometheus-compatible remote write endpoint such as Mimir. Use a Collector distribution that contains every configured component. The minimal debug example works with the core Collector, while `prometheusremotewrite`, `probabilistic_sampler`, and `tail_sampling` are commonly deployed from the Collector Contrib distribution or a vendor distribution such as Grafana Alloy.
|
|
122
|
+
|
|
123
|
+
```yaml
|
|
124
|
+
extensions:
|
|
125
|
+
health_check:
|
|
126
|
+
endpoint: 0.0.0.0:13133
|
|
127
|
+
|
|
128
|
+
receivers:
|
|
129
|
+
otlp:
|
|
130
|
+
protocols:
|
|
131
|
+
grpc:
|
|
132
|
+
endpoint: 0.0.0.0:4317
|
|
133
|
+
http:
|
|
134
|
+
endpoint: 0.0.0.0:4318
|
|
135
|
+
|
|
136
|
+
processors:
|
|
137
|
+
memory_limiter:
|
|
138
|
+
check_interval: 1s
|
|
139
|
+
limit_mib: 1024
|
|
140
|
+
spike_limit_mib: 256
|
|
141
|
+
|
|
142
|
+
batch:
|
|
143
|
+
timeout: 2s
|
|
144
|
+
send_batch_size: 1024
|
|
145
|
+
send_batch_max_size: 2048
|
|
146
|
+
|
|
147
|
+
resource/observme:
|
|
148
|
+
attributes:
|
|
149
|
+
- key: telemetry.source
|
|
150
|
+
value: observme
|
|
151
|
+
action: upsert
|
|
152
|
+
- key: service.name
|
|
153
|
+
value: observme-pi-extension
|
|
154
|
+
action: insert
|
|
155
|
+
- key: service.namespace
|
|
156
|
+
value: pi
|
|
157
|
+
action: upsert
|
|
158
|
+
|
|
159
|
+
resource/drop_high_cardinality_metric_attrs:
|
|
160
|
+
attributes:
|
|
161
|
+
- key: pi.workflow.id
|
|
162
|
+
action: delete
|
|
163
|
+
- key: pi.workflow.root_agent_id
|
|
164
|
+
action: delete
|
|
165
|
+
- key: pi.agent.id
|
|
166
|
+
action: delete
|
|
167
|
+
- key: pi.agent.parent_id
|
|
168
|
+
action: delete
|
|
169
|
+
- key: pi.agent.root_id
|
|
170
|
+
action: delete
|
|
171
|
+
- key: pi.agent.run.id
|
|
172
|
+
action: delete
|
|
173
|
+
- key: pi.agent.spawn.id
|
|
174
|
+
action: delete
|
|
175
|
+
- key: pi.agent.spawn.tool_call_id
|
|
176
|
+
action: delete
|
|
177
|
+
- key: pi.agent.child.id
|
|
178
|
+
action: delete
|
|
179
|
+
- key: pi.session.id
|
|
180
|
+
action: delete
|
|
181
|
+
|
|
182
|
+
# Drops accidental content attributes from logs. Intentional LLM content capture
|
|
183
|
+
# is emitted as already-redacted log bodies and opt-in span attributes.
|
|
184
|
+
attributes/drop_content_attributes:
|
|
185
|
+
actions:
|
|
186
|
+
- key: gen_ai.input.messages
|
|
187
|
+
action: delete
|
|
188
|
+
- key: gen_ai.output.messages
|
|
189
|
+
action: delete
|
|
190
|
+
- key: pi.llm.prompt.redacted
|
|
191
|
+
action: delete
|
|
192
|
+
- key: pi.llm.response.redacted
|
|
193
|
+
action: delete
|
|
194
|
+
- key: pi.llm.thinking.redacted
|
|
195
|
+
action: delete
|
|
196
|
+
- key: pi.tool.arguments.redacted
|
|
197
|
+
action: delete
|
|
198
|
+
- key: pi.tool.result.redacted
|
|
199
|
+
action: delete
|
|
200
|
+
|
|
201
|
+
exporters:
|
|
202
|
+
otlp/tempo:
|
|
203
|
+
endpoint: tempo:4317
|
|
204
|
+
tls:
|
|
205
|
+
insecure: true
|
|
206
|
+
sending_queue:
|
|
207
|
+
enabled: true
|
|
208
|
+
retry_on_failure:
|
|
209
|
+
enabled: true
|
|
210
|
+
|
|
211
|
+
otlphttp/loki:
|
|
212
|
+
endpoint: http://loki:3100/otlp
|
|
213
|
+
sending_queue:
|
|
214
|
+
enabled: true
|
|
215
|
+
retry_on_failure:
|
|
216
|
+
enabled: true
|
|
217
|
+
|
|
218
|
+
prometheusremotewrite/mimir:
|
|
219
|
+
endpoint: http://mimir:9009/api/v1/push
|
|
220
|
+
resource_to_telemetry_conversion:
|
|
221
|
+
enabled: true
|
|
222
|
+
sending_queue:
|
|
223
|
+
enabled: true
|
|
224
|
+
retry_on_failure:
|
|
225
|
+
enabled: true
|
|
226
|
+
|
|
227
|
+
debug:
|
|
228
|
+
verbosity: basic
|
|
229
|
+
|
|
230
|
+
service:
|
|
231
|
+
extensions: [health_check]
|
|
232
|
+
pipelines:
|
|
233
|
+
traces:
|
|
234
|
+
receivers: [otlp]
|
|
235
|
+
processors: [memory_limiter, resource/observme, batch]
|
|
236
|
+
exporters: [otlp/tempo]
|
|
237
|
+
|
|
238
|
+
metrics:
|
|
239
|
+
receivers: [otlp]
|
|
240
|
+
processors: [memory_limiter, resource/observme, resource/drop_high_cardinality_metric_attrs, batch]
|
|
241
|
+
exporters: [prometheusremotewrite/mimir]
|
|
242
|
+
|
|
243
|
+
logs:
|
|
244
|
+
receivers: [otlp]
|
|
245
|
+
processors: [memory_limiter, resource/observme, attributes/drop_content_attributes, batch]
|
|
246
|
+
exporters: [otlphttp/loki]
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
The Collector attribute processor is defense in depth for log attributes only. It must not be the only redaction layer, and it does not sanitize arbitrary log bodies; ObservMe must redact or drop sensitive content before export. The traces pipeline intentionally keeps `pi.llm.prompt.redacted`, `pi.llm.response.redacted`, and `pi.llm.thinking.redacted` so Tempo can display redacted content after explicit capture is enabled. Old telemetry that an earlier Collector dropped cannot be recovered; generate new LLM events after updating the Collector.
|
|
250
|
+
|
|
251
|
+
Keep high-cardinality lineage attributes on traces/logs, but remove them from the metrics pipeline unless the organization explicitly accepts the cardinality. The bundled local Loki pipeline promotes `pi.agent.id` and `pi.agent.run.id` as log labels so the LLM Conversations dashboard can filter captured chat content by agent and run. Prometheus resource-to-telemetry conversion is safe only after the metrics pipeline drops `pi.workflow.id`, `pi.agent.id`, `pi.session.id`, trace IDs, and spawn IDs; the remaining generated `service.instance.id`/`observme.instance.id` labels keep concurrent ObservMe metric streams distinct so session counters can be summed accurately.
|
|
252
|
+
|
|
253
|
+
## 7. Direct-to-Backend Development Mode
|
|
254
|
+
|
|
255
|
+
Allowed only for development:
|
|
256
|
+
|
|
257
|
+
```text
|
|
258
|
+
ObservMe -> Tempo OTLP HTTP for traces
|
|
259
|
+
ObservMe -> Loki OTLP HTTP for logs
|
|
260
|
+
ObservMe -> Prometheus OTLP HTTP receiver for metrics only
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
Not recommended for production because every Pi agent would need backend credentials and backend-specific routing. If direct metric export is used, configure SDK views/exporter resource handling so `pi.workflow.*`, `pi.agent.*`, `pi.session.id`, trace IDs, and spawn IDs are not emitted as Prometheus labels.
|
|
264
|
+
|
|
265
|
+
## 8. Sampling Strategy
|
|
266
|
+
|
|
267
|
+
Default for developer and CI agents:
|
|
268
|
+
|
|
269
|
+
```yaml
|
|
270
|
+
traces:
|
|
271
|
+
sampleRatio: 1.0
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Production high-volume environments can sample traces in the Collector:
|
|
275
|
+
|
|
276
|
+
```yaml
|
|
277
|
+
processors:
|
|
278
|
+
probabilistic_sampler:
|
|
279
|
+
sampling_percentage: 25
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
For AI agent observability, tail sampling can be valuable:
|
|
283
|
+
|
|
284
|
+
- Always keep errors.
|
|
285
|
+
- Always keep expensive turns.
|
|
286
|
+
- Always keep tool failures.
|
|
287
|
+
- Sample successful low-cost turns.
|
|
288
|
+
|
|
289
|
+
Example policy concept:
|
|
290
|
+
|
|
291
|
+
```yaml
|
|
292
|
+
processors:
|
|
293
|
+
tail_sampling:
|
|
294
|
+
decision_wait: 10s
|
|
295
|
+
policies:
|
|
296
|
+
- name: keep-errors
|
|
297
|
+
type: status_code
|
|
298
|
+
status_code:
|
|
299
|
+
status_codes: [ERROR]
|
|
300
|
+
- name: keep-expensive
|
|
301
|
+
type: numeric_attribute
|
|
302
|
+
numeric_attribute:
|
|
303
|
+
key: pi.llm.cost.total_usd
|
|
304
|
+
min_value: 0.10
|
|
305
|
+
- name: sample-rest
|
|
306
|
+
type: probabilistic
|
|
307
|
+
probabilistic:
|
|
308
|
+
sampling_percentage: 20
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
## 9. Collector Security
|
|
312
|
+
|
|
313
|
+
Production collectors must:
|
|
314
|
+
|
|
315
|
+
- Require TLS or run inside trusted network boundaries.
|
|
316
|
+
- Authenticate external agents.
|
|
317
|
+
- Restrict OTLP ingestion ports.
|
|
318
|
+
- Apply rate limits at ingress.
|
|
319
|
+
- Avoid exposing collector debug endpoints publicly.
|
|
320
|
+
- Use separate tenants or headers for environments.
|
|
321
|
+
|
|
322
|
+
## 10. Multi-Tenant Routing
|
|
323
|
+
|
|
324
|
+
Use resource attributes or headers:
|
|
325
|
+
|
|
326
|
+
```text
|
|
327
|
+
observme.tenant.id
|
|
328
|
+
deployment.environment.name
|
|
329
|
+
observme.environment
|
|
330
|
+
pi.project.name
|
|
331
|
+
pi.agent.role
|
|
332
|
+
pi.agent.depth
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
Collector routing can send tenants to separate backends or tenants within Mimir/Loki/Tempo.
|
|
336
|
+
|
|
337
|
+
## 11. Backend Notes
|
|
338
|
+
|
|
339
|
+
### Tempo
|
|
340
|
+
|
|
341
|
+
Use Tempo for traces. Send via OTLP gRPC or HTTP. Prefer Collector -> Tempo.
|
|
342
|
+
|
|
343
|
+
### Loki
|
|
344
|
+
|
|
345
|
+
Use Loki OTLP ingestion for logs. Ensure structured metadata support is enabled for Loki versions/configurations that require it.
|
|
346
|
+
|
|
347
|
+
### Prometheus / Mimir
|
|
348
|
+
|
|
349
|
+
For Prometheus-only setups, choose one:
|
|
350
|
+
|
|
351
|
+
1. Collector exposes Prometheus scrape endpoint.
|
|
352
|
+
2. Prometheus enables the OTLP HTTP receiver with `--web.enable-otlp-receiver`; send SDK metrics to base endpoint `http://prometheus:9090/api/v1/otlp` when the exporter appends `/v1/metrics`, or to explicit URL `http://prometheus:9090/api/v1/otlp/v1/metrics` when configuring a signal-specific exporter URL.
|
|
353
|
+
3. Collector remote writes to Mimir, Thanos, Cortex, or compatible backend.
|
|
354
|
+
|
|
355
|
+
For production scale, Mimir or compatible remote write backend is preferred.
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
# ObservMe Security, Privacy, and Redaction Specification
|
|
2
|
+
|
|
3
|
+
## 1. Security Philosophy
|
|
4
|
+
|
|
5
|
+
ObservMe observes AI agents that may process source code, credentials, logs, customer data, incident data, infrastructure names, filesystem paths, and proprietary prompts. Therefore, ObservMe must be privacy-preserving by default.
|
|
6
|
+
|
|
7
|
+
## 2. Default Capture Policy
|
|
8
|
+
|
|
9
|
+
Default configuration:
|
|
10
|
+
|
|
11
|
+
```yaml
|
|
12
|
+
capture:
|
|
13
|
+
prompts: false
|
|
14
|
+
responses: false
|
|
15
|
+
thinking: false
|
|
16
|
+
toolArguments: false
|
|
17
|
+
toolResults: false
|
|
18
|
+
bashCommands: false
|
|
19
|
+
bashOutput: false
|
|
20
|
+
filePaths: false
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Failed-tool output is content, not default operational metadata. It may appear in the Tools dashboard only after `capture.toolResults` is explicitly enabled. The value must pass the shared capture policy before being emitted as the body of a dedicated `tool.error.captured` log; capture-disabled and fail-closed redaction paths emit no body. Broad session-log queries must exclude `event.category="tool_content"`.
|
|
24
|
+
|
|
25
|
+
Default allowed metadata:
|
|
26
|
+
|
|
27
|
+
```text
|
|
28
|
+
lengths
|
|
29
|
+
hashes
|
|
30
|
+
counts
|
|
31
|
+
durations
|
|
32
|
+
status
|
|
33
|
+
model/provider
|
|
34
|
+
token usage
|
|
35
|
+
cost
|
|
36
|
+
tool names
|
|
37
|
+
error class
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## 3. Data Classification
|
|
41
|
+
|
|
42
|
+
### Safe by Default
|
|
43
|
+
|
|
44
|
+
- Provider name
|
|
45
|
+
- Model name
|
|
46
|
+
- Token counts
|
|
47
|
+
- Cost numbers
|
|
48
|
+
- Stop reason
|
|
49
|
+
- Tool name
|
|
50
|
+
- Boolean success/failure
|
|
51
|
+
- Redacted error class
|
|
52
|
+
- Duration
|
|
53
|
+
- Generated agent role/depth metadata
|
|
54
|
+
|
|
55
|
+
### Sensitive
|
|
56
|
+
|
|
57
|
+
- User prompts
|
|
58
|
+
- Assistant responses
|
|
59
|
+
- Thinking/reasoning content
|
|
60
|
+
- Tool arguments
|
|
61
|
+
- Tool results
|
|
62
|
+
- Bash commands
|
|
63
|
+
- Bash output
|
|
64
|
+
- Full file paths
|
|
65
|
+
- Git remote URLs
|
|
66
|
+
- Environment variables
|
|
67
|
+
- Stack traces
|
|
68
|
+
- Raw parent process command lines or environment variables used to launch subagents
|
|
69
|
+
|
|
70
|
+
### Highly Sensitive
|
|
71
|
+
|
|
72
|
+
- API keys
|
|
73
|
+
- Tokens
|
|
74
|
+
- Passwords
|
|
75
|
+
- SSH keys
|
|
76
|
+
- Private certificates
|
|
77
|
+
- Personal data
|
|
78
|
+
- Customer data
|
|
79
|
+
- Proprietary code snippets
|
|
80
|
+
|
|
81
|
+
## 4. Redaction Pipeline
|
|
82
|
+
|
|
83
|
+
Every optional content field must pass through:
|
|
84
|
+
|
|
85
|
+
```text
|
|
86
|
+
raw value
|
|
87
|
+
-> size guard
|
|
88
|
+
-> secret detector
|
|
89
|
+
-> PII detector if enabled
|
|
90
|
+
-> path scrubber
|
|
91
|
+
-> custom regex redactors
|
|
92
|
+
-> truncation
|
|
93
|
+
-> hashing
|
|
94
|
+
-> export
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## 5. Secret Detection Patterns
|
|
98
|
+
|
|
99
|
+
Minimum built-in patterns:
|
|
100
|
+
|
|
101
|
+
```text
|
|
102
|
+
AWS access key id: (A3T[A-Z0-9]|AKIA|ASIA)[0-9A-Z]{16}
|
|
103
|
+
Generic bearer token: (?i)bearer\s+[a-z0-9._\-]{20,}
|
|
104
|
+
GitHub token: (gh[pousr]_[A-Za-z0-9_]{36,}|github_pat_[A-Za-z0-9_]{22,255})
|
|
105
|
+
OpenAI-like key: sk-[A-Za-z0-9_-]{20,}
|
|
106
|
+
Anthropic-like key: sk-ant-[A-Za-z0-9_-]{20,}
|
|
107
|
+
Slack token: xox[baprs]-[A-Za-z0-9-]{10,}
|
|
108
|
+
Private key block: -----BEGIN [A-Z ]*PRIVATE KEY-----
|
|
109
|
+
Password assignment: (?i)(password|passwd|pwd)\s*[:=]\s*[^\s]+
|
|
110
|
+
API key assignment: (?i)(api[_-]?key|token|secret|client[_-]?secret)\s*[:=]\s*[^\s]+
|
|
111
|
+
URL credentials: [a-z][a-z0-9+.-]*://[^\s:/?#]+:[^\s@/]+@
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
These patterns are a minimum safety net, not a complete secret scanner. Keep them covered by tests and allow organizations to add custom regexes for proprietary credential formats.
|
|
115
|
+
|
|
116
|
+
Matched values are replaced with:
|
|
117
|
+
|
|
118
|
+
```text
|
|
119
|
+
[REDACTED:<type>:<sha256-prefix>]
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## 6. Path Redaction
|
|
123
|
+
|
|
124
|
+
Path recognition covers standalone and embedded POSIX absolute paths, Windows drive paths, and UNC paths. It must use the matching POSIX or Windows basename/dirname semantics and must not classify normal URLs or harmless slash-separated prose as filesystem paths.
|
|
125
|
+
|
|
126
|
+
Representative sensitive inputs:
|
|
127
|
+
|
|
128
|
+
```text
|
|
129
|
+
/home/alice/projects/customer-x/app.ts
|
|
130
|
+
/workspace/project/file.ts
|
|
131
|
+
/etc/hosts
|
|
132
|
+
C:\Users\alice\secret.txt
|
|
133
|
+
\\server\share\secret.txt
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Options:
|
|
137
|
+
|
|
138
|
+
```yaml
|
|
139
|
+
privacy:
|
|
140
|
+
pathMode: hash # hash|basename|full|drop
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
`hash`, `basename`, and `drop` must remove every recognized raw absolute path. Hashes are deterministic only within the configured tenant salt and fail closed when salt resolution fails. `drop` omits a standalone path and uses a bounded placeholder for an embedded path. `full` is the only explicit mode that preserves raw path text; it is reached only after the relevant content/path capture opt-in, and all other redaction stages still apply. URL credential redaction runs before path handling so the remaining URL is not malformed.
|
|
144
|
+
|
|
145
|
+
## 7. Hashing
|
|
146
|
+
|
|
147
|
+
Hashes are used for correlation without storing raw data.
|
|
148
|
+
|
|
149
|
+
Recommended minimum:
|
|
150
|
+
|
|
151
|
+
```text
|
|
152
|
+
sha256(tenant_salt + "\0" + normalized_value)
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Preferred when the salt is secret:
|
|
156
|
+
|
|
157
|
+
```text
|
|
158
|
+
hmac_sha256(tenant_salt, normalized_value)
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Use a tenant-specific salt to prevent cross-tenant dictionary attacks. The salt itself is a secret and must come from environment or secure runtime configuration.
|
|
162
|
+
|
|
163
|
+
## 8. Workflow and Agent Identity Privacy
|
|
164
|
+
|
|
165
|
+
Workflow, agent, and subagent lineage should use generated IDs or salted hashes only:
|
|
166
|
+
|
|
167
|
+
```text
|
|
168
|
+
pi.workflow.id
|
|
169
|
+
pi.workflow.root_agent_id
|
|
170
|
+
pi.agent.id
|
|
171
|
+
pi.agent.parent_id
|
|
172
|
+
pi.agent.root_id
|
|
173
|
+
pi.agent.spawn.id
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Do not derive these IDs directly from raw cwd, username, prompt text, file path, shell command, PID, container name, or hostname. Treat parent-process command lines and inherited environment variables as sensitive; if they are captured for debugging, they must pass through the redaction pipeline first.
|
|
177
|
+
|
|
178
|
+
Workflow IDs and agent IDs are high-cardinality operational identifiers. They may be exported as resource/span/log attributes for drill-down, but they must not be metric labels by default.
|
|
179
|
+
|
|
180
|
+
## 9. Content Size Limits
|
|
181
|
+
|
|
182
|
+
Defaults:
|
|
183
|
+
|
|
184
|
+
```yaml
|
|
185
|
+
limits:
|
|
186
|
+
maxPromptChars: 12000
|
|
187
|
+
maxResponseChars: 12000
|
|
188
|
+
maxToolArgumentChars: 8000
|
|
189
|
+
maxToolResultChars: 16000
|
|
190
|
+
maxBashOutputChars: 16000
|
|
191
|
+
maxLogBodyChars: 32000
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
If content exceeds limit:
|
|
195
|
+
|
|
196
|
+
- Truncate
|
|
197
|
+
- Add attribute `observme.truncated=true`
|
|
198
|
+
- Add original length attribute
|
|
199
|
+
|
|
200
|
+
## 10. Opt-in LLM Content Export
|
|
201
|
+
|
|
202
|
+
Prompt, response, and thinking bodies are not exported by default. They become visible in Tempo and Loki only when the corresponding capture flag is enabled, redaction remains enabled, and a tenant hash salt is available for the session:
|
|
203
|
+
|
|
204
|
+
```text
|
|
205
|
+
OBSERVME_CAPTURE_PROMPTS=true
|
|
206
|
+
OBSERVME_CAPTURE_RESPONSES=true
|
|
207
|
+
OBSERVME_CAPTURE_THINKING=true
|
|
208
|
+
OBSERVME_REDACTION_ENABLED=true
|
|
209
|
+
OBSERVME_HASH_SALT=<project-specific-random-salt>
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Set `OBSERVME_ALLOW_UNSAFE_CAPTURE=true` only with `OBSERVME_REDACTION_ENABLED=false` for intentionally raw local debugging. When redacted capture is enabled, ObservMe writes the already-redacted value to the LLM span attribute (`pi.llm.prompt.redacted`, `pi.llm.response.redacted`, or `pi.llm.thinking.redacted`) and emits one correlated Loki log whose body is the same redacted value.
|
|
213
|
+
|
|
214
|
+
Example:
|
|
215
|
+
|
|
216
|
+
```json
|
|
217
|
+
{
|
|
218
|
+
"event.name": "llm.prompt.captured",
|
|
219
|
+
"event.category": "llm_content",
|
|
220
|
+
"pi.session.id": "...",
|
|
221
|
+
"pi.turn.id": "...",
|
|
222
|
+
"pi.llm.content.kind": "prompt",
|
|
223
|
+
"trace_id": "...",
|
|
224
|
+
"span_id": "...",
|
|
225
|
+
"body": "<redacted prompt>"
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
The Collector cannot recover content dropped by an older configuration; generate new LLM events after updating the Collector and dashboards. Do not use raw chat text in Loki or Tempo query strings.
|
|
230
|
+
|
|
231
|
+
## 11. Authentication
|
|
232
|
+
|
|
233
|
+
ObservMe supports OTLP headers:
|
|
234
|
+
|
|
235
|
+
```yaml
|
|
236
|
+
otlp:
|
|
237
|
+
headers:
|
|
238
|
+
Authorization: "Bearer ${OBSERVME_OTLP_TOKEN}"
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Secrets must be read from environment variables or secure runtime config, not hardcoded in extension source.
|
|
242
|
+
|
|
243
|
+
## 12. TLS
|
|
244
|
+
|
|
245
|
+
Production default:
|
|
246
|
+
|
|
247
|
+
```yaml
|
|
248
|
+
otlp:
|
|
249
|
+
tls:
|
|
250
|
+
enabled: true
|
|
251
|
+
insecureSkipVerify: false
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Development may use insecure local endpoints only when explicitly configured.
|
|
255
|
+
|
|
256
|
+
## 13. Tenant Isolation
|
|
257
|
+
|
|
258
|
+
Set tenant and environment as resource attributes:
|
|
259
|
+
|
|
260
|
+
```yaml
|
|
261
|
+
resource:
|
|
262
|
+
attributes:
|
|
263
|
+
observme.tenant.id: platform
|
|
264
|
+
deployment.environment.name: production
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Never derive tenant solely from raw cwd or username.
|
|
268
|
+
|
|
269
|
+
## 14. Auditability
|
|
270
|
+
|
|
271
|
+
ObservMe should emit security-relevant logs:
|
|
272
|
+
|
|
273
|
+
- capture settings at startup
|
|
274
|
+
- agent-lineage propagation enabled/disabled
|
|
275
|
+
- redaction enabled/disabled
|
|
276
|
+
- redaction failures
|
|
277
|
+
- exporter authentication failures
|
|
278
|
+
- rejected unsafe config
|
|
279
|
+
|
|
280
|
+
Do not log secrets while reporting security failures.
|
|
281
|
+
|
|
282
|
+
## 15. Safe Config Validation
|
|
283
|
+
|
|
284
|
+
Reject config if:
|
|
285
|
+
|
|
286
|
+
- capture is enabled but redaction is disabled, unless `allowUnsafeCapture: true`
|
|
287
|
+
- OTLP endpoint is plain HTTP in production, unless `allowInsecureTransport: true`
|
|
288
|
+
- metric labels include forbidden high-cardinality fields such as workflow IDs, session IDs, or agent IDs
|
|
289
|
+
- propagated workflow or agent lineage values are malformed, too long, or contain unsafe characters
|
|
290
|
+
- queue sizes exceed configured memory limits
|
|
291
|
+
|
|
292
|
+
## 16. Compliance Posture
|
|
293
|
+
|
|
294
|
+
ObservMe does not claim compliance by itself. It provides controls needed for organizations to implement compliant telemetry pipelines. Retention, access control, deletion, and legal policy are backend responsibilities.
|