@temporalio/interceptors-opentelemetry 1.13.0 → 1.13.2
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/lib/client/index.d.ts +1 -1
- package/lib/instrumentation.d.ts +3 -3
- package/lib/instrumentation.js +5 -3
- package/lib/instrumentation.js.map +1 -1
- package/lib/worker/index.d.ts +5 -5
- package/lib/worker/index.js +1 -1
- package/lib/worker/index.js.map +1 -1
- package/lib/workflow/context-manager.d.ts +2 -1
- package/lib/workflow/context-manager.js +8 -2
- package/lib/workflow/context-manager.js.map +1 -1
- package/lib/workflow/index.d.ts +7 -1
- package/lib/workflow/index.js +43 -11
- package/lib/workflow/index.js.map +1 -1
- package/lib/workflow/runtime.js +3 -2
- package/lib/workflow/runtime.js.map +1 -1
- package/lib/workflow/span-exporter.d.ts +1 -0
- package/lib/workflow/span-exporter.js +5 -25
- package/lib/workflow/span-exporter.js.map +1 -1
- package/lib/workflow/workflow-module-loader.d.ts +28 -0
- package/lib/workflow/workflow-module-loader.js +56 -0
- package/lib/workflow/workflow-module-loader.js.map +1 -0
- package/package.json +14 -12
- package/src/client/index.ts +1 -1
- package/src/instrumentation.ts +11 -4
- package/src/worker/index.ts +9 -9
- package/src/workflow/context-manager.ts +13 -5
- package/src/workflow/index.ts +44 -10
- package/src/workflow/runtime.ts +4 -2
- package/src/workflow/span-exporter.ts +7 -3
- package/src/workflow/workflow-module-loader.ts +64 -0
package/lib/client/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as otel from '@opentelemetry/api';
|
|
2
|
-
import { Next,
|
|
2
|
+
import type { Next, WorkflowSignalInput, WorkflowStartInput, WorkflowClientInterceptor } from '@temporalio/client';
|
|
3
3
|
export interface InterceptorOptions {
|
|
4
4
|
readonly tracer?: otel.Tracer;
|
|
5
5
|
}
|
package/lib/instrumentation.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @module
|
|
4
4
|
*/
|
|
5
5
|
import * as otel from '@opentelemetry/api';
|
|
6
|
-
import { Headers } from '@temporalio/common';
|
|
6
|
+
import { type Headers } from '@temporalio/common';
|
|
7
7
|
/** Default trace header for opentelemetry interceptors */
|
|
8
8
|
export declare const TRACE_HEADER = "_tracer-data";
|
|
9
9
|
/** As in workflow run id */
|
|
@@ -11,11 +11,11 @@ export declare const RUN_ID_ATTR_KEY = "run_id";
|
|
|
11
11
|
/**
|
|
12
12
|
* If found, return an otel Context deserialized from the provided headers
|
|
13
13
|
*/
|
|
14
|
-
export declare function extractContextFromHeaders(headers: Headers):
|
|
14
|
+
export declare function extractContextFromHeaders(headers: Headers): otel.Context | undefined;
|
|
15
15
|
/**
|
|
16
16
|
* Given headers, return new headers with the current otel context inserted
|
|
17
17
|
*/
|
|
18
|
-
export declare function headersWithContext(headers: Headers):
|
|
18
|
+
export declare function headersWithContext(headers: Headers): Headers;
|
|
19
19
|
export interface InstrumentOptions<T> {
|
|
20
20
|
tracer: otel.Tracer;
|
|
21
21
|
spanName: string;
|
package/lib/instrumentation.js
CHANGED
|
@@ -41,7 +41,7 @@ const payloadConverter = common_1.defaultPayloadConverter;
|
|
|
41
41
|
/**
|
|
42
42
|
* If found, return an otel Context deserialized from the provided headers
|
|
43
43
|
*/
|
|
44
|
-
|
|
44
|
+
function extractContextFromHeaders(headers) {
|
|
45
45
|
const encodedSpanContext = headers[exports.TRACE_HEADER];
|
|
46
46
|
if (encodedSpanContext === undefined) {
|
|
47
47
|
return undefined;
|
|
@@ -52,7 +52,7 @@ async function extractContextFromHeaders(headers) {
|
|
|
52
52
|
/**
|
|
53
53
|
* Given headers, return new headers with the current otel context inserted
|
|
54
54
|
*/
|
|
55
|
-
|
|
55
|
+
function headersWithContext(headers) {
|
|
56
56
|
const carrier = {};
|
|
57
57
|
otel.propagation.inject(otel.context.active(), carrier, otel.defaultTextMapSetter);
|
|
58
58
|
return { ...headers, [exports.TRACE_HEADER]: payloadConverter.toPayload(carrier) };
|
|
@@ -64,8 +64,10 @@ async function wrapWithSpan(span, fn, acceptableErrors) {
|
|
|
64
64
|
return ret;
|
|
65
65
|
}
|
|
66
66
|
catch (err) {
|
|
67
|
+
const isBenignErr = err instanceof common_1.ApplicationFailure && err.category === common_1.ApplicationFailureCategory.BENIGN;
|
|
67
68
|
if (acceptableErrors === undefined || !acceptableErrors(err)) {
|
|
68
|
-
|
|
69
|
+
const statusCode = isBenignErr ? otel.SpanStatusCode.UNSET : otel.SpanStatusCode.ERROR;
|
|
70
|
+
span.setStatus({ code: statusCode, message: err.message ?? String(err) });
|
|
69
71
|
span.recordException(err);
|
|
70
72
|
}
|
|
71
73
|
else {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrumentation.js","sourceRoot":"","sources":["../src/instrumentation.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"instrumentation.js","sourceRoot":"","sources":["../src/instrumentation.ts"],"names":[],"mappings":"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"}
|
package/lib/worker/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as otel from '@opentelemetry/api';
|
|
2
|
-
import { Resource } from '@opentelemetry/resources';
|
|
3
|
-
import { SpanExporter } from '@opentelemetry/sdk-trace-base';
|
|
4
|
-
import { Context as ActivityContext } from '@temporalio/activity';
|
|
5
|
-
import {
|
|
6
|
-
import { OpenTelemetryWorkflowExporter } from '../workflow';
|
|
2
|
+
import type { Resource } from '@opentelemetry/resources';
|
|
3
|
+
import type { SpanExporter } from '@opentelemetry/sdk-trace-base';
|
|
4
|
+
import type { Context as ActivityContext } from '@temporalio/activity';
|
|
5
|
+
import type { Next, ActivityInboundCallsInterceptor, ActivityOutboundCallsInterceptor, InjectedSink, GetLogAttributesInput, ActivityExecuteInput } from '@temporalio/worker';
|
|
6
|
+
import { type OpenTelemetryWorkflowExporter } from '../workflow';
|
|
7
7
|
export interface InterceptorOptions {
|
|
8
8
|
readonly tracer?: otel.Tracer;
|
|
9
9
|
}
|
package/lib/worker/index.js
CHANGED
|
@@ -42,7 +42,7 @@ class OpenTelemetryActivityInboundInterceptor {
|
|
|
42
42
|
this.tracer = options?.tracer ?? otel.trace.getTracer('@temporalio/interceptor-activity');
|
|
43
43
|
}
|
|
44
44
|
async execute(input, next) {
|
|
45
|
-
const context =
|
|
45
|
+
const context = (0, instrumentation_1.extractContextFromHeaders)(input.headers);
|
|
46
46
|
const spanName = `${workflow_1.SpanName.ACTIVITY_EXECUTE}${workflow_1.SPAN_DELIMITER}${this.ctx.info.activityType}`;
|
|
47
47
|
return await (0, instrumentation_1.instrument)({ tracer: this.tracer, spanName, fn: () => next(input), context });
|
|
48
48
|
}
|
package/lib/worker/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/worker/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAwEA,oDAiBC;AAzFD,yDAA2C;AAY3C,wDAA2E;AAC3E,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/worker/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAwEA,oDAiBC;AAzFD,yDAA2C;AAY3C,wDAA2E;AAC3E,0CAAkH;AAMlH;;;;;GAKG;AACH,MAAa,uCAAuC;IAI7B;IAHF,MAAM,CAAc;IAEvC,YACqB,GAAoB,EACvC,OAA4B;QADT,QAAG,GAAH,GAAG,CAAiB;QAGvC,IAAI,CAAC,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,kCAAkC,CAAC,CAAC;IAC5F,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,KAA2B,EAAE,IAAsD;QAC/F,MAAM,OAAO,GAAG,IAAA,2CAAyB,EAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACzD,MAAM,QAAQ,GAAG,GAAG,mBAAQ,CAAC,gBAAgB,GAAG,yBAAc,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;QAC9F,OAAO,MAAM,IAAA,4BAAU,EAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IAC7F,CAAC;CACF;AAfD,0FAeC;AAED;;;;GAIG;AACH,MAAa,wCAAwC;IACpB;IAA/B,YAA+B,GAAoB;QAApB,QAAG,GAAH,GAAG,CAAiB;IAAG,CAAC;IAEhD,gBAAgB,CACrB,KAA4B,EAC5B,IAAgE;QAEhE,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QACvD,MAAM,WAAW,GAAG,IAAI,EAAE,WAAW,EAAE,CAAC;QACxC,IAAI,WAAW,IAAI,IAAI,CAAC,kBAAkB,CAAC,WAAW,CAAC,EAAE,CAAC;YACxD,OAAO,IAAI,CAAC;gBACV,QAAQ,EAAE,WAAW,CAAC,OAAO;gBAC7B,OAAO,EAAE,WAAW,CAAC,MAAM;gBAC3B,WAAW,EAAE,IAAI,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE;gBACtD,GAAG,KAAK;aACT,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;CACF;AApBD,4FAoBC;AAED;;GAEG;AACH,SAAgB,oBAAoB,CAClC,QAAsB,EACtB,QAAkB;IAElB,OAAO;QACL,MAAM,EAAE;YACN,EAAE,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE;gBACrB,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE;oBACxC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;oBAC3C,qFAAqF;oBACrF,OAAO,mBAAmB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;gBACnD,CAAC,CAAC,CAAC;gBACH,0CAA0C;gBAC1C,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YAC1C,CAAC;SACF;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB,CAAC,YAA8B,EAAE,QAAkB;IAC7E,MAAM,EAAE,WAAW,EAAE,GAAG,IAAI,EAAE,GAAG,YAAY,CAAC;IAC9C,OAAO;QACL,WAAW;YACT,OAAO,WAAW,CAAC;QACrB,CAAC;QACD,QAAQ;QACR,GAAG,IAAI;KACR,CAAC;AACJ,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as otel from '@opentelemetry/api';
|
|
2
2
|
export declare class ContextManager implements otel.ContextManager {
|
|
3
|
-
protected storage: import("async_hooks").AsyncLocalStorage<otel.Context
|
|
3
|
+
protected storage: import("async_hooks").AsyncLocalStorage<otel.Context> | undefined;
|
|
4
|
+
constructor();
|
|
4
5
|
active(): otel.Context;
|
|
5
6
|
bind<T>(context: otel.Context, target: T): T;
|
|
6
7
|
enable(): this;
|
|
@@ -25,9 +25,15 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
26
|
exports.ContextManager = void 0;
|
|
27
27
|
const otel = __importStar(require("@opentelemetry/api"));
|
|
28
|
-
const
|
|
28
|
+
const workflow_module_loader_1 = require("./workflow-module-loader");
|
|
29
|
+
const AsyncLocalStorage = (0, workflow_module_loader_1.getWorkflowModuleIfAvailable)()?.AsyncLocalStorage;
|
|
29
30
|
class ContextManager {
|
|
30
|
-
|
|
31
|
+
// If `@temporalio/workflow` is not available, ignore for now.
|
|
32
|
+
// When ContextManager is constructed module resolution error will be thrown.
|
|
33
|
+
storage = AsyncLocalStorage ? new AsyncLocalStorage() : undefined;
|
|
34
|
+
constructor() {
|
|
35
|
+
(0, workflow_module_loader_1.ensureWorkflowModuleLoaded)();
|
|
36
|
+
}
|
|
31
37
|
active() {
|
|
32
38
|
return this.storage.getStore() || otel.ROOT_CONTEXT;
|
|
33
39
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-manager.js","sourceRoot":"","sources":["../../src/workflow/context-manager.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,yDAA2C;AAC3C,
|
|
1
|
+
{"version":3,"file":"context-manager.js","sourceRoot":"","sources":["../../src/workflow/context-manager.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,yDAA2C;AAC3C,qEAAoG;AAEpG,MAAM,iBAAiB,GAAG,IAAA,qDAA4B,GAAE,EAAE,iBAAiB,CAAC;AAE5E,MAAa,cAAc;IACzB,8DAA8D;IAC9D,6EAA6E;IACnE,OAAO,GAAG,iBAAiB,CAAC,CAAC,CAAC,IAAI,iBAAiB,EAAgB,CAAC,CAAC,CAAC,SAAS,CAAC;IAE1F;QACE,IAAA,mDAA0B,GAAE,CAAC;IAC/B,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAC,OAAQ,CAAC,QAAQ,EAAE,IAAI,IAAI,CAAC,YAAY,CAAC;IACvD,CAAC;IAED,IAAI,CAAI,OAAqB,EAAE,MAAS;QACtC,IAAI,OAAO,MAAM,KAAK,UAAU,EAAE,CAAC;YACjC,MAAM,IAAI,SAAS,CAAC,2CAA2C,OAAO,MAAM,EAAE,CAAC,CAAC;QAClF,CAAC;QAED,8JAA8J;QAC9J,MAAM,cAAc,GAAG,CAAC,GAAG,IAAe,EAAE,EAAE;YAC5C,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QAC5D,CAAC,CAAC;QACF,MAAM,CAAC,cAAc,CAAC,cAAc,EAAE,QAAQ,EAAE;YAC9C,UAAU,EAAE,KAAK;YACjB,YAAY,EAAE,IAAI;YAClB,QAAQ,EAAE,KAAK;YACf,KAAK,EAAE,MAAM,CAAC,MAAM;SACrB,CAAC,CAAC;QACH;;;WAGG;QACH,8DAA8D;QAC9D,OAAO,cAAqB,CAAC;IAC/B,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO;QACL,IAAI,CAAC,OAAQ,CAAC,OAAO,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CACF,OAAqB,EACrB,EAAK,EACL,OAA8B,EAC9B,GAAG,IAAO;QAEV,MAAM,EAAE,GAAG,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC,OAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC;IACjD,CAAC;CACF;AAtDD,wCAsDC"}
|
package/lib/workflow/index.d.ts
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import './runtime';
|
|
2
2
|
import * as otel from '@opentelemetry/api';
|
|
3
|
-
import { ActivityInput, ContinueAsNewInput, DisposeInput, GetLogAttributesInput, LocalActivityInput, Next, SignalInput, SignalWorkflowInput, StartChildWorkflowExecutionInput, WorkflowExecuteInput, WorkflowInboundCallsInterceptor, WorkflowInternalsInterceptor, WorkflowOutboundCallsInterceptor } from '@temporalio/workflow';
|
|
3
|
+
import type { ActivityInput, ContinueAsNewInput, DisposeInput, GetLogAttributesInput, LocalActivityInput, Next, SignalInput, SignalWorkflowInput, StartChildWorkflowExecutionInput, WorkflowExecuteInput, WorkflowInboundCallsInterceptor, WorkflowInternalsInterceptor, WorkflowOutboundCallsInterceptor } from '@temporalio/workflow';
|
|
4
4
|
export * from './definitions';
|
|
5
5
|
/**
|
|
6
6
|
* Intercepts calls to run a Workflow
|
|
7
7
|
*
|
|
8
8
|
* Wraps the operation in an opentelemetry Span and links it to a parent Span context if one is
|
|
9
9
|
* provided in the Workflow input headers.
|
|
10
|
+
*
|
|
11
|
+
* `@temporalio/workflow` must be provided by host package in order to function.
|
|
10
12
|
*/
|
|
11
13
|
export declare class OpenTelemetryInboundInterceptor implements WorkflowInboundCallsInterceptor {
|
|
12
14
|
protected readonly tracer: otel.Tracer;
|
|
15
|
+
constructor();
|
|
13
16
|
execute(input: WorkflowExecuteInput, next: Next<WorkflowInboundCallsInterceptor, 'execute'>): Promise<unknown>;
|
|
14
17
|
handleSignal(input: SignalInput, next: Next<WorkflowInboundCallsInterceptor, 'handleSignal'>): Promise<void>;
|
|
15
18
|
}
|
|
@@ -17,9 +20,12 @@ export declare class OpenTelemetryInboundInterceptor implements WorkflowInboundC
|
|
|
17
20
|
* Intercepts outbound calls to schedule an Activity
|
|
18
21
|
*
|
|
19
22
|
* Wraps the operation in an opentelemetry Span and passes it to the Activity via headers.
|
|
23
|
+
*
|
|
24
|
+
* `@temporalio/workflow` must be provided by host package in order to function.
|
|
20
25
|
*/
|
|
21
26
|
export declare class OpenTelemetryOutboundInterceptor implements WorkflowOutboundCallsInterceptor {
|
|
22
27
|
protected readonly tracer: otel.Tracer;
|
|
28
|
+
constructor();
|
|
23
29
|
scheduleActivity(input: ActivityInput, next: Next<WorkflowOutboundCallsInterceptor, 'scheduleActivity'>): Promise<unknown>;
|
|
24
30
|
scheduleLocalActivity(input: LocalActivityInput, next: Next<WorkflowOutboundCallsInterceptor, 'scheduleLocalActivity'>): Promise<unknown>;
|
|
25
31
|
startChildWorkflowExecution(input: StartChildWorkflowExecutionInput, next: Next<WorkflowOutboundCallsInterceptor, 'startChildWorkflowExecution'>): Promise<[Promise<string>, Promise<unknown>]>;
|
package/lib/workflow/index.js
CHANGED
|
@@ -32,11 +32,11 @@ exports.OpenTelemetryInternalsInterceptor = exports.OpenTelemetryOutboundInterce
|
|
|
32
32
|
require("./runtime"); // Patch the Workflow isolate runtime for opentelemetry
|
|
33
33
|
const otel = __importStar(require("@opentelemetry/api"));
|
|
34
34
|
const tracing = __importStar(require("@opentelemetry/sdk-trace-base"));
|
|
35
|
-
const workflow_1 = require("@temporalio/workflow");
|
|
36
35
|
const instrumentation_1 = require("../instrumentation");
|
|
37
36
|
const context_manager_1 = require("./context-manager");
|
|
38
37
|
const definitions_1 = require("./definitions");
|
|
39
38
|
const span_exporter_1 = require("./span-exporter");
|
|
39
|
+
const workflow_module_loader_1 = require("./workflow-module-loader");
|
|
40
40
|
__exportStar(require("./definitions"), exports);
|
|
41
41
|
let tracer = undefined;
|
|
42
42
|
let contextManager = undefined;
|
|
@@ -57,21 +57,34 @@ function getTracer() {
|
|
|
57
57
|
*
|
|
58
58
|
* Wraps the operation in an opentelemetry Span and links it to a parent Span context if one is
|
|
59
59
|
* provided in the Workflow input headers.
|
|
60
|
+
*
|
|
61
|
+
* `@temporalio/workflow` must be provided by host package in order to function.
|
|
60
62
|
*/
|
|
61
63
|
class OpenTelemetryInboundInterceptor {
|
|
62
64
|
tracer = getTracer();
|
|
65
|
+
constructor() {
|
|
66
|
+
(0, workflow_module_loader_1.ensureWorkflowModuleLoaded)();
|
|
67
|
+
}
|
|
63
68
|
async execute(input, next) {
|
|
64
|
-
const
|
|
69
|
+
const { workflowInfo, ContinueAsNew } = (0, workflow_module_loader_1.getWorkflowModule)();
|
|
70
|
+
const context = (0, instrumentation_1.extractContextFromHeaders)(input.headers);
|
|
71
|
+
if (!(0, workflow_module_loader_1.hasSdkFlag)('OpenTelemetryInterceporsAvoidsExtraYields'))
|
|
72
|
+
await Promise.resolve();
|
|
65
73
|
return await (0, instrumentation_1.instrument)({
|
|
66
74
|
tracer: this.tracer,
|
|
67
|
-
spanName: `${definitions_1.SpanName.WORKFLOW_EXECUTE}${definitions_1.SPAN_DELIMITER}${
|
|
75
|
+
spanName: `${definitions_1.SpanName.WORKFLOW_EXECUTE}${definitions_1.SPAN_DELIMITER}${workflowInfo().workflowType}`,
|
|
68
76
|
fn: () => next(input),
|
|
69
77
|
context,
|
|
70
|
-
acceptableErrors: (err) => err instanceof
|
|
78
|
+
acceptableErrors: (err) => err instanceof ContinueAsNew,
|
|
71
79
|
});
|
|
72
80
|
}
|
|
73
81
|
async handleSignal(input, next) {
|
|
74
|
-
|
|
82
|
+
// Tracing of inbound signals was added in v1.11.5.
|
|
83
|
+
if (!(0, workflow_module_loader_1.hasSdkFlag)('OpenTelemetryInterceptorsTracesInboundSignals'))
|
|
84
|
+
return next(input);
|
|
85
|
+
const context = (0, instrumentation_1.extractContextFromHeaders)(input.headers);
|
|
86
|
+
if (!(0, workflow_module_loader_1.hasSdkFlag)('OpenTelemetryInterceporsAvoidsExtraYields'))
|
|
87
|
+
await Promise.resolve();
|
|
75
88
|
return await (0, instrumentation_1.instrument)({
|
|
76
89
|
tracer: this.tracer,
|
|
77
90
|
spanName: `${definitions_1.SpanName.WORKFLOW_SIGNAL}${definitions_1.SPAN_DELIMITER}${input.signalName}`,
|
|
@@ -85,15 +98,22 @@ exports.OpenTelemetryInboundInterceptor = OpenTelemetryInboundInterceptor;
|
|
|
85
98
|
* Intercepts outbound calls to schedule an Activity
|
|
86
99
|
*
|
|
87
100
|
* Wraps the operation in an opentelemetry Span and passes it to the Activity via headers.
|
|
101
|
+
*
|
|
102
|
+
* `@temporalio/workflow` must be provided by host package in order to function.
|
|
88
103
|
*/
|
|
89
104
|
class OpenTelemetryOutboundInterceptor {
|
|
90
105
|
tracer = getTracer();
|
|
106
|
+
constructor() {
|
|
107
|
+
(0, workflow_module_loader_1.ensureWorkflowModuleLoaded)();
|
|
108
|
+
}
|
|
91
109
|
async scheduleActivity(input, next) {
|
|
92
110
|
return await (0, instrumentation_1.instrument)({
|
|
93
111
|
tracer: this.tracer,
|
|
94
112
|
spanName: `${definitions_1.SpanName.ACTIVITY_START}${definitions_1.SPAN_DELIMITER}${input.activityType}`,
|
|
95
113
|
fn: async () => {
|
|
96
|
-
const headers =
|
|
114
|
+
const headers = (0, instrumentation_1.headersWithContext)(input.headers);
|
|
115
|
+
if (!(0, workflow_module_loader_1.hasSdkFlag)('OpenTelemetryInterceporsAvoidsExtraYields'))
|
|
116
|
+
await Promise.resolve();
|
|
97
117
|
return next({
|
|
98
118
|
...input,
|
|
99
119
|
headers,
|
|
@@ -102,11 +122,16 @@ class OpenTelemetryOutboundInterceptor {
|
|
|
102
122
|
});
|
|
103
123
|
}
|
|
104
124
|
async scheduleLocalActivity(input, next) {
|
|
125
|
+
// Tracing of local activities was added in v1.11.6.
|
|
126
|
+
if (!(0, workflow_module_loader_1.hasSdkFlag)('OpenTelemetryInterceptorsTracesLocalActivities'))
|
|
127
|
+
return next(input);
|
|
105
128
|
return await (0, instrumentation_1.instrument)({
|
|
106
129
|
tracer: this.tracer,
|
|
107
130
|
spanName: `${definitions_1.SpanName.ACTIVITY_START}${definitions_1.SPAN_DELIMITER}${input.activityType}`,
|
|
108
131
|
fn: async () => {
|
|
109
|
-
const headers =
|
|
132
|
+
const headers = (0, instrumentation_1.headersWithContext)(input.headers);
|
|
133
|
+
if (!(0, workflow_module_loader_1.hasSdkFlag)('OpenTelemetryInterceporsAvoidsExtraYields'))
|
|
134
|
+
await Promise.resolve();
|
|
110
135
|
return next({
|
|
111
136
|
...input,
|
|
112
137
|
headers,
|
|
@@ -119,7 +144,9 @@ class OpenTelemetryOutboundInterceptor {
|
|
|
119
144
|
tracer: this.tracer,
|
|
120
145
|
spanName: `${definitions_1.SpanName.CHILD_WORKFLOW_START}${definitions_1.SPAN_DELIMITER}${input.workflowType}`,
|
|
121
146
|
fn: async () => {
|
|
122
|
-
const headers =
|
|
147
|
+
const headers = (0, instrumentation_1.headersWithContext)(input.headers);
|
|
148
|
+
if (!(0, workflow_module_loader_1.hasSdkFlag)('OpenTelemetryInterceporsAvoidsExtraYields'))
|
|
149
|
+
await Promise.resolve();
|
|
123
150
|
return next({
|
|
124
151
|
...input,
|
|
125
152
|
headers,
|
|
@@ -128,17 +155,20 @@ class OpenTelemetryOutboundInterceptor {
|
|
|
128
155
|
});
|
|
129
156
|
}
|
|
130
157
|
async continueAsNew(input, next) {
|
|
158
|
+
const { ContinueAsNew } = (0, workflow_module_loader_1.getWorkflowModule)();
|
|
131
159
|
return await (0, instrumentation_1.instrument)({
|
|
132
160
|
tracer: this.tracer,
|
|
133
161
|
spanName: `${definitions_1.SpanName.CONTINUE_AS_NEW}${definitions_1.SPAN_DELIMITER}${input.options.workflowType}`,
|
|
134
162
|
fn: async () => {
|
|
135
|
-
const headers =
|
|
163
|
+
const headers = (0, instrumentation_1.headersWithContext)(input.headers);
|
|
164
|
+
if (!(0, workflow_module_loader_1.hasSdkFlag)('OpenTelemetryInterceporsAvoidsExtraYields'))
|
|
165
|
+
await Promise.resolve();
|
|
136
166
|
return next({
|
|
137
167
|
...input,
|
|
138
168
|
headers,
|
|
139
169
|
});
|
|
140
170
|
},
|
|
141
|
-
acceptableErrors: (err) => err instanceof
|
|
171
|
+
acceptableErrors: (err) => err instanceof ContinueAsNew,
|
|
142
172
|
});
|
|
143
173
|
}
|
|
144
174
|
async signalWorkflow(input, next) {
|
|
@@ -146,7 +176,9 @@ class OpenTelemetryOutboundInterceptor {
|
|
|
146
176
|
tracer: this.tracer,
|
|
147
177
|
spanName: `${definitions_1.SpanName.WORKFLOW_SIGNAL}${definitions_1.SPAN_DELIMITER}${input.signalName}`,
|
|
148
178
|
fn: async () => {
|
|
149
|
-
const headers =
|
|
179
|
+
const headers = (0, instrumentation_1.headersWithContext)(input.headers);
|
|
180
|
+
if (!(0, workflow_module_loader_1.hasSdkFlag)('OpenTelemetryInterceporsAvoidsExtraYields'))
|
|
181
|
+
await Promise.resolve();
|
|
150
182
|
return next({
|
|
151
183
|
...input,
|
|
152
184
|
headers,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/workflow/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,iCAAiC;AACjC,uDAAuD;AACvD,qBAAmB,CAAC,uDAAuD;AAC3E,yDAA2C;AAC3C,uEAAyD;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/workflow/index.ts"],"names":[],"mappings":"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"}
|
package/lib/workflow/runtime.js
CHANGED
|
@@ -4,8 +4,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
4
4
|
* Sets global variables required for importing opentelemetry in isolate
|
|
5
5
|
* @module
|
|
6
6
|
*/
|
|
7
|
-
const
|
|
8
|
-
|
|
7
|
+
const workflow_module_loader_1 = require("./workflow-module-loader");
|
|
8
|
+
const inWorkflowContext = (0, workflow_module_loader_1.getWorkflowModuleIfAvailable)()?.inWorkflowContext;
|
|
9
|
+
if (inWorkflowContext?.()) {
|
|
9
10
|
// Required by opentelemetry (pretend to be a browser)
|
|
10
11
|
Object.assign(globalThis, {
|
|
11
12
|
performance: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/workflow/runtime.ts"],"names":[],"mappings":";;AAAA;;;GAGG;AACH,
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/workflow/runtime.ts"],"names":[],"mappings":";;AAAA;;;GAGG;AACH,qEAAwE;AAExE,MAAM,iBAAiB,GAAG,IAAA,qDAA4B,GAAE,EAAE,iBAAiB,CAAC;AAE5E,IAAI,iBAAiB,EAAE,EAAE,EAAE,CAAC;IAC1B,sDAAsD;IACtD,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE;QACxB,WAAW,EAAE;YACX,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE;YACtB,GAAG;gBACD,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC;YACtC,CAAC;SACF;QACD,MAAM,EAAE,UAAU;KACnB,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -2,6 +2,7 @@ import * as tracing from '@opentelemetry/sdk-trace-base';
|
|
|
2
2
|
import { ExportResult } from '@opentelemetry/core';
|
|
3
3
|
import { SerializableSpan } from './definitions';
|
|
4
4
|
export declare class SpanExporter implements tracing.SpanExporter {
|
|
5
|
+
constructor();
|
|
5
6
|
export(spans: tracing.ReadableSpan[], resultCallback: (result: ExportResult) => void): void;
|
|
6
7
|
shutdown(): Promise<void>;
|
|
7
8
|
makeSerializable(span: tracing.ReadableSpan): SerializableSpan;
|
|
@@ -1,33 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
3
|
exports.SpanExporter = void 0;
|
|
27
4
|
const core_1 = require("@opentelemetry/core");
|
|
28
|
-
const
|
|
29
|
-
const
|
|
5
|
+
const workflow_module_loader_1 = require("./workflow-module-loader");
|
|
6
|
+
const exporter = (0, workflow_module_loader_1.getWorkflowModuleIfAvailable)()?.proxySinks()?.exporter;
|
|
30
7
|
class SpanExporter {
|
|
8
|
+
constructor() {
|
|
9
|
+
(0, workflow_module_loader_1.ensureWorkflowModuleLoaded)();
|
|
10
|
+
}
|
|
31
11
|
export(spans, resultCallback) {
|
|
32
12
|
exporter.export(spans.map((span) => this.makeSerializable(span)));
|
|
33
13
|
resultCallback({ code: core_1.ExportResultCode.SUCCESS });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"span-exporter.js","sourceRoot":"","sources":["../../src/workflow/span-exporter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"span-exporter.js","sourceRoot":"","sources":["../../src/workflow/span-exporter.ts"],"names":[],"mappings":";;;AACA,8CAAqE;AAErE,qEAAoG;AAEpG,MAAM,QAAQ,GAAG,IAAA,qDAA4B,GAAE,EAAE,UAAU,EAAsB,EAAE,QAAQ,CAAC;AAE5F,MAAa,YAAY;IACvB;QACE,IAAA,mDAA0B,GAAE,CAAC;IAC/B,CAAC;IAEM,MAAM,CAAC,KAA6B,EAAE,cAA8C;QACzF,QAAS,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACnE,cAAc,CAAC,EAAE,IAAI,EAAE,uBAAgB,CAAC,OAAO,EAAE,CAAC,CAAC;IACrD,CAAC;IAEM,KAAK,CAAC,QAAQ;QACnB,uBAAuB;IACzB,CAAC;IAEM,gBAAgB,CAAC,IAA0B;QAChD,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE;YAC/B,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,sBAAsB,EAAE,IAAI,CAAC,sBAAsB;YACnD,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;YAC3C,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;YACzC,sBAAsB,EAAE,IAAI,CAAC,sBAAsB;SACpD,CAAC;IACJ,CAAC;CACF;AAlCD,oCAkCC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utilities for working with a possibly missing `@temporalio/workflow` peer dependency
|
|
3
|
+
* @module
|
|
4
|
+
*/
|
|
5
|
+
import type * as WorkflowModule from '@temporalio/workflow';
|
|
6
|
+
import type { SdkFlags as SdkFlagsT } from '@temporalio/workflow/lib/flags';
|
|
7
|
+
type SdkFlags = typeof SdkFlagsT;
|
|
8
|
+
/**
|
|
9
|
+
* Returns `@temporalio/workflow` module if present.
|
|
10
|
+
* Throws if the module failed to load
|
|
11
|
+
*/
|
|
12
|
+
export declare function getWorkflowModule(): typeof WorkflowModule;
|
|
13
|
+
/**
|
|
14
|
+
* Returns if an SDK flag was set
|
|
15
|
+
*
|
|
16
|
+
* Expects to be called only after `ensureWorkflowModuleLoaded`.
|
|
17
|
+
* Will throw if `@temporalio/workflow` is not available
|
|
18
|
+
*/
|
|
19
|
+
export declare function hasSdkFlag(flag: keyof SdkFlags): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Checks if the workflow module loaded successfully and throws if not.
|
|
22
|
+
*/
|
|
23
|
+
export declare function ensureWorkflowModuleLoaded(): void;
|
|
24
|
+
/**
|
|
25
|
+
* Returns the workflow module if available, or undefined if it failed to load.
|
|
26
|
+
*/
|
|
27
|
+
export declare function getWorkflowModuleIfAvailable(): typeof WorkflowModule | undefined;
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getWorkflowModule = getWorkflowModule;
|
|
4
|
+
exports.hasSdkFlag = hasSdkFlag;
|
|
5
|
+
exports.ensureWorkflowModuleLoaded = ensureWorkflowModuleLoaded;
|
|
6
|
+
exports.getWorkflowModuleIfAvailable = getWorkflowModuleIfAvailable;
|
|
7
|
+
// @temporalio/workflow is an optional peer dependency.
|
|
8
|
+
// It can be missing as long as the user isn't attempting to construct a workflow interceptor.
|
|
9
|
+
// If we start shipping ES modules alongside CJS, we will have to reconsider
|
|
10
|
+
// this dynamic import as `import` is async for ES modules.
|
|
11
|
+
let workflowModule;
|
|
12
|
+
let workflowModuleLoadError;
|
|
13
|
+
try {
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
15
|
+
workflowModule = require('@temporalio/workflow');
|
|
16
|
+
}
|
|
17
|
+
catch (err) {
|
|
18
|
+
// Capture the module not found error to rethrow if the module is required
|
|
19
|
+
workflowModuleLoadError = err;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Returns `@temporalio/workflow` module if present.
|
|
23
|
+
* Throws if the module failed to load
|
|
24
|
+
*/
|
|
25
|
+
function getWorkflowModule() {
|
|
26
|
+
if (workflowModuleLoadError) {
|
|
27
|
+
throw workflowModuleLoadError;
|
|
28
|
+
}
|
|
29
|
+
return workflowModule;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Returns if an SDK flag was set
|
|
33
|
+
*
|
|
34
|
+
* Expects to be called only after `ensureWorkflowModuleLoaded`.
|
|
35
|
+
* Will throw if `@temporalio/workflow` is not available
|
|
36
|
+
*/
|
|
37
|
+
function hasSdkFlag(flag) {
|
|
38
|
+
const { SdkFlags } = require('@temporalio/workflow/lib/flags'); // eslint-disable-line @typescript-eslint/no-require-imports
|
|
39
|
+
const { getActivator } = require('@temporalio/workflow/lib/global-attributes'); // eslint-disable-line @typescript-eslint/no-require-imports
|
|
40
|
+
return getActivator().hasFlag(SdkFlags[flag]);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Checks if the workflow module loaded successfully and throws if not.
|
|
44
|
+
*/
|
|
45
|
+
function ensureWorkflowModuleLoaded() {
|
|
46
|
+
if (workflowModuleLoadError) {
|
|
47
|
+
throw workflowModuleLoadError;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Returns the workflow module if available, or undefined if it failed to load.
|
|
52
|
+
*/
|
|
53
|
+
function getWorkflowModuleIfAvailable() {
|
|
54
|
+
return workflowModule;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=workflow-module-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-module-loader.js","sourceRoot":"","sources":["../../src/workflow/workflow-module-loader.ts"],"names":[],"mappings":";;AA4BA,8CAKC;AAQD,gCAMC;AAKD,gEAIC;AAKD,oEAEC;AAtDD,uDAAuD;AACvD,8FAA8F;AAC9F,4EAA4E;AAC5E,2DAA2D;AAC3D,IAAI,cAAiD,CAAC;AACtD,IAAI,uBAAwC,CAAC;AAE7C,IAAI,CAAC;IACH,iEAAiE;IACjE,cAAc,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;AACnD,CAAC;AAAC,OAAO,GAAG,EAAE,CAAC;IACb,0EAA0E;IAC1E,uBAAuB,GAAG,GAAG,CAAC;AAChC,CAAC;AAED;;;GAGG;AACH,SAAgB,iBAAiB;IAC/B,IAAI,uBAAuB,EAAE,CAAC;QAC5B,MAAM,uBAAuB,CAAC;IAChC,CAAC;IACD,OAAO,cAAe,CAAC;AACzB,CAAC;AAED;;;;;GAKG;AACH,SAAgB,UAAU,CAAC,IAAoB;IAC7C,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,gCAAgC,CAAoD,CAAC,CAAC,4DAA4D;IAC/K,MAAM,EAAE,YAAY,EAAE,GACpB,OAAO,CAAC,4CAA4C,CAAgE,CAAC,CAAC,4DAA4D;IAEpL,OAAO,YAAY,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;AAChD,CAAC;AAED;;GAEG;AACH,SAAgB,0BAA0B;IACxC,IAAI,uBAAuB,EAAE,CAAC;QAC5B,MAAM,uBAAuB,CAAC;IAChC,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAgB,4BAA4B;IAC1C,OAAO,cAAc,CAAC;AACxB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@temporalio/interceptors-opentelemetry",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.2",
|
|
4
4
|
"description": "Temporal.io SDK interceptors bundle for tracing with opentelemetry",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "./lib/index.d.ts",
|
|
@@ -20,18 +20,20 @@
|
|
|
20
20
|
"@opentelemetry/sdk-trace-base": "^1.19.0"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@temporalio/activity": "1.13.
|
|
24
|
-
"@temporalio/client": "1.13.
|
|
25
|
-
"@temporalio/common": "1.13.
|
|
26
|
-
"@temporalio/worker": "1.13.
|
|
27
|
-
"@temporalio/workflow": "1.13.
|
|
23
|
+
"@temporalio/activity": "1.13.2",
|
|
24
|
+
"@temporalio/client": "1.13.2",
|
|
25
|
+
"@temporalio/common": "1.13.2",
|
|
26
|
+
"@temporalio/worker": "1.13.2",
|
|
27
|
+
"@temporalio/workflow": "1.13.2"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
30
|
-
"@temporalio/
|
|
31
|
-
"@temporalio/
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
"@temporalio/workflow":
|
|
30
|
+
"@temporalio/common": "1.13.2",
|
|
31
|
+
"@temporalio/workflow": "1.13.2"
|
|
32
|
+
},
|
|
33
|
+
"peerDependenciesMeta": {
|
|
34
|
+
"@temporalio/workflow": {
|
|
35
|
+
"optional": true
|
|
36
|
+
}
|
|
35
37
|
},
|
|
36
38
|
"bugs": {
|
|
37
39
|
"url": "https://github.com/temporalio/sdk-typescript/issues"
|
|
@@ -52,5 +54,5 @@
|
|
|
52
54
|
"src",
|
|
53
55
|
"lib"
|
|
54
56
|
],
|
|
55
|
-
"gitHead": "
|
|
57
|
+
"gitHead": "cccc54c72f85377ac520b5d6cdd9a9a847027c27"
|
|
56
58
|
}
|
package/src/client/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as otel from '@opentelemetry/api';
|
|
2
|
-
import { Next,
|
|
2
|
+
import type { Next, WorkflowSignalInput, WorkflowStartInput, WorkflowClientInterceptor } from '@temporalio/client';
|
|
3
3
|
import { instrument, headersWithContext, RUN_ID_ATTR_KEY } from '../instrumentation';
|
|
4
4
|
import { SpanName, SPAN_DELIMITER } from '../workflow';
|
|
5
5
|
|
package/src/instrumentation.ts
CHANGED
|
@@ -3,7 +3,12 @@
|
|
|
3
3
|
* @module
|
|
4
4
|
*/
|
|
5
5
|
import * as otel from '@opentelemetry/api';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
type Headers,
|
|
8
|
+
ApplicationFailure,
|
|
9
|
+
ApplicationFailureCategory,
|
|
10
|
+
defaultPayloadConverter,
|
|
11
|
+
} from '@temporalio/common';
|
|
7
12
|
|
|
8
13
|
/** Default trace header for opentelemetry interceptors */
|
|
9
14
|
export const TRACE_HEADER = '_tracer-data';
|
|
@@ -15,7 +20,7 @@ const payloadConverter = defaultPayloadConverter;
|
|
|
15
20
|
/**
|
|
16
21
|
* If found, return an otel Context deserialized from the provided headers
|
|
17
22
|
*/
|
|
18
|
-
export
|
|
23
|
+
export function extractContextFromHeaders(headers: Headers): otel.Context | undefined {
|
|
19
24
|
const encodedSpanContext = headers[TRACE_HEADER];
|
|
20
25
|
if (encodedSpanContext === undefined) {
|
|
21
26
|
return undefined;
|
|
@@ -27,7 +32,7 @@ export async function extractContextFromHeaders(headers: Headers): Promise<otel.
|
|
|
27
32
|
/**
|
|
28
33
|
* Given headers, return new headers with the current otel context inserted
|
|
29
34
|
*/
|
|
30
|
-
export
|
|
35
|
+
export function headersWithContext(headers: Headers): Headers {
|
|
31
36
|
const carrier = {};
|
|
32
37
|
otel.propagation.inject(otel.context.active(), carrier, otel.defaultTextMapSetter);
|
|
33
38
|
return { ...headers, [TRACE_HEADER]: payloadConverter.toPayload(carrier) };
|
|
@@ -43,8 +48,10 @@ async function wrapWithSpan<T>(
|
|
|
43
48
|
span.setStatus({ code: otel.SpanStatusCode.OK });
|
|
44
49
|
return ret;
|
|
45
50
|
} catch (err: any) {
|
|
51
|
+
const isBenignErr = err instanceof ApplicationFailure && err.category === ApplicationFailureCategory.BENIGN;
|
|
46
52
|
if (acceptableErrors === undefined || !acceptableErrors(err)) {
|
|
47
|
-
|
|
53
|
+
const statusCode = isBenignErr ? otel.SpanStatusCode.UNSET : otel.SpanStatusCode.ERROR;
|
|
54
|
+
span.setStatus({ code: statusCode, message: (err as Error).message ?? String(err) });
|
|
48
55
|
span.recordException(err);
|
|
49
56
|
} else {
|
|
50
57
|
span.setStatus({ code: otel.SpanStatusCode.OK });
|
package/src/worker/index.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import * as otel from '@opentelemetry/api';
|
|
2
|
-
import { Resource } from '@opentelemetry/resources';
|
|
3
|
-
import { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-base';
|
|
4
|
-
import { Context as ActivityContext } from '@temporalio/activity';
|
|
5
|
-
import {
|
|
6
|
-
|
|
2
|
+
import type { Resource } from '@opentelemetry/resources';
|
|
3
|
+
import type { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-base';
|
|
4
|
+
import type { Context as ActivityContext } from '@temporalio/activity';
|
|
5
|
+
import type {
|
|
6
|
+
Next,
|
|
7
7
|
ActivityInboundCallsInterceptor,
|
|
8
8
|
ActivityOutboundCallsInterceptor,
|
|
9
|
-
GetLogAttributesInput,
|
|
10
9
|
InjectedSink,
|
|
11
|
-
|
|
10
|
+
GetLogAttributesInput,
|
|
11
|
+
ActivityExecuteInput,
|
|
12
12
|
} from '@temporalio/worker';
|
|
13
13
|
import { instrument, extractContextFromHeaders } from '../instrumentation';
|
|
14
|
-
import { OpenTelemetryWorkflowExporter, SerializableSpan, SpanName, SPAN_DELIMITER } from '../workflow';
|
|
14
|
+
import { type OpenTelemetryWorkflowExporter, type SerializableSpan, SpanName, SPAN_DELIMITER } from '../workflow';
|
|
15
15
|
|
|
16
16
|
export interface InterceptorOptions {
|
|
17
17
|
readonly tracer?: otel.Tracer;
|
|
@@ -34,7 +34,7 @@ export class OpenTelemetryActivityInboundInterceptor implements ActivityInboundC
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
async execute(input: ActivityExecuteInput, next: Next<ActivityInboundCallsInterceptor, 'execute'>): Promise<unknown> {
|
|
37
|
-
const context =
|
|
37
|
+
const context = extractContextFromHeaders(input.headers);
|
|
38
38
|
const spanName = `${SpanName.ACTIVITY_EXECUTE}${SPAN_DELIMITER}${this.ctx.info.activityType}`;
|
|
39
39
|
return await instrument({ tracer: this.tracer, spanName, fn: () => next(input), context });
|
|
40
40
|
}
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import * as otel from '@opentelemetry/api';
|
|
2
|
-
import {
|
|
2
|
+
import { ensureWorkflowModuleLoaded, getWorkflowModuleIfAvailable } from './workflow-module-loader';
|
|
3
|
+
|
|
4
|
+
const AsyncLocalStorage = getWorkflowModuleIfAvailable()?.AsyncLocalStorage;
|
|
3
5
|
|
|
4
6
|
export class ContextManager implements otel.ContextManager {
|
|
5
|
-
|
|
7
|
+
// If `@temporalio/workflow` is not available, ignore for now.
|
|
8
|
+
// When ContextManager is constructed module resolution error will be thrown.
|
|
9
|
+
protected storage = AsyncLocalStorage ? new AsyncLocalStorage<otel.Context>() : undefined;
|
|
10
|
+
|
|
11
|
+
public constructor() {
|
|
12
|
+
ensureWorkflowModuleLoaded();
|
|
13
|
+
}
|
|
6
14
|
|
|
7
15
|
active(): otel.Context {
|
|
8
|
-
return this.storage
|
|
16
|
+
return this.storage!.getStore() || otel.ROOT_CONTEXT;
|
|
9
17
|
}
|
|
10
18
|
|
|
11
19
|
bind<T>(context: otel.Context, target: T): T {
|
|
@@ -36,7 +44,7 @@ export class ContextManager implements otel.ContextManager {
|
|
|
36
44
|
}
|
|
37
45
|
|
|
38
46
|
disable(): this {
|
|
39
|
-
this.storage
|
|
47
|
+
this.storage!.disable();
|
|
40
48
|
return this;
|
|
41
49
|
}
|
|
42
50
|
|
|
@@ -47,6 +55,6 @@ export class ContextManager implements otel.ContextManager {
|
|
|
47
55
|
...args: A
|
|
48
56
|
): ReturnType<F> {
|
|
49
57
|
const cb = thisArg == null ? fn : fn.bind(thisArg);
|
|
50
|
-
return this.storage
|
|
58
|
+
return this.storage!.run(context, cb, ...args);
|
|
51
59
|
}
|
|
52
60
|
}
|
package/src/workflow/index.ts
CHANGED
|
@@ -3,9 +3,8 @@
|
|
|
3
3
|
import './runtime'; // Patch the Workflow isolate runtime for opentelemetry
|
|
4
4
|
import * as otel from '@opentelemetry/api';
|
|
5
5
|
import * as tracing from '@opentelemetry/sdk-trace-base';
|
|
6
|
-
import {
|
|
6
|
+
import type {
|
|
7
7
|
ActivityInput,
|
|
8
|
-
ContinueAsNew,
|
|
9
8
|
ContinueAsNewInput,
|
|
10
9
|
DisposeInput,
|
|
11
10
|
GetLogAttributesInput,
|
|
@@ -16,7 +15,6 @@ import {
|
|
|
16
15
|
StartChildWorkflowExecutionInput,
|
|
17
16
|
WorkflowExecuteInput,
|
|
18
17
|
WorkflowInboundCallsInterceptor,
|
|
19
|
-
workflowInfo,
|
|
20
18
|
WorkflowInternalsInterceptor,
|
|
21
19
|
WorkflowOutboundCallsInterceptor,
|
|
22
20
|
} from '@temporalio/workflow';
|
|
@@ -24,6 +22,7 @@ import { instrument, extractContextFromHeaders, headersWithContext } from '../in
|
|
|
24
22
|
import { ContextManager } from './context-manager';
|
|
25
23
|
import { SpanName, SPAN_DELIMITER } from './definitions';
|
|
26
24
|
import { SpanExporter } from './span-exporter';
|
|
25
|
+
import { ensureWorkflowModuleLoaded, getWorkflowModule, hasSdkFlag } from './workflow-module-loader';
|
|
27
26
|
|
|
28
27
|
export * from './definitions';
|
|
29
28
|
|
|
@@ -48,15 +47,25 @@ function getTracer(): otel.Tracer {
|
|
|
48
47
|
*
|
|
49
48
|
* Wraps the operation in an opentelemetry Span and links it to a parent Span context if one is
|
|
50
49
|
* provided in the Workflow input headers.
|
|
50
|
+
*
|
|
51
|
+
* `@temporalio/workflow` must be provided by host package in order to function.
|
|
51
52
|
*/
|
|
52
53
|
export class OpenTelemetryInboundInterceptor implements WorkflowInboundCallsInterceptor {
|
|
53
54
|
protected readonly tracer = getTracer();
|
|
54
55
|
|
|
56
|
+
public constructor() {
|
|
57
|
+
ensureWorkflowModuleLoaded();
|
|
58
|
+
}
|
|
59
|
+
|
|
55
60
|
public async execute(
|
|
56
61
|
input: WorkflowExecuteInput,
|
|
57
62
|
next: Next<WorkflowInboundCallsInterceptor, 'execute'>
|
|
58
63
|
): Promise<unknown> {
|
|
59
|
-
const
|
|
64
|
+
const { workflowInfo, ContinueAsNew } = getWorkflowModule();
|
|
65
|
+
|
|
66
|
+
const context = extractContextFromHeaders(input.headers);
|
|
67
|
+
if (!hasSdkFlag('OpenTelemetryInterceporsAvoidsExtraYields')) await Promise.resolve();
|
|
68
|
+
|
|
60
69
|
return await instrument({
|
|
61
70
|
tracer: this.tracer,
|
|
62
71
|
spanName: `${SpanName.WORKFLOW_EXECUTE}${SPAN_DELIMITER}${workflowInfo().workflowType}`,
|
|
@@ -70,7 +79,12 @@ export class OpenTelemetryInboundInterceptor implements WorkflowInboundCallsInte
|
|
|
70
79
|
input: SignalInput,
|
|
71
80
|
next: Next<WorkflowInboundCallsInterceptor, 'handleSignal'>
|
|
72
81
|
): Promise<void> {
|
|
73
|
-
|
|
82
|
+
// Tracing of inbound signals was added in v1.11.5.
|
|
83
|
+
if (!hasSdkFlag('OpenTelemetryInterceptorsTracesInboundSignals')) return next(input);
|
|
84
|
+
|
|
85
|
+
const context = extractContextFromHeaders(input.headers);
|
|
86
|
+
if (!hasSdkFlag('OpenTelemetryInterceporsAvoidsExtraYields')) await Promise.resolve();
|
|
87
|
+
|
|
74
88
|
return await instrument({
|
|
75
89
|
tracer: this.tracer,
|
|
76
90
|
spanName: `${SpanName.WORKFLOW_SIGNAL}${SPAN_DELIMITER}${input.signalName}`,
|
|
@@ -84,10 +98,16 @@ export class OpenTelemetryInboundInterceptor implements WorkflowInboundCallsInte
|
|
|
84
98
|
* Intercepts outbound calls to schedule an Activity
|
|
85
99
|
*
|
|
86
100
|
* Wraps the operation in an opentelemetry Span and passes it to the Activity via headers.
|
|
101
|
+
*
|
|
102
|
+
* `@temporalio/workflow` must be provided by host package in order to function.
|
|
87
103
|
*/
|
|
88
104
|
export class OpenTelemetryOutboundInterceptor implements WorkflowOutboundCallsInterceptor {
|
|
89
105
|
protected readonly tracer = getTracer();
|
|
90
106
|
|
|
107
|
+
public constructor() {
|
|
108
|
+
ensureWorkflowModuleLoaded();
|
|
109
|
+
}
|
|
110
|
+
|
|
91
111
|
public async scheduleActivity(
|
|
92
112
|
input: ActivityInput,
|
|
93
113
|
next: Next<WorkflowOutboundCallsInterceptor, 'scheduleActivity'>
|
|
@@ -96,7 +116,9 @@ export class OpenTelemetryOutboundInterceptor implements WorkflowOutboundCallsIn
|
|
|
96
116
|
tracer: this.tracer,
|
|
97
117
|
spanName: `${SpanName.ACTIVITY_START}${SPAN_DELIMITER}${input.activityType}`,
|
|
98
118
|
fn: async () => {
|
|
99
|
-
const headers =
|
|
119
|
+
const headers = headersWithContext(input.headers);
|
|
120
|
+
if (!hasSdkFlag('OpenTelemetryInterceporsAvoidsExtraYields')) await Promise.resolve();
|
|
121
|
+
|
|
100
122
|
return next({
|
|
101
123
|
...input,
|
|
102
124
|
headers,
|
|
@@ -109,11 +131,16 @@ export class OpenTelemetryOutboundInterceptor implements WorkflowOutboundCallsIn
|
|
|
109
131
|
input: LocalActivityInput,
|
|
110
132
|
next: Next<WorkflowOutboundCallsInterceptor, 'scheduleLocalActivity'>
|
|
111
133
|
): Promise<unknown> {
|
|
134
|
+
// Tracing of local activities was added in v1.11.6.
|
|
135
|
+
if (!hasSdkFlag('OpenTelemetryInterceptorsTracesLocalActivities')) return next(input);
|
|
136
|
+
|
|
112
137
|
return await instrument({
|
|
113
138
|
tracer: this.tracer,
|
|
114
139
|
spanName: `${SpanName.ACTIVITY_START}${SPAN_DELIMITER}${input.activityType}`,
|
|
115
140
|
fn: async () => {
|
|
116
|
-
const headers =
|
|
141
|
+
const headers = headersWithContext(input.headers);
|
|
142
|
+
if (!hasSdkFlag('OpenTelemetryInterceporsAvoidsExtraYields')) await Promise.resolve();
|
|
143
|
+
|
|
117
144
|
return next({
|
|
118
145
|
...input,
|
|
119
146
|
headers,
|
|
@@ -130,7 +157,9 @@ export class OpenTelemetryOutboundInterceptor implements WorkflowOutboundCallsIn
|
|
|
130
157
|
tracer: this.tracer,
|
|
131
158
|
spanName: `${SpanName.CHILD_WORKFLOW_START}${SPAN_DELIMITER}${input.workflowType}`,
|
|
132
159
|
fn: async () => {
|
|
133
|
-
const headers =
|
|
160
|
+
const headers = headersWithContext(input.headers);
|
|
161
|
+
if (!hasSdkFlag('OpenTelemetryInterceporsAvoidsExtraYields')) await Promise.resolve();
|
|
162
|
+
|
|
134
163
|
return next({
|
|
135
164
|
...input,
|
|
136
165
|
headers,
|
|
@@ -143,11 +172,14 @@ export class OpenTelemetryOutboundInterceptor implements WorkflowOutboundCallsIn
|
|
|
143
172
|
input: ContinueAsNewInput,
|
|
144
173
|
next: Next<WorkflowOutboundCallsInterceptor, 'continueAsNew'>
|
|
145
174
|
): Promise<never> {
|
|
175
|
+
const { ContinueAsNew } = getWorkflowModule();
|
|
146
176
|
return await instrument({
|
|
147
177
|
tracer: this.tracer,
|
|
148
178
|
spanName: `${SpanName.CONTINUE_AS_NEW}${SPAN_DELIMITER}${input.options.workflowType}`,
|
|
149
179
|
fn: async () => {
|
|
150
|
-
const headers =
|
|
180
|
+
const headers = headersWithContext(input.headers);
|
|
181
|
+
if (!hasSdkFlag('OpenTelemetryInterceporsAvoidsExtraYields')) await Promise.resolve();
|
|
182
|
+
|
|
151
183
|
return next({
|
|
152
184
|
...input,
|
|
153
185
|
headers,
|
|
@@ -165,7 +197,9 @@ export class OpenTelemetryOutboundInterceptor implements WorkflowOutboundCallsIn
|
|
|
165
197
|
tracer: this.tracer,
|
|
166
198
|
spanName: `${SpanName.WORKFLOW_SIGNAL}${SPAN_DELIMITER}${input.signalName}`,
|
|
167
199
|
fn: async () => {
|
|
168
|
-
const headers =
|
|
200
|
+
const headers = headersWithContext(input.headers);
|
|
201
|
+
if (!hasSdkFlag('OpenTelemetryInterceporsAvoidsExtraYields')) await Promise.resolve();
|
|
202
|
+
|
|
169
203
|
return next({
|
|
170
204
|
...input,
|
|
171
205
|
headers,
|
package/src/workflow/runtime.ts
CHANGED
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
* Sets global variables required for importing opentelemetry in isolate
|
|
3
3
|
* @module
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
5
|
+
import { getWorkflowModuleIfAvailable } from './workflow-module-loader';
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
const inWorkflowContext = getWorkflowModuleIfAvailable()?.inWorkflowContext;
|
|
8
|
+
|
|
9
|
+
if (inWorkflowContext?.()) {
|
|
8
10
|
// Required by opentelemetry (pretend to be a browser)
|
|
9
11
|
Object.assign(globalThis, {
|
|
10
12
|
performance: {
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import * as tracing from '@opentelemetry/sdk-trace-base';
|
|
2
2
|
import { ExportResult, ExportResultCode } from '@opentelemetry/core';
|
|
3
|
-
import * as wf from '@temporalio/workflow';
|
|
4
3
|
import { OpenTelemetrySinks, SerializableSpan } from './definitions';
|
|
4
|
+
import { ensureWorkflowModuleLoaded, getWorkflowModuleIfAvailable } from './workflow-module-loader';
|
|
5
5
|
|
|
6
|
-
const
|
|
6
|
+
const exporter = getWorkflowModuleIfAvailable()?.proxySinks<OpenTelemetrySinks>()?.exporter;
|
|
7
7
|
|
|
8
8
|
export class SpanExporter implements tracing.SpanExporter {
|
|
9
|
+
public constructor() {
|
|
10
|
+
ensureWorkflowModuleLoaded();
|
|
11
|
+
}
|
|
12
|
+
|
|
9
13
|
public export(spans: tracing.ReadableSpan[], resultCallback: (result: ExportResult) => void): void {
|
|
10
|
-
exporter
|
|
14
|
+
exporter!.export(spans.map((span) => this.makeSerializable(span)));
|
|
11
15
|
resultCallback({ code: ExportResultCode.SUCCESS });
|
|
12
16
|
}
|
|
13
17
|
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utilities for working with a possibly missing `@temporalio/workflow` peer dependency
|
|
3
|
+
* @module
|
|
4
|
+
*/
|
|
5
|
+
import type * as WorkflowModule from '@temporalio/workflow';
|
|
6
|
+
import type { SdkFlags as SdkFlagsT } from '@temporalio/workflow/lib/flags';
|
|
7
|
+
|
|
8
|
+
type SdkFlags = typeof SdkFlagsT;
|
|
9
|
+
|
|
10
|
+
// @temporalio/workflow is an optional peer dependency.
|
|
11
|
+
// It can be missing as long as the user isn't attempting to construct a workflow interceptor.
|
|
12
|
+
// If we start shipping ES modules alongside CJS, we will have to reconsider
|
|
13
|
+
// this dynamic import as `import` is async for ES modules.
|
|
14
|
+
let workflowModule: typeof WorkflowModule | undefined;
|
|
15
|
+
let workflowModuleLoadError: any | undefined;
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
19
|
+
workflowModule = require('@temporalio/workflow');
|
|
20
|
+
} catch (err) {
|
|
21
|
+
// Capture the module not found error to rethrow if the module is required
|
|
22
|
+
workflowModuleLoadError = err;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Returns `@temporalio/workflow` module if present.
|
|
27
|
+
* Throws if the module failed to load
|
|
28
|
+
*/
|
|
29
|
+
export function getWorkflowModule(): typeof WorkflowModule {
|
|
30
|
+
if (workflowModuleLoadError) {
|
|
31
|
+
throw workflowModuleLoadError;
|
|
32
|
+
}
|
|
33
|
+
return workflowModule!;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Returns if an SDK flag was set
|
|
38
|
+
*
|
|
39
|
+
* Expects to be called only after `ensureWorkflowModuleLoaded`.
|
|
40
|
+
* Will throw if `@temporalio/workflow` is not available
|
|
41
|
+
*/
|
|
42
|
+
export function hasSdkFlag(flag: keyof SdkFlags): boolean {
|
|
43
|
+
const { SdkFlags } = require('@temporalio/workflow/lib/flags') as typeof import('@temporalio/workflow/lib/flags'); // eslint-disable-line @typescript-eslint/no-require-imports
|
|
44
|
+
const { getActivator } =
|
|
45
|
+
require('@temporalio/workflow/lib/global-attributes') as typeof import('@temporalio/workflow/lib/global-attributes'); // eslint-disable-line @typescript-eslint/no-require-imports
|
|
46
|
+
|
|
47
|
+
return getActivator().hasFlag(SdkFlags[flag]);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Checks if the workflow module loaded successfully and throws if not.
|
|
52
|
+
*/
|
|
53
|
+
export function ensureWorkflowModuleLoaded(): void {
|
|
54
|
+
if (workflowModuleLoadError) {
|
|
55
|
+
throw workflowModuleLoadError;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Returns the workflow module if available, or undefined if it failed to load.
|
|
61
|
+
*/
|
|
62
|
+
export function getWorkflowModuleIfAvailable(): typeof WorkflowModule | undefined {
|
|
63
|
+
return workflowModule;
|
|
64
|
+
}
|