@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,155 @@
|
|
|
1
|
+
import { SpanStatusCode } from "@opentelemetry/api";
|
|
2
|
+
import { recordObsSessionTurn } from "../../commands/obs-session.ts";
|
|
3
|
+
import { AGENT_RUN_ATTRIBUTES, TURN_ATTRIBUTES } from "../../semconv/attributes.ts";
|
|
4
|
+
import { LOG_EVENT_NAMES } from "../../semconv/metrics.ts";
|
|
5
|
+
import { SPAN_NAMES } from "../../semconv/spans.ts";
|
|
6
|
+
import {
|
|
7
|
+
buildAgentRunAttributes,
|
|
8
|
+
buildLineageMetricSafeLogAttributes,
|
|
9
|
+
buildTurnAttributes,
|
|
10
|
+
deriveTurnId,
|
|
11
|
+
emitLifecycleLog,
|
|
12
|
+
endActiveSpan,
|
|
13
|
+
metricLabels,
|
|
14
|
+
nextAgentRunId,
|
|
15
|
+
nextTurnIndex,
|
|
16
|
+
readInteger,
|
|
17
|
+
readString,
|
|
18
|
+
recordSpanDurationMs,
|
|
19
|
+
recordTelemetryDrop,
|
|
20
|
+
startActiveChildSpan,
|
|
21
|
+
} from "../handler-internals.ts";
|
|
22
|
+
import { workflowFailed } from "../handler-runtime.ts";
|
|
23
|
+
import type { HandlerRegistrar } from "../handler-runtime.ts";
|
|
24
|
+
import type { Handler, HandlerSessionState, ObservMeHandlerContext } from "../handler-types.ts";
|
|
25
|
+
|
|
26
|
+
export function registerAgentTurnHandlers(registrar: HandlerRegistrar, state: HandlerSessionState): void {
|
|
27
|
+
registrar.add("agent_start", createAgentStartHandler(state));
|
|
28
|
+
registrar.add("turn_start", createTurnStartHandler(state));
|
|
29
|
+
registrar.add("turn_end", createTurnEndHandler(state));
|
|
30
|
+
registrar.add("agent_end", createAgentEndHandler(state));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function createAgentStartHandler(state: HandlerSessionState): Handler {
|
|
34
|
+
return handleAgentStart.bind(undefined, state);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function handleAgentStart(state: HandlerSessionState, event: unknown, _ctx: ObservMeHandlerContext): void {
|
|
38
|
+
const session = state.session;
|
|
39
|
+
if (!session) return;
|
|
40
|
+
|
|
41
|
+
const runId = nextAgentRunId(session, event);
|
|
42
|
+
const attributes = buildAgentRunAttributes(event, session, runId);
|
|
43
|
+
const span = startActiveChildSpan(session, SPAN_NAMES.PI_AGENT_RUN, session.sessionSpan, attributes, "agent_run");
|
|
44
|
+
|
|
45
|
+
session.currentAgentRunId = runId;
|
|
46
|
+
session.spans.activeAgentRuns.set(runId, span);
|
|
47
|
+
session.metrics.agentRuns.add(1, metricLabels(session.config, session.lineage));
|
|
48
|
+
emitLifecycleLog(session.logger, LOG_EVENT_NAMES.AGENT_RUN_STARTED, attributes);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function createAgentEndHandler(state: HandlerSessionState): Handler {
|
|
52
|
+
return handleAgentEnd.bind(undefined, state);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function handleAgentEnd(state: HandlerSessionState, event: unknown, _ctx: ObservMeHandlerContext): void {
|
|
56
|
+
const session = state.session;
|
|
57
|
+
if (!session) return;
|
|
58
|
+
|
|
59
|
+
const runId = readString(event, "agentRunId") ?? readString(event, "runId") ?? session.currentAgentRunId;
|
|
60
|
+
if (!runId) return;
|
|
61
|
+
|
|
62
|
+
const span = session.spans.activeAgentRuns.get(runId);
|
|
63
|
+
const failed = workflowFailed(event);
|
|
64
|
+
const labels = metricLabels(session.config, session.lineage);
|
|
65
|
+
if (failed) span?.setStatus({ code: SpanStatusCode.ERROR });
|
|
66
|
+
if (span && failed) session.metrics.agentRunErrors.add(1, labels);
|
|
67
|
+
recordSpanDurationMs(span, session.metrics.agentRunDurationMs, labels);
|
|
68
|
+
endActiveSpan(session, span);
|
|
69
|
+
session.spans.activeAgentRuns.delete(runId);
|
|
70
|
+
session.turnSequences.delete(runId);
|
|
71
|
+
if (session.currentAgentRunId === runId) session.currentAgentRunId = undefined;
|
|
72
|
+
emitLifecycleLog(session.logger, failed ? LOG_EVENT_NAMES.AGENT_RUN_FAILED : LOG_EVENT_NAMES.AGENT_RUN_COMPLETED, {
|
|
73
|
+
[AGENT_RUN_ATTRIBUTES.PI_AGENT_RUN_ID]: runId,
|
|
74
|
+
...buildLineageMetricSafeLogAttributes(session),
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function createTurnStartHandler(state: HandlerSessionState): Handler {
|
|
79
|
+
return handleTurnStart.bind(undefined, state);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function handleTurnStart(state: HandlerSessionState, event: unknown, _ctx: ObservMeHandlerContext): void {
|
|
83
|
+
const session = state.session;
|
|
84
|
+
if (!session) return;
|
|
85
|
+
|
|
86
|
+
const hadCurrentAgentRun = session.currentAgentRunId !== undefined;
|
|
87
|
+
const runId = session.currentAgentRunId ?? nextAgentRunId(session, event);
|
|
88
|
+
if (!hadCurrentAgentRun) recordTelemetryDrop(session, "agent_run_id_missing_turn_start", { operation: "turn_start" });
|
|
89
|
+
const runSpan = session.spans.activeAgentRuns.get(runId) ?? session.sessionSpan;
|
|
90
|
+
const turnIndex = nextTurnIndex(session, runId, event);
|
|
91
|
+
const turnId = deriveTurnId(runId, turnIndex);
|
|
92
|
+
const attributes = buildTurnAttributes(event, session, runId, turnId, turnIndex);
|
|
93
|
+
const span = startActiveChildSpan(session, SPAN_NAMES.PI_TURN, runSpan, attributes, "turn");
|
|
94
|
+
|
|
95
|
+
session.currentTurnId = turnId;
|
|
96
|
+
session.spans.activeTurns.set(turnId, span);
|
|
97
|
+
session.metrics.turnsStarted.add(1, metricLabels(session.config, session.lineage));
|
|
98
|
+
recordObsSessionTurn();
|
|
99
|
+
emitLifecycleLog(session.logger, LOG_EVENT_NAMES.TURN_STARTED, attributes);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function createTurnEndHandler(state: HandlerSessionState): Handler {
|
|
103
|
+
return handleTurnEnd.bind(undefined, state);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function handleTurnEnd(state: HandlerSessionState, event: unknown, _ctx: ObservMeHandlerContext): void {
|
|
107
|
+
const session = state.session;
|
|
108
|
+
if (!session) return;
|
|
109
|
+
|
|
110
|
+
const explicitTurnId = readString(event, "turnId") ?? readString(event, "turn_id");
|
|
111
|
+
let turnId = explicitTurnId;
|
|
112
|
+
let runId = readString(event, "agentRunId") ?? readString(event, "runId") ?? session.currentAgentRunId;
|
|
113
|
+
if (!runId && !turnId && session.currentTurnId) {
|
|
114
|
+
turnId = session.currentTurnId;
|
|
115
|
+
runId = readRunIdFromTurnId(turnId);
|
|
116
|
+
}
|
|
117
|
+
if (!runId) {
|
|
118
|
+
recordTelemetryDrop(session, "turn_run_id_missing", { operation: "turn_end" });
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const turnIndex = readInteger(event, "turnIndex") ?? readInteger(event, "turn_index") ?? session.turnSequences.get(runId);
|
|
123
|
+
if (!turnId) {
|
|
124
|
+
if (!turnIndex) {
|
|
125
|
+
recordTelemetryDrop(session, "turn_index_missing", { operation: "turn_end" });
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
turnId = deriveTurnId(runId, turnIndex);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const span = session.spans.activeTurns.get(turnId);
|
|
132
|
+
if (!span) {
|
|
133
|
+
recordTelemetryDrop(session, "turn_span_missing", { operation: "turn_end" });
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (workflowFailed(event)) span.setStatus({ code: SpanStatusCode.ERROR });
|
|
138
|
+
recordSpanDurationMs(span, session.metrics.turnDurationMs, metricLabels(session.config, session.lineage));
|
|
139
|
+
endActiveSpan(session, span);
|
|
140
|
+
session.spans.activeTurns.delete(turnId);
|
|
141
|
+
if (session.currentTurnId === turnId) session.currentTurnId = undefined;
|
|
142
|
+
session.metrics.turnsCompleted.add(1, metricLabels(session.config, session.lineage));
|
|
143
|
+
emitLifecycleLog(session.logger, LOG_EVENT_NAMES.TURN_COMPLETED, {
|
|
144
|
+
[TURN_ATTRIBUTES.PI_TURN_ID]: turnId,
|
|
145
|
+
[AGENT_RUN_ATTRIBUTES.PI_AGENT_RUN_ID]: runId,
|
|
146
|
+
...buildLineageMetricSafeLogAttributes(session),
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function readRunIdFromTurnId(turnId: string): string | undefined {
|
|
151
|
+
const separator = "-turn-";
|
|
152
|
+
const separatorIndex = turnId.lastIndexOf(separator);
|
|
153
|
+
if (separatorIndex <= 0) return undefined;
|
|
154
|
+
return turnId.slice(0, separatorIndex);
|
|
155
|
+
}
|