@outputai/core 0.6.0 → 0.6.1-dev.aab2335.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.
Files changed (51) hide show
  1. package/package.json +2 -2
  2. package/src/activity_integration/context.d.ts +5 -9
  3. package/src/activity_integration/context.js +5 -4
  4. package/src/activity_integration/context.spec.js +10 -15
  5. package/src/activity_integration/events.d.ts +2 -4
  6. package/src/activity_integration/events.js +8 -3
  7. package/src/activity_integration/events.spec.js +58 -29
  8. package/src/bus.js +18 -9
  9. package/src/bus.spec.js +30 -0
  10. package/src/hooks/index.d.ts +112 -58
  11. package/src/hooks/index.js +15 -12
  12. package/src/hooks/index.spec.js +60 -32
  13. package/src/interface/workflow.js +19 -35
  14. package/src/interface/workflow.spec.js +104 -15
  15. package/src/internal_activities/index.js +3 -3
  16. package/src/internal_activities/index.spec.js +31 -1
  17. package/src/internal_utils/temporal_context.js +12 -0
  18. package/src/internal_utils/temporal_context.spec.ts +83 -0
  19. package/src/internal_utils/trace_info.js +21 -0
  20. package/src/internal_utils/trace_info.spec.js +47 -0
  21. package/src/internal_utils/workflow_context.js +29 -0
  22. package/src/internal_utils/workflow_context.spec.js +46 -0
  23. package/src/logger/development.js +61 -0
  24. package/src/logger/development.spec.js +70 -0
  25. package/src/logger/index.js +14 -0
  26. package/src/logger/index.spec.js +27 -0
  27. package/src/logger/production.js +15 -0
  28. package/src/logger/production.spec.js +52 -0
  29. package/src/tracing/internal_interface.js +4 -4
  30. package/src/tracing/processors/local/index.js +21 -26
  31. package/src/tracing/processors/local/index.spec.js +39 -45
  32. package/src/tracing/processors/s3/index.js +13 -23
  33. package/src/tracing/processors/s3/index.spec.js +33 -26
  34. package/src/tracing/trace_attribute.js +0 -1
  35. package/src/tracing/trace_engine.js +8 -12
  36. package/src/tracing/trace_engine.spec.js +31 -27
  37. package/src/worker/configs.js +2 -0
  38. package/src/worker/configs.spec.js +25 -0
  39. package/src/worker/index.js +4 -1
  40. package/src/worker/index.spec.js +4 -0
  41. package/src/worker/interceptors/activity.js +31 -29
  42. package/src/worker/interceptors/activity.spec.js +58 -26
  43. package/src/worker/interceptors/workflow.js +7 -2
  44. package/src/worker/interceptors/workflow.spec.js +42 -6
  45. package/src/worker/log_hooks.js +35 -46
  46. package/src/worker/log_hooks.spec.js +43 -46
  47. package/src/worker/setup_telemetry.js +19 -0
  48. package/src/worker/setup_telemetry.spec.js +80 -0
  49. package/src/worker/sinks.js +24 -24
  50. package/src/interface/workflow_context.js +0 -33
  51. package/src/logger.js +0 -73
@@ -1,4 +1,4 @@
1
- import { Context } from '@temporalio/activity';
1
+ import { Context, activityInfo as activityInfoFn } from '@temporalio/activity';
2
2
  import { Storage } from '#async_storage';
3
3
  import * as Tracing from '#tracing';
4
4
  import { headersToObject } from '../sandboxed_utils.js';
@@ -25,7 +25,7 @@ const log = createChildLogger( 'ActivityInterceptor' );
25
25
 
26
26
  Context information comes from two sources:
27
27
  - Temporal's Activity Context (workflowId, activityId, activityType)
28
- - Headers injected by the workflow interceptor (executionContext)
28
+ - Headers injected by the workflow interceptor
29
29
  */
