@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.
Files changed (45) hide show
  1. package/lib/AdoReporter.d.ts +3 -0
  2. package/lib/AdoReporter.js +1 -1
  3. package/lib/AdoReporter.js.map +1 -1
  4. package/lib/BasicReporter.d.ts +12 -1
  5. package/lib/BasicReporter.js +33 -28
  6. package/lib/BasicReporter.js.map +1 -1
  7. package/lib/ChromeTraceEventsReporter.d.ts +3 -0
  8. package/lib/ChromeTraceEventsReporter.js +4 -5
  9. package/lib/ChromeTraceEventsReporter.js.map +1 -1
  10. package/lib/GithubActionsReporter.d.ts +3 -0
  11. package/lib/GithubActionsReporter.js +1 -1
  12. package/lib/GithubActionsReporter.js.map +1 -1
  13. package/lib/GroupedReporter.d.ts +5 -10
  14. package/lib/GroupedReporter.js +45 -70
  15. package/lib/GroupedReporter.js.map +1 -1
  16. package/lib/JsonReporter.d.ts +4 -1
  17. package/lib/JsonReporter.js.map +1 -1
  18. package/lib/LogReporter.d.ts +22 -3
  19. package/lib/LogReporter.js +67 -85
  20. package/lib/LogReporter.js.map +1 -1
  21. package/lib/ProgressReporter.d.ts +21 -4
  22. package/lib/ProgressReporter.js +105 -123
  23. package/lib/ProgressReporter.js.map +1 -1
  24. package/lib/VerboseFileLogReporter.d.ts +3 -1
  25. package/lib/VerboseFileLogReporter.js +21 -24
  26. package/lib/VerboseFileLogReporter.js.map +1 -1
  27. package/lib/formatDuration.d.ts +4 -0
  28. package/lib/formatDuration.js +13 -1
  29. package/lib/formatDuration.js.map +1 -1
  30. package/lib/formatHelpers.d.ts +13 -0
  31. package/lib/formatHelpers.js +68 -0
  32. package/lib/formatHelpers.js.map +1 -0
  33. package/lib/index.d.ts +1 -1
  34. package/lib/index.js +17 -0
  35. package/lib/index.js.map +1 -1
  36. package/package.json +7 -9
  37. package/lib/formatBytes.d.ts +0 -1
  38. package/lib/formatBytes.js +0 -13
  39. package/lib/formatBytes.js.map +0 -1
  40. package/lib/gradient.d.ts +0 -6
  41. package/lib/gradient.js +0 -18
  42. package/lib/gradient.js.map +0 -1
  43. package/lib/types/progressBarTypes.d.ts +0 -12
  44. package/lib/types/progressBarTypes.js +0 -4
  45. package/lib/types/progressBarTypes.js.map +0 -1
