fix(maestro-processes): update getExecutionHistory to use element-executions and Traces APIs [PLT-97257]#428
fix(maestro-processes): update getExecutionHistory to use element-executions and Traces APIs [PLT-97257]#428Sarath1018 wants to merge 8 commits into
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
…cutions and Traces APIs Replaces the single spans endpoint with a two-call flow: first fetches element-executions to get structural data and traceId, then fetches Traces/spans and merges results by elementRunId. Adds folderKey param for authorization on both calls. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…xecutionHistory Replaces positional folderKey string param with ProcessInstanceGetExecutionHistoryOptions extending FolderScopedOptions (folderKey/folderId/folderPath). Uses resolveFolderHeaders for consistent folder context resolution, matching the pattern from PR #386. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… error handling - Correct @example: replace non-existent span.startTime/duration with span.startedTime/endTime; add missing @param for options - Integration test: throw instead of console.log+return on missing precondition; remove try/catch so errors propagate naturally Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ceId lookup - Use response.data.traceId (not instanceId) for the Traces/spans call - Match spans by parsing Attributes JSON for elementRunId instead of span.Id - Add traceId field to ElementExecutionsApiResponse internal type - Fix integration test to use config.folderKey (not folderId) and add field-level assertions on the response shape - Update mock traceId and Attributes to match real API structure - Update oauth-scopes.md: getExecutionHistory requires PIMS + Traces.Api Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Allows calling without folder context when SDK is initialized with a meta-tag folder key (coded-app deployments). resolveFolderHeaders handles the fallback. Bound method passes folderKey if present on instance data, undefined otherwise. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
07f84f9 to
aef9191
Compare
This comment was marked as resolved.
This comment was marked as resolved.
… in service class Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| name: span.Name, | ||
| startedTime: span.StartTime, | ||
| endTime: span.EndTime, | ||
| attributes: span.Attributes, |
There was a problem hiding this comment.
should we parse attributes as this is a json string?
|
|
||
| try { | ||
| const result = await processInstances.getExecutionHistory(testInstanceId); | ||
| const result = await processInstances.getExecutionHistory(testInstanceId, { folderKey: config.folderKey || '' }); |
There was a problem hiding this comment.
Per convention: "Always throw new Error() when test preconditions are not met — whether it's missing config (e.g., no folderId) or missing test data." config.folderKey || '' silently passes an empty string when folderKey is not configured. This changes folder-resolution behaviour in resolveFolderHeaders (an empty string is not the same as undefined) and masks an unrunnable test.
| const result = await processInstances.getExecutionHistory(testInstanceId, { folderKey: config.folderKey || '' }); | |
| if (!config.folderKey) throw new Error('folderKey not configured — set UIPATH_FOLDER_KEY in test env to run this test'); | |
| const result = await processInstances.getExecutionHistory(testInstanceId, { folderKey: config.folderKey }); |
| expect(result[0]).toHaveProperty('id', MAESTRO_TEST_CONSTANTS.SPAN_ID); | ||
| expect(result[0]).toHaveProperty('traceId', MAESTRO_TEST_CONSTANTS.TRACE_ID); | ||
| expect(result[0]).toHaveProperty('name', MAESTRO_TEST_CONSTANTS.ACTIVITY_NAME); |
There was a problem hiding this comment.
Per convention: "Validate transform completeness — verify both: (a) transformed fields have correct values, AND (b) original PascalCase fields are absent. This catches transform regressions that value-only assertions miss."
mapSpanToHistory explicitly maps span.Id → id, span.TraceId → traceId, span.Name → name, span.StartTime → startedTime, etc. The test verifies the camelCase values are present but never checks that the raw PascalCase fields are absent. A regression where mapSpanToHistory accidentally spreads the whole span (exposing Id, TraceId, StartTime, …) would pass these assertions undetected.
Add absence checks after the existing ones:
expect(result[0]).toHaveProperty('id', MAESTRO_TEST_CONSTANTS.SPAN_ID);
expect(result[0]).toHaveProperty('traceId', MAESTRO_TEST_CONSTANTS.TRACE_ID);
expect(result[0]).toHaveProperty('name', MAESTRO_TEST_CONSTANTS.ACTIVITY_NAME);
// transform completeness: raw PascalCase fields must not leak through
expect((result[0] as any).Id).toBeUndefined();
expect((result[0] as any).TraceId).toBeUndefined();
expect((result[0] as any).StartTime).toBeUndefined();
Review findingsTwo new issues found this run: 1. Integration test silently accepts missing
|
…n getExecutionHistory Aligns getExecutionHistory with the rest of the ProcessInstances service (getById, cancel, pause, resume, getBpmn) which all take folderKey as a required positional argument. The Maestro element-executions endpoint requires X-UIPATH-FolderKey and does not accept folderId or X-UIPATH-FolderPath-Encoded, so the FolderScopedOptions surface was misleading. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
| * Get execution history (spans) for a process instance | ||
| * @param instanceId The ID of the instance to get history for | ||
| * @param folderKey The folder key for authorization | ||
| * @returns Promise<ProcessInstanceExecutionHistoryResponse[]> |
There was a problem hiding this comment.
Per convention: "Keep JSDoc on service class methods in sync with {Entity}ServiceModel — both the models file and the service implementation file must have identical JSDoc for each public method."
The ProcessInstancesServiceModel interface in process-instances.models.ts has:
* @returns Promise resolving to execution history
* {@link ProcessInstanceExecutionHistoryResponse}
* @example
* ```typescript
* // Get execution history for a process instance
* const history = await processInstances.getExecutionHistory(
* <instanceId>,
* <folderKey>
* );
*
* // Analyze execution timeline
* history.forEach(span => {
* console.log(`Activity: ${span.name}`);
* console.log(`Start: ${span.startedTime}`);
* console.log(`End: ${span.endTime}`);
* });
* ```
The service implementation has only @returns Promise<ProcessInstanceExecutionHistoryResponse[]> — missing the {@link} and the entire @example block. The service copy must be brought to match the model.
|



Method Added
processInstances.getExecutionHistory()getExecutionHistory(instanceId: string, options: ProcessInstanceGetExecutionHistoryOptions): Promise<ProcessInstanceExecutionHistoryResponse[]>Endpoint Called
getExecutionHistory()pims_/api/v1/instances/{instanceId}/element-executionsgetExecutionHistory()llmopstenant_/api/Traces/spans?traceId={traceId}optionsextendsFolderScopedOptions(folderKey,folderId,folderPath) — usesresolveFolderHeaders()for consistent folder context resolution, matching the pattern from feat(orchestrator): getByName for Assets + Processes, encoded folder header, meta-tag fallback [PLT-92768][PLT-92817][PLT-92813] #386elementRunIdfrom the element-executions response are returned — the rootProcessRunspan (covers the whole instance, noelementRunId) is dropped automaticallySample SDK response (live API)
[ { "id": "00000000-0000-0000-0b6a-051ca7aec9ce", "traceId": "910e3f56-1fbd-4947-9cee-148355c38d08", "parentId": "00000000-0000-0000-9b54-950bbe5a2e63", "name": "Start event", "startedTime": "2026-05-12T11:48:06.077714Z", "endTime": "2026-05-12T11:48:06.8733245Z", "attributes": "{\"spanType\":\"ElementRun\",\"status\":\"Completed\",\"elementId\":\"Event_start\",\"elementRunId\":\"88952b06-da40-4ab5-8cf3-2fecfbc53164\",\"elementType\":\"StartEvent\",\"runIndex\":1,...}", "updatedTime": "2026-05-12T11:48:07.1584589Z", "expiredTime": null }, { "id": "00000000-0000-0000-42ef-2088c0ac72ac", "traceId": "910e3f56-1fbd-4947-9cee-148355c38d08", "parentId": "00000000-0000-0000-9b54-950bbe5a2e63", "name": "Activity_tblfOr", "startedTime": "2026-05-12T11:48:07.4381836Z", "endTime": "2026-05-12T11:48:07.7687194Z", "attributes": "{\"spanType\":\"ElementRun\",\"status\":\"Completed\",\"elementId\":\"Activity_tblfOr\",\"elementRunId\":\"c0322c6a-16fb-4232-bee2-8811445c16ca\",\"elementType\":\"Task\",\"runIndex\":1,...}", "updatedTime": "2026-05-12T11:48:08.2378818Z", "expiredTime": null }, { "id": "00000000-0000-0000-38ec-7544ef9d965d", "traceId": "910e3f56-1fbd-4947-9cee-148355c38d08", "parentId": "00000000-0000-0000-9b54-950bbe5a2e63", "name": "Event_lLnUK8", "startedTime": "2026-05-12T11:48:08.5335271Z", "endTime": "2026-05-12T11:48:09.1996998Z", "attributes": "{\"spanType\":\"ElementRun\",\"status\":\"Completed\",\"elementId\":\"Event_lLnUK8\",\"elementRunId\":\"23f305b7-ffbf-4d0b-bba7-5fe2b4127aab\",\"elementType\":\"EndEvent\",\"runIndex\":1,...}", "updatedTime": "2026-05-12T11:48:09.4081965Z", "expiredTime": null } ]Example Usage
API Response vs SDK Response
Composition flow
Fixes #265
🤖 Auto-generated using onboarding skills