@outputai/core 0.8.2-next.ec4c07d.0 → 0.8.2-next.edf06bb.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/package.json +1 -1
- package/src/hooks/index.d.ts +30 -102
- package/src/hooks/index.js +1 -16
- package/src/hooks/index.spec.js +1 -55
- package/src/interface/index.d.ts +1 -1
- package/src/interface/index.js +1 -1
- package/src/interface/logger.d.ts +44 -52
- package/src/interface/logger.js +11 -16
- package/src/interface/logger.spec.js +1 -35
- package/src/worker/interceptors/activity.js +9 -6
- package/src/worker/interceptors/activity.spec.js +26 -25
package/package.json
CHANGED
package/src/hooks/index.d.ts
CHANGED
|
@@ -79,47 +79,6 @@ export interface WorkflowDetails {
|
|
|
79
79
|
attempt: number;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
/**
|
|
83
|
-
* Attribute totals collected while an activity executes.
|
|
84
|
-
*/
|
|
85
|
-
export interface Aggregations {
|
|
86
|
-
/** Cost totals collected from HTTP request cost and LLM usage attributes. */
|
|
87
|
-
cost: {
|
|
88
|
-
total: number;
|
|
89
|
-
};
|
|
90
|
-
/** Token totals collected from LLM usage attributes. */
|
|
91
|
-
tokens: {
|
|
92
|
-
[tokenType: string]: number | undefined;
|
|
93
|
-
total: number;
|
|
94
|
-
};
|
|
95
|
-
/** HTTP request count totals. */
|
|
96
|
-
httpRequests: {
|
|
97
|
-
total: number;
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Common lifecycle hook payload fields for events associated with a workflow.
|
|
103
|
-
*/
|
|
104
|
-
export interface HookPayloadBase {
|
|
105
|
-
/** UUID v4 stamped per emit. Stable per-emit idempotency key. */
|
|
106
|
-
eventId: string;
|
|
107
|
-
/** Timestamp of the event */
|
|
108
|
-
eventDate: number;
|
|
109
|
-
/** Information about the current workflow execution */
|
|
110
|
-
workflowDetails: WorkflowDetails;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Common hook payload fields for events associated with an activity.
|
|
115
|
-
*/
|
|
116
|
-
export interface ActivityPayloadBase extends HookPayloadBase {
|
|
117
|
-
/** Temporal's activityInfo(). */
|
|
118
|
-
activityInfo: Info;
|
|
119
|
-
/** Output component kind for the activity, e.g. step or evaluator. */
|
|
120
|
-
outputActivityKind: string;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
82
|
/**
|
|
124
83
|
* Payload passed to the onError() handler when a workflow, activity or runtime error occurs.
|
|
125
84
|
*/
|
|
@@ -136,8 +95,6 @@ export interface ErrorHookPayload {
|
|
|
136
95
|
activityInfo?: Info;
|
|
137
96
|
/** Output component kind for the activity, e.g. step, evaluator, or internal_step. */
|
|
138
97
|
outputActivityKind?: string;
|
|
139
|
-
/** Attribute totals collected during the activity execution. */
|
|
140
|
-
aggregations?: Aggregations | null;
|
|
141
98
|
/** The error thrown. */
|
|
142
99
|
error: Error;
|
|
143
100
|
}
|
|
@@ -145,45 +102,37 @@ export interface ErrorHookPayload {
|
|
|
145
102
|
/**
|
|
146
103
|
* Payload passed to the onWorkflowStart() handler when a workflow run begins.
|
|
147
104
|
*/
|
|
148
|
-
export
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Payload passed to the onWorkflowError() handler when a workflow run fails.
|
|
157
|
-
*/
|
|
158
|
-
export interface WorkflowErrorHookPayload extends HookPayloadBase {
|
|
159
|
-
/** The error thrown. */
|
|
160
|
-
error: Error;
|
|
105
|
+
export interface WorkflowStartHookPayload {
|
|
106
|
+
/** UUID v4 stamped per emit. Stable per-emit idempotency key. */
|
|
107
|
+
eventId: string;
|
|
108
|
+
/** Timestamp of the event */
|
|
109
|
+
eventDate: number;
|
|
110
|
+
/** Information about the current workflow execution */
|
|
111
|
+
workflowDetails: WorkflowDetails;
|
|
161
112
|
}
|
|
162
113
|
|
|
163
114
|
/**
|
|
164
|
-
*
|
|
165
|
-
*/
|
|
166
|
-
export type ActivityHookPayload = ActivityPayloadBase;
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Payload passed to the onActivityStart() handler when an activity starts.
|
|
170
|
-
*/
|
|
171
|
-
export type ActivityStartHookPayload = ActivityHookPayload;
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* Payload passed to the onActivityEnd() handler when an activity completes successfully.
|
|
115
|
+
* Payload passed to the onWorkflowEnd() handler when a workflow run completes successfully.
|
|
175
116
|
*/
|
|
176
|
-
export interface
|
|
177
|
-
/**
|
|
178
|
-
|
|
117
|
+
export interface WorkflowEndHookPayload {
|
|
118
|
+
/** UUID v4 stamped per emit. Stable per-emit idempotency key. */
|
|
119
|
+
eventId: string;
|
|
120
|
+
/** Timestamp of the event */
|
|
121
|
+
eventDate: number;
|
|
122
|
+
/** Information about the current workflow execution */
|
|
123
|
+
workflowDetails: WorkflowDetails;
|
|
179
124
|
}
|
|
180
125
|
|
|
181
126
|
/**
|
|
182
|
-
* Payload passed to the
|
|
127
|
+
* Payload passed to the onWorkflowError() handler when a workflow run fails.
|
|
183
128
|
*/
|
|
184
|
-
export interface
|
|
185
|
-
/**
|
|
186
|
-
|
|
129
|
+
export interface WorkflowErrorHookPayload {
|
|
130
|
+
/** UUID v4 stamped per emit. Stable per-emit idempotency key. */
|
|
131
|
+
eventId: string;
|
|
132
|
+
/** Timestamp of the event */
|
|
133
|
+
eventDate: number;
|
|
134
|
+
/** Information about the current workflow execution */
|
|
135
|
+
workflowDetails: WorkflowDetails;
|
|
187
136
|
/** The error thrown. */
|
|
188
137
|
error: Error;
|
|
189
138
|
}
|
|
@@ -230,37 +179,16 @@ export declare function onWorkflowEnd( handler: ( payload: WorkflowEndHookPayloa
|
|
|
230
179
|
*/
|
|
231
180
|
export declare function onWorkflowError( handler: ( payload: WorkflowErrorHookPayload ) => void ): void;
|
|
232
181
|
|
|
233
|
-
/**
|
|
234
|
-
* Register a handler to be invoked when an activity starts.
|
|
235
|
-
*
|
|
236
|
-
* Excludes internal activities.
|
|
237
|
-
*
|
|
238
|
-
* @param handler - Function called with the activity start payload.
|
|
239
|
-
*/
|
|
240
|
-
export declare function onActivityStart( handler: ( payload: ActivityStartHookPayload ) => void ): void;
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* Register a handler to be invoked when an activity completes successfully.
|
|
244
|
-
*
|
|
245
|
-
* Excludes internal activities.
|
|
246
|
-
*
|
|
247
|
-
* @param handler - Function called with the activity end payload.
|
|
248
|
-
*/
|
|
249
|
-
export declare function onActivityEnd( handler: ( payload: ActivityEndHookPayload ) => void ): void;
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* Register a handler to be invoked when an activity fails.
|
|
253
|
-
*
|
|
254
|
-
* Excludes internal activities.
|
|
255
|
-
*
|
|
256
|
-
* @param handler - Function called with the activity error payload.
|
|
257
|
-
*/
|
|
258
|
-
export declare function onActivityError( handler: ( payload: ActivityErrorHookPayload ) => void ): void;
|
|
259
|
-
|
|
260
182
|
/**
|
|
261
183
|
* Framework-managed envelope added to payloads passed to on() handlers.
|
|
262
184
|
*/
|
|
263
|
-
export interface OnHookEnvelope
|
|
185
|
+
export interface OnHookEnvelope {
|
|
186
|
+
/** UUID v4 stamped per emit. Stable per-emit idempotency key. */
|
|
187
|
+
eventId: string;
|
|
188
|
+
/** Timestamp of the event */
|
|
189
|
+
eventDate: number;
|
|
190
|
+
/** Information about the current workflow execution */
|
|
191
|
+
workflowDetails: WorkflowDetails;
|
|
264
192
|
/** Temporal's activityInfo(). */
|
|
265
193
|
activityInfo: Info;
|
|
266
194
|
/** Output component kind for the activity, e.g. step, evaluator, or internal_step. */
|
package/src/hooks/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { messageBus } from '#bus';
|
|
2
|
-
import { BusEventType,
|
|
2
|
+
import { BusEventType, WORKFLOW_CATALOG } from '#consts';
|
|
3
3
|
import { createChildLogger } from '#logger';
|
|
4
4
|
|
|
5
5
|
const log = createChildLogger( 'Hooks' );
|
|
@@ -48,21 +48,6 @@ export const onWorkflowEnd = handler => messageBus.on( BusEventType.WORKFLOW_END
|
|
|
48
48
|
export const onWorkflowError = handler => messageBus.on( BusEventType.WORKFLOW_ERROR, ( { workflowDetails, ...eventFields } ) =>
|
|
49
49
|
shouldEmitWorkflowEvent( workflowDetails ) ? safeInvoke( handler, { workflowDetails, ...eventFields }, 'onWorkflowError' ) : null );
|
|
50
50
|
|
|
51
|
-
/** Internal activities do not trigger hooks */
|
|
52
|
-
const shouldEmitActivityEvent = outputActivityKind => outputActivityKind !== ComponentType.INTERNAL_STEP;
|
|
53
|
-
|
|
54
|
-
/** Listen to workflow start events, excludes catalog workflow */
|
|
55
|
-
export const onActivityStart = handler => messageBus.on( BusEventType.ACTIVITY_START, ( { outputActivityKind, ...eventFields } ) =>
|
|
56
|
-
shouldEmitActivityEvent( outputActivityKind ) ? safeInvoke( handler, { outputActivityKind, ...eventFields }, 'onActivityStart' ) : null );
|
|
57
|
-
|
|
58
|
-
/** Listen to workflow end events, excludes catalog workflow */
|
|
59
|
-
export const onActivityEnd = handler => messageBus.on( BusEventType.ACTIVITY_END, ( { outputActivityKind, ...eventFields } ) =>
|
|
60
|
-
shouldEmitActivityEvent( outputActivityKind ) ? safeInvoke( handler, { outputActivityKind, ...eventFields }, 'onActivityEnd' ) : null );
|
|
61
|
-
|
|
62
|
-
/** Listen to workflow error events, excludes catalog workflow */
|
|
63
|
-
export const onActivityError = handler => messageBus.on( BusEventType.ACTIVITY_ERROR, ( { outputActivityKind, ...eventFields } ) =>
|
|
64
|
-
shouldEmitActivityEvent( outputActivityKind ) ? safeInvoke( handler, { outputActivityKind, ...eventFields }, 'onActivityError' ) : null );
|
|
65
|
-
|
|
66
51
|
/** Generic listener for events emitted elsewhere (outside core) */
|
|
67
52
|
export const on = ( eventName, handler ) => messageBus.on( `external:${eventName}`, payload =>
|
|
68
53
|
safeInvoke( handler, payload, eventName ) );
|
package/src/hooks/index.spec.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
-
import { BusEventType,
|
|
2
|
+
import { BusEventType, WORKFLOW_CATALOG } from '#consts';
|
|
3
3
|
|
|
4
4
|
const logErrorMock = vi.hoisted( () => vi.fn() );
|
|
5
5
|
const createChildLoggerMock = vi.hoisted( () =>
|
|
@@ -18,9 +18,6 @@ vi.mock( '#bus', () => ( { messageBus: messageBusMock } ) );
|
|
|
18
18
|
|
|
19
19
|
import {
|
|
20
20
|
on,
|
|
21
|
-
onActivityEnd,
|
|
22
|
-
onActivityError,
|
|
23
|
-
onActivityStart,
|
|
24
21
|
onBeforeWorkerStart,
|
|
25
22
|
onError,
|
|
26
23
|
onWorkflowEnd,
|
|
@@ -52,12 +49,6 @@ const activityInfo = {
|
|
|
52
49
|
|
|
53
50
|
const eventDate = 1710000001234;
|
|
54
51
|
|
|
55
|
-
const aggregations = {
|
|
56
|
-
cost: { total: 0 },
|
|
57
|
-
tokens: { total: 0 },
|
|
58
|
-
httpRequests: { total: 1 }
|
|
59
|
-
};
|
|
60
|
-
|
|
61
52
|
describe( 'hooks/index', () => {
|
|
62
53
|
beforeEach( () => {
|
|
63
54
|
vi.clearAllMocks();
|
|
@@ -207,51 +198,6 @@ describe( 'hooks/index', () => {
|
|
|
207
198
|
} );
|
|
208
199
|
} );
|
|
209
200
|
|
|
210
|
-
describe( 'activity lifecycle hooks', () => {
|
|
211
|
-
const cases = [
|
|
212
|
-
[ 'onActivityStart', onActivityStart, BusEventType.ACTIVITY_START, undefined ],
|
|
213
|
-
[ 'onActivityEnd', onActivityEnd, BusEventType.ACTIVITY_END, { aggregations } ],
|
|
214
|
-
[ 'onActivityError', onActivityError, BusEventType.ACTIVITY_ERROR, { error: new Error( 'activity failed' ) } ]
|
|
215
|
-
];
|
|
216
|
-
|
|
217
|
-
it.each( cases )( '%s skips internal activities and forwards bus fields', async ( _name, registerHook, eventType, extraFields = {} ) => {
|
|
218
|
-
const handler = vi.fn().mockResolvedValue( undefined );
|
|
219
|
-
registerHook( handler );
|
|
220
|
-
|
|
221
|
-
expect( messageBusMock.on ).toHaveBeenCalledWith( eventType, expect.any( Function ) );
|
|
222
|
-
|
|
223
|
-
await Promise.resolve( onHandlers[eventType]( {
|
|
224
|
-
eventId: 'evt-ignored',
|
|
225
|
-
eventDate,
|
|
226
|
-
activityInfo,
|
|
227
|
-
workflowDetails,
|
|
228
|
-
outputActivityKind: ComponentType.INTERNAL_STEP,
|
|
229
|
-
...extraFields
|
|
230
|
-
} ) );
|
|
231
|
-
expect( handler ).not.toHaveBeenCalled();
|
|
232
|
-
|
|
233
|
-
await Promise.resolve( onHandlers[eventType]( {
|
|
234
|
-
eventId: 'evt-activity-1',
|
|
235
|
-
eventDate,
|
|
236
|
-
activityInfo,
|
|
237
|
-
workflowDetails,
|
|
238
|
-
outputActivityKind: ComponentType.STEP,
|
|
239
|
-
extra: 'passthrough',
|
|
240
|
-
...extraFields
|
|
241
|
-
} ) );
|
|
242
|
-
|
|
243
|
-
expect( handler ).toHaveBeenCalledWith( {
|
|
244
|
-
eventId: 'evt-activity-1',
|
|
245
|
-
eventDate,
|
|
246
|
-
activityInfo,
|
|
247
|
-
workflowDetails,
|
|
248
|
-
outputActivityKind: ComponentType.STEP,
|
|
249
|
-
extra: 'passthrough',
|
|
250
|
-
...extraFields
|
|
251
|
-
} );
|
|
252
|
-
} );
|
|
253
|
-
} );
|
|
254
|
-
|
|
255
201
|
describe( 'on', () => {
|
|
256
202
|
it( 'subscribes to external event channel and forwards payload', async () => {
|
|
257
203
|
const handler = vi.fn().mockResolvedValue( undefined );
|
package/src/interface/index.d.ts
CHANGED
package/src/interface/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import { step } from './step.js';
|
|
|
10
10
|
import { workflow } from './workflow.js';
|
|
11
11
|
import { executeInParallel } from './workflow_utils.js';
|
|
12
12
|
import { sendHttpRequest, sendPostRequestAndAwaitWebhook } from './webhook.js';
|
|
13
|
-
import
|
|
13
|
+
import * as Logger from './logger.js';
|
|
14
14
|
|
|
15
15
|
export {
|
|
16
16
|
evaluator,
|
|
@@ -1,61 +1,53 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
* @param metadata Additional information to be displayed
|
|
6
|
-
*/
|
|
7
|
-
error( message: string, metadata?: Record<string, unknown> ) : void,
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Log a warn (level 1)
|
|
11
|
-
* @param message Log message
|
|
12
|
-
* @param metadata Additional information to be displayed
|
|
13
|
-
*/
|
|
14
|
-
warn( message: string, metadata?: Record<string, unknown> ) : void,
|
|
1
|
+
/**
|
|
2
|
+
* Additional structured fields attached to a log record.
|
|
3
|
+
*/
|
|
4
|
+
export type LogMetadata = Record<string, unknown>;
|
|
15
5
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Log an error (level 0)
|
|
8
|
+
* @param message Log message
|
|
9
|
+
* @param metadata Additional information to be displayed
|
|
10
|
+
*/
|
|
11
|
+
export declare function error( message: string, metadata?: LogMetadata ) : void;
|
|
22
12
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Log a warn (level 1)
|
|
15
|
+
* @param message Log message
|
|
16
|
+
* @param metadata Additional information to be displayed
|
|
17
|
+
*/
|
|
18
|
+
export declare function warn( message: string, metadata?: LogMetadata ) : void;
|
|
29
19
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Log an info (level 2)
|
|
22
|
+
* @param message Log message
|
|
23
|
+
* @param metadata Additional information to be displayed
|
|
24
|
+
*/
|
|
25
|
+
export declare function info( message: string, metadata?: LogMetadata ) : void;
|
|
36
26
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Log http (level 3)
|
|
29
|
+
* @param message Log message
|
|
30
|
+
* @param metadata Additional information to be displayed
|
|
31
|
+
*/
|
|
32
|
+
export declare function http( message: string, metadata?: LogMetadata ) : void;
|
|
43
33
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Log verbose (level 4)
|
|
36
|
+
* @param message Log message
|
|
37
|
+
* @param metadata Additional information to be displayed
|
|
38
|
+
*/
|
|
39
|
+
export declare function verbose( message: string, metadata?: LogMetadata ) : void;
|
|
50
40
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Log debug (level 5)
|
|
43
|
+
* @param message Log message
|
|
44
|
+
* @param metadata Additional information to be displayed
|
|
45
|
+
*/
|
|
46
|
+
export declare function debug( message: string, metadata?: LogMetadata ) : void;
|
|
57
47
|
|
|
58
48
|
/**
|
|
59
|
-
*
|
|
49
|
+
* Log silly (level 6)
|
|
50
|
+
* @param message Log message
|
|
51
|
+
* @param metadata Additional information to be displayed
|
|
60
52
|
*/
|
|
61
|
-
export declare
|
|
53
|
+
export declare function silly( message: string, metadata?: LogMetadata ) : void;
|
package/src/interface/logger.js
CHANGED
|
@@ -9,6 +9,7 @@ const reservedMetadataFields = new Set( [
|
|
|
9
9
|
'level',
|
|
10
10
|
'message',
|
|
11
11
|
'metadata',
|
|
12
|
+
'namespace',
|
|
12
13
|
'splat',
|
|
13
14
|
'stack',
|
|
14
15
|
'timestamp',
|
|
@@ -25,7 +26,6 @@ const reservedMetadataFields = new Set( [
|
|
|
25
26
|
// This is inoffensive and can be used outside workflow sandbox
|
|
26
27
|
const sinks = proxySinks();
|
|
27
28
|
|
|
28
|
-
// Winston uses npm levels by default: https://github.com/winstonjs/winston#logging-levels
|
|
29
29
|
// Convert npm log levels to console levels
|
|
30
30
|
const levelToConsole = {
|
|
31
31
|
error: 'error',
|
|
@@ -36,17 +36,14 @@ const levelToConsole = {
|
|
|
36
36
|
debug: 'debug',
|
|
37
37
|
silly: 'log'
|
|
38
38
|
};
|
|
39
|
-
const levels = Object.keys( levelToConsole );
|
|
40
39
|
|
|
41
40
|
/** Drops reserved keys from object */
|
|
42
41
|
const removeReservedFields = obj => Object.fromEntries( Object.entries( obj ).filter( ( [ k ] ) => !reservedMetadataFields.has( k ) ) );
|
|
43
42
|
|
|
44
|
-
|
|
45
|
-
const log = ( level, namespace, message, metadata ) => {
|
|
46
|
-
const baseMetadata = namespace ? { namespace } : {};
|
|
43
|
+
const log = ( level, message, metadata ) => {
|
|
47
44
|
const sanitized = {
|
|
48
45
|
message: String( message ),
|
|
49
|
-
|
|
46
|
+
...( isPlainObject( metadata ) && { metadata: removeReservedFields( metadata ) } )
|
|
50
47
|
};
|
|
51
48
|
|
|
52
49
|
// When inside workflow, use sinks to send logs out
|
|
@@ -61,13 +58,11 @@ const log = ( level, namespace, message, metadata ) => {
|
|
|
61
58
|
}
|
|
62
59
|
};
|
|
63
60
|
|
|
64
|
-
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
export { logger as Logger };
|
|
61
|
+
// Winston uses npm levels by default: https://github.com/winstonjs/winston#logging-levels
|
|
62
|
+
export const error = log.bind( null, 'error' );
|
|
63
|
+
export const warn = log.bind( null, 'warn' );
|
|
64
|
+
export const info = log.bind( null, 'info' );
|
|
65
|
+
export const http = log.bind( null, 'http' );
|
|
66
|
+
export const verbose = log.bind( null, 'verbose' );
|
|
67
|
+
export const debug = log.bind( null, 'debug' );
|
|
68
|
+
export const silly = log.bind( null, 'silly' );
|
|
@@ -34,7 +34,7 @@ const consoleMethodsByLevel = {
|
|
|
34
34
|
silly: 'log'
|
|
35
35
|
};
|
|
36
36
|
|
|
37
|
-
const loadLogger = async () =>
|
|
37
|
+
const loadLogger = async () => import( './logger.js' );
|
|
38
38
|
|
|
39
39
|
describe( 'interface/logger', () => {
|
|
40
40
|
beforeEach( () => {
|
|
@@ -135,38 +135,4 @@ describe( 'interface/logger', () => {
|
|
|
135
135
|
expect( consoleMocks.log ).toHaveBeenCalledTimes( 3 );
|
|
136
136
|
expect( workflowLogMock ).not.toHaveBeenCalled();
|
|
137
137
|
} );
|
|
138
|
-
|
|
139
|
-
it( 'creates a logger with a default namespace for every level', async () => {
|
|
140
|
-
const logger = await loadLogger();
|
|
141
|
-
inWorkflowContextMock.mockReturnValue( true );
|
|
142
|
-
|
|
143
|
-
const namespacedLogger = logger.createLogger( 'Namespace' );
|
|
144
|
-
logLevels.forEach( level => {
|
|
145
|
-
namespacedLogger[level]( `${level} message`, { requestId: level } );
|
|
146
|
-
} );
|
|
147
|
-
|
|
148
|
-
logLevels.forEach( ( level, index ) => {
|
|
149
|
-
expect( workflowLogMock ).toHaveBeenNthCalledWith( index + 1, {
|
|
150
|
-
level,
|
|
151
|
-
message: `${level} message`,
|
|
152
|
-
metadata: {
|
|
153
|
-
namespace: 'Namespace',
|
|
154
|
-
requestId: level
|
|
155
|
-
}
|
|
156
|
-
} );
|
|
157
|
-
} );
|
|
158
|
-
} );
|
|
159
|
-
|
|
160
|
-
it( 'lets log metadata override the default namespace', async () => {
|
|
161
|
-
const logger = await loadLogger();
|
|
162
|
-
inWorkflowContextMock.mockReturnValue( true );
|
|
163
|
-
|
|
164
|
-
logger.createLogger( 'Default namespace' ).info( 'message', { namespace: 'Inline namespace' } );
|
|
165
|
-
|
|
166
|
-
expect( workflowLogMock ).toHaveBeenCalledWith( {
|
|
167
|
-
level: 'info',
|
|
168
|
-
message: 'message',
|
|
169
|
-
metadata: { namespace: 'Inline namespace' }
|
|
170
|
-
} );
|
|
171
|
-
} );
|
|
172
138
|
} );
|
|
@@ -77,18 +77,21 @@ export class ActivityExecutionInterceptor {
|
|
|
77
77
|
|
|
78
78
|
const output = await Storage.runWithContext( async _ => next( input ), storageContext );
|
|
79
79
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
messageBus.emit( BusEventType.ACTIVITY_END, { activityInfo, aggregations, workflowDetails, outputActivityKind } );
|
|
80
|
+
messageBus.emit( BusEventType.ACTIVITY_END, { activityInfo, workflowDetails, outputActivityKind } );
|
|
83
81
|
Tracing.addEventEnd( { id: activityId, details: output, traceInfo } );
|
|
84
82
|
|
|
85
|
-
return {
|
|
83
|
+
return {
|
|
84
|
+
[ACTIVITY_WRAPPER_VERSION_FIELD]: 1,
|
|
85
|
+
output,
|
|
86
|
+
aggregations: state.attributes.length > 0 ? aggregateAttributes( state.attributes ) : null
|
|
87
|
+
};
|
|
86
88
|
|
|
87
89
|
} catch ( error ) {
|
|
88
|
-
|
|
89
|
-
messageBus.emit( BusEventType.ACTIVITY_ERROR, { activityInfo, aggregations, workflowDetails, outputActivityKind, error } );
|
|
90
|
+
messageBus.emit( BusEventType.ACTIVITY_ERROR, { activityInfo, workflowDetails, outputActivityKind, error } );
|
|
90
91
|
Tracing.addEventError( { id: activityId, details: error, traceInfo } );
|
|
91
92
|
|
|
93
|
+
const aggregations = state.attributes.length > 0 ? aggregateAttributes( state.attributes ) : null;
|
|
94
|
+
|
|
92
95
|
throw aggregations ? buildApplicationFailureWithDetails( error, { aggregations } ) : error;
|
|
93
96
|
} finally {
|
|
94
97
|
clearInterval( state.heartbeat );
|
|
@@ -100,12 +100,6 @@ const httpRequestAttribute = {
|
|
|
100
100
|
requestId: 'req-1'
|
|
101
101
|
};
|
|
102
102
|
|
|
103
|
-
const httpRequestAggregations = {
|
|
104
|
-
cost: { total: 0 },
|
|
105
|
-
tokens: { total: 0 },
|
|
106
|
-
httpRequests: { total: 1 }
|
|
107
|
-
};
|
|
108
|
-
|
|
109
103
|
describe( 'ActivityExecutionInterceptor', () => {
|
|
110
104
|
beforeEach( () => {
|
|
111
105
|
vi.clearAllMocks();
|
|
@@ -142,7 +136,7 @@ describe( 'ActivityExecutionInterceptor', () => {
|
|
|
142
136
|
);
|
|
143
137
|
expect( messageBusEmitMock ).toHaveBeenCalledWith(
|
|
144
138
|
BusEventType.ACTIVITY_END,
|
|
145
|
-
{ activityInfo: activityInfoMock,
|
|
139
|
+
{ activityInfo: activityInfoMock, workflowDetails: workflowDetailsMock, outputActivityKind: 'step' }
|
|
146
140
|
);
|
|
147
141
|
expect( addEventStartMock ).toHaveBeenCalledWith( {
|
|
148
142
|
id: 'act-1',
|
|
@@ -195,16 +189,14 @@ describe( 'ActivityExecutionInterceptor', () => {
|
|
|
195
189
|
|
|
196
190
|
await expect( interceptor.execute( makeInput(), next ) ).resolves.toEqual( {
|
|
197
191
|
output: { result: 'ok' },
|
|
198
|
-
aggregations:
|
|
192
|
+
aggregations: {
|
|
193
|
+
cost: { total: 0 },
|
|
194
|
+
tokens: { total: 0 },
|
|
195
|
+
httpRequests: { total: 1 }
|
|
196
|
+
},
|
|
199
197
|
[ACTIVITY_WRAPPER_VERSION_FIELD]: 1
|
|
200
198
|
} );
|
|
201
199
|
|
|
202
|
-
expect( messageBusEmitMock ).toHaveBeenCalledWith( BusEventType.ACTIVITY_END, {
|
|
203
|
-
activityInfo: activityInfoMock,
|
|
204
|
-
aggregations: httpRequestAggregations,
|
|
205
|
-
workflowDetails: workflowDetailsMock,
|
|
206
|
-
outputActivityKind: 'step'
|
|
207
|
-
} );
|
|
208
200
|
} );
|
|
209
201
|
|
|
210
202
|
it( 'stores collected aggregations in ApplicationFailure details after failed execution', async () => {
|
|
@@ -223,17 +215,15 @@ describe( 'ActivityExecutionInterceptor', () => {
|
|
|
223
215
|
message: 'step failed',
|
|
224
216
|
type: 'Error',
|
|
225
217
|
details: [ {
|
|
226
|
-
aggregations:
|
|
218
|
+
aggregations: {
|
|
219
|
+
cost: { total: 0 },
|
|
220
|
+
tokens: { total: 0 },
|
|
221
|
+
httpRequests: { total: 1 }
|
|
222
|
+
}
|
|
227
223
|
} ],
|
|
228
224
|
cause: error
|
|
229
225
|
} );
|
|
230
|
-
expect( messageBusEmitMock ).toHaveBeenCalledWith( BusEventType.ACTIVITY_ERROR, {
|
|
231
|
-
activityInfo: activityInfoMock,
|
|
232
|
-
aggregations: httpRequestAggregations,
|
|
233
|
-
workflowDetails: workflowDetailsMock,
|
|
234
|
-
outputActivityKind: 'step',
|
|
235
|
-
error
|
|
236
|
-
} );
|
|
226
|
+
expect( messageBusEmitMock ).toHaveBeenCalledWith( BusEventType.ACTIVITY_ERROR, expect.objectContaining( { error } ) );
|
|
237
227
|
expect( addEventErrorMock ).toHaveBeenCalledOnce();
|
|
238
228
|
expect( addEventEndMock ).not.toHaveBeenCalled();
|
|
239
229
|
} );
|
|
@@ -253,7 +243,13 @@ describe( 'ActivityExecutionInterceptor', () => {
|
|
|
253
243
|
|
|
254
244
|
expect( thrown.details ).toEqual( [
|
|
255
245
|
{ domain: { reason: 'bad-input' } },
|
|
256
|
-
{
|
|
246
|
+
{
|
|
247
|
+
aggregations: {
|
|
248
|
+
cost: { total: 0 },
|
|
249
|
+
tokens: { total: 0 },
|
|
250
|
+
httpRequests: { total: 1 }
|
|
251
|
+
}
|
|
252
|
+
}
|
|
257
253
|
] );
|
|
258
254
|
} );
|
|
259
255
|
|
|
@@ -304,7 +300,13 @@ describe( 'ActivityExecutionInterceptor', () => {
|
|
|
304
300
|
nonRetryable: true,
|
|
305
301
|
details: [
|
|
306
302
|
{ domain: { reason: 'bad-input' } },
|
|
307
|
-
{
|
|
303
|
+
{
|
|
304
|
+
aggregations: {
|
|
305
|
+
cost: { total: 0 },
|
|
306
|
+
tokens: { total: 0 },
|
|
307
|
+
httpRequests: { total: 1 }
|
|
308
|
+
}
|
|
309
|
+
}
|
|
308
310
|
]
|
|
309
311
|
} );
|
|
310
312
|
} );
|
|
@@ -322,7 +324,6 @@ describe( 'ActivityExecutionInterceptor', () => {
|
|
|
322
324
|
expect( messageBusEmitMock ).toHaveBeenCalledWith( BusEventType.ACTIVITY_START, expect.any( Object ) );
|
|
323
325
|
expect( messageBusEmitMock ).toHaveBeenCalledWith( BusEventType.ACTIVITY_ERROR, {
|
|
324
326
|
activityInfo: activityInfoMock,
|
|
325
|
-
aggregations: null,
|
|
326
327
|
workflowDetails: workflowDetailsMock,
|
|
327
328
|
outputActivityKind: 'step',
|
|
328
329
|
error
|