@hatchet-dev/typescript-sdk 1.17.1 → 1.18.0
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/clients/event/event-client.d.ts +8 -0
- package/clients/event/event-client.js +8 -0
- package/clients/hatchet-client/client-config.d.ts +45 -0
- package/clients/hatchet-client/client-config.js +14 -1
- package/opentelemetry/hatchet-exporter.d.ts +24 -0
- package/opentelemetry/hatchet-exporter.js +123 -0
- package/opentelemetry/hatchet-span-context.d.ts +22 -0
- package/opentelemetry/hatchet-span-context.js +27 -0
- package/opentelemetry/index.d.ts +3 -0
- package/opentelemetry/index.js +7 -0
- package/opentelemetry/instrumentor.d.ts +78 -0
- package/opentelemetry/instrumentor.js +595 -0
- package/opentelemetry/types.d.ts +6 -0
- package/opentelemetry/types.js +8 -0
- package/package.json +6 -1
- package/util/config-loader/config-loader.d.ts +1 -0
- package/util/config-loader/config-loader.js +18 -4
- package/util/opentelemetry.d.ts +34 -0
- package/util/opentelemetry.js +38 -0
- package/v1/client/admin.d.ts +6 -0
- package/v1/client/admin.js +6 -0
- package/v1/client/features/metrics.d.ts +11 -0
- package/v1/client/features/metrics.js +20 -0
- package/v1/client/features/schedules.d.ts +3 -0
- package/v1/client/features/schedules.js +3 -0
- package/v1/client/worker/worker-internal.d.ts +10 -2
- package/v1/client/worker/worker-internal.js +13 -2
- package/v1/examples/opentelemetry_instrumentation/run.d.ts +1 -0
- package/v1/examples/opentelemetry_instrumentation/run.js +57 -0
- package/v1/examples/opentelemetry_instrumentation/setup.d.ts +9 -0
- package/v1/examples/opentelemetry_instrumentation/setup.js +26 -0
- package/v1/examples/opentelemetry_instrumentation/worker.d.ts +7 -0
- package/v1/examples/opentelemetry_instrumentation/worker.js +123 -0
- package/version.d.ts +1 -1
- package/version.js +1 -1
|
@@ -44,7 +44,7 @@ const token_1 = require("./token");
|
|
|
44
44
|
const DEFAULT_CONFIG_FILE = '.hatchet.yaml';
|
|
45
45
|
class ConfigLoader {
|
|
46
46
|
static loadClientConfig(override, config) {
|
|
47
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8;
|
|
47
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10;
|
|
48
48
|
const yaml = this.loadYamlConfig(config === null || config === void 0 ? void 0 : config.path);
|
|
49
49
|
const tlsConfig = (_a = override === null || override === void 0 ? void 0 : override.tls_config) !== null && _a !== void 0 ? _a : {
|
|
50
50
|
tls_strategy: (_d = (_c = (_b = yaml === null || yaml === void 0 ? void 0 : yaml.tls_config) === null || _b === void 0 ? void 0 : _b.tls_strategy) !== null && _c !== void 0 ? _c : this.env('HATCHET_CLIENT_TLS_STRATEGY')) !== null && _d !== void 0 ? _d : 'tls',
|
|
@@ -74,7 +74,7 @@ class ConfigLoader {
|
|
|
74
74
|
apiUrl =
|
|
75
75
|
(_x = (_w = (_v = override === null || override === void 0 ? void 0 : override.api_url) !== null && _v !== void 0 ? _v : yaml === null || yaml === void 0 ? void 0 : yaml.api_url) !== null && _w !== void 0 ? _w : this.env('HATCHET_CLIENT_API_URL')) !== null && _x !== void 0 ? _x : addresses.serverUrl;
|
|
76
76
|
}
|
|
77
|
-
catch (
|
|
77
|
+
catch (_11) {
|
|
78
78
|
grpcBroadcastAddress =
|
|
79
79
|
(_z = (_y = override === null || override === void 0 ? void 0 : override.host_port) !== null && _y !== void 0 ? _y : yaml === null || yaml === void 0 ? void 0 : yaml.host_port) !== null && _z !== void 0 ? _z : this.env('HATCHET_CLIENT_HOST_PORT');
|
|
80
80
|
apiUrl = (_1 = (_0 = override === null || override === void 0 ? void 0 : override.api_url) !== null && _0 !== void 0 ? _0 : yaml === null || yaml === void 0 ? void 0 : yaml.api_url) !== null && _1 !== void 0 ? _1 : this.env('HATCHET_CLIENT_API_URL');
|
|
@@ -83,17 +83,31 @@ class ConfigLoader {
|
|
|
83
83
|
if (namespace && !(namespace === null || namespace === void 0 ? void 0 : namespace.endsWith('_'))) {
|
|
84
84
|
namespace = `${namespace}_`;
|
|
85
85
|
}
|
|
86
|
+
const otelConfig = (_5 = (_4 = override === null || override === void 0 ? void 0 : override.otel) !== null && _4 !== void 0 ? _4 : yaml === null || yaml === void 0 ? void 0 : yaml.otel) !== null && _5 !== void 0 ? _5 : {
|
|
87
|
+
excludedAttributes: this.parseJsonArray(this.env('HATCHET_CLIENT_OPENTELEMETRY_EXCLUDED_ATTRIBUTES') || '[]'),
|
|
88
|
+
includeTaskNameInSpanName: this.env('HATCHET_CLIENT_OPENTELEMETRY_INCLUDE_TASK_NAME_IN_SPAN_NAME') === 'true',
|
|
89
|
+
};
|
|
86
90
|
return {
|
|
87
|
-
token: (
|
|
91
|
+
token: (_7 = (_6 = override === null || override === void 0 ? void 0 : override.token) !== null && _6 !== void 0 ? _6 : yaml === null || yaml === void 0 ? void 0 : yaml.token) !== null && _7 !== void 0 ? _7 : this.env('HATCHET_CLIENT_TOKEN'),
|
|
88
92
|
host_port: grpcBroadcastAddress,
|
|
89
93
|
api_url: apiUrl,
|
|
90
94
|
tls_config: tlsConfig,
|
|
91
95
|
healthcheck: healthCheckConfig,
|
|
92
|
-
log_level: (
|
|
96
|
+
log_level: (_10 = (_9 = (_8 = override === null || override === void 0 ? void 0 : override.log_level) !== null && _8 !== void 0 ? _8 : yaml === null || yaml === void 0 ? void 0 : yaml.log_level) !== null && _9 !== void 0 ? _9 : this.env('HATCHET_CLIENT_LOG_LEVEL')) !== null && _10 !== void 0 ? _10 : 'INFO',
|
|
93
97
|
tenant_id: tenantId,
|
|
94
98
|
namespace: namespace ? `${namespace}`.toLowerCase() : '',
|
|
99
|
+
otel: otelConfig,
|
|
95
100
|
};
|
|
96
101
|
}
|
|
102
|
+
static parseJsonArray(value) {
|
|
103
|
+
try {
|
|
104
|
+
const parsed = JSON.parse(value);
|
|
105
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
106
|
+
}
|
|
107
|
+
catch (_a) {
|
|
108
|
+
return [];
|
|
109
|
+
}
|
|
110
|
+
}
|
|
97
111
|
static get default_yaml_config_path() {
|
|
98
112
|
return p.join(process.cwd(), DEFAULT_CONFIG_FILE);
|
|
99
113
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export declare const OTelAttribute: {
|
|
2
|
+
readonly NAMESPACE: "namespace";
|
|
3
|
+
readonly ADDITIONAL_METADATA: "additional_metadata";
|
|
4
|
+
readonly WORKFLOW_NAME: "workflow_name";
|
|
5
|
+
readonly PRIORITY: "priority";
|
|
6
|
+
readonly ACTION_PAYLOAD: "payload";
|
|
7
|
+
readonly ACTION_NAME: "action_name";
|
|
8
|
+
readonly STEP_NAME: "step_name";
|
|
9
|
+
readonly CHILD_WORKFLOW_INDEX: "child_workflow_index";
|
|
10
|
+
readonly CHILD_WORKFLOW_KEY: "child_workflow_key";
|
|
11
|
+
readonly PARENT_WORKFLOW_RUN_ID: "parent_workflow_run_id";
|
|
12
|
+
readonly RETRY_COUNT: "retry_count";
|
|
13
|
+
readonly STEP_ID: "step_id";
|
|
14
|
+
readonly STEP_RUN_ID: "step_run_id";
|
|
15
|
+
readonly TENANT_ID: "tenant_id";
|
|
16
|
+
readonly WORKER_ID: "worker_id";
|
|
17
|
+
readonly WORKFLOW_ID: "workflow_id";
|
|
18
|
+
readonly WORKFLOW_RUN_ID: "workflow_run_id";
|
|
19
|
+
readonly WORKFLOW_VERSION_ID: "workflow_version_id";
|
|
20
|
+
readonly EVENT_KEY: "event_key";
|
|
21
|
+
readonly FILTER_SCOPE: "scope";
|
|
22
|
+
readonly PARENT_ID: "parent_id";
|
|
23
|
+
readonly PARENT_STEP_RUN_ID: "parent_step_run_id";
|
|
24
|
+
readonly CHILD_INDEX: "child_index";
|
|
25
|
+
readonly CHILD_KEY: "child_key";
|
|
26
|
+
readonly DESIRED_WORKER_ID: "desired_worker_id";
|
|
27
|
+
readonly STICKY: "sticky";
|
|
28
|
+
readonly KEY: "key";
|
|
29
|
+
readonly RUN_AT_TIMESTAMPS: "run_at_timestamps";
|
|
30
|
+
};
|
|
31
|
+
export type OTelAttributeType = (typeof OTelAttribute)[keyof typeof OTelAttribute];
|
|
32
|
+
type ActionOTelAttributeKey = 'TENANT_ID' | 'WORKER_ID' | 'WORKFLOW_RUN_ID' | 'STEP_ID' | 'STEP_RUN_ID' | 'RETRY_COUNT' | 'PARENT_WORKFLOW_RUN_ID' | 'CHILD_WORKFLOW_INDEX' | 'CHILD_WORKFLOW_KEY' | 'ACTION_PAYLOAD' | 'WORKFLOW_NAME' | 'ACTION_NAME' | 'STEP_NAME' | 'WORKFLOW_ID' | 'WORKFLOW_VERSION_ID';
|
|
33
|
+
export type ActionOTelAttributeValue = (typeof OTelAttribute)[ActionOTelAttributeKey];
|
|
34
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OTelAttribute = void 0;
|
|
4
|
+
exports.OTelAttribute = {
|
|
5
|
+
// Shared
|
|
6
|
+
NAMESPACE: 'namespace',
|
|
7
|
+
ADDITIONAL_METADATA: 'additional_metadata',
|
|
8
|
+
WORKFLOW_NAME: 'workflow_name',
|
|
9
|
+
PRIORITY: 'priority',
|
|
10
|
+
ACTION_PAYLOAD: 'payload',
|
|
11
|
+
// Action
|
|
12
|
+
ACTION_NAME: 'action_name',
|
|
13
|
+
STEP_NAME: 'step_name',
|
|
14
|
+
CHILD_WORKFLOW_INDEX: 'child_workflow_index',
|
|
15
|
+
CHILD_WORKFLOW_KEY: 'child_workflow_key',
|
|
16
|
+
PARENT_WORKFLOW_RUN_ID: 'parent_workflow_run_id',
|
|
17
|
+
RETRY_COUNT: 'retry_count',
|
|
18
|
+
STEP_ID: 'step_id',
|
|
19
|
+
STEP_RUN_ID: 'step_run_id',
|
|
20
|
+
TENANT_ID: 'tenant_id',
|
|
21
|
+
WORKER_ID: 'worker_id',
|
|
22
|
+
WORKFLOW_ID: 'workflow_id',
|
|
23
|
+
WORKFLOW_RUN_ID: 'workflow_run_id',
|
|
24
|
+
WORKFLOW_VERSION_ID: 'workflow_version_id',
|
|
25
|
+
// Push Event
|
|
26
|
+
EVENT_KEY: 'event_key',
|
|
27
|
+
FILTER_SCOPE: 'scope',
|
|
28
|
+
// Trigger Workflow
|
|
29
|
+
PARENT_ID: 'parent_id',
|
|
30
|
+
PARENT_STEP_RUN_ID: 'parent_step_run_id',
|
|
31
|
+
CHILD_INDEX: 'child_index',
|
|
32
|
+
CHILD_KEY: 'child_key',
|
|
33
|
+
DESIRED_WORKER_ID: 'desired_worker_id',
|
|
34
|
+
STICKY: 'sticky',
|
|
35
|
+
KEY: 'key',
|
|
36
|
+
// Schedule Workflow
|
|
37
|
+
RUN_AT_TIMESTAMPS: 'run_at_timestamps',
|
|
38
|
+
};
|
package/v1/client/admin.d.ts
CHANGED
|
@@ -53,6 +53,9 @@ export declare class AdminClient {
|
|
|
53
53
|
* @param input an object containing the input to the workflow
|
|
54
54
|
* @param options an object containing the options to run the workflow
|
|
55
55
|
* @returns the ID of the new workflow run
|
|
56
|
+
*
|
|
57
|
+
* @important This method is instrumented by HatchetInstrumentor._patchRunWorkflow.
|
|
58
|
+
* Keep the signature in sync with the instrumentor wrapper.
|
|
56
59
|
*/
|
|
57
60
|
runWorkflow<Q = object, P = object>(workflowName: string, input: Q, options?: {
|
|
58
61
|
parentId?: string | undefined;
|
|
@@ -80,6 +83,9 @@ export declare class AdminClient {
|
|
|
80
83
|
* Order is preserved in the response.
|
|
81
84
|
* @param workflowRuns an array of objects containing the workflow name, input, and options for each workflow run
|
|
82
85
|
* @returns an array of workflow run references
|
|
86
|
+
*
|
|
87
|
+
* @important This method is instrumented by HatchetInstrumentor._patchRunWorkflows.
|
|
88
|
+
* Keep the signature in sync with the instrumentor wrapper.
|
|
83
89
|
*/
|
|
84
90
|
runWorkflows<Q = object, P = object>(workflowRuns: Array<{
|
|
85
91
|
workflowName: string;
|
package/v1/client/admin.js
CHANGED
|
@@ -76,6 +76,9 @@ class AdminClient {
|
|
|
76
76
|
* @param input an object containing the input to the workflow
|
|
77
77
|
* @param options an object containing the options to run the workflow
|
|
78
78
|
* @returns the ID of the new workflow run
|
|
79
|
+
*
|
|
80
|
+
* @important This method is instrumented by HatchetInstrumentor._patchRunWorkflow.
|
|
81
|
+
* Keep the signature in sync with the instrumentor wrapper.
|
|
79
82
|
*/
|
|
80
83
|
runWorkflow(workflowName, input, options) {
|
|
81
84
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -105,6 +108,9 @@ class AdminClient {
|
|
|
105
108
|
* Order is preserved in the response.
|
|
106
109
|
* @param workflowRuns an array of objects containing the workflow name, input, and options for each workflow run
|
|
107
110
|
* @returns an array of workflow run references
|
|
111
|
+
*
|
|
112
|
+
* @important This method is instrumented by HatchetInstrumentor._patchRunWorkflows.
|
|
113
|
+
* Keep the signature in sync with the instrumentor wrapper.
|
|
108
114
|
*/
|
|
109
115
|
runWorkflows(workflowRuns_1) {
|
|
110
116
|
return __awaiter(this, arguments, void 0, function* (workflowRuns, batchSize = 500) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { TaskStats } from '../../../clients/rest/generated/data-contracts';
|
|
1
2
|
import { HatchetClient } from '../client';
|
|
2
3
|
export type TaskStatusMetrics = {
|
|
3
4
|
cancelled: number;
|
|
@@ -26,4 +27,14 @@ export declare class MetricsClient {
|
|
|
26
27
|
* @returns The queue metrics for the current tenant.
|
|
27
28
|
*/
|
|
28
29
|
getQueueMetrics(opts?: Parameters<typeof this.api.tenantGetStepRunQueueMetrics>[1]): Promise<import("../../../clients/rest/generated/data-contracts").TenantStepRunQueueMetrics>;
|
|
30
|
+
/**
|
|
31
|
+
* Scrape Prometheus metrics for the tenant.
|
|
32
|
+
* @returns The metrics in Prometheus text format.
|
|
33
|
+
*/
|
|
34
|
+
scrapePrometheusMetrics(): Promise<string>;
|
|
35
|
+
/**
|
|
36
|
+
* Get task statistics for the tenant.
|
|
37
|
+
* @returns A record mapping task names to their statistics.
|
|
38
|
+
*/
|
|
39
|
+
getTaskStats(): Promise<TaskStats>;
|
|
29
40
|
}
|
|
@@ -44,5 +44,25 @@ class MetricsClient {
|
|
|
44
44
|
return data;
|
|
45
45
|
});
|
|
46
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Scrape Prometheus metrics for the tenant.
|
|
49
|
+
* @returns The metrics in Prometheus text format.
|
|
50
|
+
*/
|
|
51
|
+
scrapePrometheusMetrics() {
|
|
52
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
53
|
+
const { data } = yield this.api.tenantGetPrometheusMetrics(this.tenantId);
|
|
54
|
+
return data;
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Get task statistics for the tenant.
|
|
59
|
+
* @returns A record mapping task names to their statistics.
|
|
60
|
+
*/
|
|
61
|
+
getTaskStats() {
|
|
62
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
63
|
+
const { data } = yield this.api.tenantGetTaskStats(this.tenantId);
|
|
64
|
+
return data;
|
|
65
|
+
});
|
|
66
|
+
}
|
|
47
67
|
}
|
|
48
68
|
exports.MetricsClient = MetricsClient;
|
|
@@ -62,6 +62,9 @@ export declare class ScheduleClient {
|
|
|
62
62
|
* @param scheduledRun - The input data for creating the Scheduled Run.
|
|
63
63
|
* @returns A promise that resolves to the created ScheduledWorkflows object.
|
|
64
64
|
* @throws Will throw an error if the input is invalid or the API call fails.
|
|
65
|
+
*
|
|
66
|
+
* @important This method is instrumented by HatchetInstrumentor._patchScheduleCreate.
|
|
67
|
+
* Keep the signature in sync with the instrumentor wrapper.
|
|
65
68
|
*/
|
|
66
69
|
create(workflow: string | Workflow, cron: CreateScheduledRunInput): Promise<ScheduledWorkflows>;
|
|
67
70
|
/**
|
|
@@ -71,6 +71,9 @@ class ScheduleClient {
|
|
|
71
71
|
* @param scheduledRun - The input data for creating the Scheduled Run.
|
|
72
72
|
* @returns A promise that resolves to the created ScheduledWorkflows object.
|
|
73
73
|
* @throws Will throw an error if the input is invalid or the API call fails.
|
|
74
|
+
*
|
|
75
|
+
* @important This method is instrumented by HatchetInstrumentor._patchScheduleCreate.
|
|
76
|
+
* Keep the signature in sync with the instrumentor wrapper.
|
|
74
77
|
*/
|
|
75
78
|
create(workflow, cron) {
|
|
76
79
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -64,9 +64,17 @@ export declare class InternalWorker {
|
|
|
64
64
|
registerWorkflow(initWorkflow: BaseWorkflowDeclaration<any, any>, durable?: boolean): Promise<void>;
|
|
65
65
|
private ensureEvictionManager;
|
|
66
66
|
private cleanupRun;
|
|
67
|
-
|
|
67
|
+
/**
|
|
68
|
+
* @important This method is instrumented by HatchetInstrumentor._patchHandleStartStepRun.
|
|
69
|
+
* Keep the signature in sync with the instrumentor wrapper.
|
|
70
|
+
*/
|
|
71
|
+
handleStartStepRun(action: Action): Promise<Error | undefined>;
|
|
68
72
|
getStepActionEvent(action: Action, eventType: StepActionEventType, shouldNotRetry: boolean, payload?: any, retryCount?: number): StepActionEvent;
|
|
69
73
|
getGroupKeyActionEvent(action: Action, eventType: GroupKeyActionEventType, payload?: any): GroupKeyActionEvent;
|
|
74
|
+
/**
|
|
75
|
+
* @important This method is instrumented by HatchetInstrumentor._patchHandleCancelStepRun.
|
|
76
|
+
* Keep the signature in sync with the instrumentor wrapper.
|
|
77
|
+
*/
|
|
70
78
|
handleCancelStepRun(action: Action): Promise<void>;
|
|
71
79
|
stop(): Promise<void>;
|
|
72
80
|
exitGracefully(handleKill: boolean): Promise<void>;
|
|
@@ -76,7 +84,7 @@ export declare class InternalWorker {
|
|
|
76
84
|
*/
|
|
77
85
|
protected createListener(): Promise<ActionListener>;
|
|
78
86
|
start(): Promise<void>;
|
|
79
|
-
handleAction(action: Action): Promise<void>;
|
|
87
|
+
handleAction(action: Action): Promise<void | Error>;
|
|
80
88
|
upsertLabels(labels: WorkerLabels): Promise<WorkerLabels>;
|
|
81
89
|
}
|
|
82
90
|
export declare function mapRateLimitPb(limits: CreateWorkflowTaskOpts<any, any>['rateLimits']): CreateStepRateLimit[];
|
|
@@ -394,6 +394,10 @@ class InternalWorker {
|
|
|
394
394
|
delete this.futures[key];
|
|
395
395
|
delete this.contexts[key];
|
|
396
396
|
}
|
|
397
|
+
/**
|
|
398
|
+
* @important This method is instrumented by HatchetInstrumentor._patchHandleStartStepRun.
|
|
399
|
+
* Keep the signature in sync with the instrumentor wrapper.
|
|
400
|
+
*/
|
|
397
401
|
handleStartStepRun(action) {
|
|
398
402
|
return __awaiter(this, void 0, void 0, function* () {
|
|
399
403
|
var _a;
|
|
@@ -515,7 +519,8 @@ class InternalWorker {
|
|
|
515
519
|
}
|
|
516
520
|
catch (e) {
|
|
517
521
|
yield failure(e);
|
|
518
|
-
|
|
522
|
+
// Return error for OTel instrumentor to capture
|
|
523
|
+
return e;
|
|
519
524
|
}
|
|
520
525
|
// Postcheck: user code may swallow AbortError; don't report completion after cancellation.
|
|
521
526
|
// If we reached this point and the signal is aborted, the task likely caught/ignored cancellation.
|
|
@@ -527,6 +532,7 @@ class InternalWorker {
|
|
|
527
532
|
}
|
|
528
533
|
(0, abort_error_1.throwIfAborted)(context.abortController.signal);
|
|
529
534
|
yield success(result);
|
|
535
|
+
return undefined;
|
|
530
536
|
}))());
|
|
531
537
|
this.futures[actionKey] = future;
|
|
532
538
|
// Send the action event to the dispatcher
|
|
@@ -535,7 +541,7 @@ class InternalWorker {
|
|
|
535
541
|
this.logger.error(`Could not send action event: ${e.message}`);
|
|
536
542
|
});
|
|
537
543
|
try {
|
|
538
|
-
yield future.promise;
|
|
544
|
+
return yield future.promise;
|
|
539
545
|
}
|
|
540
546
|
catch (e) {
|
|
541
547
|
if (!(0, task_run_terminated_error_1.isTaskRunTerminatedError)(e)) {
|
|
@@ -550,6 +556,7 @@ class InternalWorker {
|
|
|
550
556
|
catch (e) {
|
|
551
557
|
this.cleanupRun(actionKey);
|
|
552
558
|
this.logger.error('Could not send action event (outer): ', e);
|
|
559
|
+
return e instanceof Error ? e : new Error(String(e));
|
|
553
560
|
}
|
|
554
561
|
});
|
|
555
562
|
}
|
|
@@ -582,6 +589,10 @@ class InternalWorker {
|
|
|
582
589
|
eventPayload: JSON.stringify(payload),
|
|
583
590
|
};
|
|
584
591
|
}
|
|
592
|
+
/**
|
|
593
|
+
* @important This method is instrumented by HatchetInstrumentor._patchHandleCancelStepRun.
|
|
594
|
+
* Keep the signature in sync with the instrumentor wrapper.
|
|
595
|
+
*/
|
|
585
596
|
handleCancelStepRun(action) {
|
|
586
597
|
return __awaiter(this, void 0, void 0, function* () {
|
|
587
598
|
var _a, _b, _c;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const api_1 = require("@opentelemetry/api");
|
|
13
|
+
const hatchet_client_1 = require("../hatchet-client");
|
|
14
|
+
const setup_1 = require("./setup");
|
|
15
|
+
const worker_1 = require("./worker");
|
|
16
|
+
(0, setup_1.initOtel)();
|
|
17
|
+
const tracer = (0, setup_1.getTracer)('otel-instrumentation-triggers');
|
|
18
|
+
function runWorkflow() {
|
|
19
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
20
|
+
return tracer.startActiveSpan('trigger_order_processing', (span) => __awaiter(this, void 0, void 0, function* () {
|
|
21
|
+
try {
|
|
22
|
+
const workflowRun = yield hatchet_client_1.hatchet.admin.runWorkflow(worker_1.orderWorkflow.name, {
|
|
23
|
+
orderId: 'order-123',
|
|
24
|
+
customerId: 'cust-456',
|
|
25
|
+
amount: 4999,
|
|
26
|
+
});
|
|
27
|
+
const runId = yield workflowRun.getWorkflowRunId();
|
|
28
|
+
console.log(`Started workflow run: ${runId}`);
|
|
29
|
+
const result = yield workflowRun.output;
|
|
30
|
+
span.setStatus({ code: api_1.SpanStatusCode.OK, message: 'Order processed' });
|
|
31
|
+
console.log('Order completed:', result);
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
const errorMessage = Array.isArray(error)
|
|
35
|
+
? error.join(', ')
|
|
36
|
+
: (error === null || error === void 0 ? void 0 : error.message) || String(error);
|
|
37
|
+
console.error('Order processing failed:', errorMessage);
|
|
38
|
+
span.recordException(error);
|
|
39
|
+
span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: errorMessage });
|
|
40
|
+
}
|
|
41
|
+
finally {
|
|
42
|
+
span.end();
|
|
43
|
+
}
|
|
44
|
+
}));
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
function main() {
|
|
48
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
49
|
+
yield runWorkflow();
|
|
50
|
+
console.log('Waiting for spans to be exported...');
|
|
51
|
+
yield new Promise((resolve) => setTimeout(resolve, 5000));
|
|
52
|
+
process.exit(0);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
if (require.main === module) {
|
|
56
|
+
main().catch(console.error);
|
|
57
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared OTel instrumentor setup.
|
|
3
|
+
*
|
|
4
|
+
* Import and call initOtel() once at process startup (in both worker and run)
|
|
5
|
+
* before using the tracer.
|
|
6
|
+
*/
|
|
7
|
+
import type { Tracer } from '@opentelemetry/api';
|
|
8
|
+
export declare function initOtel(): void;
|
|
9
|
+
export declare function getTracer(name: string): Tracer;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Shared OTel instrumentor setup.
|
|
4
|
+
*
|
|
5
|
+
* Import and call initOtel() once at process startup (in both worker and run)
|
|
6
|
+
* before using the tracer.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.initOtel = initOtel;
|
|
10
|
+
exports.getTracer = getTracer;
|
|
11
|
+
/* eslint-disable @typescript-eslint/no-require-imports */
|
|
12
|
+
const { registerInstrumentations } = require('@opentelemetry/instrumentation');
|
|
13
|
+
const { trace } = require('@opentelemetry/api');
|
|
14
|
+
const opentelemetry_1 = require("../../../opentelemetry");
|
|
15
|
+
function initOtel() {
|
|
16
|
+
registerInstrumentations({
|
|
17
|
+
instrumentations: [
|
|
18
|
+
new opentelemetry_1.HatchetInstrumentor({
|
|
19
|
+
includeTaskNameInSpanName: true,
|
|
20
|
+
}),
|
|
21
|
+
],
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
function getTracer(name) {
|
|
25
|
+
return trace.getTracer(name);
|
|
26
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.orderWorkflow = void 0;
|
|
13
|
+
const hatchet_client_1 = require("../hatchet-client");
|
|
14
|
+
const setup_1 = require("./setup");
|
|
15
|
+
const api_1 = require("@opentelemetry/api");
|
|
16
|
+
(0, setup_1.initOtel)();
|
|
17
|
+
const tracer = (0, setup_1.getTracer)('otel-instrumentation-worker');
|
|
18
|
+
exports.orderWorkflow = hatchet_client_1.hatchet.workflow({
|
|
19
|
+
name: 'otel-order-processing-ts',
|
|
20
|
+
});
|
|
21
|
+
const validateOrder = exports.orderWorkflow.task({
|
|
22
|
+
name: 'validate-order',
|
|
23
|
+
fn: (input) => __awaiter(void 0, void 0, void 0, function* () {
|
|
24
|
+
yield tracer.startActiveSpan('order.validate.schema', (span) => __awaiter(void 0, void 0, void 0, function* () {
|
|
25
|
+
yield new Promise((resolve) => setTimeout(resolve, 10));
|
|
26
|
+
span.setAttribute('order.id', input.orderId);
|
|
27
|
+
span.end();
|
|
28
|
+
}));
|
|
29
|
+
yield tracer.startActiveSpan('order.validate.fraud-check', (span) => __awaiter(void 0, void 0, void 0, function* () {
|
|
30
|
+
yield new Promise((resolve) => setTimeout(resolve, 20));
|
|
31
|
+
span.setAttribute('fraud.score', 0.05);
|
|
32
|
+
span.setAttribute('fraud.decision', 'allow');
|
|
33
|
+
span.end();
|
|
34
|
+
}));
|
|
35
|
+
return { valid: true, orderId: input.orderId };
|
|
36
|
+
}),
|
|
37
|
+
});
|
|
38
|
+
const chargePayment = exports.orderWorkflow.task({
|
|
39
|
+
name: 'charge-payment',
|
|
40
|
+
parents: [validateOrder],
|
|
41
|
+
fn: (input, ctx) => __awaiter(void 0, void 0, void 0, function* () {
|
|
42
|
+
const validated = yield ctx.parentOutput(validateOrder);
|
|
43
|
+
return tracer.startActiveSpan('payment.process', (paySpan) => __awaiter(void 0, void 0, void 0, function* () {
|
|
44
|
+
try {
|
|
45
|
+
yield tracer.startActiveSpan('payment.tokenize-card', (span) => __awaiter(void 0, void 0, void 0, function* () {
|
|
46
|
+
yield new Promise((resolve) => setTimeout(resolve, 15));
|
|
47
|
+
span.setAttribute('payment.provider', 'stripe');
|
|
48
|
+
span.end();
|
|
49
|
+
}));
|
|
50
|
+
yield tracer.startActiveSpan('payment.charge', (span) => __awaiter(void 0, void 0, void 0, function* () {
|
|
51
|
+
yield new Promise((resolve) => setTimeout(resolve, 30));
|
|
52
|
+
span.setAttribute('payment.amount_cents', input.amount);
|
|
53
|
+
span.setAttribute('payment.currency', 'USD');
|
|
54
|
+
span.end();
|
|
55
|
+
}));
|
|
56
|
+
paySpan.setStatus({ code: api_1.SpanStatusCode.OK });
|
|
57
|
+
return {
|
|
58
|
+
transactionId: `txn-${validated.orderId}`,
|
|
59
|
+
charged: input.amount,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
paySpan.end();
|
|
64
|
+
}
|
|
65
|
+
}));
|
|
66
|
+
}),
|
|
67
|
+
});
|
|
68
|
+
const reserveInventory = exports.orderWorkflow.task({
|
|
69
|
+
name: 'reserve-inventory',
|
|
70
|
+
parents: [validateOrder],
|
|
71
|
+
fn: (input) => __awaiter(void 0, void 0, void 0, function* () {
|
|
72
|
+
yield tracer.startActiveSpan('inventory.check-availability', (span) => __awaiter(void 0, void 0, void 0, function* () {
|
|
73
|
+
yield new Promise((resolve) => setTimeout(resolve, 10));
|
|
74
|
+
span.setAttribute('inventory.sku_count', 3);
|
|
75
|
+
span.setAttribute('inventory.all_available', true);
|
|
76
|
+
span.end();
|
|
77
|
+
}));
|
|
78
|
+
yield tracer.startActiveSpan('inventory.reserve', (span) => __awaiter(void 0, void 0, void 0, function* () {
|
|
79
|
+
yield new Promise((resolve) => setTimeout(resolve, 15));
|
|
80
|
+
span.setAttribute('inventory.warehouse', 'us-east-1');
|
|
81
|
+
span.end();
|
|
82
|
+
}));
|
|
83
|
+
return {
|
|
84
|
+
reservationId: `res-${input.orderId}`,
|
|
85
|
+
itemsReserved: 3,
|
|
86
|
+
};
|
|
87
|
+
}),
|
|
88
|
+
});
|
|
89
|
+
exports.orderWorkflow.task({
|
|
90
|
+
name: 'send-confirmation',
|
|
91
|
+
parents: [chargePayment, reserveInventory],
|
|
92
|
+
fn: (input, ctx) => __awaiter(void 0, void 0, void 0, function* () {
|
|
93
|
+
const payment = yield ctx.parentOutput(chargePayment);
|
|
94
|
+
const inventory = yield ctx.parentOutput(reserveInventory);
|
|
95
|
+
yield tracer.startActiveSpan('notification.render-template', (span) => __awaiter(void 0, void 0, void 0, function* () {
|
|
96
|
+
yield new Promise((resolve) => setTimeout(resolve, 5));
|
|
97
|
+
span.setAttribute('template.name', 'order-confirmation');
|
|
98
|
+
span.end();
|
|
99
|
+
}));
|
|
100
|
+
yield tracer.startActiveSpan('notification.send-email', (span) => __awaiter(void 0, void 0, void 0, function* () {
|
|
101
|
+
yield new Promise((resolve) => setTimeout(resolve, 20));
|
|
102
|
+
span.setAttribute('email.to', 'customer@example.com');
|
|
103
|
+
span.setAttribute('email.provider', 'sendgrid');
|
|
104
|
+
span.end();
|
|
105
|
+
}));
|
|
106
|
+
return {
|
|
107
|
+
sent: true,
|
|
108
|
+
transactionId: payment.transactionId,
|
|
109
|
+
reservationId: inventory.reservationId,
|
|
110
|
+
};
|
|
111
|
+
}),
|
|
112
|
+
});
|
|
113
|
+
function main() {
|
|
114
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
115
|
+
const worker = yield hatchet_client_1.hatchet.worker('otel-instrumentation-worker-ts', {
|
|
116
|
+
workflows: [exports.orderWorkflow],
|
|
117
|
+
});
|
|
118
|
+
yield worker.start();
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
if (require.main === module) {
|
|
122
|
+
main().catch(console.error);
|
|
123
|
+
}
|
package/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const HATCHET_VERSION = "1.
|
|
1
|
+
export declare const HATCHET_VERSION = "1.18.0";
|
package/version.js
CHANGED