30
30
  export class ActivityExecutionInterceptor {
31
31
  constructor( { activities, workflows, connection } ) {
@@ -42,25 +42,24 @@ export class ActivityExecutionInterceptor {
42
42
 
43
43
  /**
44
44
  * Returns a workflow entry by its name or throws error
45
- * @param {string} workflowName
45
+ * @param {string} workflowType
46
46
  * @returns {object} Workflow entry
47
47
  * @throws {Error}
48
48
  */
49
- getWorkflowEntry( workflowName ) {
50
- const workflowEntry = this.workflowsMap.get( workflowName );
49
+ getWorkflowEntry( workflowType ) {
50
+ const workflowEntry = this.workflowsMap.get( workflowType );
51
51
  if ( !workflowEntry ) {
52
- throw new Error( `Activity interceptor: workflow "${workflowName}" not found in workflowsMap.` );
52
+ throw new Error( `Activity interceptor: workflow "${workflowType}" not found in workflowsMap.` );
53
53
  }
54
54
  return workflowEntry;
55
55
  }
56
56
 
57
57
  async execute( input, next ) {
58
- const startDate = Date.now();
59
-
60
- const { workflowExecution: { workflowId }, activityId: id, activityType: name, workflowType: workflowName } = Context.current().info;
61
- const { executionContext } = headersToObject( input.headers );
62
- const { type: kind } = this.activities?.[name]?.[METADATA_ACCESS_SYMBOL];
63
- const { path: workflowFilename } = this.getWorkflowEntry( workflowName );
58
+ const activityInfo = activityInfoFn();
59
+ const { workflowExecution: { workflowId, runId }, activityId, activityType, workflowType } = activityInfo;
60
+ const { traceInfo, workflowDetails } = headersToObject( input.headers );
61
+ const { type: outputActivityKind } = this.activities?.[activityType]?.[METADATA_ACCESS_SYMBOL];
62
+ const { path: workflowFilename } = this.getWorkflowEntry( workflowType );
64
63
 
65
64
  const state = {
66
65
  heartbeat: null,
@@ -76,32 +75,35 @@ export class ActivityExecutionInterceptor {
76
75
  const workflowHandle = client.workflow.getHandle( workflowId );
77
76
  await workflowHandle.signal( Signal.SEND_AGGREGATIONS, aggregateAttributes( state.attributes ) );
78
77
  } catch ( error ) {
79
- log.warn( `Signal "${Signal.SEND_AGGREGATIONS}" failed`, {
80
- message: error.message,
81
- stack: error.stack,
82
- activityId: id,
83
- activityName: name,
84
- workflowId,
85
- workflowName
86
- } );
78
+ const errorContext = { message: error.message, stack: error.stack, activityId, activityType, workflowId, workflowType, runId };
79
+ log.warn( `Signal "${Signal.SEND_AGGREGATIONS}" failed`, errorContext );
87
80
  }
88
81
  }
89
82
  };
90
83
 
91
- // Wraps the execution with accessible metadata for the activity
92
- const ctx = { parentId: id, executionContext, workflowFilename, addAttribute };
84
+ // Adds context accessible information
85
+ const storageContext = {
86
+ parentId: activityId,
87
+ outputActivityKind,
88
+ activityInfo,
89
+ workflowDetails,
90
+ workflowFilename,
91
+ traceInfo,
92
+ addAttribute
93
+ };
93
94
 
94
- messageBus.emit( BusEventType.ACTIVITY_START, { id, name, kind, workflowId, workflowName } );
95
- Tracing.addEventStart( { id, name, kind, parentId: workflowId, details: input.args[0], executionContext } );
95
+ messageBus.emit( BusEventType.ACTIVITY_START, { activityInfo, workflowDetails, outputActivityKind } );
96
+ Tracing.addEventStart( { id: activityId, name: activityType, kind: outputActivityKind, parentId: runId, details: input.args[0], traceInfo } );
96
97
 
97
98
  try {
98
99
  // Sends heartbeat to communicate that activity is still alive
99
100
  state.heartbeat = activityHeartbeatEnabled && setInterval( () => Context.current().heartbeat(), activityHeartbeatIntervalMs );
100
101
 
101
- const output = await Storage.runWithContext( async _ => next( input ), ctx );
102
+ const output = await Storage.runWithContext( async _ => next( input ), storageContext );
103
+
104
+ messageBus.emit( BusEventType.ACTIVITY_END, { activityInfo, workflowDetails, outputActivityKind } );
105
+ Tracing.addEventEnd( { id: activityId, details: output, traceInfo } );
102
106
 
103
- messageBus.emit( BusEventType.ACTIVITY_END, { id, name, kind, workflowId, workflowName, duration: Date.now() - startDate } );
104
- Tracing.addEventEnd( { id, details: output, executionContext } );
105
107
  return {
106
108
  [ACTIVITY_WRAPPER_VERSION_FIELD]: 1,
107
109
  output,
@@ -109,8 +111,8 @@ export class ActivityExecutionInterceptor {
109
111
  };
110
112
 
111
113
  } catch ( error ) {
112
- messageBus.emit( BusEventType.ACTIVITY_ERROR, { id, name, kind, workflowId, workflowName, duration: Date.now() - startDate, error } );
113
- Tracing.addEventError( { id, details: error, executionContext } );
114
+ messageBus.emit( BusEventType.ACTIVITY_ERROR, { activityInfo, workflowDetails, outputActivityKind, error } );
115
+ Tracing.addEventError( { id: activityId, details: error, traceInfo } );
114
116
 
115
117
  await sendAggregationsViaSignal();
116
118
 
@@ -7,20 +7,36 @@ const workflowHandleMock = vi.hoisted( () => ( { signal: vi.fn() } ) );
7
7
  const getHandleMock = vi.hoisted( () => vi.fn( () => workflowHandleMock ) );
8
8
  const clientConstructorMock = vi.hoisted( () => vi.fn() );
9
9
  const logWarnMock = vi.hoisted( () => vi.fn() );
10
-
11
- const heartbeatMock = vi.fn();
10
+ const heartbeatMock = vi.hoisted( () => vi.fn() );
12
11
  const runWithContextMock = vi.hoisted( () => vi.fn().mockImplementation( async fn => fn() ) );
13
- const contextInfoMock = {
14
- workflowExecution: { workflowId: 'wf-1' },
12
+ const activityInfoMock = vi.hoisted( () => ( {
13
+ workflowExecution: { workflowId: 'wf-1', runId: 'run-1' },
15
14
  activityId: 'act-1',
16
15
  activityType: 'myWorkflow#myStep',
17
16
  workflowType: 'myWorkflow'
18
- };
17
+ } ) );
18
+ const traceInfoMock = vi.hoisted( () => ( {
19
+ workflowId: 'wf-1',
20
+ runId: 'run-1',
21
+ workflowType: 'myWorkflow',
22
+ startTime: 1710000000000,
23
+ disableTrace: false
24
+ } ) );
25
+ const workflowDetailsMock = vi.hoisted( () => ( {
26
+ workflowId: 'wf-1',
27
+ runId: 'run-1',
28
+ workflowType: 'myWorkflow',
29
+ firstExecutionRunId: 'run-1',
30
+ startTime: 1710000000000,
31
+ runStartTime: 1710000000000,
32
+ attempt: 1
33
+ } ) );
19
34
 
20
35
  vi.mock( '@temporalio/activity', () => ( {
36
+ activityInfo: () => activityInfoMock,
21
37
  Context: {
22
38
  current: () => ( {
23
- info: contextInfoMock,
39
+ info: activityInfoMock,
24
40
  heartbeat: heartbeatMock
25
41
  } )
26
42
  }
@@ -58,7 +74,7 @@ vi.mock( '#tracing', () => ( {
58
74
  } ) );
59
75
 
60
76
  vi.mock( '../sandboxed_utils.js', () => ( {
61
- headersToObject: () => ( { executionContext: { workflowId: 'wf-1' } } )
77
+ headersToObject: () => ( { traceInfo: traceInfoMock, workflowDetails: workflowDetailsMock } )
62
78
  } ) );
63
79
 
64
80
  const messageBusEmitMock = vi.fn();
@@ -105,6 +121,7 @@ const httpRequestAttribute = {
105
121
  describe( 'ActivityExecutionInterceptor', () => {
106
122
  beforeEach( () => {
107
123
  vi.clearAllMocks();
124
+ activityInfoMock.workflowType = 'myWorkflow';
108
125
  workflowHandleMock.signal.mockResolvedValue( undefined );
109
126
  vi.useFakeTimers();
110
127
  vi.resetModules();
@@ -132,22 +149,34 @@ describe( 'ActivityExecutionInterceptor', () => {
132
149
  aggregations: null,
133
150
  [ACTIVITY_WRAPPER_VERSION_FIELD]: 1
134
151
  } );
135
- expect( messageBusEmitMock ).toHaveBeenCalledWith( BusEventType.ACTIVITY_START, expect.objectContaining( {
136
- id: 'act-1', name: 'myWorkflow#myStep', kind: 'step', workflowId: 'wf-1', workflowName: 'myWorkflow'
137
- } ) );
138
- expect( messageBusEmitMock ).toHaveBeenCalledWith( BusEventType.ACTIVITY_END, expect.objectContaining( {
139
- id: 'act-1', name: 'myWorkflow#myStep', kind: 'step', workflowId: 'wf-1', workflowName: 'myWorkflow', duration: expect.any( Number )
140
- } ) );
141
- expect( addEventStartMock ).toHaveBeenCalledOnce();
142
- expect( addEventEndMock ).toHaveBeenCalledOnce();
152
+ expect( messageBusEmitMock ).toHaveBeenCalledWith(
153
+ BusEventType.ACTIVITY_START,
154
+ { activityInfo: activityInfoMock, workflowDetails: workflowDetailsMock, outputActivityKind: 'step' }
155
+ );
156
+ expect( messageBusEmitMock ).toHaveBeenCalledWith(
157
+ BusEventType.ACTIVITY_END,
158
+ { activityInfo: activityInfoMock, workflowDetails: workflowDetailsMock, outputActivityKind: 'step' }
159
+ );
160
+ expect( addEventStartMock ).toHaveBeenCalledWith( {
161
+ id: 'act-1',
162
+ name: 'myWorkflow#myStep',
163
+ kind: 'step',
164
+ parentId: 'run-1',
165
+ details: { someInput: 'data' },
166
+ traceInfo: traceInfoMock
167
+ } );
168
+ expect( addEventEndMock ).toHaveBeenCalledWith( { id: 'act-1', details: { result: 'ok' }, traceInfo: traceInfoMock } );
143
169
  expect( addEventErrorMock ).not.toHaveBeenCalled();
144
170
  expect( clientConstructorMock ).not.toHaveBeenCalled();
145
171
  expect( runWithContextMock ).toHaveBeenCalledWith(
146
172
  expect.any( Function ),
147
173
  expect.objectContaining( {
148
174
  parentId: 'act-1',
149
- executionContext: { workflowId: 'wf-1' },
175
+ activityInfo: activityInfoMock,
176
+ workflowDetails: workflowDetailsMock,
177
+ outputActivityKind: 'step',
150
178
  workflowFilename: '/workflows/myWorkflow.js',
179
+ traceInfo: traceInfoMock,
151
180
  addAttribute: expect.any( Function )
152
181
  } )
153
182
  );
@@ -166,7 +195,7 @@ describe( 'ActivityExecutionInterceptor', () => {
166
195
  } );
167
196
 
168
197
  expect( messageBusEmitMock ).toHaveBeenCalledWith( BusEventType.ACTIVITY_END, expect.any( Object ) );
169
- expect( addEventEndMock ).toHaveBeenCalledWith( { id: 'act-1', details: { result: 'sync' }, executionContext: { workflowId: 'wf-1' } } );
198
+ expect( addEventEndMock ).toHaveBeenCalledWith( { id: 'act-1', details: { result: 'sync' }, traceInfo: traceInfoMock } );
170
199
  expect( addEventErrorMock ).not.toHaveBeenCalled();
171
200
  } );
172
201
 
@@ -244,9 +273,10 @@ describe( 'ActivityExecutionInterceptor', () => {
244
273
  expect( logWarnMock ).toHaveBeenCalledWith( `Signal "${Signal.SEND_AGGREGATIONS}" failed`, expect.objectContaining( {
245
274
  message: 'signal failed',
246
275
  activityId: 'act-1',
247
- activityName: 'myWorkflow#myStep',
276
+ activityType: 'myWorkflow#myStep',
248
277
  workflowId: 'wf-1',
249
- workflowName: 'myWorkflow'
278
+ workflowType: 'myWorkflow',
279
+ runId: 'run-1'
250
280
  } ) );
251
281
  } );
252
282
 
@@ -261,12 +291,14 @@ describe( 'ActivityExecutionInterceptor', () => {
261
291
 
262
292
  await expect( promise ).rejects.toThrow( 'step failed' );
263
293
  expect( messageBusEmitMock ).toHaveBeenCalledWith( BusEventType.ACTIVITY_START, expect.any( Object ) );
264
- expect( messageBusEmitMock ).toHaveBeenCalledWith( BusEventType.ACTIVITY_ERROR, expect.objectContaining( {
265
- id: 'act-1', name: 'myWorkflow#myStep', kind: 'step', workflowId: 'wf-1', workflowName: 'myWorkflow',
266
- duration: expect.any( Number ), error: expect.any( Error )
267
- } ) );
294
+ expect( messageBusEmitMock ).toHaveBeenCalledWith( BusEventType.ACTIVITY_ERROR, {
295
+ activityInfo: activityInfoMock,
296
+ workflowDetails: workflowDetailsMock,
297
+ outputActivityKind: 'step',
298
+ error
299
+ } );
268
300
  expect( addEventStartMock ).toHaveBeenCalledOnce();
269
- expect( addEventErrorMock ).toHaveBeenCalledOnce();
301
+ expect( addEventErrorMock ).toHaveBeenCalledWith( { id: 'act-1', details: error, traceInfo: traceInfoMock } );
270
302
  expect( addEventEndMock ).not.toHaveBeenCalled();
271
303
  } );
272
304
 
@@ -331,7 +363,7 @@ describe( 'ActivityExecutionInterceptor', () => {
331
363
  const interceptor = new ActivityExecutionInterceptor( { activities: makeActivities(), workflows } );
332
364
 
333
365
  // Override context to use alias as workflowType
334
- contextInfoMock.workflowType = 'myWorkflowOld';
366
+ activityInfoMock.workflowType = 'myWorkflowOld';
335
367
  const next = vi.fn().mockResolvedValue( { result: 'ok' } );
336
368
 
337
369
  const promise = interceptor.execute( makeInput(), next );
@@ -345,7 +377,7 @@ describe( 'ActivityExecutionInterceptor', () => {
345
377
  );
346
378
 
347
379
  // Restore for other tests
348
- contextInfoMock.workflowType = 'myWorkflow';
380
+ activityInfoMock.workflowType = 'myWorkflow';
349
381
  } );
350
382
 
351
383
  it( 'does not heartbeat when OUTPUT_ACTIVITY_HEARTBEAT_ENABLED is false', async () => {
@@ -5,6 +5,7 @@ import { deepMerge } from '#utils';
5
5
  import { METADATA_ACCESS_SYMBOL, WorkflowSpecialOutput } from '#consts';
6
6
  // this is a dynamic generated file with activity configs overwrites
7
7
  import stepOptions from '../temp/__activity_options.js';
8
+ import { createWorkflowDetails } from '#internal_utils/temporal_context';
8
9
 
9
10
  /*
10
11
  This is not an AI comment!
@@ -17,8 +18,12 @@ import stepOptions from '../temp/__activity_options.js';
17
18
  */
18
19
  class HeadersInjectionInterceptor {
19
20
  async scheduleActivity( input, next ) {
20
- const memo = workflowInfo().memo ?? {};
21
- Object.assign( input.headers, memoToHeaders( memo ) );
21
+ const info = workflowInfo();
22
+ const memo = info.memo ?? {};
23
+ Object.assign( input.headers, memoToHeaders( {
24
+ ...memo,
25
+ workflowDetails: createWorkflowDetails( info )
26
+ } ) );
22
27
  // apply per-invocation options passed as second argument by rewritten calls
23
28
  const options = stepOptions[input.activityType];
24
29
  if ( options ) {
@@ -7,6 +7,35 @@ const workflowStartMock = vi.fn();
7
7
  const workflowEndMock = vi.fn();
8
8
  const workflowErrorMock = vi.fn();
9
9
  const isCancellationMock = vi.fn();
10
+ const startTime = new Date( '2026-06-02T09:00:00.000Z' );
11
+ const runStartTime = new Date( '2026-06-02T09:05:00.000Z' );
12
+ const workflowDetails = {
13
+ attempt: 1,
14
+ continuedFromExecutionRunId: undefined,
15
+ firstExecutionRunId: 'first-run',
16
+ parent: undefined,
17
+ root: undefined,
18
+ runId: 'run-1',
19
+ runStartTime: runStartTime.getTime(),
20
+ startTime: startTime.getTime(),
21
+ workflowId: 'workflow-1',
22
+ workflowType: 'MyWorkflow'
23
+ };
24
+
25
+ const workflowInfo = {
26
+ attempt: 1,
27
+ continuedFromExecutionRunId: undefined,
28
+ firstExecutionRunId: 'first-run',
29
+ parent: undefined,
30
+ root: undefined,
31
+ runId: 'run-1',
32
+ runStartTime,
33
+ startTime,
34
+ workflowId: 'workflow-1',
35
+ workflowType: 'MyWorkflow',
36
+ memo: { traceInfo: { runId: 'root-run' } }
37
+ };
38
+
10
39
  vi.mock( '@temporalio/workflow', () => ( {
11
40
  workflowInfo: ( ...args ) => workflowInfoMock( ...args ),
12
41
  proxySinks: () => ( {
@@ -53,7 +82,7 @@ describe( 'workflow interceptors', () => {
53
82
  beforeEach( () => {
54
83
  vi.clearAllMocks();
55
84
  isCancellationMock.mockReturnValue( false );
56
- workflowInfoMock.mockReturnValue( { workflowType: 'MyWorkflow', memo: { executionContext: { id: 'ctx-1' } } } );
85
+ workflowInfoMock.mockReturnValue( workflowInfo );
57
86
  } );
58
87
 
59
88
  describe( 'HeadersInjectionInterceptor', () => {
@@ -64,12 +93,19 @@ describe( 'workflow interceptors', () => {
64
93
  const input = { headers: { existing: 'header' }, activityType: 'MyWorkflow#step1' };
65
94
  const next = vi.fn().mockResolvedValue( 'result' );
66
95
 
67
- memoToHeadersMock.mockReturnValue( { executionContext: { id: 'ctx-1' } } );
96
+ memoToHeadersMock.mockReturnValue( { traceInfo: workflowInfo.memo.traceInfo, workflowDetails } );
68
97
 
69
98
  const out = await interceptor.scheduleActivity( input, next );
70
99
 
71
- expect( memoToHeadersMock ).toHaveBeenCalledWith( { executionContext: { id: 'ctx-1' } } );
72
- expect( input.headers ).toEqual( { existing: 'header', executionContext: { id: 'ctx-1' } } );
100
+ expect( memoToHeadersMock ).toHaveBeenCalledWith( {
101
+ traceInfo: workflowInfo.memo.traceInfo,
102
+ workflowDetails
103
+ } );
104
+ expect( input.headers ).toEqual( {
105
+ existing: 'header',
106
+ traceInfo: workflowInfo.memo.traceInfo,
107
+ workflowDetails
108
+ } );
73
109
  expect( next ).toHaveBeenCalledWith( input );
74
110
  expect( out ).toBe( 'result' );
75
111
  } );
@@ -77,8 +113,8 @@ describe( 'workflow interceptors', () => {
77
113
  it( 'merges stepOptions with memo.activityOptions when stepOptions exist for activityType', async () => {
78
114
  stepOptionsDefault['MyWorkflow#step1'] = { scheduleToCloseTimeout: 60 };
79
115
  workflowInfoMock.mockReturnValue( {
80
- workflowType: 'MyWorkflow',
81
- memo: { executionContext: {}, activityOptions: { heartbeatTimeout: 10 } }
116
+ ...workflowInfo,
117
+ memo: { traceInfo: workflowInfo.memo.traceInfo, activityOptions: { heartbeatTimeout: 10 } }
82
118
  } );
83
119
  memoToHeadersMock.mockReturnValue( {} );
84
120
  deepMergeMock.mockReturnValue( { heartbeatTimeout: 10, scheduleToCloseTimeout: 60 } );
@@ -1,6 +1,6 @@
1
1
  import { messageBus } from '#bus';
2
2
  import { createChildLogger } from '#logger';
3
- import { BusEventType, ComponentType, LifecycleEvent, WORKFLOW_CATALOG } from '#consts';
3
+ import { ACTIVITY_GET_TRACE_DESTINATIONS, BusEventType, LifecycleEvent, WORKFLOW_CATALOG } from '#consts';
4
4
 
5
5
  const activityLog = createChildLogger( 'Activity' );
6
6
  const workflowLog = createChildLogger( 'Workflow' );
@@ -15,43 +15,34 @@ const workflowLog = createChildLogger( 'Workflow' );
15
15
  ╚═════════════════╝
16
16
  */
17
17
 
18
- /**
19
- * Returns true if activity event should be logged
20
- */
21
- const shouldLogActivityEvent = ( { kind } ) => kind !== ComponentType.INTERNAL_STEP;
18
+ const serializedActivityFields = activityInfo => ( {
19
+ activityId: activityInfo.activityId,
20
+ activityType: activityInfo.activityType,
21
+ workflowId: activityInfo.workflowExecution.workflowId,
22
+ workflowType: activityInfo.workflowType,
23
+ runId: activityInfo.workflowExecution.runId
24
+ } );
25
+
26
+ const shouldLogActivity = activityInfo => activityInfo.activityType !== ACTIVITY_GET_TRACE_DESTINATIONS;
22
27
 
23
- messageBus.on( BusEventType.ACTIVITY_START, ( { id, name, kind, workflowId, workflowName } ) =>
24
- shouldLogActivityEvent( { kind } ) && activityLog.info( `Started ${name} ${kind}`, {
28
+ messageBus.on( BusEventType.ACTIVITY_START, ( { activityInfo, outputActivityKind } ) =>
29
+ shouldLogActivity( activityInfo ) && activityLog.info( `Started ${activityInfo.activityType} ${outputActivityKind}`, {
25
30
  event: LifecycleEvent.START,
26
- activityId: id,
27
- activityName: name,
28
- activityKind: kind,
29
- workflowId,
30
- workflowName
31
+ ...serializedActivityFields( activityInfo )
31
32
  } )
32
33
  );
33
34
 
34
- messageBus.on( BusEventType.ACTIVITY_END, ( { id, name, kind, workflowId, workflowName, duration } ) =>
35
- shouldLogActivityEvent( { kind } ) && activityLog.info( `Ended ${name} ${kind}`, {
35
+ messageBus.on( BusEventType.ACTIVITY_END, ( { activityInfo, outputActivityKind } ) =>
36
+ shouldLogActivity( activityInfo ) && activityLog.info( `Ended ${activityInfo.activityType} ${outputActivityKind}`, {
36
37
  event: LifecycleEvent.END,
37
- activityId: id,
38
- activityName: name,
39
- activityKind: kind,
40
- workflowId,
41
- workflowName,
42
- durationMs: duration
38
+ ...serializedActivityFields( activityInfo )
43
39
  } )
44
40
  );
45
41
 
46
- messageBus.on( BusEventType.ACTIVITY_ERROR, ( { id, name, kind, workflowId, workflowName, duration, error } ) =>
47
- shouldLogActivityEvent( { kind } ) && activityLog.error( `Error ${name} ${kind}: ${error.constructor.name}`, {
42
+ messageBus.on( BusEventType.ACTIVITY_ERROR, ( { activityInfo, outputActivityKind, error } ) =>
43
+ shouldLogActivity( activityInfo ) && activityLog.error( `Error ${activityInfo.activityType} ${outputActivityKind}: ${error.constructor.name}`, {
48
44
  event: LifecycleEvent.ERROR,
49
- activityId: id,
50
- activityName: name,
51
- activityKind: kind,
52
- workflowId,
53
- workflowName,
54
- durationMs: duration,
45
+ ...serializedActivityFields( activityInfo ),
55
46
  error: error.message
56
47
  } )
57
48
  );
@@ -62,34 +53,32 @@ messageBus.on( BusEventType.ACTIVITY_ERROR, ( { id, name, kind, workflowId, work
62
53
  ╚═════════════════╝
63
54
  */
64
55
 
65
- /**
66
- * Returns true if activity event should be logged
67
- */
68
- const shouldLogWorkflowEvent = ( { name } ) => name !== WORKFLOW_CATALOG;
56
+ const serializeWorkflowFields = workflowDetails => ( {
57
+ workflowId: workflowDetails.workflowId,
58
+ workflowType: workflowDetails.workflowType,
59
+ runId: workflowDetails.runId
60
+ } );
61
+
62
+ const shouldLogWorkflow = workflowDetails => workflowDetails.workflowType !== WORKFLOW_CATALOG;
69
63
 
70
- messageBus.on( BusEventType.WORKFLOW_START, ( { id, name } ) =>
71
- shouldLogWorkflowEvent( { name } ) && workflowLog.info( `Started ${name} workflow`, {
64
+ messageBus.on( BusEventType.WORKFLOW_START, ( { workflowDetails } ) =>
65
+ shouldLogWorkflow( workflowDetails ) && workflowLog.info( `Started ${workflowDetails.workflowType} workflow`, {
72
66
  event: LifecycleEvent.START,
73
- workflowId: id,
74
- workflowName: name
67
+ ...serializeWorkflowFields( workflowDetails )
75
68
  } )
76
69
  );
77
70
 
78
- messageBus.on( BusEventType.WORKFLOW_END, ( { id, name, duration } ) =>
79
- shouldLogWorkflowEvent( { name } ) && workflowLog.info( `Ended ${name} workflow`, {
71
+ messageBus.on( BusEventType.WORKFLOW_END, ( { workflowDetails } ) =>
72
+ shouldLogWorkflow( workflowDetails ) && workflowLog.info( `Ended ${workflowDetails.workflowType} workflow`, {
80
73
  event: LifecycleEvent.END,
81
- workflowId: id,
82
- workflowName: name,
83
- durationMs: duration
74
+ ...serializeWorkflowFields( workflowDetails )
84
75
  } )
85
76
  );
86
77
 
87
- messageBus.on( BusEventType.WORKFLOW_ERROR, ( { id, name, duration, error } ) =>
88
- shouldLogWorkflowEvent( { name } ) && workflowLog.error( `Error ${name} workflow: ${error.constructor.name}`, {
78
+ messageBus.on( BusEventType.WORKFLOW_ERROR, ( { workflowDetails, error } ) =>
79
+ shouldLogWorkflow( workflowDetails ) && workflowLog.error( `Error ${workflowDetails.workflowType} workflow: ${error.constructor.name}`, {
89
80
  event: LifecycleEvent.ERROR,
90
- workflowId: id,
91
- workflowName: name,
92
- durationMs: duration,
81
+ ...serializeWorkflowFields( workflowDetails ),
93
82
  error: error.message
94
83
  } )
95
84
  );