@contractspec/lib.observability 1.57.0 → 1.59.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/CHANGELOG.md +25 -0
- package/dist/anomaly/alert-manager.d.ts +17 -0
- package/dist/anomaly/alert-manager.js +24 -0
- package/dist/anomaly/anomaly-detector.d.ts +22 -0
- package/dist/anomaly/anomaly-detector.js +102 -0
- package/dist/anomaly/baseline-calculator.d.ts +23 -0
- package/dist/anomaly/baseline-calculator.js +40 -0
- package/dist/anomaly/root-cause-analyzer.d.ts +19 -0
- package/dist/anomaly/root-cause-analyzer.js +32 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +1078 -0
- package/dist/intent/aggregator.d.ts +57 -0
- package/dist/intent/aggregator.js +110 -0
- package/dist/intent/detector.d.ts +28 -0
- package/dist/intent/detector.js +133 -0
- package/dist/logging/index.d.ts +17 -0
- package/dist/logging/index.js +42 -0
- package/dist/metrics/index.d.ts +12 -0
- package/dist/metrics/index.js +31 -0
- package/dist/node/anomaly/alert-manager.js +23 -0
- package/dist/node/anomaly/anomaly-detector.js +101 -0
- package/dist/node/anomaly/baseline-calculator.js +39 -0
- package/dist/node/anomaly/root-cause-analyzer.js +31 -0
- package/dist/node/index.js +1077 -0
- package/dist/node/intent/aggregator.js +109 -0
- package/dist/node/intent/detector.js +132 -0
- package/dist/node/logging/index.js +41 -0
- package/dist/node/metrics/index.js +30 -0
- package/dist/node/pipeline/evolution-pipeline.js +299 -0
- package/dist/node/pipeline/lifecycle-pipeline.js +85 -0
- package/dist/node/telemetry/posthog-baseline-reader.js +308 -0
- package/dist/node/telemetry/posthog-telemetry.js +60 -0
- package/dist/node/tracing/index.js +52 -0
- package/dist/node/tracing/middleware.js +150 -0
- package/dist/pipeline/evolution-pipeline.d.ts +36 -0
- package/dist/pipeline/evolution-pipeline.js +300 -0
- package/dist/pipeline/lifecycle-pipeline.d.ts +40 -0
- package/dist/pipeline/lifecycle-pipeline.js +86 -0
- package/dist/telemetry/posthog-baseline-reader.d.ts +27 -0
- package/dist/telemetry/posthog-baseline-reader.js +309 -0
- package/dist/telemetry/posthog-telemetry.d.ts +15 -0
- package/dist/telemetry/posthog-telemetry.js +61 -0
- package/dist/tracing/index.d.ts +5 -0
- package/dist/tracing/index.js +53 -0
- package/dist/tracing/middleware.d.ts +15 -0
- package/dist/tracing/middleware.js +151 -0
- package/package.json +140 -43
- package/dist/anomaly/alert-manager.d.mts +0 -21
- package/dist/anomaly/alert-manager.mjs +0 -23
- package/dist/anomaly/anomaly-detector.d.mts +0 -26
- package/dist/anomaly/anomaly-detector.mjs +0 -58
- package/dist/anomaly/baseline-calculator.d.mts +0 -26
- package/dist/anomaly/baseline-calculator.mjs +0 -37
- package/dist/anomaly/root-cause-analyzer.d.mts +0 -23
- package/dist/anomaly/root-cause-analyzer.mjs +0 -27
- package/dist/index.d.mts +0 -15
- package/dist/index.mjs +0 -16
- package/dist/intent/aggregator.d.mts +0 -60
- package/dist/intent/aggregator.mjs +0 -98
- package/dist/intent/detector.d.mts +0 -32
- package/dist/intent/detector.mjs +0 -122
- package/dist/logging/index.d.mts +0 -20
- package/dist/logging/index.mjs +0 -40
- package/dist/metrics/index.d.mts +0 -17
- package/dist/metrics/index.mjs +0 -26
- package/dist/pipeline/evolution-pipeline.d.mts +0 -40
- package/dist/pipeline/evolution-pipeline.mjs +0 -66
- package/dist/pipeline/lifecycle-pipeline.d.mts +0 -44
- package/dist/pipeline/lifecycle-pipeline.mjs +0 -73
- package/dist/telemetry/posthog-baseline-reader.d.mts +0 -31
- package/dist/telemetry/posthog-baseline-reader.mjs +0 -266
- package/dist/telemetry/posthog-telemetry.d.mts +0 -19
- package/dist/telemetry/posthog-telemetry.mjs +0 -61
- package/dist/tracing/index.d.mts +0 -9
- package/dist/tracing/index.mjs +0 -47
- package/dist/tracing/middleware.d.mts +0 -19
- package/dist/tracing/middleware.mjs +0 -80
|
@@ -1,266 +0,0 @@
|
|
|
1
|
-
//#region src/telemetry/posthog-baseline-reader.ts
|
|
2
|
-
var PosthogBaselineReader = class {
|
|
3
|
-
reader;
|
|
4
|
-
eventPrefix;
|
|
5
|
-
constructor(reader, options = {}) {
|
|
6
|
-
this.reader = reader;
|
|
7
|
-
this.eventPrefix = options.eventPrefix ?? "observability";
|
|
8
|
-
}
|
|
9
|
-
async readSamples(input) {
|
|
10
|
-
return mapTelemetrySamples(await this.queryHogQL({
|
|
11
|
-
query: [
|
|
12
|
-
"select",
|
|
13
|
-
" properties.operation as operationName,",
|
|
14
|
-
" properties.version as version,",
|
|
15
|
-
" properties.durationMs as durationMs,",
|
|
16
|
-
" properties.success as success,",
|
|
17
|
-
" properties.errorCode as errorCode,",
|
|
18
|
-
" properties.tenantId as tenantId,",
|
|
19
|
-
" properties.traceId as traceId,",
|
|
20
|
-
" properties.metadata as metadata,",
|
|
21
|
-
" distinct_id as actorId,",
|
|
22
|
-
" timestamp as timestamp",
|
|
23
|
-
"from events",
|
|
24
|
-
`where ${buildOperationWhereClause(this.eventPrefix, input)}`,
|
|
25
|
-
"order by timestamp desc",
|
|
26
|
-
`limit ${input.limit ?? 1e3}`
|
|
27
|
-
].join("\n"),
|
|
28
|
-
values: buildOperationValues(input)
|
|
29
|
-
}));
|
|
30
|
-
}
|
|
31
|
-
async readAggregatedMetrics(operation, windowDays = 7) {
|
|
32
|
-
const dateRange = buildWindowRange(windowDays);
|
|
33
|
-
const stats = mapAggregatedMetrics(await this.queryHogQL({
|
|
34
|
-
query: [
|
|
35
|
-
"select",
|
|
36
|
-
" count() as totalCalls,",
|
|
37
|
-
" avg(properties.durationMs) as averageLatencyMs,",
|
|
38
|
-
" quantile(0.95)(properties.durationMs) as p95LatencyMs,",
|
|
39
|
-
" quantile(0.99)(properties.durationMs) as p99LatencyMs,",
|
|
40
|
-
" max(properties.durationMs) as maxLatencyMs,",
|
|
41
|
-
" sum(if(properties.success = 1, 1, 0)) as successCount,",
|
|
42
|
-
" sum(if(properties.success = 0, 1, 0)) as errorCount",
|
|
43
|
-
"from events",
|
|
44
|
-
`where ${buildOperationWhereClause(this.eventPrefix, {
|
|
45
|
-
operations: [operation],
|
|
46
|
-
dateRange
|
|
47
|
-
})}`
|
|
48
|
-
].join("\n"),
|
|
49
|
-
values: buildOperationValues({
|
|
50
|
-
operations: [operation],
|
|
51
|
-
dateRange
|
|
52
|
-
})
|
|
53
|
-
}), operation, dateRange);
|
|
54
|
-
if (!stats) return null;
|
|
55
|
-
const topErrors = await this.readTopErrors(operation, dateRange);
|
|
56
|
-
return {
|
|
57
|
-
...stats,
|
|
58
|
-
topErrors
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
async readOperationSequences(dateRange) {
|
|
62
|
-
return mergeSequences(await this.queryHogQL({
|
|
63
|
-
query: [
|
|
64
|
-
"select",
|
|
65
|
-
" properties.sequences as sequences",
|
|
66
|
-
"from events",
|
|
67
|
-
`where event = {eventName}`,
|
|
68
|
-
dateRange?.from ? "and timestamp >= {dateFrom}" : "",
|
|
69
|
-
dateRange?.to ? "and timestamp < {dateTo}" : "",
|
|
70
|
-
"order by timestamp desc",
|
|
71
|
-
"limit 50"
|
|
72
|
-
].filter(Boolean).join("\n"),
|
|
73
|
-
values: {
|
|
74
|
-
eventName: `${this.eventPrefix}.window`,
|
|
75
|
-
dateFrom: toIsoString(dateRange?.from),
|
|
76
|
-
dateTo: toIsoString(dateRange?.to)
|
|
77
|
-
}
|
|
78
|
-
}));
|
|
79
|
-
}
|
|
80
|
-
async readTopErrors(operation, dateRange) {
|
|
81
|
-
return mapRows(await this.queryHogQL({
|
|
82
|
-
query: [
|
|
83
|
-
"select",
|
|
84
|
-
" properties.errorCode as errorCode,",
|
|
85
|
-
" count() as errorCount",
|
|
86
|
-
"from events",
|
|
87
|
-
`where ${buildOperationWhereClause(this.eventPrefix, {
|
|
88
|
-
operations: [operation],
|
|
89
|
-
dateRange
|
|
90
|
-
})} and properties.success = 0`,
|
|
91
|
-
"group by errorCode",
|
|
92
|
-
"order by errorCount desc",
|
|
93
|
-
"limit 5"
|
|
94
|
-
].join("\n"),
|
|
95
|
-
values: buildOperationValues({
|
|
96
|
-
operations: [operation],
|
|
97
|
-
dateRange
|
|
98
|
-
})
|
|
99
|
-
})).reduce((acc, row) => {
|
|
100
|
-
const code = asString(row.errorCode);
|
|
101
|
-
if (!code) return acc;
|
|
102
|
-
acc[code] = asNumber(row.errorCount);
|
|
103
|
-
return acc;
|
|
104
|
-
}, {});
|
|
105
|
-
}
|
|
106
|
-
async queryHogQL(input) {
|
|
107
|
-
if (!this.reader.queryHogQL) throw new Error("Analytics reader does not support HogQL queries.");
|
|
108
|
-
return this.reader.queryHogQL(input);
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
function buildOperationWhereClause(eventPrefix, input) {
|
|
112
|
-
const clauses = [`event = '${eventPrefix}.operation'`];
|
|
113
|
-
if (input.operations?.length) clauses.push(`(${buildOperationFilters(input.operations)})`);
|
|
114
|
-
if (input.dateRange?.from) clauses.push("timestamp >= {dateFrom}");
|
|
115
|
-
if (input.dateRange?.to) clauses.push("timestamp < {dateTo}");
|
|
116
|
-
return clauses.join(" and ");
|
|
117
|
-
}
|
|
118
|
-
function buildOperationValues(input) {
|
|
119
|
-
const values = {
|
|
120
|
-
dateFrom: toIsoString(input.dateRange?.from),
|
|
121
|
-
dateTo: toIsoString(input.dateRange?.to)
|
|
122
|
-
};
|
|
123
|
-
input.operations?.forEach((op, index) => {
|
|
124
|
-
values[`operationName${index}`] = op.name;
|
|
125
|
-
values[`operationVersion${index}`] = op.version;
|
|
126
|
-
});
|
|
127
|
-
return values;
|
|
128
|
-
}
|
|
129
|
-
function buildOperationFilters(operations) {
|
|
130
|
-
return operations.map((_op, index) => `(properties.operation = {operationName${index}} and properties.version = {operationVersion${index}})`).join(" or ");
|
|
131
|
-
}
|
|
132
|
-
function mapTelemetrySamples(result) {
|
|
133
|
-
return mapRows(result).flatMap((row) => {
|
|
134
|
-
const operationName = asString(row.operationName);
|
|
135
|
-
const version = asString(row.version);
|
|
136
|
-
const timestamp = asDate(row.timestamp);
|
|
137
|
-
if (!operationName || !version || !timestamp) return [];
|
|
138
|
-
return [{
|
|
139
|
-
operation: {
|
|
140
|
-
name: operationName,
|
|
141
|
-
version
|
|
142
|
-
},
|
|
143
|
-
durationMs: asNumber(row.durationMs),
|
|
144
|
-
success: asBoolean(row.success),
|
|
145
|
-
timestamp,
|
|
146
|
-
errorCode: asOptionalString(row.errorCode) ?? void 0,
|
|
147
|
-
tenantId: asOptionalString(row.tenantId) ?? void 0,
|
|
148
|
-
traceId: asOptionalString(row.traceId) ?? void 0,
|
|
149
|
-
actorId: asOptionalString(row.actorId) ?? void 0,
|
|
150
|
-
metadata: isRecord(row.metadata) ? row.metadata : void 0
|
|
151
|
-
}];
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
function mapAggregatedMetrics(result, operation, dateRange) {
|
|
155
|
-
const row = mapRows(result)[0];
|
|
156
|
-
if (!row) return null;
|
|
157
|
-
const totalCalls = asNumber(row.totalCalls);
|
|
158
|
-
if (!totalCalls) return null;
|
|
159
|
-
const successCount = asNumber(row.successCount);
|
|
160
|
-
const errorCount = asNumber(row.errorCount);
|
|
161
|
-
const windowStart = toDate(dateRange.from) ?? /* @__PURE__ */ new Date();
|
|
162
|
-
const windowEnd = toDate(dateRange.to) ?? /* @__PURE__ */ new Date();
|
|
163
|
-
return {
|
|
164
|
-
operation,
|
|
165
|
-
totalCalls,
|
|
166
|
-
successRate: totalCalls ? successCount / totalCalls : 0,
|
|
167
|
-
errorRate: totalCalls ? errorCount / totalCalls : 0,
|
|
168
|
-
averageLatencyMs: asNumber(row.averageLatencyMs),
|
|
169
|
-
p95LatencyMs: asNumber(row.p95LatencyMs),
|
|
170
|
-
p99LatencyMs: asNumber(row.p99LatencyMs),
|
|
171
|
-
maxLatencyMs: asNumber(row.maxLatencyMs),
|
|
172
|
-
windowStart,
|
|
173
|
-
windowEnd,
|
|
174
|
-
topErrors: {}
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
function mergeSequences(result) {
|
|
178
|
-
const rows = mapRows(result);
|
|
179
|
-
const merged = /* @__PURE__ */ new Map();
|
|
180
|
-
rows.forEach((row) => {
|
|
181
|
-
const sequences = row.sequences;
|
|
182
|
-
if (!Array.isArray(sequences)) return;
|
|
183
|
-
sequences.forEach((sequence) => {
|
|
184
|
-
if (!isRecord(sequence)) return;
|
|
185
|
-
const steps = Array.isArray(sequence.steps) ? sequence.steps.filter((step) => typeof step === "string") : [];
|
|
186
|
-
if (steps.length === 0) return;
|
|
187
|
-
const tenantId = typeof sequence.tenantId === "string" ? sequence.tenantId : void 0;
|
|
188
|
-
const count = typeof sequence.count === "number" && Number.isFinite(sequence.count) ? sequence.count : 0;
|
|
189
|
-
const key = `${tenantId ?? "global"}:${steps.join(">")}`;
|
|
190
|
-
const existing = merged.get(key);
|
|
191
|
-
if (existing) existing.count += count;
|
|
192
|
-
else merged.set(key, {
|
|
193
|
-
steps,
|
|
194
|
-
tenantId,
|
|
195
|
-
count
|
|
196
|
-
});
|
|
197
|
-
});
|
|
198
|
-
});
|
|
199
|
-
return [...merged.values()];
|
|
200
|
-
}
|
|
201
|
-
function mapRows(result) {
|
|
202
|
-
if (!Array.isArray(result.results) || !Array.isArray(result.columns)) return [];
|
|
203
|
-
const columns = result.columns;
|
|
204
|
-
return result.results.flatMap((row) => {
|
|
205
|
-
if (!Array.isArray(row)) return [];
|
|
206
|
-
const record = {};
|
|
207
|
-
columns.forEach((column, index) => {
|
|
208
|
-
record[column] = row[index];
|
|
209
|
-
});
|
|
210
|
-
return [record];
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
function buildWindowRange(windowDays) {
|
|
214
|
-
const windowEnd = /* @__PURE__ */ new Date();
|
|
215
|
-
return {
|
|
216
|
-
from: /* @__PURE__ */ new Date(windowEnd.getTime() - windowDays * 24 * 60 * 60 * 1e3),
|
|
217
|
-
to: windowEnd
|
|
218
|
-
};
|
|
219
|
-
}
|
|
220
|
-
function asString(value) {
|
|
221
|
-
if (typeof value === "string" && value.trim()) return value;
|
|
222
|
-
if (typeof value === "number") return String(value);
|
|
223
|
-
return null;
|
|
224
|
-
}
|
|
225
|
-
function asOptionalString(value) {
|
|
226
|
-
if (typeof value === "string") return value;
|
|
227
|
-
if (typeof value === "number") return String(value);
|
|
228
|
-
return null;
|
|
229
|
-
}
|
|
230
|
-
function asNumber(value) {
|
|
231
|
-
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
232
|
-
if (typeof value === "string" && value.trim()) {
|
|
233
|
-
const parsed = Number(value);
|
|
234
|
-
if (Number.isFinite(parsed)) return parsed;
|
|
235
|
-
}
|
|
236
|
-
return 0;
|
|
237
|
-
}
|
|
238
|
-
function asBoolean(value) {
|
|
239
|
-
if (typeof value === "boolean") return value;
|
|
240
|
-
if (typeof value === "number") return value !== 0;
|
|
241
|
-
if (typeof value === "string") return value.toLowerCase() === "true";
|
|
242
|
-
return false;
|
|
243
|
-
}
|
|
244
|
-
function asDate(value) {
|
|
245
|
-
if (value instanceof Date) return value;
|
|
246
|
-
if (typeof value === "string" || typeof value === "number") {
|
|
247
|
-
const date = new Date(value);
|
|
248
|
-
if (!Number.isNaN(date.getTime())) return date;
|
|
249
|
-
}
|
|
250
|
-
return null;
|
|
251
|
-
}
|
|
252
|
-
function toIsoString(value) {
|
|
253
|
-
if (!value) return void 0;
|
|
254
|
-
return typeof value === "string" ? value : value.toISOString();
|
|
255
|
-
}
|
|
256
|
-
function toDate(value) {
|
|
257
|
-
if (!value) return null;
|
|
258
|
-
return value instanceof Date ? value : new Date(value);
|
|
259
|
-
}
|
|
260
|
-
function isRecord(value) {
|
|
261
|
-
return typeof value === "object" && value !== null;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
//#endregion
|
|
265
|
-
export { PosthogBaselineReader };
|
|
266
|
-
//# sourceMappingURL=posthog-baseline-reader.mjs.map
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { IntentAggregatorSnapshot, TelemetrySample } from "../intent/aggregator.mjs";
|
|
2
|
-
import { AnalyticsProvider } from "@contractspec/lib.contracts/integrations/providers/analytics";
|
|
3
|
-
|
|
4
|
-
//#region src/telemetry/posthog-telemetry.d.ts
|
|
5
|
-
interface PosthogTelemetryProviderOptions {
|
|
6
|
-
eventPrefix?: string;
|
|
7
|
-
includeMetadata?: boolean;
|
|
8
|
-
}
|
|
9
|
-
declare class PosthogTelemetryProvider {
|
|
10
|
-
private readonly provider;
|
|
11
|
-
private readonly eventPrefix;
|
|
12
|
-
private readonly includeMetadata;
|
|
13
|
-
constructor(provider: AnalyticsProvider, options?: PosthogTelemetryProviderOptions);
|
|
14
|
-
captureSample(sample: TelemetrySample): Promise<void>;
|
|
15
|
-
captureSnapshot(snapshot: IntentAggregatorSnapshot): Promise<void>;
|
|
16
|
-
}
|
|
17
|
-
//#endregion
|
|
18
|
-
export { PosthogTelemetryProvider, PosthogTelemetryProviderOptions };
|
|
19
|
-
//# sourceMappingURL=posthog-telemetry.d.mts.map
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
//#region src/telemetry/posthog-telemetry.ts
|
|
2
|
-
var PosthogTelemetryProvider = class {
|
|
3
|
-
provider;
|
|
4
|
-
eventPrefix;
|
|
5
|
-
includeMetadata;
|
|
6
|
-
constructor(provider, options = {}) {
|
|
7
|
-
this.provider = provider;
|
|
8
|
-
this.eventPrefix = options.eventPrefix ?? "observability";
|
|
9
|
-
this.includeMetadata = options.includeMetadata ?? false;
|
|
10
|
-
}
|
|
11
|
-
async captureSample(sample) {
|
|
12
|
-
await this.provider.capture({
|
|
13
|
-
distinctId: sample.actorId ?? sample.tenantId ?? "unknown",
|
|
14
|
-
event: `${this.eventPrefix}.operation`,
|
|
15
|
-
timestamp: sample.timestamp,
|
|
16
|
-
properties: {
|
|
17
|
-
operation: sample.operation.name,
|
|
18
|
-
version: sample.operation.version,
|
|
19
|
-
durationMs: sample.durationMs,
|
|
20
|
-
success: sample.success,
|
|
21
|
-
errorCode: sample.errorCode ?? null,
|
|
22
|
-
tenantId: sample.tenantId ?? null,
|
|
23
|
-
traceId: sample.traceId ?? null,
|
|
24
|
-
...this.includeMetadata && sample.metadata ? { metadata: sample.metadata } : {}
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
async captureSnapshot(snapshot) {
|
|
29
|
-
await this.provider.capture({
|
|
30
|
-
distinctId: "system",
|
|
31
|
-
event: `${this.eventPrefix}.window`,
|
|
32
|
-
timestamp: snapshot.windowEnd ?? /* @__PURE__ */ new Date(),
|
|
33
|
-
properties: {
|
|
34
|
-
sampleCount: snapshot.sampleCount,
|
|
35
|
-
metricsCount: snapshot.metrics.length,
|
|
36
|
-
sequencesCount: snapshot.sequences.length,
|
|
37
|
-
windowStart: snapshot.windowStart?.toISOString() ?? null,
|
|
38
|
-
windowEnd: snapshot.windowEnd?.toISOString() ?? null,
|
|
39
|
-
...this.includeMetadata ? {
|
|
40
|
-
metrics: snapshot.metrics.map((metric) => ({
|
|
41
|
-
operation: metric.operation.name,
|
|
42
|
-
version: metric.operation.version,
|
|
43
|
-
totalCalls: metric.totalCalls,
|
|
44
|
-
successRate: metric.successRate,
|
|
45
|
-
errorRate: metric.errorRate,
|
|
46
|
-
averageLatencyMs: metric.averageLatencyMs,
|
|
47
|
-
p95LatencyMs: metric.p95LatencyMs,
|
|
48
|
-
p99LatencyMs: metric.p99LatencyMs,
|
|
49
|
-
maxLatencyMs: metric.maxLatencyMs,
|
|
50
|
-
topErrors: metric.topErrors
|
|
51
|
-
})),
|
|
52
|
-
sequences: snapshot.sequences
|
|
53
|
-
} : {}
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
//#endregion
|
|
60
|
-
export { PosthogTelemetryProvider };
|
|
61
|
-
//# sourceMappingURL=posthog-telemetry.mjs.map
|
package/dist/tracing/index.d.mts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { Span, Tracer } from "@opentelemetry/api";
|
|
2
|
-
|
|
3
|
-
//#region src/tracing/index.d.ts
|
|
4
|
-
declare function getTracer(name?: string): Tracer;
|
|
5
|
-
declare function traceAsync<T>(name: string, fn: (span: Span) => Promise<T>, tracerName?: string): Promise<T>;
|
|
6
|
-
declare function traceSync<T>(name: string, fn: (span: Span) => T, tracerName?: string): T;
|
|
7
|
-
//#endregion
|
|
8
|
-
export { getTracer, traceAsync, traceSync };
|
|
9
|
-
//# sourceMappingURL=index.d.mts.map
|
package/dist/tracing/index.mjs
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { SpanStatusCode, trace } from "@opentelemetry/api";
|
|
2
|
-
|
|
3
|
-
//#region src/tracing/index.ts
|
|
4
|
-
const DEFAULT_TRACER_NAME = "@contractspec/lib.observability";
|
|
5
|
-
function getTracer(name = DEFAULT_TRACER_NAME) {
|
|
6
|
-
return trace.getTracer(name);
|
|
7
|
-
}
|
|
8
|
-
async function traceAsync(name, fn, tracerName) {
|
|
9
|
-
return getTracer(tracerName).startActiveSpan(name, async (span) => {
|
|
10
|
-
try {
|
|
11
|
-
const result = await fn(span);
|
|
12
|
-
span.setStatus({ code: SpanStatusCode.OK });
|
|
13
|
-
return result;
|
|
14
|
-
} catch (error) {
|
|
15
|
-
span.recordException(error);
|
|
16
|
-
span.setStatus({
|
|
17
|
-
code: SpanStatusCode.ERROR,
|
|
18
|
-
message: error instanceof Error ? error.message : String(error)
|
|
19
|
-
});
|
|
20
|
-
throw error;
|
|
21
|
-
} finally {
|
|
22
|
-
span.end();
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
function traceSync(name, fn, tracerName) {
|
|
27
|
-
return getTracer(tracerName).startActiveSpan(name, (span) => {
|
|
28
|
-
try {
|
|
29
|
-
const result = fn(span);
|
|
30
|
-
span.setStatus({ code: SpanStatusCode.OK });
|
|
31
|
-
return result;
|
|
32
|
-
} catch (error) {
|
|
33
|
-
span.recordException(error);
|
|
34
|
-
span.setStatus({
|
|
35
|
-
code: SpanStatusCode.ERROR,
|
|
36
|
-
message: error instanceof Error ? error.message : String(error)
|
|
37
|
-
});
|
|
38
|
-
throw error;
|
|
39
|
-
} finally {
|
|
40
|
-
span.end();
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
//#endregion
|
|
46
|
-
export { getTracer, traceAsync, traceSync };
|
|
47
|
-
//# sourceMappingURL=index.mjs.map
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { TelemetrySample } from "../intent/aggregator.mjs";
|
|
2
|
-
|
|
3
|
-
//#region src/tracing/middleware.d.ts
|
|
4
|
-
interface TracingMiddlewareOptions {
|
|
5
|
-
resolveOperation?: (input: {
|
|
6
|
-
req: Request;
|
|
7
|
-
res?: Response;
|
|
8
|
-
}) => {
|
|
9
|
-
name: string;
|
|
10
|
-
version: string;
|
|
11
|
-
} | undefined;
|
|
12
|
-
onSample?: (sample: TelemetrySample) => void;
|
|
13
|
-
tenantResolver?: (req: Request) => string | undefined;
|
|
14
|
-
actorResolver?: (req: Request) => string | undefined;
|
|
15
|
-
}
|
|
16
|
-
declare function createTracingMiddleware(options?: TracingMiddlewareOptions): (req: Request, next: () => Promise<Response>) => Promise<Response>;
|
|
17
|
-
//#endregion
|
|
18
|
-
export { TracingMiddlewareOptions, createTracingMiddleware };
|
|
19
|
-
//# sourceMappingURL=middleware.d.mts.map
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import { traceAsync } from "./index.mjs";
|
|
2
|
-
import { standardMetrics } from "../metrics/index.mjs";
|
|
3
|
-
|
|
4
|
-
//#region src/tracing/middleware.ts
|
|
5
|
-
function createTracingMiddleware(options = {}) {
|
|
6
|
-
return async (req, next) => {
|
|
7
|
-
const method = req.method;
|
|
8
|
-
const path = new URL(req.url).pathname;
|
|
9
|
-
standardMetrics.httpRequests.add(1, {
|
|
10
|
-
method,
|
|
11
|
-
path
|
|
12
|
-
});
|
|
13
|
-
const startTime = performance.now();
|
|
14
|
-
return traceAsync(`HTTP ${method} ${path}`, async (span) => {
|
|
15
|
-
span.setAttribute("http.method", method);
|
|
16
|
-
span.setAttribute("http.url", req.url);
|
|
17
|
-
try {
|
|
18
|
-
const response = await next();
|
|
19
|
-
span.setAttribute("http.status_code", response.status);
|
|
20
|
-
const duration = (performance.now() - startTime) / 1e3;
|
|
21
|
-
standardMetrics.httpDuration.record(duration, {
|
|
22
|
-
method,
|
|
23
|
-
path,
|
|
24
|
-
status: response.status.toString()
|
|
25
|
-
});
|
|
26
|
-
emitTelemetrySample({
|
|
27
|
-
req,
|
|
28
|
-
res: response,
|
|
29
|
-
span,
|
|
30
|
-
success: true,
|
|
31
|
-
durationMs: duration * 1e3,
|
|
32
|
-
options
|
|
33
|
-
});
|
|
34
|
-
return response;
|
|
35
|
-
} catch (error) {
|
|
36
|
-
standardMetrics.operationErrors.add(1, {
|
|
37
|
-
method,
|
|
38
|
-
path
|
|
39
|
-
});
|
|
40
|
-
emitTelemetrySample({
|
|
41
|
-
req,
|
|
42
|
-
span,
|
|
43
|
-
success: false,
|
|
44
|
-
durationMs: performance.now() - startTime,
|
|
45
|
-
error,
|
|
46
|
-
options
|
|
47
|
-
});
|
|
48
|
-
throw error;
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
function emitTelemetrySample({ req, res, span, success, durationMs, error, options }) {
|
|
54
|
-
if (!options.onSample || !options.resolveOperation) return;
|
|
55
|
-
const operation = options.resolveOperation({
|
|
56
|
-
req,
|
|
57
|
-
res
|
|
58
|
-
});
|
|
59
|
-
if (!operation) return;
|
|
60
|
-
const sample = {
|
|
61
|
-
operation,
|
|
62
|
-
durationMs,
|
|
63
|
-
success,
|
|
64
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
65
|
-
errorCode: !success && error instanceof Error ? error.name : success ? void 0 : "unknown",
|
|
66
|
-
tenantId: options.tenantResolver?.(req),
|
|
67
|
-
actorId: options.actorResolver?.(req),
|
|
68
|
-
traceId: span.spanContext().traceId,
|
|
69
|
-
metadata: {
|
|
70
|
-
method: req.method,
|
|
71
|
-
path: new URL(req.url).pathname,
|
|
72
|
-
status: res?.status
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
options.onSample(sample);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
//#endregion
|
|
79
|
-
export { createTracingMiddleware };
|
|
80
|
-
//# sourceMappingURL=middleware.mjs.map
|