From 209bc249b6e05c5da7a9762422beab591908e8e6 Mon Sep 17 00:00:00 2001 From: Joey Perrott Date: Wed, 2 Oct 2024 11:25:28 -0600 Subject: [PATCH] refactor(ng-dev): append logging to the log file live instead of only writing the file on exit Append logging live instead of writing to the file on exit. --- .github/local-actions/branch-manager/main.js | 26 +++++-- .github/local-actions/changelog/main.js | 26 +++++-- apps/prs/src/app/login/login.component.ts | 5 +- .../src/app/pr-table/pr-table.component.ts | 5 +- bazel/api-golden/module_mappings.ts | 5 +- bazel/map-size-tracking/size_tracker.ts | 5 +- github-actions/create-pr-for-changes/main.js | 26 +++++-- github-actions/feature-request/src/testing.ts | 5 +- github-actions/slash-commands/main.js | 26 +++++-- ng-dev/format/formatters/base-formatter.ts | 5 +- ng-dev/utils/logging.ts | 77 +++++++++++-------- 11 files changed, 143 insertions(+), 68 deletions(-) diff --git a/.github/local-actions/branch-manager/main.js b/.github/local-actions/branch-manager/main.js index fc5dfab1e..3ddedb1ff 100644 --- a/.github/local-actions/branch-manager/main.js +++ b/.github/local-actions/branch-manager/main.js @@ -18339,7 +18339,7 @@ var require_summary = __commonJS({ exports.summary = exports.markdownSummary = exports.SUMMARY_DOCS_URL = exports.SUMMARY_ENV_VAR = void 0; var os_1 = __require("os"); var fs_1 = __require("fs"); - var { access, appendFile, writeFile } = fs_1.promises; + var { access, appendFile: appendFile2, writeFile } = fs_1.promises; exports.SUMMARY_ENV_VAR = "GITHUB_STEP_SUMMARY"; exports.SUMMARY_DOCS_URL = "https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary"; var Summary = class { @@ -18375,7 +18375,7 @@ var require_summary = __commonJS({ return __awaiter(this, void 0, void 0, function* () { const overwrite = !!(options === null || options === void 0 ? void 0 : options.overwrite); const filePath = yield this.filePath(); - const writeFunc = overwrite ? writeFile : appendFile; + const writeFunc = overwrite ? writeFile : appendFile2; yield writeFunc(filePath, this._buffer, { encoding: "utf8" }); return this.emptyBuffer(); }); @@ -55959,6 +55959,8 @@ ${stderr}`); } // +import { appendFile } from "fs/promises"; +import { stripVTControlCharacters } from "util"; var LogLevel; (function(LogLevel2) { LogLevel2[LogLevel2["SILENT"] = 0] = "SILENT"; @@ -56004,7 +56006,7 @@ function runConsoleCommand(loadCommand, logLevel, ...text) { if (getLogLevel() >= logLevel) { loadCommand()(...text); } - printToLogFile(logLevel, ...text); + appendToLogFile(logLevel, ...text); } function getLogLevel() { const logLevel = Object.keys(LogLevel).indexOf((process.env[`LOG_LEVEL`] || "").toUpperCase()); @@ -56013,12 +56015,22 @@ function getLogLevel() { } return logLevel; } -var LOGGED_TEXT = ""; var LOG_LEVEL_COLUMNS = 7; -function printToLogFile(logLevel, ...text) { +var logFilePath = void 0; +function appendToLogFile(logLevel, ...text) { + if (logFilePath === void 0) { + return; + } + if (logLevel === void 0) { + appendFile(logFilePath, text.join(" ")); + return; + } const logLevelText = `${LogLevel[logLevel]}:`.padEnd(LOG_LEVEL_COLUMNS); - LOGGED_TEXT += text.join(" ").split("\n").map((l) => `${logLevelText} ${l} -`).join(""); + appendFile( + logFilePath, + stripVTControlCharacters(text.join(" ").split("\n").map((l) => `${logLevelText} ${l} +`).join("")) + ); } // diff --git a/.github/local-actions/changelog/main.js b/.github/local-actions/changelog/main.js index 08980bfe5..444f8a4c8 100644 --- a/.github/local-actions/changelog/main.js +++ b/.github/local-actions/changelog/main.js @@ -18339,7 +18339,7 @@ var require_summary = __commonJS({ exports.summary = exports.markdownSummary = exports.SUMMARY_DOCS_URL = exports.SUMMARY_ENV_VAR = void 0; var os_1 = __require("os"); var fs_1 = __require("fs"); - var { access, appendFile, writeFile } = fs_1.promises; + var { access, appendFile: appendFile2, writeFile } = fs_1.promises; exports.SUMMARY_ENV_VAR = "GITHUB_STEP_SUMMARY"; exports.SUMMARY_DOCS_URL = "https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary"; var Summary = class { @@ -18375,7 +18375,7 @@ var require_summary = __commonJS({ return __awaiter(this, void 0, void 0, function* () { const overwrite = !!(options === null || options === void 0 ? void 0 : options.overwrite); const filePath = yield this.filePath(); - const writeFunc = overwrite ? writeFile : appendFile; + const writeFunc = overwrite ? writeFile : appendFile2; yield writeFunc(filePath, this._buffer, { encoding: "utf8" }); return this.emptyBuffer(); }); @@ -55832,6 +55832,8 @@ ${stderr}`); } // +import { appendFile } from "fs/promises"; +import { stripVTControlCharacters } from "util"; var LogLevel; (function(LogLevel2) { LogLevel2[LogLevel2["SILENT"] = 0] = "SILENT"; @@ -55877,7 +55879,7 @@ function runConsoleCommand(loadCommand, logLevel, ...text) { if (getLogLevel() >= logLevel) { loadCommand()(...text); } - printToLogFile(logLevel, ...text); + appendToLogFile(logLevel, ...text); } function getLogLevel() { const logLevel = Object.keys(LogLevel).indexOf((process.env[`LOG_LEVEL`] || "").toUpperCase()); @@ -55886,12 +55888,22 @@ function getLogLevel() { } return logLevel; } -var LOGGED_TEXT = ""; var LOG_LEVEL_COLUMNS = 7; -function printToLogFile(logLevel, ...text) { +var logFilePath = void 0; +function appendToLogFile(logLevel, ...text) { + if (logFilePath === void 0) { + return; + } + if (logLevel === void 0) { + appendFile(logFilePath, text.join(" ")); + return; + } const logLevelText = `${LogLevel[logLevel]}:`.padEnd(LOG_LEVEL_COLUMNS); - LOGGED_TEXT += text.join(" ").split("\n").map((l) => `${logLevelText} ${l} -`).join(""); + appendFile( + logFilePath, + stripVTControlCharacters(text.join(" ").split("\n").map((l) => `${logLevelText} ${l} +`).join("")) + ); } // diff --git a/apps/prs/src/app/login/login.component.ts b/apps/prs/src/app/login/login.component.ts index 46725c097..7c15e83b4 100644 --- a/apps/prs/src/app/login/login.component.ts +++ b/apps/prs/src/app/login/login.component.ts @@ -8,7 +8,10 @@ import {AccountService} from '../../../../shared/account/account.service.js'; styleUrls: ['./login.component.scss'], }) export class LoginComponent { - constructor(private account: AccountService, private router: Router) {} + constructor( + private account: AccountService, + private router: Router, + ) {} signIn() { this.account.signInWithGoogle().then((signedIn) => { diff --git a/apps/prs/src/app/pr-table/pr-table.component.ts b/apps/prs/src/app/pr-table/pr-table.component.ts index 0509cba5c..9ef9635b8 100644 --- a/apps/prs/src/app/pr-table/pr-table.component.ts +++ b/apps/prs/src/app/pr-table/pr-table.component.ts @@ -30,7 +30,10 @@ export class PrTableComponent implements AfterViewInit { /** The header row definition. */ @ViewChild(MatHeaderRowDef, {static: true}) tableHeaderRow!: MatHeaderRowDef; - constructor(private injector: Injector, private vcr: ViewContainerRef) {} + constructor( + private injector: Injector, + private vcr: ViewContainerRef, + ) {} ngAfterViewInit(): void { const columns = this.columns.map((column) => { diff --git a/bazel/api-golden/module_mappings.ts b/bazel/api-golden/module_mappings.ts index c4c57e26d..020ed5bd0 100644 --- a/bazel/api-golden/module_mappings.ts +++ b/bazel/api-golden/module_mappings.ts @@ -27,9 +27,8 @@ export async function resolveTypePackages(typePackageNames: string[]): Promise<{ for (const typePackageName of typePackageNames) { const moduleNames = getModuleNamesForTypePackage(typePackageName); - const {entryPointTypeFile, resolvedPackageDir} = await resolveTypeDeclarationOfPackage( - typePackageName, - ); + const {entryPointTypeFile, resolvedPackageDir} = + await resolveTypeDeclarationOfPackage(typePackageName); typeFiles.push(entryPointTypeFile); diff --git a/bazel/map-size-tracking/size_tracker.ts b/bazel/map-size-tracking/size_tracker.ts index fff23f56c..fc7d5e554 100644 --- a/bazel/map-size-tracking/size_tracker.ts +++ b/bazel/map-size-tracking/size_tracker.ts @@ -17,7 +17,10 @@ import { } from './file_size_data.js'; export class SizeTracker { - constructor(private filePath: string, private sourceMapPath: string) {} + constructor( + private filePath: string, + private sourceMapPath: string, + ) {} /** * Computes the file size data by analyzing the input file through diff --git a/github-actions/create-pr-for-changes/main.js b/github-actions/create-pr-for-changes/main.js index f05ca968a..55eb91123 100644 --- a/github-actions/create-pr-for-changes/main.js +++ b/github-actions/create-pr-for-changes/main.js @@ -18330,7 +18330,7 @@ var require_summary = __commonJS({ exports.summary = exports.markdownSummary = exports.SUMMARY_DOCS_URL = exports.SUMMARY_ENV_VAR = void 0; var os_1 = __require("os"); var fs_1 = __require("fs"); - var { access, appendFile, writeFile } = fs_1.promises; + var { access, appendFile: appendFile2, writeFile } = fs_1.promises; exports.SUMMARY_ENV_VAR = "GITHUB_STEP_SUMMARY"; exports.SUMMARY_DOCS_URL = "https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary"; var Summary = class { @@ -18366,7 +18366,7 @@ var require_summary = __commonJS({ return __awaiter(this, void 0, void 0, function* () { const overwrite = !!(options === null || options === void 0 ? void 0 : options.overwrite); const filePath = yield this.filePath(); - const writeFunc = overwrite ? writeFile : appendFile; + const writeFunc = overwrite ? writeFile : appendFile2; yield writeFunc(filePath, this._buffer, { encoding: "utf8" }); return this.emptyBuffer(); }); @@ -40768,6 +40768,8 @@ ${stderr}`); } // +import { appendFile } from "fs/promises"; +import { stripVTControlCharacters } from "util"; var LogLevel; (function(LogLevel2) { LogLevel2[LogLevel2["SILENT"] = 0] = "SILENT"; @@ -40813,7 +40815,7 @@ function runConsoleCommand(loadCommand, logLevel, ...text) { if (getLogLevel() >= logLevel) { loadCommand()(...text); } - printToLogFile(logLevel, ...text); + appendToLogFile(logLevel, ...text); } function getLogLevel() { const logLevel = Object.keys(LogLevel).indexOf((process.env[`LOG_LEVEL`] || "").toUpperCase()); @@ -40822,12 +40824,22 @@ function getLogLevel() { } return logLevel; } -var LOGGED_TEXT = ""; var LOG_LEVEL_COLUMNS = 7; -function printToLogFile(logLevel, ...text) { +var logFilePath = void 0; +function appendToLogFile(logLevel, ...text) { + if (logFilePath === void 0) { + return; + } + if (logLevel === void 0) { + appendFile(logFilePath, text.join(" ")); + return; + } const logLevelText = `${LogLevel[logLevel]}:`.padEnd(LOG_LEVEL_COLUMNS); - LOGGED_TEXT += text.join(" ").split("\n").map((l) => `${logLevelText} ${l} -`).join(""); + appendFile( + logFilePath, + stripVTControlCharacters(text.join(" ").split("\n").map((l) => `${logLevelText} ${l} +`).join("")) + ); } // diff --git a/github-actions/feature-request/src/testing.ts b/github-actions/feature-request/src/testing.ts index 3dd59a875..ea442ad5b 100644 --- a/github-actions/feature-request/src/testing.ts +++ b/github-actions/feature-request/src/testing.ts @@ -1,7 +1,10 @@ import {GitHubAPI, GitHubIssueAPI, Issue, Comment, Query, User} from './api.js'; export class APIMock implements GitHubAPI { - constructor(public issues: IssueAPIMock[], public orgMembers: OrgMembers) {} + constructor( + public issues: IssueAPIMock[], + public orgMembers: OrgMembers, + ) {} query(_: Query) { const self = this; diff --git a/github-actions/slash-commands/main.js b/github-actions/slash-commands/main.js index e1e65de4d..2916866a0 100644 --- a/github-actions/slash-commands/main.js +++ b/github-actions/slash-commands/main.js @@ -18338,7 +18338,7 @@ var require_summary = __commonJS({ exports.summary = exports.markdownSummary = exports.SUMMARY_DOCS_URL = exports.SUMMARY_ENV_VAR = void 0; var os_1 = __require("os"); var fs_1 = __require("fs"); - var { access, appendFile, writeFile } = fs_1.promises; + var { access, appendFile: appendFile2, writeFile } = fs_1.promises; exports.SUMMARY_ENV_VAR = "GITHUB_STEP_SUMMARY"; exports.SUMMARY_DOCS_URL = "https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary"; var Summary = class { @@ -18374,7 +18374,7 @@ var require_summary = __commonJS({ return __awaiter(this, void 0, void 0, function* () { const overwrite = !!(options === null || options === void 0 ? void 0 : options.overwrite); const filePath = yield this.filePath(); - const writeFunc = overwrite ? writeFile : appendFile; + const writeFunc = overwrite ? writeFile : appendFile2; yield writeFunc(filePath, this._buffer, { encoding: "utf8" }); return this.emptyBuffer(); }); @@ -52692,6 +52692,8 @@ ${stderr}`); } // +import { appendFile } from "fs/promises"; +import { stripVTControlCharacters } from "util"; var LogLevel; (function(LogLevel2) { LogLevel2[LogLevel2["SILENT"] = 0] = "SILENT"; @@ -52737,7 +52739,7 @@ function runConsoleCommand(loadCommand, logLevel, ...text) { if (getLogLevel() >= logLevel) { loadCommand()(...text); } - printToLogFile(logLevel, ...text); + appendToLogFile(logLevel, ...text); } function getLogLevel() { const logLevel = Object.keys(LogLevel).indexOf((process.env[`LOG_LEVEL`] || "").toUpperCase()); @@ -52746,12 +52748,22 @@ function getLogLevel() { } return logLevel; } -var LOGGED_TEXT = ""; var LOG_LEVEL_COLUMNS = 7; -function printToLogFile(logLevel, ...text) { +var logFilePath = void 0; +function appendToLogFile(logLevel, ...text) { + if (logFilePath === void 0) { + return; + } + if (logLevel === void 0) { + appendFile(logFilePath, text.join(" ")); + return; + } const logLevelText = `${LogLevel[logLevel]}:`.padEnd(LOG_LEVEL_COLUMNS); - LOGGED_TEXT += text.join(" ").split("\n").map((l) => `${logLevelText} ${l} -`).join(""); + appendFile( + logFilePath, + stripVTControlCharacters(text.join(" ").split("\n").map((l) => `${logLevelText} ${l} +`).join("")) + ); } // diff --git a/ng-dev/format/formatters/base-formatter.ts b/ng-dev/format/formatters/base-formatter.ts index c80c99d63..f294f9f77 100644 --- a/ng-dev/format/formatters/base-formatter.ts +++ b/ng-dev/format/formatters/base-formatter.ts @@ -50,7 +50,10 @@ export abstract class Formatter { /** The default matchers for the formatter for filtering files to be formatted. */ abstract defaultFileMatcher: string[]; - constructor(protected git: GitClient, protected config: FormatConfig) {} + constructor( + protected git: GitClient, + protected config: FormatConfig, + ) {} /** * Retrieve the command to execute the provided action, including both the binary diff --git a/ng-dev/utils/logging.ts b/ng-dev/utils/logging.ts index 6b6a79278..685a92a93 100644 --- a/ng-dev/utils/logging.ts +++ b/ng-dev/utils/logging.ts @@ -7,10 +7,12 @@ */ import chalk, {ChalkInstance} from 'chalk'; -import {writeFileSync} from 'fs'; +import {copyFileSync, writeFileSync} from 'fs'; import {join} from 'path'; import {Arguments} from 'yargs'; import {determineRepoBaseDirFromCwd} from './repo-directory.js'; +import {appendFile} from 'fs/promises'; +import {stripVTControlCharacters} from 'util'; /** * Supported levels for logging functions. Levels are mapped to @@ -98,7 +100,7 @@ function runConsoleCommand(loadCommand: () => Function, logLevel: LogLevel, ...t if (getLogLevel() >= logLevel) { loadCommand()(...text); } - printToLogFile(logLevel, ...text); + appendToLogFile(logLevel, ...text); } /** @@ -114,15 +116,16 @@ function getLogLevel(): LogLevel { return logLevel; } -/** All text to write to the log file. */ -let LOGGED_TEXT = ''; -/** Whether file logging as been enabled. */ -let FILE_LOGGING_ENABLED = false; /** * The number of columns used in the prepended log level information on each line of the logging * output file. */ const LOG_LEVEL_COLUMNS = 7; +/** + * The path to the log file being written to live. Starts as undefined before being trigger for usage by + * `captureLogOutputForCommand` which runs from yargs execution. + */ +let logFilePath: string | undefined = undefined; /** * Enable writing the logged outputs to the log file on process exit, sets initial lines from the @@ -135,49 +138,59 @@ const LOG_LEVEL_COLUMNS = 7; export async function captureLogOutputForCommand(argv: Arguments) { // TODO(josephperrott): remove this guard against running multiple times after // https://github.com/yargs/yargs/issues/2223 is fixed - if (FILE_LOGGING_ENABLED) { + if (logFilePath !== undefined) { return; } - const repoDir = determineRepoBaseDirFromCwd(); + logFilePath = join(repoDir, '.ng-dev.log'); + writeFileSync(logFilePath, ''); + /** The date time used for timestamping when the command was invoked. */ const now = new Date(); /** Header line to separate command runs in log files. */ const headerLine = Array(100).fill('#').join(''); - LOGGED_TEXT += `${headerLine}\nCommand: ${argv.$0} ${argv._.join(' ')}\nRan at: ${now}\n`; + appendToLogFile( + undefined, + `${headerLine}\nCommand: ${argv.$0} ${argv._.join(' ')}\nRan at: ${now}\n`, + ); // On process exit, write the logged output to the appropriate log files process.on('exit', (code: number) => { - LOGGED_TEXT += `${headerLine}\n`; - LOGGED_TEXT += `Command ran in ${new Date().getTime() - now.getTime()}ms\n`; - LOGGED_TEXT += `Exit Code: ${code}\n`; - /** Path to the log file location. */ - const logFilePath = join(repoDir, '.ng-dev.log'); - - // Strip ANSI escape codes from log outputs. - LOGGED_TEXT = LOGGED_TEXT.replace(/\x1B\[([0-9]{1,3}(;[0-9]{1,2})?)?[mGK]/g, ''); - - writeFileSync(logFilePath, LOGGED_TEXT); + appendToLogFile( + undefined, + `\n\nCommand ran in ${new Date().getTime() - now.getTime()}ms\nExit Code: ${code}\n`, + ); // For failure codes greater than 1, the new logged lines should be written to a specific log // file for the command run failure. - if (code > 1) { - const logFileName = `.ng-dev.err-${now.getTime()}.log`; - console.error(`Exit code: ${code}. Writing full log to ${logFileName}`); - writeFileSync(join(repoDir, logFileName), LOGGED_TEXT); + if (code > 1 && logFilePath) { + const errorLogFileName = `.ng-dev.err-${now.getTime()}.log`; + console.error(`Exit code: ${code}. Writing full log to ${errorLogFileName}`); + copyFileSync(logFilePath, join(repoDir, errorLogFileName)); } }); - - // Mark file logging as enabled to prevent the function from executing multiple times. - FILE_LOGGING_ENABLED = true; } /** Write the provided text to the log file, prepending each line with the log level. */ -function printToLogFile(logLevel: LogLevel, ...text: unknown[]) { +function appendToLogFile(logLevel: LogLevel | undefined, ...text: unknown[]) { + if (logFilePath === undefined) { + return; + } + if (logLevel === undefined) { + appendFile(logFilePath, text.join(' ')); + return; + } + const logLevelText = `${LogLevel[logLevel]}:`.padEnd(LOG_LEVEL_COLUMNS); - LOGGED_TEXT += text - .join(' ') - .split('\n') - .map((l) => `${logLevelText} ${l}\n`) - .join(''); + appendFile( + logFilePath, + // Strip ANSI escape codes from log outputs. + stripVTControlCharacters( + text + .join(' ') + .split('\n') + .map((l) => `${logLevelText} ${l}\n`) + .join(''), + ), + ); }