@contractspec/lib.observability 3.7.16 → 3.7.18
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/CHANGELOG.md +25 -0
- package/dist/anomaly/alert-manager.js +1 -23
- package/dist/anomaly/anomaly-detector.js +1 -101
- package/dist/anomaly/baseline-calculator.js +1 -39
- package/dist/anomaly/root-cause-analyzer.js +1 -31
- package/dist/index.js +5 -1128
- package/dist/intent/aggregator.js +1 -109
- package/dist/intent/detector.js +1 -132
- package/dist/logging/index.js +1 -41
- package/dist/metrics/index.js +1 -30
- package/dist/node/anomaly/alert-manager.js +1 -23
- package/dist/node/anomaly/anomaly-detector.js +1 -101
- package/dist/node/anomaly/baseline-calculator.js +1 -39
- package/dist/node/anomaly/root-cause-analyzer.js +1 -31
- package/dist/node/index.js +5 -1128
- package/dist/node/intent/aggregator.js +1 -109
- package/dist/node/intent/detector.js +1 -132
- package/dist/node/logging/index.js +1 -41
- package/dist/node/metrics/index.js +1 -30
- package/dist/node/pipeline/evolution-pipeline.js +1 -299
- package/dist/node/pipeline/lifecycle-pipeline.js +1 -85
- package/dist/node/telemetry/model-selection-telemetry.js +1 -30
- package/dist/node/telemetry/posthog-baseline-reader.js +5 -308
- package/dist/node/telemetry/posthog-telemetry.js +1 -60
- package/dist/node/tracing/core.js +1 -52
- package/dist/node/tracing/index.js +1 -75
- package/dist/node/tracing/middleware.js +1 -171
- package/dist/node/tracing/model-selection.span.js +1 -72
- package/dist/pipeline/evolution-pipeline.js +1 -299
- package/dist/pipeline/lifecycle-pipeline.js +1 -85
- package/dist/telemetry/model-selection-telemetry.js +1 -30
- package/dist/telemetry/posthog-baseline-reader.js +5 -308
- package/dist/telemetry/posthog-telemetry.js +1 -60
- package/dist/tracing/core.js +1 -52
- package/dist/tracing/index.js +1 -75
- package/dist/tracing/middleware.js +1 -171
- package/dist/tracing/model-selection.span.js +1 -72
- package/package.json +8 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# @contractspec/lib.observability
|
|
2
2
|
|
|
3
|
+
## 3.7.18
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- chore: auto-bump internal dependents
|
|
8
|
+
- Updated dependencies because of chore: auto-bump internal dependents
|
|
9
|
+
- Updated dependencies because of Introduce the Builder v3 control plane as a governed authoring layer over external execution providers.
|
|
10
|
+
- Updated dependencies because of Implement ContractSpec Connect as a first-class spec, runtime, and CLI workflow.
|
|
11
|
+
- @contractspec/lib.contracts-integrations@3.8.10
|
|
12
|
+
- @contractspec/lib.lifecycle@3.7.18
|
|
13
|
+
- @contractspec/lib.contracts-spec@5.2.0
|
|
14
|
+
|
|
15
|
+
## 3.7.17
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- Fix workflow runtime imports for sandboxed workflow execution and keep workflow authoring on safe subpaths.
|
|
20
|
+
- Migration: Keep Node-only workflow runner code out of "use workflow" entrypoints.
|
|
21
|
+
- Deprecations: Importing the broad `@contractspec/lib.contracts-spec/workflow` barrel from sandboxed workflow entrypoints is discouraged.
|
|
22
|
+
- Updated dependencies because of Fix workflow runtime imports for sandboxed workflow execution and keep workflow authoring on safe subpaths.
|
|
23
|
+
- Updated dependencies because of Add versioning-backed release capsules, generated patch notes, and guided upgrade flows.
|
|
24
|
+
- @contractspec/lib.contracts-integrations@3.8.9
|
|
25
|
+
- @contractspec/lib.contracts-spec@5.1.0
|
|
26
|
+
- @contractspec/lib.lifecycle@3.7.17
|
|
27
|
+
|
|
3
28
|
## 3.7.16
|
|
4
29
|
|
|
5
30
|
### Patch Changes
|
|
@@ -1,24 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
|
|
3
|
-
class AlertManager {
|
|
4
|
-
options;
|
|
5
|
-
cooldownMs;
|
|
6
|
-
lastAlert = new Map;
|
|
7
|
-
constructor(options) {
|
|
8
|
-
this.options = options;
|
|
9
|
-
this.cooldownMs = options.cooldownMs ?? 60000;
|
|
10
|
-
}
|
|
11
|
-
async notify(signal, analysis) {
|
|
12
|
-
const key = `${signal.type}:${analysis.culprit?.id ?? "none"}`;
|
|
13
|
-
const now = Date.now();
|
|
14
|
-
const last = this.lastAlert.get(key) ?? 0;
|
|
15
|
-
if (now - last < this.cooldownMs) {
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
await this.options.transport({ signal, analysis });
|
|
19
|
-
this.lastAlert.set(key, now);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
export {
|
|
23
|
-
AlertManager
|
|
24
|
-
};
|
|
2
|
+
class r{options;cooldownMs;lastAlert=new Map;constructor(o){this.options=o;this.cooldownMs=o.cooldownMs??60000}async notify(o,t){let a=`${o.type}:${t.culprit?.id??"none"}`,n=Date.now(),e=this.lastAlert.get(a)??0;if(n-e<this.cooldownMs)return;await this.options.transport({signal:o,analysis:t}),this.lastAlert.set(a,n)}}export{r as AlertManager};
|
|
@@ -1,102 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
|
|
3
|
-
class BaselineCalculator {
|
|
4
|
-
alpha;
|
|
5
|
-
snapshot = {
|
|
6
|
-
latencyP99: 0,
|
|
7
|
-
latencyP95: 0,
|
|
8
|
-
errorRate: 0,
|
|
9
|
-
throughput: 0,
|
|
10
|
-
sampleCount: 0
|
|
11
|
-
};
|
|
12
|
-
constructor(alpha = 0.2) {
|
|
13
|
-
this.alpha = alpha;
|
|
14
|
-
}
|
|
15
|
-
update(point) {
|
|
16
|
-
const { sampleCount } = this.snapshot;
|
|
17
|
-
const nextCount = sampleCount + 1;
|
|
18
|
-
const weight = sampleCount === 0 ? 1 : this.alpha;
|
|
19
|
-
this.snapshot = {
|
|
20
|
-
latencyP99: this.mix(this.snapshot.latencyP99, point.latencyP99, weight),
|
|
21
|
-
latencyP95: this.mix(this.snapshot.latencyP95, point.latencyP95, weight),
|
|
22
|
-
errorRate: this.mix(this.snapshot.errorRate, point.errorRate, weight),
|
|
23
|
-
throughput: this.mix(this.snapshot.throughput, point.throughput, weight),
|
|
24
|
-
sampleCount: nextCount
|
|
25
|
-
};
|
|
26
|
-
return this.snapshot;
|
|
27
|
-
}
|
|
28
|
-
getSnapshot() {
|
|
29
|
-
return this.snapshot;
|
|
30
|
-
}
|
|
31
|
-
mix(current, next, weight) {
|
|
32
|
-
if (this.snapshot.sampleCount === 0) {
|
|
33
|
-
return next;
|
|
34
|
-
}
|
|
35
|
-
return current * (1 - weight) + next * weight;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// src/anomaly/anomaly-detector.ts
|
|
40
|
-
class AnomalyDetector {
|
|
41
|
-
baseline;
|
|
42
|
-
thresholds = {
|
|
43
|
-
errorRateDelta: 0.5,
|
|
44
|
-
latencyDelta: 0.35,
|
|
45
|
-
throughputDrop: 0.4,
|
|
46
|
-
minSamples: 10
|
|
47
|
-
};
|
|
48
|
-
constructor(options = {}) {
|
|
49
|
-
this.baseline = new BaselineCalculator;
|
|
50
|
-
this.thresholds = { ...this.thresholds, ...options };
|
|
51
|
-
}
|
|
52
|
-
evaluate(point) {
|
|
53
|
-
const baselineSnapshot = this.baseline.update(point);
|
|
54
|
-
if (baselineSnapshot.sampleCount < this.thresholds.minSamples) {
|
|
55
|
-
return [];
|
|
56
|
-
}
|
|
57
|
-
const signals = [];
|
|
58
|
-
const errorDelta = this.relativeDelta(point.errorRate, baselineSnapshot.errorRate);
|
|
59
|
-
if (errorDelta > this.thresholds.errorRateDelta) {
|
|
60
|
-
signals.push({
|
|
61
|
-
type: "error_rate_spike",
|
|
62
|
-
delta: errorDelta,
|
|
63
|
-
point,
|
|
64
|
-
baseline: baselineSnapshot
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
const latencyDelta = this.relativeDelta(point.latencyP99, baselineSnapshot.latencyP99);
|
|
68
|
-
if (latencyDelta > this.thresholds.latencyDelta) {
|
|
69
|
-
signals.push({
|
|
70
|
-
type: "latency_regression",
|
|
71
|
-
delta: latencyDelta,
|
|
72
|
-
point,
|
|
73
|
-
baseline: baselineSnapshot
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
const throughputDelta = this.relativeDrop(point.throughput, baselineSnapshot.throughput);
|
|
77
|
-
if (throughputDelta > this.thresholds.throughputDrop) {
|
|
78
|
-
signals.push({
|
|
79
|
-
type: "throughput_drop",
|
|
80
|
-
delta: throughputDelta,
|
|
81
|
-
point,
|
|
82
|
-
baseline: baselineSnapshot
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
return signals;
|
|
86
|
-
}
|
|
87
|
-
relativeDelta(value, baseline) {
|
|
88
|
-
if (baseline === 0) {
|
|
89
|
-
return 0;
|
|
90
|
-
}
|
|
91
|
-
return (value - baseline) / baseline;
|
|
92
|
-
}
|
|
93
|
-
relativeDrop(value, baseline) {
|
|
94
|
-
if (baseline === 0) {
|
|
95
|
-
return 0;
|
|
96
|
-
}
|
|
97
|
-
return (baseline - value) / baseline;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
export {
|
|
101
|
-
AnomalyDetector
|
|
102
|
-
};
|
|
2
|
+
class s{alpha;snapshot={latencyP99:0,latencyP95:0,errorRate:0,throughput:0,sampleCount:0};constructor(e=0.2){this.alpha=e}update(e){let{sampleCount:t}=this.snapshot,r=t+1,a=t===0?1:this.alpha;return this.snapshot={latencyP99:this.mix(this.snapshot.latencyP99,e.latencyP99,a),latencyP95:this.mix(this.snapshot.latencyP95,e.latencyP95,a),errorRate:this.mix(this.snapshot.errorRate,e.errorRate,a),throughput:this.mix(this.snapshot.throughput,e.throughput,a),sampleCount:r},this.snapshot}getSnapshot(){return this.snapshot}mix(e,t,r){if(this.snapshot.sampleCount===0)return t;return e*(1-r)+t*r}}class l{baseline;thresholds={errorRateDelta:0.5,latencyDelta:0.35,throughputDrop:0.4,minSamples:10};constructor(e={}){this.baseline=new s,this.thresholds={...this.thresholds,...e}}evaluate(e){let t=this.baseline.update(e);if(t.sampleCount<this.thresholds.minSamples)return[];let r=[],a=this.relativeDelta(e.errorRate,t.errorRate);if(a>this.thresholds.errorRateDelta)r.push({type:"error_rate_spike",delta:a,point:e,baseline:t});let n=this.relativeDelta(e.latencyP99,t.latencyP99);if(n>this.thresholds.latencyDelta)r.push({type:"latency_regression",delta:n,point:e,baseline:t});let o=this.relativeDrop(e.throughput,t.throughput);if(o>this.thresholds.throughputDrop)r.push({type:"throughput_drop",delta:o,point:e,baseline:t});return r}relativeDelta(e,t){if(t===0)return 0;return(e-t)/t}relativeDrop(e,t){if(t===0)return 0;return(t-e)/t}}export{l as AnomalyDetector};
|
|
@@ -1,40 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
|
|
3
|
-
class BaselineCalculator {
|
|
4
|
-
alpha;
|
|
5
|
-
snapshot = {
|
|
6
|
-
latencyP99: 0,
|
|
7
|
-
latencyP95: 0,
|
|
8
|
-
errorRate: 0,
|
|
9
|
-
throughput: 0,
|
|
10
|
-
sampleCount: 0
|
|
11
|
-
};
|
|
12
|
-
constructor(alpha = 0.2) {
|
|
13
|
-
this.alpha = alpha;
|
|
14
|
-
}
|
|
15
|
-
update(point) {
|
|
16
|
-
const { sampleCount } = this.snapshot;
|
|
17
|
-
const nextCount = sampleCount + 1;
|
|
18
|
-
const weight = sampleCount === 0 ? 1 : this.alpha;
|
|
19
|
-
this.snapshot = {
|
|
20
|
-
latencyP99: this.mix(this.snapshot.latencyP99, point.latencyP99, weight),
|
|
21
|
-
latencyP95: this.mix(this.snapshot.latencyP95, point.latencyP95, weight),
|
|
22
|
-
errorRate: this.mix(this.snapshot.errorRate, point.errorRate, weight),
|
|
23
|
-
throughput: this.mix(this.snapshot.throughput, point.throughput, weight),
|
|
24
|
-
sampleCount: nextCount
|
|
25
|
-
};
|
|
26
|
-
return this.snapshot;
|
|
27
|
-
}
|
|
28
|
-
getSnapshot() {
|
|
29
|
-
return this.snapshot;
|
|
30
|
-
}
|
|
31
|
-
mix(current, next, weight) {
|
|
32
|
-
if (this.snapshot.sampleCount === 0) {
|
|
33
|
-
return next;
|
|
34
|
-
}
|
|
35
|
-
return current * (1 - weight) + next * weight;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
export {
|
|
39
|
-
BaselineCalculator
|
|
40
|
-
};
|
|
2
|
+
class a{alpha;snapshot={latencyP99:0,latencyP95:0,errorRate:0,throughput:0,sampleCount:0};constructor(t=0.2){this.alpha=t}update(t){let{sampleCount:e}=this.snapshot,n=e+1,r=e===0?1:this.alpha;return this.snapshot={latencyP99:this.mix(this.snapshot.latencyP99,t.latencyP99,r),latencyP95:this.mix(this.snapshot.latencyP95,t.latencyP95,r),errorRate:this.mix(this.snapshot.errorRate,t.errorRate,r),throughput:this.mix(this.snapshot.throughput,t.throughput,r),sampleCount:n},this.snapshot}getSnapshot(){return this.snapshot}mix(t,e,n){if(this.snapshot.sampleCount===0)return e;return t*(1-n)+e*n}}export{a as BaselineCalculator};
|
|
@@ -1,32 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
|
|
3
|
-
class RootCauseAnalyzer {
|
|
4
|
-
lookbackMs;
|
|
5
|
-
constructor(lookbackMs = 15 * 60 * 1000) {
|
|
6
|
-
this.lookbackMs = lookbackMs;
|
|
7
|
-
}
|
|
8
|
-
analyze(signal, deployments) {
|
|
9
|
-
const windowStart = new Date(signal.point.timestamp.getTime() - this.lookbackMs);
|
|
10
|
-
const candidates = deployments.filter((deployment) => deployment.deployedAt >= windowStart).sort((a, b) => b.deployedAt.getTime() - a.deployedAt.getTime());
|
|
11
|
-
const notes = [];
|
|
12
|
-
let culprit;
|
|
13
|
-
if (candidates.length > 0) {
|
|
14
|
-
culprit = candidates[0];
|
|
15
|
-
if (culprit) {
|
|
16
|
-
notes.push(`Closest deployment ${culprit.id} (${culprit.operation}) at ${culprit.deployedAt.toISOString()}`);
|
|
17
|
-
}
|
|
18
|
-
} else {
|
|
19
|
-
notes.push("No deployments found within lookback window.");
|
|
20
|
-
}
|
|
21
|
-
if (signal.type === "latency_regression") {
|
|
22
|
-
notes.push("Verify recent schema changes and external dependency latency.");
|
|
23
|
-
}
|
|
24
|
-
if (signal.type === "error_rate_spike") {
|
|
25
|
-
notes.push("Check SLO monitor for correlated incidents.");
|
|
26
|
-
}
|
|
27
|
-
return { signal, culprit, notes };
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
export {
|
|
31
|
-
RootCauseAnalyzer
|
|
32
|
-
};
|
|
2
|
+
class l{lookbackMs;constructor(t=900000){this.lookbackMs=t}analyze(t,i){let s=new Date(t.point.timestamp.getTime()-this.lookbackMs),r=i.filter((n)=>n.deployedAt>=s).sort((n,a)=>a.deployedAt.getTime()-n.deployedAt.getTime()),o=[],e;if(r.length>0){if(e=r[0],e)o.push(`Closest deployment ${e.id} (${e.operation}) at ${e.deployedAt.toISOString()}`)}else o.push("No deployments found within lookback window.");if(t.type==="latency_regression")o.push("Verify recent schema changes and external dependency latency.");if(t.type==="error_rate_spike")o.push("Check SLO monitor for correlated incidents.");return{signal:t,culprit:e,notes:o}}}export{l as RootCauseAnalyzer};
|