@qlever-llc/trellis 0.10.11 → 0.10.12
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/esm/errors/TrellisError.d.ts +3 -3
- package/esm/errors/TrellisError.js +3 -3
- package/esm/server/internal_jobs/job-manager.d.ts.map +1 -1
- package/esm/server/internal_jobs/job-manager.js +32 -1
- package/esm/server/runtime.d.ts +3 -0
- package/esm/server/runtime.d.ts.map +1 -1
- package/esm/server/service.d.ts +15 -0
- package/esm/server/service.d.ts.map +1 -1
- package/esm/server/service.js +8 -0
- package/esm/server.d.ts.map +1 -1
- package/esm/server.js +54 -6
- package/esm/service/deno.d.ts +1 -1
- package/esm/service/deno.d.ts.map +1 -1
- package/esm/service/mod.d.ts +1 -1
- package/esm/service/mod.d.ts.map +1 -1
- package/esm/service/node.d.ts +1 -1
- package/esm/service/node.d.ts.map +1 -1
- package/esm/service/outbox_inbox.d.ts.map +1 -1
- package/esm/service/outbox_inbox.js +14 -0
- package/esm/telemetry/core.d.ts.map +1 -1
- package/esm/telemetry/core.js +1 -1
- package/esm/telemetry/env.d.ts.map +1 -1
- package/esm/telemetry/env.js +6 -1
- package/esm/telemetry/init.d.ts +3 -0
- package/esm/telemetry/init.d.ts.map +1 -0
- package/esm/telemetry/init.js +7 -0
- package/esm/telemetry/metrics.d.ts +34 -0
- package/esm/telemetry/metrics.d.ts.map +1 -0
- package/esm/telemetry/metrics.js +181 -0
- package/esm/telemetry/mod.d.ts +3 -0
- package/esm/telemetry/mod.d.ts.map +1 -1
- package/esm/telemetry/mod.js +2 -0
- package/esm/telemetry/runtime.d.ts +2 -0
- package/esm/telemetry/runtime.d.ts.map +1 -0
- package/esm/telemetry/runtime.js +134 -0
- package/esm/telemetry.d.ts +3 -0
- package/esm/telemetry.d.ts.map +1 -0
- package/esm/telemetry.js +2 -0
- package/esm/transfer.d.ts.map +1 -1
- package/esm/transfer.js +27 -16
- package/esm/trellis.d.ts.map +1 -1
- package/esm/trellis.js +460 -56
- package/package.json +7 -5
- package/script/errors/TrellisError.d.ts +3 -3
- package/script/errors/TrellisError.js +3 -3
- package/script/server/internal_jobs/job-manager.d.ts.map +1 -1
- package/script/server/internal_jobs/job-manager.js +32 -1
- package/script/server/runtime.d.ts +3 -0
- package/script/server/runtime.d.ts.map +1 -1
- package/script/server/service.d.ts +15 -0
- package/script/server/service.d.ts.map +1 -1
- package/script/server/service.js +8 -0
- package/script/server.d.ts.map +1 -1
- package/script/server.js +54 -6
- package/script/service/deno.d.ts +1 -1
- package/script/service/deno.d.ts.map +1 -1
- package/script/service/mod.d.ts +1 -1
- package/script/service/mod.d.ts.map +1 -1
- package/script/service/node.d.ts +1 -1
- package/script/service/node.d.ts.map +1 -1
- package/script/service/outbox_inbox.d.ts.map +1 -1
- package/script/service/outbox_inbox.js +14 -0
- package/script/telemetry/core.d.ts.map +1 -1
- package/script/telemetry/core.js +1 -1
- package/script/telemetry/env.d.ts.map +1 -1
- package/script/telemetry/env.js +6 -1
- package/script/telemetry/init.d.ts +3 -0
- package/script/telemetry/init.d.ts.map +1 -0
- package/script/telemetry/init.js +10 -0
- package/script/telemetry/metrics.d.ts +34 -0
- package/script/telemetry/metrics.d.ts.map +1 -0
- package/script/telemetry/metrics.js +186 -0
- package/script/telemetry/mod.d.ts +3 -0
- package/script/telemetry/mod.d.ts.map +1 -1
- package/script/telemetry/mod.js +7 -1
- package/script/telemetry/runtime.d.ts +2 -0
- package/script/telemetry/runtime.d.ts.map +1 -0
- package/script/telemetry/runtime.js +137 -0
- package/script/telemetry.d.ts +3 -0
- package/script/telemetry.d.ts.map +1 -0
- package/script/telemetry.js +18 -0
- package/script/transfer.d.ts.map +1 -1
- package/script/transfer.js +28 -17
- package/script/trellis.d.ts.map +1 -1
- package/script/trellis.js +490 -86
- package/src/errors/TrellisError.ts +4 -4
- package/src/server/internal_jobs/job-manager.ts +35 -5
- package/src/server/runtime.ts +4 -0
- package/src/server/service.ts +27 -0
- package/src/server.ts +66 -11
- package/src/service/deno.ts +1 -0
- package/src/service/mod.ts +1 -0
- package/src/service/node.ts +1 -0
- package/src/service/outbox_inbox.ts +14 -0
- package/src/telemetry/core.ts +1 -1
- package/src/telemetry/env.ts +5 -1
- package/src/telemetry/init.ts +8 -0
- package/src/telemetry/metrics.ts +294 -0
- package/src/telemetry/mod.ts +7 -0
- package/src/telemetry/runtime.ts +218 -0
- package/src/telemetry.ts +2 -0
- package/src/transfer.ts +69 -30
- package/src/trellis.ts +487 -88
- package/esm/tracing.d.ts +0 -5
- package/esm/tracing.d.ts.map +0 -1
- package/esm/tracing.js +0 -8
- package/script/tracing.d.ts +0 -5
- package/script/tracing.d.ts.map +0 -1
- package/script/tracing.js +0 -27
- package/src/tracing.ts +0 -28
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Base class for all Trellis-specific errors.
|
|
3
|
-
* Extends BaseError and relies on the traceId getter being configured via
|
|
3
|
+
* Extends BaseError and relies on the traceId getter being configured via initTelemetry.
|
|
4
4
|
*/
|
|
5
5
|
import { BaseError, type BaseErrorSchema } from "@qlever-llc/result";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Abstract base class for Trellis errors.
|
|
9
|
-
* Trellis errors automatically include traceId when
|
|
9
|
+
* Trellis errors automatically include traceId when initTelemetry() has been called
|
|
10
10
|
* and a span is active in the current context.
|
|
11
11
|
*
|
|
12
|
-
* The traceId integration is configured by the
|
|
12
|
+
* The traceId integration is configured by the telemetry module's initTelemetry() function,
|
|
13
13
|
* which sets up BaseError.traceIdGetter to retrieve the traceId from the active span.
|
|
14
14
|
*/
|
|
15
15
|
export abstract class TrellisError<
|
|
16
16
|
TData extends BaseErrorSchema = BaseErrorSchema,
|
|
17
17
|
> extends BaseError<TData> {
|
|
18
18
|
// TrellisError inherits getTraceId() from BaseError which uses the static traceIdGetter.
|
|
19
|
-
// The traceIdGetter is configured by
|
|
19
|
+
// The traceIdGetter is configured by initTelemetry() in the telemetry module.
|
|
20
20
|
}
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
createMapCarrier,
|
|
5
5
|
injectTraceContext,
|
|
6
6
|
} from "../../telemetry/carrier.js";
|
|
7
|
+
import { recordTrellisError } from "../../telemetry/mod.js";
|
|
7
8
|
|
|
8
9
|
import {
|
|
9
10
|
ActiveJob,
|
|
@@ -103,11 +104,22 @@ export class JobManager<TPayload = unknown, TResult = unknown> {
|
|
|
103
104
|
): Promise<void> {
|
|
104
105
|
const binding = this.#getQueueBinding(type);
|
|
105
106
|
const headers = headersFromJobContext(event.context);
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
107
|
+
try {
|
|
108
|
+
await this.#context.nc.publish(
|
|
109
|
+
`${binding.publishPrefix}.${jobId}.${event.eventType}`,
|
|
110
|
+
new TextEncoder().encode(JSON.stringify(event)),
|
|
111
|
+
{ headers },
|
|
112
|
+
);
|
|
113
|
+
} catch (error) {
|
|
114
|
+
recordTrellisError(error, {
|
|
115
|
+
surface: "job",
|
|
116
|
+
direction: "worker",
|
|
117
|
+
operation: type,
|
|
118
|
+
phase: "publish",
|
|
119
|
+
messagingSystem: "nats",
|
|
120
|
+
});
|
|
121
|
+
throw error;
|
|
122
|
+
}
|
|
111
123
|
}
|
|
112
124
|
|
|
113
125
|
async create(
|
|
@@ -247,6 +259,12 @@ export class JobManager<TPayload = unknown, TResult = unknown> {
|
|
|
247
259
|
if (error instanceof JobProcessError) {
|
|
248
260
|
const detail = error.message;
|
|
249
261
|
if (error.kind === "retryable") {
|
|
262
|
+
recordTrellisError(error, {
|
|
263
|
+
surface: "job",
|
|
264
|
+
direction: "worker",
|
|
265
|
+
operation: job.type,
|
|
266
|
+
phase: "handler_result",
|
|
267
|
+
});
|
|
250
268
|
await this.#publishJobEvent(job.type, job.id, {
|
|
251
269
|
jobId: job.id,
|
|
252
270
|
service: job.service,
|
|
@@ -262,6 +280,12 @@ export class JobManager<TPayload = unknown, TResult = unknown> {
|
|
|
262
280
|
return { outcome: "retry", tries, error: detail };
|
|
263
281
|
}
|
|
264
282
|
|
|
283
|
+
recordTrellisError(error, {
|
|
284
|
+
surface: "job",
|
|
285
|
+
direction: "worker",
|
|
286
|
+
operation: job.type,
|
|
287
|
+
phase: "handler_result",
|
|
288
|
+
});
|
|
265
289
|
await this.#publishJobEvent(job.type, job.id, {
|
|
266
290
|
jobId: job.id,
|
|
267
291
|
service: job.service,
|
|
@@ -277,6 +301,12 @@ export class JobManager<TPayload = unknown, TResult = unknown> {
|
|
|
277
301
|
return { outcome: "failed", tries, error: detail };
|
|
278
302
|
}
|
|
279
303
|
|
|
304
|
+
recordTrellisError(error, {
|
|
305
|
+
surface: "job",
|
|
306
|
+
direction: "worker",
|
|
307
|
+
operation: job.type,
|
|
308
|
+
phase: "runtime",
|
|
309
|
+
});
|
|
280
310
|
throw error;
|
|
281
311
|
}
|
|
282
312
|
}
|
package/src/server/runtime.ts
CHANGED
|
@@ -20,8 +20,12 @@ export type NatsCredsAuthenticatorFn = (creds: Uint8Array) => unknown;
|
|
|
20
20
|
|
|
21
21
|
export type ReadFileSyncFn = (path: string) => Uint8Array;
|
|
22
22
|
|
|
23
|
+
/** Initializes telemetry for a service runtime. */
|
|
24
|
+
export type InitTelemetryFn = (serviceName: string) => void;
|
|
25
|
+
|
|
23
26
|
export type TrellisServiceRuntimeDeps = {
|
|
24
27
|
connect: NatsConnectFn;
|
|
25
28
|
credsAuthenticator?: NatsCredsAuthenticatorFn;
|
|
26
29
|
readFileSync?: ReadFileSyncFn;
|
|
30
|
+
initTelemetry?: InitTelemetryFn;
|
|
27
31
|
};
|
package/src/server/service.ts
CHANGED
|
@@ -128,6 +128,7 @@ import {
|
|
|
128
128
|
observeNatsTrellisConnection,
|
|
129
129
|
type TrellisConnection,
|
|
130
130
|
} from "../connection.js";
|
|
131
|
+
import { initTelemetry } from "../telemetry/init.js";
|
|
131
132
|
|
|
132
133
|
type ExtraNatsConnectOpts = Omit<
|
|
133
134
|
NatsConnectOpts,
|
|
@@ -431,6 +432,7 @@ async function loadDefaultServiceRuntimeDeps(): Promise<
|
|
|
431
432
|
> {
|
|
432
433
|
const transport = await loadDefaultRuntimeTransport();
|
|
433
434
|
return {
|
|
435
|
+
initTelemetry,
|
|
434
436
|
connect: (
|
|
435
437
|
{ servers, token, authenticator, inboxPrefix, ...extraOptions },
|
|
436
438
|
) =>
|
|
@@ -444,6 +446,12 @@ async function loadDefaultServiceRuntimeDeps(): Promise<
|
|
|
444
446
|
};
|
|
445
447
|
}
|
|
446
448
|
|
|
449
|
+
function automaticTelemetryEnabled(
|
|
450
|
+
telemetry: TrellisServiceConnectTelemetryOpts | undefined,
|
|
451
|
+
): boolean {
|
|
452
|
+
return telemetry !== false && telemetry?.enabled !== false;
|
|
453
|
+
}
|
|
454
|
+
|
|
447
455
|
const ServiceBootstrapReadySchema = Type.Object({
|
|
448
456
|
status: Type.Literal("ready"),
|
|
449
457
|
serverNow: Type.Integer(),
|
|
@@ -871,9 +879,20 @@ export type TrellisServiceConnectOpts<
|
|
|
871
879
|
contract: ServiceContract<TOwnedApi, TTrellisApi>;
|
|
872
880
|
name: string;
|
|
873
881
|
sessionKeySeed: string;
|
|
882
|
+
/**
|
|
883
|
+
* Controls automatic telemetry initialization for this service connection.
|
|
884
|
+
* Enabled by default; pass `false` or `{ enabled: false }` to disable it.
|
|
885
|
+
*/
|
|
886
|
+
telemetry?: TrellisServiceConnectTelemetryOpts;
|
|
874
887
|
server?: TrellisServiceServerOpts;
|
|
875
888
|
};
|
|
876
889
|
|
|
890
|
+
/** Controls automatic telemetry initialization for `TrellisService.connect()`. */
|
|
891
|
+
export type TrellisServiceConnectTelemetryOpts = false | {
|
|
892
|
+
/** Whether automatic telemetry initialization is enabled. Defaults to `true`. */
|
|
893
|
+
enabled?: boolean;
|
|
894
|
+
};
|
|
895
|
+
|
|
877
896
|
type ServiceKvFacade<TKv extends ContractKvMetadata> = {
|
|
878
897
|
[K in keyof TKv]: TKv[K]["required"] extends false
|
|
879
898
|
? TypedKV<TKv[K]["schema"]> | undefined
|
|
@@ -1760,6 +1779,11 @@ export type TrellisServiceConnectArgs<
|
|
|
1760
1779
|
contract: TContract;
|
|
1761
1780
|
name: string;
|
|
1762
1781
|
sessionKeySeed: string;
|
|
1782
|
+
/**
|
|
1783
|
+
* Controls automatic telemetry initialization for this service connection.
|
|
1784
|
+
* Enabled by default; pass `false` or `{ enabled: false }` to disable it.
|
|
1785
|
+
*/
|
|
1786
|
+
telemetry?: TrellisServiceConnectTelemetryOpts;
|
|
1763
1787
|
server?: TrellisServiceServerOpts;
|
|
1764
1788
|
};
|
|
1765
1789
|
|
|
@@ -3142,6 +3166,9 @@ export class TrellisService<
|
|
|
3142
3166
|
...(await loadDefaultServiceRuntimeDeps()),
|
|
3143
3167
|
...deps,
|
|
3144
3168
|
} satisfies TrellisServiceRuntimeDeps;
|
|
3169
|
+
if (automaticTelemetryEnabled(args.telemetry)) {
|
|
3170
|
+
runtimeDeps.initTelemetry?.(args.name);
|
|
3171
|
+
}
|
|
3145
3172
|
const auth = await createAuth({ sessionKeySeed: args.sessionKeySeed });
|
|
3146
3173
|
const bootstrapLog = resolveServiceLogger(args.server?.log);
|
|
3147
3174
|
const bootstrap = await fetchServiceBootstrapInfo({
|
package/src/server.ts
CHANGED
|
@@ -25,6 +25,10 @@ import {
|
|
|
25
25
|
import { RemoteError } from "./errors/RemoteError.js";
|
|
26
26
|
import type { LoggerLike } from "./globals.js";
|
|
27
27
|
import { serverLogger } from "./server_logger.js";
|
|
28
|
+
import {
|
|
29
|
+
recordTrellisError,
|
|
30
|
+
type TrellisErrorMetricAttributes,
|
|
31
|
+
} from "./telemetry/mod.js";
|
|
28
32
|
import {
|
|
29
33
|
type AcceptedOperation,
|
|
30
34
|
annotateHandlerBoundaryError,
|
|
@@ -220,6 +224,18 @@ function traceIdFromTraceparent(
|
|
|
220
224
|
return traceId;
|
|
221
225
|
}
|
|
222
226
|
|
|
227
|
+
function recordOperationServerError(
|
|
228
|
+
error: unknown,
|
|
229
|
+
attributes: TrellisErrorMetricAttributes,
|
|
230
|
+
): void {
|
|
231
|
+
recordTrellisError(error, {
|
|
232
|
+
messagingSystem: "nats",
|
|
233
|
+
surface: "operation",
|
|
234
|
+
direction: "server",
|
|
235
|
+
...attributes,
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
|
|
223
239
|
export class TrellisServiceRuntime extends Trellis<TrellisAPI, TrellisMode> {
|
|
224
240
|
#version?: string;
|
|
225
241
|
#log: LoggerLike;
|
|
@@ -937,6 +953,10 @@ export class TrellisServiceRuntime extends Trellis<TrellisAPI, TrellisMode> {
|
|
|
937
953
|
const trellisError = error instanceof BaseError
|
|
938
954
|
? error
|
|
939
955
|
: new UnexpectedError({ cause: error });
|
|
956
|
+
recordOperationServerError(trellisError, {
|
|
957
|
+
operation,
|
|
958
|
+
phase: "control",
|
|
959
|
+
});
|
|
940
960
|
msg.respond(JSON.stringify({
|
|
941
961
|
kind: "error",
|
|
942
962
|
error: trellisError.toSerializable(),
|
|
@@ -1539,6 +1559,10 @@ export class TrellisServiceRuntime extends Trellis<TrellisAPI, TrellisMode> {
|
|
|
1539
1559
|
const validated = await authenticate(msg, true);
|
|
1540
1560
|
const value = validated.take();
|
|
1541
1561
|
if (isErr(value)) {
|
|
1562
|
+
recordOperationServerError(value.error, {
|
|
1563
|
+
operation: String(operation),
|
|
1564
|
+
phase: "start",
|
|
1565
|
+
});
|
|
1542
1566
|
this.respondWithError(msg, value.error);
|
|
1543
1567
|
continue;
|
|
1544
1568
|
}
|
|
@@ -1546,15 +1570,20 @@ export class TrellisServiceRuntime extends Trellis<TrellisAPI, TrellisMode> {
|
|
|
1546
1570
|
let transferSession: RuntimeOperationTransferSession | undefined;
|
|
1547
1571
|
if (ctx.transfer) {
|
|
1548
1572
|
if (!this.#transferSupport) {
|
|
1573
|
+
const error = new UnexpectedError({
|
|
1574
|
+
cause: new Error(
|
|
1575
|
+
`Operation '${
|
|
1576
|
+
String(operation)
|
|
1577
|
+
}' declared transfer support but no runtime transfer support is configured`,
|
|
1578
|
+
),
|
|
1579
|
+
});
|
|
1580
|
+
recordOperationServerError(error, {
|
|
1581
|
+
operation: String(operation),
|
|
1582
|
+
phase: "start",
|
|
1583
|
+
});
|
|
1549
1584
|
this.respondWithError(
|
|
1550
1585
|
msg,
|
|
1551
|
-
|
|
1552
|
-
cause: new Error(
|
|
1553
|
-
`Operation '${
|
|
1554
|
-
String(operation)
|
|
1555
|
-
}' declared transfer support but no runtime transfer support is configured`,
|
|
1556
|
-
),
|
|
1557
|
-
}),
|
|
1586
|
+
error,
|
|
1558
1587
|
);
|
|
1559
1588
|
continue;
|
|
1560
1589
|
}
|
|
@@ -1566,6 +1595,10 @@ export class TrellisServiceRuntime extends Trellis<TrellisAPI, TrellisMode> {
|
|
|
1566
1595
|
"key",
|
|
1567
1596
|
).take();
|
|
1568
1597
|
if (isErr(key)) {
|
|
1598
|
+
recordOperationServerError(key.error, {
|
|
1599
|
+
operation: String(operation),
|
|
1600
|
+
phase: "start",
|
|
1601
|
+
});
|
|
1569
1602
|
this.respondWithError(msg, key.error);
|
|
1570
1603
|
continue;
|
|
1571
1604
|
}
|
|
@@ -1575,6 +1608,10 @@ export class TrellisServiceRuntime extends Trellis<TrellisAPI, TrellisMode> {
|
|
|
1575
1608
|
ctx.transfer.contentType,
|
|
1576
1609
|
).take();
|
|
1577
1610
|
if (isErr(contentType)) {
|
|
1611
|
+
recordOperationServerError(contentType.error, {
|
|
1612
|
+
operation: String(operation),
|
|
1613
|
+
phase: "start",
|
|
1614
|
+
});
|
|
1578
1615
|
this.respondWithError(msg, contentType.error);
|
|
1579
1616
|
continue;
|
|
1580
1617
|
}
|
|
@@ -1584,6 +1621,10 @@ export class TrellisServiceRuntime extends Trellis<TrellisAPI, TrellisMode> {
|
|
|
1584
1621
|
ctx.transfer.metadata,
|
|
1585
1622
|
).take();
|
|
1586
1623
|
if (isErr(metadata)) {
|
|
1624
|
+
recordOperationServerError(metadata.error, {
|
|
1625
|
+
operation: String(operation),
|
|
1626
|
+
phase: "start",
|
|
1627
|
+
});
|
|
1587
1628
|
this.respondWithError(msg, metadata.error);
|
|
1588
1629
|
continue;
|
|
1589
1630
|
}
|
|
@@ -1601,6 +1642,10 @@ export class TrellisServiceRuntime extends Trellis<TrellisAPI, TrellisMode> {
|
|
|
1601
1642
|
...(metadata !== undefined ? { metadata } : {}),
|
|
1602
1643
|
}).take();
|
|
1603
1644
|
if (isErr(openedTransferValue)) {
|
|
1645
|
+
recordOperationServerError(openedTransferValue.error, {
|
|
1646
|
+
operation: String(operation),
|
|
1647
|
+
phase: "start",
|
|
1648
|
+
});
|
|
1604
1649
|
this.respondWithError(msg, openedTransferValue.error);
|
|
1605
1650
|
continue;
|
|
1606
1651
|
}
|
|
@@ -1694,7 +1739,7 @@ export class TrellisServiceRuntime extends Trellis<TrellisAPI, TrellisMode> {
|
|
|
1694
1739
|
? handlerResult.take()
|
|
1695
1740
|
: handlerResult;
|
|
1696
1741
|
if (isErr(handlerOutcome)) {
|
|
1697
|
-
|
|
1742
|
+
const error = annotateHandlerBoundaryError(
|
|
1698
1743
|
handlerOutcome.error,
|
|
1699
1744
|
{
|
|
1700
1745
|
operation: String(operation),
|
|
@@ -1704,7 +1749,12 @@ export class TrellisServiceRuntime extends Trellis<TrellisAPI, TrellisMode> {
|
|
|
1704
1749
|
contractDigest: this.contractDigest,
|
|
1705
1750
|
traceId: operationContext.traceId,
|
|
1706
1751
|
},
|
|
1707
|
-
)
|
|
1752
|
+
);
|
|
1753
|
+
recordOperationServerError(error, {
|
|
1754
|
+
operation: String(operation),
|
|
1755
|
+
phase: "handler_result",
|
|
1756
|
+
});
|
|
1757
|
+
await op.fail(error);
|
|
1708
1758
|
return;
|
|
1709
1759
|
}
|
|
1710
1760
|
|
|
@@ -1724,14 +1774,19 @@ export class TrellisServiceRuntime extends Trellis<TrellisAPI, TrellisMode> {
|
|
|
1724
1774
|
await op.complete(handlerOutcome);
|
|
1725
1775
|
}
|
|
1726
1776
|
} catch (cause) {
|
|
1727
|
-
|
|
1777
|
+
const error = annotateHandlerBoundaryError(cause, {
|
|
1728
1778
|
operation: String(operation),
|
|
1729
1779
|
requestId: operationContext.requestId,
|
|
1730
1780
|
service: this.name,
|
|
1731
1781
|
contractId: this.contractId,
|
|
1732
1782
|
contractDigest: this.contractDigest,
|
|
1733
1783
|
traceId: operationContext.traceId,
|
|
1734
|
-
})
|
|
1784
|
+
});
|
|
1785
|
+
recordOperationServerError(error, {
|
|
1786
|
+
operation: String(operation),
|
|
1787
|
+
phase: "handler_throw",
|
|
1788
|
+
});
|
|
1789
|
+
await op.fail(error);
|
|
1735
1790
|
}
|
|
1736
1791
|
})();
|
|
1737
1792
|
}
|
package/src/service/deno.ts
CHANGED
package/src/service/mod.ts
CHANGED
package/src/service/node.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { type AsyncResult, type BaseError, isErr } from "@qlever-llc/result";
|
|
|
3
3
|
import { type StaticDecode, Type } from "typebox";
|
|
4
4
|
import type { PreparedTrellisEvent, Trellis } from "../trellis.js";
|
|
5
5
|
import { TypedKV } from "../kv.js";
|
|
6
|
+
import { recordTrellisError } from "../telemetry/mod.js";
|
|
6
7
|
|
|
7
8
|
export type OutboxMessageState = "pending" | "dispatched" | "failed";
|
|
8
9
|
|
|
@@ -646,6 +647,12 @@ export class OutboxDispatcher {
|
|
|
646
647
|
retryDelayMs: this.#retryDelayMs(),
|
|
647
648
|
});
|
|
648
649
|
} catch (error) {
|
|
650
|
+
recordTrellisError(error, {
|
|
651
|
+
surface: "outbox",
|
|
652
|
+
direction: "dispatcher",
|
|
653
|
+
operation: "batch",
|
|
654
|
+
phase: "dispatch",
|
|
655
|
+
});
|
|
649
656
|
this.#scheduleRetryWakeup();
|
|
650
657
|
try {
|
|
651
658
|
this.#options.onError?.(error);
|
|
@@ -693,6 +700,13 @@ export async function dispatchOutbox(
|
|
|
693
700
|
);
|
|
694
701
|
const value = result.take();
|
|
695
702
|
if (isErr(value)) {
|
|
703
|
+
recordTrellisError(value.error, {
|
|
704
|
+
surface: "outbox",
|
|
705
|
+
direction: "dispatcher",
|
|
706
|
+
operation: message.event,
|
|
707
|
+
phase: "publish",
|
|
708
|
+
messagingSystem: "nats",
|
|
709
|
+
});
|
|
696
710
|
failed += 1;
|
|
697
711
|
await repository.markFailed(message.id, {
|
|
698
712
|
error: value.error.message,
|
package/src/telemetry/core.ts
CHANGED
package/src/telemetry/env.ts
CHANGED
|
@@ -13,7 +13,11 @@ type ProcessLike = {
|
|
|
13
13
|
export function getEnv(key: string): string | undefined {
|
|
14
14
|
const deno = dntShim.dntGlobalThis as typeof dntShim.dntGlobalThis & { Deno?: DenoLike };
|
|
15
15
|
if (deno.Deno?.env?.get) {
|
|
16
|
-
|
|
16
|
+
try {
|
|
17
|
+
return deno.Deno.env.get(key);
|
|
18
|
+
} catch {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
17
21
|
}
|
|
18
22
|
|
|
19
23
|
const processGlobal = dntShim.dntGlobalThis as typeof dntShim.dntGlobalThis & {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { configureErrorTraceId } from "./result.js";
|
|
2
|
+
import { initTelemetryRuntime } from "./runtime.js";
|
|
3
|
+
|
|
4
|
+
/** Initializes Trellis telemetry for a service runtime. */
|
|
5
|
+
export function initTelemetry(serviceName: string): void {
|
|
6
|
+
configureErrorTraceId();
|
|
7
|
+
initTelemetryRuntime(serviceName);
|
|
8
|
+
}
|