-
Notifications
You must be signed in to change notification settings - Fork 213
Expand file tree
/
Copy pathjson-logs.ts
More file actions
125 lines (111 loc) · 3.3 KB
/
json-logs.ts
File metadata and controls
125 lines (111 loc) · 3.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import { calculateTotals, conditionallyMaskSecrets } from '@redocly/respect-core';
import type {
TestContext,
JsonLogs,
WorkflowExecutionResult,
WorkflowExecutionResultJson,
Step,
StepExecutionResult,
Check,
} from '@redocly/respect-core';
export function composeJsonLogsFiles(
filesResult: {
file: string;
totalRequests: number;
totalTimeMs: number;
executedWorkflows: WorkflowExecutionResult[];
ctx: TestContext;
globalTimeoutError: boolean;
secretValues?: string[];
}[]
): JsonLogs['files'] {
const files: JsonLogs['files'] = {};
for (const fileResult of filesResult) {
const {
executedWorkflows,
globalTimeoutError: fileGlobalTimeoutError,
ctx,
secretValues,
} = fileResult;
files[fileResult.file] = conditionallyMaskSecrets({
value: {
totalRequests: fileResult.totalRequests,
executedWorkflows: executedWorkflows.map((workflow) => mapJsonWorkflow(workflow)),
totalTimeMs: fileResult.totalTimeMs,
globalTimeoutError: fileGlobalTimeoutError,
secretValues,
},
secretsReveal: ctx.secretsReveal,
secretsSet: ctx.secretsSet || new Set(),
});
}
return files;
}
function mapJsonWorkflow(workflow: WorkflowExecutionResult): WorkflowExecutionResultJson {
const { ctx, ...rest } = workflow;
const steps = workflow.executedSteps.map((step) => mapJsonStep(step, workflow.workflowId, ctx));
const totals = calculateTotals([workflow]);
const result: WorkflowExecutionResultJson = {
...rest,
executedSteps: steps,
status: totals.steps.failed > 0 ? 'error' : totals.steps.warnings > 0 ? 'warn' : 'success',
totalRequests: totals.totalRequests,
totalTimeMs: workflow.totalTimeMs,
};
return result;
}
function mapJsonStep(
step: Step | WorkflowExecutionResult,
workflowId: string,
ctx: TestContext
): StepExecutionResult | WorkflowExecutionResultJson {
if ('executedSteps' in step) {
return mapJsonWorkflow(step as WorkflowExecutionResult);
}
const publicStep = ctx.$workflows[workflowId].steps[step.stepId];
return {
type: 'step',
stepId: step.stepId,
workflowId,
request: {
method: publicStep.request?.method || '',
url: step.response?.requestUrl || '',
headers: publicStep.request?.header || {},
body: publicStep.request?.body,
},
response: {
statusCode: step.response?.statusCode || 0,
body: publicStep.response?.body,
headers: step.response?.header || {},
time: step.response?.time || 0,
},
checks: step.checks.map((check) => ({
...check,
status: calculateCheckStatus(check),
})),
totalTimeMs: publicStep.response?.time || 0,
retriesLeft: step.retriesLeft,
status: calculateStepStatus(step.checks),
};
}
function calculateCheckStatus(check: Check): 'success' | 'error' | 'warn' {
if (check.passed) {
return 'success';
}
if (check.severity === 'error') {
return 'error';
}
return 'warn';
}
function calculateStepStatus(checks: Check[]): 'success' | 'error' | 'warn' {
let hasWarning = false;
for (const check of checks) {
if (!check.passed && check.severity === 'error') {
return 'error';
}
if (!check.passed && check.severity === 'warn') {
hasWarning = true;
}
}
return hasWarning ? 'warn' : 'success';
}