@lage-run/reporters 1.7.4 → 1.8.0

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 (39) hide show
  1. package/lib/BasicReporter.d.ts +4 -3
  2. package/lib/BasicReporter.js +19 -13
  3. package/lib/BasicReporter.js.map +1 -1
  4. package/lib/ChromeTraceEventsReporter.d.ts +2 -2
  5. package/lib/ChromeTraceEventsReporter.js.map +1 -1
  6. package/lib/GroupedReporter.d.ts +24 -24
  7. package/lib/GroupedReporter.js +37 -28
  8. package/lib/GroupedReporter.js.map +1 -1
  9. package/lib/JsonReporter.d.ts +6 -8
  10. package/lib/JsonReporter.js +2 -1
  11. package/lib/JsonReporter.js.map +1 -1
  12. package/lib/LogReporter.d.ts +11 -13
  13. package/lib/LogReporter.js +45 -41
  14. package/lib/LogReporter.js.map +1 -1
  15. package/lib/ProgressReporter.d.ts +4 -4
  16. package/lib/ProgressReporter.js +35 -32
  17. package/lib/ProgressReporter.js.map +1 -1
  18. package/lib/VerboseFileLogReporter.d.ts +14 -8
  19. package/lib/VerboseFileLogReporter.js +19 -18
  20. package/lib/VerboseFileLogReporter.js.map +1 -1
  21. package/lib/index.d.ts +3 -2
  22. package/lib/index.js.map +1 -1
  23. package/lib/isCompletionStatus.d.ts +4 -0
  24. package/lib/isCompletionStatus.js +28 -0
  25. package/lib/isCompletionStatus.js.map +1 -0
  26. package/lib/isTargetLogEntry.d.ts +6 -0
  27. package/lib/isTargetLogEntry.js +35 -0
  28. package/lib/isTargetLogEntry.js.map +1 -0
  29. package/lib/slowestTargetRuns.d.ts +3 -0
  30. package/lib/slowestTargetRuns.js +1 -1
  31. package/lib/slowestTargetRuns.js.map +1 -1
  32. package/lib/types/TargetLogData.d.ts +13 -7
  33. package/lib/types/TargetReporter.d.ts +17 -0
  34. package/lib/types/TargetReporter.js +4 -0
  35. package/lib/types/TargetReporter.js.map +1 -0
  36. package/package.json +4 -4
  37. package/lib/isTargetStatusLogEntry.d.ts +0 -3
  38. package/lib/isTargetStatusLogEntry.js +0 -13
  39. package/lib/isTargetStatusLogEntry.js.map +0 -1
@@ -1,11 +1,12 @@
1
- import type { LogEntry, Reporter } from "@lage-run/logger";
2
1
  import type { SchedulerRunSummary } from "@lage-run/scheduler-types";
3
2
  import type { Writable } from "stream";
3
+ import type { TargetReporter, MaybeTargetLogEntry } from "./types/TargetReporter.js";
4
4
  /**
5
5
  * Shows running/remaining target counts and completed targets, but does not display
6
6
  * the names of running targets for efficiency.
7
7
  */