@@ -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;
@@ -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.formatDuration)((0, _formatDuration.hrToSeconds)(duration))}` : ""}\n`;
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`;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/AdoReporter.ts"],"sourcesContent":["import { formatDuration, hrToSeconds } from \"./formatDuration.js\";\nimport chalk from \"chalk\";\nimport type { TargetRun } from \"@lage-run/scheduler-types\";\nimport { colors, GroupedReporter } from \"./GroupedReporter.js\";\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}${\n duration ? `, took ${formatDuration(hrToSeconds(duration))}` : \"\"\n }\\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","formatDuration","hrToSeconds","formatGroupEnd","writeSummaryHeader","logStream","write","chalk","cyanBright","writeSummaryFooter","writeFailures","failed","targetRuns","packagesMessage","targetId","target","get","taskLogs","logEntries","magenta","cyan","redBright","entry","msg"],"mappings":";;;;+BAKaA;;;eAAAA;;;gCAL+B;8DAC1B;iCAEsB;;;;;;AAEjC,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,SAClEC,WAAW,CAAC,OAAO,EAAEG,IAAAA,8BAAc,EAACC,IAAAA,2BAAW,EAACJ,YAAY,GAAG,GAChE,EAAE,CAAC;IACN;IAEUK,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,EAAEpB,WAAW,EAAEC,IAAI,EAAE,GAAGmB;gBAC9B,MAAME,WAAW,IAAI,CAACC,UAAU,CAACF,GAAG,CAACF;gBAErCD,mBAAmB,CAAC,CAAC,EAAElB,YAAY,CAAC,EAAEC,KAAK,GAAG,CAAC;gBAE/C,IAAI,CAACS,SAAS,CAACC,KAAK,CAAC,CAAC,WAAW,EAAEC,cAAK,CAACY,OAAO,CAACxB,aAAa,CAAC,EAAEY,cAAK,CAACa,IAAI,CAACxB,MAAM,EAAE,EAAEW,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"}
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"}
@@ -1,19 +1,30 @@
1
- import { type LogEntry, type Reporter } from "@lage-run/logger";
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
  }
@@ -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 _formatBytes = require("./formatBytes.js");
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
- process.stdout.write(terminal.clearLine);
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, _formatBytes.formatBytes)(schedulerRunSummary.maxWorkerMemoryUsage)}`);
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 ? fancy(`All targets skipped!`) : "";
131
- print(`Took a total of ${(0, _formatDuration.formatDuration)((0, _formatDuration.hrToSeconds)(duration))} to complete. ${allCacheHitText}`);
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.formatDuration)((0, _formatDuration.hrToSeconds)(completion.duration))})` : "";
137
- const memText = this.logMemory && completion.memoryUsage ? ` [rss: ${(0, _formatBytes.formatBytes)(completion.memoryUsage.rss)}, heap: ${(0, _formatBytes.formatBytes)(completion.memoryUsage.heapUsed)}]` : "";
138
- const message = `${statusColor(`${icon} ${completion.status.padEnd(8)}`)} ${colors.label(completion.target.label)}${colors.duration(durationText)}${colors.duration(memText)}`;
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
- process.stdout.write(output);
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
- print(`${fancy("lage")} - Version ${version} - ${concurrency} Workers`);
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
- process.stdout.write(terminal.hideCursor);
177
- process.on("exit", ()=>process.stdout.write(terminal.showCursor));
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
  }
@@ -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 (!_fs.default.existsSync(_path.default.dirname(this.outputFile))) {
73
- _fs.default.mkdirSync(_path.default.dirname(this.outputFile), {
74
- recursive: true
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 } as CompleteEvent;\n\n if (categorize) {\n event.cat += `,${categorize(targetRun)}`;\n }\n\n this.events.traceEvents.push(event);\n }\n\n if (!fs.existsSync(path.dirname(this.outputFile))) {\n fs.mkdirSync(path.dirname(this.outputFile), { recursive: true });\n }\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","existsSync","path","dirname","outputFile","mkdirSync","recursive","writeFileSync","JSON","stringify","consoleLogStream","write","chalk","blueBright","underline","displayTimeUnit","process","stdout"],"mappings":";;;;+BAwCaA;;;eAAAA;;;8DAxCK;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;AAEO,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,QAAQ;gBACZC,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,IAAI,CAACe,WAAE,CAACC,UAAU,CAACC,aAAI,CAACC,OAAO,CAAC,IAAI,CAACC,UAAU,IAAI;YACjDJ,WAAE,CAACK,SAAS,CAACH,aAAI,CAACC,OAAO,CAAC,IAAI,CAACC,UAAU,GAAG;gBAAEE,WAAW;YAAK;QAChE;QAEAN,WAAE,CAACO,aAAa,CAAC,IAAI,CAACH,UAAU,EAAEI,KAAKC,SAAS,CAAC,IAAI,CAACZ,MAAM,EAAE,MAAM;QAEpE,IAAI,CAACa,gBAAgB,CAACC,KAAK,CACzBC,cAAK,CAACC,UAAU,CACd,CAAC,6BAA6B,EAAED,cAAK,CAACE,SAAS,CAAC,IAAI,CAACV,UAAU,EAAE,mDAAmD,CAAC;IAG3H;IAvDA,YACE,AAAQzB,OAGP,CACD;;QAbF,uBAAQ+B,oBAAR,KAAA;QAEA,uBAAQb,UAAR,KAAA;QAIA,uBAAQO,cAAR,KAAA;aAGUzB,UAAAA;aAPFkB,SAA4B;YAClCC,aAAa,EAAE;YACfiB,iBAAiB;QACnB;QASE,IAAI,CAACX,UAAU,GAAGzB,QAAQyB,UAAU,IAAIxC,qBAAqB;QAC7D,IAAI,CAAC8C,gBAAgB,GAAG/B,QAAQ+B,gBAAgB,IAAIM,QAAQC,MAAM;IACpE;AAgDF"}
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.formatDuration)((0, _formatDuration.hrToSeconds)(duration))}` : ""}\n`;
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 { formatDuration, hrToSeconds } from \"./formatDuration.js\";\nimport type { TargetRun } from \"@lage-run/scheduler-types\";\nimport { GroupedReporter } from \"./GroupedReporter.js\";\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 ${formatDuration(hrToSeconds(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","formatDuration","hrToSeconds","formatGroupEnd","writeSummaryHeader","logStream","write","writeSummaryFooter","writeFailures","failed","targetRuns","targetId","target","get","taskLogs","logEntries","entry","msg","trim"],"mappings":";;;;+BAIaA;;;eAAAA;;;gCAJ+B;iCAEZ;AAEzB,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,8BAAc,EAACC,IAAAA,2BAAW,EAACF,YAAY,GAAG,GAAG,EAAE,CAAC;IAC1H;IAEUG,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,EAAEf,WAAW,EAAEC,IAAI,EAAE,GAAGc;gBAC9B,MAAME,WAAW,IAAI,CAACC,UAAU,CAACF,GAAG,CAACF;gBAErC,IAAI,CAACN,SAAS,CAACC,KAAK,CAAC,CAAC,cAAc,EAAET,YAAY,CAAC,EAAEC,KAAK,gBAAgB,CAAC;gBAE3E,IAAIgB,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"}
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"}
@@ -16,15 +16,10 @@ export declare const colors: {
16
16
  error: chalk.Chalk;
17
17
  warn: chalk.Chalk;
18
18
  };
19
- export declare const logLevelLabel: {
20
- 30: string;
21
- 20: string;
22
- 10: string;
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
- private formatMemory;
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;
@@ -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 _formatBytes = require("./formatBytes.js");
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
- formatMemory(memoryUsage) {
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 ((0, _isTargetStatusLogEntry.isTargetStatusLogEntry)(data)) {
117
- const { target, hash, duration, memoryUsage } = data;
118
- const { packageName, task } = target;
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
- } else if (entry?.data?.target) {
137
- const { target } = data;
138
- const { packageName, task } = target;
139
- const normalizedArgs = this.options.grouped ? normalize(entry.msg) : normalize(getTaskLogPrefix(packageName ?? "<root>", task), entry.msg);
140
- return this.logStream.write(format(entry.level, normalizedArgs.prefix, colorFn("| " + normalizedArgs.message)));
141
- } else if (entry?.msg.trim() !== "") {
142
- return this.logStream.write(format(entry.level, "", entry.msg));
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, duration } = schedulerRunSummary;
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 colorFn = statusColorFn[wrappedTarget.status];
182
- const target = wrappedTarget.target;
183
- this.logStream.write(format(_logger.LogLevel.info, getTaskLogPrefix(target.packageName || "[GLOBAL]", target.task), colorFn(`${wrappedTarget.status}${wrappedTarget.duration ? `, took ${(0, _formatDuration.formatDuration)((0, _formatDuration.hrToSeconds)(wrappedTarget.duration))}` : ""}`)));
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 && failed.length > 0) {
164
+ if (failed.length > 0) {
191
165
  this.writeFailures(failed, targetRuns);
192
166
  }
193
- this.logStream.write(format(_logger.LogLevel.info, "", `Took a total of ${(0, _formatDuration.formatDuration)((0, _formatDuration.hrToSeconds)(duration))} to complete`));
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);