@lunora/do 1.0.0-alpha.34 → 1.0.0-alpha.35
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/dist/index.d.mts +380 -69
- package/dist/index.d.ts +380 -69
- package/dist/index.mjs +4 -3
- package/dist/packem_shared/{ADMIN_FUNCTIONS-CAHLZMj8.mjs → ADMIN_FUNCTIONS-CqVmUVNs.mjs} +2 -0
- package/dist/packem_shared/{ROOT_DO_SIZE_WARN_BYTES-B5c6kQIN.mjs → ROOT_DO_SIZE_WARN_BYTES-QSOI2hpe.mjs} +376 -65
- package/dist/packem_shared/context-telemetry-DWfYDxCS.mjs +165 -0
- package/dist/packem_shared/createMetrics-BIL8Cl8X.mjs +1 -0
- package/dist/packem_shared/{serveRelationFanout-BgaNg3Hu.mjs → serveRelationFanout-Yiyx2OQB.mjs} +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { isLunoraError } from '@lunora/errors';
|
|
2
|
+
|
|
3
|
+
const stringifyFieldValue = (value) => {
|
|
4
|
+
if (typeof value === "string") {
|
|
5
|
+
return value;
|
|
6
|
+
}
|
|
7
|
+
try {
|
|
8
|
+
return JSON.stringify(value) ?? String(value);
|
|
9
|
+
} catch {
|
|
10
|
+
return String(value);
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
const coerceFieldValue = (value) => typeof value === "boolean" || typeof value === "number" || typeof value === "string" ? value : stringifyFieldValue(value);
|
|
14
|
+
const normalizeLogFields = (perCall, bound) => {
|
|
15
|
+
if (perCall === void 0 && bound === void 0) {
|
|
16
|
+
return void 0;
|
|
17
|
+
}
|
|
18
|
+
const merged = {};
|
|
19
|
+
if (bound !== void 0) {
|
|
20
|
+
for (const [key, value] of Object.entries(bound)) {
|
|
21
|
+
merged[key] = coerceFieldValue(value);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (perCall !== void 0) {
|
|
25
|
+
for (const [key, value] of Object.entries(perCall)) {
|
|
26
|
+
merged[key] = coerceFieldValue(value);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return Object.keys(merged).length === 0 ? void 0 : merged;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const otlpRandomHex = (bytes) => {
|
|
33
|
+
const buffer = new Uint8Array(bytes);
|
|
34
|
+
crypto.getRandomValues(buffer);
|
|
35
|
+
let hex = "";
|
|
36
|
+
for (const byte of buffer) {
|
|
37
|
+
hex += byte.toString(16).padStart(2, "0");
|
|
38
|
+
}
|
|
39
|
+
return hex;
|
|
40
|
+
};
|
|
41
|
+
const HEX_ONLY = /^[0-9a-f]+$/;
|
|
42
|
+
const parseTraceparent = (header) => {
|
|
43
|
+
if (header === null || header === void 0) {
|
|
44
|
+
return void 0;
|
|
45
|
+
}
|
|
46
|
+
const parts = header.trim().toLowerCase().split("-");
|
|
47
|
+
const [version, traceId, parentSpanId, flags] = parts;
|
|
48
|
+
if (parts.length < 4 || version === void 0 || version.length !== 2 || !HEX_ONLY.test(version) || version === "ff" || // Version 00 forbids trailing fields; only a future version may carry them.
|
|
49
|
+
version === "00" && parts.length !== 4 || traceId === void 0 || parentSpanId === void 0 || flags === void 0 || flags.length !== 2 || !HEX_ONLY.test(flags) || traceId.length !== 32 || parentSpanId.length !== 16 || !HEX_ONLY.test(traceId) || !HEX_ONLY.test(parentSpanId) || traceId === "00000000000000000000000000000000" || parentSpanId === "0000000000000000") {
|
|
50
|
+
return void 0;
|
|
51
|
+
}
|
|
52
|
+
return { parentSpanId, traceId };
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const resolveTraceAnchor = (traceparent) => {
|
|
56
|
+
const inbound = parseTraceparent(traceparent);
|
|
57
|
+
return { rootSpanId: inbound?.parentSpanId ?? otlpRandomHex(8), traceId: inbound?.traceId ?? otlpRandomHex(16) };
|
|
58
|
+
};
|
|
59
|
+
const toErrorType = (error) => {
|
|
60
|
+
if (isLunoraError(error)) {
|
|
61
|
+
return error.code;
|
|
62
|
+
}
|
|
63
|
+
return error instanceof Error ? error.constructor.name : "Error";
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const createTracer = (deps) => {
|
|
67
|
+
const { anchor, functionPath, record, shardKey, userId } = deps;
|
|
68
|
+
const tracerFor = (parentSpanId) => async (name, function_, attributes) => {
|
|
69
|
+
const spanId = otlpRandomHex(8);
|
|
70
|
+
const startTs = Date.now();
|
|
71
|
+
const normalized = normalizeLogFields(attributes);
|
|
72
|
+
let ok = true;
|
|
73
|
+
let error;
|
|
74
|
+
try {
|
|
75
|
+
return await function_(tracerFor(spanId));
|
|
76
|
+
} catch (error_) {
|
|
77
|
+
ok = false;
|
|
78
|
+
error = {
|
|
79
|
+
message: error_ instanceof Error ? error_.message : String(error_),
|
|
80
|
+
// Prefer a LunoraError's stable `code` over the class name so
|
|
81
|
+
// spans group by the same taxonomy the RPC spans use.
|
|
82
|
+
type: toErrorType(error_)
|
|
83
|
+
};
|
|
84
|
+
throw error_;
|
|
85
|
+
} finally {
|
|
86
|
+
try {
|
|
87
|
+
record({
|
|
88
|
+
...normalized === void 0 ? {} : { attributes: normalized },
|
|
89
|
+
durationMs: Date.now() - startTs,
|
|
90
|
+
...error === void 0 ? {} : { error },
|
|
91
|
+
functionPath,
|
|
92
|
+
name,
|
|
93
|
+
ok,
|
|
94
|
+
parentSpanId,
|
|
95
|
+
shardKey,
|
|
96
|
+
spanId,
|
|
97
|
+
startTs,
|
|
98
|
+
traceId: anchor.traceId,
|
|
99
|
+
userId: userId()
|
|
100
|
+
});
|
|
101
|
+
} catch {
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
return tracerFor(anchor.rootSpanId);
|
|
106
|
+
};
|
|
107
|
+
const createMetrics = (deps) => {
|
|
108
|
+
const { functionPath, record, shardKey } = deps;
|
|
109
|
+
const emit = (kind, name, value, attributes) => {
|
|
110
|
+
if (!Number.isFinite(value)) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const normalized = normalizeLogFields(attributes);
|
|
114
|
+
try {
|
|
115
|
+
record({
|
|
116
|
+
...normalized === void 0 ? {} : { attributes: normalized },
|
|
117
|
+
functionPath,
|
|
118
|
+
kind,
|
|
119
|
+
name,
|
|
120
|
+
shardKey,
|
|
121
|
+
ts: Date.now(),
|
|
122
|
+
value
|
|
123
|
+
});
|
|
124
|
+
} catch {
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
return {
|
|
128
|
+
count: (name, value = 1, attributes) => {
|
|
129
|
+
emit("counter", name, value, attributes);
|
|
130
|
+
},
|
|
131
|
+
gauge: (name, value, attributes) => {
|
|
132
|
+
emit("gauge", name, value, attributes);
|
|
133
|
+
},
|
|
134
|
+
record: (name, value, attributes) => {
|
|
135
|
+
emit("histogram", name, value, attributes);
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
};
|
|
139
|
+
const dispatchRootSpan = (input) => {
|
|
140
|
+
const { anchor, durationMs, failure, functionPath, shardKey, startTs, userId } = input;
|
|
141
|
+
return {
|
|
142
|
+
dispatch: true,
|
|
143
|
+
durationMs,
|
|
144
|
+
...failure === void 0 ? {} : {
|
|
145
|
+
error: {
|
|
146
|
+
message: failure.thrown instanceof Error ? failure.thrown.message : String(failure.thrown),
|
|
147
|
+
type: toErrorType(failure.thrown)
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
functionPath,
|
|
151
|
+
name: functionPath,
|
|
152
|
+
ok: failure === void 0,
|
|
153
|
+
// Empty: this span IS the trace's root locally. The worker's own RPC span
|
|
154
|
+
// sits above it in a full collector-side trace, but it is not in this
|
|
155
|
+
// buffer, so naming it here would dangle.
|
|
156
|
+
parentSpanId: "",
|
|
157
|
+
shardKey,
|
|
158
|
+
spanId: anchor.rootSpanId,
|
|
159
|
+
startTs,
|
|
160
|
+
traceId: anchor.traceId,
|
|
161
|
+
userId
|
|
162
|
+
};
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
export { createTracer as a, createMetrics as c, dispatchRootSpan as d, normalizeLogFields as n, resolveTraceAnchor as r };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { c as createMetrics, a as createTracer, d as dispatchRootSpan } from './context-telemetry-DWfYDxCS.mjs';
|
package/dist/packem_shared/{serveRelationFanout-BgaNg3Hu.mjs → serveRelationFanout-Yiyx2OQB.mjs}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LunoraError } from '@lunora/errors';
|
|
2
|
-
import { RELATION_FUNCTION_PREFIX } from './ADMIN_FUNCTIONS-
|
|
2
|
+
import { RELATION_FUNCTION_PREFIX } from './ADMIN_FUNCTIONS-CqVmUVNs.mjs';
|
|
3
3
|
|
|
4
4
|
const serveRelationFanout = async (schema, database, functionPath, args) => {
|
|
5
5
|
const table = typeof args["table"] === "string" ? args["table"] : "";
|