@obsunified/collector 2.1.1 → 2.2.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.
Files changed (37) hide show
  1. package/dist/{chunk-XKQTVIRE.js → chunk-ZSF5XP3B.js} +8 -2
  2. package/dist/chunk-ZSF5XP3B.js.map +1 -0
  3. package/dist/index.d.ts +359 -2
  4. package/dist/index.js +5000 -334
  5. package/dist/index.js.map +1 -1
  6. package/dist/{openai-FJYOQ7WO.js → openai-GSJZGFGL.js} +2 -2
  7. package/package.json +2 -2
  8. package/src/__tests__/autosre-closed-loop.test.ts +2222 -0
  9. package/src/index.ts +43 -0
  10. package/src/lib/analyses-runner.ts +46 -0
  11. package/src/lib/autosre-change-correlation.ts +807 -0
  12. package/src/lib/autosre-findings.ts +763 -0
  13. package/src/lib/autosre-ontology-cache.test.ts +78 -0
  14. package/src/lib/autosre-ontology.ts +938 -0
  15. package/src/lib/autosre-remediation-gate.ts +2127 -0
  16. package/src/lib/eval-cases-store.ts +63 -1
  17. package/src/lib/evidence-references.ts +6 -0
  18. package/src/lib/housekeeping.test.ts +150 -0
  19. package/src/lib/housekeeping.ts +109 -1
  20. package/src/lib/store/ingest.ts +46 -6
  21. package/src/migrations/050_autosre_causal_ontology.sql +216 -0
  22. package/src/migrations/051_incident_active_dedup_unique.sql +31 -0
  23. package/src/migrations/alert-state-notified.test.ts +3 -3
  24. package/src/migrations/parity.test.ts +4 -0
  25. package/src/migrations/project-scoped-keys.test.ts +1 -1
  26. package/src/migrations-postgres/050_autosre_causal_ontology.sql +216 -0
  27. package/src/migrations-postgres/051_incident_active_dedup_unique.sql +31 -0
  28. package/src/plugins/alerts-evaluator.ts +29 -1
  29. package/src/plugins/autosre-routes.ts +1134 -0
  30. package/src/plugins/connected-routes/manifest.ts +10 -1
  31. package/src/plugins/connected-routes.ts +241 -0
  32. package/src/plugins/default-span-enrichment.ts +13 -1
  33. package/src/plugins/eval-cases-routes.ts +57 -2
  34. package/src/plugins/evidence-retrieval-routes.test.ts +32 -0
  35. package/src/plugins/evidence-retrieval-routes.ts +643 -5
  36. package/dist/chunk-XKQTVIRE.js.map +0 -1
  37. /package/dist/{openai-FJYOQ7WO.js.map → openai-GSJZGFGL.js.map} +0 -0
@@ -0,0 +1,78 @@
1
+ import type { StoredSpan } from "@obsunified/types";
2
+ import { afterEach, describe, expect, it, vi } from "vitest";
3
+ import {
4
+ clearOntologyUpsertCache,
5
+ extractSpanLineageAndTopology,
6
+ upsertOntologyFromSpans,
7
+ } from "./autosre-ontology";
8
+ import type { SqlDb } from "./sql-db";
9
+
10
+ const dbSpan = (i: number, environment = "prod"): StoredSpan =>
11
+ ({
12
+ projectId: "p",
13
+ traceId: `t${i}`,
14
+ spanId: `s${i}`,
15
+ environment,
16
+ startTime: "2026-10-15T00:00:00.000Z",
17
+ receivedAt: "2026-10-15T00:00:00.000Z",
18
+ attributesJson: JSON.stringify({
19
+ "db.system": "postgresql",
20
+ "db.name": `db${i}`,
21
+ "server.address": "pg.internal",
22
+ "server.port": 5432,
23
+ }),
24
+ resourceAttributesJson: "{}",
25
+ }) as unknown as StoredSpan;
26
+
27
+ const fakeDb = (batch: SqlDb["batch"]): SqlDb => {
28
+ const stmt = { bind: () => stmt };
29
+ return { prepare: () => stmt, batch } as unknown as SqlDb;
30
+ };
31
+
32
+ describe("ontology env normalization", () => {
33
+ afterEach(() => clearOntologyUpsertCache());
34
+
35
+ it("maps production-tagged spans to the prod environment", () => {
36
+ const span = {
37
+ ...dbSpan(1, ""),
38
+ environment: undefined,
39
+ resourceAttributesJson: JSON.stringify({
40
+ "deployment.environment.name": "Production",
41
+ }),
42
+ } as unknown as StoredSpan;
43
+ expect(extractSpanLineageAndTopology(span).environment).toBe("prod");
44
+ });
45
+ });
46
+
47
+ describe("NODE_UPSERT_CACHE", () => {
48
+ afterEach(() => clearOntologyUpsertCache());
49
+
50
+ it("does not remember keys when the batch fails", async () => {
51
+ const failing = vi.fn(async () => {
52
+ throw new Error("boom");
53
+ });
54
+ await expect(
55
+ upsertOntologyFromSpans(fakeDb(failing as never), [dbSpan(1)]),
56
+ ).rejects.toThrow("boom");
57
+ const ok = vi.fn(async () => []);
58
+ await upsertOntologyFromSpans(fakeDb(ok as never), [dbSpan(1)]);
59
+ expect(ok).toHaveBeenCalledTimes(1);
60
+ // Now cached: a third call writes nothing.
61
+ const again = vi.fn(async () => []);
62
+ await upsertOntologyFromSpans(fakeDb(again as never), [dbSpan(1)]);
63
+ expect(again).not.toHaveBeenCalled();
64
+ });
65
+
66
+ it("caps the cache and evicts the oldest entries", async () => {
67
+ const spans = Array.from({ length: 5_002 }, (_, i) => dbSpan(i));
68
+ const batch = vi.fn(async () => []);
69
+ await upsertOntologyFromSpans(fakeDb(batch as never), spans);
70
+ // Oldest keys were evicted so they are written again; newest stay cached.
71
+ const second = vi.fn(async () => []);
72
+ await upsertOntologyFromSpans(fakeDb(second as never), [dbSpan(0)]);
73
+ expect(second).toHaveBeenCalledTimes(1);
74
+ const third = vi.fn(async () => []);
75
+ await upsertOntologyFromSpans(fakeDb(third as never), [dbSpan(5_001)]);
76
+ expect(third).not.toHaveBeenCalled();
77
+ });
78
+ });