@lage-run/reporters 1.6.0 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/AdoReporter.d.ts +3 -0
- package/lib/AdoReporter.js +1 -1
- package/lib/AdoReporter.js.map +1 -1
- package/lib/BasicReporter.d.ts +12 -1
- package/lib/BasicReporter.js +33 -28
- package/lib/BasicReporter.js.map +1 -1
- package/lib/ChromeTraceEventsReporter.d.ts +3 -0
- package/lib/ChromeTraceEventsReporter.js +4 -5
- package/lib/ChromeTraceEventsReporter.js.map +1 -1
- package/lib/GithubActionsReporter.d.ts +3 -0
- package/lib/GithubActionsReporter.js +1 -1
- package/lib/GithubActionsReporter.js.map +1 -1
- package/lib/GroupedReporter.d.ts +5 -10
- package/lib/GroupedReporter.js +45 -70
- package/lib/GroupedReporter.js.map +1 -1
- package/lib/JsonReporter.d.ts +4 -1
- package/lib/JsonReporter.js.map +1 -1
- package/lib/LogReporter.d.ts +22 -3
- package/lib/LogReporter.js +67 -85
- package/lib/LogReporter.js.map +1 -1
- package/lib/ProgressReporter.d.ts +21 -4
- package/lib/ProgressReporter.js +105 -123
- package/lib/ProgressReporter.js.map +1 -1
- package/lib/VerboseFileLogReporter.d.ts +3 -1
- package/lib/VerboseFileLogReporter.js +21 -24
- package/lib/VerboseFileLogReporter.js.map +1 -1
- package/lib/formatDuration.d.ts +4 -0
- package/lib/formatDuration.js +13 -1
- package/lib/formatDuration.js.map +1 -1
- package/lib/formatHelpers.d.ts +13 -0
- package/lib/formatHelpers.js +68 -0
- package/lib/formatHelpers.js.map +1 -0
- package/lib/index.d.ts +1 -1
- package/lib/index.js +17 -0
- package/lib/index.js.map +1 -1
- package/package.json +7 -9
- package/lib/formatBytes.d.ts +0 -1
- package/lib/formatBytes.js +0 -13
- package/lib/formatBytes.js.map +0 -1
- package/lib/gradient.d.ts +0 -6
- package/lib/gradient.js +0 -18
- package/lib/gradient.js.map +0 -1
- package/lib/types/progressBarTypes.d.ts +0 -12
- package/lib/types/progressBarTypes.js +0 -4
- package/lib/types/progressBarTypes.js.map +0 -1
package/lib/AdoReporter.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { TargetRun } from "@lage-run/scheduler-types";
|
|
2
2
|
import { GroupedReporter } from "./GroupedReporter.js";
|
|
3
|
+
/**
|
|
4
|
+
* Reporter that formats logs for Azure DevOps, optionally with grouping.
|
|
5
|
+
*/
|
|
3
6
|
export declare class AdoReporter extends GroupedReporter {
|
|
4
7
|
protected formatGroupStart(packageName: string, task: string, status: string, duration?: [number, number]): string;
|
|
5
8
|
protected formatGroupEnd(): string;
|
package/lib/AdoReporter.js
CHANGED
|
@@ -18,7 +18,7 @@ function _interop_require_default(obj) {
|
|
|
18
18
|
}
|
|
19
19
|
class AdoReporter extends _GroupedReporter.GroupedReporter {
|
|
20
20
|
formatGroupStart(packageName, task, status, duration) {
|
|
21
|
-
return `##[group] ${_GroupedReporter.colors.pkg(packageName)} ${_GroupedReporter.colors.task(task)} ${status}${duration ? `, took ${(0, _formatDuration.
|
|
21
|
+
return `##[group] ${_GroupedReporter.colors.pkg(packageName)} ${_GroupedReporter.colors.task(task)} ${status}${duration ? `, took ${(0, _formatDuration.formatHrtime)(duration)}` : ""}\n`;
|
|
22
22
|
}
|
|
23
23
|
formatGroupEnd() {
|
|
24
24
|
return `##[endgroup]\n`;
|
package/lib/AdoReporter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/AdoReporter.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"sources":["../src/AdoReporter.ts"],"sourcesContent":["import { formatHrtime } from \"./formatDuration.js\";\nimport chalk from \"chalk\";\nimport type { TargetRun } from \"@lage-run/scheduler-types\";\nimport { colors, GroupedReporter } from \"./GroupedReporter.js\";\n\n/**\n * Reporter that formats logs for Azure DevOps, optionally with grouping.\n */\nexport class AdoReporter extends GroupedReporter {\n protected formatGroupStart(packageName: string, task: string, status: string, duration?: [number, number]): string {\n return `##[group] ${colors.pkg(packageName)} ${colors.task(task)} ${status}${duration ? `, took ${formatHrtime(duration)}` : \"\"}\\n`;\n }\n\n protected formatGroupEnd(): string {\n return `##[endgroup]\\n`;\n }\n\n protected writeSummaryHeader(): void {\n this.logStream.write(chalk.cyanBright(`##[section]Summary\\n`));\n }\n\n protected writeSummaryFooter(): void {\n // ADO sections have no closing marker\n }\n\n protected writeFailures(failed: string[], targetRuns: Map<string, TargetRun<unknown>>): void {\n let packagesMessage = `##vso[task.logissue type=error]Your build failed on the following packages => `;\n\n for (const targetId of failed) {\n const target = targetRuns.get(targetId)?.target;\n\n if (target) {\n const { packageName, task } = target;\n const taskLogs = this.logEntries.get(targetId);\n\n packagesMessage += `[${packageName} ${task}], `;\n\n this.logStream.write(`##[error] [${chalk.magenta(packageName)} ${chalk.cyan(task)}] ${chalk.redBright(\"ERROR DETECTED\")}\\n`);\n\n if (taskLogs) {\n for (const entry of taskLogs) {\n // Log each entry separately to prevent truncation\n this.logStream.write(`##[error] ${entry.msg}\\n`);\n }\n }\n }\n }\n\n packagesMessage += \"find the error logs above with the prefix '##[error]!'\\n\";\n this.logStream.write(packagesMessage);\n }\n}\n"],"names":["AdoReporter","GroupedReporter","formatGroupStart","packageName","task","status","duration","colors","pkg","formatHrtime","formatGroupEnd","writeSummaryHeader","logStream","write","chalk","cyanBright","writeSummaryFooter","writeFailures","failed","targetRuns","packagesMessage","targetId","target","get","taskLogs","logEntries","magenta","cyan","redBright","entry","msg"],"mappings":";;;;+BAQaA;;;eAAAA;;;gCARgB;8DACX;iCAEsB;;;;;;AAKjC,MAAMA,oBAAoBC,gCAAe;IACpCC,iBAAiBC,WAAmB,EAAEC,IAAY,EAAEC,MAAc,EAAEC,QAA2B,EAAU;QACjH,OAAO,CAAC,UAAU,EAAEC,uBAAM,CAACC,GAAG,CAACL,aAAa,CAAC,EAAEI,uBAAM,CAACH,IAAI,CAACA,MAAM,CAAC,EAAEC,SAASC,WAAW,CAAC,OAAO,EAAEG,IAAAA,4BAAY,EAACH,WAAW,GAAG,GAAG,EAAE,CAAC;IACrI;IAEUI,iBAAyB;QACjC,OAAO,CAAC,cAAc,CAAC;IACzB;IAEUC,qBAA2B;QACnC,IAAI,CAACC,SAAS,CAACC,KAAK,CAACC,cAAK,CAACC,UAAU,CAAC,CAAC,oBAAoB,CAAC;IAC9D;IAEUC,qBAA2B;IACnC,sCAAsC;IACxC;IAEUC,cAAcC,MAAgB,EAAEC,UAA2C,EAAQ;QAC3F,IAAIC,kBAAkB,CAAC,8EAA8E,CAAC;QAEtG,KAAK,MAAMC,YAAYH,OAAQ;YAC7B,MAAMI,SAASH,WAAWI,GAAG,CAACF,WAAWC;YAEzC,IAAIA,QAAQ;gBACV,MAAM,EAAEnB,WAAW,EAAEC,IAAI,EAAE,GAAGkB;gBAC9B,MAAME,WAAW,IAAI,CAACC,UAAU,CAACF,GAAG,CAACF;gBAErCD,mBAAmB,CAAC,CAAC,EAAEjB,YAAY,CAAC,EAAEC,KAAK,GAAG,CAAC;gBAE/C,IAAI,CAACQ,SAAS,CAACC,KAAK,CAAC,CAAC,WAAW,EAAEC,cAAK,CAACY,OAAO,CAACvB,aAAa,CAAC,EAAEW,cAAK,CAACa,IAAI,CAACvB,MAAM,EAAE,EAAEU,cAAK,CAACc,SAAS,CAAC,kBAAkB,EAAE,CAAC;gBAE3H,IAAIJ,UAAU;oBACZ,KAAK,MAAMK,SAASL,SAAU;wBAC5B,kDAAkD;wBAClD,IAAI,CAACZ,SAAS,CAACC,KAAK,CAAC,CAAC,UAAU,EAAEgB,MAAMC,GAAG,CAAC,EAAE,CAAC;oBACjD;gBACF;YACF;QACF;QAEAV,mBAAmB;QACnB,IAAI,CAACR,SAAS,CAACC,KAAK,CAACO;IACvB;AACF"}
|
package/lib/BasicReporter.d.ts
CHANGED
|
@@ -1,19 +1,30 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { LogEntry, Reporter } from "@lage-run/logger";
|
|
2
2
|
import type { SchedulerRunSummary } from "@lage-run/scheduler-types";
|
|
3
|
+
import type { Writable } from "stream";
|
|
4
|
+
/**
|
|
5
|
+
* Shows running/remaining target counts and completed targets, but does not display
|
|
6
|
+
* the names of running targets for efficiency.
|
|
7
|
+
*/
|
|
3
8
|
export declare class BasicReporter implements Reporter {
|
|
4
9
|
private taskData;
|
|
5
10
|
private updateTimer;
|
|
6
11
|
private startTimer;
|
|
7
12
|
private logMemory;
|
|
13
|
+
private logStream;
|
|
8
14
|
constructor(params?: {
|
|
9
15
|
concurrency?: number;
|
|
10
16
|
version?: string;
|
|
11
17
|
frequency?: number;
|
|
12
18
|
/** Whether to capture and report main process memory usage on target completion */
|
|
13
19
|
logMemory?: boolean;
|
|
20
|
+
/** Stream for output (defaults to process.stdout) */
|
|
21
|
+
logStream?: Writable;
|
|
14
22
|
});
|
|
15
23
|
log(entry: LogEntry): void;
|
|
16
24
|
summarize(schedulerRunSummary: SchedulerRunSummary): void;
|
|
25
|
+
/** Clear the update timer */
|
|
26
|
+
cleanup(): void;
|
|
17
27
|
private reportCompletion;
|
|
18
28
|
private renderStatus;
|
|
29
|
+
private print;
|
|
19
30
|
}
|
package/lib/BasicReporter.js
CHANGED
|
@@ -9,9 +9,8 @@ Object.defineProperty(exports, "BasicReporter", {
|
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
11
|
const _chalk = /*#__PURE__*/ _interop_require_default(require("chalk"));
|
|
12
|
-
const _gradient = require("./gradient.js");
|
|
13
12
|
const _formatDuration = require("./formatDuration.js");
|
|
14
|
-
const
|
|
13
|
+
const _formatHelpers = require("./formatHelpers.js");
|
|
15
14
|
function _define_property(obj, key, value) {
|
|
16
15
|
if (key in obj) {
|
|
17
16
|
Object.defineProperty(obj, key, {
|
|
@@ -52,7 +51,6 @@ const colors = {
|
|
|
52
51
|
task: _chalk.default.hex("#00DDDD"),
|
|
53
52
|
pkg: _chalk.default.hex("#FFD66B")
|
|
54
53
|
};
|
|
55
|
-
const hrLine = "┈".repeat(80);
|
|
56
54
|
const icons = {
|
|
57
55
|
success: "✓",
|
|
58
56
|
failed: "✗",
|
|
@@ -64,12 +62,6 @@ const terminal = {
|
|
|
64
62
|
showCursor: "\x1b[?25h",
|
|
65
63
|
clearLine: "\x1b[2K\r"
|
|
66
64
|
};
|
|
67
|
-
const fancy = (str)=>(0, _gradient.gradient)({
|
|
68
|
-
r: 237,
|
|
69
|
-
g: 178,
|
|
70
|
-
b: 77
|
|
71
|
-
}, "cyan")(str);
|
|
72
|
-
const print = (message)=>process.stdout.write(message + "\n");
|
|
73
65
|
class BasicReporter {
|
|
74
66
|
log(entry) {
|
|
75
67
|
const data = entry.data;
|
|
@@ -99,43 +91,47 @@ class BasicReporter {
|
|
|
99
91
|
}
|
|
100
92
|
summarize(schedulerRunSummary) {
|
|
101
93
|
clearInterval(this.updateTimer);
|
|
102
|
-
|
|
94
|
+
this.logStream.write(terminal.clearLine);
|
|
103
95
|
const { targetRuns, targetRunByStatus, duration } = schedulerRunSummary;
|
|
104
96
|
const { failed, aborted, skipped, success, pending } = targetRunByStatus;
|
|
105
97
|
if (targetRuns.size > 0) {
|
|
106
|
-
print(colors.summary(`\nSummary`));
|
|
107
|
-
print(hrLine);
|
|
108
|
-
print(`success: ${success.length}, skipped: ${skipped.length}, pending: ${pending.length}, aborted: ${aborted.length}, failed: ${failed.length}`);
|
|
109
|
-
print(`worker restarts: ${schedulerRunSummary.workerRestarts}, max worker memory usage: ${(0,
|
|
98
|
+
this.print(colors.summary(`\nSummary`));
|
|
99
|
+
this.print(_formatHelpers.hrLine);
|
|
100
|
+
this.print(`success: ${success.length}, skipped: ${skipped.length}, pending: ${pending.length}, aborted: ${aborted.length}, failed: ${failed.length}`);
|
|
101
|
+
this.print(`worker restarts: ${schedulerRunSummary.workerRestarts}, max worker memory usage: ${(0, _formatHelpers.formatBytes)(schedulerRunSummary.maxWorkerMemoryUsage)}`);
|
|
110
102
|
} else {
|
|
111
|
-
print("Nothing has been run.");
|
|
103
|
+
this.print("Nothing has been run.");
|
|
112
104
|
}
|
|
113
|
-
print(hrLine);
|
|
105
|
+
this.print(_formatHelpers.hrLine);
|
|
114
106
|
for (const targetId of failed){
|
|
115
107
|
const target = targetRuns.get(targetId)?.target;
|
|
116
108
|
if (target) {
|
|
117
109
|
const failureLogs = this.taskData.get(targetId)?.logEntries;
|
|
118
|
-
print(`[${colors.pkg(target.packageName ?? "<root>")} ${colors.task(target.task)}] ${colors.failed("ERROR DETECTED")}`);
|
|
110
|
+
this.print(`[${colors.pkg(target.packageName ?? "<root>")} ${colors.task(target.task)}] ${colors.failed("ERROR DETECTED")}`);
|
|
119
111
|
if (failureLogs) {
|
|
120
112
|
for (const entry of failureLogs){
|
|
121
|
-
print(entry.msg);
|
|
113
|
+
this.print(entry.msg);
|
|
122
114
|
}
|
|
123
115
|
}
|
|
124
|
-
print(hrLine);
|
|
116
|
+
this.print(_formatHelpers.hrLine);
|
|
125
117
|
}
|
|
126
118
|
}
|
|
127
119
|
const allCacheHits = [
|
|
128
120
|
...targetRuns.values()
|
|
129
121
|
].filter((run)=>!run.target.hidden).length === skipped.length;
|
|
130
|
-
const allCacheHitText = allCacheHits ?
|
|
131
|
-
print(`Took a total of ${(0, _formatDuration.
|
|
122
|
+
const allCacheHitText = allCacheHits ? (0, _formatHelpers.fancyGradient)(`All targets skipped!`) : "";
|
|
123
|
+
this.print(`Took a total of ${(0, _formatDuration.formatHrtime)(duration)} to complete. ${allCacheHitText}`);
|
|
124
|
+
}
|
|
125
|
+
/** Clear the update timer */ cleanup() {
|
|
126
|
+
clearInterval(this.updateTimer);
|
|
127
|
+
this.updateTimer = undefined;
|
|
132
128
|
}
|
|
133
129
|
reportCompletion(completion) {
|
|
134
130
|
const icon = icons[completion.status];
|
|
135
131
|
const statusColor = colors[completion.status];
|
|
136
|
-
const durationText = completion.duration ? ` (${(0, _formatDuration.
|
|
137
|
-
const memText =
|
|
138
|
-
const message = `${statusColor(`${icon} ${completion.status.padEnd(8)}`)} ${colors.label(completion.target.label)}${colors.duration(durationText
|
|
132
|
+
const durationText = completion.duration ? ` (${(0, _formatDuration.formatHrtime)(completion.duration)})` : "";
|
|
133
|
+
const memText = (0, _formatHelpers.formatMemoryUsage)(completion.memoryUsage, this.logMemory);
|
|
134
|
+
const message = `${statusColor(`${icon} ${completion.status.padEnd(8)}`)} ${colors.label(completion.target.label)}${colors.duration(durationText + memText)}`;
|
|
139
135
|
this.renderStatus(message);
|
|
140
136
|
}
|
|
141
137
|
renderStatus(completedTaskMessage) {
|
|
@@ -158,22 +154,31 @@ class BasicReporter {
|
|
|
158
154
|
}
|
|
159
155
|
const percentage = Math.round(completed / total * 100);
|
|
160
156
|
output += `${timestamp} Completed: ${completed}/${total} (${percentage}%) [${running} running, ${pending} pending]`;
|
|
161
|
-
|
|
157
|
+
this.logStream.write(output);
|
|
158
|
+
}
|
|
159
|
+
print(message) {
|
|
160
|
+
this.logStream.write(message + "\n");
|
|
162
161
|
}
|
|
163
162
|
constructor(params = {}){
|
|
164
163
|
_define_property(this, "taskData", new Map());
|
|
165
164
|
_define_property(this, "updateTimer", void 0);
|
|
166
165
|
_define_property(this, "startTimer", void 0);
|
|
167
166
|
_define_property(this, "logMemory", void 0);
|
|
167
|
+
_define_property(this, "logStream", void 0);
|
|
168
168
|
const { concurrency = 0, version = "0.0.0", frequency = 500 } = params;
|
|
169
169
|
this.logMemory = !!params.logMemory;
|
|
170
|
-
|
|
170
|
+
this.logStream = params.logStream || process.stdout;
|
|
171
|
+
this.print(`${(0, _formatHelpers.fancyGradient)("lage")} - Version ${version} - ${concurrency} Workers`);
|
|
171
172
|
this.startTimer = ()=>{
|
|
172
173
|
this.updateTimer = setInterval(()=>this.renderStatus(), frequency);
|
|
173
174
|
this.updateTimer.unref();
|
|
174
175
|
this.startTimer = ()=>{};
|
|
175
176
|
};
|
|
176
|
-
|
|
177
|
-
|
|
177
|
+
if (!params.logStream) {
|
|
178
|
+
// Only hide and show the cursor if writing to the default stdout
|
|
179
|
+
// (definitely don't want the exit handler if writing to a custom stream)
|
|
180
|
+
process.stdout.write(terminal.hideCursor);
|
|
181
|
+
process.on("exit", ()=>process.stdout.write(terminal.showCursor));
|
|
182
|
+
}
|
|
178
183
|
}
|
|
179
184
|
}
|
package/lib/BasicReporter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/BasicReporter.ts"],"sourcesContent":["import { type LogEntry, type Reporter } from \"@lage-run/logger\";\nimport type { SchedulerRunSummary, TargetStatus } from \"@lage-run/scheduler-types\";\nimport type { Target } from \"@lage-run/target-graph\";\nimport chalk from \"chalk\";\nimport { gradient } from \"./gradient.js\";\nimport { formatDuration, hrToSeconds } from \"./formatDuration.js\";\nimport { formatBytes } from \"./formatBytes.js\";\n\ntype CoarseStatus = \"completed\" | \"running\" | \"pending\";\n\nconst coarseStatus: Record<TargetStatus, CoarseStatus> = {\n success: \"completed\",\n failed: \"completed\",\n skipped: \"completed\",\n aborted: \"completed\",\n running: \"running\",\n pending: \"pending\",\n queued: \"pending\",\n};\n\ntype CompletionStatus = \"success\" | \"failed\" | \"skipped\" | \"aborted\";\nconst isCompletionStatus = (status: TargetStatus): status is CompletionStatus => coarseStatus[status] === \"completed\";\n\nconst colors = {\n label: chalk.white,\n timestamp: chalk.gray,\n duration: chalk.gray,\n success: chalk.green,\n failed: chalk.red,\n skipped: chalk.gray,\n aborted: chalk.yellow,\n summary: chalk.cyanBright,\n task: chalk.hex(\"#00DDDD\"),\n pkg: chalk.hex(\"#FFD66B\"),\n};\n\nconst hrLine = \"┈\".repeat(80);\n\nconst icons: Record<CompletionStatus, string> = {\n success: \"✓\",\n failed: \"✗\",\n skipped: \"-\",\n aborted: \"-\",\n};\n\nconst terminal = {\n hideCursor: \"\\x1b[?25l\",\n showCursor: \"\\x1b[?25h\",\n clearLine: \"\\x1b[2K\\r\",\n};\n\nconst fancy = (str: string) => gradient({ r: 237, g: 178, b: 77 }, \"cyan\")(str);\nconst print = (message: string) => process.stdout.write(message + \"\\n\");\n\nexport class BasicReporter implements Reporter {\n private taskData = new Map<string, { target: Target; status: TargetStatus; logEntries: LogEntry[] }>();\n private updateTimer: NodeJS.Timeout | undefined;\n private startTimer: () => void;\n private logMemory: boolean;\n\n constructor(\n params: {\n concurrency?: number;\n version?: string;\n frequency?: number;\n /** Whether to capture and report main process memory usage on target completion */\n logMemory?: boolean;\n } = {}\n ) {\n const { concurrency = 0, version = \"0.0.0\", frequency = 500 } = params;\n this.logMemory = !!params.logMemory;\n print(`${fancy(\"lage\")} - Version ${version} - ${concurrency} Workers`);\n\n this.startTimer = () => {\n this.updateTimer = setInterval(() => this.renderStatus(), frequency);\n this.updateTimer.unref();\n this.startTimer = () => {};\n };\n\n process.stdout.write(terminal.hideCursor);\n process.on(\"exit\", () => process.stdout.write(terminal.showCursor));\n }\n\n public log(entry: LogEntry): void {\n const data = entry.data;\n if (!data?.target || data.target.hidden) return;\n\n let taskData = this.taskData.get(data.target.id);\n if (!taskData) {\n taskData = { target: data.target, status: \"pending\", logEntries: [] };\n this.taskData.set(data.target.id, taskData);\n }\n\n this.startTimer();\n taskData.logEntries.push(entry);\n\n if (data.status) {\n taskData.status = data.status;\n if (isCompletionStatus(data.status)) {\n this.reportCompletion({ target: data.target, status: data.status, duration: data.duration, memoryUsage: data.memoryUsage });\n }\n }\n }\n\n public summarize(schedulerRunSummary: SchedulerRunSummary): void {\n clearInterval(this.updateTimer);\n process.stdout.write(terminal.clearLine);\n\n const { targetRuns, targetRunByStatus, duration } = schedulerRunSummary;\n const { failed, aborted, skipped, success, pending } = targetRunByStatus;\n\n if (targetRuns.size > 0) {\n print(colors.summary(`\\nSummary`));\n print(hrLine);\n print(\n `success: ${success.length}, skipped: ${skipped.length}, pending: ${pending.length}, aborted: ${aborted.length}, failed: ${failed.length}`\n );\n print(\n `worker restarts: ${schedulerRunSummary.workerRestarts}, max worker memory usage: ${formatBytes(schedulerRunSummary.maxWorkerMemoryUsage)}`\n );\n } else {\n print(\"Nothing has been run.\");\n }\n\n print(hrLine);\n\n for (const targetId of failed) {\n const target = targetRuns.get(targetId)?.target;\n if (target) {\n const failureLogs = this.taskData.get(targetId)?.logEntries;\n\n print(`[${colors.pkg(target.packageName ?? \"<root>\")} ${colors.task(target.task)}] ${colors.failed(\"ERROR DETECTED\")}`);\n\n if (failureLogs) {\n for (const entry of failureLogs) {\n print(entry.msg);\n }\n }\n print(hrLine);\n }\n }\n\n const allCacheHits = [...targetRuns.values()].filter((run) => !run.target.hidden).length === skipped.length;\n const allCacheHitText = allCacheHits ? fancy(`All targets skipped!`) : \"\";\n\n print(`Took a total of ${formatDuration(hrToSeconds(duration))} to complete. ${allCacheHitText}`);\n }\n\n private reportCompletion(completion: {\n target: Target;\n status: CompletionStatus;\n duration?: [number, number];\n memoryUsage?: NodeJS.MemoryUsage;\n }) {\n const icon = icons[completion.status];\n const statusColor = colors[completion.status];\n const durationText = completion.duration ? ` (${formatDuration(hrToSeconds(completion.duration))})` : \"\";\n const memText =\n this.logMemory && completion.memoryUsage\n ? ` [rss: ${formatBytes(completion.memoryUsage.rss)}, heap: ${formatBytes(completion.memoryUsage.heapUsed)}]`\n : \"\";\n\n const message = `${statusColor(`${icon} ${completion.status.padEnd(8)}`)} ${colors.label(completion.target.label)}${colors.duration(durationText)}${colors.duration(memText)}`;\n this.renderStatus(message);\n }\n\n private renderStatus(completedTaskMessage?: string) {\n const counts: Record<CoarseStatus, number> = { completed: 0, running: 0, pending: 0 };\n for (const data of this.taskData.values()) {\n counts[coarseStatus[data.status]]++;\n }\n const { completed, running, pending } = counts;\n const total = this.taskData.size;\n const timestamp = colors.timestamp(`[${new Date().toLocaleTimeString(\"en-US\", { hour12: false })}]`);\n\n let output = terminal.clearLine;\n if (completedTaskMessage) {\n output += `${timestamp} ${completedTaskMessage}\\n`;\n }\n const percentage = Math.round((completed / total) * 100);\n output += `${timestamp} Completed: ${completed}/${total} (${percentage}%) [${running} running, ${pending} pending]`;\n process.stdout.write(output);\n }\n}\n"],"names":["BasicReporter","coarseStatus","success","failed","skipped","aborted","running","pending","queued","isCompletionStatus","status","colors","label","chalk","white","timestamp","gray","duration","green","red","yellow","summary","cyanBright","task","hex","pkg","hrLine","repeat","icons","terminal","hideCursor","showCursor","clearLine","fancy","str","gradient","r","g","b","print","message","process","stdout","write","log","entry","data","target","hidden","taskData","get","id","logEntries","set","startTimer","push","reportCompletion","memoryUsage","summarize","schedulerRunSummary","clearInterval","updateTimer","targetRuns","targetRunByStatus","size","length","workerRestarts","formatBytes","maxWorkerMemoryUsage","targetId","failureLogs","packageName","msg","allCacheHits","values","filter","run","allCacheHitText","formatDuration","hrToSeconds","completion","icon","statusColor","durationText","memText","logMemory","rss","heapUsed","padEnd","renderStatus","completedTaskMessage","counts","completed","total","Date","toLocaleTimeString","hour12","output","percentage","Math","round","params","Map","concurrency","version","frequency","setInterval","unref","on"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/BasicReporter.ts"],"sourcesContent":["import type { LogEntry, Reporter } from \"@lage-run/logger\";\nimport type { SchedulerRunSummary, TargetStatus } from \"@lage-run/scheduler-types\";\nimport type { Target } from \"@lage-run/target-graph\";\nimport type { Writable } from \"stream\";\nimport chalk from \"chalk\";\nimport { formatHrtime } from \"./formatDuration.js\";\nimport { fancyGradient, formatBytes, formatMemoryUsage, hrLine } from \"./formatHelpers.js\";\n\ntype CoarseStatus = \"completed\" | \"running\" | \"pending\";\n\nconst coarseStatus: Record<TargetStatus, CoarseStatus> = {\n success: \"completed\",\n failed: \"completed\",\n skipped: \"completed\",\n aborted: \"completed\",\n running: \"running\",\n pending: \"pending\",\n queued: \"pending\",\n};\n\ntype CompletionStatus = \"success\" | \"failed\" | \"skipped\" | \"aborted\";\nconst isCompletionStatus = (status: TargetStatus): status is CompletionStatus => coarseStatus[status] === \"completed\";\n\nconst colors = {\n label: chalk.white,\n timestamp: chalk.gray,\n duration: chalk.gray,\n success: chalk.green,\n failed: chalk.red,\n skipped: chalk.gray,\n aborted: chalk.yellow,\n summary: chalk.cyanBright,\n task: chalk.hex(\"#00DDDD\"),\n pkg: chalk.hex(\"#FFD66B\"),\n};\n\nconst icons: Record<CompletionStatus, string> = {\n success: \"✓\",\n failed: \"✗\",\n skipped: \"-\",\n aborted: \"-\",\n};\n\nconst terminal = {\n hideCursor: \"\\x1b[?25l\",\n showCursor: \"\\x1b[?25h\",\n clearLine: \"\\x1b[2K\\r\",\n};\n\n/**\n * Shows running/remaining target counts and completed targets, but does not display\n * the names of running targets for efficiency.\n */\nexport class BasicReporter implements Reporter {\n private taskData = new Map<string, { target: Target; status: TargetStatus; logEntries: LogEntry[] }>();\n private updateTimer: NodeJS.Timeout | undefined;\n private startTimer: () => void;\n private logMemory: boolean;\n private logStream: Writable;\n\n constructor(\n params: {\n concurrency?: number;\n version?: string;\n frequency?: number;\n /** Whether to capture and report main process memory usage on target completion */\n logMemory?: boolean;\n /** Stream for output (defaults to process.stdout) */\n logStream?: Writable;\n } = {}\n ) {\n const { concurrency = 0, version = \"0.0.0\", frequency = 500 } = params;\n this.logMemory = !!params.logMemory;\n this.logStream = params.logStream || process.stdout;\n this.print(`${fancyGradient(\"lage\")} - Version ${version} - ${concurrency} Workers`);\n\n this.startTimer = () => {\n this.updateTimer = setInterval(() => this.renderStatus(), frequency);\n this.updateTimer.unref();\n this.startTimer = () => {};\n };\n\n if (!params.logStream) {\n // Only hide and show the cursor if writing to the default stdout\n // (definitely don't want the exit handler if writing to a custom stream)\n process.stdout.write(terminal.hideCursor);\n process.on(\"exit\", () => process.stdout.write(terminal.showCursor));\n }\n }\n\n public log(entry: LogEntry): void {\n const data = entry.data;\n if (!data?.target || data.target.hidden) return;\n\n let taskData = this.taskData.get(data.target.id);\n if (!taskData) {\n taskData = { target: data.target, status: \"pending\", logEntries: [] };\n this.taskData.set(data.target.id, taskData);\n }\n\n this.startTimer();\n taskData.logEntries.push(entry);\n\n if (data.status) {\n taskData.status = data.status;\n if (isCompletionStatus(data.status)) {\n this.reportCompletion({ target: data.target, status: data.status, duration: data.duration, memoryUsage: data.memoryUsage });\n }\n }\n }\n\n public summarize(schedulerRunSummary: SchedulerRunSummary): void {\n clearInterval(this.updateTimer);\n this.logStream.write(terminal.clearLine);\n\n const { targetRuns, targetRunByStatus, duration } = schedulerRunSummary;\n const { failed, aborted, skipped, success, pending } = targetRunByStatus;\n\n if (targetRuns.size > 0) {\n this.print(colors.summary(`\\nSummary`));\n this.print(hrLine);\n this.print(\n `success: ${success.length}, skipped: ${skipped.length}, pending: ${pending.length}, aborted: ${aborted.length}, failed: ${failed.length}`\n );\n this.print(\n `worker restarts: ${schedulerRunSummary.workerRestarts}, max worker memory usage: ${formatBytes(schedulerRunSummary.maxWorkerMemoryUsage)}`\n );\n } else {\n this.print(\"Nothing has been run.\");\n }\n\n this.print(hrLine);\n\n for (const targetId of failed) {\n const target = targetRuns.get(targetId)?.target;\n if (target) {\n const failureLogs = this.taskData.get(targetId)?.logEntries;\n\n this.print(`[${colors.pkg(target.packageName ?? \"<root>\")} ${colors.task(target.task)}] ${colors.failed(\"ERROR DETECTED\")}`);\n\n if (failureLogs) {\n for (const entry of failureLogs) {\n this.print(entry.msg);\n }\n }\n this.print(hrLine);\n }\n }\n\n const allCacheHits = [...targetRuns.values()].filter((run) => !run.target.hidden).length === skipped.length;\n const allCacheHitText = allCacheHits ? fancyGradient(`All targets skipped!`) : \"\";\n\n this.print(`Took a total of ${formatHrtime(duration)} to complete. ${allCacheHitText}`);\n }\n\n /** Clear the update timer */\n public cleanup(): void {\n clearInterval(this.updateTimer);\n this.updateTimer = undefined;\n }\n\n private reportCompletion(completion: {\n target: Target;\n status: CompletionStatus;\n duration?: [number, number];\n memoryUsage?: NodeJS.MemoryUsage;\n }) {\n const icon = icons[completion.status];\n const statusColor = colors[completion.status];\n const durationText = completion.duration ? ` (${formatHrtime(completion.duration)})` : \"\";\n const memText = formatMemoryUsage(completion.memoryUsage, this.logMemory);\n\n const message = `${statusColor(`${icon} ${completion.status.padEnd(8)}`)} ${colors.label(completion.target.label)}${colors.duration(durationText + memText)}`;\n this.renderStatus(message);\n }\n\n private renderStatus(completedTaskMessage?: string) {\n const counts: Record<CoarseStatus, number> = { completed: 0, running: 0, pending: 0 };\n for (const data of this.taskData.values()) {\n counts[coarseStatus[data.status]]++;\n }\n const { completed, running, pending } = counts;\n const total = this.taskData.size;\n const timestamp = colors.timestamp(`[${new Date().toLocaleTimeString(\"en-US\", { hour12: false })}]`);\n\n let output = terminal.clearLine;\n if (completedTaskMessage) {\n output += `${timestamp} ${completedTaskMessage}\\n`;\n }\n const percentage = Math.round((completed / total) * 100);\n output += `${timestamp} Completed: ${completed}/${total} (${percentage}%) [${running} running, ${pending} pending]`;\n this.logStream.write(output);\n }\n\n private print(message: string): void {\n this.logStream.write(message + \"\\n\");\n }\n}\n"],"names":["BasicReporter","coarseStatus","success","failed","skipped","aborted","running","pending","queued","isCompletionStatus","status","colors","label","chalk","white","timestamp","gray","duration","green","red","yellow","summary","cyanBright","task","hex","pkg","icons","terminal","hideCursor","showCursor","clearLine","log","entry","data","target","hidden","taskData","get","id","logEntries","set","startTimer","push","reportCompletion","memoryUsage","summarize","schedulerRunSummary","clearInterval","updateTimer","logStream","write","targetRuns","targetRunByStatus","size","print","hrLine","length","workerRestarts","formatBytes","maxWorkerMemoryUsage","targetId","failureLogs","packageName","msg","allCacheHits","values","filter","run","allCacheHitText","fancyGradient","formatHrtime","cleanup","undefined","completion","icon","statusColor","durationText","memText","formatMemoryUsage","logMemory","message","padEnd","renderStatus","completedTaskMessage","counts","completed","total","Date","toLocaleTimeString","hour12","output","percentage","Math","round","params","Map","concurrency","version","frequency","process","stdout","setInterval","unref","on"],"mappings":"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"}
|
|
@@ -6,6 +6,9 @@ export interface ChromeTraceEventsReporterOptions {
|
|
|
6
6
|
concurrency: number;
|
|
7
7
|
categorize?: (targetRun?: TargetRun) => string;
|
|
8
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* Reporter that generates a Chrome dev tools profile file.
|
|
11
|
+
*/
|
|
9
12
|
export declare class ChromeTraceEventsReporter implements Reporter {
|
|
10
13
|
private options;
|
|
11
14
|
private consoleLogStream;
|
|
@@ -69,11 +69,10 @@ class ChromeTraceEventsReporter {
|
|
|
69
69
|
}
|
|
70
70
|
this.events.traceEvents.push(event);
|
|
71
71
|
}
|
|
72
|
-
if (
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
72
|
+
// make the directory if it doesn't exist (no-op if exists)
|
|
73
|
+
_fs.default.mkdirSync(_path.default.dirname(this.outputFile), {
|
|
74
|
+
recursive: true
|
|
75
|
+
});
|
|
77
76
|
_fs.default.writeFileSync(this.outputFile, JSON.stringify(this.events, null, 2));
|
|
78
77
|
this.consoleLogStream.write(_chalk.default.blueBright(`\nProfiler output written to ${_chalk.default.underline(this.outputFile)}, open it with chrome://tracing or edge://tracing\n`));
|
|
79
78
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ChromeTraceEventsReporter.ts"],"sourcesContent":["import chalk from \"chalk\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport type { Reporter } from \"@lage-run/logger\";\nimport type { SchedulerRunSummary, TargetRun } from \"@lage-run/scheduler-types\";\nimport type { Writable } from \"stream\";\n\ninterface TraceEventsObject {\n traceEvents: CompleteEvent[];\n displayTimeUnit: \"ms\" | \"ns\";\n}\n\ninterface CompleteEvent {\n name: string;\n cat: string; // status#task\n ph: \"X\";\n ts: number; // in microseconds\n pid: number;\n tid: number;\n dur: number;\n args?: Record<string, any>;\n}\n\nexport interface ChromeTraceEventsReporterOptions {\n outputFile?: string;\n concurrency: number;\n categorize?: (targetRun?: TargetRun) => string;\n}\n\nfunction hrTimeToMicroseconds(hr: [number, number]) {\n return hr[0] * 1e6 + hr[1] * 1e-3;\n}\n\nfunction getTimeBasedFilename(prefix: string) {\n const now = new Date(); // 2011-10-05T14:48:00.000Z\n const datetime = now.toISOString().split(\".\")[0]; // 2011-10-05T14:48:00\n const datetimeNormalized = datetime.replace(/-|:/g, \"\"); // 20111005T144800\n return `${prefix ? prefix + \"-\" : \"\"}${datetimeNormalized}.json`;\n}\n\nexport class ChromeTraceEventsReporter implements Reporter {\n private consoleLogStream: Writable;\n\n private events: TraceEventsObject = {\n traceEvents: [],\n displayTimeUnit: \"ms\",\n };\n private outputFile: string;\n\n constructor(\n private options: ChromeTraceEventsReporterOptions & {\n /** stream for testing */\n consoleLogStream?: Writable;\n }\n ) {\n this.outputFile = options.outputFile ?? getTimeBasedFilename(\"profile\");\n this.consoleLogStream = options.consoleLogStream ?? process.stdout;\n }\n\n public log(): void {\n // pass\n }\n\n public summarize(schedulerRunSummary: SchedulerRunSummary): void {\n const { targetRuns, startTime } = schedulerRunSummary;\n\n // categorize events\n const { categorize } = this.options;\n\n for (const targetRun of targetRuns.values()) {\n // Skip hidden targets because those should be hidden by reporters.\n // Hiding as well skipped targets to avoid polluting the profile.\n if (targetRun.target.hidden || targetRun.status === \"skipped\") {\n continue;\n }\n\n const event = {\n name: targetRun.target.id,\n cat: `${targetRun.status}#${targetRun.target.task}`,\n ph: \"X\",\n ts: hrTimeToMicroseconds(targetRun.startTime) - hrTimeToMicroseconds(startTime), // in microseconds\n dur: hrTimeToMicroseconds(targetRun.duration ?? [0, 1000]), // in microseconds\n pid: 1,\n tid: targetRun.threadId,\n }
|
|
1
|
+
{"version":3,"sources":["../src/ChromeTraceEventsReporter.ts"],"sourcesContent":["import chalk from \"chalk\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport type { Reporter } from \"@lage-run/logger\";\nimport type { SchedulerRunSummary, TargetRun } from \"@lage-run/scheduler-types\";\nimport type { Writable } from \"stream\";\n\ninterface TraceEventsObject {\n traceEvents: CompleteEvent[];\n displayTimeUnit: \"ms\" | \"ns\";\n}\n\ninterface CompleteEvent {\n name: string;\n cat: string; // status#task\n ph: \"X\";\n ts: number; // in microseconds\n pid: number;\n tid: number;\n dur: number;\n args?: Record<string, any>;\n}\n\nexport interface ChromeTraceEventsReporterOptions {\n outputFile?: string;\n concurrency: number;\n categorize?: (targetRun?: TargetRun) => string;\n}\n\nfunction hrTimeToMicroseconds(hr: [number, number]) {\n return hr[0] * 1e6 + hr[1] * 1e-3;\n}\n\nfunction getTimeBasedFilename(prefix: string) {\n const now = new Date(); // 2011-10-05T14:48:00.000Z\n const datetime = now.toISOString().split(\".\")[0]; // 2011-10-05T14:48:00\n const datetimeNormalized = datetime.replace(/-|:/g, \"\"); // 20111005T144800\n return `${prefix ? prefix + \"-\" : \"\"}${datetimeNormalized}.json`;\n}\n\n/**\n * Reporter that generates a Chrome dev tools profile file.\n */\nexport class ChromeTraceEventsReporter implements Reporter {\n private consoleLogStream: Writable;\n\n private events: TraceEventsObject = {\n traceEvents: [],\n displayTimeUnit: \"ms\",\n };\n private outputFile: string;\n\n constructor(\n private options: ChromeTraceEventsReporterOptions & {\n /** stream for testing */\n consoleLogStream?: Writable;\n }\n ) {\n this.outputFile = options.outputFile ?? getTimeBasedFilename(\"profile\");\n this.consoleLogStream = options.consoleLogStream ?? process.stdout;\n }\n\n public log(): void {\n // pass\n }\n\n public summarize(schedulerRunSummary: SchedulerRunSummary): void {\n const { targetRuns, startTime } = schedulerRunSummary;\n\n // categorize events\n const { categorize } = this.options;\n\n for (const targetRun of targetRuns.values()) {\n // Skip hidden targets because those should be hidden by reporters.\n // Hiding as well skipped targets to avoid polluting the profile.\n if (targetRun.target.hidden || targetRun.status === \"skipped\") {\n continue;\n }\n\n const event: CompleteEvent = {\n name: targetRun.target.id,\n cat: `${targetRun.status}#${targetRun.target.task}`,\n ph: \"X\",\n ts: hrTimeToMicroseconds(targetRun.startTime) - hrTimeToMicroseconds(startTime), // in microseconds\n dur: hrTimeToMicroseconds(targetRun.duration ?? [0, 1000]), // in microseconds\n pid: 1,\n tid: targetRun.threadId,\n };\n\n if (categorize) {\n event.cat += `,${categorize(targetRun)}`;\n }\n\n this.events.traceEvents.push(event);\n }\n\n // make the directory if it doesn't exist (no-op if exists)\n fs.mkdirSync(path.dirname(this.outputFile), { recursive: true });\n\n fs.writeFileSync(this.outputFile, JSON.stringify(this.events, null, 2));\n\n this.consoleLogStream.write(\n chalk.blueBright(\n `\\nProfiler output written to ${chalk.underline(this.outputFile)}, open it with chrome://tracing or edge://tracing\\n`\n )\n );\n }\n}\n"],"names":["ChromeTraceEventsReporter","hrTimeToMicroseconds","hr","getTimeBasedFilename","prefix","now","Date","datetime","toISOString","split","datetimeNormalized","replace","log","summarize","schedulerRunSummary","targetRuns","startTime","categorize","options","targetRun","values","target","hidden","status","event","name","id","cat","task","ph","ts","dur","duration","pid","tid","threadId","events","traceEvents","push","fs","mkdirSync","path","dirname","outputFile","recursive","writeFileSync","JSON","stringify","consoleLogStream","write","chalk","blueBright","underline","displayTimeUnit","process","stdout"],"mappings":";;;;+BA2CaA;;;eAAAA;;;8DA3CK;2DACH;6DACE;;;;;;;;;;;;;;;;;;;AA2BjB,SAASC,qBAAqBC,EAAoB;IAChD,OAAOA,EAAE,CAAC,EAAE,GAAG,MAAMA,EAAE,CAAC,EAAE,GAAG;AAC/B;AAEA,SAASC,qBAAqBC,MAAc;IAC1C,MAAMC,MAAM,IAAIC,QAAQ,2BAA2B;IACnD,MAAMC,WAAWF,IAAIG,WAAW,GAAGC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,sBAAsB;IACxE,MAAMC,qBAAqBH,SAASI,OAAO,CAAC,QAAQ,KAAK,kBAAkB;IAC3E,OAAO,GAAGP,SAASA,SAAS,MAAM,KAAKM,mBAAmB,KAAK,CAAC;AAClE;AAKO,MAAMV;IAmBJY,MAAY;IACjB,OAAO;IACT;IAEOC,UAAUC,mBAAwC,EAAQ;QAC/D,MAAM,EAAEC,UAAU,EAAEC,SAAS,EAAE,GAAGF;QAElC,oBAAoB;QACpB,MAAM,EAAEG,UAAU,EAAE,GAAG,IAAI,CAACC,OAAO;QAEnC,KAAK,MAAMC,aAAaJ,WAAWK,MAAM,GAAI;YAC3C,mEAAmE;YACnE,iEAAiE;YACjE,IAAID,UAAUE,MAAM,CAACC,MAAM,IAAIH,UAAUI,MAAM,KAAK,WAAW;gBAC7D;YACF;YAEA,MAAMC,QAAuB;gBAC3BC,MAAMN,UAAUE,MAAM,CAACK,EAAE;gBACzBC,KAAK,GAAGR,UAAUI,MAAM,CAAC,CAAC,EAAEJ,UAAUE,MAAM,CAACO,IAAI,EAAE;gBACnDC,IAAI;gBACJC,IAAI7B,qBAAqBkB,UAAUH,SAAS,IAAIf,qBAAqBe;gBACrEe,KAAK9B,qBAAqBkB,UAAUa,QAAQ,IAAI;oBAAC;oBAAG;iBAAK;gBACzDC,KAAK;gBACLC,KAAKf,UAAUgB,QAAQ;YACzB;YAEA,IAAIlB,YAAY;gBACdO,MAAMG,GAAG,IAAI,CAAC,CAAC,EAAEV,WAAWE,YAAY;YAC1C;YAEA,IAAI,CAACiB,MAAM,CAACC,WAAW,CAACC,IAAI,CAACd;QAC/B;QAEA,2DAA2D;QAC3De,WAAE,CAACC,SAAS,CAACC,aAAI,CAACC,OAAO,CAAC,IAAI,CAACC,UAAU,GAAG;YAAEC,WAAW;QAAK;QAE9DL,WAAE,CAACM,aAAa,CAAC,IAAI,CAACF,UAAU,EAAEG,KAAKC,SAAS,CAAC,IAAI,CAACX,MAAM,EAAE,MAAM;QAEpE,IAAI,CAACY,gBAAgB,CAACC,KAAK,CACzBC,cAAK,CAACC,UAAU,CACd,CAAC,6BAA6B,EAAED,cAAK,CAACE,SAAS,CAAC,IAAI,CAACT,UAAU,EAAE,mDAAmD,CAAC;IAG3H;IAtDA,YACE,AAAQzB,OAGP,CACD;;QAbF,uBAAQ8B,oBAAR,KAAA;QAEA,uBAAQZ,UAAR,KAAA;QAIA,uBAAQO,cAAR,KAAA;aAGUzB,UAAAA;aAPFkB,SAA4B;YAClCC,aAAa,EAAE;YACfgB,iBAAiB;QACnB;QASE,IAAI,CAACV,UAAU,GAAGzB,QAAQyB,UAAU,IAAIxC,qBAAqB;QAC7D,IAAI,CAAC6C,gBAAgB,GAAG9B,QAAQ8B,gBAAgB,IAAIM,QAAQC,MAAM;IACpE;AA+CF"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { TargetRun } from "@lage-run/scheduler-types";
|
|
2
2
|
import { GroupedReporter } from "./GroupedReporter.js";
|
|
3
|
+
/**
|
|
4
|
+
* Reporter that formats logs for GitHub Actions, optionally with grouping.
|
|
5
|
+
*/
|
|
3
6
|
export declare class GithubActionsReporter extends GroupedReporter {
|
|
4
7
|
protected formatGroupStart(packageName: string, task: string, status: string, duration?: [number, number]): string;
|
|
5
8
|
protected formatGroupEnd(): string;
|
|
@@ -12,7 +12,7 @@ const _formatDuration = require("./formatDuration.js");
|
|
|
12
12
|
const _GroupedReporter = require("./GroupedReporter.js");
|
|
13
13
|
class GithubActionsReporter extends _GroupedReporter.GroupedReporter {
|
|
14
14
|
formatGroupStart(packageName, task, status, duration) {
|
|
15
|
-
return `::group::${packageName} ${task} ${status}${duration ? `, took ${(0, _formatDuration.
|
|
15
|
+
return `::group::${packageName} ${task} ${status}${duration ? `, took ${(0, _formatDuration.formatHrtime)(duration)}` : ""}\n`;
|
|
16
16
|
}
|
|
17
17
|
formatGroupEnd() {
|
|
18
18
|
return `::endgroup::\n`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/GithubActionsReporter.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"sources":["../src/GithubActionsReporter.ts"],"sourcesContent":["import { formatHrtime } from \"./formatDuration.js\";\nimport type { TargetRun } from \"@lage-run/scheduler-types\";\nimport { GroupedReporter } from \"./GroupedReporter.js\";\n\n/**\n * Reporter that formats logs for GitHub Actions, optionally with grouping.\n */\nexport class GithubActionsReporter extends GroupedReporter {\n protected formatGroupStart(packageName: string, task: string, status: string, duration?: [number, number]): string {\n return `::group::${packageName} ${task} ${status}${duration ? `, took ${formatHrtime(duration)}` : \"\"}\\n`;\n }\n\n protected formatGroupEnd(): string {\n return `::endgroup::\\n`;\n }\n\n protected writeSummaryHeader(): void {\n this.logStream.write(`::group::Summary\\n`);\n }\n\n protected writeSummaryFooter(): void {\n this.logStream.write(`::endgroup::\\n`);\n }\n\n protected writeFailures(failed: string[], targetRuns: Map<string, TargetRun<unknown>>): void {\n for (const targetId of failed) {\n const target = targetRuns.get(targetId)?.target;\n\n if (target) {\n const { packageName, task } = target;\n const taskLogs = this.logEntries.get(targetId);\n\n this.logStream.write(`::error title=${packageName} ${task}::Build failed\\n`);\n\n if (taskLogs) {\n for (const entry of taskLogs) {\n if (entry.msg.trim() !== \"\") {\n this.logStream.write(`::error::${entry.msg}\\n`);\n }\n }\n }\n }\n }\n }\n}\n"],"names":["GithubActionsReporter","GroupedReporter","formatGroupStart","packageName","task","status","duration","formatHrtime","formatGroupEnd","writeSummaryHeader","logStream","write","writeSummaryFooter","writeFailures","failed","targetRuns","targetId","target","get","taskLogs","logEntries","entry","msg","trim"],"mappings":";;;;+BAOaA;;;eAAAA;;;gCAPgB;iCAEG;AAKzB,MAAMA,8BAA8BC,gCAAe;IAC9CC,iBAAiBC,WAAmB,EAAEC,IAAY,EAAEC,MAAc,EAAEC,QAA2B,EAAU;QACjH,OAAO,CAAC,SAAS,EAAEH,YAAY,CAAC,EAAEC,KAAK,CAAC,EAAEC,SAASC,WAAW,CAAC,OAAO,EAAEC,IAAAA,4BAAY,EAACD,WAAW,GAAG,GAAG,EAAE,CAAC;IAC3G;IAEUE,iBAAyB;QACjC,OAAO,CAAC,cAAc,CAAC;IACzB;IAEUC,qBAA2B;QACnC,IAAI,CAACC,SAAS,CAACC,KAAK,CAAC,CAAC,kBAAkB,CAAC;IAC3C;IAEUC,qBAA2B;QACnC,IAAI,CAACF,SAAS,CAACC,KAAK,CAAC,CAAC,cAAc,CAAC;IACvC;IAEUE,cAAcC,MAAgB,EAAEC,UAA2C,EAAQ;QAC3F,KAAK,MAAMC,YAAYF,OAAQ;YAC7B,MAAMG,SAASF,WAAWG,GAAG,CAACF,WAAWC;YAEzC,IAAIA,QAAQ;gBACV,MAAM,EAAEd,WAAW,EAAEC,IAAI,EAAE,GAAGa;gBAC9B,MAAME,WAAW,IAAI,CAACC,UAAU,CAACF,GAAG,CAACF;gBAErC,IAAI,CAACN,SAAS,CAACC,KAAK,CAAC,CAAC,cAAc,EAAER,YAAY,CAAC,EAAEC,KAAK,gBAAgB,CAAC;gBAE3E,IAAIe,UAAU;oBACZ,KAAK,MAAME,SAASF,SAAU;wBAC5B,IAAIE,MAAMC,GAAG,CAACC,IAAI,OAAO,IAAI;4BAC3B,IAAI,CAACb,SAAS,CAACC,KAAK,CAAC,CAAC,SAAS,EAAEU,MAAMC,GAAG,CAAC,EAAE,CAAC;wBAChD;oBACF;gBACF;YACF;QACF;IACF;AACF"}
|
package/lib/GroupedReporter.d.ts
CHANGED
|
@@ -16,15 +16,10 @@ export declare const colors: {
|
|
|
16
16
|
error: chalk.Chalk;
|
|
17
17
|
warn: chalk.Chalk;
|
|
18
18
|
};
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
50: string;
|
|
24
|
-
40: string;
|
|
25
|
-
};
|
|
26
|
-
export declare function getTaskLogPrefix(pkg: string, task: string): string;
|
|
27
|
-
export declare function format(level: LogLevel, prefix: string, message: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* Abstract reporter which optionally groups log entries by target.
|
|
21
|
+
* If grouping is enabled, it only flushes a target's log entries when it completes.
|
|
22
|
+
*/
|
|
28
23
|
export declare abstract class GroupedReporter implements Reporter {
|
|
29
24
|
protected options: {
|
|
30
25
|
logLevel?: LogLevel;
|
|
@@ -46,7 +41,7 @@ export declare abstract class GroupedReporter implements Reporter {
|
|
|
46
41
|
logStream?: Writable;
|
|
47
42
|
});
|
|
48
43
|
log(entry: LogEntry<any>): boolean | void;
|
|
49
|
-
|
|
44
|
+
/** Print the entry for a target */
|
|
50
45
|
protected logTargetEntry(entry: LogEntry<TargetLogData>): boolean | void;
|
|
51
46
|
private logTargetEntryByGroup;
|
|
52
47
|
summarize(schedulerRunSummary: SchedulerRunSummary): void;
|
package/lib/GroupedReporter.js
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", {
|
|
3
3
|
value: true
|
|
4
4
|
});
|
|
5
|
+
0 && (module.exports = {
|
|
6
|
+
GroupedReporter: null,
|
|
7
|
+
colors: null
|
|
8
|
+
});
|
|
5
9
|
function _export(target, all) {
|
|
6
10
|
for(var name in all)Object.defineProperty(target, name, {
|
|
7
11
|
enumerable: true,
|
|
@@ -14,15 +18,6 @@ _export(exports, {
|
|
|
14
18
|
},
|
|
15
19
|
get colors () {
|
|
16
20
|
return colors;
|
|
17
|
-
},
|
|
18
|
-
get format () {
|
|
19
|
-
return format;
|
|
20
|
-
},
|
|
21
|
-
get getTaskLogPrefix () {
|
|
22
|
-
return getTaskLogPrefix;
|
|
23
|
-
},
|
|
24
|
-
get logLevelLabel () {
|
|
25
|
-
return logLevelLabel;
|
|
26
21
|
}
|
|
27
22
|
});
|
|
28
23
|
const _formatDuration = require("./formatDuration.js");
|
|
@@ -30,7 +25,8 @@ const _isTargetStatusLogEntry = require("./isTargetStatusLogEntry.js");
|
|
|
30
25
|
const _logger = require("@lage-run/logger");
|
|
31
26
|
const _chalk = /*#__PURE__*/ _interop_require_default(require("chalk"));
|
|
32
27
|
const _slowestTargetRuns = require("./slowestTargetRuns.js");
|
|
33
|
-
const
|
|
28
|
+
const _formatHelpers = require("./formatHelpers.js");
|
|
29
|
+
const _LogReporter = require("./LogReporter.js");
|
|
34
30
|
function _define_property(obj, key, value) {
|
|
35
31
|
if (key in obj) {
|
|
36
32
|
Object.defineProperty(obj, key, {
|
|
@@ -71,18 +67,6 @@ const logLevelLabel = {
|
|
|
71
67
|
function getTaskLogPrefix(pkg, task) {
|
|
72
68
|
return `${colors.pkg(pkg)} ${colors.task(task)}`;
|
|
73
69
|
}
|
|
74
|
-
function normalize(prefixOrMessage, message) {
|
|
75
|
-
if (typeof message === "string") {
|
|
76
|
-
return {
|
|
77
|
-
prefix: prefixOrMessage,
|
|
78
|
-
message
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
return {
|
|
82
|
-
prefix: "",
|
|
83
|
-
message: prefixOrMessage
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
70
|
function format(level, prefix, message) {
|
|
87
71
|
return `${logLevelLabel[level]}: ${prefix} ${message}\n`;
|
|
88
72
|
}
|
|
@@ -104,42 +88,41 @@ class GroupedReporter {
|
|
|
104
88
|
return this.logTargetEntry(entry);
|
|
105
89
|
}
|
|
106
90
|
}
|
|
107
|
-
|
|
108
|
-
if (!this.options.logMemory || !memoryUsage) {
|
|
109
|
-
return "";
|
|
110
|
-
}
|
|
111
|
-
return ` [rss: ${(0, _formatBytes.formatBytes)(memoryUsage.rss)}, heap: ${(0, _formatBytes.formatBytes)(memoryUsage.heapUsed)}]`;
|
|
112
|
-
}
|
|
113
|
-
logTargetEntry(entry) {
|
|
91
|
+
/** Print the entry for a target */ logTargetEntry(entry) {
|
|
114
92
|
const colorFn = colors[entry.level];
|
|
115
93
|
const data = entry.data;
|
|
116
|
-
if (
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
const mem = this.formatMemory(memoryUsage);
|
|
120
|
-
const normalizedArgs = this.options.grouped ? normalize(entry.msg) : normalize(getTaskLogPrefix(packageName ?? "<root>", task), entry.msg);
|
|
121
|
-
const pkgTask = this.options.grouped ? `${_chalk.default.magenta(packageName)} ${_chalk.default.cyan(task)}` : "";
|
|
122
|
-
switch(data.status){
|
|
123
|
-
case "running":
|
|
124
|
-
return this.logStream.write(format(entry.level, normalizedArgs.prefix, colorFn(`${colors.ok("➔")} start ${pkgTask}`)));
|
|
125
|
-
case "success":
|
|
126
|
-
return this.logStream.write(format(entry.level, normalizedArgs.prefix, colorFn(`${colors.ok("✓")} done ${pkgTask} - ${(0, _formatDuration.formatDuration)((0, _formatDuration.hrToSeconds)(duration))}${mem}`)));
|
|
127
|
-
case "failed":
|
|
128
|
-
return this.logStream.write(format(entry.level, normalizedArgs.prefix, colorFn(`${colors.error("✖")} fail ${pkgTask}${mem}`)));
|
|
129
|
-
case "skipped":
|
|
130
|
-
return this.logStream.write(format(entry.level, normalizedArgs.prefix, colorFn(`${colors.ok("»")} skip ${pkgTask} - ${hash}${mem}`)));
|
|
131
|
-
case "aborted":
|
|
132
|
-
return this.logStream.write(format(entry.level, normalizedArgs.prefix, colorFn(`${colors.warn("-")} aborted ${pkgTask}`)));
|
|
133
|
-
case "queued":
|
|
134
|
-
return this.logStream.write(format(entry.level, normalizedArgs.prefix, colorFn(`${colors.warn("…")} queued ${pkgTask}`)));
|
|
94
|
+
if (!data?.target) {
|
|
95
|
+
if (entry.msg.trim()) {
|
|
96
|
+
this.logStream.write(format(entry.level, "", entry.msg));
|
|
135
97
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
return this.logStream.write(format(entry.level, ""
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const { target } = data;
|
|
101
|
+
const { packageName, task } = target;
|
|
102
|
+
const prefix = this.options.grouped ? "" : getTaskLogPrefix(packageName ?? "<root>", task);
|
|
103
|
+
if (!(0, _isTargetStatusLogEntry.isTargetStatusLogEntry)(data)) {
|
|
104
|
+
return this.logStream.write(format(entry.level, prefix, colorFn("| " + entry.msg)));
|
|
105
|
+
}
|
|
106
|
+
const { hash, duration, memoryUsage, status } = data;
|
|
107
|
+
const mem = (0, _formatHelpers.formatMemoryUsage)(memoryUsage, this.options.logMemory);
|
|
108
|
+
const pkgTask = this.options.grouped ? `${_chalk.default.magenta(packageName)} ${_chalk.default.cyan(task)}` : "";
|
|
109
|
+
switch(status){
|
|
110
|
+
case "running":
|
|
111
|
+
return this.logStream.write(format(entry.level, prefix, colorFn(`${colors.ok("➔")} start ${pkgTask}`)));
|
|
112
|
+
case "success":
|
|
113
|
+
return this.logStream.write(format(entry.level, prefix, colorFn(`${colors.ok("✓")} done ${pkgTask} - ${(0, _formatDuration.formatHrtime)(duration)}${mem}`)));
|
|
114
|
+
case "failed":
|
|
115
|
+
return this.logStream.write(format(entry.level, prefix, colorFn(`${colors.error("✖")} fail ${pkgTask}${mem}`)));
|
|
116
|
+
case "skipped":
|
|
117
|
+
return this.logStream.write(format(entry.level, prefix, colorFn(`${colors.ok("»")} skip ${pkgTask} - ${hash}${mem}`)));
|
|
118
|
+
case "aborted":
|
|
119
|
+
return this.logStream.write(format(entry.level, prefix, colorFn(`${colors.warn("-")} aborted ${pkgTask}`)));
|
|
120
|
+
case "queued":
|
|
121
|
+
return this.logStream.write(format(entry.level, prefix, colorFn(`${colors.warn("…")} queued ${pkgTask}`)));
|
|
122
|
+
case "pending":
|
|
123
|
+
return;
|
|
124
|
+
default:
|
|
125
|
+
throw new Error(`Internal error: unhandled target status "${status}"`);
|
|
143
126
|
}
|
|
144
127
|
}
|
|
145
128
|
logTargetEntryByGroup(entry) {
|
|
@@ -161,36 +144,28 @@ class GroupedReporter {
|
|
|
161
144
|
}
|
|
162
145
|
}
|
|
163
146
|
summarize(schedulerRunSummary) {
|
|
164
|
-
const { targetRuns, targetRunByStatus
|
|
147
|
+
const { targetRuns, targetRunByStatus } = schedulerRunSummary;
|
|
165
148
|
const { failed, aborted, skipped, success, pending } = targetRunByStatus;
|
|
166
|
-
const statusColorFn = {
|
|
167
|
-
success: _chalk.default.greenBright,
|
|
168
|
-
failed: _chalk.default.redBright,
|
|
169
|
-
skipped: _chalk.default.gray,
|
|
170
|
-
running: _chalk.default.yellow,
|
|
171
|
-
pending: _chalk.default.gray,
|
|
172
|
-
aborted: _chalk.default.red,
|
|
173
|
-
queued: _chalk.default.magenta
|
|
174
|
-
};
|
|
175
149
|
this.writeSummaryHeader();
|
|
176
150
|
if (targetRuns.size > 0) {
|
|
177
151
|
const slowestTargets = (0, _slowestTargetRuns.slowestTargetRuns)([
|
|
178
152
|
...targetRuns.values()
|
|
179
153
|
]);
|
|
180
154
|
for (const wrappedTarget of slowestTargets){
|
|
181
|
-
const
|
|
182
|
-
const
|
|
183
|
-
this.logStream.write(format(_logger.LogLevel.info, getTaskLogPrefix(target.packageName || "[GLOBAL]", target.task), colorFn(`${
|
|
155
|
+
const { target, status, duration } = wrappedTarget;
|
|
156
|
+
const colorFn = _LogReporter.statusColorFn[status] ?? _chalk.default.white;
|
|
157
|
+
this.logStream.write(format(_logger.LogLevel.info, getTaskLogPrefix(target.packageName || "[GLOBAL]", target.task), colorFn(`${status}${duration ? `, took ${(0, _formatDuration.formatHrtime)(duration)}` : ""}`)));
|
|
184
158
|
}
|
|
185
159
|
this.logStream.write(`[Tasks Count] success: ${success.length}, skipped: ${skipped.length}, pending: ${pending.length}, aborted: ${aborted.length}\n`);
|
|
186
160
|
} else {
|
|
187
161
|
this.logStream.write("Nothing has been run.\n");
|
|
188
162
|
}
|
|
189
163
|
this.writeSummaryFooter();
|
|
190
|
-
if (failed
|
|
164
|
+
if (failed.length > 0) {
|
|
191
165
|
this.writeFailures(failed, targetRuns);
|
|
192
166
|
}
|
|
193
|
-
|
|
167
|
+
const formattedDuration = (0, _formatDuration.formatHrtime)(schedulerRunSummary.duration);
|
|
168
|
+
this.logStream.write(format(_logger.LogLevel.info, "", `Took a total of ${formattedDuration} to complete`));
|
|
194
169
|
}
|
|
195
170
|
constructor(options){
|
|
196
171
|
_define_property(this, "options", void 0);
|