@senad-d/observme 0.1.3 → 0.1.5
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 +4 -0
- package/CHANGELOG.md +48 -0
- package/README.md +36 -11
- package/dashboards/observme-agent-node-graphs.json +5 -5
- package/dashboards/observme-agents.json +169 -4
- package/dashboards/observme-alerts.yaml +16 -3
- package/dashboards/observme-overview.json +6 -6
- package/dashboards/observme-trace-journey.json +4 -4
- package/docs/agent-subagent-observability-requirements.md +19 -10
- package/docs/compatibility-matrix.md +21 -4
- package/docs/configuration.md +7 -2
- package/docs/extension-integration.md +20 -13
- package/docs/reference/03-pi-event-and-session-model.md +6 -6
- package/docs/reference/04-telemetry-semantic-conventions.md +39 -1
- package/docs/reference/05-otel-pipeline-and-collector.md +23 -10
- package/docs/reference/06-security-privacy-redaction.md +13 -6
- package/docs/reference/08-query-grafana-integration.md +30 -7
- package/docs/reference/09-dashboards-alerts-slos.md +132 -3
- package/docs/reference/10-testing-release-operations.md +44 -14
- package/docs/reference/11-deployment-runbooks.md +82 -5
- package/docs/reference/12-configuration-reference.md +48 -5
- package/docs/review-validation.md +17 -0
- package/examples/README.md +7 -2
- package/examples/collector.yaml +8 -8
- package/examples/integrations/subagent-runner.ts +8 -5
- package/examples/observme.yaml +3 -2
- package/package.json +14 -4
- package/src/commands/obs-agents.ts +17 -12
- package/src/commands/obs-backfill.ts +2 -2
- package/src/commands/obs-command-support.ts +2 -1
- package/src/commands/obs-cost.ts +15 -7
- package/src/commands/obs-health.ts +22 -2
- package/src/commands/obs-loki-summary.ts +4 -8
- package/src/commands/obs-session.ts +35 -28
- package/src/commands/obs-status.ts +56 -13
- package/src/commands/obs-tools.ts +19 -8
- package/src/commands/obs-trace.ts +9 -0
- package/src/commands/obs.ts +6 -1
- package/src/config/bootstrap-project-config.ts +50 -32
- package/src/config/defaults.ts +1 -2
- package/src/config/load-config.ts +270 -81
- package/src/config/project-paths.ts +318 -6
- package/src/config/query-limits.ts +10 -0
- package/src/config/schema.ts +18 -8
- package/src/config/transport-security.ts +107 -0
- package/src/config/validate.ts +88 -12
- package/src/extension.ts +2 -12
- package/src/integration.ts +6 -2
- package/src/otel/logs.ts +24 -13
- package/src/otel/metrics.ts +24 -13
- package/src/otel/otlp-endpoint.ts +41 -2
- package/src/otel/otlp-http-options.ts +11 -0
- package/src/otel/sdk.ts +155 -9
- package/src/otel/shutdown.ts +39 -11
- package/src/otel/traces.ts +34 -16
- package/src/pi/active-agent-lease.ts +101 -0
- package/src/pi/agent-tree-tracker.ts +14 -1
- package/src/pi/compatibility.ts +121 -0
- package/src/pi/event-handlers/agent-turn.ts +16 -9
- package/src/pi/event-handlers/lifecycle.ts +312 -106
- package/src/pi/event-handlers/llm.ts +17 -9
- package/src/pi/event-handlers/session-events.ts +53 -19
- package/src/pi/event-handlers/tool-bash.ts +21 -27
- package/src/pi/handler-internals.ts +16 -26
- package/src/pi/handler-runtime.ts +159 -54
- package/src/pi/handler-types.ts +40 -17
- package/src/pi/handlers.ts +12 -1
- package/src/pi/integration-api.ts +27 -15
- package/src/pi/session-correlation.ts +167 -0
- package/src/pi/subagent-spawn.ts +164 -31
- package/src/privacy/redact.ts +574 -68
- package/src/privacy/secret-patterns.ts +6 -1
- package/src/query/grafana-readiness.ts +18 -2
- package/src/query/grafana-transport.ts +150 -27
- package/src/query/grafana-url.ts +36 -0
- package/src/query/grafana.ts +4 -136
- package/src/query/loki.ts +2 -4
- package/src/query/prometheus.ts +8 -10
- package/src/query/tempo.ts +2 -4
- package/src/query/trace-link.ts +186 -0
- package/src/safety/display-bounds.ts +84 -0
- package/src/semconv/metrics.ts +7 -0
- package/src/semconv/values.ts +2 -0
package/.env.example
CHANGED
|
@@ -13,6 +13,10 @@ OBSERVME_TENANT=local-dev
|
|
|
13
13
|
OBSERVME_OTLP_ENDPOINT=http://localhost:4318
|
|
14
14
|
OBSERVME_OTLP_PROTOCOL=http/protobuf
|
|
15
15
|
|
|
16
|
+
# Active-agent lease duration. Must be 10000-300000 ms and at least
|
|
17
|
+
# twice the metric export interval plus 5000 ms of clock-skew margin.
|
|
18
|
+
OBSERVME_ACTIVE_AGENT_LEASE_DURATION_MS=60000
|
|
19
|
+
|
|
16
20
|
# Optional OTLP bearer token for remote/secured collectors. Leave blank for local dev.
|
|
17
21
|
OBSERVME_OTLP_TOKEN=
|
|
18
22
|
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,12 @@
|
|
|
4
4
|
|
|
5
5
|
### Added
|
|
6
6
|
|
|
7
|
+
- Added a bounded GitHub-hosted Linux CI job for active-agent lease contracts and cancellation-oriented Docker integration coverage, with resource-labeled unconditional cleanup.
|
|
8
|
+
- Added Docker-backed active-agent lease integration coverage for clean shutdown, `SIGTERM`, and `SIGKILL`, proving cached raw claims outlive lease-aware activity without a Collector restart.
|
|
9
|
+
- Added a session-scoped active-agent lease controller that renews from the SDK metric collection cycle with an injectable wall clock and deterministic disposal.
|
|
10
|
+
- Added the `observme_agent_lease_expires_unixtime_seconds` asynchronous gauge contract with unit metadata and deterministic observable callback test support.
|
|
11
|
+
- Added bounded `metrics.activeAgentLeaseDurationMillis` configuration with layered `OBSERVME_ACTIVE_AGENT_LEASE_DURATION_MS` loading, fail-safe validation, and generated/example configuration coverage.
|
|
12
|
+
- Added a production-readiness task plan for lease-based active-agent accounting that remains accurate after crashes, forced termination, and cancelled GitHub Actions jobs.
|
|
7
13
|
- Added a packaged `observme-docs` Pi skill that routes natural-language ObservMe questions to focused user, operator, reference, example, and contributor documentation through Pi's normal skill discovery, without an ObservMe system-prompt hook.
|
|
8
14
|
- Added a versioned `@senad-d/observme/integration` event-bus API and transport-agnostic child-runner example for parent-side spawn/wait/join telemetry and child process lineage propagation.
|
|
9
15
|
- Added README tables cataloging available metrics, trace spans, and structured log events, including opt-in and reserved signals.
|
|
@@ -15,6 +21,15 @@
|
|
|
15
21
|
|
|
16
22
|
### Changed
|
|
17
23
|
|
|
24
|
+
- Made the 0.1.5 hardening patch self-contained with explicit review units, all imported production modules included, and unrelated specification history preserved.
|
|
25
|
+
- Established a typed Pi event registration contract, removed non-event legacy registrations, pinned the release-resolved Pi API, and added minimum/release compatibility validation with pre-registration diagnostics.
|
|
26
|
+
- Centralized embedded-credential Grafana URL diagnostics so configuration validation, readiness checks, URL construction, and transports share one safe failure class and operator guidance.
|
|
27
|
+
- Documented credential-free Grafana base URLs and the fail-closed canonical project-file boundary across configuration, security, query, and troubleshooting guidance.
|
|
28
|
+
- Completed production active-agent lease documentation, raw-query migration guidance, GitHub Actions/self-hosted clock and cleanup runbooks, missing/expired-lease troubleshooting, Collector restart semantics, and sanitized release-validation evidence.
|
|
29
|
+
- Reframed the Collector's five-minute Prometheus `metric_expiration` as exporter-wide stale-series/cardinality cleanup, longer than the default active-agent lease and independent of leased liveness.
|
|
30
|
+
- Migrated active-agent dashboard totals, bounded breakdowns, aggregate topology inputs, and stuck-high alerts to leased activity, with raw/expired-claim diagnostics and a deployment-tunable stale-claim alert.
|
|
31
|
+
- Defined and enforced canonical lease-aware active-agent PromQL for totals, bounded breakdowns, topology inputs, and alerts, including replica deduplication, future-lease rejection, and zero-safe idle states.
|
|
32
|
+
- Documented the production active-agent lease, clock, convergence, instance-join, failure-mode, and backward-compatibility contract used by upcoming runtime and dashboard integration.
|
|
18
33
|
- Moved the detailed technical reference into `docs/reference/` and updated package, documentation, examples, dashboards, tests, and skill routes to use the new location.
|
|
19
34
|
- Made the packaged `observme-docs` skill resolve routed references from its installed package root instead of the caller's working directory or a repository checkout.
|
|
20
35
|
- Reorganized documentation around `docs/README.md`, a categorized technical-reference index, and an example guide with explicit usage and safety notes.
|
|
@@ -27,6 +42,39 @@
|
|
|
27
42
|
|
|
28
43
|
### Fixed
|
|
29
44
|
|
|
45
|
+
- Simplified Pi SemVer validation into focused numeric-core and metadata checks, and made missing project-path component reversal explicit.
|
|
46
|
+
- Accepted supported stable Pi versions with SemVer build metadata while preserving bounded diagnostics and prerelease rejection.
|
|
47
|
+
- Rejected prerelease Pi builds excluded by the declared stable compatibility range before extension registration.
|
|
48
|
+
- Applied one control-safe 64-row/8,192-character policy to every `/obs` notification and capped query result counts at configuration and runtime boundaries.
|
|
49
|
+
- Coupled canonical project config, `.env`, and starter-config I/O to identity-verified file handles so concurrent symlink and ancestor swaps fail closed without exposing external paths.
|
|
50
|
+
- Rejected credentials embedded in Grafana base URLs during config validation, query readiness, and transport preflight without exposing their values.
|
|
51
|
+
- Rejected active and retained child-agent identifier collisions before creating integration spans, tree state, metrics, or propagation envelopes.
|
|
52
|
+
- Retained ownership of timed-out OpenTelemetry shutdowns, observed late settlement safely, and deferred session replacement until prior exporter cleanup completes.
|
|
53
|
+
- Replaced custom-redaction regex heuristics with bounded structural validation that rejects nested, ambiguous-alternative, and overlapping sequential repetition while preserving safe disjoint quantified alternatives.
|
|
54
|
+
- Used concise word-character syntax for single-brace unresolved trace-link placeholders.
|
|
55
|
+
- Used concise word-character syntax for dollar-brace unresolved trace-link placeholders.
|
|
56
|
+
- Used concise word-character syntax for double-brace unresolved trace-link placeholders.
|
|
57
|
+
- Split unresolved trace-link placeholder validation into simple per-syntax patterns while preserving rejection behavior.
|
|
58
|
+
- Documented why best-effort Grafana stream cancellation failures are intentionally ignored.
|
|
59
|
+
- Removed redundant explicit `undefined` support from the optional lifecycle model context property.
|
|
60
|
+
- Simplified lifecycle recovery header selection by replacing a nested conditional expression with explicit branches.
|
|
61
|
+
- Removed redundant awaiting of Pi's synchronous lifecycle status update.
|
|
62
|
+
- Replaced deprecated proxy tracer construction with an isolated always-off provider for disabled and shutdown trace states.
|
|
63
|
+
- Validated OTLP endpoints as secret-free absolute HTTP(S) URLs and constructed signal exporter paths with deterministic URL pathname semantics.
|
|
64
|
+
- Implemented opt-in, versioned, active-branch correlation persistence with bounded validation and idempotent reload recovery, and removed unsupported automatic replay configuration and synthetic duplicate startup telemetry.
|
|
65
|
+
- Bound live telemetry, query commands, and backfill correlation to Pi's typed session manager, preserved identity across reload, adopted replacement-session identity, and refreshed active metadata on session rename.
|
|
66
|
+
- Bounded and sanitized backend-derived `/obs cost`, `/obs tools`, and `/obs agents` labels, rows, and notification output with visible Unicode-safe truncation.
|
|
67
|
+
- Unified `/obs session`, `/obs trace`, and `/obs link` on one validated trace-link builder with canonical placeholders, structured Grafana fallback URLs, and bounded configuration diagnostics.
|
|
68
|
+
- Made multi-signal OpenTelemetry startup transactional with bounded rollback, a terminal failed controller state, sanitized Pi diagnostics, and clean later-session recovery.
|
|
69
|
+
- Preserved malformed environment and file configuration as bounded rejection diagnostics, with source-specific `/obs status` reporting and strict trusted `.env` parsing.
|
|
70
|
+
- Enforced coherent terminal subagent transitions across the integration API, agent tree, spans, events, metrics, runtime state, waits, and joins.
|
|
71
|
+
- Enforced production acknowledgement for Grafana and OTLP certificate-verification bypasses, wired retained OTLP TLS behavior into every exporter, and exposed effective transport security in `/obs status` and `/obs health`.
|
|
72
|
+
- Kept live-session and backfill OpenTelemetry providers scoped to ObservMe instead of replacing process-global providers.
|
|
73
|
+
- Redacted complete supported PEM private-key blocks, including malformed/truncated input, across live and backfilled content capture.
|
|
74
|
+
- Bounded all Grafana health and datasource response bodies before JSON parsing across default, custom Node, and injected fetch transports.
|
|
75
|
+
- Enforced top-level ObservMe disablement across lifecycle startup, runtime state, integration availability, and all OpenTelemetry signal factories.
|
|
76
|
+
- Restored clean npm dependency resolution by pinning TypeScript to the latest release supported by `typescript-eslint`.
|
|
77
|
+
- Integrated active-agent lease activation and deactivation with clean shutdown, duplicate/reload replacement, resume, and failed-start cleanup so final flushes cannot renew stale activity.
|
|
30
78
|
- Fixed session, workflow, agent, turn, LLM, tool, Bash, histogram, active-span, failure/recovery, and session-count telemetry accuracy.
|
|
31
79
|
- Fixed lifecycle serialization, duplicate session replacement, bounded shutdown/flush behavior, backfill cancellation, parallel tool correlation, and bounded agent-tree state cleanup.
|
|
32
80
|
- Hardened configuration validation, project-root path confinement, endpoint security, custom redaction patterns, tenant-salted hashing, and environment propagation.
|
package/README.md
CHANGED
|
@@ -62,7 +62,7 @@ This checkout implements the ObservMe MVP scope described by the packaged [`docs
|
|
|
62
62
|
|
|
63
63
|
- Extension load checks and `/obs health` backend checks.
|
|
64
64
|
- Session, workflow, agent-run, turn, LLM, tool, bash, subagent-spawn, wait/join, compaction, branch, model-change, and thinking-level telemetry.
|
|
65
|
-
-
|
|
65
|
+
- Lease-qualified multi-agent activity plus tree metrics for depth, fan-out, orphan agents, trace-context propagation failures, child failures, and workflow duration; abrupt exits converge without a Collector restart.
|
|
66
66
|
- Session-scoped OTLP trace, metric, and log exporters with bounded queues, timeouts, and shutdown flushing.
|
|
67
67
|
- Configurable capture controls, redaction, path scrubbing, hashing, truncation, and high-cardinality metric-label guards.
|
|
68
68
|
- Grafana dashboard JSON, alert rules, SLO definitions, Collector examples, and compatibility matrix artifacts.
|
|
@@ -162,12 +162,28 @@ const started = observme?.startSubagent({
|
|
|
162
162
|
});
|
|
163
163
|
|
|
164
164
|
if (started?.ok) {
|
|
165
|
-
|
|
166
|
-
|
|
165
|
+
let child;
|
|
166
|
+
try {
|
|
167
|
+
child = await launchChildPi({ env: started.env });
|
|
168
|
+
} catch (error) {
|
|
169
|
+
observme.failSubagent(started.spawnId, {
|
|
170
|
+
childAgentId: started.childAgentId,
|
|
171
|
+
errorClass: error instanceof Error ? error.name : "launcher_error",
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (child) {
|
|
176
|
+
const result = await waitForChildPi(child);
|
|
177
|
+
observme.completeSubagent(started.spawnId, {
|
|
178
|
+
childAgentId: started.childAgentId,
|
|
179
|
+
childStatus: result.status,
|
|
180
|
+
outcome: result.status,
|
|
181
|
+
});
|
|
182
|
+
}
|
|
167
183
|
}
|
|
168
184
|
```
|
|
169
185
|
|
|
170
|
-
The discovery helper fails open when the event bus or a provider is malformed. API methods also reject unsafe/oversized requests
|
|
186
|
+
The discovery helper fails open when the event bus or a provider is malformed. API methods also reject unsafe/oversized requests, duplicate active lifecycle IDs, and active or retained child-placeholder collisions without replacing existing telemetry state. Handle every discriminated failure result locally and keep orchestration functional.
|
|
171
187
|
|
|
172
188
|
Use [`docs/extension-integration.md`](docs/extension-integration.md) for the complete lifecycle, validation limits, and failure contract. The shipped [`examples/integrations/subagent-runner.ts`](examples/integrations/subagent-runner.ts) wraps a generic child transport, while [`docs/agent-subagent-observability-requirements.md`](docs/agent-subagent-observability-requirements.md) covers the larger orchestration design.
|
|
173
189
|
|
|
@@ -230,10 +246,17 @@ Metric labels are intentionally low-cardinality. Session, workflow, agent, trace
|
|
|
230
246
|
| Histogram | Workflow and agent tree | `observme_workflow_duration_ms`<br>`observme_agent_run_duration_ms`<br>`observme_subagent_spawn_duration_ms`<br>`observme_agent_wait_duration_ms`<br>`observme_agent_join_duration_ms`<br>`observme_agent_tree_depth`<br>`observme_agent_tree_width`<br>`observme_agent_fanout_count` | Workflow/agent latency and multi-agent tree shape. |
|
|
231
247
|
| Histogram | Operation latency | `observme_turn_duration_ms`<br>`observme_llm_request_duration_ms`<br>`observme_tool_duration_ms`<br>`observme_bash_duration_ms`<br>`observme_handler_duration_ms` | End-to-end operation and extension-handler duration in milliseconds. |
|
|
232
248
|
| Histogram | Context and payload size | `observme_compaction_tokens_before`<br>`observme_prompt_size_chars`<br>`observme_response_size_chars`<br>`observme_tool_result_size_chars` | Context size before compaction and payload sizes in characters. Size metrics do not contain payload content. |
|
|
233
|
-
| Up-down counter | Current activity | `observme_active_spans`<br>`observme_active_agents` | Active operations and
|
|
249
|
+
| Up-down counter | Current activity | `observme_active_spans`<br>`observme_active_agents` | Active operations and the compatibility lifecycle claim for agents in the current exported stream. |
|
|
250
|
+
| Asynchronous gauge | Agent liveness lease | `observme_agent_lease_expires_unixtime_seconds` | Absolute Unix expiry renewed on each metric collection while the session is active; operational active-agent queries join it to the positive lifecycle claim. |
|
|
234
251
|
| Registered, not yet recorded | Agent lifetime | `observme_agent_lifetime_duration_ms` | Reserved instrument; the current live handlers do not record measurements yet. |
|
|
235
252
|
| Registered, not yet recorded | Official GenAI compatibility | `gen_ai.client.token.usage`<br>`gen_ai.client.operation.duration` | Reserved OpenTelemetry GenAI instruments; use the `observme_llm_*` metrics above for current data. |
|
|
236
253
|
|
|
254
|
+
### Active-agent liveness
|
|
255
|
+
|
|
256
|
+
`observme_active_agents` remains a clean-start/clean-shutdown lifecycle claim, but raw sums are not authoritative after a crash, `SIGKILL`, cancelled GitHub Actions job, or lost runner. The shipped dashboards and alerts count an instance only when that claim is positive and its `observme_agent_lease_expires_unixtime_seconds` value is current and within the supported future horizon. Clean shutdown reaches zero after export/scrape propagation; an ungraceful exit converges within the configured lease plus up to 5 seconds of supported clock skew and one Prometheus scrape/evaluation interval (80 seconds with the default 60-second lease and a 15-second scrape).
|
|
257
|
+
|
|
258
|
+
Missing, expired, malformed, or pathologically future leases fail closed. GitHub-hosted runners satisfy the clock requirement; self-hosted runners must keep the producer and Prometheus clocks synchronized within 5 seconds. Collector restart is not required for convergence, even when its Prometheus exporter continues to expose a cached raw claim. Migrate custom panels, alerts, and recording rules from raw `sum(observme_active_agents)` queries to the [canonical lease-aware PromQL](docs/reference/09-dashboards-alerts-slos.md#131-canonical-active-agent-promql), and use raw/expired claims only for diagnostics.
|
|
259
|
+
|
|
237
260
|
### Traces
|
|
238
261
|
|
|
239
262
|
| Span name | Created for | Notes |
|
|
@@ -261,7 +284,7 @@ All operational logs use short event bodies plus structured attributes. Correlat
|
|
|
261
284
|
| Configuration, session, and workflow | `config.rejected`<br>`session.started`<br>`session.shutdown`<br>`session.duplicate_start`<br>`workflow.started`<br>`workflow.completed`<br>`workflow.failed` | Configuration diagnostics and top-level lifecycle/outcome events. |
|
|
262
285
|
| Reserved session events | `session.named`<br>`session.error` | Public event names reserved for compatibility; current live handlers do not emit them. |
|
|
263
286
|
| Agent run | `agent.run.started`<br>`agent.run.completed`<br>`agent.run.failed` | Agent-run lifecycle and outcome. |
|
|
264
|
-
| Subagent lineage | `agent.spawn.started`<br>`agent.spawn.completed`<br>`agent.spawn.failed`<br>`agent.wait.started`<br>`agent.wait.completed`<br>`agent.join.started`<br>`agent.join.completed`<br>`agent.orphaned`<br>`trace_context.propagation_failed` | Parent/child lifecycle, lineage gaps, propagation failures, and join outcomes. |
|
|
287
|
+
| Subagent lineage | `agent.spawn.started`<br>`agent.spawn.completed`<br>`agent.spawn.failed`<br>`agent.spawn.cancelled`<br>`agent.wait.started`<br>`agent.wait.completed`<br>`agent.join.started`<br>`agent.join.completed`<br>`agent.orphaned`<br>`trace_context.propagation_failed` | Parent/child lifecycle, lineage gaps, propagation failures, and join outcomes. |
|
|
265
288
|
| Turn | `turn.started`<br>`turn.completed` | Turn lifecycle with run/turn correlation. |
|
|
266
289
|
| LLM lifecycle | `llm.request.started`<br>`llm.request.completed`<br>`llm.request.failed` | Content-free provider request lifecycle, usage, cost, stop reason, and bounded errors. |
|
|
267
290
|
| LLM content | `llm.prompt.captured`<br>`llm.response.captured`<br>`llm.thinking.captured` | Emitted only when the corresponding prompt, response, or thinking capture flag is enabled and redaction succeeds. |
|
|
@@ -280,7 +303,7 @@ ObservMe supports layered configuration with this precedence:
|
|
|
280
303
|
defaults → global ~/.pi/agent/observme.yaml → trusted project config → trusted project .env → system environment variables → runtime options
|
|
281
304
|
```
|
|
282
305
|
|
|
283
|
-
Factory-safe loading uses defaults/global/system-environment/runtime options only. Session-scoped loading can add trusted project config and a project-local `.env` when Pi marks the project trusted. `/obs status` reports the effective config source, whether project-local config was loaded, skipped because the project is untrusted, or
|
|
306
|
+
Factory-safe loading uses defaults/global/system-environment/runtime options only. Session-scoped loading can add trusted project config and a project-local `.env` when Pi marks the project trusted. These project files must remain inside the stable canonical project root: in-root symlinks are supported, while out-of-root, dangling, replaced, or unverifiable paths fail closed through identity-verified file I/O. `/obs status` reports the effective config source, whether project-local config was loaded, skipped because the project is untrusted, missing, or rejected, plus bounded rejection issue codes, effective OTLP/Grafana transport security, the configured Grafana URL, and query-readiness status without rendering tokens, passwords, canonical targets, or external paths. In untrusted projects, ObservMe does not read project-local config or `.env` files and uses safe defaults/global/system-environment layers instead. Invalid or unsafe configuration emits a bounded `config.rejected` diagnostic and falls back safely without exposing rejected values.
|
|
284
307
|
|
|
285
308
|
Cross-process agent lineage has a separate boundary: only the Pi process environment available to the shipped extension, or explicit runtime options for controlled embedders, is eligible for parent provenance. Project-local `.env` values configure ObservMe but cannot establish lineage. A child accepts only a complete validated workflow/parent/root/depth/spawn envelope and valid W3C context; malformed or stale envelopes fail open to a root/orphan fallback with sanitized telemetry.
|
|
286
309
|
|
|
@@ -310,7 +333,7 @@ To show failed-tool output such as GuardMe denial messages in the Tools dashboar
|
|
|
310
333
|
|
|
311
334
|
Metadata such as token counts, duration, status, model/provider, tool name, and agent role/depth is captured by default. High-cardinality identifiers (session IDs, workflow IDs, agent IDs, trace/span IDs, entry IDs) are allowed on spans/logs for drill-down but are blocked from Prometheus metric labels.
|
|
312
335
|
|
|
313
|
-
Grafana-backed query commands use the Grafana HTTP API, so browser login cookies are irrelevant. Configure either a Grafana service-account token (`OBSERVME_GRAFANA_TOKEN`) or local Basic auth (`OBSERVME_GRAFANA_USERNAME`/`OBSERVME_GRAFANA_PASSWORD`); token auth takes precedence and secrets are never rendered in command errors. You can supply these values as system environment variables before starting Pi, or copy the `.env.example` shipped with ObservMe to `.env` in a trusted project; system environment variables override `.env` values.
|
|
336
|
+
Grafana-backed query commands use the Grafana HTTP API, so browser login cookies are irrelevant. Keep `query.grafana.url` credential-free; a base URL containing a username or password is rejected before network I/O with a bounded diagnostic that does not render the URL or credentials. Configure either a Grafana service-account token (`OBSERVME_GRAFANA_TOKEN`) or local Basic auth (`OBSERVME_GRAFANA_USERNAME`/`OBSERVME_GRAFANA_PASSWORD`); token auth takes precedence and secrets are never rendered in command errors. You can supply these values as system environment variables before starting Pi, or copy the `.env.example` shipped with ObservMe to `.env` in a trusted project; system environment variables override `.env` values.
|
|
314
337
|
|
|
315
338
|
### Supported local-stack query profile
|
|
316
339
|
|
|
@@ -336,7 +359,7 @@ query:
|
|
|
336
359
|
preferIPv4: true
|
|
337
360
|
```
|
|
338
361
|
|
|
339
|
-
Create a Grafana service-account token in Grafana (Administration → Users and access → Service accounts → Add service account/token; Viewer is enough for read-only datasource queries) and export it as `OBSERVME_GRAFANA_TOKEN`, or for local-only Basic auth read the generated admin password from the repository-only local stack's secrets directory. If you prefer a project-local env file, run `cp .env.example .env`, fill either `OBSERVME_GRAFANA_TOKEN` or `OBSERVME_GRAFANA_PASSWORD`, then restart Pi from that project. The local Collector and Loki profile uses `service.name=observme-pi-extension`; Loki queries use normalized labels such as `service_name`, `pi_session_id`, `pi_agent_id`, `pi_agent_run_id`, `event_name`, and `event_category`. If data is visible in Grafana but `/obs` commands fail, run `/obs health` and check extension env loading, Grafana auth, datasource UIDs, TLS, and DNS details.
|
|
362
|
+
Create a Grafana service-account token in Grafana (Administration → Users and access → Service accounts → Add service account/token; Viewer is enough for read-only datasource queries) and export it as `OBSERVME_GRAFANA_TOKEN`, or for local-only Basic auth read the generated admin password from the repository-only local stack's secrets directory. Certificate verification stays enabled for HTTPS by default. Production rejects OTLP or Grafana certificate-verification bypass unless `privacy.allowInsecureTransport: true` explicitly acknowledges the risk; `otlp.tls.enabled` is not a supported setting because each endpoint URL scheme selects HTTP or HTTPS. If you prefer a project-local env file, run `cp .env.example .env`, fill either `OBSERVME_GRAFANA_TOKEN` or `OBSERVME_GRAFANA_PASSWORD`, then restart Pi from that project. The local Collector and Loki profile uses `service.name=observme-pi-extension`; Loki queries use normalized labels such as `service_name`, `pi_session_id`, `pi_agent_id`, `pi_agent_run_id`, `event_name`, and `event_category`. If data is visible in Grafana but `/obs` commands fail, run `/obs health` and check extension env loading, Grafana auth, datasource UIDs, TLS, and DNS details.
|
|
340
363
|
|
|
341
364
|
### Show LLM chat content in Grafana
|
|
342
365
|
|
|
@@ -361,7 +384,7 @@ Full configuration schema: `docs/reference/12-configuration-reference.md`. Full
|
|
|
361
384
|
- ObservMe does not execute shell commands itself; it only observes tool/bash execution events emitted by Pi.
|
|
362
385
|
- ObservMe never blocks Pi agent execution when the observability backend is degraded or unreachable.
|
|
363
386
|
- ObservMe starts exporters only for a trusted session and shuts them down with bounded timeouts.
|
|
364
|
-
- ObservMe does not continuously tail the full Pi session file
|
|
387
|
+
- ObservMe does not continuously tail the full Pi session file. Optional correlation persistence uses one bounded `observme.correlation` custom entry on the active Pi branch, never LLM context; historical replay is never automatic and requires an explicit, confirmed `/obs backfill` command.
|
|
365
388
|
- Optional content capture is disabled by default and must pass through the redaction pipeline before export when enabled.
|
|
366
389
|
- `/obs` query commands are read-only and are not imported by telemetry-emission code paths.
|
|
367
390
|
- Invalid or unsafe configuration falls back to safe defaults with bounded `config.rejected`, `/obs status`, and available Pi UI diagnostics; rejected values are never rendered. Intentionally unsafe capture emits a visible warning.
|
|
@@ -383,7 +406,7 @@ These assets are included in the npm package:
|
|
|
383
406
|
|
|
384
407
|
Open **ObservMe Overview** first for health/SLO chips, workload, cost, latency, agent-lineage status, and time-preserving links to focused dashboards. Use **Trace Journey** to follow a session/workflow/agent/run across Prometheus aggregates, Loki logs, and Tempo traces. Use **LLM Conversations** only for redacted opt-in content; raw prompt, response, command, path, and error-message values should never be placed in dashboard URLs or Prometheus labels. Empty failure tables normally mean no matching failures in the selected range, while optional content panels can be empty because capture is disabled by default.
|
|
385
408
|
|
|
386
|
-
The full dashboard map, standard variables, drill-down workflow, threshold colors, and zero-state semantics are documented in `docs/reference/09-dashboards-alerts-slos.md`.
|
|
409
|
+
The full dashboard map, canonical lease-aware active-agent queries, raw-query migration, standard variables, drill-down workflow, threshold colors, and zero-state semantics are documented in `docs/reference/09-dashboards-alerts-slos.md`. For an unexpected zero or stale raw claim, follow the active-lease troubleshooting flow in `docs/reference/11-deployment-runbooks.md` and check Export Health before concluding that the producer stopped.
|
|
387
410
|
|
|
388
411
|
## Documentation Set
|
|
389
412
|
|
|
@@ -415,8 +438,10 @@ npm run lint:fix # ESLint auto-fix pass
|
|
|
415
438
|
npm run format:check
|
|
416
439
|
npm run test
|
|
417
440
|
npm run test:integration:collector
|
|
441
|
+
npm run test:integration:active-agent-lease
|
|
418
442
|
npm run test:integration:grafana-stack
|
|
419
443
|
npm run check:pack
|
|
444
|
+
npm run pack:dry-run
|
|
420
445
|
npm run smoke:pi-runtime
|
|
421
446
|
npm run validate:grafana-obs
|
|
422
447
|
pi --no-extensions -e .
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"type": "prometheus",
|
|
46
46
|
"uid": "prometheus"
|
|
47
47
|
},
|
|
48
|
-
"description": "Aggregate
|
|
48
|
+
"description": "Aggregate fleet topology built only from bounded Prometheus labels; it is not per-workflow truth or a single trace tree. Role nodes combine canonical leased-current activity with selected-range run/spawn counts, so node and edge values must not be read as one execution. Clean shutdown removes leased activity after export/scrape propagation; after a crash, SIGKILL, cancelled job, or runner loss, leased activity converges to zero within the default 60-second lease plus one Prometheus scrape while raw claims may stay cached. Red nodes and edges identify spawn, lineage, or propagation failures. /obs agents is current-process child state; use Trace Journey for one execution.",
|
|
49
49
|
"fieldConfig": {
|
|
50
50
|
"defaults": {
|
|
51
51
|
"mappings": [],
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
"uid": "prometheus"
|
|
89
89
|
},
|
|
90
90
|
"editorMode": "code",
|
|
91
|
-
"expr": "label_replace(label_replace(label_replace(label_replace(label_replace(label_replace(vector(1), \"id\", \"pi-root\", \"__name__\", \".*\"), \"title\", \"Pi root\", \"id\", \".*\"), \"subTitle\", \"workflow entry\", \"id\", \".*\"), \"mainStat\", \"entry\", \"id\", \".*\"), \"secondaryStat\", \"aggregate\", \"id\", \".*\"), \"color\", \"blue\", \"id\", \".*\") or label_replace(label_replace(label_replace(label_replace(label_replace(label_replace((sum(
|
|
91
|
+
"expr": "label_replace(label_replace(label_replace(label_replace(label_replace(label_replace(vector(1), \"id\", \"pi-root\", \"__name__\", \".*\"), \"title\", \"Pi root\", \"id\", \".*\"), \"subTitle\", \"workflow entry\", \"id\", \".*\"), \"mainStat\", \"entry\", \"id\", \".*\"), \"secondaryStat\", \"aggregate\", \"id\", \".*\"), \"color\", \"blue\", \"id\", \".*\") or label_replace(label_replace(label_replace(label_replace(label_replace(label_replace((sum by (agent_role) (max by (observme_instance_id, agent_role) ((observme_active_agents > 0) and on (observme_instance_id) ((observme_agent_lease_expires_unixtime_seconds > time()) and (observme_agent_lease_expires_unixtime_seconds <= time() + 305)))) or sum(increase(observme_agent_runs_total[$__range])) by (agent_role) or sum(increase(observme_subagents_spawned_total[$__range])) by (agent_role)), \"id\", \"agent_$1\", \"agent_role\", \"(.+)\"), \"title\", \"Agent: $1\", \"agent_role\", \"(.+)\"), \"subTitle\", \"active or observed role\", \"agent_role\", \"(.+)\"), \"mainStat\", \"count\", \"agent_role\", \"(.+)\"), \"secondaryStat\", \"role\", \"agent_role\", \"(.+)\"), \"color\", \"green\", \"agent_role\", \"(.+)\") or label_replace(label_replace(label_replace(label_replace(label_replace(label_replace(sum(increase(observme_subagents_spawned_total[$__range])) by (subagent_depth), \"id\", \"subagents_depth_$1\", \"subagent_depth\", \"(.+)\"), \"title\", \"Subagents depth $1\", \"subagent_depth\", \"(.+)\"), \"subtitle\", \"spawned in range\", \"subagent_depth\", \"(.+)\"), \"mainStat\", \"spawns\", \"subagent_depth\", \"(.+)\"), \"secondaryStat\", \"depth\", \"subagent_depth\", \"(.+)\"), \"color\", \"orange\", \"subagent_depth\", \"(.+)\") or label_replace(label_replace(label_replace(label_replace(label_replace(label_replace((sum(increase(observme_subagent_spawn_failures_total[$__range])) by (error_class) > 0), \"id\", \"spawn_failure_$1\", \"error_class\", \"(.+)\"), \"title\", \"Spawn failure: $1\", \"error_class\", \"(.+)\"), \"subtitle\", \"failed spawns\", \"error_class\", \"(.+)\"), \"mainStat\", \"failures\", \"error_class\", \"(.+)\"), \"secondaryStat\", \"error\", \"error_class\", \"(.+)\"), \"color\", \"red\", \"error_class\", \"(.+)\") or label_replace(label_replace(label_replace(label_replace(label_replace(label_replace((sum(increase(observme_orphan_agents_total[$__range])) by (reason) > 0), \"id\", \"orphan_$1\", \"reason\", \"(.+)\"), \"title\", \"Orphan: $1\", \"reason\", \"(.+)\"), \"subtitle\", \"lineage missing\", \"reason\", \"(.+)\"), \"mainStat\", \"orphans\", \"reason\", \"(.+)\"), \"secondaryStat\", \"reason\", \"reason\", \"(.+)\"), \"color\", \"red\", \"reason\", \"(.+)\") or label_replace(label_replace(label_replace(label_replace(label_replace(label_replace((sum(increase(observme_trace_context_propagation_failures_total[$__range])) by (reason) > 0), \"id\", \"propagation_$1\", \"reason\", \"(.+)\"), \"title\", \"Propagation: $1\", \"reason\", \"(.+)\"), \"subtitle\", \"trace context failures\", \"reason\", \"(.+)\"), \"mainStat\", \"failures\", \"reason\", \"(.+)\"), \"secondaryStat\", \"reason\", \"reason\", \"(.+)\"), \"color\", \"red\", \"reason\", \"(.+)\")",
|
|
92
92
|
"format": "table",
|
|
93
93
|
"instant": true,
|
|
94
94
|
"legendFormat": "nodes",
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
"uid": "prometheus"
|
|
102
102
|
},
|
|
103
103
|
"editorMode": "code",
|
|
104
|
-
"expr": "label_join(label_replace(label_replace(label_replace(label_replace(label_replace((sum(
|
|
104
|
+
"expr": "label_join(label_replace(label_replace(label_replace(label_replace(label_replace((sum by (agent_role) (max by (observme_instance_id, agent_role) ((observme_active_agents > 0) and on (observme_instance_id) ((observme_agent_lease_expires_unixtime_seconds > time()) and (observme_agent_lease_expires_unixtime_seconds <= time() + 305)))) or sum(increase(observme_agent_runs_total[$__range])) by (agent_role)), \"source\", \"pi-root\", \"agent_role\", \"(.+)\"), \"target\", \"agent_$1\", \"agent_role\", \"(.+)\"), \"mainStat\", \"count\", \"agent_role\", \"(.+)\"), \"secondaryStat\", \"active/runs\", \"agent_role\", \"(.+)\"), \"color\", \"gray\", \"agent_role\", \"(.+)\"), \"id\", \":\", \"source\", \"target\") or label_join(label_replace(label_replace(label_replace(label_replace(label_replace(sum(increase(observme_subagents_spawned_total[$__range])) by (agent_role, subagent_depth, spawn_type, spawn_reason), \"source\", \"agent_$1\", \"agent_role\", \"(.+)\"), \"target\", \"subagents_depth_$1\", \"subagent_depth\", \"(.+)\"), \"mainStat\", \"spawns\", \"agent_role\", \"(.+)\"), \"secondaryStat\", \"spawn_type/reason\", \"agent_role\", \"(.+)\"), \"color\", \"gray\", \"agent_role\", \"(.+)\"), \"id\", \":\", \"source\", \"target\", \"spawn_type\", \"spawn_reason\") or label_join(label_replace(label_replace(label_replace(label_replace(label_replace((sum(increase(observme_subagent_spawn_failures_total[$__range])) by (error_class) > 0), \"source\", \"pi-root\", \"error_class\", \"(.+)\"), \"target\", \"spawn_failure_$1\", \"error_class\", \"(.+)\"), \"mainStat\", \"failures\", \"error_class\", \"(.+)\"), \"secondaryStat\", \"spawn\", \"error_class\", \"(.+)\"), \"color\", \"red\", \"error_class\", \"(.+)\"), \"id\", \":\", \"source\", \"target\") or label_join(label_replace(label_replace(label_replace(label_replace(label_replace((sum(increase(observme_orphan_agents_total[$__range])) by (reason) > 0), \"source\", \"pi-root\", \"reason\", \"(.+)\"), \"target\", \"orphan_$1\", \"reason\", \"(.+)\"), \"mainStat\", \"orphans\", \"reason\", \"(.+)\"), \"secondaryStat\", \"lineage\", \"reason\", \"(.+)\"), \"color\", \"red\", \"reason\", \"(.+)\"), \"id\", \":\", \"source\", \"target\") or label_join(label_replace(label_replace(label_replace(label_replace(label_replace((sum(increase(observme_trace_context_propagation_failures_total[$__range])) by (reason) > 0), \"source\", \"pi-root\", \"reason\", \"(.+)\"), \"target\", \"propagation_$1\", \"reason\", \"(.+)\"), \"mainStat\", \"failures\", \"reason\", \"(.+)\"), \"secondaryStat\", \"trace context\", \"reason\", \"(.+)\"), \"color\", \"red\", \"reason\", \"(.+)\"), \"id\", \":\", \"source\", \"target\")",
|
|
105
105
|
"format": "table",
|
|
106
106
|
"instant": true,
|
|
107
107
|
"legendFormat": "edges",
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
"type": "prometheus",
|
|
138
138
|
"uid": "prometheus"
|
|
139
139
|
},
|
|
140
|
-
"description": "Aggregate delegation topology by bounded
|
|
140
|
+
"description": "Aggregate fleet delegation topology by bounded role, spawn reason, and resulting depth; it is not per-workflow truth or a single trace tree. Role nodes may combine canonical leased-current activity with selected-range run/spawn counts, while other values are selected-range aggregates. Clean shutdown removes leased activity after export/scrape propagation; after an ungraceful exit, leased activity converges to zero within the default 60-second lease plus one Prometheus scrape while raw claims may stay cached. Red health nodes and edges summarize spawn failures. /obs agents is local current-process child state; use Trace Journey for one execution.",
|
|
141
141
|
"fieldConfig": {
|
|
142
142
|
"defaults": {
|
|
143
143
|
"mappings": [],
|
|
@@ -180,7 +180,7 @@
|
|
|
180
180
|
"uid": "prometheus"
|
|
181
181
|
},
|
|
182
182
|
"editorMode": "code",
|
|
183
|
-
"expr": "label_replace(label_replace(label_replace(label_replace(label_replace(label_replace((sum(
|
|
183
|
+
"expr": "label_replace(label_replace(label_replace(label_replace(label_replace(label_replace((sum by (agent_role) (max by (observme_instance_id, agent_role) ((observme_active_agents > 0) and on (observme_instance_id) ((observme_agent_lease_expires_unixtime_seconds > time()) and (observme_agent_lease_expires_unixtime_seconds <= time() + 305)))) or sum(increase(observme_agent_runs_total[$__range])) by (agent_role) or sum(increase(observme_subagents_spawned_total[$__range])) by (agent_role)), \"id\", \"agent_$1\", \"agent_role\", \"(.+)\"), \"title\", \"Agent: $1\", \"agent_role\", \"(.+)\"), \"subTitle\", \"active or observed role\", \"agent_role\", \"(.+)\"), \"mainStat\", \"count\", \"agent_role\", \"(.+)\"), \"secondaryStat\", \"role\", \"agent_role\", \"(.+)\"), \"color\", \"green\", \"agent_role\", \"(.+)\") or label_replace(label_replace(label_replace(label_replace(label_replace(label_replace(sum(increase(observme_subagents_spawned_total[$__range])) by (spawn_reason), \"id\", \"spawn_reason_$1\", \"spawn_reason\", \"(.+)\"), \"title\", \"Spawn: $1\", \"spawn_reason\", \"(.+)\"), \"subTitle\", \"spawn reason\", \"spawn_reason\", \"(.+)\"), \"mainStat\", \"spawns\", \"spawn_reason\", \"(.+)\"), \"secondaryStat\", \"reason\", \"spawn_reason\", \"(.+)\"), \"color\", \"purple\", \"spawn_reason\", \"(.+)\") or label_replace(label_replace(label_replace(label_replace(label_replace(label_replace(sum(increase(observme_subagents_spawned_total[$__range])) by (subagent_depth), \"id\", \"subagents_depth_$1\", \"subagent_depth\", \"(.+)\"), \"title\", \"Subagents depth $1\", \"subagent_depth\", \"(.+)\"), \"subTitle\", \"spawned in range\", \"subagent_depth\", \"(.+)\"), \"mainStat\", \"spawns\", \"subagent_depth\", \"(.+)\"), \"secondaryStat\", \"depth\", \"subagent_depth\", \"(.+)\"), \"color\", \"orange\", \"subagent_depth\", \"(.+)\") or label_replace(label_replace(label_replace(label_replace(label_replace(label_replace((sum(increase(observme_subagent_spawn_failures_total[$__range])) > 0), \"id\", \"spawn-health\", \"__name__\", \".*\"), \"title\", \"Spawn failure health\", \"id\", \".*\"), \"subTitle\", \"failure-only aggregate\", \"id\", \".*\"), \"mainStat\", \"failures\", \"id\", \".*\"), \"secondaryStat\", \"health\", \"id\", \".*\"), \"color\", \"red\", \"id\", \".*\") or label_replace(label_replace(label_replace(label_replace(label_replace(label_replace((sum(increase(observme_subagent_spawn_failures_total[$__range])) by (error_class) > 0), \"id\", \"spawn_failure_$1\", \"error_class\", \"(.+)\"), \"title\", \"Spawn failure: $1\", \"error_class\", \"(.+)\"), \"subTitle\", \"failed spawns\", \"error_class\", \"(.+)\"), \"mainStat\", \"failures\", \"error_class\", \"(.+)\"), \"secondaryStat\", \"error class\", \"error_class\", \"(.+)\"), \"color\", \"red\", \"error_class\", \"(.+)\")",
|
|
184
184
|
"format": "table",
|
|
185
185
|
"instant": true,
|
|
186
186
|
"legendFormat": "nodes",
|
|
@@ -1065,7 +1065,7 @@
|
|
|
1065
1065
|
"type": "prometheus",
|
|
1066
1066
|
"uid": "prometheus"
|
|
1067
1067
|
},
|
|
1068
|
-
"description": "
|
|
1068
|
+
"description": "Canonical leased-active agents grouped by emitted agent_role, plus the fleet total. Clean shutdown reaches zero after export/scrape propagation; after a crash, SIGKILL, cancelled job, or runner loss, the leased total converges to zero within the default 60-second lease plus one Prometheus scrape even when raw claims stay cached. Zero can also mean healthy idle or a failed-closed lease, so compare Export Health. /obs agents reports current-process child state, not this aggregate fleet view. The total=100 reference matches the deployment-tunable ObservMeActiveAgentsStuckHigh threshold.",
|
|
1069
1069
|
"fieldConfig": {
|
|
1070
1070
|
"defaults": {
|
|
1071
1071
|
"color": {
|
|
@@ -1115,7 +1115,7 @@
|
|
|
1115
1115
|
"uid": "prometheus"
|
|
1116
1116
|
},
|
|
1117
1117
|
"editorMode": "code",
|
|
1118
|
-
"expr": "sum(
|
|
1118
|
+
"expr": "sum by (agent_role) (max by (observme_instance_id, agent_role) ((observme_active_agents > 0) and on (observme_instance_id) ((observme_agent_lease_expires_unixtime_seconds > time()) and (observme_agent_lease_expires_unixtime_seconds <= time() + 305)))) or on() vector(0)",
|
|
1119
1119
|
"range": true,
|
|
1120
1120
|
"refId": "A",
|
|
1121
1121
|
"legendFormat": "{{agent_role}}"
|
|
@@ -1126,7 +1126,7 @@
|
|
|
1126
1126
|
"uid": "prometheus"
|
|
1127
1127
|
},
|
|
1128
1128
|
"editorMode": "code",
|
|
1129
|
-
"expr": "sum(observme_active_agents)",
|
|
1129
|
+
"expr": "sum(max by (observme_instance_id) ((observme_active_agents > 0) and on (observme_instance_id) ((observme_agent_lease_expires_unixtime_seconds > time()) and (observme_agent_lease_expires_unixtime_seconds <= time() + 305)))) or vector(0)",
|
|
1130
1130
|
"range": true,
|
|
1131
1131
|
"refId": "B",
|
|
1132
1132
|
"legendFormat": "total active agents"
|
|
@@ -1697,6 +1697,171 @@
|
|
|
1697
1697
|
"x": 0,
|
|
1698
1698
|
"y": 57
|
|
1699
1699
|
},
|
|
1700
|
+
"id": 105,
|
|
1701
|
+
"panels": [],
|
|
1702
|
+
"title": "Lease health diagnostics",
|
|
1703
|
+
"type": "row"
|
|
1704
|
+
},
|
|
1705
|
+
{
|
|
1706
|
+
"datasource": {
|
|
1707
|
+
"type": "prometheus",
|
|
1708
|
+
"uid": "prometheus"
|
|
1709
|
+
},
|
|
1710
|
+
"description": "Diagnostic positive lifecycle claims before lease qualification. These are not live-agent totals and may remain cached after a crash, SIGKILL, cancelled job, or runner loss; leased activity converges to zero within the default 60-second lease plus one Prometheus scrape. Clean shutdown exports zero immediately. Compare Expired active claims and Export Health. /obs agents reports only current-process child state, not fleet liveness.",
|
|
1711
|
+
"fieldConfig": {
|
|
1712
|
+
"defaults": {
|
|
1713
|
+
"color": {
|
|
1714
|
+
"mode": "thresholds"
|
|
1715
|
+
},
|
|
1716
|
+
"mappings": [],
|
|
1717
|
+
"thresholds": {
|
|
1718
|
+
"mode": "absolute",
|
|
1719
|
+
"steps": [
|
|
1720
|
+
{
|
|
1721
|
+
"color": "green",
|
|
1722
|
+
"value": null
|
|
1723
|
+
}
|
|
1724
|
+
]
|
|
1725
|
+
},
|
|
1726
|
+
"unit": "short"
|
|
1727
|
+
},
|
|
1728
|
+
"overrides": []
|
|
1729
|
+
},
|
|
1730
|
+
"gridPos": {
|
|
1731
|
+
"h": 8,
|
|
1732
|
+
"w": 12,
|
|
1733
|
+
"x": 0,
|
|
1734
|
+
"y": 58
|
|
1735
|
+
},
|
|
1736
|
+
"id": 22,
|
|
1737
|
+
"links": [
|
|
1738
|
+
{
|
|
1739
|
+
"targetBlank": false,
|
|
1740
|
+
"title": "Open Export Health",
|
|
1741
|
+
"url": "/d/observme-export-health/observme-export-health?${__url_time_range}"
|
|
1742
|
+
}
|
|
1743
|
+
],
|
|
1744
|
+
"options": {
|
|
1745
|
+
"colorMode": "value",
|
|
1746
|
+
"graphMode": "area",
|
|
1747
|
+
"justifyMode": "auto",
|
|
1748
|
+
"orientation": "auto",
|
|
1749
|
+
"reduceOptions": {
|
|
1750
|
+
"calcs": [
|
|
1751
|
+
"lastNotNull"
|
|
1752
|
+
],
|
|
1753
|
+
"fields": "",
|
|
1754
|
+
"values": false
|
|
1755
|
+
},
|
|
1756
|
+
"showPercentChange": false,
|
|
1757
|
+
"textMode": "auto",
|
|
1758
|
+
"wideLayout": true
|
|
1759
|
+
},
|
|
1760
|
+
"pluginVersion": "11.1.0",
|
|
1761
|
+
"targets": [
|
|
1762
|
+
{
|
|
1763
|
+
"datasource": {
|
|
1764
|
+
"type": "prometheus",
|
|
1765
|
+
"uid": "prometheus"
|
|
1766
|
+
},
|
|
1767
|
+
"editorMode": "code",
|
|
1768
|
+
"expr": "sum(max by (observme_instance_id) (observme_active_agents > 0)) or vector(0)",
|
|
1769
|
+
"instant": true,
|
|
1770
|
+
"range": false,
|
|
1771
|
+
"refId": "A"
|
|
1772
|
+
}
|
|
1773
|
+
],
|
|
1774
|
+
"title": "Raw active claims (diagnostic)",
|
|
1775
|
+
"type": "stat"
|
|
1776
|
+
},
|
|
1777
|
+
{
|
|
1778
|
+
"datasource": {
|
|
1779
|
+
"type": "prometheus",
|
|
1780
|
+
"uid": "prometheus"
|
|
1781
|
+
},
|
|
1782
|
+
"description": "Positive raw claims whose lease has expired. They are stale diagnostics and never contribute to leased active totals; clean shutdown normally avoids them, while ungraceful exits appear after the default 60-second lease plus one Prometheus scrape and may remain until Collector cleanup. Yellow at 1 and red at 5 are deployment-tunable. Compare Raw active claims and Export Health. /obs agents reports only current-process child state, not fleet liveness.",
|
|
1783
|
+
"fieldConfig": {
|
|
1784
|
+
"defaults": {
|
|
1785
|
+
"color": {
|
|
1786
|
+
"mode": "thresholds"
|
|
1787
|
+
},
|
|
1788
|
+
"mappings": [],
|
|
1789
|
+
"thresholds": {
|
|
1790
|
+
"mode": "absolute",
|
|
1791
|
+
"steps": [
|
|
1792
|
+
{
|
|
1793
|
+
"color": "green",
|
|
1794
|
+
"value": null
|
|
1795
|
+
},
|
|
1796
|
+
{
|
|
1797
|
+
"color": "yellow",
|
|
1798
|
+
"value": 1
|
|
1799
|
+
},
|
|
1800
|
+
{
|
|
1801
|
+
"color": "red",
|
|
1802
|
+
"value": 5
|
|
1803
|
+
}
|
|
1804
|
+
]
|
|
1805
|
+
},
|
|
1806
|
+
"unit": "short"
|
|
1807
|
+
},
|
|
1808
|
+
"overrides": []
|
|
1809
|
+
},
|
|
1810
|
+
"gridPos": {
|
|
1811
|
+
"h": 8,
|
|
1812
|
+
"w": 12,
|
|
1813
|
+
"x": 12,
|
|
1814
|
+
"y": 58
|
|
1815
|
+
},
|
|
1816
|
+
"id": 23,
|
|
1817
|
+
"links": [
|
|
1818
|
+
{
|
|
1819
|
+
"targetBlank": false,
|
|
1820
|
+
"title": "Open Export Health",
|
|
1821
|
+
"url": "/d/observme-export-health/observme-export-health?${__url_time_range}"
|
|
1822
|
+
}
|
|
1823
|
+
],
|
|
1824
|
+
"options": {
|
|
1825
|
+
"colorMode": "value",
|
|
1826
|
+
"graphMode": "area",
|
|
1827
|
+
"justifyMode": "auto",
|
|
1828
|
+
"orientation": "auto",
|
|
1829
|
+
"reduceOptions": {
|
|
1830
|
+
"calcs": [
|
|
1831
|
+
"lastNotNull"
|
|
1832
|
+
],
|
|
1833
|
+
"fields": "",
|
|
1834
|
+
"values": false
|
|
1835
|
+
},
|
|
1836
|
+
"showPercentChange": false,
|
|
1837
|
+
"textMode": "auto",
|
|
1838
|
+
"wideLayout": true
|
|
1839
|
+
},
|
|
1840
|
+
"pluginVersion": "11.1.0",
|
|
1841
|
+
"targets": [
|
|
1842
|
+
{
|
|
1843
|
+
"datasource": {
|
|
1844
|
+
"type": "prometheus",
|
|
1845
|
+
"uid": "prometheus"
|
|
1846
|
+
},
|
|
1847
|
+
"editorMode": "code",
|
|
1848
|
+
"expr": "sum(max by (observme_instance_id) ((observme_active_agents > 0) and on (observme_instance_id) (observme_agent_lease_expires_unixtime_seconds <= time()))) or vector(0)",
|
|
1849
|
+
"instant": true,
|
|
1850
|
+
"range": false,
|
|
1851
|
+
"refId": "A"
|
|
1852
|
+
}
|
|
1853
|
+
],
|
|
1854
|
+
"title": "Expired active claims (diagnostic)",
|
|
1855
|
+
"type": "stat"
|
|
1856
|
+
},
|
|
1857
|
+
{
|
|
1858
|
+
"collapsed": false,
|
|
1859
|
+
"gridPos": {
|
|
1860
|
+
"h": 1,
|
|
1861
|
+
"w": 24,
|
|
1862
|
+
"x": 0,
|
|
1863
|
+
"y": 66
|
|
1864
|
+
},
|
|
1700
1865
|
"id": 104,
|
|
1701
1866
|
"panels": [],
|
|
1702
1867
|
"title": "Lineage logs",
|
|
@@ -1768,7 +1933,7 @@
|
|
|
1768
1933
|
"h": 10,
|
|
1769
1934
|
"w": 24,
|
|
1770
1935
|
"x": 0,
|
|
1771
|
-
"y":
|
|
1936
|
+
"y": 67
|
|
1772
1937
|
},
|
|
1773
1938
|
"id": 6,
|
|
1774
1939
|
"options": {
|
|
@@ -103,11 +103,24 @@ groups:
|
|
|
103
103
|
runbook: "Severity guidance from production docs: warning."
|
|
104
104
|
- alert: ObservMeActiveAgentsStuckHigh
|
|
105
105
|
expr: >-
|
|
106
|
-
sum(
|
|
106
|
+
(sum(max by (observme_instance_id) ((observme_active_agents > 0) and on (observme_instance_id)
|
|
107
|
+
((observme_agent_lease_expires_unixtime_seconds > time()) and
|
|
108
|
+
(observme_agent_lease_expires_unixtime_seconds <= time() + 305)))) or vector(0)) > 100
|
|
107
109
|
for: 30m
|
|
108
110
|
labels:
|
|
109
111
|
severity: deployment-dependent
|
|
110
112
|
annotations:
|
|
111
113
|
summary: Active agents stuck high
|
|
112
|
-
description: ObservMe active-agent
|
|
113
|
-
runbook: "Severity guidance from production docs: depends on normal fleet size; tune per deployment."
|
|
114
|
+
description: ObservMe leased active-agent count remains above 100; expired, missing, and pathological leases fail closed.
|
|
115
|
+
runbook: "Severity guidance from production docs: depends on normal fleet size; tune per deployment. Compare leased activity with raw and expired claims plus Export Health."
|
|
116
|
+
- alert: ObservMeExpiredActiveAgentClaims
|
|
117
|
+
expr: >-
|
|
118
|
+
(sum(max by (observme_instance_id) ((observme_active_agents > 0) and on (observme_instance_id)
|
|
119
|
+
(observme_agent_lease_expires_unixtime_seconds <= time()))) or vector(0)) > 5
|
|
120
|
+
for: 15m
|
|
121
|
+
labels:
|
|
122
|
+
severity: deployment-dependent
|
|
123
|
+
annotations:
|
|
124
|
+
summary: Expired active-agent claims detected
|
|
125
|
+
description: More than five positive lifecycle claims have expired leases for 15 minutes; they are stale diagnostics and excluded from leased active totals.
|
|
126
|
+
runbook: "Deployment-tunable diagnostic: compare Raw active claims, Expired active claims, leased Active agents, and Export Health; investigate abrupt producer death, export gaps, and Collector cleanup. /obs agents is local child state, not fleet truth."
|
|
@@ -1075,7 +1075,7 @@
|
|
|
1075
1075
|
"type": "prometheus",
|
|
1076
1076
|
"uid": "prometheus"
|
|
1077
1077
|
},
|
|
1078
|
-
"description": "
|
|
1078
|
+
"description": "Canonical leased-active ObservMe runtimes. Clean shutdown reaches zero after export/scrape propagation; after a crash, SIGKILL, cancelled job, or runner loss, the leased total converges to zero within the default 60-second lease plus one Prometheus scrape even if raw claims stay cached. Zero can also mean healthy idle or a failed-closed lease, so check Export Health. /obs agents reports only current-process child state, not fleet liveness. Red at 100 matches the deployment-tunable ObservMeActiveAgentsStuckHigh threshold; yellow at 50 is an early warning.",
|
|
1079
1079
|
"fieldConfig": {
|
|
1080
1080
|
"defaults": {
|
|
1081
1081
|
"color": {
|
|
@@ -1141,7 +1141,7 @@
|
|
|
1141
1141
|
"uid": "prometheus"
|
|
1142
1142
|
},
|
|
1143
1143
|
"editorMode": "code",
|
|
1144
|
-
"expr": "sum(observme_active_agents) or vector(0)",
|
|
1144
|
+
"expr": "sum(max by (observme_instance_id) ((observme_active_agents > 0) and on (observme_instance_id) ((observme_agent_lease_expires_unixtime_seconds > time()) and (observme_agent_lease_expires_unixtime_seconds <= time() + 305)))) or vector(0)",
|
|
1145
1145
|
"range": true,
|
|
1146
1146
|
"refId": "A"
|
|
1147
1147
|
}
|
|
@@ -1998,7 +1998,7 @@
|
|
|
1998
1998
|
"type": "prometheus",
|
|
1999
1999
|
"uid": "prometheus"
|
|
2000
2000
|
},
|
|
2001
|
-
"description": "
|
|
2001
|
+
"description": "Canonical leased-active agents by emitted bounded role and environment. Clean shutdown reaches zero after export/scrape propagation; after an ungraceful exit, leased totals converge to zero within the default 60-second lease plus one Prometheus scrape while raw claims may remain cached. Depth is omitted because active signals do not emit subagent_depth. An unlabeled zero means healthy idle or no qualifying lease when Prometheus is reachable; compare Export Health. /obs agents is current-process child state, not this aggregate fleet view.",
|
|
2002
2002
|
"fieldConfig": {
|
|
2003
2003
|
"defaults": {
|
|
2004
2004
|
"color": {
|
|
@@ -2058,14 +2058,14 @@
|
|
|
2058
2058
|
"uid": "prometheus"
|
|
2059
2059
|
},
|
|
2060
2060
|
"editorMode": "code",
|
|
2061
|
-
"expr": "sum(
|
|
2061
|
+
"expr": "sum by (agent_role, environment) (max by (observme_instance_id, agent_role, environment) ((observme_active_agents > 0) and on (observme_instance_id) ((observme_agent_lease_expires_unixtime_seconds > time()) and (observme_agent_lease_expires_unixtime_seconds <= time() + 305)))) or on() vector(0)",
|
|
2062
2062
|
"instant": true,
|
|
2063
|
-
"legendFormat": "{{agent_role}}
|
|
2063
|
+
"legendFormat": "{{agent_role}} / {{environment}}",
|
|
2064
2064
|
"range": false,
|
|
2065
2065
|
"refId": "A"
|
|
2066
2066
|
}
|
|
2067
2067
|
],
|
|
2068
|
-
"title": "Active agents by role/
|
|
2068
|
+
"title": "Active agents by role/environment",
|
|
2069
2069
|
"type": "bargauge"
|
|
2070
2070
|
},
|
|
2071
2071
|
{
|