-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathlogger.ts
94 lines (83 loc) · 2.73 KB
/
logger.ts
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
const LOG_LEVELS = ["DEBUG", "INFO", "SUBMIT", "WARN", "ERROR"] as const;
export type LogLevel = (typeof LOG_LEVELS)[number];
type ChatLogEntry = {
timestamp: number;
workflowRunId: string;
logLevel: LogLevel;
eventType:
| "ENDPOINT_START" // when the endpoint is called
| "SUBMIT_THIRD_PARTY_RESULT" // third party call result
| "CREATE_CONTEXT" // isFirstInvocation, workflowRunId, headers, url and initialPayload and steps (steps only in DEBUG)
| "SUBMIT_FIRST_INVOCATION" // if triggerFirstInvocation is called
| "RUN_SINGLE"
| "RUN_PARALLEL"
| "SUBMIT_STEP"
| "SUBMIT_CLEANUP" // cleanup when a workflow ends
| "RESPONSE_WORKFLOW" // when onStepFinish is called with workflowRunId
| "RESPONSE_DEFAULT" // when onStepFinish("no-workflow-id") is called
| "ERROR"; // when onStepFinish("no-workflow-id") is called
details: unknown;
};
export type WorkflowLoggerOptions = {
logLevel: LogLevel;
logOutput: "console";
};
export class WorkflowLogger {
private logs: ChatLogEntry[] = [];
private options: WorkflowLoggerOptions;
private workflowRunId?: string = undefined;
constructor(options: WorkflowLoggerOptions) {
this.options = options;
}
public async log(
level: LogLevel,
eventType: ChatLogEntry["eventType"],
details?: unknown
): Promise<void> {
if (this.shouldLog(level)) {
const timestamp = Date.now();
const logEntry: ChatLogEntry = {
timestamp,
workflowRunId: this.workflowRunId ?? "",
logLevel: level,
eventType,
details,
};
this.logs.push(logEntry);
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (this.options.logOutput === "console") {
this.writeToConsole(logEntry);
}
// Introduce a small delay to make the sequence more visible
await new Promise((resolve) => setTimeout(resolve, 100));
}
}
public setWorkflowRunId(workflowRunId: string) {
this.workflowRunId = workflowRunId;
}
private writeToConsole(logEntry: ChatLogEntry): void {
const JSON_SPACING = 2;
const logMethod =
logEntry.logLevel === "ERROR"
? console.error
: logEntry.logLevel === "WARN"
? console.warn
: console.log;
logMethod(JSON.stringify(logEntry, undefined, JSON_SPACING));
}
private shouldLog(level: LogLevel): boolean {
return LOG_LEVELS.indexOf(level) >= LOG_LEVELS.indexOf(this.options.logLevel);
}
public static getLogger(verbose?: boolean | WorkflowLogger) {
if (typeof verbose === "object") {
return verbose;
} else {
return verbose
? new WorkflowLogger({
logLevel: "INFO",
logOutput: "console",
})
: undefined;
}
}
}