Skip to content

Commit 9f73ae1

Browse files
committed
Log more structued information when running graph
1 parent 64d28fa commit 9f73ae1

8 files changed

Lines changed: 105 additions & 61 deletions

File tree

packages/flowtest-electron/src/ipc/collection.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ const registerRendererEventHandlers = (mainWindow, watcher) => {
303303
status: result.status,
304304
statusText: result.statusText,
305305
data: result.data,
306+
headers: result.headers,
306307
};
307308
} catch (error) {
308309
if (error?.response) {

src/components/molecules/flow/graph/Graph.js

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ import complexNode from './compute/complexnode';
88
import assertNode from './compute/assertnode';
99
import requestNode from './compute/requestnode';
1010
import setVarNode from './compute/setvarnode';
11+
import { LogLevel } from './GraphLogger';
1112

1213
class Graph {
13-
constructor(nodes, edges, startTime, initialEnvVars, initialLogs) {
14+
constructor(nodes, edges, startTime, initialEnvVars, logger) {
1415
this.nodes = nodes;
1516
this.edges = edges;
16-
this.logs = initialLogs;
17+
this.logger = logger;
1718
this.timeout = useCanvasStore.getState().timeout;
1819
this.startTime = startTime;
1920
this.graphRunNodeOutput = {};
@@ -67,7 +68,8 @@ class Graph {
6768
console.debug('Executing node: ', node);
6869

6970
if (node.type === 'outputNode') {
70-
this.logs.push(`Output: ${JSON.stringify(prevNodeOutputData)}`);
71+
//this.logs.push(`Output: ${JSON.stringify(prevNodeOutputData)}`);
72+
this.logger.add(LogLevel.INFO, '', { type: 'outputNode', data: prevNodeOutputData });
7173
useCanvasStore.getState().setOutputNode(node.id, prevNodeOutputData);
7274
result = {
7375
status: 'Success',
@@ -81,17 +83,15 @@ class Graph {
8183
node.data.variables,
8284
prevNodeOutputData,
8385
this.envVariables,
84-
this.logs,
86+
this.logger,
8587
);
8688
if (eNode.evaluate()) {
87-
this.logs.push('Result: true');
8889
result = {
8990
status: 'Success',
9091
data: prevNodeOutputData,
9192
output: true,
9293
};
9394
} else {
94-
this.logs.push('Result: false');
9595
result = {
9696
status: 'Success',
9797
data: prevNodeOutputData,
@@ -106,7 +106,7 @@ class Graph {
106106
return new Promise((resolve) => setTimeout(resolve, Math.min(ms, this.timeout)));
107107
};
108108
await wait(delay);
109-
this.logs.push(`Wait for: ${delay} ms`);
109+
this.logger.add(LogLevel.INFO, '', { type: 'delayNode', data: delay });
110110
result = {
111111
status: 'Success',
112112
};
@@ -121,7 +121,7 @@ class Graph {
121121
}
122122

123123
if (node.type === 'requestNode') {
124-
const rNode = new requestNode(node.data, prevNodeOutputData, this.envVariables, this.auth, this.logs);
124+
const rNode = new requestNode(node.data, prevNodeOutputData, this.envVariables, this.auth, this.logger);
125125
result = await rNode.evaluate();
126126
// add post response variables if any
127127
if (result.postRespVars) {
@@ -140,7 +140,7 @@ class Graph {
140140
cloneDeep(flowData.edges),
141141
this.startTime,
142142
this.envVariables,
143-
this.logs,
143+
this.logger,
144144
);
145145
result = await cNode.evaluate();
146146
this.envVariables = result.envVars;
@@ -155,7 +155,13 @@ class Graph {
155155
const sNode = new setVarNode(node.data, prevNodeOutputData, this.envVariables);
156156
const newVariable = sNode.evaluate();
157157
if (newVariable != undefined) {
158-
this.logs.push(`Evaluate variable: ${JSON.stringify(newVariable)}`);
158+
this.logger.add(LogLevel.INFO, 'Set Variable', {
159+
type: 'setVarNode',
160+
data: {
161+
name: Object.keys(newVariable)[0],
162+
value: newVariable[Object.keys(newVariable)[0]],
163+
},
164+
});
159165
this.envVariables = {
160166
...this.envVariables,
161167
...newVariable,
@@ -167,17 +173,18 @@ class Graph {
167173
}
168174

169175
if (this.#checkTimeout()) {
176+
this.logger.add(LogLevel.ERROR, `Timeout of ${this.timeout} ms exceeded, stopping graph run`, node);
170177
throw `Timeout of ${this.timeout} ms exceeded, stopping graph run`;
171178
}
172179
} catch (err) {
173-
this.logs.push(`Flow failed at: ${JSON.stringify(node)} due to ${err}`);
180+
this.logger.add(LogLevel.ERROR, `Flow failed due to ${err}`, node);
174181
return {
175182
status: 'Failed',
176183
};
177184
}
178185

179186
if (result === undefined) {
180-
this.logs.push(`Flow failed at: ${JSON.stringify(node)}`);
187+
this.logger.add(LogLevel.ERROR, 'Flow failed due to failure to evaluate result', node);
181188
return {
182189
status: 'Failed',
183190
};
@@ -208,11 +215,11 @@ class Graph {
208215
});
209216
this.graphRunNodeOutput = {};
210217

211-
this.logs.push('Start Flowtest');
218+
this.logger.add(LogLevel.INFO, 'Start Flowtest');
212219
const startNode = this.nodes.find((node) => node.type === 'startNode');
213220
if (startNode == undefined) {
214-
this.logs.push('No start node found');
215-
this.logs.push('End Flowtest');
221+
this.logger.add(LogLevel.INFO, 'No start node found');
222+
this.logger.add(LogLevel.INFO, 'End Flowtest');
216223
return {
217224
status: 'Success',
218225
logs: this.logs,
@@ -228,18 +235,14 @@ class Graph {
228235
// if (result.status == 'Failed') {
229236
// console.debug('Flow failed at: ', result.node);
230237
// }
231-
this.logs.push('End Flowtest');
238+
this.logger.add(LogLevel.INFO, 'End Flowtest');
232239
return {
233240
status: result.status,
234-
logs: this.logs,
235-
envVars: this.envVariables,
236241
};
237242
} else {
238-
this.logs.push('End Flowtest');
243+
this.logger.add(LogLevel.INFO, 'End Flowtest');
239244
return {
240245
status: 'Success',
241-
logs: this.logs,
242-
envVars: this.envVariables,
243246
};
244247
}
245248
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
export const LogLevel = Object.freeze({
2+
INFO: 0,
3+
WARN: 1,
4+
ERROR: 2,
5+
});
6+
7+
class GraphLogger {
8+
constructor() {
9+
this.logs = [];
10+
}
11+
12+
add(logLevel, message, node) {
13+
this.logs.push({
14+
logLevel,
15+
timestamp: new Date().toISOString(),
16+
message,
17+
node,
18+
});
19+
}
20+
21+
get() {
22+
return this.logs;
23+
}
24+
}
25+
26+
export default GraphLogger;

src/components/molecules/flow/graph/compute/assertnode.js

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import AssertOperators from '../../constants/assertOperators';
22
import { computeNodeVariable } from './utils';
33
import Node from './node';
4+
import { LogLevel } from '../GraphLogger';
45

56
class assertNode extends Node {
6-
constructor(operator, variables, prevNodeOutputData, envVariables, logs) {
7+
constructor(operator, variables, prevNodeOutputData, envVariables, logger) {
78
super('assertNode');
89
this.operator = operator;
910
this.variables = variables;
1011
this.prevNodeOutputData = prevNodeOutputData;
11-
this.logs = logs;
12+
this.logger = logger;
1213
this.envVariables = envVariables;
1314
}
1415

@@ -33,18 +34,27 @@ class assertNode extends Node {
3334
if (operator == undefined) {
3435
throw 'Operator undefined';
3536
}
36-
this.logs.push(
37-
`Assert var1: ${JSON.stringify(var1)} of type: ${typeof var1}, var2: ${JSON.stringify(var2)} of type: ${typeof var2} with operator: ${operator}`,
38-
);
39-
if (operator == AssertOperators.isEqualTo) {
40-
return var1 === var2;
41-
} else if (operator == AssertOperators.isNotEqualTo) {
42-
return var1 != var2;
43-
} else if (operator == AssertOperators.isGreaterThan) {
44-
return var1 > var2;
45-
} else if (operator == AssertOperators.isLessThan) {
46-
return var1 < var2;
37+
38+
let result;
39+
switch (operator) {
40+
case AssertOperators.isEqualTo:
41+
result = var1 === var2;
42+
break;
43+
case AssertOperators.isNotEqualTo:
44+
result = var1 != var2;
45+
break;
46+
case AssertOperators.isGreaterThan:
47+
result = var1 > var2;
48+
break;
49+
case AssertOperators.isLessThan:
50+
result = var1 < var2;
51+
break;
52+
default:
53+
throw 'Unsupported operator';
4754
}
55+
this.logger.add(LogLevel.INFO, '', { type: 'assertNode', data: { var1, var2, result } });
56+
57+
return result;
4858
}
4959
}
5060

src/components/molecules/flow/graph/compute/complexnode.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import Graph1 from '../Graph';
22
import Node from './node';
33

44
class complexNode extends Node {
5-
constructor(nodes, edges, startTime, initialEnvVars, initialLogs) {
5+
constructor(nodes, edges, startTime, initialEnvVars, logger) {
66
super('complexNode');
7-
this.internalGraph = new Graph1(nodes, edges, startTime, initialEnvVars, initialLogs);
7+
this.internalGraph = new Graph1(nodes, edges, startTime, initialEnvVars, logger);
88
}
99

1010
async evaluate() {

src/components/molecules/flow/graph/compute/requestnode.js

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import { computeNodeVariables, computeVariables } from '../compute/utils';
2+
import { LogLevel } from '../GraphLogger';
23
import Node from './node';
34

45
class requestNode extends Node {
5-
constructor(nodeData, prevNodeOutputData, envVariables, auth, logs) {
6+
constructor(nodeData, prevNodeOutputData, envVariables, auth, logger) {
67
super('requestNode');
78
this.nodeData = nodeData;
89
this.prevNodeOutputData = prevNodeOutputData;
910
this.envVariables = envVariables;
1011
this.auth = auth;
11-
this.logs = logs;
12+
this.logger = logger;
1213
}
1314

1415
async evaluate() {
@@ -32,28 +33,37 @@ class requestNode extends Node {
3233
const res = await this.runHttpRequest(options);
3334

3435
if (res.error) {
35-
//console.debug('Failure at node: ', node);
36-
//console.debug('Error encountered: ', JSON.stringify(res.error));
37-
this.logs.push(`Request failed: ${JSON.stringify(res.error)}`);
36+
this.logger.add(LogLevel.ERROR, 'HTTP request failed', {
37+
type: 'requestNode',
38+
data: { request: { type: options.method, url: options.url }, response: res.error, preReqVars: evalVariables },
39+
});
3840
return {
3941
status: 'Failed',
40-
//node,
4142
};
4243
} else {
43-
this.logs.push(`Request successful: ${JSON.stringify(res)}`);
44-
console.debug('Response: ', JSON.stringify(res));
4544
if (this.nodeData.postRespVars) {
4645
const evalPostRespVars = computeNodeVariables(this.nodeData.postRespVars, res.data);
46+
this.logger.add(LogLevel.INFO, 'HTTP request success', {
47+
type: 'requestNode',
48+
data: {
49+
request: { type: options.method, url: options.url },
50+
response: res,
51+
preReqVars: evalVariables,
52+
postRespVars: evalPostRespVars,
53+
},
54+
});
4755
return {
4856
status: 'Success',
49-
//node,
5057
data: res.data,
5158
postRespVars: evalPostRespVars,
5259
};
5360
}
61+
this.logger.add(LogLevel.INFO, 'HTTP request success', {
62+
type: 'requestNode',
63+
data: { request: { type: options.method, url: options.url }, response: res, preReqVars: evalVariables },
64+
});
5465
return {
5566
status: 'Success',
56-
//node,
5767
data: res.data,
5868
};
5969
}
@@ -95,7 +105,6 @@ class requestNode extends Node {
95105
options.auth.password = this.auth.password;
96106
}
97107

98-
this.logs.push(`${restMethod} ${finalUrl}`);
99108
return options;
100109
}
101110

src/components/molecules/flow/index.js

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import SetVarNode from './nodes/SetVarNode';
2525
import { saveHandle } from '../modals/SaveFlowModal';
2626
import Button from 'components/atoms/common/Button';
2727
import { BUTTON_INTENT_TYPES, BUTTON_TYPES } from 'constants/Common';
28+
import GraphLogger, { LogLevel } from './graph/GraphLogger';
2829

2930
const StartNode = () => (
3031
<FlowNode title='Start' handleLeft={false} handleRight={true} handleRightData={{ type: 'source' }}></FlowNode>
@@ -243,8 +244,6 @@ const Flow = ({ tab, collectionId }) => {
243244
runnableEdges(true);
244245
const startTime = Date.now();
245246
try {
246-
let result = undefined;
247-
let g = undefined;
248247
let envVariables = {};
249248

250249
const activeEnv = useCollectionStore
@@ -256,22 +255,18 @@ const Flow = ({ tab, collectionId }) => {
256255
}
257256

258257
// ============= flow =====================
259-
g = new Graph(
258+
const logger = new GraphLogger();
259+
const g = new Graph(
260260
cloneDeep(reactFlowInstance.getNodes()),
261261
cloneDeep(reactFlowInstance.getEdges()),
262262
startTime,
263-
result ? result.envVars : envVariables,
264-
result ? result.logs : [],
263+
envVariables,
264+
logger,
265265
);
266-
result = await g.run();
266+
const result = await g.run();
267+
logger.add(LogLevel.INFO, `Total time: ${Date.now() - startTime} ms`);
267268

268-
if (result.status === 'Failed') {
269-
onGraphComplete(result.status, result.logs);
270-
return;
271-
}
272-
273-
result.logs.push(`Total time: ${Date.now() - startTime} ms`);
274-
onGraphComplete(result.status, result.logs);
269+
onGraphComplete(result.status, logger.get());
275270
} catch (error) {
276271
toast.error(`Error running graph: ${error}`);
277272
runnableEdges(false);

src/components/molecules/headers/TabPanelHeader.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ const TabPanelHeader = () => {
100100
<ul className='min-h-full p-4 menu w-80 bg-base-200 text-base-content'>
101101
{graphRunLogs.map((item, index) => (
102102
<li key={index}>
103-
<a>{item}</a>
103+
<a>{JSON.stringify(item)}</a>
104104
</li>
105105
))}
106106
</ul>

0 commit comments

Comments
 (0)