@lunora/runtime 1.0.0-alpha.25 → 1.0.0-alpha.26
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 +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.mjs +2 -2
- package/dist/packem_shared/{analyticsEngineSink-BpJlA7e9.mjs → analyticsEngineSink-F-5ZAdUA.mjs} +5 -80
- package/dist/packem_shared/{composeWorker-CxwkPZUl.mjs → composeWorker-BMxMYwKq.mjs} +7 -2
- package/dist/packem_shared/otlp-D_YzGXu1.mjs +81 -0
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -682,6 +682,16 @@ interface ObservabilityEvent {
|
|
|
682
682
|
ok: boolean;
|
|
683
683
|
/** Shard key for single-shard calls; absent for fan-outs. */
|
|
684
684
|
shardKey?: string;
|
|
685
|
+
/**
|
|
686
|
+
* W3C trace context for this dispatch, generated once at dispatch entry (32-
|
|
687
|
+
* and 16-hex). A sink (e.g. `otlpSink`) reuses these for the dispatch's span
|
|
688
|
+
* instead of minting fresh ids, and the runtime propagates them to the shard
|
|
689
|
+
* as a `traceparent` so a container the handler calls can stitch its spans
|
|
690
|
+
* under the same trace. Absent on paths that don't originate a trace (a sink
|
|
691
|
+
* falls back to random ids).
|
|
692
|
+
*/
|
|
693
|
+
spanId?: string;
|
|
694
|
+
traceId?: string;
|
|
685
695
|
}
|
|
686
696
|
/** Severity of a {@link LogEvent}, mirroring the usual console levels. */
|
|
687
697
|
type LogLevel = "debug" | "error" | "info" | "log" | "warn";
|
package/dist/index.d.ts
CHANGED
|
@@ -682,6 +682,16 @@ interface ObservabilityEvent {
|
|
|
682
682
|
ok: boolean;
|
|
683
683
|
/** Shard key for single-shard calls; absent for fan-outs. */
|
|
684
684
|
shardKey?: string;
|
|
685
|
+
/**
|
|
686
|
+
* W3C trace context for this dispatch, generated once at dispatch entry (32-
|
|
687
|
+
* and 16-hex). A sink (e.g. `otlpSink`) reuses these for the dispatch's span
|
|
688
|
+
* instead of minting fresh ids, and the runtime propagates them to the shard
|
|
689
|
+
* as a `traceparent` so a container the handler calls can stitch its spans
|
|
690
|
+
* under the same trace. Absent on paths that don't originate a trace (a sink
|
|
691
|
+
* falls back to random ids).
|
|
692
|
+
*/
|
|
693
|
+
spanId?: string;
|
|
694
|
+
traceId?: string;
|
|
685
695
|
}
|
|
686
696
|
/** Severity of a {@link LogEvent}, mirroring the usual console levels. */
|
|
687
697
|
type LogLevel = "debug" | "error" | "info" | "log" | "warn";
|
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
export { toAirbyteMessages, toFivetranResponse } from './packem_shared/toAirbyteMessages-DrHdplb4.mjs';
|
|
2
|
-
export { composeWorker, createLunoraHandler, createWorker, defineRpcEnvelope, resolveLunoraOptions, withFrameworkWorker } from './packem_shared/composeWorker-
|
|
2
|
+
export { composeWorker, createLunoraHandler, createWorker, defineRpcEnvelope, resolveLunoraOptions, withFrameworkWorker } from './packem_shared/composeWorker-BMxMYwKq.mjs';
|
|
3
3
|
export { createCrossShardRelationCapabilities } from './packem_shared/createCrossShardRelationCapabilities-CbcWjkAn.mjs';
|
|
4
4
|
export { DEFAULT_REGISTRY_CACHE_TTL_MS, SHARD_REGISTRY_DO_NAME, createDynamicShardRegistry } from './packem_shared/DEFAULT_REGISTRY_CACHE_TTL_MS-B3pA7aXp.mjs';
|
|
5
5
|
export { LunoraError, toErrorResponse } from './packem_shared/LunoraError-Bpb9EFJ3.mjs';
|
|
6
6
|
export { emitLogEvent, emitRpcEvent } from './packem_shared/emitLogEvent-pEdtqAK8.mjs';
|
|
7
|
-
export { analyticsEngineSink, combineSinks, consoleSink, otlpSink, sentrySink, webhookSink } from './packem_shared/analyticsEngineSink-
|
|
7
|
+
export { analyticsEngineSink, combineSinks, consoleSink, otlpSink, sentrySink, webhookSink } from './packem_shared/analyticsEngineSink-F-5ZAdUA.mjs';
|
|
8
8
|
export { createQueryCoordinator, createStaticShardRegistry, mergeStrategyForAggregate } from './packem_shared/createQueryCoordinator-DNCJzOZE.mjs';
|
|
9
9
|
export { applyJurisdiction, resolveShard } from './packem_shared/applyJurisdiction-BkZtTkct.mjs';
|
|
10
10
|
export { decorateResponse, enforceOrigin, handleCorsPreflight, resolveSecurity } from './packem_shared/decorateResponse-DRWQFNhF.mjs';
|
package/dist/packem_shared/{analyticsEngineSink-BpJlA7e9.mjs → analyticsEngineSink-F-5ZAdUA.mjs}
RENAMED
|
@@ -1,81 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
debug: 5,
|
|
3
|
-
// DEBUG
|
|
4
|
-
error: 17,
|
|
5
|
-
// ERROR
|
|
6
|
-
info: 9,
|
|
7
|
-
// INFO
|
|
8
|
-
log: 9,
|
|
9
|
-
// INFO
|
|
10
|
-
warn: 13
|
|
11
|
-
// WARN
|
|
12
|
-
};
|
|
13
|
-
const otlpUnixNano = (ms) => `${String(Math.round(ms))}000000`;
|
|
14
|
-
const otlpRandomHex = (bytes) => {
|
|
15
|
-
const buffer = new Uint8Array(bytes);
|
|
16
|
-
crypto.getRandomValues(buffer);
|
|
17
|
-
let hex = "";
|
|
18
|
-
for (const byte of buffer) {
|
|
19
|
-
hex += byte.toString(16).padStart(2, "0");
|
|
20
|
-
}
|
|
21
|
-
return hex;
|
|
22
|
-
};
|
|
23
|
-
const encodeAttribute = (key, value) => {
|
|
24
|
-
if (typeof value === "boolean") {
|
|
25
|
-
return { key, value: { boolValue: value } };
|
|
26
|
-
}
|
|
27
|
-
if (typeof value === "number") {
|
|
28
|
-
if (!Number.isFinite(value)) {
|
|
29
|
-
return { key, value: { stringValue: String(value) } };
|
|
30
|
-
}
|
|
31
|
-
return Number.isSafeInteger(value) ? { key, value: { intValue: String(value) } } : { key, value: { doubleValue: value } };
|
|
32
|
-
}
|
|
33
|
-
return { key, value: { stringValue: value } };
|
|
34
|
-
};
|
|
35
|
-
const mergeHeaders = (defaults, overrides, token) => {
|
|
36
|
-
const merged = {};
|
|
37
|
-
const seen = /* @__PURE__ */ new Map();
|
|
38
|
-
const put = (name, value) => {
|
|
39
|
-
const lower = name.toLowerCase();
|
|
40
|
-
const existing = seen.get(lower);
|
|
41
|
-
if (existing === void 0) {
|
|
42
|
-
seen.set(lower, name);
|
|
43
|
-
merged[name] = value;
|
|
44
|
-
} else {
|
|
45
|
-
merged[existing] = value;
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
for (const [name, value] of Object.entries(defaults)) {
|
|
49
|
-
put(name, value);
|
|
50
|
-
}
|
|
51
|
-
for (const [name, value] of Object.entries(overrides ?? {})) {
|
|
52
|
-
put(name, value);
|
|
53
|
-
}
|
|
54
|
-
if (token !== void 0 && token.length > 0) {
|
|
55
|
-
put("authorization", `Bearer ${token}`);
|
|
56
|
-
}
|
|
57
|
-
return merged;
|
|
58
|
-
};
|
|
59
|
-
const wrapResourceSpans = (span, scopeName, serviceName) => {
|
|
60
|
-
return {
|
|
61
|
-
resourceSpans: [
|
|
62
|
-
{
|
|
63
|
-
resource: { attributes: [encodeAttribute("service.name", serviceName)] },
|
|
64
|
-
scopeSpans: [{ scope: { name: scopeName }, spans: [span] }]
|
|
65
|
-
}
|
|
66
|
-
]
|
|
67
|
-
};
|
|
68
|
-
};
|
|
69
|
-
const wrapResourceLogs = (logRecord, scopeName, serviceName) => {
|
|
70
|
-
return {
|
|
71
|
-
resourceLogs: [
|
|
72
|
-
{
|
|
73
|
-
resource: { attributes: [encodeAttribute("service.name", serviceName)] },
|
|
74
|
-
scopeLogs: [{ logRecords: [logRecord], scope: { name: scopeName } }]
|
|
75
|
-
}
|
|
76
|
-
]
|
|
77
|
-
};
|
|
78
|
-
};
|
|
1
|
+
import { m as mergeHeaders, o as otlpRandomHex, w as wrapResourceSpans, a as wrapResourceLogs, e as encodeAttribute, O as OTLP_SEVERITY, c as otlpUnixNano } from './otlp-D_YzGXu1.mjs';
|
|
79
2
|
|
|
80
3
|
const shouldSkip = (event, onlyErrors) => onlyErrors === true && event.ok;
|
|
81
4
|
const otlpTraceBody = (event, serviceName, endMs) => {
|
|
@@ -99,11 +22,13 @@ const otlpTraceBody = (event, serviceName, endMs) => {
|
|
|
99
22
|
// SPAN_KIND_SERVER — a dispatched RPC is server-side request handling.
|
|
100
23
|
kind: 2,
|
|
101
24
|
name: event.functionPath,
|
|
102
|
-
|
|
25
|
+
// Reuse the dispatch's trace context when the runtime set it (so this span
|
|
26
|
+
// shares the id it propagated as `traceparent`); else mint fresh ids.
|
|
27
|
+
spanId: event.spanId ?? otlpRandomHex(8),
|
|
103
28
|
startTimeUnixNano: otlpUnixNano(endMs - event.durationMs),
|
|
104
29
|
// STATUS_CODE_OK (1) / STATUS_CODE_ERROR (2).
|
|
105
30
|
status: event.ok ? { code: 1 } : { code: 2, message: event.error?.message ?? "" },
|
|
106
|
-
traceId: otlpRandomHex(16)
|
|
31
|
+
traceId: event.traceId ?? otlpRandomHex(16)
|
|
107
32
|
};
|
|
108
33
|
return wrapResourceSpans(span, "@lunora/runtime", serviceName);
|
|
109
34
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { isLunoraError, toErrorBody } from '@lunora/errors';
|
|
2
2
|
import { NOOP_EXECUTION_CONTEXT } from './NOOP_EXECUTION_CONTEXT-CCTu0Bf1.mjs';
|
|
3
|
+
import { o as otlpRandomHex, b as buildTraceparent } from './otlp-D_YzGXu1.mjs';
|
|
3
4
|
import { LunoraError, toErrorResponse } from './LunoraError-Bpb9EFJ3.mjs';
|
|
4
5
|
import { wrapResolverWithContract } from './composeIdentityResolvers-XGjO7V1J.mjs';
|
|
5
6
|
export { composeIdentityResolvers, routeIdentityResolvers } from './composeIdentityResolvers-XGjO7V1J.mjs';
|
|
@@ -2605,9 +2606,11 @@ const createWorker = (options) => {
|
|
|
2605
2606
|
const dispatchSingleShard = async (functionPath, args, shardKey, forwardedHeaders, sinkContext) => {
|
|
2606
2607
|
const rpcStartedAt = Date.now();
|
|
2607
2608
|
const { observability } = options;
|
|
2609
|
+
const traceId = otlpRandomHex(16);
|
|
2610
|
+
const spanId = otlpRandomHex(8);
|
|
2608
2611
|
const forwarded = new Request(`https://shard.internal/rpc`, {
|
|
2609
2612
|
body: JSON.stringify({ args, functionPath }),
|
|
2610
|
-
headers: forwardedHeaders,
|
|
2613
|
+
headers: { ...forwardedHeaders, traceparent: buildTraceparent(traceId, spanId) },
|
|
2611
2614
|
method: "POST"
|
|
2612
2615
|
});
|
|
2613
2616
|
try {
|
|
@@ -2619,13 +2622,15 @@ const createWorker = (options) => {
|
|
|
2619
2622
|
functionPath,
|
|
2620
2623
|
ok: response.ok,
|
|
2621
2624
|
shardKey,
|
|
2625
|
+
spanId,
|
|
2626
|
+
traceId,
|
|
2622
2627
|
...response.ok ? {} : { error: { code: "SHARD_ERROR", message: `shard returned ${String(response.status)}`, status: response.status } }
|
|
2623
2628
|
},
|
|
2624
2629
|
sinkContext
|
|
2625
2630
|
);
|
|
2626
2631
|
return response;
|
|
2627
2632
|
} catch (error) {
|
|
2628
|
-
emitRpcEvent(observability, buildErrorEvent(functionPath, Date.now() - rpcStartedAt, error, { shardKey }), sinkContext);
|
|
2633
|
+
emitRpcEvent(observability, { ...buildErrorEvent(functionPath, Date.now() - rpcStartedAt, error, { shardKey }), spanId, traceId }, sinkContext);
|
|
2629
2634
|
throw error;
|
|
2630
2635
|
}
|
|
2631
2636
|
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
const OTLP_SEVERITY = {
|
|
2
|
+
debug: 5,
|
|
3
|
+
// DEBUG
|
|
4
|
+
error: 17,
|
|
5
|
+
// ERROR
|
|
6
|
+
info: 9,
|
|
7
|
+
// INFO
|
|
8
|
+
log: 9,
|
|
9
|
+
// INFO
|
|
10
|
+
warn: 13
|
|
11
|
+
// WARN
|
|
12
|
+
};
|
|
13
|
+
const otlpUnixNano = (ms) => `${String(Math.round(ms))}000000`;
|
|
14
|
+
const otlpRandomHex = (bytes) => {
|
|
15
|
+
const buffer = new Uint8Array(bytes);
|
|
16
|
+
crypto.getRandomValues(buffer);
|
|
17
|
+
let hex = "";
|
|
18
|
+
for (const byte of buffer) {
|
|
19
|
+
hex += byte.toString(16).padStart(2, "0");
|
|
20
|
+
}
|
|
21
|
+
return hex;
|
|
22
|
+
};
|
|
23
|
+
const buildTraceparent = (traceId, spanId) => `00-${traceId}-${spanId}-01`;
|
|
24
|
+
const encodeAttribute = (key, value) => {
|
|
25
|
+
if (typeof value === "boolean") {
|
|
26
|
+
return { key, value: { boolValue: value } };
|
|
27
|
+
}
|
|
28
|
+
if (typeof value === "number") {
|
|
29
|
+
if (!Number.isFinite(value)) {
|
|
30
|
+
return { key, value: { stringValue: String(value) } };
|
|
31
|
+
}
|
|
32
|
+
return Number.isSafeInteger(value) ? { key, value: { intValue: String(value) } } : { key, value: { doubleValue: value } };
|
|
33
|
+
}
|
|
34
|
+
return { key, value: { stringValue: value } };
|
|
35
|
+
};
|
|
36
|
+
const mergeHeaders = (defaults, overrides, token) => {
|
|
37
|
+
const merged = {};
|
|
38
|
+
const seen = /* @__PURE__ */ new Map();
|
|
39
|
+
const put = (name, value) => {
|
|
40
|
+
const lower = name.toLowerCase();
|
|
41
|
+
const existing = seen.get(lower);
|
|
42
|
+
if (existing === void 0) {
|
|
43
|
+
seen.set(lower, name);
|
|
44
|
+
merged[name] = value;
|
|
45
|
+
} else {
|
|
46
|
+
merged[existing] = value;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
for (const [name, value] of Object.entries(defaults)) {
|
|
50
|
+
put(name, value);
|
|
51
|
+
}
|
|
52
|
+
for (const [name, value] of Object.entries(overrides ?? {})) {
|
|
53
|
+
put(name, value);
|
|
54
|
+
}
|
|
55
|
+
if (token !== void 0 && token.length > 0) {
|
|
56
|
+
put("authorization", `Bearer ${token}`);
|
|
57
|
+
}
|
|
58
|
+
return merged;
|
|
59
|
+
};
|
|
60
|
+
const wrapResourceSpans = (span, scopeName, serviceName) => {
|
|
61
|
+
return {
|
|
62
|
+
resourceSpans: [
|
|
63
|
+
{
|
|
64
|
+
resource: { attributes: [encodeAttribute("service.name", serviceName)] },
|
|
65
|
+
scopeSpans: [{ scope: { name: scopeName }, spans: [span] }]
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
const wrapResourceLogs = (logRecord, scopeName, serviceName) => {
|
|
71
|
+
return {
|
|
72
|
+
resourceLogs: [
|
|
73
|
+
{
|
|
74
|
+
resource: { attributes: [encodeAttribute("service.name", serviceName)] },
|
|
75
|
+
scopeLogs: [{ logRecords: [logRecord], scope: { name: scopeName } }]
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export { OTLP_SEVERITY as O, wrapResourceLogs as a, buildTraceparent as b, otlpUnixNano as c, encodeAttribute as e, mergeHeaders as m, otlpRandomHex as o, wrapResourceSpans as w };
|