Add console logs to code step (#10786)

Works for local and lambda drivers

## After

![image](https://github.com/user-attachments/assets/ec082cf6-4159-4a15-99b6-243c73a13773)

![image](https://github.com/user-attachments/assets/f42e3f43-5ea4-4167-b4b5-9a17826fd224)
This commit is contained in:
martmull
2025-03-12 10:40:59 +01:00
committed by GitHub
parent 4d0450069c
commit 4036933c84
11 changed files with 189 additions and 9 deletions

View File

@ -10,6 +10,7 @@ export type ServerlessExecuteError = {
export type ServerlessExecuteResult = {
data: object | null;
duration: number;
logs: string;
status: ServerlessFunctionExecutionStatus;
error?: ServerlessExecuteError;
};

View File

@ -17,6 +17,7 @@ import {
PublishLayerVersionCommandInput,
ResourceNotFoundException,
waitUntilFunctionUpdatedV2,
LogType,
} from '@aws-sdk/client-lambda';
import { AssumeRoleCommand, STSClient } from '@aws-sdk/client-sts';
import { isDefined } from 'twenty-shared';
@ -262,6 +263,21 @@ export class LambdaDriver implements ServerlessDriver {
await lambdaBuildDirectoryManager.clean();
}
private extractLogs(logString: string): string {
const formattedLogString = Buffer.from(logString, 'base64')
.toString('utf8')
.split('\t')
.join(' ');
return formattedLogString
.replace(/^(START|END|REPORT).*\n?/gm, '')
.replace(
/^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z) [a-f0-9-]+ INFO /gm,
'$1 INFO ',
)
.trim();
}
async execute(
serverlessFunction: ServerlessFunctionEntity,
payload: object,
@ -302,6 +318,7 @@ export class LambdaDriver implements ServerlessDriver {
const params: InvokeCommandInput = {
FunctionName: serverlessFunction.id,
Payload: JSON.stringify(executorPayload),
LogType: LogType.Tail,
};
const command = new InvokeCommand(params);
@ -313,6 +330,8 @@ export class LambdaDriver implements ServerlessDriver {
? JSON.parse(result.Payload.transformToString())
: {};
const logs = result.LogResult ? this.extractLogs(result.LogResult) : '';
const duration = Date.now() - startTime;
if (result.FunctionError) {
@ -321,11 +340,13 @@ export class LambdaDriver implements ServerlessDriver {
duration,
status: ServerlessFunctionExecutionStatus.ERROR,
error: parsedResult,
logs,
};
}
return {
data: parsedResult,
logs,
duration,
status: ServerlessFunctionExecutionStatus.SUCCESS,
};

View File

@ -1,3 +1,4 @@
/* eslint-disable no-console */
import { promises as fs } from 'fs';
import { join } from 'path';
@ -129,6 +130,55 @@ export class LocalDriver implements ServerlessDriver {
}
}
const originalConsole = {
log: console.log,
error: console.error,
warn: console.warn,
info: console.info,
debug: console.debug,
};
const interceptConsole = (
callback: (type: string, message: any[]) => void,
) => {
Object.keys(originalConsole).forEach((method) => {
console[method] = (...args: any[]) => {
callback(method, args);
};
});
};
let logs = '';
interceptConsole((type, args) => {
const formattedArgs = args.map((arg) => {
if (typeof arg === 'object' && arg !== null) {
const seen = new WeakSet();
return JSON.stringify(
arg,
(key, value) => {
if (typeof value === 'object' && value !== null) {
if (seen.has(value)) {
return '[Circular]'; // Handle circular references
}
seen.add(value);
}
return value;
},
2,
);
}
return arg;
});
const formattedType = type === 'log' ? 'info' : type;
logs += `${new Date().toISOString()} ${formattedType.toUpperCase()} ${formattedArgs.join(' ')}\n`;
});
try {
const mainFile = await import(compiledCodeFilePath);
@ -141,12 +191,14 @@ export class LocalDriver implements ServerlessDriver {
return {
data: result,
logs,
duration,
status: ServerlessFunctionExecutionStatus.SUCCESS,
};
} catch (error) {
return {
data: null,
logs,
duration: Date.now() - startTime,
error: {
errorType: 'UnhandledError',
@ -156,6 +208,12 @@ export class LocalDriver implements ServerlessDriver {
status: ServerlessFunctionExecutionStatus.ERROR,
};
} finally {
// Restoring originalConsole
Object.keys(originalConsole).forEach((method) => {
console[method] = (...args: any[]) => {
originalConsole[method](...args);
};
});
await fs.rm(compiledCodeFolderPath, { recursive: true, force: true });
}
}