@event-driven-io/emmett 0.43.0-beta.22 → 0.43.0-beta.24
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.cjs +289 -311
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +108 -114
- package/dist/index.d.ts +108 -114
- package/dist/index.js +285 -306
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -619,6 +619,11 @@ const bigIntReplacer = (_key, value) => {
|
|
|
619
619
|
const dateReplacer = (_key, value) => {
|
|
620
620
|
return value instanceof Date ? value.toISOString() : value;
|
|
621
621
|
};
|
|
622
|
+
const errorReplacer = (_key, value) => value instanceof Error ? {
|
|
623
|
+
type: value.constructor.name || "error",
|
|
624
|
+
message: value.message,
|
|
625
|
+
stack: value.stack
|
|
626
|
+
} : value;
|
|
622
627
|
const isFirstLetterNumeric = (str) => {
|
|
623
628
|
const c = str.charCodeAt(0);
|
|
624
629
|
return c >= 48 && c <= 57;
|
|
@@ -660,11 +665,12 @@ const composeJSONRevivers = (...revivers) => {
|
|
|
660
665
|
if (filteredRevivers.length === 0) return void 0;
|
|
661
666
|
return (key, value, context) => filteredRevivers.reduce((accValue, reviver) => reviver(key, accValue, context), value);
|
|
662
667
|
};
|
|
663
|
-
const JSONReplacer = (opts) => composeJSONReplacers(opts?.replacer, opts?.failOnBigIntSerialization !== true ? JSONReplacers.bigInt : void 0, opts?.useDefaultDateSerialization !== true ? JSONReplacers.date : void 0);
|
|
668
|
+
const JSONReplacer = (opts) => composeJSONReplacers(opts?.replacer, opts?.failOnBigIntSerialization !== true ? JSONReplacers.bigInt : void 0, opts?.useDefaultDateSerialization !== true ? JSONReplacers.date : void 0, opts?.skipErrorSerialization !== true ? JSONReplacers.error : void 0);
|
|
664
669
|
const JSONReviver = (opts) => composeJSONRevivers(opts?.reviver, opts?.parseBigInts === true ? JSONRevivers.bigInt : void 0, opts?.parseDates === true ? JSONRevivers.date : void 0);
|
|
665
670
|
const JSONReplacers = {
|
|
666
671
|
bigInt: bigIntReplacer,
|
|
667
|
-
date: dateReplacer
|
|
672
|
+
date: dateReplacer,
|
|
673
|
+
error: errorReplacer
|
|
668
674
|
};
|
|
669
675
|
const JSONRevivers = {
|
|
670
676
|
bigInt: bigIntReviver,
|
|
@@ -673,8 +679,19 @@ const JSONRevivers = {
|
|
|
673
679
|
const jsonSerializer = (options) => {
|
|
674
680
|
const defaultReplacer = JSONReplacer(options);
|
|
675
681
|
const defaultReviver = JSONReviver(options);
|
|
682
|
+
const defaultFormat = options?.format ?? "compact";
|
|
683
|
+
const defaultSafe = options?.safe ?? false;
|
|
676
684
|
return {
|
|
677
|
-
serialize: (object, serializerOptions) =>
|
|
685
|
+
serialize: (object, serializerOptions) => {
|
|
686
|
+
const replacer = serializerOptions ? JSONReplacer(serializerOptions) : defaultReplacer;
|
|
687
|
+
const indent = (serializerOptions?.format ?? defaultFormat) === "pretty" ? 2 : void 0;
|
|
688
|
+
if (serializerOptions?.safe ?? defaultSafe) try {
|
|
689
|
+
return JSON.stringify(object, replacer, indent);
|
|
690
|
+
} catch (e) {
|
|
691
|
+
return `{"__serializationError":${JSON.stringify(String(e))}}`;
|
|
692
|
+
}
|
|
693
|
+
return JSON.stringify(object, replacer, indent);
|
|
694
|
+
},
|
|
678
695
|
deserialize: (payload, deserializerOptions) => JSON.parse(payload, deserializerOptions ? JSONReviver(deserializerOptions) : defaultReviver)
|
|
679
696
|
};
|
|
680
697
|
};
|
|
@@ -978,6 +995,15 @@ const getInMemoryDatabase = () => {
|
|
|
978
995
|
} };
|
|
979
996
|
};
|
|
980
997
|
|
|
998
|
+
//#endregion
|
|
999
|
+
//#region src/processors/checkpoints.ts
|
|
1000
|
+
const ProcessorCheckpoint = (checkpoint) => checkpoint;
|
|
1001
|
+
const bigIntProcessorCheckpoint = (value) => bigInt.toNormalizedString(value);
|
|
1002
|
+
const parseBigIntProcessorCheckpoint = (value) => BigInt(value);
|
|
1003
|
+
const getCheckpoint = (message) => {
|
|
1004
|
+
return message.metadata.checkpoint;
|
|
1005
|
+
};
|
|
1006
|
+
|
|
981
1007
|
//#endregion
|
|
982
1008
|
//#region src/observability/attributes.ts
|
|
983
1009
|
const EmmettAttributes = {
|
|
@@ -1065,281 +1091,21 @@ const MessagingSystemName = "emmett";
|
|
|
1065
1091
|
|
|
1066
1092
|
//#endregion
|
|
1067
1093
|
//#region src/observability/options.ts
|
|
1068
|
-
const
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
attributeTarget: options?.observability?.attributeTarget ?? parent?.observability?.attributeTarget ?? "both"
|
|
1073
|
-
});
|
|
1074
|
-
const resolveWorkflowObservability = (options, parent) => ({
|
|
1075
|
-
tracer: options?.observability?.tracer ?? parent?.observability?.tracer ?? (0, _event_driven_io_almanac.noopTracer)(),
|
|
1076
|
-
meter: options?.observability?.meter ?? parent?.observability?.meter ?? (0, _event_driven_io_almanac.noopMeter)(),
|
|
1077
|
-
propagation: options?.observability?.propagation ?? parent?.observability?.propagation ?? "links",
|
|
1078
|
-
attributeTarget: options?.observability?.attributeTarget ?? parent?.observability?.attributeTarget ?? "both",
|
|
1079
|
-
includeMessagePayloads: options?.observability?.includeMessagePayloads ?? parent?.observability?.includeMessagePayloads ?? false
|
|
1080
|
-
});
|
|
1081
|
-
|
|
1082
|
-
//#endregion
|
|
1083
|
-
//#region src/observability/tracer.ts
|
|
1084
|
-
const tracer = () => {};
|
|
1085
|
-
const LogLevel = {
|
|
1086
|
-
DISABLED: "DISABLED",
|
|
1087
|
-
INFO: "INFO",
|
|
1088
|
-
LOG: "LOG",
|
|
1089
|
-
WARN: "WARN",
|
|
1090
|
-
ERROR: "ERROR"
|
|
1091
|
-
};
|
|
1092
|
-
const LogStyle = {
|
|
1093
|
-
RAW: "RAW",
|
|
1094
|
-
PRETTY: "PRETTY"
|
|
1095
|
-
};
|
|
1096
|
-
const getEnvVariable = (name) => {
|
|
1097
|
-
try {
|
|
1098
|
-
if (typeof process !== "undefined" && process.env) return process.env[name];
|
|
1099
|
-
return;
|
|
1100
|
-
} catch {
|
|
1101
|
-
return;
|
|
1102
|
-
}
|
|
1103
|
-
};
|
|
1104
|
-
const shouldLog = (logLevel) => {
|
|
1105
|
-
const definedLogLevel = getEnvVariable("DUMBO_LOG_LEVEL") ?? LogLevel.ERROR;
|
|
1106
|
-
if (definedLogLevel === LogLevel.ERROR && logLevel === LogLevel.ERROR) return true;
|
|
1107
|
-
if (definedLogLevel === LogLevel.WARN && [LogLevel.ERROR, LogLevel.WARN].includes(logLevel)) return true;
|
|
1108
|
-
if (definedLogLevel === LogLevel.LOG && [
|
|
1109
|
-
LogLevel.ERROR,
|
|
1110
|
-
LogLevel.WARN,
|
|
1111
|
-
LogLevel.LOG
|
|
1112
|
-
].includes(logLevel)) return true;
|
|
1113
|
-
if (definedLogLevel === LogLevel.INFO && [
|
|
1114
|
-
LogLevel.ERROR,
|
|
1115
|
-
LogLevel.WARN,
|
|
1116
|
-
LogLevel.LOG,
|
|
1117
|
-
LogLevel.INFO
|
|
1118
|
-
].includes(logLevel)) return true;
|
|
1119
|
-
return false;
|
|
1120
|
-
};
|
|
1121
|
-
const nulloTraceEventRecorder = () => {};
|
|
1122
|
-
const getTraceEventFormatter = (logStyle, serializer) => (event) => {
|
|
1123
|
-
serializer = serializer ?? JSONSerializer.from();
|
|
1124
|
-
switch (logStyle) {
|
|
1125
|
-
case "RAW": return serializer.serialize(event);
|
|
1126
|
-
case "PRETTY": return serializer.serialize(event);
|
|
1127
|
-
}
|
|
1128
|
-
};
|
|
1129
|
-
const getTraceEventRecorder = (logLevel, logStyle) => {
|
|
1130
|
-
const format = getTraceEventFormatter(logStyle);
|
|
1131
|
-
switch (logLevel) {
|
|
1132
|
-
case "DISABLED": return nulloTraceEventRecorder;
|
|
1133
|
-
case "INFO": return (event) => console.info(format(event));
|
|
1134
|
-
case "LOG": return (event) => console.log(format(event));
|
|
1135
|
-
case "WARN": return (event) => console.warn(format(event));
|
|
1136
|
-
case "ERROR": return (event) => console.error(format(event));
|
|
1137
|
-
}
|
|
1138
|
-
};
|
|
1139
|
-
const recordTraceEvent = (logLevel, eventName, attributes) => {
|
|
1140
|
-
if (!shouldLog(LogLevel.LOG)) return;
|
|
1141
|
-
const event = {
|
|
1142
|
-
name: eventName,
|
|
1143
|
-
timestamp: (/* @__PURE__ */ new Date()).getTime(),
|
|
1144
|
-
...attributes
|
|
1094
|
+
const mergeObservabilityOptions = (options, defaults) => {
|
|
1095
|
+
const observability = defaults === void 0 ? options.observability : options.observability === void 0 ? defaults : {
|
|
1096
|
+
...defaults,
|
|
1097
|
+
...options.observability
|
|
1145
1098
|
};
|
|
1146
|
-
|
|
1147
|
-
};
|
|
1148
|
-
tracer.info = (eventName, attributes) => recordTraceEvent(LogLevel.INFO, eventName, attributes);
|
|
1149
|
-
tracer.warn = (eventName, attributes) => recordTraceEvent(LogLevel.WARN, eventName, attributes);
|
|
1150
|
-
tracer.log = (eventName, attributes) => recordTraceEvent(LogLevel.LOG, eventName, attributes);
|
|
1151
|
-
tracer.error = (eventName, attributes) => recordTraceEvent(LogLevel.ERROR, eventName, attributes);
|
|
1152
|
-
|
|
1153
|
-
//#endregion
|
|
1154
|
-
//#region src/eventStore/observability/eventStoreCollector.ts
|
|
1155
|
-
const resolveEventStoreObservability = (options, parent) => ({
|
|
1156
|
-
tracer: options?.observability?.tracer ?? parent?.observability?.tracer ?? (0, _event_driven_io_almanac.noopTracer)(),
|
|
1157
|
-
meter: options?.observability?.meter ?? parent?.observability?.meter ?? (0, _event_driven_io_almanac.noopMeter)(),
|
|
1158
|
-
attributeTarget: options?.observability?.attributeTarget ?? parent?.observability?.attributeTarget ?? "both"
|
|
1159
|
-
});
|
|
1160
|
-
const eventStoreCollector = (observability) => {
|
|
1161
|
-
const A = EmmettAttributes;
|
|
1162
|
-
const M = _event_driven_io_almanac.MessagingAttributes;
|
|
1163
|
-
const streamReadingDuration = observability.meter.histogram(EmmettMetrics.stream.readingDuration);
|
|
1164
|
-
const streamReadingSize = observability.meter.histogram(EmmettMetrics.stream.readingSize);
|
|
1165
|
-
const eventReadingCount = observability.meter.counter(EmmettMetrics.event.readingCount);
|
|
1166
|
-
const streamAppendingDuration = observability.meter.histogram(EmmettMetrics.stream.appendingDuration);
|
|
1167
|
-
const streamAppendingSize = observability.meter.histogram(EmmettMetrics.stream.appendingSize);
|
|
1168
|
-
const eventAppendingCount = observability.meter.counter(EmmettMetrics.event.appendingCount);
|
|
1099
|
+
if (observability === options.observability) return options;
|
|
1169
1100
|
return {
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
return observability.tracer.startSpan("eventStore.readStream", async (span) => {
|
|
1173
|
-
span.setAttributes({
|
|
1174
|
-
[A.eventStore.operation]: "readStream",
|
|
1175
|
-
[A.stream.name]: streamName,
|
|
1176
|
-
[M.operation.type]: "receive",
|
|
1177
|
-
[M.destination.name]: streamName,
|
|
1178
|
-
[M.system]: MessagingSystemName
|
|
1179
|
-
});
|
|
1180
|
-
let status = "success";
|
|
1181
|
-
try {
|
|
1182
|
-
const result = await fn();
|
|
1183
|
-
const events = result.events;
|
|
1184
|
-
span.setAttributes({
|
|
1185
|
-
[A.eventStore.read.status]: status,
|
|
1186
|
-
[A.eventStore.read.eventCount]: events.length,
|
|
1187
|
-
[A.eventStore.read.eventTypes]: [...new Set(events.map((e) => e.type))]
|
|
1188
|
-
});
|
|
1189
|
-
streamReadingSize.record(events.length, { [A.eventStore.read.status]: status });
|
|
1190
|
-
for (const event of events) eventReadingCount.add(1, { [A.event.type]: event.type });
|
|
1191
|
-
return result;
|
|
1192
|
-
} catch (err) {
|
|
1193
|
-
status = "failure";
|
|
1194
|
-
span.setAttributes({ [A.eventStore.read.status]: status });
|
|
1195
|
-
throw err;
|
|
1196
|
-
} finally {
|
|
1197
|
-
streamReadingDuration.record(Date.now() - start, { [A.eventStore.read.status]: status });
|
|
1198
|
-
}
|
|
1199
|
-
});
|
|
1200
|
-
},
|
|
1201
|
-
instrumentAppend: (streamName, events, fn) => {
|
|
1202
|
-
const start = Date.now();
|
|
1203
|
-
return observability.tracer.startSpan("eventStore.appendToStream", async (span) => {
|
|
1204
|
-
span.setAttributes({
|
|
1205
|
-
[A.eventStore.operation]: "appendToStream",
|
|
1206
|
-
[A.stream.name]: streamName,
|
|
1207
|
-
[A.eventStore.append.batchSize]: events.length,
|
|
1208
|
-
[M.operation.type]: "send",
|
|
1209
|
-
[M.batch.messageCount]: events.length,
|
|
1210
|
-
[M.destination.name]: streamName,
|
|
1211
|
-
[M.system]: MessagingSystemName
|
|
1212
|
-
});
|
|
1213
|
-
let status = "success";
|
|
1214
|
-
try {
|
|
1215
|
-
const result = await fn();
|
|
1216
|
-
span.setAttributes({
|
|
1217
|
-
[A.eventStore.append.status]: status,
|
|
1218
|
-
[A.stream.versionAfter]: Number(result.nextExpectedStreamVersion)
|
|
1219
|
-
});
|
|
1220
|
-
streamAppendingSize.record(events.length, { [A.eventStore.append.status]: status });
|
|
1221
|
-
for (const event of events) eventAppendingCount.add(1, { [A.event.type]: event.type });
|
|
1222
|
-
return result;
|
|
1223
|
-
} catch (err) {
|
|
1224
|
-
status = "failure";
|
|
1225
|
-
span.setAttributes({ [A.eventStore.append.status]: status });
|
|
1226
|
-
throw err;
|
|
1227
|
-
} finally {
|
|
1228
|
-
streamAppendingDuration.record(Date.now() - start, { [A.eventStore.append.status]: status });
|
|
1229
|
-
}
|
|
1230
|
-
});
|
|
1231
|
-
}
|
|
1232
|
-
};
|
|
1233
|
-
};
|
|
1234
|
-
|
|
1235
|
-
//#endregion
|
|
1236
|
-
//#region src/observability/collectors/consumerCollector.ts
|
|
1237
|
-
const consumerCollector = (observability) => {
|
|
1238
|
-
const { startScope } = (0, _event_driven_io_almanac.ObservabilityScope)({
|
|
1239
|
-
...observability,
|
|
1240
|
-
attributePrefix: "emmett"
|
|
1241
|
-
});
|
|
1242
|
-
const A = EmmettAttributes;
|
|
1243
|
-
const M = _event_driven_io_almanac.MessagingAttributes;
|
|
1244
|
-
const pollDuration = observability.meter.histogram(EmmettMetrics.consumer.pollDuration);
|
|
1245
|
-
const deliveryDuration = observability.meter.histogram(EmmettMetrics.consumer.deliveryDuration);
|
|
1246
|
-
return {
|
|
1247
|
-
tracePoll: (context, fn) => {
|
|
1248
|
-
if (observability.pollTracing === "off" || observability.pollTracing === "active" && context.batchSize === 0) return fn(_event_driven_io_almanac.noopScope);
|
|
1249
|
-
return startScope("consumer.poll", async (scope) => {
|
|
1250
|
-
scope.setAttributes({
|
|
1251
|
-
[A.scope.type]: ScopeTypes.consumer,
|
|
1252
|
-
[A.consumer.batchSize]: context.batchSize,
|
|
1253
|
-
[A.consumer.processorCount]: context.processorCount,
|
|
1254
|
-
[M.system]: MessagingSystemName,
|
|
1255
|
-
[M.operation.type]: "receive",
|
|
1256
|
-
...context.empty ? { "emmett.consumer.poll.empty": true } : {},
|
|
1257
|
-
...context.waitMs != null ? { "emmett.consumer.poll.wait_ms": context.waitMs } : {}
|
|
1258
|
-
});
|
|
1259
|
-
return fn(scope);
|
|
1260
|
-
});
|
|
1261
|
-
},
|
|
1262
|
-
recordPollMetrics: (durationMs, attrs) => {
|
|
1263
|
-
pollDuration.record(durationMs, attrs);
|
|
1264
|
-
},
|
|
1265
|
-
traceDelivery: (scope, processorId, fn) => {
|
|
1266
|
-
const start = Date.now();
|
|
1267
|
-
return scope.scope(`consumer.deliver.${processorId}`, async (child) => {
|
|
1268
|
-
try {
|
|
1269
|
-
return await fn();
|
|
1270
|
-
} catch (error) {
|
|
1271
|
-
if (error instanceof Error) child.recordException(error);
|
|
1272
|
-
throw error;
|
|
1273
|
-
} finally {
|
|
1274
|
-
deliveryDuration.record(Date.now() - start, { [A.consumer.delivery.processorId]: processorId });
|
|
1275
|
-
}
|
|
1276
|
-
}, { attributes: { [A.consumer.delivery.processorId]: processorId } });
|
|
1277
|
-
}
|
|
1278
|
-
};
|
|
1279
|
-
};
|
|
1280
|
-
|
|
1281
|
-
//#endregion
|
|
1282
|
-
//#region src/observability/collectors/workflowCollector.ts
|
|
1283
|
-
const workflowCollector = (observability) => {
|
|
1284
|
-
const { startScope } = (0, _event_driven_io_almanac.ObservabilityScope)({
|
|
1285
|
-
...observability,
|
|
1286
|
-
attributePrefix: "emmett"
|
|
1287
|
-
});
|
|
1288
|
-
const A = EmmettAttributes;
|
|
1289
|
-
const M = _event_driven_io_almanac.MessagingAttributes;
|
|
1290
|
-
const processingDuration = observability.meter.histogram(EmmettMetrics.workflow.processingDuration);
|
|
1291
|
-
return {
|
|
1292
|
-
startScope: (context, fn) => {
|
|
1293
|
-
const start = Date.now();
|
|
1294
|
-
return startScope("workflow.handle", async (scope) => {
|
|
1295
|
-
scope.setAttributes({
|
|
1296
|
-
[A.scope.type]: ScopeTypes.workflow,
|
|
1297
|
-
[A.workflow.id]: context.workflowId,
|
|
1298
|
-
[A.workflow.type]: context.workflowType,
|
|
1299
|
-
[A.workflow.inputType]: context.inputType,
|
|
1300
|
-
[M.system]: MessagingSystemName
|
|
1301
|
-
});
|
|
1302
|
-
let status = "success";
|
|
1303
|
-
try {
|
|
1304
|
-
return await fn(scope);
|
|
1305
|
-
} catch (err) {
|
|
1306
|
-
status = "failure";
|
|
1307
|
-
throw err;
|
|
1308
|
-
} finally {
|
|
1309
|
-
processingDuration.record(Date.now() - start, {
|
|
1310
|
-
[A.workflow.type]: context.workflowType,
|
|
1311
|
-
status
|
|
1312
|
-
});
|
|
1313
|
-
}
|
|
1314
|
-
}, { attributes: {
|
|
1315
|
-
[A.scope.type]: ScopeTypes.workflow,
|
|
1316
|
-
[A.workflow.type]: context.workflowType
|
|
1317
|
-
} });
|
|
1318
|
-
},
|
|
1319
|
-
recordOutputs: (scope, outputs) => {
|
|
1320
|
-
scope.setAttributes({
|
|
1321
|
-
[A.workflow.outputs]: outputs.map((o) => o.type),
|
|
1322
|
-
[A.workflow.outputsCount]: outputs.length
|
|
1323
|
-
});
|
|
1324
|
-
},
|
|
1325
|
-
recordStateRebuild: (scope, eventCount) => {
|
|
1326
|
-
scope.setAttributes({ [A.workflow.stateRebuildEventCount]: eventCount });
|
|
1327
|
-
}
|
|
1101
|
+
...options,
|
|
1102
|
+
observability
|
|
1328
1103
|
};
|
|
1329
1104
|
};
|
|
1330
1105
|
|
|
1331
|
-
//#endregion
|
|
1332
|
-
//#region src/processors/checkpoints.ts
|
|
1333
|
-
const ProcessorCheckpoint = (checkpoint) => checkpoint;
|
|
1334
|
-
const bigIntProcessorCheckpoint = (value) => bigInt.toNormalizedString(value);
|
|
1335
|
-
const parseBigIntProcessorCheckpoint = (value) => BigInt(value);
|
|
1336
|
-
const getCheckpoint = (message) => {
|
|
1337
|
-
return message.metadata.checkpoint;
|
|
1338
|
-
};
|
|
1339
|
-
|
|
1340
1106
|
//#endregion
|
|
1341
1107
|
//#region src/processors/observability/processorCollector.ts
|
|
1342
|
-
const
|
|
1108
|
+
const processorObservability = (options, parent) => ({
|
|
1343
1109
|
tracer: options?.observability?.tracer ?? parent?.observability?.tracer ?? (0, _event_driven_io_almanac.noopTracer)(),
|
|
1344
1110
|
meter: options?.observability?.meter ?? parent?.observability?.meter ?? (0, _event_driven_io_almanac.noopMeter)(),
|
|
1345
1111
|
propagation: options?.observability?.propagation ?? parent?.observability?.propagation ?? "links",
|
|
@@ -1447,9 +1213,10 @@ const defaultProcessorVersion = 1;
|
|
|
1447
1213
|
const defaultProcessorPartition = defaultTag;
|
|
1448
1214
|
const getProcessorInstanceId = (processorId) => `${processorId}:${(0, uuid.v7)()}`;
|
|
1449
1215
|
const getProjectorId = (options) => `emt:processor:projector:${options.projectionName}`;
|
|
1216
|
+
const { info, error } = _event_driven_io_almanac.LogEvent;
|
|
1450
1217
|
const reactor = (options) => {
|
|
1451
1218
|
const { checkpoints, processorId, processorInstanceId: instanceId = getProcessorInstanceId(processorId), type = MessageProcessorType.REACTOR, version = 1, partition = defaultProcessorPartition, hooks = {}, processingScope = defaultProcessingMessageProcessingScope, startFrom, canHandle, stopAfter } = options;
|
|
1452
|
-
const collector = processorCollector(
|
|
1219
|
+
const collector = processorCollector(processorObservability(options));
|
|
1453
1220
|
const isCustomBatch = "eachBatch" in options && !!options.eachBatch;
|
|
1454
1221
|
const eachBatch = isCustomBatch ? options.eachBatch : async (messages, context) => {
|
|
1455
1222
|
const batchCtx = context.observabilityScope.spanContext();
|
|
@@ -1531,25 +1298,27 @@ const reactor = (options) => {
|
|
|
1531
1298
|
...partialOptions,
|
|
1532
1299
|
observabilityScope: ("observabilityScope" in partialOptions ? partialOptions.observabilityScope ?? _event_driven_io_almanac.noopScope : _event_driven_io_almanac.noopScope) ?? _event_driven_io_almanac.noopScope
|
|
1533
1300
|
};
|
|
1301
|
+
const log = startOptions.observabilityScope.log;
|
|
1534
1302
|
if (isActive) {
|
|
1535
|
-
|
|
1303
|
+
log(info(`Processor ${processorId} with instance id ${instanceId} is already active. Start request ignored.`));
|
|
1536
1304
|
return;
|
|
1537
1305
|
}
|
|
1538
|
-
|
|
1306
|
+
log(info(`Starting processor ${processorId} with instance id ${instanceId}`));
|
|
1539
1307
|
await init(startOptions);
|
|
1540
1308
|
isActive = true;
|
|
1541
1309
|
closeSignal = onShutdown(() => close(startOptions));
|
|
1542
1310
|
if (lastCheckpoint !== null) {
|
|
1543
|
-
|
|
1311
|
+
log(info(`Processor ${processorId} started with instance id ${instanceId}, checkpoint: ${JSONSerializer.serialize(lastCheckpoint)}`));
|
|
1544
1312
|
return { lastCheckpoint };
|
|
1545
1313
|
}
|
|
1546
1314
|
return await processingScope(async (context) => {
|
|
1315
|
+
const log = context.observabilityScope.log;
|
|
1547
1316
|
if (hooks.onStart) {
|
|
1548
|
-
|
|
1317
|
+
log(info(`Executing onStart hook for processor ${processorId} with instance id ${instanceId}`));
|
|
1549
1318
|
await hooks.onStart(context);
|
|
1550
1319
|
}
|
|
1551
1320
|
if (startFrom && startFrom !== "CURRENT") {
|
|
1552
|
-
|
|
1321
|
+
log(info(`Processor ${processorId} with instance id ${instanceId} starting from: ${JSONSerializer.serialize(startFrom)}`));
|
|
1553
1322
|
return startFrom;
|
|
1554
1323
|
}
|
|
1555
1324
|
if (checkpoints) lastCheckpoint = (await checkpoints?.read({
|
|
@@ -1560,10 +1329,10 @@ const reactor = (options) => {
|
|
|
1560
1329
|
...context
|
|
1561
1330
|
})).lastCheckpoint;
|
|
1562
1331
|
if (lastCheckpoint === null) {
|
|
1563
|
-
|
|
1332
|
+
log(info(`Processor ${processorId} with instance id ${instanceId} starting from: BEGINNING`));
|
|
1564
1333
|
return "BEGINNING";
|
|
1565
1334
|
}
|
|
1566
|
-
|
|
1335
|
+
log(info(`Checkpoint read for processor ${processorId} with instance id ${instanceId}: ${JSONSerializer.serialize(lastCheckpoint)}`));
|
|
1567
1336
|
return { lastCheckpoint };
|
|
1568
1337
|
}, startOptions);
|
|
1569
1338
|
},
|
|
@@ -1620,12 +1389,12 @@ const reactor = (options) => {
|
|
|
1620
1389
|
...partialContext,
|
|
1621
1390
|
observabilityScope: scope
|
|
1622
1391
|
});
|
|
1623
|
-
} catch (
|
|
1624
|
-
|
|
1392
|
+
} catch (err) {
|
|
1393
|
+
scope.log(error({ err }, `Error during message processing for processor ${processorId} with instance id ${instanceId}. Stopping the processor.`));
|
|
1625
1394
|
isActive = false;
|
|
1626
1395
|
return {
|
|
1627
1396
|
type: "STOP",
|
|
1628
|
-
error,
|
|
1397
|
+
error: err,
|
|
1629
1398
|
reason: "Error during message processing"
|
|
1630
1399
|
};
|
|
1631
1400
|
}
|
|
@@ -1995,6 +1764,7 @@ const assertThatArray = (array) => {
|
|
|
1995
1764
|
|
|
1996
1765
|
//#endregion
|
|
1997
1766
|
//#region src/testing/deciderSpecification.ts
|
|
1767
|
+
const isPromiseLike = (value) => value !== null && (typeof value === "object" || typeof value === "function") && typeof value.then === "function";
|
|
1998
1768
|
const DeciderSpecification = { for: deciderSpecificationFor };
|
|
1999
1769
|
function deciderSpecificationFor(decider) {
|
|
2000
1770
|
return (givenEvents) => {
|
|
@@ -2004,16 +1774,14 @@ function deciderSpecificationFor(decider) {
|
|
|
2004
1774
|
return decider.decide(command, currentState);
|
|
2005
1775
|
};
|
|
2006
1776
|
return {
|
|
2007
|
-
then: (
|
|
1777
|
+
then: (expectedEventsOrAssert) => {
|
|
2008
1778
|
const resultEvents = handle();
|
|
2009
|
-
if (resultEvents
|
|
2010
|
-
|
|
2011
|
-
});
|
|
2012
|
-
thenHandler$1(resultEvents, expectedEvents);
|
|
1779
|
+
if (isPromiseLike(resultEvents)) return Promise.resolve(resultEvents).then((events) => thenHandler$1(events, expectedEventsOrAssert));
|
|
1780
|
+
return thenHandler$1(resultEvents, expectedEventsOrAssert);
|
|
2013
1781
|
},
|
|
2014
1782
|
thenNothingHappened: () => {
|
|
2015
1783
|
const resultEvents = handle();
|
|
2016
|
-
if (resultEvents
|
|
1784
|
+
if (isPromiseLike(resultEvents)) return Promise.resolve(resultEvents).then((events) => {
|
|
2017
1785
|
thenNothingHappensHandler$1(events);
|
|
2018
1786
|
});
|
|
2019
1787
|
thenNothingHappensHandler$1(resultEvents);
|
|
@@ -2021,7 +1789,7 @@ function deciderSpecificationFor(decider) {
|
|
|
2021
1789
|
thenThrows: (...args) => {
|
|
2022
1790
|
try {
|
|
2023
1791
|
const result = handle();
|
|
2024
|
-
if (result
|
|
1792
|
+
if (isPromiseLike(result)) return Promise.resolve(result).then(() => {
|
|
2025
1793
|
throw new AssertionError("Handler did not fail as expected");
|
|
2026
1794
|
}).catch((error) => {
|
|
2027
1795
|
thenThrowsErrorHandler$1(error, args);
|
|
@@ -2035,11 +1803,26 @@ function deciderSpecificationFor(decider) {
|
|
|
2035
1803
|
} };
|
|
2036
1804
|
};
|
|
2037
1805
|
}
|
|
2038
|
-
function thenHandler$1(events,
|
|
1806
|
+
function thenHandler$1(events, expectedEventsOrAssert) {
|
|
2039
1807
|
const resultEventsArray = Array.isArray(events) ? events : [events];
|
|
2040
|
-
|
|
1808
|
+
if (typeof expectedEventsOrAssert === "function") return runThenAssert(resultEventsArray, expectedEventsOrAssert);
|
|
1809
|
+
const expectedEventsArray = Array.isArray(expectedEventsOrAssert) ? expectedEventsOrAssert : [expectedEventsOrAssert];
|
|
2041
1810
|
assertThatArray(resultEventsArray).containsOnlyElementsMatching(expectedEventsArray);
|
|
2042
1811
|
}
|
|
1812
|
+
/**
|
|
1813
|
+
* Runs the client-provided assertion. The test fails (throws) when the callback
|
|
1814
|
+
* throws, returns an `Error`, or returns a Promise that rejects or resolves to
|
|
1815
|
+
* an `Error`. A thrown error is propagated as-is so the client's assertion
|
|
1816
|
+
* library (node:assert, Vitest `expect`, ...) keeps its own message and diff.
|
|
1817
|
+
*/
|
|
1818
|
+
function runThenAssert(events, assert) {
|
|
1819
|
+
const outcome = assert(events);
|
|
1820
|
+
if (isPromiseLike(outcome)) return Promise.resolve(outcome).then(failIfError);
|
|
1821
|
+
failIfError(outcome);
|
|
1822
|
+
}
|
|
1823
|
+
function failIfError(outcome) {
|
|
1824
|
+
if (outcome instanceof Error) throw outcome;
|
|
1825
|
+
}
|
|
2043
1826
|
function thenNothingHappensHandler$1(events) {
|
|
2044
1827
|
assertThatArray(Array.isArray(events) ? events : [events]).isEmpty();
|
|
2045
1828
|
}
|
|
@@ -2184,7 +1967,7 @@ const InMemoryProjectionSpec = { for: (options) => {
|
|
|
2184
1967
|
return Promise.resolve(false);
|
|
2185
1968
|
}
|
|
2186
1969
|
},
|
|
2187
|
-
observability:
|
|
1970
|
+
observability: eventStoreObservability(void 0)
|
|
2188
1971
|
});
|
|
2189
1972
|
};
|
|
2190
1973
|
return {
|
|
@@ -2289,6 +2072,88 @@ const upcastRecordedMessages = (recordedMessages, options) => {
|
|
|
2289
2072
|
return recordedMessages.map((recordedMessage) => upcastRecordedMessage(recordedMessage, options));
|
|
2290
2073
|
};
|
|
2291
2074
|
|
|
2075
|
+
//#endregion
|
|
2076
|
+
//#region src/eventStore/observability/eventStoreCollector.ts
|
|
2077
|
+
const eventStoreObservability = (options, parent) => ({
|
|
2078
|
+
tracer: options?.observability?.tracer ?? parent?.observability?.tracer ?? (0, _event_driven_io_almanac.noopTracer)(),
|
|
2079
|
+
meter: options?.observability?.meter ?? parent?.observability?.meter ?? (0, _event_driven_io_almanac.noopMeter)(),
|
|
2080
|
+
attributeTarget: options?.observability?.attributeTarget ?? parent?.observability?.attributeTarget ?? "both"
|
|
2081
|
+
});
|
|
2082
|
+
const eventStoreCollector = (observability) => {
|
|
2083
|
+
const A = EmmettAttributes;
|
|
2084
|
+
const M = _event_driven_io_almanac.MessagingAttributes;
|
|
2085
|
+
const streamReadingDuration = observability.meter.histogram(EmmettMetrics.stream.readingDuration);
|
|
2086
|
+
const streamReadingSize = observability.meter.histogram(EmmettMetrics.stream.readingSize);
|
|
2087
|
+
const eventReadingCount = observability.meter.counter(EmmettMetrics.event.readingCount);
|
|
2088
|
+
const streamAppendingDuration = observability.meter.histogram(EmmettMetrics.stream.appendingDuration);
|
|
2089
|
+
const streamAppendingSize = observability.meter.histogram(EmmettMetrics.stream.appendingSize);
|
|
2090
|
+
const eventAppendingCount = observability.meter.counter(EmmettMetrics.event.appendingCount);
|
|
2091
|
+
return {
|
|
2092
|
+
instrumentRead: (streamName, fn) => {
|
|
2093
|
+
const start = Date.now();
|
|
2094
|
+
return observability.tracer.startSpan("eventStore.readStream", async (span) => {
|
|
2095
|
+
span.setAttributes({
|
|
2096
|
+
[A.eventStore.operation]: "readStream",
|
|
2097
|
+
[A.stream.name]: streamName,
|
|
2098
|
+
[M.operation.type]: "receive",
|
|
2099
|
+
[M.destination.name]: streamName,
|
|
2100
|
+
[M.system]: MessagingSystemName
|
|
2101
|
+
});
|
|
2102
|
+
let status = "success";
|
|
2103
|
+
try {
|
|
2104
|
+
const result = await fn();
|
|
2105
|
+
const events = result.events;
|
|
2106
|
+
span.setAttributes({
|
|
2107
|
+
[A.eventStore.read.status]: status,
|
|
2108
|
+
[A.eventStore.read.eventCount]: events.length,
|
|
2109
|
+
[A.eventStore.read.eventTypes]: [...new Set(events.map((e) => e.type))]
|
|
2110
|
+
});
|
|
2111
|
+
streamReadingSize.record(events.length, { [A.eventStore.read.status]: status });
|
|
2112
|
+
for (const event of events) eventReadingCount.add(1, { [A.event.type]: event.type });
|
|
2113
|
+
return result;
|
|
2114
|
+
} catch (err) {
|
|
2115
|
+
status = "failure";
|
|
2116
|
+
span.setAttributes({ [A.eventStore.read.status]: status });
|
|
2117
|
+
throw err;
|
|
2118
|
+
} finally {
|
|
2119
|
+
streamReadingDuration.record(Date.now() - start, { [A.eventStore.read.status]: status });
|
|
2120
|
+
}
|
|
2121
|
+
});
|
|
2122
|
+
},
|
|
2123
|
+
instrumentAppend: (streamName, events, fn) => {
|
|
2124
|
+
const start = Date.now();
|
|
2125
|
+
return observability.tracer.startSpan("eventStore.appendToStream", async (span) => {
|
|
2126
|
+
span.setAttributes({
|
|
2127
|
+
[A.eventStore.operation]: "appendToStream",
|
|
2128
|
+
[A.stream.name]: streamName,
|
|
2129
|
+
[A.eventStore.append.batchSize]: events.length,
|
|
2130
|
+
[M.operation.type]: "send",
|
|
2131
|
+
[M.batch.messageCount]: events.length,
|
|
2132
|
+
[M.destination.name]: streamName,
|
|
2133
|
+
[M.system]: MessagingSystemName
|
|
2134
|
+
});
|
|
2135
|
+
let status = "success";
|
|
2136
|
+
try {
|
|
2137
|
+
const result = await fn();
|
|
2138
|
+
span.setAttributes({
|
|
2139
|
+
[A.eventStore.append.status]: status,
|
|
2140
|
+
[A.stream.versionAfter]: Number(result.nextExpectedStreamVersion)
|
|
2141
|
+
});
|
|
2142
|
+
streamAppendingSize.record(events.length, { [A.eventStore.append.status]: status });
|
|
2143
|
+
for (const event of events) eventAppendingCount.add(1, { [A.event.type]: event.type });
|
|
2144
|
+
return result;
|
|
2145
|
+
} catch (err) {
|
|
2146
|
+
status = "failure";
|
|
2147
|
+
span.setAttributes({ [A.eventStore.append.status]: status });
|
|
2148
|
+
throw err;
|
|
2149
|
+
} finally {
|
|
2150
|
+
streamAppendingDuration.record(Date.now() - start, { [A.eventStore.append.status]: status });
|
|
2151
|
+
}
|
|
2152
|
+
});
|
|
2153
|
+
}
|
|
2154
|
+
};
|
|
2155
|
+
};
|
|
2156
|
+
|
|
2292
2157
|
//#endregion
|
|
2293
2158
|
//#region src/eventStore/inMemoryEventStore.ts
|
|
2294
2159
|
const InMemoryEventStoreDefaultStreamVersion = 0n;
|
|
@@ -2299,7 +2164,7 @@ const getInMemoryEventStore = (eventStoreOptions) => {
|
|
|
2299
2164
|
};
|
|
2300
2165
|
const database = eventStoreOptions?.database || getInMemoryDatabase();
|
|
2301
2166
|
const inlineProjections = (eventStoreOptions?.projections ?? []).filter(({ type }) => type === "inline").map(({ projection }) => projection);
|
|
2302
|
-
const observability =
|
|
2167
|
+
const observability = eventStoreObservability(eventStoreOptions);
|
|
2303
2168
|
const collector = eventStoreCollector(observability);
|
|
2304
2169
|
const eventStore = {
|
|
2305
2170
|
database,
|
|
@@ -2381,7 +2246,7 @@ const getInMemoryEventStore = (eventStoreOptions) => {
|
|
|
2381
2246
|
|
|
2382
2247
|
//#endregion
|
|
2383
2248
|
//#region src/commandHandling/observability/commandHandlerCollector.ts
|
|
2384
|
-
const
|
|
2249
|
+
const commandObservability = (options, parent) => ({
|
|
2385
2250
|
tracer: options?.observability?.tracer ?? parent?.observability?.tracer ?? (0, _event_driven_io_almanac.noopTracer)(),
|
|
2386
2251
|
meter: options?.observability?.meter ?? parent?.observability?.meter ?? (0, _event_driven_io_almanac.noopMeter)(),
|
|
2387
2252
|
attributeTarget: options?.observability?.attributeTarget ?? parent?.observability?.attributeTarget ?? "both",
|
|
@@ -2425,7 +2290,7 @@ const commandHandlerCollector = (observability) => {
|
|
|
2425
2290
|
"exception.message": err instanceof Error ? err.message : String(err),
|
|
2426
2291
|
"exception.type": err instanceof Error ? err.constructor.name : "unknown"
|
|
2427
2292
|
});
|
|
2428
|
-
scope.
|
|
2293
|
+
scope.log(_event_driven_io_almanac.LogEvent.error(err instanceof Error ? err : new Error(String(err))));
|
|
2429
2294
|
throw err;
|
|
2430
2295
|
} finally {
|
|
2431
2296
|
commandHandlingDuration.record(Date.now() - start, {
|
|
@@ -2474,7 +2339,7 @@ const CommandHandlerStreamVersionConflictRetryOptions = {
|
|
|
2474
2339
|
shouldRetryError: isExpectedVersionConflictError
|
|
2475
2340
|
};
|
|
2476
2341
|
const CommandHandler = (options) => async (store, id, handle, handleOptions) => {
|
|
2477
|
-
const collector = commandHandlerCollector(
|
|
2342
|
+
const collector = commandHandlerCollector(commandObservability(options));
|
|
2478
2343
|
const streamName = (options.mapToStreamId ?? ((id) => id))(id);
|
|
2479
2344
|
const commandType = handleOptions?.commandType ?? options.commandType ?? options.name ?? handlerNames(handle);
|
|
2480
2345
|
const correlationId = handleOptions?.observability?.correlationId ?? (0, uuid.v7)();
|
|
@@ -2573,6 +2438,61 @@ const DeciderCommandHandler = (options) => async (eventStore, id, commands, hand
|
|
|
2573
2438
|
});
|
|
2574
2439
|
};
|
|
2575
2440
|
|
|
2441
|
+
//#endregion
|
|
2442
|
+
//#region src/consumers/observability/consumerCollector.ts
|
|
2443
|
+
const consumerObservability = (options, parent) => {
|
|
2444
|
+
const observability = mergeObservabilityOptions({ observability: options?.observability }, parent?.observability).observability;
|
|
2445
|
+
return {
|
|
2446
|
+
tracer: observability?.tracer ?? (0, _event_driven_io_almanac.noopTracer)(),
|
|
2447
|
+
meter: observability?.meter ?? (0, _event_driven_io_almanac.noopMeter)(),
|
|
2448
|
+
pollTracing: observability?.pollTracing ?? "off",
|
|
2449
|
+
attributeTarget: observability?.attributeTarget ?? "both"
|
|
2450
|
+
};
|
|
2451
|
+
};
|
|
2452
|
+
const consumerCollector = (observability) => {
|
|
2453
|
+
const { startScope } = (0, _event_driven_io_almanac.ObservabilityScope)({
|
|
2454
|
+
...observability,
|
|
2455
|
+
attributePrefix: "emmett"
|
|
2456
|
+
});
|
|
2457
|
+
const A = EmmettAttributes;
|
|
2458
|
+
const M = _event_driven_io_almanac.MessagingAttributes;
|
|
2459
|
+
const pollDuration = observability.meter.histogram(EmmettMetrics.consumer.pollDuration);
|
|
2460
|
+
const deliveryDuration = observability.meter.histogram(EmmettMetrics.consumer.deliveryDuration);
|
|
2461
|
+
return {
|
|
2462
|
+
tracePoll: (context, fn) => {
|
|
2463
|
+
if (observability.pollTracing === "off" || observability.pollTracing === "active" && context.batchSize === 0) return fn(_event_driven_io_almanac.noopScope);
|
|
2464
|
+
return startScope("consumer.poll", async (scope) => {
|
|
2465
|
+
scope.setAttributes({
|
|
2466
|
+
[A.scope.type]: ScopeTypes.consumer,
|
|
2467
|
+
[A.consumer.batchSize]: context.batchSize,
|
|
2468
|
+
[A.consumer.processorCount]: context.processorCount,
|
|
2469
|
+
[M.system]: MessagingSystemName,
|
|
2470
|
+
[M.operation.type]: "receive",
|
|
2471
|
+
...context.empty ? { "emmett.consumer.poll.empty": true } : {},
|
|
2472
|
+
...context.waitMs != null ? { "emmett.consumer.poll.wait_ms": context.waitMs } : {}
|
|
2473
|
+
});
|
|
2474
|
+
return fn(scope);
|
|
2475
|
+
});
|
|
2476
|
+
},
|
|
2477
|
+
recordPollMetrics: (durationMs, attrs) => {
|
|
2478
|
+
pollDuration.record(durationMs, attrs);
|
|
2479
|
+
},
|
|
2480
|
+
traceDelivery: (scope, processorId, fn) => {
|
|
2481
|
+
const start = Date.now();
|
|
2482
|
+
return scope.scope(`consumer.deliver.${processorId}`, async (child) => {
|
|
2483
|
+
try {
|
|
2484
|
+
return await fn();
|
|
2485
|
+
} catch (error) {
|
|
2486
|
+
if (error instanceof Error) child.log(_event_driven_io_almanac.LogEvent.error(error));
|
|
2487
|
+
throw error;
|
|
2488
|
+
} finally {
|
|
2489
|
+
deliveryDuration.record(Date.now() - start, { [A.consumer.delivery.processorId]: processorId });
|
|
2490
|
+
}
|
|
2491
|
+
}, { attributes: { [A.consumer.delivery.processorId]: processorId } });
|
|
2492
|
+
}
|
|
2493
|
+
};
|
|
2494
|
+
};
|
|
2495
|
+
|
|
2576
2496
|
//#endregion
|
|
2577
2497
|
//#region src/messageBus/index.ts
|
|
2578
2498
|
const getInMemoryMessageBus = () => {
|
|
@@ -2639,6 +2559,66 @@ const projections = {
|
|
|
2639
2559
|
async: asyncProjections
|
|
2640
2560
|
};
|
|
2641
2561
|
|
|
2562
|
+
//#endregion
|
|
2563
|
+
//#region src/workflows/observability/workflowCollector.ts
|
|
2564
|
+
const workflowObservability = (options, parent) => {
|
|
2565
|
+
const observability = mergeObservabilityOptions({ observability: options?.observability }, parent?.observability).observability;
|
|
2566
|
+
return {
|
|
2567
|
+
tracer: observability?.tracer ?? (0, _event_driven_io_almanac.noopTracer)(),
|
|
2568
|
+
meter: observability?.meter ?? (0, _event_driven_io_almanac.noopMeter)(),
|
|
2569
|
+
propagation: observability?.propagation ?? "links",
|
|
2570
|
+
attributeTarget: observability?.attributeTarget ?? "both",
|
|
2571
|
+
includeMessagePayloads: observability?.includeMessagePayloads ?? false
|
|
2572
|
+
};
|
|
2573
|
+
};
|
|
2574
|
+
const workflowCollector = (observability) => {
|
|
2575
|
+
const { startScope } = (0, _event_driven_io_almanac.ObservabilityScope)({
|
|
2576
|
+
...observability,
|
|
2577
|
+
attributePrefix: "emmett"
|
|
2578
|
+
});
|
|
2579
|
+
const A = EmmettAttributes;
|
|
2580
|
+
const M = _event_driven_io_almanac.MessagingAttributes;
|
|
2581
|
+
const processingDuration = observability.meter.histogram(EmmettMetrics.workflow.processingDuration);
|
|
2582
|
+
return {
|
|
2583
|
+
startScope: (context, fn) => {
|
|
2584
|
+
const start = Date.now();
|
|
2585
|
+
return startScope("workflow.handle", async (scope) => {
|
|
2586
|
+
scope.setAttributes({
|
|
2587
|
+
[A.scope.type]: ScopeTypes.workflow,
|
|
2588
|
+
[A.workflow.id]: context.workflowId,
|
|
2589
|
+
[A.workflow.type]: context.workflowType,
|
|
2590
|
+
[A.workflow.inputType]: context.inputType,
|
|
2591
|
+
[M.system]: MessagingSystemName
|
|
2592
|
+
});
|
|
2593
|
+
let status = "success";
|
|
2594
|
+
try {
|
|
2595
|
+
return await fn(scope);
|
|
2596
|
+
} catch (err) {
|
|
2597
|
+
status = "failure";
|
|
2598
|
+
throw err;
|
|
2599
|
+
} finally {
|
|
2600
|
+
processingDuration.record(Date.now() - start, {
|
|
2601
|
+
[A.workflow.type]: context.workflowType,
|
|
2602
|
+
status
|
|
2603
|
+
});
|
|
2604
|
+
}
|
|
2605
|
+
}, { attributes: {
|
|
2606
|
+
[A.scope.type]: ScopeTypes.workflow,
|
|
2607
|
+
[A.workflow.type]: context.workflowType
|
|
2608
|
+
} });
|
|
2609
|
+
},
|
|
2610
|
+
recordOutputs: (scope, outputs) => {
|
|
2611
|
+
scope.setAttributes({
|
|
2612
|
+
[A.workflow.outputs]: outputs.map((o) => o.type),
|
|
2613
|
+
[A.workflow.outputsCount]: outputs.length
|
|
2614
|
+
});
|
|
2615
|
+
},
|
|
2616
|
+
recordStateRebuild: (scope, eventCount) => {
|
|
2617
|
+
scope.setAttributes({ [A.workflow.stateRebuildEventCount]: eventCount });
|
|
2618
|
+
}
|
|
2619
|
+
};
|
|
2620
|
+
};
|
|
2621
|
+
|
|
2642
2622
|
//#endregion
|
|
2643
2623
|
//#region src/workflows/handleWorkflow.ts
|
|
2644
2624
|
const WorkflowHandlerStreamVersionConflictRetryOptions = {
|
|
@@ -2708,7 +2688,7 @@ const createWrappedEvolve = (evolve, workflowName, separateInputInboxFromProcess
|
|
|
2708
2688
|
};
|
|
2709
2689
|
const workflowStreamName = ({ workflowName, workflowId }) => `emt:workflow:${workflowName}:${workflowId}`;
|
|
2710
2690
|
const WorkflowHandler = (options) => async (store, message, handleOptions) => {
|
|
2711
|
-
const collector = workflowCollector(
|
|
2691
|
+
const collector = workflowCollector(workflowObservability(options));
|
|
2712
2692
|
const workflowType = options.workflow.name;
|
|
2713
2693
|
const inputType = message.type;
|
|
2714
2694
|
const workflowId = options.getWorkflowId(message) ?? "";
|
|
@@ -2894,8 +2874,6 @@ var src_exports = /* @__PURE__ */ require_plugins.__exportAll({
|
|
|
2894
2874
|
JSONReviver: () => JSONReviver,
|
|
2895
2875
|
JSONRevivers: () => JSONRevivers,
|
|
2896
2876
|
JSONSerializer: () => JSONSerializer,
|
|
2897
|
-
LogLevel: () => LogLevel,
|
|
2898
|
-
LogStyle: () => LogStyle,
|
|
2899
2877
|
MessageProcessor: () => MessageProcessor,
|
|
2900
2878
|
MessageProcessorType: () => MessageProcessorType,
|
|
2901
2879
|
MessagingSystemName: () => MessagingSystemName,
|
|
@@ -2951,6 +2929,7 @@ var src_exports = /* @__PURE__ */ require_plugins.__exportAll({
|
|
|
2951
2929
|
composeJSONReplacers: () => composeJSONReplacers,
|
|
2952
2930
|
composeJSONRevivers: () => composeJSONRevivers,
|
|
2953
2931
|
consumerCollector: () => consumerCollector,
|
|
2932
|
+
consumerObservability: () => consumerObservability,
|
|
2954
2933
|
deepEquals: () => deepEquals,
|
|
2955
2934
|
defaultProcessingMessageProcessingScope: () => defaultProcessingMessageProcessingScope,
|
|
2956
2935
|
defaultProcessorPartition: () => defaultProcessorPartition,
|
|
@@ -2961,9 +2940,11 @@ var src_exports = /* @__PURE__ */ require_plugins.__exportAll({
|
|
|
2961
2940
|
downcastRecordedMessage: () => downcastRecordedMessage,
|
|
2962
2941
|
downcastRecordedMessages: () => downcastRecordedMessages,
|
|
2963
2942
|
emmettPrefix: () => "emt",
|
|
2943
|
+
errorReplacer: () => errorReplacer,
|
|
2964
2944
|
event: () => event,
|
|
2965
2945
|
eventInStream: () => eventInStream,
|
|
2966
2946
|
eventStoreCollector: () => eventStoreCollector,
|
|
2947
|
+
eventStoreObservability: () => eventStoreObservability,
|
|
2967
2948
|
eventsInStream: () => eventsInStream,
|
|
2968
2949
|
expectInMemoryDocuments: () => expectInMemoryDocuments,
|
|
2969
2950
|
filterProjections: () => filterProjections,
|
|
@@ -3005,6 +2986,7 @@ var src_exports = /* @__PURE__ */ require_plugins.__exportAll({
|
|
|
3005
2986
|
jsonSerializer: () => jsonSerializer,
|
|
3006
2987
|
matchesExpectedVersion: () => matchesExpectedVersion,
|
|
3007
2988
|
merge: () => merge,
|
|
2989
|
+
mergeObservabilityOptions: () => mergeObservabilityOptions,
|
|
3008
2990
|
message: () => message,
|
|
3009
2991
|
newEventsInStream: () => newEventsInStream,
|
|
3010
2992
|
nulloSessionFactory: () => nulloSessionFactory,
|
|
@@ -3012,18 +2994,14 @@ var src_exports = /* @__PURE__ */ require_plugins.__exportAll({
|
|
|
3012
2994
|
parseBigIntProcessorCheckpoint: () => parseBigIntProcessorCheckpoint,
|
|
3013
2995
|
parseDateFromUtcYYYYMMDD: () => require_plugins.parseDateFromUtcYYYYMMDD,
|
|
3014
2996
|
processorCollector: () => processorCollector,
|
|
2997
|
+
processorObservability: () => processorObservability,
|
|
3015
2998
|
projection: () => projection,
|
|
3016
2999
|
projections: () => projections,
|
|
3017
3000
|
projector: () => projector,
|
|
3018
3001
|
reactor: () => reactor,
|
|
3019
3002
|
reduceAsync: () => reduceAsync,
|
|
3020
|
-
resolveConsumerObservability: () => resolveConsumerObservability,
|
|
3021
|
-
resolveEventStoreObservability: () => resolveEventStoreObservability,
|
|
3022
|
-
resolveProcessorObservability: () => resolveProcessorObservability,
|
|
3023
|
-
resolveWorkflowObservability: () => resolveWorkflowObservability,
|
|
3024
3003
|
sum: () => sum,
|
|
3025
3004
|
toNormalizedString: () => toNormalizedString,
|
|
3026
|
-
tracer: () => tracer,
|
|
3027
3005
|
tryPublishMessagesAfterCommit: () => tryPublishMessagesAfterCommit,
|
|
3028
3006
|
unknownTag: () => unknownTag,
|
|
3029
3007
|
upcastRecordedMessage: () => upcastRecordedMessage,
|
|
@@ -3031,6 +3009,7 @@ var src_exports = /* @__PURE__ */ require_plugins.__exportAll({
|
|
|
3031
3009
|
verifyThat: () => verifyThat,
|
|
3032
3010
|
wasMessageHandled: () => wasMessageHandled,
|
|
3033
3011
|
workflowCollector: () => workflowCollector,
|
|
3012
|
+
workflowObservability: () => workflowObservability,
|
|
3034
3013
|
workflowOutputHandler: () => workflowOutputHandler,
|
|
3035
3014
|
workflowProcessor: () => workflowProcessor,
|
|
3036
3015
|
workflowStreamName: () => workflowStreamName
|
|
@@ -3060,8 +3039,6 @@ exports.JSONReplacers = JSONReplacers;
|
|
|
3060
3039
|
exports.JSONReviver = JSONReviver;
|
|
3061
3040
|
exports.JSONRevivers = JSONRevivers;
|
|
3062
3041
|
exports.JSONSerializer = JSONSerializer;
|
|
3063
|
-
exports.LogLevel = LogLevel;
|
|
3064
|
-
exports.LogStyle = LogStyle;
|
|
3065
3042
|
exports.MessageProcessor = MessageProcessor;
|
|
3066
3043
|
exports.MessageProcessorType = MessageProcessorType;
|
|
3067
3044
|
exports.MessagingSystemName = MessagingSystemName;
|
|
@@ -3117,6 +3094,7 @@ exports.command = command;
|
|
|
3117
3094
|
exports.composeJSONReplacers = composeJSONReplacers;
|
|
3118
3095
|
exports.composeJSONRevivers = composeJSONRevivers;
|
|
3119
3096
|
exports.consumerCollector = consumerCollector;
|
|
3097
|
+
exports.consumerObservability = consumerObservability;
|
|
3120
3098
|
exports.deepEquals = deepEquals;
|
|
3121
3099
|
exports.defaultProcessingMessageProcessingScope = defaultProcessingMessageProcessingScope;
|
|
3122
3100
|
exports.defaultProcessorPartition = defaultProcessorPartition;
|
|
@@ -3127,9 +3105,11 @@ exports.documentExists = documentExists;
|
|
|
3127
3105
|
exports.downcastRecordedMessage = downcastRecordedMessage;
|
|
3128
3106
|
exports.downcastRecordedMessages = downcastRecordedMessages;
|
|
3129
3107
|
exports.emmettPrefix = emmettPrefix;
|
|
3108
|
+
exports.errorReplacer = errorReplacer;
|
|
3130
3109
|
exports.event = event;
|
|
3131
3110
|
exports.eventInStream = eventInStream;
|
|
3132
3111
|
exports.eventStoreCollector = eventStoreCollector;
|
|
3112
|
+
exports.eventStoreObservability = eventStoreObservability;
|
|
3133
3113
|
exports.eventsInStream = eventsInStream;
|
|
3134
3114
|
exports.expectInMemoryDocuments = expectInMemoryDocuments;
|
|
3135
3115
|
exports.filterProjections = filterProjections;
|
|
@@ -3171,6 +3151,7 @@ exports.isValidYYYYMMDD = require_plugins.isValidYYYYMMDD;
|
|
|
3171
3151
|
exports.jsonSerializer = jsonSerializer;
|
|
3172
3152
|
exports.matchesExpectedVersion = matchesExpectedVersion;
|
|
3173
3153
|
exports.merge = merge;
|
|
3154
|
+
exports.mergeObservabilityOptions = mergeObservabilityOptions;
|
|
3174
3155
|
exports.message = message;
|
|
3175
3156
|
exports.newEventsInStream = newEventsInStream;
|
|
3176
3157
|
exports.nulloSessionFactory = nulloSessionFactory;
|
|
@@ -3178,18 +3159,14 @@ exports.onShutdown = onShutdown;
|
|
|
3178
3159
|
exports.parseBigIntProcessorCheckpoint = parseBigIntProcessorCheckpoint;
|
|
3179
3160
|
exports.parseDateFromUtcYYYYMMDD = require_plugins.parseDateFromUtcYYYYMMDD;
|
|
3180
3161
|
exports.processorCollector = processorCollector;
|
|
3162
|
+
exports.processorObservability = processorObservability;
|
|
3181
3163
|
exports.projection = projection;
|
|
3182
3164
|
exports.projections = projections;
|
|
3183
3165
|
exports.projector = projector;
|
|
3184
3166
|
exports.reactor = reactor;
|
|
3185
3167
|
exports.reduceAsync = reduceAsync;
|
|
3186
|
-
exports.resolveConsumerObservability = resolveConsumerObservability;
|
|
3187
|
-
exports.resolveEventStoreObservability = resolveEventStoreObservability;
|
|
3188
|
-
exports.resolveProcessorObservability = resolveProcessorObservability;
|
|
3189
|
-
exports.resolveWorkflowObservability = resolveWorkflowObservability;
|
|
3190
3168
|
exports.sum = sum;
|
|
3191
3169
|
exports.toNormalizedString = toNormalizedString;
|
|
3192
|
-
exports.tracer = tracer;
|
|
3193
3170
|
exports.tryPublishMessagesAfterCommit = tryPublishMessagesAfterCommit;
|
|
3194
3171
|
exports.unknownTag = unknownTag;
|
|
3195
3172
|
exports.upcastRecordedMessage = upcastRecordedMessage;
|
|
@@ -3197,6 +3174,7 @@ exports.upcastRecordedMessages = upcastRecordedMessages;
|
|
|
3197
3174
|
exports.verifyThat = verifyThat;
|
|
3198
3175
|
exports.wasMessageHandled = wasMessageHandled;
|
|
3199
3176
|
exports.workflowCollector = workflowCollector;
|
|
3177
|
+
exports.workflowObservability = workflowObservability;
|
|
3200
3178
|
exports.workflowOutputHandler = workflowOutputHandler;
|
|
3201
3179
|
exports.workflowProcessor = workflowProcessor;
|
|
3202
3180
|
exports.workflowStreamName = workflowStreamName;
|