@obsunified/collector 2.0.1
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/LICENSE +21 -0
- package/README.md +60 -0
- package/dist/auth.d.ts +2 -0
- package/dist/auth.js +9 -0
- package/dist/auth.js.map +1 -0
- package/dist/chunk-UGWDOGGH.js +319 -0
- package/dist/chunk-UGWDOGGH.js.map +1 -0
- package/dist/chunk-XKQTVIRE.js +671 -0
- package/dist/chunk-XKQTVIRE.js.map +1 -0
- package/dist/index.d.ts +1197 -0
- package/dist/index.js +17707 -0
- package/dist/index.js.map +1 -0
- package/dist/ingest-auth-HFVO1zIp.d.ts +165 -0
- package/dist/openai-FJYOQ7WO.js +384 -0
- package/dist/openai-FJYOQ7WO.js.map +1 -0
- package/package.json +73 -0
- package/src/ai-parity/ai-parity.acceptance.test.ts +449 -0
- package/src/analyses/derive.ts +642 -0
- package/src/analyses/index.ts +50 -0
- package/src/analyses/investigations.ts +277 -0
- package/src/analyses/tier0.ts +568 -0
- package/src/auth/dashboard-auth.ts +269 -0
- package/src/auth/ingest-auth.ts +147 -0
- package/src/durable-objects/tail-hub.test.ts +32 -0
- package/src/durable-objects/tail-hub.ts +158 -0
- package/src/framework/collector.ts +467 -0
- package/src/framework/env.ts +90 -0
- package/src/framework/logger.ts +81 -0
- package/src/index.ts +211 -0
- package/src/lib/action-aggregates.ts +1031 -0
- package/src/lib/action-identity.ts +106 -0
- package/src/lib/actions-store.ts +397 -0
- package/src/lib/ai-pricing.ts +80 -0
- package/src/lib/ai-store/calls.ts +148 -0
- package/src/lib/ai-store/evaluations.test.ts +47 -0
- package/src/lib/ai-store/evaluations.ts +125 -0
- package/src/lib/ai-store/helpers.ts +37 -0
- package/src/lib/ai-store/retention.ts +17 -0
- package/src/lib/ai-store/sessions.ts +277 -0
- package/src/lib/ai-store/spans.ts +109 -0
- package/src/lib/ai-store/types.ts +112 -0
- package/src/lib/ai-store.ts +76 -0
- package/src/lib/alerts-store.ts +458 -0
- package/src/lib/analyses-runner.ts +439 -0
- package/src/lib/analyses-store.test.ts +243 -0
- package/src/lib/analyses-store.ts +454 -0
- package/src/lib/ask.test.ts +302 -0
- package/src/lib/ask.ts +390 -0
- package/src/lib/blob-store-s3.ts +213 -0
- package/src/lib/blob-store.ts +366 -0
- package/src/lib/eval-cases-store.test.ts +171 -0
- package/src/lib/eval-cases-store.ts +1033 -0
- package/src/lib/evidence-references.test.ts +10 -0
- package/src/lib/evidence-references.ts +684 -0
- package/src/lib/hash.ts +26 -0
- package/src/lib/identity-index/action-lookups.ts +805 -0
- package/src/lib/identity-index/constants.ts +1 -0
- package/src/lib/identity-index/key-lookups.ts +199 -0
- package/src/lib/identity-index/mappers.ts +349 -0
- package/src/lib/identity-index/types.ts +196 -0
- package/src/lib/identity-index/user-lookup.ts +137 -0
- package/src/lib/identity-index.test.ts +624 -0
- package/src/lib/identity-index.ts +85 -0
- package/src/lib/json.ts +39 -0
- package/src/lib/llm.ts +263 -0
- package/src/lib/logs-store.ts +188 -0
- package/src/lib/metrics-store.test.ts +189 -0
- package/src/lib/metrics-store.ts +312 -0
- package/src/lib/narrate-gate.test.ts +260 -0
- package/src/lib/narrate-gate.ts +253 -0
- package/src/lib/openai.test.ts +300 -0
- package/src/lib/openai.ts +512 -0
- package/src/lib/otlp.ts +212 -0
- package/src/lib/parse-pprof.test.ts +64 -0
- package/src/lib/parse-pprof.ts +184 -0
- package/src/lib/payload-capture.ts +22 -0
- package/src/lib/projects-store.ts +207 -0
- package/src/lib/propagation-metric.test.ts +196 -0
- package/src/lib/propagation-metric.ts +175 -0
- package/src/lib/sql-db-dialect.test.ts +22 -0
- package/src/lib/sql-db-postgres.ts +229 -0
- package/src/lib/sql-db.ts +166 -0
- package/src/lib/stage6.test.ts +216 -0
- package/src/lib/store/export.ts +65 -0
- package/src/lib/store/helpers.ts +367 -0
- package/src/lib/store/ingest.ts +68 -0
- package/src/lib/store/issues.ts +158 -0
- package/src/lib/store/overview.ts +127 -0
- package/src/lib/store/retention.ts +10 -0
- package/src/lib/store/service-map.ts +384 -0
- package/src/lib/store/trace-detail.bench.ts +76 -0
- package/src/lib/store/trace-detail.test.ts +410 -0
- package/src/lib/store/trace-detail.ts +427 -0
- package/src/lib/store/trace-queries.test.ts +29 -0
- package/src/lib/store/trace-queries.ts +89 -0
- package/src/lib/store-overview.test.ts +77 -0
- package/src/lib/store.ts +96 -0
- package/src/lib/tail-publisher.ts +64 -0
- package/src/lib/test-utils/mem-sql-db.test.ts +93 -0
- package/src/lib/test-utils/mem-sql-db.ts +86 -0
- package/src/lib/ua-parser.ts +61 -0
- package/src/lib/usage-store.ts +567 -0
- package/src/migrations/001_telemetry_spans.sql +28 -0
- package/src/migrations/002_usage_events.sql +24 -0
- package/src/migrations/003_usage_analytics_columns.sql +13 -0
- package/src/migrations/004_logs.sql +19 -0
- package/src/migrations/005_ai_calls.sql +25 -0
- package/src/migrations/006_user_profiles.sql +11 -0
- package/src/migrations/007_session_replay_metadata.sql +10 -0
- package/src/migrations/008_session_replay_storage_bytes.sql +1 -0
- package/src/migrations/009_projects_and_keys.sql +22 -0
- package/src/migrations/010_signal_project_id.sql +15 -0
- package/src/migrations/011_default_project_seed.sql +3 -0
- package/src/migrations/012_alert_rules.sql +17 -0
- package/src/migrations/013_alert_evaluations.sql +13 -0
- package/src/migrations/014_alert_state.sql +9 -0
- package/src/migrations/015_metrics.sql +58 -0
- package/src/migrations/016_metrics_exp_histogram_summary.sql +5 -0
- package/src/migrations/017_span_dropped_counts.sql +11 -0
- package/src/migrations/018_log_flags.sql +8 -0
- package/src/migrations/019_ai_span_payloads.sql +30 -0
- package/src/migrations/020_ai_span_evaluations.sql +33 -0
- package/src/migrations/021_ai_span_session.sql +13 -0
- package/src/migrations/022_span_log_session_id.sql +13 -0
- package/src/migrations/023_service_map_indexes.sql +32 -0
- package/src/migrations/024_analysis_results.sql +49 -0
- package/src/migrations/025_stage6_autopinning_alerts.sql +38 -0
- package/src/migrations/026_obs_dashboard_project_seed.sql +18 -0
- package/src/migrations/027_identity_propagation.sql +50 -0
- package/src/migrations/028_profile_blobs.sql +57 -0
- package/src/migrations/029_telemetry_sdk_name.sql +20 -0
- package/src/migrations/030_analysis_claim.sql +18 -0
- package/src/migrations/031_agent_action_graph.sql +154 -0
- package/src/migrations/032_payload_capture_flags.sql +8 -0
- package/src/migrations/033_eval_cases.sql +52 -0
- package/src/migrations/034_eval_case_results.sql +23 -0
- package/src/migrations/035_metric_exemplars.sql +33 -0
- package/src/migrations/036_trace_instrumentation_gaps.sql +19 -0
- package/src/migrations/037_eval_runs.sql +37 -0
- package/src/migrations/038_tool_call_evidence.sql +11 -0
- package/src/migrations/039_drop_trace_instrumentation_gaps.sql +11 -0
- package/src/migrations/040_evidence_retrieval_refs.sql +50 -0
- package/src/migrations-postgres/001_telemetry_spans.sql +33 -0
- package/src/migrations-postgres/002_usage_events.sql +24 -0
- package/src/migrations-postgres/003_usage_analytics_columns.sql +13 -0
- package/src/migrations-postgres/004_logs.sql +19 -0
- package/src/migrations-postgres/005_ai_calls.sql +25 -0
- package/src/migrations-postgres/006_user_profiles.sql +11 -0
- package/src/migrations-postgres/007_session_replay_metadata.sql +10 -0
- package/src/migrations-postgres/008_session_replay_storage_bytes.sql +2 -0
- package/src/migrations-postgres/009_projects_and_keys.sql +25 -0
- package/src/migrations-postgres/010_signal_project_id.sql +18 -0
- package/src/migrations-postgres/011_default_project_seed.sql +5 -0
- package/src/migrations-postgres/012_alert_rules.sql +17 -0
- package/src/migrations-postgres/013_alert_evaluations.sql +13 -0
- package/src/migrations-postgres/014_alert_state.sql +9 -0
- package/src/migrations-postgres/015_metrics.sql +47 -0
- package/src/migrations-postgres/016_metrics_exp_histogram_summary.sql +1 -0
- package/src/migrations-postgres/017_span_dropped_counts.sql +4 -0
- package/src/migrations-postgres/018_log_flags.sql +2 -0
- package/src/migrations-postgres/019_ai_span_payloads.sql +18 -0
- package/src/migrations-postgres/020_ai_span_evaluations.sql +21 -0
- package/src/migrations-postgres/021_ai_span_session.sql +7 -0
- package/src/migrations-postgres/022_span_log_session_id.sql +7 -0
- package/src/migrations-postgres/023_service_map_indexes.sql +9 -0
- package/src/migrations-postgres/024_analysis_results.sql +41 -0
- package/src/migrations-postgres/025_stage6_autopinning_alerts.sql +17 -0
- package/src/migrations-postgres/026_obs_dashboard_project_seed.sql +14 -0
- package/src/migrations-postgres/027_identity_propagation.sql +27 -0
- package/src/migrations-postgres/028_profile_blobs.sql +48 -0
- package/src/migrations-postgres/029_telemetry_sdk_name.sql +5 -0
- package/src/migrations-postgres/030_analysis_claim.sql +5 -0
- package/src/migrations-postgres/031_agent_action_graph.sql +190 -0
- package/src/migrations-postgres/032_payload_capture_flags.sql +8 -0
- package/src/migrations-postgres/033_eval_cases.sql +55 -0
- package/src/migrations-postgres/034_eval_case_results.sql +26 -0
- package/src/migrations-postgres/035_metric_exemplars.sql +31 -0
- package/src/migrations-postgres/036_trace_instrumentation_gaps.sql +19 -0
- package/src/migrations-postgres/037_eval_runs.sql +40 -0
- package/src/migrations-postgres/038_tool_call_evidence.sql +11 -0
- package/src/migrations-postgres/039_drop_trace_instrumentation_gaps.sql +11 -0
- package/src/migrations-postgres/040_evidence_retrieval_refs.sql +47 -0
- package/src/migrations-postgres/README.md +40 -0
- package/src/otlp/acceptance.test.ts +373 -0
- package/src/otlp/decode/body.ts +127 -0
- package/src/otlp/decode/logs.ts +96 -0
- package/src/otlp/decode/metrics.ts +402 -0
- package/src/otlp/decode/traces.ts +92 -0
- package/src/otlp/decode/values.ts +150 -0
- package/src/otlp/decode.test.ts +800 -0
- package/src/otlp/decode.ts +11 -0
- package/src/otlp/gen/opentelemetry/proto/collector/logs/v1/logs_service_pb.ts +132 -0
- package/src/otlp/gen/opentelemetry/proto/collector/metrics/v1/metrics_service_pb.ts +158 -0
- package/src/otlp/gen/opentelemetry/proto/collector/trace/v1/trace_service_pb.ts +158 -0
- package/src/otlp/gen/opentelemetry/proto/common/v1/common_pb.ts +289 -0
- package/src/otlp/gen/opentelemetry/proto/logs/v1/logs_pb.ts +397 -0
- package/src/otlp/gen/opentelemetry/proto/metrics/v1/metrics_pb.ts +1329 -0
- package/src/otlp/gen/opentelemetry/proto/resource/v1/resource_pb.ts +86 -0
- package/src/otlp/gen/opentelemetry/proto/trace/v1/trace_pb.ts +710 -0
- package/src/otlp/response.test.ts +158 -0
- package/src/otlp/response.ts +129 -0
- package/src/plugins/_context.ts +15 -0
- package/src/plugins/action-graph-processor/enrichers.ts +45 -0
- package/src/plugins/action-graph-processor/redaction.ts +84 -0
- package/src/plugins/action-graph-processor.test.ts +1023 -0
- package/src/plugins/action-graph-processor.ts +1172 -0
- package/src/plugins/action-routes.test.ts +716 -0
- package/src/plugins/action-routes.ts +343 -0
- package/src/plugins/ai-receiver.ts +254 -0
- package/src/plugins/ai-span-payloads-processor.test.ts +90 -0
- package/src/plugins/ai-span-payloads-processor.ts +180 -0
- package/src/plugins/alerts-evaluator.test.ts +91 -0
- package/src/plugins/alerts-evaluator.ts +328 -0
- package/src/plugins/alerts-routes.ts +101 -0
- package/src/plugins/analyses-routes.ts +138 -0
- package/src/plugins/ask-routes.ts +182 -0
- package/src/plugins/bot-filter.ts +19 -0
- package/src/plugins/connected-routes/manifest.ts +531 -0
- package/src/plugins/connected-routes.test.ts +1791 -0
- package/src/plugins/connected-routes.ts +1103 -0
- package/src/plugins/dashboard-routes.ts +41 -0
- package/src/plugins/default-span-enrichment.ts +92 -0
- package/src/plugins/eval-cases-routes.test.ts +391 -0
- package/src/plugins/eval-cases-routes.ts +529 -0
- package/src/plugins/evidence-retrieval-routes.benchmark.test.ts +245 -0
- package/src/plugins/evidence-retrieval-routes.test.ts +932 -0
- package/src/plugins/evidence-retrieval-routes.ts +2179 -0
- package/src/plugins/gen-ai-normalizer.test.ts +680 -0
- package/src/plugins/gen-ai-normalizer.ts +302 -0
- package/src/plugins/identity-receiver.ts +96 -0
- package/src/plugins/issue-enrichment.ts +132 -0
- package/src/plugins/issue-insights.ts +81 -0
- package/src/plugins/logs-receiver.ts +160 -0
- package/src/plugins/metrics-receiver.ts +91 -0
- package/src/plugins/onboarding-routes.ts +54 -0
- package/src/plugins/otlp-receiver.ts +124 -0
- package/src/plugins/platform-routes.ts +165 -0
- package/src/plugins/profile-routes.ts +468 -0
- package/src/plugins/projects-routes.ts +92 -0
- package/src/plugins/query-routes.ts +220 -0
- package/src/plugins/redaction-processor.ts +132 -0
- package/src/plugins/replay-query-routes.test.ts +38 -0
- package/src/plugins/replay-query-routes.ts +199 -0
- package/src/plugins/replay-receiver.ts +81 -0
- package/src/plugins/tail-routes.test.ts +47 -0
- package/src/plugins/tail-routes.ts +42 -0
- package/src/plugins/timeline-routes.ts +244 -0
- package/src/plugins/ua-enrichment.ts +27 -0
- package/src/plugins/usage-normalization.ts +46 -0
- package/src/plugins/usage-privacy.ts +55 -0
- package/src/plugins/usage-query-routes.ts +102 -0
- package/src/plugins/usage-receiver.ts +129 -0
- package/src/plugins/users-query-routes.ts +78 -0
- package/src/plugins/utm-enrichment.ts +36 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,1197 @@
|
|
|
1
|
+
import * as hono from 'hono';
|
|
2
|
+
import { MiddlewareHandler, Hono } from 'hono';
|
|
3
|
+
import * as hono_types from 'hono/types';
|
|
4
|
+
import * as _obsunified_types from '@obsunified/types';
|
|
5
|
+
import { StoredSpan, TelemetryOverviewOptions, TelemetryOverviewResponse, TelemetryTraceDetailResponse, TelemetryInstrumentationGapsResponse, TelemetryIssueOptions, TelemetryIssueOverviewResponse, TelemetryIssueDetailResponse, UsageEventRecord, UsageOverviewOptions, UsageOverviewResponse, UsageSessionDetailResponse, UsageSessionSummary, AlertRuleInput, AlertRule, AlertStateRow, AlertState, AlertEvaluationsListResponse, AlertComparison, JsonValue, EvidenceReference, EvidenceReferenceContract, Project, IngestKey, IngestKeyWithPlaintext } from '@obsunified/types';
|
|
6
|
+
import { b as CollectorEnv, c as CollectorRouteContext, L as Logger, C as ChildSpanRunner } from './ingest-auth-HFVO1zIp.js';
|
|
7
|
+
export { a as CollectorApp, d as consoleLogger, e as createIngestAuth } from './ingest-auth-HFVO1zIp.js';
|
|
8
|
+
import { ActionConfidence } from '@obsunified/types/constants';
|
|
9
|
+
import { Pool } from 'pg';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Storage seam for the collector — RFC 0008.
|
|
13
|
+
*
|
|
14
|
+
* Stores and plugins target this interface instead of `D1Database` directly,
|
|
15
|
+
* so a future Node / better-sqlite3 / ClickHouse runtime is one new adapter
|
|
16
|
+
* away rather than a fork-and-rewrite. The shape is deliberately D1's
|
|
17
|
+
* existing `prepare → bind → first|all|run` chain so the migration of
|
|
18
|
+
* existing stores is mechanical (search-and-replace the constructor type).
|
|
19
|
+
*
|
|
20
|
+
* Today there is one implementation, `D1Adapter`. A `MemSqlDb` test double
|
|
21
|
+
* lives next door under `test-utils/`; `BetterSqliteAdapter` and
|
|
22
|
+
* `ClickHouseAdapter` are deferred until they have a real runtime to serve.
|
|
23
|
+
*/
|
|
24
|
+
interface SqlDb {
|
|
25
|
+
readonly dialect?: SqlDialect;
|
|
26
|
+
prepare(sql: string): SqlStatement;
|
|
27
|
+
/**
|
|
28
|
+
* Run multiple prepared statements as a batch. On D1 this maps to a
|
|
29
|
+
* single network round-trip; on a future better-sqlite3 adapter it
|
|
30
|
+
* wraps the calls in a transaction. Returns one result per statement
|
|
31
|
+
* in input order, mirroring D1's `batch`.
|
|
32
|
+
*
|
|
33
|
+
* Statements MUST have been produced by this same `SqlDb` instance —
|
|
34
|
+
* mixing adapters is an error and runtime behavior is undefined.
|
|
35
|
+
*/
|
|
36
|
+
batch(statements: SqlStatement[]): Promise<Array<{
|
|
37
|
+
meta: {
|
|
38
|
+
changes: number;
|
|
39
|
+
};
|
|
40
|
+
}>>;
|
|
41
|
+
}
|
|
42
|
+
type SqlDialectName = "sqlite" | "postgres";
|
|
43
|
+
interface SqlDialect {
|
|
44
|
+
readonly name: SqlDialectName;
|
|
45
|
+
now(): string;
|
|
46
|
+
sinceHours(param: string): string;
|
|
47
|
+
sinceMinutes(param: string): string;
|
|
48
|
+
jsonText(expr: string, path: string): string;
|
|
49
|
+
}
|
|
50
|
+
interface SqlStatement {
|
|
51
|
+
bind(...args: unknown[]): SqlStatement;
|
|
52
|
+
first<T = Record<string, unknown>>(): Promise<T | null>;
|
|
53
|
+
all<T = Record<string, unknown>>(): Promise<{
|
|
54
|
+
results: T[];
|
|
55
|
+
}>;
|
|
56
|
+
run(): Promise<{
|
|
57
|
+
meta: {
|
|
58
|
+
changes: number;
|
|
59
|
+
};
|
|
60
|
+
}>;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* D1 already conforms to this shape almost exactly; the adapter normalizes
|
|
64
|
+
* two small differences:
|
|
65
|
+
* - `all()` on D1 returns `results?: T[]` (optional). We coerce to `[]`.
|
|
66
|
+
* - `run()`'s `meta.changes` is optional on D1. We coerce to `0`.
|
|
67
|
+
* Both differences are runtime-undetectable for the queries this codebase
|
|
68
|
+
* issues (every successful all() returns results; every run() against an
|
|
69
|
+
* INSERT/UPDATE/DELETE reports changes), but coercing keeps the typed
|
|
70
|
+
* interface honest.
|
|
71
|
+
*/
|
|
72
|
+
declare class D1Adapter implements SqlDb {
|
|
73
|
+
private readonly d1;
|
|
74
|
+
readonly dialect: SqlDialect;
|
|
75
|
+
constructor(d1: D1Database);
|
|
76
|
+
prepare(sql: string): SqlStatement;
|
|
77
|
+
batch(statements: SqlStatement[]): Promise<Array<{
|
|
78
|
+
meta: {
|
|
79
|
+
changes: number;
|
|
80
|
+
};
|
|
81
|
+
}>>;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
interface ServiceMapOptions {
|
|
85
|
+
projectId: string;
|
|
86
|
+
hours: number;
|
|
87
|
+
source?: "all" | "sdk" | "ebpf";
|
|
88
|
+
}
|
|
89
|
+
interface ServiceOperationsOptions {
|
|
90
|
+
projectId: string;
|
|
91
|
+
service: string;
|
|
92
|
+
hours: number;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
interface TelemetryInstrumentationGapCalibrationOptions {
|
|
96
|
+
projectId: string;
|
|
97
|
+
hours: number;
|
|
98
|
+
limit?: number;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
declare class TelemetryStore {
|
|
102
|
+
private readonly db;
|
|
103
|
+
constructor(db: SqlDb);
|
|
104
|
+
ingest(spans: StoredSpan[]): Promise<{
|
|
105
|
+
inserted: number;
|
|
106
|
+
traceCount: number;
|
|
107
|
+
}>;
|
|
108
|
+
getOverview(options: TelemetryOverviewOptions): Promise<TelemetryOverviewResponse>;
|
|
109
|
+
getTraceDetail(traceId: string, projectId: string): Promise<TelemetryTraceDetailResponse | null>;
|
|
110
|
+
getTraceGaps(traceId: string, projectId: string): Promise<TelemetryInstrumentationGapsResponse | null>;
|
|
111
|
+
calibrateTraceGaps(options: TelemetryInstrumentationGapCalibrationOptions): Promise<{
|
|
112
|
+
thresholds: _obsunified_types.InstrumentationGapThresholds;
|
|
113
|
+
windowHours: number;
|
|
114
|
+
sampledSpanCount: number;
|
|
115
|
+
traceCount: number;
|
|
116
|
+
flaggedTraceCount: number;
|
|
117
|
+
blindspotCount: number;
|
|
118
|
+
uninstrumentedTimeMs: number;
|
|
119
|
+
flaggedTraceRate: number;
|
|
120
|
+
status: string;
|
|
121
|
+
topTraces: {
|
|
122
|
+
traceId: string;
|
|
123
|
+
rootSpanName: string;
|
|
124
|
+
serviceName: string;
|
|
125
|
+
totalDurationMs: number;
|
|
126
|
+
blindspotCount: number;
|
|
127
|
+
uninstrumentedTimeMs: number;
|
|
128
|
+
ratio: number;
|
|
129
|
+
topBlindspot: _obsunified_types.TelemetryInstrumentationGap | null;
|
|
130
|
+
}[];
|
|
131
|
+
timestamp: string;
|
|
132
|
+
}>;
|
|
133
|
+
getIssueOverview(options: TelemetryIssueOptions): Promise<TelemetryIssueOverviewResponse>;
|
|
134
|
+
getIssueDetail(issueId: string, options: TelemetryIssueOptions): Promise<TelemetryIssueDetailResponse | null>;
|
|
135
|
+
getExportRows(options: TelemetryOverviewOptions): Promise<string>;
|
|
136
|
+
getServiceMap(options: ServiceMapOptions): Promise<{
|
|
137
|
+
nodes: {
|
|
138
|
+
service: string;
|
|
139
|
+
spanCount: number;
|
|
140
|
+
errorCount: number;
|
|
141
|
+
traceCount: number;
|
|
142
|
+
errorRate: number;
|
|
143
|
+
}[];
|
|
144
|
+
edges: {
|
|
145
|
+
source: string;
|
|
146
|
+
target: string;
|
|
147
|
+
calls: number;
|
|
148
|
+
errors: number;
|
|
149
|
+
errorRate: number;
|
|
150
|
+
p50DurationMs: number;
|
|
151
|
+
p95DurationMs: number;
|
|
152
|
+
rps: number;
|
|
153
|
+
isEbpf: boolean;
|
|
154
|
+
}[];
|
|
155
|
+
}>;
|
|
156
|
+
getServiceOperations(options: ServiceOperationsOptions): Promise<{
|
|
157
|
+
service: string;
|
|
158
|
+
spanCount: number;
|
|
159
|
+
traceCount: number;
|
|
160
|
+
errorCount: number;
|
|
161
|
+
operations: {
|
|
162
|
+
spanName: string;
|
|
163
|
+
calls: number;
|
|
164
|
+
errors: number;
|
|
165
|
+
errorRate: number;
|
|
166
|
+
p50DurationMs: number;
|
|
167
|
+
p95DurationMs: number;
|
|
168
|
+
}[];
|
|
169
|
+
recentErrors: {
|
|
170
|
+
traceId: string;
|
|
171
|
+
spanId: string;
|
|
172
|
+
spanName: string;
|
|
173
|
+
statusMessage: string | null;
|
|
174
|
+
durationMs: number;
|
|
175
|
+
startTime: string;
|
|
176
|
+
}[];
|
|
177
|
+
}>;
|
|
178
|
+
purgeExpired(): Promise<number>;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* UsageStore — union of all repos.
|
|
183
|
+
* - A's in-memory aggregation approach (more flexible, handles legacy load time keys)
|
|
184
|
+
* - A's broader error detection (event_type='frontend_error' OR severity='error')
|
|
185
|
+
* - A's multi-key load time parsing (loadTimeMs, load_time_ms, durationMs)
|
|
186
|
+
* - A's purgeExpired()
|
|
187
|
+
* - A's summarizeMap helper
|
|
188
|
+
*/
|
|
189
|
+
|
|
190
|
+
declare class UsageStore {
|
|
191
|
+
private readonly db;
|
|
192
|
+
constructor(db: SqlDb);
|
|
193
|
+
ingest(events: UsageEventRecord[]): Promise<{
|
|
194
|
+
inserted: number;
|
|
195
|
+
sessionCount: number;
|
|
196
|
+
}>;
|
|
197
|
+
getOverview(options: UsageOverviewOptions): Promise<UsageOverviewResponse>;
|
|
198
|
+
getSessionDetail(sessionId: string, projectId: string): Promise<UsageSessionDetailResponse | null>;
|
|
199
|
+
/**
|
|
200
|
+
* List sessions with an optional qualitative filter.
|
|
201
|
+
*
|
|
202
|
+
* Aggregates per session_id in a single query; supports three filters
|
|
203
|
+
* derived from session-level rollups: sessions that errored, sessions
|
|
204
|
+
* with no interactions (engagement drop-off), and sessions with slow
|
|
205
|
+
* page loads.
|
|
206
|
+
*/
|
|
207
|
+
listSessions(options: {
|
|
208
|
+
projectId: string;
|
|
209
|
+
hours: number;
|
|
210
|
+
filter: "all" | "ended_in_error" | "dropoff" | "slow";
|
|
211
|
+
slowMs?: number;
|
|
212
|
+
limit?: number;
|
|
213
|
+
}): Promise<{
|
|
214
|
+
sessions: Array<UsageSessionSummary & {
|
|
215
|
+
interactionCount: number;
|
|
216
|
+
maxLoadTimeMs: number | null;
|
|
217
|
+
}>;
|
|
218
|
+
}>;
|
|
219
|
+
purgeExpired(): Promise<number>;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Factory that materializes an `SqlDb` for the request's `env`. Per-request
|
|
224
|
+
* because Cloudflare's `D1Database` binding only exists once `env` is in
|
|
225
|
+
* scope; on Workers this is essentially free since `D1Adapter` is a thin
|
|
226
|
+
* wrapper. Hosts override this to inject a fake DB in tests, a different
|
|
227
|
+
* engine in alternate runtimes, or a tracing wrapper at the storage layer.
|
|
228
|
+
*/
|
|
229
|
+
type SqlDbFactory = (env: CollectorEnv) => SqlDb;
|
|
230
|
+
interface SpanProcessorPlugin {
|
|
231
|
+
name: string;
|
|
232
|
+
process(spans: StoredSpan[], context: CollectorRouteContext): Promise<StoredSpan[]> | StoredSpan[];
|
|
233
|
+
}
|
|
234
|
+
interface UsageEventProcessorPlugin {
|
|
235
|
+
name: string;
|
|
236
|
+
process(events: UsageEventRecord[], context: CollectorRouteContext): Promise<UsageEventRecord[]> | UsageEventRecord[];
|
|
237
|
+
}
|
|
238
|
+
interface CollectorPluginContext {
|
|
239
|
+
addSpanProcessor(processor: SpanProcessorPlugin): void;
|
|
240
|
+
addUsageEventProcessor(processor: UsageEventProcessorPlugin): void;
|
|
241
|
+
getRegisteredPluginNames(): string[];
|
|
242
|
+
}
|
|
243
|
+
interface CollectorPlugin {
|
|
244
|
+
name: string;
|
|
245
|
+
register(app: Hono<{
|
|
246
|
+
Bindings: CollectorEnv;
|
|
247
|
+
}>, context: CollectorRuntime): void;
|
|
248
|
+
}
|
|
249
|
+
interface CollectorAuthConfig {
|
|
250
|
+
/** Single middleware applied to both /v1/* (ingest) and /internal/* (query) routes */
|
|
251
|
+
middleware?: MiddlewareHandler<{
|
|
252
|
+
Bindings: CollectorEnv;
|
|
253
|
+
Variables: any;
|
|
254
|
+
}>;
|
|
255
|
+
/** @deprecated Use middleware instead. Ingest-only auth for /v1/* routes. */
|
|
256
|
+
ingest?: MiddlewareHandler<{
|
|
257
|
+
Bindings: CollectorEnv;
|
|
258
|
+
Variables: any;
|
|
259
|
+
}>;
|
|
260
|
+
/** @deprecated Use middleware instead. Query-only auth for /internal/* routes. */
|
|
261
|
+
query?: MiddlewareHandler<{
|
|
262
|
+
Bindings: CollectorEnv;
|
|
263
|
+
Variables: any;
|
|
264
|
+
}>;
|
|
265
|
+
}
|
|
266
|
+
interface CollectorConfig {
|
|
267
|
+
plugins: CollectorPlugin[];
|
|
268
|
+
auth?: CollectorAuthConfig;
|
|
269
|
+
/** Comma-separated allowed origins for CORS on ingest endpoints */
|
|
270
|
+
allowedOrigins?: string;
|
|
271
|
+
/** Register dashboard auth routes and middleware */
|
|
272
|
+
dashboardAuth?: {
|
|
273
|
+
middleware: MiddlewareHandler<{
|
|
274
|
+
Bindings: CollectorEnv;
|
|
275
|
+
Variables: any;
|
|
276
|
+
}>;
|
|
277
|
+
registerRoutes: (app: Hono<{
|
|
278
|
+
Bindings: CollectorEnv;
|
|
279
|
+
}>) => void;
|
|
280
|
+
};
|
|
281
|
+
/**
|
|
282
|
+
* Pluggable structured logger. Defaults to console output. Pass a logger
|
|
283
|
+
* from `@obsunified/telemetry-sdk` to ship the collector's own log output as
|
|
284
|
+
* OTLP — see apps/collector/SELF_INSTRUMENTATION.md.
|
|
285
|
+
*/
|
|
286
|
+
logger?: Logger;
|
|
287
|
+
/**
|
|
288
|
+
* Wraps async work in a child span on the active request span. Wire this
|
|
289
|
+
* to `@obsunified/telemetry-sdk`'s `withChildSpan` from the worker entrypoint to
|
|
290
|
+
* surface LLM hops + DB-heavy paths as nested spans. Defaults to
|
|
291
|
+
* pass-through.
|
|
292
|
+
*/
|
|
293
|
+
withChildSpan?: ChildSpanRunner;
|
|
294
|
+
/**
|
|
295
|
+
* RFC 0008 — override the storage adapter. Per-request factory because
|
|
296
|
+
* `env.DB` only exists once a request lands. Defaults to wrapping
|
|
297
|
+
* `env.DB` in `D1Adapter`. Override in tests (use `MemSqlDb`) or to add
|
|
298
|
+
* a tracing layer at the storage seam.
|
|
299
|
+
*/
|
|
300
|
+
sqlDb?: SqlDbFactory;
|
|
301
|
+
}
|
|
302
|
+
declare class CollectorRuntime implements CollectorPluginContext {
|
|
303
|
+
private readonly spanProcessors;
|
|
304
|
+
private readonly usageEventProcessors;
|
|
305
|
+
private readonly plugins;
|
|
306
|
+
private readonly sqlDbFactory;
|
|
307
|
+
readonly logger: Logger;
|
|
308
|
+
readonly withChildSpan: ChildSpanRunner;
|
|
309
|
+
constructor(logger?: Logger, withChildSpan?: ChildSpanRunner, sqlDbFactory?: SqlDbFactory);
|
|
310
|
+
/**
|
|
311
|
+
* Materialize an `SqlDb` for this request. Stores will accept this
|
|
312
|
+
* directly once Phase 1.5 of RFC 0008 lands; until then plugins that
|
|
313
|
+
* want to bypass `c.env.DB` can call this to opt in early.
|
|
314
|
+
*/
|
|
315
|
+
getSqlDb(env: CollectorEnv): SqlDb;
|
|
316
|
+
registerPlugin(plugin: CollectorPlugin): void;
|
|
317
|
+
addSpanProcessor(processor: SpanProcessorPlugin): void;
|
|
318
|
+
addUsageEventProcessor(processor: UsageEventProcessorPlugin): void;
|
|
319
|
+
getRegisteredPluginNames(): string[];
|
|
320
|
+
createRouteContext(env: CollectorEnv, hono: CollectorRouteContext["hono"]): CollectorRouteContext;
|
|
321
|
+
createStore(env: CollectorEnv): TelemetryStore;
|
|
322
|
+
createUsageStore(env: CollectorEnv): UsageStore;
|
|
323
|
+
runSpanProcessors(spans: StoredSpan[], context: CollectorRouteContext): Promise<StoredSpan[]>;
|
|
324
|
+
runUsageEventProcessors(events: UsageEventRecord[], context: CollectorRouteContext): Promise<UsageEventRecord[]>;
|
|
325
|
+
}
|
|
326
|
+
declare const createTelemetryCollectorApp: (pluginsOrConfig: CollectorPlugin[] | CollectorConfig) => Hono<{
|
|
327
|
+
Bindings: CollectorEnv;
|
|
328
|
+
}>;
|
|
329
|
+
/**
|
|
330
|
+
* Scheduled handler that purges expired telemetry and usage rows.
|
|
331
|
+
* Wire into wrangler.toml: `[triggers] crons = ["0 * * * *"]`
|
|
332
|
+
* Source: AgentOwl + DecisionOps
|
|
333
|
+
*/
|
|
334
|
+
declare const createRetentionCleanupHandler: (options?: {
|
|
335
|
+
logger?: Logger;
|
|
336
|
+
}) => {
|
|
337
|
+
scheduled(_event: ScheduledEvent, env: CollectorEnv, _ctx: ExecutionContext): Promise<void>;
|
|
338
|
+
};
|
|
339
|
+
/**
|
|
340
|
+
* RFC 0002 Stage 1 — run any due Analyses. Cheap to call frequently because
|
|
341
|
+
* `runAllDueAnalyses` filters by `last_run + refreshSeconds < now` before
|
|
342
|
+
* touching D1.
|
|
343
|
+
*
|
|
344
|
+
* Wire to a per-minute trigger in wrangler.toml: `crons = ["* * * * *"]`.
|
|
345
|
+
* Kept distinct from retention so the per-minute tick doesn't sweep every
|
|
346
|
+
* retention table every cycle.
|
|
347
|
+
*/
|
|
348
|
+
declare const createAnalysesRunHandler: (options?: {
|
|
349
|
+
logger?: Logger;
|
|
350
|
+
tracer?: ChildSpanRunner;
|
|
351
|
+
}) => {
|
|
352
|
+
scheduled(_event: ScheduledEvent, env: CollectorEnv, _ctx: ExecutionContext): Promise<void>;
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
declare const actionRoutesPlugin: CollectorPlugin;
|
|
356
|
+
|
|
357
|
+
declare const aiReceiverPlugin: CollectorPlugin;
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Span processor that routes large AI payloads to the ai_span_payloads
|
|
361
|
+
* side table.
|
|
362
|
+
*
|
|
363
|
+
* For every span that has an `openinference.span.kind` attribute, we look
|
|
364
|
+
* for `ai.payload.input` / `ai.payload.output`, write them (plus the kind)
|
|
365
|
+
* to `ai_span_payloads`, and strip them from the span's attributes_json
|
|
366
|
+
* before it hits `telemetry_spans`.
|
|
367
|
+
*
|
|
368
|
+
* This keeps the hot spans table lean while preserving full replay data
|
|
369
|
+
* for AI calls.
|
|
370
|
+
*/
|
|
371
|
+
|
|
372
|
+
declare const aiSpanPayloadsProcessorPlugin: CollectorPlugin;
|
|
373
|
+
|
|
374
|
+
declare function evaluateAllRules(env: CollectorEnv, options?: {
|
|
375
|
+
logger?: Logger;
|
|
376
|
+
tracer?: ChildSpanRunner;
|
|
377
|
+
concurrency?: number;
|
|
378
|
+
ruleTimeoutMs?: number;
|
|
379
|
+
}): Promise<{
|
|
380
|
+
evaluated: number;
|
|
381
|
+
fired: number;
|
|
382
|
+
resolved: number;
|
|
383
|
+
}>;
|
|
384
|
+
/**
|
|
385
|
+
* Scheduled handler suitable for wrangler cron triggers. Dispatches on the
|
|
386
|
+
* cron expression so multiple triggers can share this handler.
|
|
387
|
+
*/
|
|
388
|
+
declare function createAlertEvaluatorHandler(): {
|
|
389
|
+
scheduled(_event: {
|
|
390
|
+
cron: string;
|
|
391
|
+
}, env: CollectorEnv, ctx: {
|
|
392
|
+
waitUntil(promise: Promise<unknown>): void;
|
|
393
|
+
}): Promise<void>;
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
declare const alertsRoutesPlugin: CollectorPlugin;
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* RFC 0002 — HTTP surface for application-aware Analyses.
|
|
400
|
+
*
|
|
401
|
+
* GET /internal/analyses — list registered definitions
|
|
402
|
+
* GET /internal/analyses/:id/result — definition + latest result
|
|
403
|
+
* GET /internal/analyses/results — bulk: every definition + latest
|
|
404
|
+
* POST /internal/analyses/:id/run — Stage 4: on-demand re-run for
|
|
405
|
+
* view: "page" investigations
|
|
406
|
+
*
|
|
407
|
+
* Cron writes happen via the scheduled handler (see analyses-runner.ts).
|
|
408
|
+
* The on-demand POST exists so an investigation page's [Re-run] button
|
|
409
|
+
* doesn't have to wait for the next 5-min tick.
|
|
410
|
+
*/
|
|
411
|
+
|
|
412
|
+
declare const analysesRoutesPlugin: CollectorPlugin;
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* RFC 0002 Stage 5 — Ask box HTTP surface.
|
|
416
|
+
*
|
|
417
|
+
* POST /internal/ask { question } → AskResponse
|
|
418
|
+
*
|
|
419
|
+
* The dashboard's top-bar AskBox calls this once per question. Single-turn
|
|
420
|
+
* for v1; the conversational `/ask` thread (with follow-ups + "Save as
|
|
421
|
+
* panel") lands in a follow-up commit.
|
|
422
|
+
*
|
|
423
|
+
* The route does no SQL itself — it composes runAsk() from the catalog
|
|
424
|
+
* lookups (AnalysesStore + getAllAnalysesForProject) and the LLM config.
|
|
425
|
+
* If ANTHROPIC_API_KEY is unset we return a structured error rather than
|
|
426
|
+
* 500-ing, so the dashboard can render a "set ANTHROPIC_API_KEY to
|
|
427
|
+
* enable Ask" hint instead of a generic failure.
|
|
428
|
+
*/
|
|
429
|
+
|
|
430
|
+
declare const askRoutesPlugin: CollectorPlugin;
|
|
431
|
+
|
|
432
|
+
declare const botFilterPlugin: CollectorPlugin;
|
|
433
|
+
|
|
434
|
+
type CausalConfidence = ActionConfidence;
|
|
435
|
+
interface ActionRef {
|
|
436
|
+
id: string;
|
|
437
|
+
projectId: string;
|
|
438
|
+
rootActionId: string;
|
|
439
|
+
causedByActionId: string | null;
|
|
440
|
+
actorType: string;
|
|
441
|
+
actorId: string | null;
|
|
442
|
+
actionKind: string;
|
|
443
|
+
name: string | null;
|
|
444
|
+
status: string;
|
|
445
|
+
startedAt: string;
|
|
446
|
+
endedAt: string | null;
|
|
447
|
+
durationMs: number | null;
|
|
448
|
+
traceId: string | null;
|
|
449
|
+
spanId: string | null;
|
|
450
|
+
sessionId: string | null;
|
|
451
|
+
interactionId: string | null;
|
|
452
|
+
userId: string | null;
|
|
453
|
+
agentRunId: string | null;
|
|
454
|
+
stepId: string | null;
|
|
455
|
+
toolCallId: string | null;
|
|
456
|
+
promptVersion: string | null;
|
|
457
|
+
modelName: string | null;
|
|
458
|
+
provider: string | null;
|
|
459
|
+
totalCostUsd: number | null;
|
|
460
|
+
causalConfidence: CausalConfidence;
|
|
461
|
+
attrsJson: string | null;
|
|
462
|
+
}
|
|
463
|
+
interface AgentRunRef {
|
|
464
|
+
id: string;
|
|
465
|
+
projectId: string;
|
|
466
|
+
agentId: string;
|
|
467
|
+
agentName: string;
|
|
468
|
+
agentVersion: string;
|
|
469
|
+
goal: string | null;
|
|
470
|
+
outcome: string | null;
|
|
471
|
+
autonomyLevel: string;
|
|
472
|
+
status: string;
|
|
473
|
+
errorMessage: string | null;
|
|
474
|
+
totalCostUsd: number | null;
|
|
475
|
+
totalDurationMs: number | null;
|
|
476
|
+
metadataJson: string | null;
|
|
477
|
+
}
|
|
478
|
+
interface ToolCallRef {
|
|
479
|
+
id: string;
|
|
480
|
+
actionId: string;
|
|
481
|
+
projectId: string;
|
|
482
|
+
toolName: string;
|
|
483
|
+
argsHash: string;
|
|
484
|
+
resultHash: string;
|
|
485
|
+
errorType: string | null;
|
|
486
|
+
sideEffect: number;
|
|
487
|
+
approvalState: string | null;
|
|
488
|
+
argsRedacted: string | null;
|
|
489
|
+
resultRedacted: string | null;
|
|
490
|
+
mcpAuditJson: string | null;
|
|
491
|
+
mutationBeforeJson: string | null;
|
|
492
|
+
mutationAfterJson: string | null;
|
|
493
|
+
mutationDiffJson: string | null;
|
|
494
|
+
mutationArtifactId: string | null;
|
|
495
|
+
}
|
|
496
|
+
interface RetrievalEventRef {
|
|
497
|
+
id: string;
|
|
498
|
+
actionId: string;
|
|
499
|
+
projectId: string;
|
|
500
|
+
retrieverName: string;
|
|
501
|
+
queryHash: string;
|
|
502
|
+
documentsJson: string | null;
|
|
503
|
+
totalResults: number;
|
|
504
|
+
maxRelevanceScore: number | null;
|
|
505
|
+
durationMs: number | null;
|
|
506
|
+
}
|
|
507
|
+
interface EvalResultRef {
|
|
508
|
+
id: string;
|
|
509
|
+
actionId: string;
|
|
510
|
+
projectId: string;
|
|
511
|
+
evaluatorName: string;
|
|
512
|
+
evaluatorVersion: string;
|
|
513
|
+
score: number | null;
|
|
514
|
+
passed: number;
|
|
515
|
+
reasoning: string | null;
|
|
516
|
+
rubricJson: string | null;
|
|
517
|
+
}
|
|
518
|
+
interface ArtifactRef {
|
|
519
|
+
id: string;
|
|
520
|
+
actionId: string;
|
|
521
|
+
projectId: string;
|
|
522
|
+
artifactName: string;
|
|
523
|
+
artifactType: string;
|
|
524
|
+
storageRef: string | null;
|
|
525
|
+
sizeBytes: number | null;
|
|
526
|
+
sha256Hash: string | null;
|
|
527
|
+
contentPreview: string | null;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* RFC 0006 Phase 3.1 — Connected rail manifest endpoint.
|
|
532
|
+
*
|
|
533
|
+
* GET /internal/connected/:kind/:id
|
|
534
|
+
*
|
|
535
|
+
* Returns the entity's identity-graph neighbors (Up / Across / Down) +
|
|
536
|
+
* topic neighbors (Related), bundled into the shape the dashboard's
|
|
537
|
+
* <ConnectedRail /> renders directly. Built on `IdentityIndex` so the
|
|
538
|
+
* underlying SQL is shared with `/internal/timeline/:sessionId` and any
|
|
539
|
+
* future cross-signal consumer.
|
|
540
|
+
*
|
|
541
|
+
* The handler is the single read path the rail uses. Sections that have
|
|
542
|
+
* no neighbors render as `links: []` with an `emptyReason` explaining
|
|
543
|
+
* why — never absent. This is the "informative absence" pattern from
|
|
544
|
+
* RFC 0006 § Connected rail / Empty-state.
|
|
545
|
+
*/
|
|
546
|
+
|
|
547
|
+
declare const connectedRoutesPlugin: CollectorPlugin;
|
|
548
|
+
|
|
549
|
+
/**
|
|
550
|
+
* Serves the dashboard SPA.
|
|
551
|
+
*
|
|
552
|
+
* For Cloudflare Workers: configure [assets] in wrangler.toml pointing to
|
|
553
|
+
* the @obsunified/dashboard build output. The Workers runtime handles static file
|
|
554
|
+
* serving automatically; this plugin provides the fallback route for SPA
|
|
555
|
+
* client-side routing.
|
|
556
|
+
*
|
|
557
|
+
* For Node.js / other runtimes: serve static files from @obsunified/dashboard/dist
|
|
558
|
+
* using your framework's static file middleware, then mount this plugin for
|
|
559
|
+
* the SPA fallback.
|
|
560
|
+
*/
|
|
561
|
+
declare const dashboardRoutesPlugin: CollectorPlugin;
|
|
562
|
+
|
|
563
|
+
declare const defaultSpanEnrichmentPlugin: CollectorPlugin;
|
|
564
|
+
|
|
565
|
+
declare const evalCasesRoutesPlugin: CollectorPlugin;
|
|
566
|
+
|
|
567
|
+
declare const evidenceRetrievalRoutesPlugin: CollectorPlugin;
|
|
568
|
+
|
|
569
|
+
/**
|
|
570
|
+
* Normalize OpenTelemetry `gen_ai.*` semantic-convention attributes, OTel MCP attributes,
|
|
571
|
+
* and OpenInference span kinds into the canonical obs-unified Agent Action Graph schema.
|
|
572
|
+
*
|
|
573
|
+
* References:
|
|
574
|
+
* https://opentelemetry.io/docs/specs/semconv/gen-ai/
|
|
575
|
+
* https://github.com/Arize-ai/openinference/blob/main/spec/
|
|
576
|
+
*
|
|
577
|
+
* Must run BEFORE ai-span-payloads-processor — that processor assumes
|
|
578
|
+
* `openinference.span.kind` and `ai.payload.*` are already set.
|
|
579
|
+
*/
|
|
580
|
+
|
|
581
|
+
declare const genAiNormalizerPlugin: CollectorPlugin;
|
|
582
|
+
|
|
583
|
+
declare const identityReceiverPlugin: CollectorPlugin;
|
|
584
|
+
|
|
585
|
+
declare const issueEnrichmentPlugin: CollectorPlugin;
|
|
586
|
+
|
|
587
|
+
declare const issueInsightsPlugin: CollectorPlugin;
|
|
588
|
+
|
|
589
|
+
declare const logsReceiverPlugin: CollectorPlugin;
|
|
590
|
+
|
|
591
|
+
/** OTLP/HTTP metrics receiver. Accepts JSON or protobuf, with gzip. */
|
|
592
|
+
|
|
593
|
+
declare const metricsReceiverPlugin: CollectorPlugin;
|
|
594
|
+
|
|
595
|
+
/**
|
|
596
|
+
* Drives the in-dashboard Onboarding tab — returns counts of signal
|
|
597
|
+
* types, used to decide which "you need to wire X" snippets to show
|
|
598
|
+
* the user.
|
|
599
|
+
*
|
|
600
|
+
* Returns zeros for tables that don't yet exist (e.g. fresh DB) rather
|
|
601
|
+
* than 500ing — onboarding has to work on day zero.
|
|
602
|
+
*/
|
|
603
|
+
declare const onboardingRoutesPlugin: CollectorPlugin;
|
|
604
|
+
|
|
605
|
+
/** OTLP/HTTP trace receiver. Accepts JSON or protobuf, with gzip. */
|
|
606
|
+
|
|
607
|
+
declare const otlpReceiverPlugin: CollectorPlugin;
|
|
608
|
+
|
|
609
|
+
declare const platformRoutesPlugin: CollectorPlugin;
|
|
610
|
+
|
|
611
|
+
/**
|
|
612
|
+
* RFC 0007 — pprof profiling receiver + read endpoints.
|
|
613
|
+
*
|
|
614
|
+
* POST /v1/profiles/pprof — accepts gzipped pprof blob
|
|
615
|
+
* GET /internal/profiles/:id — proxies the blob back
|
|
616
|
+
* GET /internal/profiles/:id?trace_id=… — Phase 4.5 server-side filter
|
|
617
|
+
*
|
|
618
|
+
* Phase 4 minimal scope: ingest-time pprof parsing is deferred. The
|
|
619
|
+
* receiver writes the blob verbatim to R2 / filesystem and reads
|
|
620
|
+
* trace_ids from an `x-obs-trace-ids` header (comma-separated). The
|
|
621
|
+
* @obsunified/telemetry-sdk profile helper will stamp this; eBPF agents that
|
|
622
|
+
* don't emit the header just don't populate `profile_trace_index`,
|
|
623
|
+
* which means the trace waterfall's 🔥 badge won't fire for those
|
|
624
|
+
* profiles. Aggregate views still work.
|
|
625
|
+
*
|
|
626
|
+
* A follow-on commit can add server-side pprof parsing using a Buf-
|
|
627
|
+
* generated schema or pprof-format. The endpoint shape doesn't change
|
|
628
|
+
* when that lands.
|
|
629
|
+
*/
|
|
630
|
+
|
|
631
|
+
declare const profileRoutesPlugin: CollectorPlugin;
|
|
632
|
+
|
|
633
|
+
declare const projectsRoutesPlugin: CollectorPlugin;
|
|
634
|
+
|
|
635
|
+
declare const queryRoutesPlugin: CollectorPlugin;
|
|
636
|
+
|
|
637
|
+
declare const redactionProcessorPlugin: CollectorPlugin;
|
|
638
|
+
|
|
639
|
+
declare const replayQueryRoutesPlugin: CollectorPlugin;
|
|
640
|
+
|
|
641
|
+
declare const replayReceiverPlugin: CollectorPlugin;
|
|
642
|
+
|
|
643
|
+
/**
|
|
644
|
+
* Live tail SSE endpoint. The dashboard opens an EventSource here; the
|
|
645
|
+
* collector proxies to the TailHub Durable Object which holds the open
|
|
646
|
+
* stream and fans out broadcasts from ingest.
|
|
647
|
+
*/
|
|
648
|
+
declare const tailRoutesPlugin: CollectorPlugin;
|
|
649
|
+
|
|
650
|
+
declare const timelineRoutesPlugin: CollectorPlugin;
|
|
651
|
+
|
|
652
|
+
declare const uaEnrichmentPlugin: CollectorPlugin;
|
|
653
|
+
|
|
654
|
+
declare const usageNormalizationPlugin: CollectorPlugin;
|
|
655
|
+
|
|
656
|
+
declare const usagePrivacyPlugin: CollectorPlugin;
|
|
657
|
+
|
|
658
|
+
declare const usageQueryRoutesPlugin: CollectorPlugin;
|
|
659
|
+
|
|
660
|
+
/** Union: A's JSON error handling, event limit, env-based retention. P/D's dynamic CORS. */
|
|
661
|
+
|
|
662
|
+
declare const usageReceiverPlugin: CollectorPlugin;
|
|
663
|
+
|
|
664
|
+
declare const usersQueryRoutesPlugin: CollectorPlugin;
|
|
665
|
+
|
|
666
|
+
declare const utmEnrichmentPlugin: CollectorPlugin;
|
|
667
|
+
|
|
668
|
+
/**
|
|
669
|
+
* Creates auth routes and middleware for dashboard password login.
|
|
670
|
+
*
|
|
671
|
+
* Routes added:
|
|
672
|
+
* POST /auth/login — accepts { password }, sets session cookie
|
|
673
|
+
* GET /auth/check — returns { authenticated: true/false }
|
|
674
|
+
* POST /auth/logout — clears session cookie
|
|
675
|
+
*
|
|
676
|
+
* The returned middleware validates the session cookie on protected routes.
|
|
677
|
+
*/
|
|
678
|
+
declare function createDashboardAuth(config: {
|
|
679
|
+
password: string;
|
|
680
|
+
}): {
|
|
681
|
+
middleware: MiddlewareHandler<{
|
|
682
|
+
Bindings: CollectorEnv;
|
|
683
|
+
Variables: {
|
|
684
|
+
projectId: string;
|
|
685
|
+
};
|
|
686
|
+
}>;
|
|
687
|
+
registerRoutes: (app: hono.Hono<{
|
|
688
|
+
Bindings: CollectorEnv;
|
|
689
|
+
}>) => void;
|
|
690
|
+
};
|
|
691
|
+
|
|
692
|
+
/**
|
|
693
|
+
* In-memory SSE pub/sub hub for live-tailing spans and logs.
|
|
694
|
+
*
|
|
695
|
+
* Ingest plugins call `/publish` after writing to D1; the dashboard opens an
|
|
696
|
+
* EventSource on `/internal/telemetry/tail` which proxies here via `/subscribe`.
|
|
697
|
+
*
|
|
698
|
+
* One singleton DO instance is used (idFromName("singleton")); it fans out to
|
|
699
|
+
* every connected subscriber, filtering by projectId and kind server-side so
|
|
700
|
+
* clients don't see other tenants' data.
|
|
701
|
+
*
|
|
702
|
+
* Heartbeat frames keep the connection alive through proxies with idle
|
|
703
|
+
* timeouts (Vite dev proxy, Cloudflare edge).
|
|
704
|
+
*/
|
|
705
|
+
type TailKind = "span" | "log";
|
|
706
|
+
interface TailEvent {
|
|
707
|
+
kind: TailKind;
|
|
708
|
+
projectId: string;
|
|
709
|
+
row: Record<string, unknown>;
|
|
710
|
+
t: string;
|
|
711
|
+
}
|
|
712
|
+
declare class TailHub {
|
|
713
|
+
private readonly subscribers;
|
|
714
|
+
private readonly encoder;
|
|
715
|
+
fetch(req: Request): Promise<Response>;
|
|
716
|
+
private subscribe;
|
|
717
|
+
private drop;
|
|
718
|
+
private broadcast;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
type ActionRecord = Omit<ActionRef, "projectId"> & {
|
|
722
|
+
projectId: string;
|
|
723
|
+
};
|
|
724
|
+
type AgentRunRecord = Omit<AgentRunRef, "projectId"> & {
|
|
725
|
+
projectId: string;
|
|
726
|
+
};
|
|
727
|
+
type ToolCallRecord = Omit<ToolCallRef, "projectId" | "sideEffect"> & {
|
|
728
|
+
projectId: string;
|
|
729
|
+
sideEffect: boolean | number;
|
|
730
|
+
};
|
|
731
|
+
type RetrievalEventRecord = Omit<RetrievalEventRef, "projectId"> & {
|
|
732
|
+
projectId: string;
|
|
733
|
+
};
|
|
734
|
+
type EvalResultRecord = Omit<EvalResultRef, "projectId" | "passed"> & {
|
|
735
|
+
projectId: string;
|
|
736
|
+
passed: boolean | number;
|
|
737
|
+
};
|
|
738
|
+
type ArtifactRecord = Omit<ArtifactRef, "projectId"> & {
|
|
739
|
+
projectId: string;
|
|
740
|
+
};
|
|
741
|
+
declare class ActionStore {
|
|
742
|
+
private readonly db;
|
|
743
|
+
constructor(db: SqlDb);
|
|
744
|
+
upsertAction(action: ActionRecord): Promise<void>;
|
|
745
|
+
upsertAgentRun(run: AgentRunRecord): Promise<void>;
|
|
746
|
+
upsertToolCall(toolCall: ToolCallRecord): Promise<void>;
|
|
747
|
+
upsertRetrievalEvent(event: RetrievalEventRecord): Promise<void>;
|
|
748
|
+
upsertEvalResult(result: EvalResultRecord): Promise<void>;
|
|
749
|
+
upsertArtifact(artifact: ArtifactRecord): Promise<void>;
|
|
750
|
+
getAction(projectId: string, actionId: string): Promise<ActionRef | null>;
|
|
751
|
+
listActionsByRoot(projectId: string, rootActionId: string, limit?: number): Promise<ActionRef[]>;
|
|
752
|
+
getAgentRun(projectId: string, agentRunId: string): Promise<AgentRunRef | null>;
|
|
753
|
+
listToolCallsByAction(projectId: string, actionId: string, limit?: number): Promise<ToolCallRef[]>;
|
|
754
|
+
listRetrievalEventsByAction(projectId: string, actionId: string, limit?: number): Promise<RetrievalEventRef[]>;
|
|
755
|
+
listEvalResultsByAction(projectId: string, actionId: string, limit?: number): Promise<EvalResultRef[]>;
|
|
756
|
+
listArtifactsByAction(projectId: string, actionId: string, limit?: number): Promise<ArtifactRef[]>;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
declare function compareValue(value: number, threshold: number, comparison: AlertComparison): boolean;
|
|
760
|
+
declare class AlertsStore {
|
|
761
|
+
private readonly db;
|
|
762
|
+
constructor(db: SqlDb);
|
|
763
|
+
validateInput(input: AlertRuleInput): void;
|
|
764
|
+
listRules(projectId: string): Promise<AlertRule[]>;
|
|
765
|
+
getRule(id: string, projectId: string): Promise<AlertRule | null>;
|
|
766
|
+
createRule(projectId: string, input: AlertRuleInput): Promise<AlertRule>;
|
|
767
|
+
updateRule(id: string, projectId: string, patch: Partial<AlertRuleInput>): Promise<AlertRule | null>;
|
|
768
|
+
deleteRule(id: string, projectId: string): Promise<boolean>;
|
|
769
|
+
listEnabledRules(): Promise<AlertRule[]>;
|
|
770
|
+
getState(ruleId: string): Promise<AlertStateRow | null>;
|
|
771
|
+
transitionState(ruleId: string, projectId: string, newState: AlertState, now: string): Promise<void>;
|
|
772
|
+
recordEvaluation(ruleId: string, projectId: string, value: number, state: AlertState, notified: boolean): Promise<void>;
|
|
773
|
+
listEvaluations(params: {
|
|
774
|
+
ruleId: string;
|
|
775
|
+
projectId?: string;
|
|
776
|
+
hours: number;
|
|
777
|
+
limit?: number;
|
|
778
|
+
}): Promise<AlertEvaluationsListResponse>;
|
|
779
|
+
evaluateRule(rule: AlertRule): Promise<number>;
|
|
780
|
+
/**
|
|
781
|
+
* Stage 6 — fetch the latest narrative associated with this rule's
|
|
782
|
+
* bound analysis. Used by the evaluator when firing an analysis-bound
|
|
783
|
+
* alert so the webhook payload includes the human-readable
|
|
784
|
+
* narrative, not just a threshold crossing.
|
|
785
|
+
*/
|
|
786
|
+
getAnalysisNarrative(projectId: string, analysisId: string): Promise<{
|
|
787
|
+
narrative: string | null;
|
|
788
|
+
status: string | null;
|
|
789
|
+
} | null>;
|
|
790
|
+
private evaluateSpanRule;
|
|
791
|
+
private evaluateLogRule;
|
|
792
|
+
private evaluateUsageRule;
|
|
793
|
+
private evaluateAIRule;
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
/**
|
|
797
|
+
* Storage seam for opaque blob payloads — replay rrweb chunks and
|
|
798
|
+
* pprof profiles.
|
|
799
|
+
*
|
|
800
|
+
* Two implementations:
|
|
801
|
+
* - `R2BlobStore` — Cloudflare R2 binding (default on Workers).
|
|
802
|
+
* - `S3BlobStore` (sibling file) — AWS S3 / MinIO / any S3-compatible.
|
|
803
|
+
*
|
|
804
|
+
* Replay chunks live under `replays/<session_id>/<chunk_id>`; pprof
|
|
805
|
+
* profiles live under `profiles/<service>/<trace_id>/<span_id>`. The
|
|
806
|
+
* adapter never sees these paths — they're constructed by the callers
|
|
807
|
+
* (`replay-receiver`, `profile-routes`).
|
|
808
|
+
*/
|
|
809
|
+
interface BlobStore {
|
|
810
|
+
put(key: string, body: ArrayBuffer | Uint8Array | ReadableStream<Uint8Array>, options?: BlobPutOptions): Promise<void>;
|
|
811
|
+
get(key: string): Promise<BlobObject | null>;
|
|
812
|
+
delete(key: string): Promise<void>;
|
|
813
|
+
list(prefix: string, options?: BlobListOptions): Promise<BlobListResult>;
|
|
814
|
+
}
|
|
815
|
+
interface BlobPutOptions {
|
|
816
|
+
httpMetadata?: {
|
|
817
|
+
contentType?: string;
|
|
818
|
+
contentEncoding?: string;
|
|
819
|
+
};
|
|
820
|
+
customMetadata?: Record<string, string>;
|
|
821
|
+
}
|
|
822
|
+
interface BlobListOptions {
|
|
823
|
+
limit?: number;
|
|
824
|
+
cursor?: string;
|
|
825
|
+
}
|
|
826
|
+
interface BlobObject {
|
|
827
|
+
body: ReadableStream<Uint8Array>;
|
|
828
|
+
bytes(): Promise<Uint8Array>;
|
|
829
|
+
/**
|
|
830
|
+
* Object size in bytes when the store knows it cheaply (S3 `ContentLength`,
|
|
831
|
+
* R2 `size`). Undefined when it can't be determined without reading the body.
|
|
832
|
+
*/
|
|
833
|
+
size?: number;
|
|
834
|
+
httpMetadata?: {
|
|
835
|
+
contentType?: string;
|
|
836
|
+
contentEncoding?: string;
|
|
837
|
+
};
|
|
838
|
+
customMetadata?: Record<string, string>;
|
|
839
|
+
}
|
|
840
|
+
interface BlobListResult {
|
|
841
|
+
objects: Array<{
|
|
842
|
+
key: string;
|
|
843
|
+
size: number;
|
|
844
|
+
uploaded: Date;
|
|
845
|
+
}>;
|
|
846
|
+
cursor?: string;
|
|
847
|
+
truncated: boolean;
|
|
848
|
+
}
|
|
849
|
+
/**
|
|
850
|
+
* R2 adapter. R2's binding shape is already very close to this
|
|
851
|
+
* interface; the adapter normalizes the differences (cursor type,
|
|
852
|
+
* list pagination shape).
|
|
853
|
+
*/
|
|
854
|
+
declare class R2BlobStore implements BlobStore {
|
|
855
|
+
private readonly bucket;
|
|
856
|
+
constructor(bucket: R2Bucket);
|
|
857
|
+
put(key: string, body: ArrayBuffer | Uint8Array | ReadableStream<Uint8Array>, options?: BlobPutOptions): Promise<void>;
|
|
858
|
+
get(key: string): Promise<BlobObject | null>;
|
|
859
|
+
delete(key: string): Promise<void>;
|
|
860
|
+
list(prefix: string, options?: BlobListOptions): Promise<BlobListResult>;
|
|
861
|
+
}
|
|
862
|
+
declare class BlobStoreToR2Adapter implements R2Bucket {
|
|
863
|
+
private readonly store;
|
|
864
|
+
constructor(store: BlobStore);
|
|
865
|
+
put(key: string, value: ReadableStream | ArrayBuffer | ArrayBufferView | string | Blob | null, options?: R2PutOptions): Promise<R2Object>;
|
|
866
|
+
get(key: string, _options?: R2GetOptions): Promise<R2ObjectBody | null>;
|
|
867
|
+
delete(keys: string | string[]): Promise<void>;
|
|
868
|
+
list(options?: R2ListOptions): Promise<R2Objects>;
|
|
869
|
+
head(key: string): Promise<R2Object | null>;
|
|
870
|
+
createMultipartUpload(_key: string, _options?: R2MultipartOptions): Promise<R2MultipartUpload>;
|
|
871
|
+
resumeMultipartUpload(_key: string, _uploadId: string): R2MultipartUpload;
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
/**
|
|
875
|
+
* S3-compatible adapter for `BlobStore`. Works against AWS S3, MinIO,
|
|
876
|
+
* Cloudflare R2's S3 API, Backblaze B2, etc.
|
|
877
|
+
*
|
|
878
|
+
* Uses `@aws-sdk/client-s3` v3. The adapter is intentionally thin —
|
|
879
|
+
* just enough to satisfy `BlobStore` for replay + pprof payloads. We
|
|
880
|
+
* deliberately do NOT expose pre-signed URLs, ACLs, or storage-class
|
|
881
|
+
* tuning — those belong in a richer storage adapter for users that
|
|
882
|
+
* outgrow the default.
|
|
883
|
+
*/
|
|
884
|
+
|
|
885
|
+
type S3Body = Uint8Array | ArrayBuffer | ReadableStream<Uint8Array>;
|
|
886
|
+
type S3CommandBody = Exclude<S3Body, ArrayBuffer>;
|
|
887
|
+
interface S3ClientShape {
|
|
888
|
+
send(command: unknown): Promise<unknown>;
|
|
889
|
+
}
|
|
890
|
+
interface S3SdkConstructors {
|
|
891
|
+
PutObjectCommand: new (input: {
|
|
892
|
+
Bucket: string;
|
|
893
|
+
Key: string;
|
|
894
|
+
Body?: S3CommandBody;
|
|
895
|
+
ContentType?: string;
|
|
896
|
+
ContentEncoding?: string;
|
|
897
|
+
Metadata?: Record<string, string>;
|
|
898
|
+
}) => unknown;
|
|
899
|
+
GetObjectCommand: new (input: {
|
|
900
|
+
Bucket: string;
|
|
901
|
+
Key: string;
|
|
902
|
+
}) => unknown;
|
|
903
|
+
DeleteObjectCommand: new (input: {
|
|
904
|
+
Bucket: string;
|
|
905
|
+
Key: string;
|
|
906
|
+
}) => unknown;
|
|
907
|
+
ListObjectsV2Command: new (input: {
|
|
908
|
+
Bucket: string;
|
|
909
|
+
Prefix: string;
|
|
910
|
+
MaxKeys?: number;
|
|
911
|
+
ContinuationToken?: string;
|
|
912
|
+
}) => unknown;
|
|
913
|
+
}
|
|
914
|
+
interface S3BlobStoreOptions {
|
|
915
|
+
client: S3ClientShape;
|
|
916
|
+
commands: S3SdkConstructors;
|
|
917
|
+
bucket: string;
|
|
918
|
+
}
|
|
919
|
+
declare class S3BlobStore implements BlobStore {
|
|
920
|
+
private readonly opts;
|
|
921
|
+
constructor(opts: S3BlobStoreOptions);
|
|
922
|
+
put(key: string, body: S3Body, options?: BlobPutOptions): Promise<void>;
|
|
923
|
+
get(key: string): Promise<BlobObject | null>;
|
|
924
|
+
delete(key: string): Promise<void>;
|
|
925
|
+
list(prefix: string, options?: BlobListOptions): Promise<BlobListResult>;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
type EvalCaseSourceType = "agent_run" | "action" | "ai_call" | "tool_call" | "trace";
|
|
929
|
+
interface EvalCaseSourceLinks {
|
|
930
|
+
sourceAgentRunId?: string | null;
|
|
931
|
+
sourceActionId?: string | null;
|
|
932
|
+
sourceAiCallId?: string | null;
|
|
933
|
+
sourceToolCallId?: string | null;
|
|
934
|
+
sourceTraceId?: string | null;
|
|
935
|
+
sourceSpanId?: string | null;
|
|
936
|
+
}
|
|
937
|
+
interface EvalCaseInput {
|
|
938
|
+
sourceEntityType: EvalCaseSourceType;
|
|
939
|
+
sourceEntityId: string;
|
|
940
|
+
name: string;
|
|
941
|
+
expectedOutcome?: string | null;
|
|
942
|
+
rubric?: JsonValue | null;
|
|
943
|
+
redactedPrompt?: JsonValue | null;
|
|
944
|
+
referencePayload?: JsonValue | null;
|
|
945
|
+
metadata?: Record<string, JsonValue>;
|
|
946
|
+
source?: EvalCaseSourceLinks;
|
|
947
|
+
}
|
|
948
|
+
interface EvalCase extends Required<EvalCaseSourceLinks> {
|
|
949
|
+
id: string;
|
|
950
|
+
projectId: string;
|
|
951
|
+
sourceEntityType: EvalCaseSourceType;
|
|
952
|
+
sourceEntityId: string;
|
|
953
|
+
name: string;
|
|
954
|
+
expectedOutcome: string | null;
|
|
955
|
+
rubric: JsonValue | null;
|
|
956
|
+
redactedPrompt: JsonValue | null;
|
|
957
|
+
referencePayload: JsonValue | null;
|
|
958
|
+
metadata: Record<string, JsonValue>;
|
|
959
|
+
createdAt: string;
|
|
960
|
+
updatedAt: string;
|
|
961
|
+
evidenceReferences?: EvidenceReference[];
|
|
962
|
+
evidenceContract?: EvidenceReferenceContract;
|
|
963
|
+
}
|
|
964
|
+
interface EvalCaseListOptions {
|
|
965
|
+
projectId: string;
|
|
966
|
+
sourceEntityType?: EvalCaseSourceType;
|
|
967
|
+
sourceEntityId?: string;
|
|
968
|
+
limit?: number;
|
|
969
|
+
}
|
|
970
|
+
type EvalRunStatus = "pending" | "running" | "completed" | "failed" | "canceled";
|
|
971
|
+
interface EvalRunCandidate {
|
|
972
|
+
agentId: string | null;
|
|
973
|
+
agentVersion: string | null;
|
|
974
|
+
promptId: string | null;
|
|
975
|
+
promptVersion: string | null;
|
|
976
|
+
modelProvider: string | null;
|
|
977
|
+
model: string | null;
|
|
978
|
+
modelVersion: string | null;
|
|
979
|
+
}
|
|
980
|
+
interface EvalRunSourceCase {
|
|
981
|
+
id: string;
|
|
982
|
+
name: string;
|
|
983
|
+
sourceEntityType: string;
|
|
984
|
+
sourceEntityId: string;
|
|
985
|
+
sourceAgentRunId: string | null;
|
|
986
|
+
sourceActionId: string | null;
|
|
987
|
+
sourceAiCallId: string | null;
|
|
988
|
+
sourceToolCallId: string | null;
|
|
989
|
+
sourceTraceId: string | null;
|
|
990
|
+
sourceSpanId: string | null;
|
|
991
|
+
evidenceReferences?: EvidenceReference[];
|
|
992
|
+
evidenceContract?: EvidenceReferenceContract;
|
|
993
|
+
}
|
|
994
|
+
interface EvalRun {
|
|
995
|
+
id: string;
|
|
996
|
+
projectId: string;
|
|
997
|
+
evalCaseId: string | null;
|
|
998
|
+
status: EvalRunStatus;
|
|
999
|
+
candidate: EvalRunCandidate;
|
|
1000
|
+
startedAt: string | null;
|
|
1001
|
+
endedAt: string | null;
|
|
1002
|
+
totalCount: number;
|
|
1003
|
+
passCount: number;
|
|
1004
|
+
failCount: number;
|
|
1005
|
+
averageScore: number | null;
|
|
1006
|
+
metadata: Record<string, JsonValue>;
|
|
1007
|
+
createdAt: string;
|
|
1008
|
+
sourceEvalCase?: EvalRunSourceCase | null;
|
|
1009
|
+
evidenceReferences?: EvidenceReference[];
|
|
1010
|
+
evidenceContract?: EvidenceReferenceContract;
|
|
1011
|
+
}
|
|
1012
|
+
interface EvalRunInput {
|
|
1013
|
+
id?: string;
|
|
1014
|
+
evalCaseId?: string | null;
|
|
1015
|
+
status?: EvalRunStatus;
|
|
1016
|
+
candidate?: Partial<EvalRunCandidate>;
|
|
1017
|
+
startedAt?: string | null;
|
|
1018
|
+
endedAt?: string | null;
|
|
1019
|
+
totalCount?: number;
|
|
1020
|
+
passCount?: number;
|
|
1021
|
+
failCount?: number;
|
|
1022
|
+
averageScore?: number | null;
|
|
1023
|
+
metadata?: Record<string, JsonValue>;
|
|
1024
|
+
}
|
|
1025
|
+
interface EvalRunsListOptions {
|
|
1026
|
+
projectId: string;
|
|
1027
|
+
evalCaseId?: string;
|
|
1028
|
+
status?: EvalRunStatus;
|
|
1029
|
+
limit?: number;
|
|
1030
|
+
}
|
|
1031
|
+
declare class EvalCaseSourceNotFoundError extends Error {
|
|
1032
|
+
readonly projectId: string;
|
|
1033
|
+
readonly sourceEntityType: EvalCaseSourceType;
|
|
1034
|
+
readonly sourceEntityId: string;
|
|
1035
|
+
constructor(projectId: string, sourceEntityType: EvalCaseSourceType, sourceEntityId: string);
|
|
1036
|
+
}
|
|
1037
|
+
declare const isEvalCaseSourceType: (value: unknown) => value is EvalCaseSourceType;
|
|
1038
|
+
declare const isEvalRunStatus: (value: unknown) => value is EvalRunStatus;
|
|
1039
|
+
declare class EvalCasesStore {
|
|
1040
|
+
private readonly db;
|
|
1041
|
+
constructor(db: SqlDb);
|
|
1042
|
+
createCase(projectId: string, input: EvalCaseInput): Promise<EvalCase>;
|
|
1043
|
+
getCase(projectId: string, id: string): Promise<EvalCase | null>;
|
|
1044
|
+
listCases(options: EvalCaseListOptions): Promise<EvalCase[]>;
|
|
1045
|
+
createRun(projectId: string, input: EvalRunInput): Promise<EvalRun>;
|
|
1046
|
+
getRun(projectId: string, id: string): Promise<EvalRun | null>;
|
|
1047
|
+
listRuns(options: EvalRunsListOptions): Promise<EvalRun[]>;
|
|
1048
|
+
refreshRunSummary(projectId: string, id: string): Promise<void>;
|
|
1049
|
+
private evalRunSelectSql;
|
|
1050
|
+
private hydrateSource;
|
|
1051
|
+
private getActionSource;
|
|
1052
|
+
private getToolCallSource;
|
|
1053
|
+
private findPayload;
|
|
1054
|
+
private buildMetadata;
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
type MetricType = "gauge" | "sum" | "histogram" | "exp_histogram" | "summary";
|
|
1058
|
+
/**
|
|
1059
|
+
* A metric data point normalized for storage. Series-identifying fields
|
|
1060
|
+
* (name, resource/scope context, attributes) are repeated on each point so
|
|
1061
|
+
* the store can do series upsert in a single pass.
|
|
1062
|
+
*/
|
|
1063
|
+
interface DecodedMetricPoint {
|
|
1064
|
+
name: string;
|
|
1065
|
+
description: string | null;
|
|
1066
|
+
unit: string | null;
|
|
1067
|
+
type: MetricType;
|
|
1068
|
+
isMonotonic: boolean | null;
|
|
1069
|
+
temporality: number | null;
|
|
1070
|
+
scopeName: string | null;
|
|
1071
|
+
scopeVersion: string | null;
|
|
1072
|
+
serviceName: string | null;
|
|
1073
|
+
resourceAttrsJson: string | null;
|
|
1074
|
+
attributesJson: string | null;
|
|
1075
|
+
identity: string;
|
|
1076
|
+
tsNs: string;
|
|
1077
|
+
startTsNs: string | null;
|
|
1078
|
+
value: number | null;
|
|
1079
|
+
count: number | null;
|
|
1080
|
+
sum: number | null;
|
|
1081
|
+
min: number | null;
|
|
1082
|
+
max: number | null;
|
|
1083
|
+
boundsJson: string | null;
|
|
1084
|
+
bucketCountsJson: string | null;
|
|
1085
|
+
/**
|
|
1086
|
+
* Type-specific fields that don't fit the column schema:
|
|
1087
|
+
* - exp_histogram: { scale, zeroCount, zeroThreshold, positive: {offset, bucketCounts}, negative: {offset, bucketCounts} }
|
|
1088
|
+
* - summary: { quantileValues: [{quantile, value}, ...] }
|
|
1089
|
+
*/
|
|
1090
|
+
extraJson: string | null;
|
|
1091
|
+
exemplarsJson: string | null;
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
/**
|
|
1095
|
+
* Metrics storage.
|
|
1096
|
+
*
|
|
1097
|
+
* Each ingest collapses points to their series identity, upserts the series
|
|
1098
|
+
* row, then batch-inserts points. Series upsert is per-unique-identity per
|
|
1099
|
+
* request — at small batch sizes this is cheap; a followup can switch to a
|
|
1100
|
+
* single SELECT-many + batched INSERT-missing when volume demands it.
|
|
1101
|
+
*/
|
|
1102
|
+
|
|
1103
|
+
interface MetricExemplarPoint {
|
|
1104
|
+
id: string;
|
|
1105
|
+
pointId: string;
|
|
1106
|
+
seriesId: string;
|
|
1107
|
+
metricName: string;
|
|
1108
|
+
serviceName: string | null;
|
|
1109
|
+
traceId: string | null;
|
|
1110
|
+
spanId: string | null;
|
|
1111
|
+
tsNs: string;
|
|
1112
|
+
value: number;
|
|
1113
|
+
receivedAt: string;
|
|
1114
|
+
}
|
|
1115
|
+
declare class MetricsStore {
|
|
1116
|
+
private readonly db;
|
|
1117
|
+
constructor(db: SqlDb);
|
|
1118
|
+
purgeExpired(): Promise<number>;
|
|
1119
|
+
ingestBatch(opts: {
|
|
1120
|
+
projectId: string;
|
|
1121
|
+
points: DecodedMetricPoint[];
|
|
1122
|
+
receivedAt: string;
|
|
1123
|
+
expiresAt: string;
|
|
1124
|
+
}): Promise<void>;
|
|
1125
|
+
exemplarsForTrace(projectId: string, traceId: string, limit?: number): Promise<MetricExemplarPoint[]>;
|
|
1126
|
+
recentExemplars(opts: {
|
|
1127
|
+
projectId: string;
|
|
1128
|
+
serviceName?: string | null;
|
|
1129
|
+
metricPrefix?: string | null;
|
|
1130
|
+
limit?: number;
|
|
1131
|
+
}): Promise<MetricExemplarPoint[]>;
|
|
1132
|
+
/**
|
|
1133
|
+
* Ensures a `metric_series` row exists for every unique identity in the
|
|
1134
|
+
* batch. Returns a map of identity → series row for point linking.
|
|
1135
|
+
*/
|
|
1136
|
+
private resolveSeries;
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
declare class ProjectsStore {
|
|
1140
|
+
private readonly db;
|
|
1141
|
+
constructor(db: SqlDb);
|
|
1142
|
+
listProjects(): Promise<Project[]>;
|
|
1143
|
+
getProject(id: string): Promise<Project | null>;
|
|
1144
|
+
createProject(input: {
|
|
1145
|
+
name: string;
|
|
1146
|
+
slug: string;
|
|
1147
|
+
}): Promise<Project>;
|
|
1148
|
+
updateProject(id: string, patch: {
|
|
1149
|
+
name?: string;
|
|
1150
|
+
payloadCaptureEnabled?: boolean;
|
|
1151
|
+
}): Promise<Project | null>;
|
|
1152
|
+
ensureDefaultProject(): Promise<void>;
|
|
1153
|
+
listKeys(projectId: string): Promise<IngestKey[]>;
|
|
1154
|
+
createKey(projectId: string, name: string): Promise<IngestKeyWithPlaintext>;
|
|
1155
|
+
revokeKey(keyId: string): Promise<boolean>;
|
|
1156
|
+
findByKeyHash(keyHash: string): Promise<{
|
|
1157
|
+
projectId: string;
|
|
1158
|
+
keyId: string;
|
|
1159
|
+
} | null>;
|
|
1160
|
+
/**
|
|
1161
|
+
* Idempotently register the legacy env INGEST_KEY as a bootstrap key on the
|
|
1162
|
+
* default project, so existing deployments keep working without manual migration.
|
|
1163
|
+
*/
|
|
1164
|
+
bootstrapEnvKey(plaintext: string): Promise<void>;
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
interface PostgresAdapterOptions {
|
|
1168
|
+
/**
|
|
1169
|
+
* Statement-level timeout in milliseconds. Defaults to 30s. Issued
|
|
1170
|
+
* via `SET statement_timeout` at the start of each query (session-level;
|
|
1171
|
+
* `SET LOCAL` outside a transaction would be a no-op).
|
|
1172
|
+
*/
|
|
1173
|
+
statementTimeoutMs?: number;
|
|
1174
|
+
}
|
|
1175
|
+
declare class PostgresAdapter implements SqlDb {
|
|
1176
|
+
private readonly pool;
|
|
1177
|
+
readonly dialect: SqlDialect;
|
|
1178
|
+
private readonly statementTimeoutMs;
|
|
1179
|
+
constructor(pool: Pool, options?: PostgresAdapterOptions);
|
|
1180
|
+
prepare(sql: string): SqlStatement;
|
|
1181
|
+
batch(statements: SqlStatement[]): Promise<Array<{
|
|
1182
|
+
meta: {
|
|
1183
|
+
changes: number;
|
|
1184
|
+
};
|
|
1185
|
+
}>>;
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
/** All built-in plugins in recommended registration order */
|
|
1189
|
+
declare const allPlugins: CollectorPlugin[];
|
|
1190
|
+
declare const createDefaultCollectorApp: (config?: Partial<CollectorConfig>) => hono.Hono<{
|
|
1191
|
+
Bindings: CollectorEnv;
|
|
1192
|
+
}, hono_types.BlankSchema, "/">;
|
|
1193
|
+
declare const _default: hono.Hono<{
|
|
1194
|
+
Bindings: CollectorEnv;
|
|
1195
|
+
}, hono_types.BlankSchema, "/">;
|
|
1196
|
+
|
|
1197
|
+
export { type ActionRecord, ActionStore, type AgentRunRecord, AlertsStore, type ArtifactRecord, type BlobListOptions, type BlobListResult, type BlobObject, type BlobPutOptions, type BlobStore, BlobStoreToR2Adapter, type CollectorAuthConfig, type CollectorConfig, CollectorEnv, type CollectorPlugin, CollectorRouteContext, CollectorRuntime, D1Adapter, type EvalCase, type EvalCaseInput, type EvalCaseListOptions, type EvalCaseSourceLinks, EvalCaseSourceNotFoundError, type EvalCaseSourceType, EvalCasesStore, type EvalResultRecord, type EvalRun, type EvalRunCandidate, type EvalRunInput, type EvalRunSourceCase, type EvalRunStatus, type EvalRunsListOptions, Logger, MetricsStore, PostgresAdapter, type PostgresAdapterOptions, ProjectsStore, R2BlobStore, type RetrievalEventRecord, S3BlobStore, type S3BlobStoreOptions, type SpanProcessorPlugin, type SqlDb, type SqlDbFactory, type SqlStatement, type TailEvent, TailHub, type TailKind, type ToolCallRecord, type UsageEventProcessorPlugin, actionRoutesPlugin, aiReceiverPlugin, aiSpanPayloadsProcessorPlugin, alertsRoutesPlugin, allPlugins, analysesRoutesPlugin, askRoutesPlugin, botFilterPlugin, compareValue, connectedRoutesPlugin, createAlertEvaluatorHandler, createAnalysesRunHandler, createDashboardAuth, createDefaultCollectorApp, createRetentionCleanupHandler, createTelemetryCollectorApp, dashboardRoutesPlugin, _default as default, defaultSpanEnrichmentPlugin, evalCasesRoutesPlugin, evaluateAllRules, evidenceRetrievalRoutesPlugin, genAiNormalizerPlugin, identityReceiverPlugin, isEvalCaseSourceType, isEvalRunStatus, issueEnrichmentPlugin, issueInsightsPlugin, logsReceiverPlugin, metricsReceiverPlugin, onboardingRoutesPlugin, otlpReceiverPlugin, platformRoutesPlugin, profileRoutesPlugin, projectsRoutesPlugin, queryRoutesPlugin, redactionProcessorPlugin, replayQueryRoutesPlugin, replayReceiverPlugin, tailRoutesPlugin, timelineRoutesPlugin, uaEnrichmentPlugin, usageNormalizationPlugin, usagePrivacyPlugin, usageQueryRoutesPlugin, usageReceiverPlugin, usersQueryRoutesPlugin, utmEnrichmentPlugin };
|