8
- export declare class BasicReporter implements Reporter {
8
+ export declare class BasicReporter implements TargetReporter {
9
+ /** Mapping from targetId to status and log entries (the logs will be cleared for non-failed completed targets) */
9
10
  private taskData;
10
11
  private updateTimer;
11
12
  private startTimer;
@@ -20,7 +21,7 @@ export declare class BasicReporter implements Reporter {
20
21
  /** Stream for output (defaults to process.stdout) */
21
22
  logStream?: Writable;
22
23
  });
23
- log(entry: LogEntry): void;
24
+ log(entry: MaybeTargetLogEntry): void;
24
25
  summarize(schedulerRunSummary: SchedulerRunSummary): void;
25
26
  /** Clear the update timer */
26
27
  cleanup(): void;
@@ -11,6 +11,8 @@ Object.defineProperty(exports, "BasicReporter", {
11
11
  const _chalk = /*#__PURE__*/ _interop_require_default(require("chalk"));
12
12
  const _formatDuration = require("./formatDuration.js");
13
13
  const _formatHelpers = require("./formatHelpers.js");
14
+ const _isTargetLogEntry = require("./isTargetLogEntry.js");
15
+ const _isCompletionStatus = require("./isCompletionStatus.js");
14
16
  function _define_property(obj, key, value) {
15
17
  if (key in obj) {
16
18
  Object.defineProperty(obj, key, {
@@ -38,7 +40,6 @@ const coarseStatus = {
38
40
  pending: "pending",
39
41
  queued: "pending"
40
42
  };
41
- const isCompletionStatus = (status)=>coarseStatus[status] === "completed";
42
43
  const colors = {
43
44
  label: _chalk.default.white,
44
45
  timestamp: _chalk.default.gray,
@@ -64,28 +65,33 @@ const terminal = {
64
65
  };
65
66
  class BasicReporter {
66
67
  log(entry) {
68
+ if (!(0, _isTargetLogEntry.isTargetLogEntry)(entry) || entry.data.target.hidden) return;
67
69
  const data = entry.data;
68
- if (!data?.target || data.target.hidden) return;
69
- let taskData = this.taskData.get(data.target.id);
70
+ const { target } = data;
71
+ let taskData = this.taskData.get(target.id);
70
72
  if (!taskData) {
71
73
  taskData = {
72
- target: data.target,
73
74
  status: "pending",
74
75
  logEntries: []
75
76
  };
76
- this.taskData.set(data.target.id, taskData);
77
+ this.taskData.set(target.id, taskData);
77
78
  }
78
79
  this.startTimer();
79
80
  taskData.logEntries.push(entry);
80
- if (data.status) {
81
- taskData.status = data.status;
82
- if (isCompletionStatus(data.status)) {
81
+ if ((0, _isTargetLogEntry.isTargetStatusData)(data)) {
82
+ const { status, duration, memoryUsage } = data;
83
+ taskData.status = status;
84
+ if ((0, _isCompletionStatus.isCompletionStatus)(status)) {
83
85
  this.reportCompletion({
84
- target: data.target,
85
- status: data.status,
86
- duration: data.duration,
87
- memoryUsage: data.memoryUsage
86
+ target,
87
+ status,
88
+ duration,
89
+ memoryUsage
88
90
  });
91
+ // Free log entries for non-failed completed targets (only needed for failure reporting at summary time)
92
+ if (status !== "failed") {
93
+ taskData.logEntries = [];
94
+ }
89
95
  }
90
96
  }
91
97
  }
@@ -160,7 +166,7 @@ class BasicReporter {
160
166
  this.logStream.write(message + "\n");
161
167
  }
162
168
  constructor(params = {}){
163
- _define_property(this, "taskData", new Map());
169
+ /** Mapping from targetId to status and log entries (the logs will be cleared for non-failed completed targets) */ _define_property(this, "taskData", new Map());
164
170
  _define_property(this, "updateTimer", void 0);
165
171
  _define_property(this, "startTimer", void 0);
166
172
  _define_property(this, "logMemory", void 0);
@@ -1 +1 @@
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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"}
1
+ {"version":3,"sources":["../src/BasicReporter.ts"],"sourcesContent":["import 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\";\nimport type { TargetReporter, MaybeTargetLogEntry, TargetLogEntry } from \"./types/TargetReporter.js\";\nimport { isTargetLogEntry, isTargetStatusData } from \"./isTargetLogEntry.js\";\nimport { isCompletionStatus, type CompletionStatus } from \"./isCompletionStatus.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\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 TargetReporter {\n /** Mapping from targetId to status and log entries (the logs will be cleared for non-failed completed targets) */\n private taskData = new Map<string, { status: TargetStatus; logEntries: TargetLogEntry[] }>();\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: MaybeTargetLogEntry): void {\n if (!isTargetLogEntry(entry) || entry.data.target.hidden) return;\n const data = entry.data;\n\n const { target } = data;\n let taskData = this.taskData.get(target.id);\n if (!taskData) {\n taskData = { status: \"pending\", logEntries: [] };\n this.taskData.set(target.id, taskData);\n }\n\n this.startTimer();\n taskData.logEntries.push(entry);\n\n if (isTargetStatusData(data)) {\n const { status, duration, memoryUsage } = data;\n taskData.status = status;\n if (isCompletionStatus(status)) {\n this.reportCompletion({ target, status, duration, memoryUsage });\n\n // Free log entries for non-failed completed targets (only needed for failure reporting at summary time)\n if (status !== \"failed\") {\n taskData.logEntries = [];\n }\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","colors","label","chalk","white","timestamp","gray","duration","green","red","yellow","summary","cyanBright","task","hex","pkg","icons","terminal","hideCursor","showCursor","clearLine","log","entry","isTargetLogEntry","data","target","hidden","taskData","get","id","status","logEntries","set","startTimer","push","isTargetStatusData","memoryUsage","isCompletionStatus","reportCompletion","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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"}
@@ -1,6 +1,6 @@
1
- import type { Reporter } from "@lage-run/logger";
2
1
  import type { SchedulerRunSummary, TargetRun } from "@lage-run/scheduler-types";
3
2
  import type { Writable } from "stream";
3
+ import type { TargetReporter } from "./types/TargetReporter.js";
4
4
  export interface ChromeTraceEventsReporterOptions {
5
5
  outputFile?: string;
6
6
  concurrency: number;
@@ -9,7 +9,7 @@ export interface ChromeTraceEventsReporterOptions {
9
9
  /**
10
10
  * Reporter that generates a Chrome dev tools profile file.
11
11
  */
12
- export declare class ChromeTraceEventsReporter implements Reporter {
12
+ export declare class ChromeTraceEventsReporter implements TargetReporter {
13
13
  private options;
14
14
  private consoleLogStream;
15
15
  private events;
@@ -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\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
+ {"version":3,"sources":["../src/ChromeTraceEventsReporter.ts"],"sourcesContent":["import chalk from \"chalk\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport type { SchedulerRunSummary, TargetRun } from \"@lage-run/scheduler-types\";\nimport type { Writable } from \"stream\";\nimport type { TargetReporter } from \"./types/TargetReporter.js\";\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 TargetReporter {\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,9 +1,8 @@
1
- import { LogLevel, type LogStructuredData } from "@lage-run/logger";
1
+ import { LogLevel } from "@lage-run/logger";
2
2
  import chalk from "chalk";
3
- import type { Reporter, LogEntry } from "@lage-run/logger";
4
3
  import type { SchedulerRunSummary, TargetRun } from "@lage-run/scheduler-types";
5
- import type { TargetLogData } from "./types/TargetLogData.js";
6
4
  import type { Writable } from "stream";
5
+ import type { MaybeTargetLogEntry, TargetLogEntry, TargetReporter } from "./types/TargetReporter.js";
7
6
  export declare const colors: {
8
7
  30: chalk.Chalk;
9
8
  40: chalk.Chalk;
@@ -16,33 +15,34 @@ export declare const colors: {
16
15
  error: chalk.Chalk;
17
16
  warn: chalk.Chalk;
18
17
  };
18
+ export interface GroupedReporterOptions {
19
+ /** Only report logs with this level or numerically lower/logically higher (default info) */
20
+ logLevel?: LogLevel;
21
+ /** Whether to group log entries by target */
22
+ grouped?: boolean;
23
+ /** Whether to capture and report main process memory usage on target completion */
24
+ logMemory?: boolean;
25
+ /** stream for testing (defaults to stdout) */
26
+ logStream?: Writable;
27
+ }
19
28
  /**
20
29
  * Abstract reporter which optionally groups log entries by target.
21
30
  * If grouping is enabled, it only flushes a target's log entries when it completes.
22
31
  */
23
- export declare abstract class GroupedReporter implements Reporter {
24
- protected options: {
25
- logLevel?: LogLevel;
26
- grouped?: boolean;
27
- /** Whether to capture and report main process memory usage on target completion */
28
- logMemory?: boolean;
29
- /** stream for testing */
30
- logStream?: Writable;
31
- };
32
+ export declare abstract class GroupedReporter implements TargetReporter {
33
+ protected options: GroupedReporterOptions;
32
34
  protected logStream: Writable;
33
- protected logEntries: Map<string, LogEntry<LogStructuredData>[]>;
34
- private readonly groupedEntries;
35
- constructor(options: {
36
- logLevel?: LogLevel;
37
- grouped?: boolean;
38
- /** Whether to capture and report main process memory usage on target completion */
39
- logMemory?: boolean;
40
- /** stream for testing */
41
- logStream?: Writable;
42
- });
43
- log(entry: LogEntry<any>): boolean | void;
35
+ /** Mapping from targetId log entries (the logs will be cleared for non-failed completed targets) */
36
+ protected logEntries: Map<string, TargetLogEntry[]>;
37
+ constructor(options: GroupedReporterOptions);
38
+ log(entry: MaybeTargetLogEntry): void;
39
+ /**
40
+ * Whether the entry should be logged based solely on its level compared to the reporter's `logLevel`
41
+ * (does not consider `entry.target.hidden` or message presence)
42
+ */
43
+ protected shouldLog(entry: MaybeTargetLogEntry): boolean;
44
44
  /** Print the entry for a target */
45
- protected logTargetEntry(entry: LogEntry<TargetLogData>): boolean | void;
45
+ protected logEntry(entry: TargetLogEntry): boolean | void;
46
46
  private logTargetEntryByGroup;
47
47
  summarize(schedulerRunSummary: SchedulerRunSummary): void;
48
48
  /** Returns the opening line for a grouped target log block, including trailing newline. */
@@ -21,12 +21,13 @@ _export(exports, {
21
21
  }
22
22
  });
23
23
  const _formatDuration = require("./formatDuration.js");
24
- const _isTargetStatusLogEntry = require("./isTargetStatusLogEntry.js");
24
+ const _isTargetLogEntry = require("./isTargetLogEntry.js");
25
25
  const _logger = require("@lage-run/logger");
26
26
  const _chalk = /*#__PURE__*/ _interop_require_default(require("chalk"));
27
27
  const _slowestTargetRuns = require("./slowestTargetRuns.js");
28
28
  const _formatHelpers = require("./formatHelpers.js");
29
29
  const _LogReporter = require("./LogReporter.js");
30
+ const _isCompletionStatus = require("./isCompletionStatus.js");
30
31
  function _define_property(obj, key, value) {
31
32
  if (key in obj) {
32
33
  Object.defineProperty(obj, key, {
@@ -72,35 +73,46 @@ function format(level, prefix, message) {
72
73
  }
73
74
  class GroupedReporter {
74
75
  log(entry) {
75
- if (entry.data && entry.data.target && entry.data.target.hidden) {
76
+ if ((0, _isTargetLogEntry.isTargetLogEntry)(entry)) {
77
+ if (entry.data.target.hidden) return;
78
+ } else {
79
+ // log generic entries (not related to target)
80
+ if (this.shouldLog(entry) && entry.msg.trim()) {
81
+ this.logStream.write(format(entry.level, "", entry.msg));
82
+ }
76
83
  return;
77
84
  }
78
- if (entry.data && entry.data.target) {
79
- if (!this.logEntries.has(entry.data.target.id)) {
80
- this.logEntries.set(entry.data.target.id, []);
81
- }
82
- this.logEntries.get(entry.data.target.id).push(entry);
85
+ // save the logs for errors (regardless of level)
86
+ const targetId = entry.data.target.id;
87
+ if (!this.logEntries.has(targetId)) {
88
+ this.logEntries.set(targetId, []);
83
89
  }
84
- if (this.options.logLevel >= entry.level) {
85
- if (this.options.grouped && entry.data?.target) {
86
- return this.logTargetEntryByGroup(entry);
90
+ this.logEntries.get(targetId).push(entry);
91
+ if (this.shouldLog(entry)) {
92
+ if (this.options.grouped) {
93
+ this.logTargetEntryByGroup(entry);
94
+ } else {
95
+ this.logEntry(entry);
87
96
  }
88
- return this.logTargetEntry(entry);
97
+ }
98
+ // If it's a status message for non-failure completion, delete the target's entries to free memory
99
+ if ((0, _isTargetLogEntry.isTargetStatusData)(entry.data) && (0, _isCompletionStatus.isNonFailureCompletionStatus)(entry.data.status)) {
100
+ this.logEntries.delete(targetId);
89
101
  }
90
102
  }
91
- /** Print the entry for a target */ logTargetEntry(entry) {
103
+ /**
104
+ * Whether the entry should be logged based solely on its level compared to the reporter's `logLevel`
105
+ * (does not consider `entry.target.hidden` or message presence)
106
+ */ shouldLog(entry) {
107
+ return this.options.logLevel >= entry.level;
108
+ }
109
+ /** Print the entry for a target */ logEntry(entry) {
92
110
  const colorFn = colors[entry.level];
93
111
  const data = entry.data;
94
- if (!data?.target) {
95
- if (entry.msg.trim()) {
96
- this.logStream.write(format(entry.level, "", entry.msg));
97
- }
98
- return;
99
- }
100
112
  const { target } = data;
101
113
  const { packageName, task } = target;
102
114
  const prefix = this.options.grouped ? "" : getTaskLogPrefix(packageName ?? "<root>", task);
103
- if (!(0, _isTargetStatusLogEntry.isTargetStatusLogEntry)(data)) {
115
+ if (!(0, _isTargetLogEntry.isTargetStatusData)(data)) {
104
116
  return this.logStream.write(format(entry.level, prefix, colorFn("| " + entry.msg)));
105
117
  }
106
118
  const { hash, duration, memoryUsage, status } = data;
@@ -129,15 +141,13 @@ class GroupedReporter {
129
141
  const data = entry.data;
130
142
  const target = data.target;
131
143
  const { id } = target;
132
- this.groupedEntries.set(id, this.groupedEntries.get(id) || []);
133
- this.groupedEntries.get(id)?.push(entry);
134
- if ((0, _isTargetStatusLogEntry.isTargetStatusLogEntry)(data)) {
144
+ if ((0, _isTargetLogEntry.isTargetStatusData)(data)) {
135
145
  if (data.status === "success" || data.status === "failed" || data.status === "skipped" || data.status === "aborted") {
136
146
  const { status, duration } = data;
137
147
  this.logStream.write(this.formatGroupStart(data.target.packageName ?? "<root>", data.target.task, status, duration));
138
- const entries = this.groupedEntries.get(id);
148
+ const entries = this.logEntries.get(id);
139
149
  for (const targetEntry of entries){
140
- this.logTargetEntry(targetEntry);
150
+ this.logEntry(targetEntry);
141
151
  }
142
152
  this.logStream.write(this.formatGroupEnd());
143
153
  }
@@ -168,14 +178,13 @@ class GroupedReporter {
168
178
  this.logStream.write(format(_logger.LogLevel.info, "", `Took a total of ${formattedDuration} to complete`));
169
179
  }
170
180
  constructor(options){
181
+ var _options;
171
182
  _define_property(this, "options", void 0);
172
183
  _define_property(this, "logStream", void 0);
173
- _define_property(this, "logEntries", void 0);
174
- _define_property(this, "groupedEntries", void 0);
184
+ /** Mapping from targetId log entries (the logs will be cleared for non-failed completed targets) */ _define_property(this, "logEntries", void 0);
175
185
  this.options = options;
176
186
  this.logEntries = new Map();
177
- this.groupedEntries = new Map();
178
- options.logLevel = options.logLevel || _logger.LogLevel.info;
187
+ (_options = options).logLevel ?? (_options.logLevel = _logger.LogLevel.info);
179
188
  this.logStream = options.logStream || process.stdout;
180
189
  }
181
190
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/GroupedReporter.ts"],"sourcesContent":["import { formatHrtime } from \"./formatDuration.js\";\nimport { isTargetStatusLogEntry } from \"./isTargetStatusLogEntry.js\";\nimport { LogLevel, type LogStructuredData } from \"@lage-run/logger\";\nimport chalk from \"chalk\";\nimport type { Reporter, LogEntry } from \"@lage-run/logger\";\nimport type { SchedulerRunSummary, TargetRun } from \"@lage-run/scheduler-types\";\nimport type { TargetLogData, TargetStatusData } from \"./types/TargetLogData.js\";\nimport type { Writable } from \"stream\";\nimport { slowestTargetRuns } from \"./slowestTargetRuns.js\";\nimport { formatMemoryUsage } from \"./formatHelpers.js\";\nimport { statusColorFn } from \"./LogReporter.js\";\n\nexport const colors = {\n [LogLevel.info]: chalk.white,\n [LogLevel.verbose]: chalk.gray,\n [LogLevel.warn]: chalk.white,\n [LogLevel.error]: chalk.white,\n [LogLevel.silly]: chalk.green,\n task: chalk.cyan,\n pkg: chalk.magenta,\n ok: chalk.green,\n error: chalk.red,\n warn: chalk.yellow,\n};\n\nconst logLevelLabel = {\n [LogLevel.info]: \"INFO\",\n [LogLevel.warn]: \"WARN\",\n [LogLevel.error]: \"ERR!\",\n [LogLevel.silly]: \"SILLY\",\n [LogLevel.verbose]: \"VERB\",\n};\n\nfunction getTaskLogPrefix(pkg: string, task: string): string {\n return `${colors.pkg(pkg)} ${colors.task(task)}`;\n}\n\nfunction format(level: LogLevel, prefix: string, message: string): string {\n return `${logLevelLabel[level]}: ${prefix} ${message}\\n`;\n}\n\n/**\n * Abstract reporter which optionally groups log entries by target.\n * If grouping is enabled, it only flushes a target's log entries when it completes.\n */\nexport abstract class GroupedReporter implements Reporter {\n protected logStream: Writable;\n protected logEntries = new Map<string, LogEntry[]>();\n private readonly groupedEntries: Map<string, LogEntry<LogStructuredData>[]> = new Map<string, LogEntry[]>();\n\n constructor(\n protected options: {\n logLevel?: LogLevel;\n grouped?: boolean;\n /** Whether to capture and report main process memory usage on target completion */\n logMemory?: boolean;\n /** stream for testing */\n logStream?: Writable;\n }\n ) {\n options.logLevel = options.logLevel || LogLevel.info;\n this.logStream = options.logStream || process.stdout;\n }\n\n public log(entry: LogEntry<any>): boolean | void {\n if (entry.data && entry.data.target && entry.data.target.hidden) {\n return;\n }\n\n if (entry.data && entry.data.target) {\n if (!this.logEntries.has(entry.data.target.id)) {\n this.logEntries.set(entry.data.target.id, []);\n }\n\n this.logEntries.get(entry.data.target.id)!.push(entry);\n }\n\n if (this.options.logLevel! >= entry.level) {\n if (this.options.grouped && entry.data?.target) {\n return this.logTargetEntryByGroup(entry);\n }\n\n return this.logTargetEntry(entry);\n }\n }\n\n /** Print the entry for a target */\n protected logTargetEntry(entry: LogEntry<TargetLogData>): boolean | void {\n const colorFn = colors[entry.level];\n const data = entry.data!;\n\n if (!data?.target) {\n if (entry.msg.trim()) {\n this.logStream.write(format(entry.level, \"\", entry.msg));\n }\n return;\n }\n\n const { target } = data;\n const { packageName, task } = target;\n const prefix = this.options.grouped ? \"\" : getTaskLogPrefix(packageName ?? \"<root>\", task);\n\n if (!isTargetStatusLogEntry(data)) {\n return this.logStream.write(format(entry.level, prefix, colorFn(\"| \" + entry.msg)));\n }\n\n const { hash, duration, memoryUsage, status } = data as TargetStatusData;\n const mem = formatMemoryUsage(memoryUsage, this.options.logMemory);\n\n const pkgTask = this.options.grouped ? `${chalk.magenta(packageName)} ${chalk.cyan(task)}` : \"\";\n\n switch (status) {\n case \"running\":\n return this.logStream.write(format(entry.level, prefix, colorFn(`${colors.ok(\"➔\")} start ${pkgTask}`)));\n\n case \"success\":\n return this.logStream.write(\n format(entry.level, prefix, colorFn(`${colors.ok(\"✓\")} done ${pkgTask} - ${formatHrtime(duration!)}${mem}`))\n );\n\n case \"failed\":\n return this.logStream.write(format(entry.level, prefix, colorFn(`${colors.error(\"✖\")} fail ${pkgTask}${mem}`)));\n\n case \"skipped\":\n return this.logStream.write(format(entry.level, prefix, colorFn(`${colors.ok(\"»\")} skip ${pkgTask} - ${hash!}${mem}`)));\n\n case \"aborted\":\n return this.logStream.write(format(entry.level, prefix, colorFn(`${colors.warn(\"-\")} aborted ${pkgTask}`)));\n\n case \"queued\":\n return this.logStream.write(format(entry.level, prefix, colorFn(`${colors.warn(\"…\")} queued ${pkgTask}`)));\n\n case \"pending\":\n return;\n\n default:\n throw new Error(`Internal error: unhandled target status \"${status}\"`);\n }\n }\n\n private logTargetEntryByGroup(entry: LogEntry<TargetLogData>) {\n const data = entry.data!;\n\n const target = data.target;\n const { id } = target;\n\n this.groupedEntries.set(id, this.groupedEntries.get(id) || []);\n this.groupedEntries.get(id)?.push(entry);\n\n if (isTargetStatusLogEntry(data)) {\n if (data.status === \"success\" || data.status === \"failed\" || data.status === \"skipped\" || data.status === \"aborted\") {\n const { status, duration } = data;\n this.logStream.write(this.formatGroupStart(data.target.packageName ?? \"<root>\", data.target.task, status, duration));\n\n const entries = this.groupedEntries.get(id)! as LogEntry<TargetStatusData>[];\n for (const targetEntry of entries) {\n this.logTargetEntry(targetEntry);\n }\n\n this.logStream.write(this.formatGroupEnd());\n }\n }\n }\n\n public summarize(schedulerRunSummary: SchedulerRunSummary): void {\n const { targetRuns, targetRunByStatus } = schedulerRunSummary;\n const { failed, aborted, skipped, success, pending } = targetRunByStatus;\n\n this.writeSummaryHeader();\n\n if (targetRuns.size > 0) {\n const slowestTargets = slowestTargetRuns([...targetRuns.values()]);\n\n for (const wrappedTarget of slowestTargets) {\n const { target, status, duration } = wrappedTarget;\n\n const colorFn = statusColorFn[status] ?? chalk.white;\n\n this.logStream.write(\n format(\n LogLevel.info,\n getTaskLogPrefix(target.packageName || \"[GLOBAL]\", target.task),\n colorFn(`${status}${duration ? `, took ${formatHrtime(duration)}` : \"\"}`)\n )\n );\n }\n\n this.logStream.write(\n `[Tasks Count] success: ${success.length}, skipped: ${skipped.length}, pending: ${pending.length}, aborted: ${aborted.length}\\n`\n );\n } else {\n this.logStream.write(\"Nothing has been run.\\n\");\n }\n\n this.writeSummaryFooter();\n\n if (failed.length > 0) {\n this.writeFailures(failed, targetRuns);\n }\n\n const formattedDuration = formatHrtime(schedulerRunSummary.duration);\n this.logStream.write(format(LogLevel.info, \"\", `Took a total of ${formattedDuration} to complete`));\n }\n\n /** Returns the opening line for a grouped target log block, including trailing newline. */\n protected abstract formatGroupStart(packageName: string, task: string, status: string, duration?: [number, number]): string;\n\n /** Returns the closing line for a grouped target log block, including trailing newline. */\n protected abstract formatGroupEnd(): string;\n\n /** Writes the summary section header. */\n protected abstract writeSummaryHeader(): void;\n\n /** Writes anything needed after the summary target list (e.g. closing a group). */\n protected abstract writeSummaryFooter(): void;\n\n /** Writes per-CI-system error annotations for all failed targets. */\n protected abstract writeFailures(failed: string[], targetRuns: Map<string, TargetRun<unknown>>): void;\n}\n"],"names":["GroupedReporter","colors","LogLevel","info","chalk","white","verbose","gray","warn","error","silly","green","task","cyan","pkg","magenta","ok","red","yellow","logLevelLabel","getTaskLogPrefix","format","level","prefix","message","log","entry","data","target","hidden","logEntries","has","id","set","get","push","options","logLevel","grouped","logTargetEntryByGroup","logTargetEntry","colorFn","msg","trim","logStream","write","packageName","isTargetStatusLogEntry","hash","duration","memoryUsage","status","mem","formatMemoryUsage","logMemory","pkgTask","formatHrtime","Error","groupedEntries","formatGroupStart","entries","targetEntry","formatGroupEnd","summarize","schedulerRunSummary","targetRuns","targetRunByStatus","failed","aborted","skipped","success","pending","writeSummaryHeader","size","slowestTargets","slowestTargetRuns","values","wrappedTarget","statusColorFn","length","writeSummaryFooter","writeFailures","formattedDuration","Map","process","stdout"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/GroupedReporter.ts"],"sourcesContent":["import { formatHrtime } from \"./formatDuration.js\";\nimport { isTargetLogEntry, isTargetStatusData } from \"./isTargetLogEntry.js\";\nimport { LogLevel } from \"@lage-run/logger\";\nimport chalk from \"chalk\";\nimport type { SchedulerRunSummary, TargetRun } from \"@lage-run/scheduler-types\";\nimport type { Writable } from \"stream\";\nimport { slowestTargetRuns } from \"./slowestTargetRuns.js\";\nimport { formatMemoryUsage } from \"./formatHelpers.js\";\nimport { statusColorFn } from \"./LogReporter.js\";\nimport type { MaybeTargetLogEntry, TargetLogEntry, TargetReporter } from \"./types/TargetReporter.js\";\nimport { isNonFailureCompletionStatus } from \"./isCompletionStatus.js\";\n\nexport const colors = {\n [LogLevel.info]: chalk.white,\n [LogLevel.verbose]: chalk.gray,\n [LogLevel.warn]: chalk.white,\n [LogLevel.error]: chalk.white,\n [LogLevel.silly]: chalk.green,\n task: chalk.cyan,\n pkg: chalk.magenta,\n ok: chalk.green,\n error: chalk.red,\n warn: chalk.yellow,\n};\n\nconst logLevelLabel = {\n [LogLevel.info]: \"INFO\",\n [LogLevel.warn]: \"WARN\",\n [LogLevel.error]: \"ERR!\",\n [LogLevel.silly]: \"SILLY\",\n [LogLevel.verbose]: \"VERB\",\n};\n\nfunction getTaskLogPrefix(pkg: string, task: string): string {\n return `${colors.pkg(pkg)} ${colors.task(task)}`;\n}\n\nfunction format(level: LogLevel, prefix: string, message: string): string {\n return `${logLevelLabel[level]}: ${prefix} ${message}\\n`;\n}\n\nexport interface GroupedReporterOptions {\n /** Only report logs with this level or numerically lower/logically higher (default info) */\n logLevel?: LogLevel;\n\n /** Whether to group log entries by target */\n grouped?: boolean;\n\n /** Whether to capture and report main process memory usage on target completion */\n logMemory?: boolean;\n\n /** stream for testing (defaults to stdout) */\n logStream?: Writable;\n}\n\n/**\n * Abstract reporter which optionally groups log entries by target.\n * If grouping is enabled, it only flushes a target's log entries when it completes.\n */\nexport abstract class GroupedReporter implements TargetReporter {\n protected logStream: Writable;\n /** Mapping from targetId log entries (the logs will be cleared for non-failed completed targets) */\n protected logEntries = new Map<string, TargetLogEntry[]>();\n\n constructor(protected options: GroupedReporterOptions) {\n options.logLevel ??= LogLevel.info;\n this.logStream = options.logStream || process.stdout;\n }\n\n public log(entry: MaybeTargetLogEntry): void {\n if (isTargetLogEntry(entry)) {\n if (entry.data.target.hidden) return;\n } else {\n // log generic entries (not related to target)\n if (this.shouldLog(entry) && entry.msg.trim()) {\n this.logStream.write(format(entry.level, \"\", entry.msg));\n }\n return;\n }\n\n // save the logs for errors (regardless of level)\n const targetId = entry.data.target.id;\n if (!this.logEntries.has(targetId)) {\n this.logEntries.set(targetId, []);\n }\n this.logEntries.get(targetId)!.push(entry);\n\n if (this.shouldLog(entry)) {\n if (this.options.grouped) {\n this.logTargetEntryByGroup(entry);\n } else {\n this.logEntry(entry);\n }\n }\n\n // If it's a status message for non-failure completion, delete the target's entries to free memory\n if (isTargetStatusData(entry.data) && isNonFailureCompletionStatus(entry.data.status)) {\n this.logEntries.delete(targetId);\n }\n }\n\n /**\n * Whether the entry should be logged based solely on its level compared to the reporter's `logLevel`\n * (does not consider `entry.target.hidden` or message presence)\n */\n protected shouldLog(entry: MaybeTargetLogEntry): boolean {\n return this.options.logLevel! >= entry.level;\n }\n\n /** Print the entry for a target */\n protected logEntry(entry: TargetLogEntry): boolean | void {\n const colorFn = colors[entry.level];\n\n const data = entry.data;\n const { target } = data;\n const { packageName, task } = target;\n const prefix = this.options.grouped ? \"\" : getTaskLogPrefix(packageName ?? \"<root>\", task);\n\n if (!isTargetStatusData(data)) {\n return this.logStream.write(format(entry.level, prefix, colorFn(\"| \" + entry.msg)));\n }\n\n const { hash, duration, memoryUsage, status } = data;\n const mem = formatMemoryUsage(memoryUsage, this.options.logMemory);\n\n const pkgTask = this.options.grouped ? `${chalk.magenta(packageName)} ${chalk.cyan(task)}` : \"\";\n\n switch (status) {\n case \"running\":\n return this.logStream.write(format(entry.level, prefix, colorFn(`${colors.ok(\"➔\")} start ${pkgTask}`)));\n\n case \"success\":\n return this.logStream.write(\n format(entry.level, prefix, colorFn(`${colors.ok(\"✓\")} done ${pkgTask} - ${formatHrtime(duration!)}${mem}`))\n );\n\n case \"failed\":\n return this.logStream.write(format(entry.level, prefix, colorFn(`${colors.error(\"✖\")} fail ${pkgTask}${mem}`)));\n\n case \"skipped\":\n return this.logStream.write(format(entry.level, prefix, colorFn(`${colors.ok(\"»\")} skip ${pkgTask} - ${hash!}${mem}`)));\n\n case \"aborted\":\n return this.logStream.write(format(entry.level, prefix, colorFn(`${colors.warn(\"-\")} aborted ${pkgTask}`)));\n\n case \"queued\":\n return this.logStream.write(format(entry.level, prefix, colorFn(`${colors.warn(\"…\")} queued ${pkgTask}`)));\n\n case \"pending\":\n return;\n\n default:\n throw new Error(`Internal error: unhandled target status \"${status}\"`);\n }\n }\n\n private logTargetEntryByGroup(entry: TargetLogEntry) {\n const data = entry.data;\n\n const target = data.target;\n const { id } = target;\n\n if (isTargetStatusData(data)) {\n if (data.status === \"success\" || data.status === \"failed\" || data.status === \"skipped\" || data.status === \"aborted\") {\n const { status, duration } = data;\n this.logStream.write(this.formatGroupStart(data.target.packageName ?? \"<root>\", data.target.task, status, duration));\n\n const entries = this.logEntries.get(id)!;\n for (const targetEntry of entries) {\n this.logEntry(targetEntry);\n }\n\n this.logStream.write(this.formatGroupEnd());\n }\n }\n }\n\n public summarize(schedulerRunSummary: SchedulerRunSummary): void {\n const { targetRuns, targetRunByStatus } = schedulerRunSummary;\n const { failed, aborted, skipped, success, pending } = targetRunByStatus;\n\n this.writeSummaryHeader();\n\n if (targetRuns.size > 0) {\n const slowestTargets = slowestTargetRuns([...targetRuns.values()]);\n\n for (const wrappedTarget of slowestTargets) {\n const { target, status, duration } = wrappedTarget;\n\n const colorFn = statusColorFn[status] ?? chalk.white;\n\n this.logStream.write(\n format(\n LogLevel.info,\n getTaskLogPrefix(target.packageName || \"[GLOBAL]\", target.task),\n colorFn(`${status}${duration ? `, took ${formatHrtime(duration)}` : \"\"}`)\n )\n );\n }\n\n this.logStream.write(\n `[Tasks Count] success: ${success.length}, skipped: ${skipped.length}, pending: ${pending.length}, aborted: ${aborted.length}\\n`\n );\n } else {\n this.logStream.write(\"Nothing has been run.\\n\");\n }\n\n this.writeSummaryFooter();\n\n if (failed.length > 0) {\n this.writeFailures(failed, targetRuns);\n }\n\n const formattedDuration = formatHrtime(schedulerRunSummary.duration);\n this.logStream.write(format(LogLevel.info, \"\", `Took a total of ${formattedDuration} to complete`));\n }\n\n /** Returns the opening line for a grouped target log block, including trailing newline. */\n protected abstract formatGroupStart(packageName: string, task: string, status: string, duration?: [number, number]): string;\n\n /** Returns the closing line for a grouped target log block, including trailing newline. */\n protected abstract formatGroupEnd(): string;\n\n /** Writes the summary section header. */\n protected abstract writeSummaryHeader(): void;\n\n /** Writes anything needed after the summary target list (e.g. closing a group). */\n protected abstract writeSummaryFooter(): void;\n\n /** Writes per-CI-system error annotations for all failed targets. */\n protected abstract writeFailures(failed: string[], targetRuns: Map<string, TargetRun<unknown>>): void;\n}\n"],"names":["GroupedReporter","colors","LogLevel","info","chalk","white","verbose","gray","warn","error","silly","green","task","cyan","pkg","magenta","ok","red","yellow","logLevelLabel","getTaskLogPrefix","format","level","prefix","message","log","entry","isTargetLogEntry","data","target","hidden","shouldLog","msg","trim","logStream","write","targetId","id","logEntries","has","set","get","push","options","grouped","logTargetEntryByGroup","logEntry","isTargetStatusData","isNonFailureCompletionStatus","status","delete","logLevel","colorFn","packageName","hash","duration","memoryUsage","mem","formatMemoryUsage","logMemory","pkgTask","formatHrtime","Error","formatGroupStart","entries","targetEntry","formatGroupEnd","summarize","schedulerRunSummary","targetRuns","targetRunByStatus","failed","aborted","skipped","success","pending","writeSummaryHeader","size","slowestTargets","slowestTargetRuns","values","wrappedTarget","statusColorFn","length","writeSummaryFooter","writeFailures","formattedDuration","Map","process","stdout"],"mappings":"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"}
@@ -1,14 +1,13 @@
1
1
  import type { SchedulerRunSummary, TargetStatus } from "@lage-run/scheduler-types";
2
2
  import type { LogLevel } from "@lage-run/logger";
3
- import { type LogEntry, type Reporter } from "@lage-run/logger";
4
- import type { TargetLogData } from "./types/TargetLogData.js";
3
+ import type { MaybeTargetLogEntry, TargetReporter } from "./types/TargetReporter.js";
5
4
  interface JsonReporterTaskStats {
6
5
  package: string | undefined;
7
6
  task: string;
8
7
  duration: string;
9
8
  status: string;
10
9
  }
11
- /** Final entry logged by `JsonReporter.summarize()` */
10
+ /** JSON content logged by `JsonReporter.summarize()` */
12
11
  export interface JsonReporterSummaryData {
13
12
  summary: {
14
13
  duration: string;
@@ -17,19 +16,18 @@ export interface JsonReporterSummaryData {
17
16
  [status in `${TargetStatus}Targets`]?: number;
18
17
  };
19
18
  }
20
- /** `LogEntry.data` types expected by `JsonReporter` */
21
- export type JsonReporterLogData = JsonReporterSummaryData | TargetLogData;
22
19
  /**
23
- * Reporter that outputs log entries as JSON, and a final summary (`JsonReporterSummaryData`) as JSON.
20
+ * Reporter that outputs log entries to the console as JSON, and a final summary
21
+ * (`JsonReporterSummaryData`) as JSON.
24
22
  */
25
- export declare class JsonReporter implements Reporter {
23
+ export declare class JsonReporter implements TargetReporter {
26
24
  private options;
27
25
  constructor(options: {
28
26
  logLevel: LogLevel;
29
27
  indented: boolean;
30
28
  logMemory?: boolean;
31
29
  });
32
- log(entry: LogEntry<TargetLogData>): void;
30
+ log(entry: MaybeTargetLogEntry): void;
33
31
  summarize(schedulerRunSummary: SchedulerRunSummary): void;
34
32
  }
35
33
  export {};
@@ -9,6 +9,7 @@ Object.defineProperty(exports, "JsonReporter", {
9
9
  }
10
10
  });
11
11
  const _formatDuration = require("./formatDuration.js");
12
+ const _isTargetLogEntry = require("./isTargetLogEntry.js");
12
13
  function _define_property(obj, key, value) {
13
14
  if (key in obj) {
14
15
  Object.defineProperty(obj, key, {
@@ -24,7 +25,7 @@ function _define_property(obj, key, value) {
24
25
  }
25
26
  class JsonReporter {
26
27
  log(entry) {
27
- if (entry.data && entry.data.target && entry.data.target.hidden) {
28
+ if ((0, _isTargetLogEntry.isTargetLogEntry)(entry) && entry.data.target.hidden) {
28
29
  return;
29
30
  }
30
31
  if (this.options.logLevel >= entry.level) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/JsonReporter.ts"],"sourcesContent":["/* eslint-disable no-console */\n\nimport { hrToSeconds } from \"./formatDuration.js\";\nimport type { SchedulerRunSummary, TargetStatus } from \"@lage-run/scheduler-types\";\nimport type { LogLevel } from \"@lage-run/logger\";\nimport { type LogEntry, type Reporter } from \"@lage-run/logger\";\nimport type { TargetLogData } from \"./types/TargetLogData.js\";\n\ninterface JsonReporterTaskStats {\n package: string | undefined;\n task: string;\n duration: string;\n status: string;\n}\n\n/** Final entry logged by `JsonReporter.summarize()` */\nexport interface JsonReporterSummaryData {\n summary: {\n duration: string;\n taskStats: JsonReporterTaskStats[];\n } & {\n [status in `${TargetStatus}Targets`]?: number;\n };\n}\n\n/** `LogEntry.data` types expected by `JsonReporter` */\nexport type JsonReporterLogData = JsonReporterSummaryData | TargetLogData;\n\n/**\n * Reporter that outputs log entries as JSON, and a final summary (`JsonReporterSummaryData`) as JSON.\n */\nexport class JsonReporter implements Reporter {\n constructor(private options: { logLevel: LogLevel; indented: boolean; logMemory?: boolean }) {}\n\n public log(entry: LogEntry<TargetLogData>): void {\n if (entry.data && entry.data.target && entry.data.target.hidden) {\n return;\n }\n\n if (this.options.logLevel >= entry.level) {\n console.log(this.options.indented ? JSON.stringify(entry, null, 2) : JSON.stringify(entry));\n }\n }\n\n public summarize(schedulerRunSummary: SchedulerRunSummary): void {\n const { duration, targetRuns, targetRunByStatus } = schedulerRunSummary;\n\n const summary: JsonReporterSummaryData[\"summary\"] = {\n duration: hrToSeconds(duration),\n taskStats: [...targetRuns.values()].map((targetRun) => ({\n package: targetRun.target.packageName,\n task: targetRun.target.task,\n duration: hrToSeconds(targetRun.duration),\n status: targetRun.status,\n })),\n };\n\n for (const status of Object.keys(targetRunByStatus) as TargetStatus[]) {\n if (targetRunByStatus[status] && targetRunByStatus[status].length) {\n summary[`${status}Targets`] = targetRunByStatus[status].length;\n }\n }\n\n console.log(JSON.stringify({ summary }));\n }\n}\n"],"names":["JsonReporter","log","entry","data","target","hidden","options","logLevel","level","console","indented","JSON","stringify","summarize","schedulerRunSummary","duration","targetRuns","targetRunByStatus","summary","hrToSeconds","taskStats","values","map","targetRun","package","packageName","task","status","Object","keys","length"],"mappings":"AAAA,6BAA6B;;;;+BA+BhBA;;;eAAAA;;;gCA7Be;;;;;;;;;;;;;;AA6BrB,MAAMA;IAGJC,IAAIC,KAA8B,EAAQ;QAC/C,IAAIA,MAAMC,IAAI,IAAID,MAAMC,IAAI,CAACC,MAAM,IAAIF,MAAMC,IAAI,CAACC,MAAM,CAACC,MAAM,EAAE;YAC/D;QACF;QAEA,IAAI,IAAI,CAACC,OAAO,CAACC,QAAQ,IAAIL,MAAMM,KAAK,EAAE;YACxCC,QAAQR,GAAG,CAAC,IAAI,CAACK,OAAO,CAACI,QAAQ,GAAGC,KAAKC,SAAS,CAACV,OAAO,MAAM,KAAKS,KAAKC,SAAS,CAACV;QACtF;IACF;IAEOW,UAAUC,mBAAwC,EAAQ;QAC/D,MAAM,EAAEC,QAAQ,EAAEC,UAAU,EAAEC,iBAAiB,EAAE,GAAGH;QAEpD,MAAMI,UAA8C;YAClDH,UAAUI,IAAAA,2BAAW,EAACJ;YACtBK,WAAW;mBAAIJ,WAAWK,MAAM;aAAG,CAACC,GAAG,CAAC,CAACC,YAAe,CAAA;oBACtDC,SAASD,UAAUnB,MAAM,CAACqB,WAAW;oBACrCC,MAAMH,UAAUnB,MAAM,CAACsB,IAAI;oBAC3BX,UAAUI,IAAAA,2BAAW,EAACI,UAAUR,QAAQ;oBACxCY,QAAQJ,UAAUI,MAAM;gBAC1B,CAAA;QACF;QAEA,KAAK,MAAMA,UAAUC,OAAOC,IAAI,CAACZ,mBAAsC;YACrE,IAAIA,iBAAiB,CAACU,OAAO,IAAIV,iBAAiB,CAACU,OAAO,CAACG,MAAM,EAAE;gBACjEZ,OAAO,CAAC,GAAGS,OAAO,OAAO,CAAC,CAAC,GAAGV,iBAAiB,CAACU,OAAO,CAACG,MAAM;YAChE;QACF;QAEArB,QAAQR,GAAG,CAACU,KAAKC,SAAS,CAAC;YAAEM;QAAQ;IACvC;IAhCA,YAAY,AAAQZ,OAAuE,CAAE;;aAAzEA,UAAAA;IAA0E;AAiChG"}
1
+ {"version":3,"sources":["../src/JsonReporter.ts"],"sourcesContent":["/* eslint-disable no-console */\n\nimport { hrToSeconds } from \"./formatDuration.js\";\nimport type { SchedulerRunSummary, TargetStatus } from \"@lage-run/scheduler-types\";\nimport type { LogLevel } from \"@lage-run/logger\";\nimport type { MaybeTargetLogEntry, TargetReporter } from \"./types/TargetReporter.js\";\nimport { isTargetLogEntry } from \"./isTargetLogEntry.js\";\n\ninterface JsonReporterTaskStats {\n package: string | undefined;\n task: string;\n duration: string;\n status: string;\n}\n\n/** JSON content logged by `JsonReporter.summarize()` */\nexport interface JsonReporterSummaryData {\n summary: {\n duration: string;\n taskStats: JsonReporterTaskStats[];\n } & {\n [status in `${TargetStatus}Targets`]?: number;\n };\n}\n\n/**\n * Reporter that outputs log entries to the console as JSON, and a final summary\n * (`JsonReporterSummaryData`) as JSON.\n */\nexport class JsonReporter implements TargetReporter {\n constructor(private options: { logLevel: LogLevel; indented: boolean; logMemory?: boolean }) {}\n\n public log(entry: MaybeTargetLogEntry): void {\n if (isTargetLogEntry(entry) && entry.data.target.hidden) {\n return;\n }\n\n if (this.options.logLevel >= entry.level) {\n console.log(this.options.indented ? JSON.stringify(entry, null, 2) : JSON.stringify(entry));\n }\n }\n\n public summarize(schedulerRunSummary: SchedulerRunSummary): void {\n const { duration, targetRuns, targetRunByStatus } = schedulerRunSummary;\n\n const summary: JsonReporterSummaryData[\"summary\"] = {\n duration: hrToSeconds(duration),\n taskStats: [...targetRuns.values()].map((targetRun) => ({\n package: targetRun.target.packageName,\n task: targetRun.target.task,\n duration: hrToSeconds(targetRun.duration),\n status: targetRun.status,\n })),\n };\n\n for (const status of Object.keys(targetRunByStatus) as TargetStatus[]) {\n if (targetRunByStatus[status] && targetRunByStatus[status].length) {\n summary[`${status}Targets`] = targetRunByStatus[status].length;\n }\n }\n\n console.log(JSON.stringify({ summary }));\n }\n}\n"],"names":["JsonReporter","log","entry","isTargetLogEntry","data","target","hidden","options","logLevel","level","console","indented","JSON","stringify","summarize","schedulerRunSummary","duration","targetRuns","targetRunByStatus","summary","hrToSeconds","taskStats","values","map","targetRun","package","packageName","task","status","Object","keys","length"],"mappings":"AAAA,6BAA6B;;;;+BA6BhBA;;;eAAAA;;;gCA3Be;kCAIK;;;;;;;;;;;;;;AAuB1B,MAAMA;IAGJC,IAAIC,KAA0B,EAAQ;QAC3C,IAAIC,IAAAA,kCAAgB,EAACD,UAAUA,MAAME,IAAI,CAACC,MAAM,CAACC,MAAM,EAAE;YACvD;QACF;QAEA,IAAI,IAAI,CAACC,OAAO,CAACC,QAAQ,IAAIN,MAAMO,KAAK,EAAE;YACxCC,QAAQT,GAAG,CAAC,IAAI,CAACM,OAAO,CAACI,QAAQ,GAAGC,KAAKC,SAAS,CAACX,OAAO,MAAM,KAAKU,KAAKC,SAAS,CAACX;QACtF;IACF;IAEOY,UAAUC,mBAAwC,EAAQ;QAC/D,MAAM,EAAEC,QAAQ,EAAEC,UAAU,EAAEC,iBAAiB,EAAE,GAAGH;QAEpD,MAAMI,UAA8C;YAClDH,UAAUI,IAAAA,2BAAW,EAACJ;YACtBK,WAAW;mBAAIJ,WAAWK,MAAM;aAAG,CAACC,GAAG,CAAC,CAACC,YAAe,CAAA;oBACtDC,SAASD,UAAUnB,MAAM,CAACqB,WAAW;oBACrCC,MAAMH,UAAUnB,MAAM,CAACsB,IAAI;oBAC3BX,UAAUI,IAAAA,2BAAW,EAACI,UAAUR,QAAQ;oBACxCY,QAAQJ,UAAUI,MAAM;gBAC1B,CAAA;QACF;QAEA,KAAK,MAAMA,UAAUC,OAAOC,IAAI,CAACZ,mBAAsC;YACrE,IAAIA,iBAAiB,CAACU,OAAO,IAAIV,iBAAiB,CAACU,OAAO,CAACG,MAAM,EAAE;gBACjEZ,OAAO,CAAC,GAAGS,OAAO,OAAO,CAAC,CAAC,GAAGV,iBAAiB,CAACU,OAAO,CAACG,MAAM;YAChE;QACF;QAEArB,QAAQT,GAAG,CAACW,KAAKC,SAAS,CAAC;YAAEM;QAAQ;IACvC;IAhCA,YAAY,AAAQZ,OAAuE,CAAE;;aAAzEA,UAAAA;IAA0E;AAiChG"}
@@ -1,9 +1,8 @@
1
- import { LogLevel } from "@lage-run/logger";
2
1
  import chalk from "chalk";
3
2
  import type { Chalk } from "chalk";
4
- import type { Reporter, LogEntry } from "@lage-run/logger";
5
3
  import type { SchedulerRunSummary, TargetStatus } from "@lage-run/scheduler-types";
6
- import type { Writable } from "stream";
4
+ import type { MaybeTargetLogEntry, TargetReporter } from "./types/TargetReporter.js";
5
+ import type { GroupedReporterOptions } from "./GroupedReporter.js";
7
6
  /** Color scheme from lage v1's reporter and others derived from it */
8
7
  export declare const colors: {
9
8
  30: chalk.Chalk;
@@ -23,19 +22,18 @@ export declare const statusColorFn: Record<TargetStatus, Chalk>;
23
22
  * Lage v1 reporter that logs tasks without progress spinners.
24
23
  * It can either log entries immediately, or grouped when a target completes.
25
24
  */
26
- export declare class LogReporter implements Reporter {
25
+ export declare class LogReporter implements TargetReporter {
27
26
  private options;
28
27
  private logStream;
28
+ /** Mapping from targetId log entries (the logs will be cleared for non-failed completed targets) */
29
29
  private logEntries;
30
- constructor(options: {
31
- logLevel?: LogLevel;
32
- grouped?: boolean;
33
- /** Whether to capture and report main process memory usage on target completion */
34
- logMemory?: boolean;
35
- /** stream for testing */
36
- logStream?: Writable;
37
- });
38
- log(entry: LogEntry<any>): void;
30
+ constructor(options: GroupedReporterOptions);
31
+ log(entry: MaybeTargetLogEntry): void;
32
+ /**
33
+ * Whether the entry should be logged based solely on its level compared to the reporter's `logLevel`
34
+ * (does not consider `entry.target.hidden` or message presence)
35
+ */
36
+ private shouldLog;
39
37
  private printEntry;
40
38
  private print;
41
39
  private logTargetEntry;