@samitouri / QOS-React-2 / commits / b2230f62a3

[pipeline] Make logging more structured

--- Add types for logged events, including a `CompileSuccess` event which can help us record successfully compiled Forget functions and their compilation details (e.g. # memoSlots used).

Mofei Zhang committed Sep 14, 2023 at 19:40 UTC b2230f62a38350f19cf02b4ee4b7f42e43610b9a
3 files changed +56 -8
compiler/packages/babel-plugin-react-forget/src/Entrypoint/Options.ts
+21 -1
@@ -5,6 +5,8 @@
5 * LICENSE file in the root directory of this source tree.
6 */
7
8 +import * as t from "@babel/types";
9 +import { CompilerErrorDetailOptions } from "../CompilerError";
10 import { EnvironmentConfig } from "../HIR/Environment";
11
12 export type ExternalFunction = {
@@ -113,8 +115,26 @@ export type CompilationMode =
115 // Compile all top-level functions
116 | "all";
117
118 +export type LoggerEvent =
119 + | {
120 + kind: "CompileError";
121 + fnLoc: t.SourceLocation | null;
122 + detail: CompilerErrorDetailOptions;
123 + }
124 + | {
125 + kind: "CompileSuccess";
126 + fnLoc: t.SourceLocation | null;
127 + fnName: string | null;
128 + memoSlots: number;
129 + }
130 + | {
131 + kind: "PipelineError";
132 + fnLoc: t.SourceLocation | null;
133 + data: any;
134 + };
135 +
136 export type Logger = {
117 - logEvent(name: string, data: any): void;
137 + logEvent: (filename: string | null, event: LoggerEvent) => void;
138 };
139
140 export const defaultOptions: PluginOptions = {
compiler/packages/babel-plugin-react-forget/src/Entrypoint/Program.ts
+31 -7
@@ -50,9 +50,27 @@ function hasAnyUseNoForgetDirectives(directives: t.Directive[]): boolean {
50 }
51 return false;
52 }
53 -function handleError(pass: CompilerPass, err: unknown): void {
54 - if (pass.opts.logger && err) {
55 - pass.opts.logger.logEvent("err", err);
53 +function handleError(
54 + pass: CompilerPass,
55 + fnLoc: t.SourceLocation | null,
56 + err: unknown
57 +): void {
58 + if (pass.opts.logger) {
59 + if (err instanceof CompilerError) {
60 + for (const detail of err.details) {
61 + pass.opts.logger.logEvent(pass.filename, {
62 + kind: "CompileError",
63 + fnLoc,
64 + detail: detail.options,
65 + });
66 + }
67 + } else {
68 + pass.opts.logger.logEvent(pass.filename, {
69 + kind: "PipelineError",
70 + fnLoc,
71 + data: err,
72 + });
73 + }
74 }
75 /** Always throw if the flag is enabled, otherwise we only throw if the error is critical
76 * (eg an invariant is broken, meaning the compiler may be buggy). See
@@ -88,8 +106,14 @@ function compileAndInsertNewFunctionDeclaration(
106 let compiledFn: CodegenFunction;
107 try {
108 compiledFn = compileFn(fnPath, pass.opts.environment);
109 + pass.opts.logger?.logEvent(pass.filename, {
110 + kind: "CompileSuccess",
111 + fnLoc: fnPath.node.loc ?? null,
112 + fnName: compiledFn.id?.name ?? null,
113 + memoSlots: compiledFn.memoSlotsUsed,
114 + });
115 } catch (err) {
92 - handleError(pass, err);
116 + handleError(pass, fnPath.node.loc ?? null, err);
117 return false;
118 }
119
@@ -266,7 +290,7 @@ export function compileProgram(
290 if (!shouldVisitNode(fn, pass)) {
291 return;
292 } else if (lintError != null) {
269 - handleError(pass, lintError);
293 + handleError(pass, fn.node.loc ?? null, lintError);
294 } else {
295 const hasMutated = compileAndInsertNewFunctionDeclaration(fn, pass);
296 hasForgetMutatedOriginalSource ||= hasMutated;
@@ -280,7 +304,7 @@ export function compileProgram(
304 if (!shouldVisitNode(fn, pass)) {
305 return;
306 } else if (lintError != null) {
283 - handleError(pass, lintError);
307 + handleError(pass, fn.node.loc ?? null, lintError);
308 } else {
309 const hasMutated = compileAndInsertNewFunctionDeclaration(fn, pass);
310 hasForgetMutatedOriginalSource ||= hasMutated;
@@ -294,7 +318,7 @@ export function compileProgram(
318 if (!shouldVisitNode(fn, pass)) {
319 return;
320 } else if (lintError != null) {
297 - handleError(pass, lintError);
321 + handleError(pass, fn.node.loc ?? null, lintError);
322 } else {
323 const hasMutated = compileAndInsertNewFunctionDeclaration(fn, pass);
324 hasForgetMutatedOriginalSource ||= hasMutated;
compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/CodegenReactiveFunction.ts
+4
@@ -43,6 +43,9 @@ export type CodegenFunction = {
43 generator: boolean;
44 async: boolean;
45 loc: SourceLocation;
46 +
47 + // Compiler info for logging and heuristics
48 + memoSlotsUsed: number;
49 };
50
51 export function codegenReactiveFunction(
@@ -89,6 +92,7 @@ export function codegenReactiveFunction(
92 body,
93 generator: fn.generator,
94 async: fn.async,
95 + memoSlotsUsed: cacheCount,
96 });
97 }
98