@lage-run/reporters 0.2.41 → 0.2.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.json +46 -1
- package/CHANGELOG.md +18 -2
- package/lib/ChromeTraceEventsReporter.d.ts +0 -2
- package/lib/ChromeTraceEventsReporter.js +1 -6
- package/lib/ProgressReporter.d.ts +5 -1
- package/lib/ProgressReporter.js +18 -131
- package/lib/components/ErrorMessages.d.ts +5 -0
- package/lib/components/ErrorMessages.js +71 -0
- package/lib/components/ProgressReporterApp.d.ts +8 -0
- package/lib/components/ProgressReporterApp.js +132 -0
- package/lib/components/ProgressStatus.d.ts +7 -0
- package/lib/components/ProgressStatus.js +56 -0
- package/lib/components/SummaryInfo.d.ts +6 -0
- package/lib/components/SummaryInfo.js +79 -0
- package/lib/components/ThreadItem.d.ts +5 -0
- package/lib/components/ThreadItem.js +59 -0
- package/lib/types/progressBarTypes.d.ts +14 -0
- package/lib/types/progressBarTypes.js +4 -0
- package/package.json +2 -2
package/CHANGELOG.json
CHANGED
|
@@ -2,7 +2,52 @@
|
|
|
2
2
|
"name": "@lage-run/reporters",
|
|
3
3
|
"entries": [
|
|
4
4
|
{
|
|
5
|
-
"date": "
|
|
5
|
+
"date": "Thu, 08 Dec 2022 00:49:16 GMT",
|
|
6
|
+
"tag": "@lage-run/reporters_v0.2.43",
|
|
7
|
+
"version": "0.2.43",
|
|
8
|
+
"comments": {
|
|
9
|
+
"patch": [
|
|
10
|
+
{
|
|
11
|
+
"author": "kchau@microsoft.com",
|
|
12
|
+
"package": "@lage-run/reporters",
|
|
13
|
+
"commit": "ad281dfe8b222d949130821828a680d1c3625154",
|
|
14
|
+
"comment": "adding some more niceties to progress reporter"
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"date": "Tue, 06 Dec 2022 23:33:47 GMT",
|
|
21
|
+
"tag": "@lage-run/reporters_v0.2.42",
|
|
22
|
+
"version": "0.2.42",
|
|
23
|
+
"comments": {
|
|
24
|
+
"none": [
|
|
25
|
+
{
|
|
26
|
+
"author": "renovate@whitesourcesoftware.com",
|
|
27
|
+
"package": "@lage-run/reporters",
|
|
28
|
+
"commit": "07c1993552c81082c2717146ce0ff57a7a2eba1b",
|
|
29
|
+
"comment": "Update devDependency @types/react to v18.0.26"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"date": "Tue, 06 Dec 2022 23:28:12 GMT",
|
|
36
|
+
"tag": "@lage-run/reporters_v0.2.42",
|
|
37
|
+
"version": "0.2.42",
|
|
38
|
+
"comments": {
|
|
39
|
+
"patch": [
|
|
40
|
+
{
|
|
41
|
+
"author": "kchau@microsoft.com",
|
|
42
|
+
"package": "@lage-run/reporters",
|
|
43
|
+
"commit": "be767568d67ce73497f83900b339737df3d0e5bd",
|
|
44
|
+
"comment": "fixes an array length issue"
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"date": "Tue, 06 Dec 2022 00:48:02 GMT",
|
|
6
51
|
"tag": "@lage-run/reporters_v0.2.41",
|
|
7
52
|
"version": "0.2.41",
|
|
8
53
|
"comments": {
|
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,28 @@
|
|
|
1
1
|
# Change Log - @lage-run/reporters
|
|
2
2
|
|
|
3
|
-
This log was last generated on
|
|
3
|
+
This log was last generated on Thu, 08 Dec 2022 00:49:16 GMT and should not be manually modified.
|
|
4
4
|
|
|
5
5
|
<!-- Start content -->
|
|
6
6
|
|
|
7
|
+
## 0.2.43
|
|
8
|
+
|
|
9
|
+
Thu, 08 Dec 2022 00:49:16 GMT
|
|
10
|
+
|
|
11
|
+
### Patches
|
|
12
|
+
|
|
13
|
+
- adding some more niceties to progress reporter (kchau@microsoft.com)
|
|
14
|
+
|
|
15
|
+
## 0.2.42
|
|
16
|
+
|
|
17
|
+
Tue, 06 Dec 2022 23:28:12 GMT
|
|
18
|
+
|
|
19
|
+
### Patches
|
|
20
|
+
|
|
21
|
+
- fixes an array length issue (kchau@microsoft.com)
|
|
22
|
+
|
|
7
23
|
## 0.2.41
|
|
8
24
|
|
|
9
|
-
Tue, 06 Dec 2022 00:
|
|
25
|
+
Tue, 06 Dec 2022 00:48:02 GMT
|
|
10
26
|
|
|
11
27
|
### Patches
|
|
12
28
|
|
|
@@ -11,8 +11,6 @@ export declare class ChromeTraceEventsReporter implements Reporter {
|
|
|
11
11
|
private options;
|
|
12
12
|
logStream: Writable;
|
|
13
13
|
consoleLogStream: Writable;
|
|
14
|
-
private threads;
|
|
15
|
-
private targetIdThreadMap;
|
|
16
14
|
private events;
|
|
17
15
|
private outputFile;
|
|
18
16
|
constructor(options: ChromeTraceEventsReporterOptions);
|
|
@@ -14,9 +14,6 @@ function _interopRequireDefault(obj) {
|
|
|
14
14
|
default: obj
|
|
15
15
|
};
|
|
16
16
|
}
|
|
17
|
-
function range(len) {
|
|
18
|
-
return Array(len).fill(0).map((_, idx)=>idx + 1);
|
|
19
|
-
}
|
|
20
17
|
function hrTimeToMicroseconds(hr) {
|
|
21
18
|
return hr[0] * 1e6 + hr[1] * 1e-3;
|
|
22
19
|
}
|
|
@@ -48,7 +45,7 @@ class ChromeTraceEventsReporter {
|
|
|
48
45
|
1000
|
|
49
46
|
]),
|
|
50
47
|
pid: 1,
|
|
51
|
-
tid: targetRun.threadId
|
|
48
|
+
tid: targetRun.threadId
|
|
52
49
|
};
|
|
53
50
|
if (categorize) {
|
|
54
51
|
event.cat += `,${categorize(targetRun)}`;
|
|
@@ -62,13 +59,11 @@ class ChromeTraceEventsReporter {
|
|
|
62
59
|
constructor(options){
|
|
63
60
|
this.options = options;
|
|
64
61
|
this.consoleLogStream = process.stdout;
|
|
65
|
-
this.targetIdThreadMap = new Map();
|
|
66
62
|
this.events = {
|
|
67
63
|
traceEvents: [],
|
|
68
64
|
displayTimeUnit: "ms"
|
|
69
65
|
};
|
|
70
66
|
this.outputFile = options.outputFile ?? getTimeBasedFilename("profile");
|
|
71
|
-
this.threads = range(options.concurrency);
|
|
72
67
|
if (!_fs.default.existsSync(_path.default.dirname(this.outputFile))) {
|
|
73
68
|
_fs.default.mkdirSync(_path.default.dirname(this.outputFile), {
|
|
74
69
|
recursive: true
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
import EventEmitter from "events";
|
|
2
4
|
import type { LogEntry, Reporter } from "@lage-run/logger";
|
|
3
5
|
import type { SchedulerRunSummary } from "@lage-run/scheduler-types";
|
|
4
|
-
import EventEmitter from "events";
|
|
5
6
|
export declare class ProgressReporter implements Reporter {
|
|
7
|
+
timer: NodeJS.Timeout;
|
|
8
|
+
startTime: [number, number];
|
|
6
9
|
logEvent: EventEmitter;
|
|
7
10
|
logEntries: Map<string, LogEntry<import("@lage-run/logger").LogStructuredData>[]>;
|
|
8
11
|
constructor(options?: {
|
|
9
12
|
concurrency: number;
|
|
10
13
|
});
|
|
14
|
+
heartBeat: () => void;
|
|
11
15
|
log(entry: LogEntry<any>): void;
|
|
12
16
|
summarize(schedulerRunSummary: SchedulerRunSummary): void;
|
|
13
17
|
}
|
package/lib/ProgressReporter.js
CHANGED
|
@@ -6,10 +6,10 @@ Object.defineProperty(exports, "ProgressReporter", {
|
|
|
6
6
|
enumerable: true,
|
|
7
7
|
get: ()=>ProgressReporter
|
|
8
8
|
});
|
|
9
|
-
const
|
|
9
|
+
const _progressReporterApp = require("./components/ProgressReporterApp");
|
|
10
10
|
const _ink = require("ink");
|
|
11
|
+
const _react = /*#__PURE__*/ _interopRequireWildcard(require("react"));
|
|
11
12
|
const _events = /*#__PURE__*/ _interopRequireDefault(require("events"));
|
|
12
|
-
const _formatHrtime = require("@lage-run/format-hrtime");
|
|
13
13
|
function _interopRequireDefault(obj) {
|
|
14
14
|
return obj && obj.__esModule ? obj : {
|
|
15
15
|
default: obj
|
|
@@ -54,134 +54,6 @@ function _interopRequireWildcard(obj, nodeInterop) {
|
|
|
54
54
|
}
|
|
55
55
|
return newObj;
|
|
56
56
|
}
|
|
57
|
-
function ProgressStatus(props) {
|
|
58
|
-
const { waiting , completed , total } = props.progress;
|
|
59
|
-
const percentage = total > 0 ? `${(completed / total * 100).toFixed(2)}%` : "0%";
|
|
60
|
-
const status = `Waiting: ${waiting} | Completed: ${completed} | Total: ${total} | ${percentage}`;
|
|
61
|
-
return /*#__PURE__*/ _react.createElement(_ink.Box, null, /*#__PURE__*/ _react.createElement(_ink.Text, null, status));
|
|
62
|
-
}
|
|
63
|
-
function ThreadItem(props) {
|
|
64
|
-
const { targetId } = props;
|
|
65
|
-
return /*#__PURE__*/ _react.createElement(_ink.Box, null, targetId ? /*#__PURE__*/ _react.createElement(_ink.Text, {
|
|
66
|
-
color: "whiteBright"
|
|
67
|
-
}, "[ ", targetId, " ]") : /*#__PURE__*/ _react.createElement(_ink.Text, {
|
|
68
|
-
color: "gray"
|
|
69
|
-
}, "[ IDLE ]"));
|
|
70
|
-
}
|
|
71
|
-
function SummaryInfo(props) {
|
|
72
|
-
const { summary } = props;
|
|
73
|
-
const { schedulerRunSummary , logEntries } = summary;
|
|
74
|
-
const { targetRunByStatus , targetRuns , duration } = schedulerRunSummary;
|
|
75
|
-
const slowestTargetRuns = [
|
|
76
|
-
...targetRuns.values()
|
|
77
|
-
].sort((a, b)=>parseFloat((0, _formatHrtime.hrToSeconds)((0, _formatHrtime.hrtimeDiff)(a.duration, b.duration))));
|
|
78
|
-
const { failed , aborted , skipped , success , pending } = targetRunByStatus;
|
|
79
|
-
const errors = failed && failed.length > 0 ? new Map(failed.map((targetId)=>[
|
|
80
|
-
targetId,
|
|
81
|
-
logEntries.get(targetId) || []
|
|
82
|
-
])) : new Map();
|
|
83
|
-
return /*#__PURE__*/ _react.createElement(_ink.Box, {
|
|
84
|
-
flexDirection: "column"
|
|
85
|
-
}, /*#__PURE__*/ _react.createElement(_ink.Text, {
|
|
86
|
-
color: "greenBright"
|
|
87
|
-
}, "Summary"), /*#__PURE__*/ _react.createElement(_ink.Newline, null), /*#__PURE__*/ _react.createElement(_ink.Text, {
|
|
88
|
-
color: "yellow"
|
|
89
|
-
}, "Slowest targets"), /*#__PURE__*/ _react.createElement(_ink.Box, {
|
|
90
|
-
flexDirection: "column",
|
|
91
|
-
marginLeft: 2,
|
|
92
|
-
marginY: 1
|
|
93
|
-
}, slowestTargetRuns.slice(0, 10).filter((run)=>!run.target.hidden).map((targetRun)=>/*#__PURE__*/ _react.createElement(_ink.Text, {
|
|
94
|
-
key: targetRun.target.id
|
|
95
|
-
}, targetRun.target.id, " - ", (0, _formatHrtime.formatDuration)((0, _formatHrtime.hrToSeconds)(targetRun.duration))))), errors.size > 0 ? /*#__PURE__*/ _react.createElement(ErrorMessages, {
|
|
96
|
-
errors: errors
|
|
97
|
-
}) : null, /*#__PURE__*/ _react.createElement(_ink.Text, null, `success: ${success.length}, skipped: ${skipped.length}, pending: ${pending.length}, aborted: ${aborted.length}, failed: ${failed.length}`), /*#__PURE__*/ _react.createElement(_ink.Text, null, "Took a total of ", (0, _formatHrtime.formatDuration)((0, _formatHrtime.hrToSeconds)(duration)), " to complete."));
|
|
98
|
-
}
|
|
99
|
-
function ErrorMessages(props) {
|
|
100
|
-
const { errors } = props;
|
|
101
|
-
return /*#__PURE__*/ _react.createElement(_ink.Box, {
|
|
102
|
-
flexDirection: "column"
|
|
103
|
-
}, /*#__PURE__*/ _react.createElement(_ink.Text, {
|
|
104
|
-
color: "redBright"
|
|
105
|
-
}, "Errors"), /*#__PURE__*/ _react.createElement(_ink.Box, {
|
|
106
|
-
flexDirection: "column",
|
|
107
|
-
marginLeft: 2,
|
|
108
|
-
marginY: 1
|
|
109
|
-
}, [
|
|
110
|
-
...errors.entries()
|
|
111
|
-
].map(([targetId, logs])=>/*#__PURE__*/ _react.createElement(_ink.Box, {
|
|
112
|
-
flexDirection: "column",
|
|
113
|
-
key: `errorlogs-${targetId}`,
|
|
114
|
-
marginBottom: 1
|
|
115
|
-
}, /*#__PURE__*/ _react.createElement(_ink.Text, {
|
|
116
|
-
color: "cyanBright",
|
|
117
|
-
underline: true,
|
|
118
|
-
bold: true
|
|
119
|
-
}, targetId), /*#__PURE__*/ _react.createElement(_ink.Text, null, logs.map((entry)=>entry.msg).join("\n"))))));
|
|
120
|
-
}
|
|
121
|
-
function ReporterApp(props) {
|
|
122
|
-
const [threadInfo, setThreadInfo] = _react.useState({});
|
|
123
|
-
const [progress, setProgress] = _react.useState({
|
|
124
|
-
waiting: 0,
|
|
125
|
-
completed: 0,
|
|
126
|
-
total: 0
|
|
127
|
-
});
|
|
128
|
-
const [summary, setSummary] = _react.useState();
|
|
129
|
-
const { logEvent } = props;
|
|
130
|
-
_react.useEffect(()=>{
|
|
131
|
-
logEvent.on("status", (entry)=>{
|
|
132
|
-
const { target , threadId , status } = entry.data;
|
|
133
|
-
if (status && status === "running") {
|
|
134
|
-
setThreadInfo((threadInfo)=>({
|
|
135
|
-
...threadInfo,
|
|
136
|
-
[threadId]: target.id
|
|
137
|
-
}));
|
|
138
|
-
} else if (status === "success" || status === "aborted" || status === "failed") {
|
|
139
|
-
setThreadInfo((threadInfo)=>{
|
|
140
|
-
const newThreadInfo = {
|
|
141
|
-
...threadInfo
|
|
142
|
-
};
|
|
143
|
-
newThreadInfo[threadId] = "";
|
|
144
|
-
return newThreadInfo;
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
});
|
|
148
|
-
logEvent.on("progress", (progress)=>{
|
|
149
|
-
setProgress(progress);
|
|
150
|
-
});
|
|
151
|
-
logEvent.on("summary", (summary)=>{
|
|
152
|
-
setSummary(summary);
|
|
153
|
-
});
|
|
154
|
-
}, [
|
|
155
|
-
logEvent
|
|
156
|
-
]);
|
|
157
|
-
const idleWorkerDummyThreadInfo = new Array(props.concurrency - Object.keys(threadInfo).length).fill(0);
|
|
158
|
-
return /*#__PURE__*/ _react.createElement(_ink.Box, {
|
|
159
|
-
flexDirection: "column"
|
|
160
|
-
}, /*#__PURE__*/ _react.createElement(_ink.Text, null, "Lage running tasks"), /*#__PURE__*/ _react.createElement(_ink.Text, {
|
|
161
|
-
color: "yellow"
|
|
162
|
-
}, "[warning: this progress reporter is currently in beta and unstable]"), summary ? /*#__PURE__*/ _react.createElement(SummaryInfo, {
|
|
163
|
-
summary: summary
|
|
164
|
-
}) : /*#__PURE__*/ _react.createElement(_ink.Box, {
|
|
165
|
-
flexDirection: "column"
|
|
166
|
-
}, /*#__PURE__*/ _react.createElement(_ink.Box, {
|
|
167
|
-
flexDirection: "column",
|
|
168
|
-
marginLeft: 2,
|
|
169
|
-
marginY: 1
|
|
170
|
-
}, Object.entries(threadInfo).map(([threadId, targetId])=>{
|
|
171
|
-
return /*#__PURE__*/ _react.createElement(ThreadItem, {
|
|
172
|
-
key: threadId,
|
|
173
|
-
targetId: targetId
|
|
174
|
-
});
|
|
175
|
-
}), idleWorkerDummyThreadInfo.map((_, index)=>{
|
|
176
|
-
return /*#__PURE__*/ _react.createElement(_react.Fragment, {
|
|
177
|
-
key: `idle-${index}`
|
|
178
|
-
}, /*#__PURE__*/ _react.createElement(ThreadItem, {
|
|
179
|
-
targetId: ""
|
|
180
|
-
}));
|
|
181
|
-
})), /*#__PURE__*/ _react.createElement(ProgressStatus, {
|
|
182
|
-
progress: progress
|
|
183
|
-
})));
|
|
184
|
-
}
|
|
185
57
|
class ProgressReporter {
|
|
186
58
|
log(entry) {
|
|
187
59
|
// save the logs for errors
|
|
@@ -195,6 +67,9 @@ class ProgressReporter {
|
|
|
195
67
|
if (entry?.data?.target?.hidden) {
|
|
196
68
|
return;
|
|
197
69
|
}
|
|
70
|
+
if (entry.data && entry.data.schedulerRun) {
|
|
71
|
+
this.startTime = entry.data.schedulerRun.startTime;
|
|
72
|
+
}
|
|
198
73
|
if (entry.data && entry.data.target && typeof entry.data.threadId !== "undefined") {
|
|
199
74
|
this.logEvent.emit("status", entry);
|
|
200
75
|
}
|
|
@@ -207,15 +82,27 @@ class ProgressReporter {
|
|
|
207
82
|
schedulerRunSummary,
|
|
208
83
|
logEntries: this.logEntries
|
|
209
84
|
});
|
|
85
|
+
clearTimeout(this.timer);
|
|
210
86
|
}
|
|
211
87
|
constructor(options = {
|
|
212
88
|
concurrency: 0
|
|
213
89
|
}){
|
|
90
|
+
this.startTime = [
|
|
91
|
+
0,
|
|
92
|
+
0
|
|
93
|
+
];
|
|
214
94
|
this.logEvent = new _events.default();
|
|
215
95
|
this.logEntries = new Map();
|
|
216
|
-
|
|
96
|
+
this.heartBeat = ()=>{
|
|
97
|
+
this.logEvent.emit("heartbeat", {
|
|
98
|
+
currentTime: process.hrtime(this.startTime)
|
|
99
|
+
});
|
|
100
|
+
this.timer = setTimeout(this.heartBeat, 1000);
|
|
101
|
+
};
|
|
102
|
+
(0, _ink.render)(/*#__PURE__*/ _react.createElement(_progressReporterApp.ProgressReporterApp, {
|
|
217
103
|
logEvent: this.logEvent,
|
|
218
104
|
concurrency: options.concurrency
|
|
219
105
|
}));
|
|
106
|
+
this.timer = setTimeout(this.heartBeat, 1000);
|
|
220
107
|
}
|
|
221
108
|
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "ErrorMessages", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: ()=>ErrorMessages
|
|
8
|
+
});
|
|
9
|
+
const _react = /*#__PURE__*/ _interopRequireWildcard(require("react"));
|
|
10
|
+
const _ink = require("ink");
|
|
11
|
+
function _getRequireWildcardCache(nodeInterop) {
|
|
12
|
+
if (typeof WeakMap !== "function") return null;
|
|
13
|
+
var cacheBabelInterop = new WeakMap();
|
|
14
|
+
var cacheNodeInterop = new WeakMap();
|
|
15
|
+
return (_getRequireWildcardCache = function(nodeInterop) {
|
|
16
|
+
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
|
17
|
+
})(nodeInterop);
|
|
18
|
+
}
|
|
19
|
+
function _interopRequireWildcard(obj, nodeInterop) {
|
|
20
|
+
if (!nodeInterop && obj && obj.__esModule) {
|
|
21
|
+
return obj;
|
|
22
|
+
}
|
|
23
|
+
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
|
|
24
|
+
return {
|
|
25
|
+
default: obj
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
var cache = _getRequireWildcardCache(nodeInterop);
|
|
29
|
+
if (cache && cache.has(obj)) {
|
|
30
|
+
return cache.get(obj);
|
|
31
|
+
}
|
|
32
|
+
var newObj = {};
|
|
33
|
+
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
34
|
+
for(var key in obj){
|
|
35
|
+
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
36
|
+
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|
37
|
+
if (desc && (desc.get || desc.set)) {
|
|
38
|
+
Object.defineProperty(newObj, key, desc);
|
|
39
|
+
} else {
|
|
40
|
+
newObj[key] = obj[key];
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
newObj.default = obj;
|
|
45
|
+
if (cache) {
|
|
46
|
+
cache.set(obj, newObj);
|
|
47
|
+
}
|
|
48
|
+
return newObj;
|
|
49
|
+
}
|
|
50
|
+
function ErrorMessages(props) {
|
|
51
|
+
const { errors } = props;
|
|
52
|
+
return /*#__PURE__*/ _react.createElement(_ink.Box, {
|
|
53
|
+
flexDirection: "column"
|
|
54
|
+
}, /*#__PURE__*/ _react.createElement(_ink.Text, {
|
|
55
|
+
color: "redBright"
|
|
56
|
+
}, "Errors"), /*#__PURE__*/ _react.createElement(_ink.Box, {
|
|
57
|
+
flexDirection: "column",
|
|
58
|
+
marginLeft: 2,
|
|
59
|
+
marginY: 1
|
|
60
|
+
}, [
|
|
61
|
+
...errors.entries()
|
|
62
|
+
].map(([targetId, logs])=>/*#__PURE__*/ _react.createElement(_ink.Box, {
|
|
63
|
+
flexDirection: "column",
|
|
64
|
+
key: `errorlogs-${targetId}`,
|
|
65
|
+
marginBottom: 1
|
|
66
|
+
}, /*#__PURE__*/ _react.createElement(_ink.Text, {
|
|
67
|
+
color: "cyanBright",
|
|
68
|
+
underline: true,
|
|
69
|
+
bold: true
|
|
70
|
+
}, targetId), /*#__PURE__*/ _react.createElement(_ink.Text, null, logs.map((entry)=>entry.msg).join("\n"))))));
|
|
71
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="react" />
|
|
3
|
+
import type EventEmitter from "events";
|
|
4
|
+
export interface ProgressReporterAppProps {
|
|
5
|
+
logEvent: EventEmitter;
|
|
6
|
+
concurrency: number;
|
|
7
|
+
}
|
|
8
|
+
export declare function ProgressReporterApp(props: ProgressReporterAppProps): JSX.Element;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "ProgressReporterApp", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: ()=>ProgressReporterApp
|
|
8
|
+
});
|
|
9
|
+
const _ink = require("ink");
|
|
10
|
+
const _react = /*#__PURE__*/ _interopRequireWildcard(require("react"));
|
|
11
|
+
const _progressStatus = require("./ProgressStatus");
|
|
12
|
+
const _summaryInfo = require("./SummaryInfo");
|
|
13
|
+
const _threadItem = require("./ThreadItem");
|
|
14
|
+
function _getRequireWildcardCache(nodeInterop) {
|
|
15
|
+
if (typeof WeakMap !== "function") return null;
|
|
16
|
+
var cacheBabelInterop = new WeakMap();
|
|
17
|
+
var cacheNodeInterop = new WeakMap();
|
|
18
|
+
return (_getRequireWildcardCache = function(nodeInterop) {
|
|
19
|
+
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
|
20
|
+
})(nodeInterop);
|
|
21
|
+
}
|
|
22
|
+
function _interopRequireWildcard(obj, nodeInterop) {
|
|
23
|
+
if (!nodeInterop && obj && obj.__esModule) {
|
|
24
|
+
return obj;
|
|
25
|
+
}
|
|
26
|
+
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
|
|
27
|
+
return {
|
|
28
|
+
default: obj
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
var cache = _getRequireWildcardCache(nodeInterop);
|
|
32
|
+
if (cache && cache.has(obj)) {
|
|
33
|
+
return cache.get(obj);
|
|
34
|
+
}
|
|
35
|
+
var newObj = {};
|
|
36
|
+
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
37
|
+
for(var key in obj){
|
|
38
|
+
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
39
|
+
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|
40
|
+
if (desc && (desc.get || desc.set)) {
|
|
41
|
+
Object.defineProperty(newObj, key, desc);
|
|
42
|
+
} else {
|
|
43
|
+
newObj[key] = obj[key];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
newObj.default = obj;
|
|
48
|
+
if (cache) {
|
|
49
|
+
cache.set(obj, newObj);
|
|
50
|
+
}
|
|
51
|
+
return newObj;
|
|
52
|
+
}
|
|
53
|
+
function range(len) {
|
|
54
|
+
return Array(len).fill(0).map((_, idx)=>idx + 1);
|
|
55
|
+
}
|
|
56
|
+
function ProgressReporterApp(props) {
|
|
57
|
+
const initialThreadInfo = range(props.concurrency).reduce((acc, threadId)=>{
|
|
58
|
+
acc[threadId] = "";
|
|
59
|
+
return acc;
|
|
60
|
+
}, {});
|
|
61
|
+
const [threadInfo, setThreadInfo] = _react.useState(initialThreadInfo);
|
|
62
|
+
const [progress, setProgress] = _react.useState({
|
|
63
|
+
waiting: 0,
|
|
64
|
+
completed: 0,
|
|
65
|
+
total: 0
|
|
66
|
+
});
|
|
67
|
+
const [summary, setSummary] = _react.useState();
|
|
68
|
+
const [currentTime, setCurrentTime] = _react.useState([
|
|
69
|
+
0,
|
|
70
|
+
0
|
|
71
|
+
]);
|
|
72
|
+
const { logEvent } = props;
|
|
73
|
+
_react.useEffect(()=>{
|
|
74
|
+
logEvent.on("status", (entry)=>{
|
|
75
|
+
const { target , threadId , status } = entry.data;
|
|
76
|
+
if (status && status === "running") {
|
|
77
|
+
setThreadInfo((threadInfo)=>({
|
|
78
|
+
...threadInfo,
|
|
79
|
+
[threadId]: target.id
|
|
80
|
+
}));
|
|
81
|
+
} else if (status === "success" || status === "aborted" || status === "failed" || status === "skipped") {
|
|
82
|
+
setThreadInfo((threadInfo)=>{
|
|
83
|
+
const newThreadInfo = {
|
|
84
|
+
...threadInfo
|
|
85
|
+
};
|
|
86
|
+
newThreadInfo[threadId] = "";
|
|
87
|
+
return newThreadInfo;
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
logEvent.on("progress", (progress)=>{
|
|
92
|
+
setProgress(progress);
|
|
93
|
+
});
|
|
94
|
+
logEvent.on("summary", (summary)=>{
|
|
95
|
+
setSummary(summary);
|
|
96
|
+
});
|
|
97
|
+
logEvent.on("heartbeat", (heartbeat)=>{
|
|
98
|
+
setCurrentTime(heartbeat.currentTime);
|
|
99
|
+
});
|
|
100
|
+
}, [
|
|
101
|
+
logEvent
|
|
102
|
+
]);
|
|
103
|
+
const arrayGapLength = props.concurrency - Object.keys(threadInfo).length;
|
|
104
|
+
const idleWorkerDummyThreadInfo = arrayGapLength > 0 ? new Array(arrayGapLength).fill(0) : [];
|
|
105
|
+
return /*#__PURE__*/ _react.createElement(_ink.Box, {
|
|
106
|
+
flexDirection: "column"
|
|
107
|
+
}, /*#__PURE__*/ _react.createElement(_ink.Text, null, "Lage running tasks with ", props.concurrency, " workers"), summary ? /*#__PURE__*/ _react.createElement(_summaryInfo.SummaryInfo, {
|
|
108
|
+
summary: summary
|
|
109
|
+
}) : /*#__PURE__*/ _react.createElement(_ink.Box, {
|
|
110
|
+
flexDirection: "column"
|
|
111
|
+
}, /*#__PURE__*/ _react.createElement(_ink.Box, {
|
|
112
|
+
flexDirection: "column",
|
|
113
|
+
marginLeft: 2,
|
|
114
|
+
marginY: 1
|
|
115
|
+
}, Object.entries(threadInfo).map(([threadId, targetId])=>{
|
|
116
|
+
return /*#__PURE__*/ _react.createElement(_threadItem.ThreadItem, {
|
|
117
|
+
key: threadId,
|
|
118
|
+
threadId: threadId,
|
|
119
|
+
targetId: targetId
|
|
120
|
+
});
|
|
121
|
+
}), idleWorkerDummyThreadInfo.map((_, index)=>{
|
|
122
|
+
return /*#__PURE__*/ _react.createElement(_react.Fragment, {
|
|
123
|
+
key: `idle-${index}`
|
|
124
|
+
}, /*#__PURE__*/ _react.createElement(_threadItem.ThreadItem, {
|
|
125
|
+
threadId: "?",
|
|
126
|
+
targetId: ""
|
|
127
|
+
}));
|
|
128
|
+
})), /*#__PURE__*/ _react.createElement(_progressStatus.ProgressStatus, {
|
|
129
|
+
progress: progress,
|
|
130
|
+
currentTime: currentTime
|
|
131
|
+
})));
|
|
132
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { Progress } from "../types/progressBarTypes";
|
|
3
|
+
export interface ProgressStatusProps {
|
|
4
|
+
progress: Progress;
|
|
5
|
+
currentTime: [number, number];
|
|
6
|
+
}
|
|
7
|
+
export declare function ProgressStatus(props: ProgressStatusProps): JSX.Element;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "ProgressStatus", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: ()=>ProgressStatus
|
|
8
|
+
});
|
|
9
|
+
const _formatHrtime = require("@lage-run/format-hrtime");
|
|
10
|
+
const _ink = require("ink");
|
|
11
|
+
const _react = /*#__PURE__*/ _interopRequireWildcard(require("react"));
|
|
12
|
+
function _getRequireWildcardCache(nodeInterop) {
|
|
13
|
+
if (typeof WeakMap !== "function") return null;
|
|
14
|
+
var cacheBabelInterop = new WeakMap();
|
|
15
|
+
var cacheNodeInterop = new WeakMap();
|
|
16
|
+
return (_getRequireWildcardCache = function(nodeInterop) {
|
|
17
|
+
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
|
18
|
+
})(nodeInterop);
|
|
19
|
+
}
|
|
20
|
+
function _interopRequireWildcard(obj, nodeInterop) {
|
|
21
|
+
if (!nodeInterop && obj && obj.__esModule) {
|
|
22
|
+
return obj;
|
|
23
|
+
}
|
|
24
|
+
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
|
|
25
|
+
return {
|
|
26
|
+
default: obj
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
var cache = _getRequireWildcardCache(nodeInterop);
|
|
30
|
+
if (cache && cache.has(obj)) {
|
|
31
|
+
return cache.get(obj);
|
|
32
|
+
}
|
|
33
|
+
var newObj = {};
|
|
34
|
+
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
35
|
+
for(var key in obj){
|
|
36
|
+
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
37
|
+
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|
38
|
+
if (desc && (desc.get || desc.set)) {
|
|
39
|
+
Object.defineProperty(newObj, key, desc);
|
|
40
|
+
} else {
|
|
41
|
+
newObj[key] = obj[key];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
newObj.default = obj;
|
|
46
|
+
if (cache) {
|
|
47
|
+
cache.set(obj, newObj);
|
|
48
|
+
}
|
|
49
|
+
return newObj;
|
|
50
|
+
}
|
|
51
|
+
function ProgressStatus(props) {
|
|
52
|
+
const { waiting , completed , total } = props.progress;
|
|
53
|
+
const percentage = total > 0 ? `${(completed / total * 100).toFixed(2)}%` : "0%";
|
|
54
|
+
const status = `Waiting: ${waiting} | Completed: ${completed} | Total: ${total} | ${percentage} | ${(0, _formatHrtime.formatDuration)((0, _formatHrtime.hrToSeconds)(props.currentTime))}`;
|
|
55
|
+
return /*#__PURE__*/ _react.createElement(_ink.Box, null, /*#__PURE__*/ _react.createElement(_ink.Text, null, status));
|
|
56
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "SummaryInfo", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: ()=>SummaryInfo
|
|
8
|
+
});
|
|
9
|
+
const _formatHrtime = require("@lage-run/format-hrtime");
|
|
10
|
+
const _ink = require("ink");
|
|
11
|
+
const _react = /*#__PURE__*/ _interopRequireWildcard(require("react"));
|
|
12
|
+
const _errorMessages = require("./ErrorMessages");
|
|
13
|
+
function _getRequireWildcardCache(nodeInterop) {
|
|
14
|
+
if (typeof WeakMap !== "function") return null;
|
|
15
|
+
var cacheBabelInterop = new WeakMap();
|
|
16
|
+
var cacheNodeInterop = new WeakMap();
|
|
17
|
+
return (_getRequireWildcardCache = function(nodeInterop) {
|
|
18
|
+
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
|
19
|
+
})(nodeInterop);
|
|
20
|
+
}
|
|
21
|
+
function _interopRequireWildcard(obj, nodeInterop) {
|
|
22
|
+
if (!nodeInterop && obj && obj.__esModule) {
|
|
23
|
+
return obj;
|
|
24
|
+
}
|
|
25
|
+
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
|
|
26
|
+
return {
|
|
27
|
+
default: obj
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
var cache = _getRequireWildcardCache(nodeInterop);
|
|
31
|
+
if (cache && cache.has(obj)) {
|
|
32
|
+
return cache.get(obj);
|
|
33
|
+
}
|
|
34
|
+
var newObj = {};
|
|
35
|
+
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
36
|
+
for(var key in obj){
|
|
37
|
+
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
38
|
+
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|
39
|
+
if (desc && (desc.get || desc.set)) {
|
|
40
|
+
Object.defineProperty(newObj, key, desc);
|
|
41
|
+
} else {
|
|
42
|
+
newObj[key] = obj[key];
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
newObj.default = obj;
|
|
47
|
+
if (cache) {
|
|
48
|
+
cache.set(obj, newObj);
|
|
49
|
+
}
|
|
50
|
+
return newObj;
|
|
51
|
+
}
|
|
52
|
+
function SummaryInfo(props) {
|
|
53
|
+
const { summary } = props;
|
|
54
|
+
const { schedulerRunSummary , logEntries } = summary;
|
|
55
|
+
const { targetRunByStatus , targetRuns , duration } = schedulerRunSummary;
|
|
56
|
+
const slowestTargetRuns = [
|
|
57
|
+
...targetRuns.values()
|
|
58
|
+
].sort((a, b)=>parseFloat((0, _formatHrtime.hrToSeconds)((0, _formatHrtime.hrtimeDiff)(a.duration, b.duration))));
|
|
59
|
+
const { failed , aborted , skipped , success , pending } = targetRunByStatus;
|
|
60
|
+
const errors = failed && failed.length > 0 ? new Map(failed.map((targetId)=>[
|
|
61
|
+
targetId,
|
|
62
|
+
logEntries.get(targetId) || []
|
|
63
|
+
])) : new Map();
|
|
64
|
+
return /*#__PURE__*/ _react.createElement(_ink.Box, {
|
|
65
|
+
flexDirection: "column"
|
|
66
|
+
}, /*#__PURE__*/ _react.createElement(_ink.Text, {
|
|
67
|
+
color: "greenBright"
|
|
68
|
+
}, "Summary"), /*#__PURE__*/ _react.createElement(_ink.Newline, null), /*#__PURE__*/ _react.createElement(_ink.Text, {
|
|
69
|
+
color: "yellow"
|
|
70
|
+
}, "Slowest targets"), /*#__PURE__*/ _react.createElement(_ink.Box, {
|
|
71
|
+
flexDirection: "column",
|
|
72
|
+
marginLeft: 2,
|
|
73
|
+
marginY: 1
|
|
74
|
+
}, slowestTargetRuns.slice(0, 10).filter((run)=>!run.target.hidden).map((targetRun)=>/*#__PURE__*/ _react.createElement(_ink.Text, {
|
|
75
|
+
key: targetRun.target.id
|
|
76
|
+
}, targetRun.target.id, " - ", (0, _formatHrtime.formatDuration)((0, _formatHrtime.hrToSeconds)(targetRun.duration))))), errors.size > 0 ? /*#__PURE__*/ _react.createElement(_errorMessages.ErrorMessages, {
|
|
77
|
+
errors: errors
|
|
78
|
+
}) : null, /*#__PURE__*/ _react.createElement(_ink.Text, null, `success: ${success.length}, skipped: ${skipped.length}, pending: ${pending.length}, aborted: ${aborted.length}, failed: ${failed.length}`), /*#__PURE__*/ _react.createElement(_ink.Text, null, "Took a total of ", (0, _formatHrtime.formatDuration)((0, _formatHrtime.hrToSeconds)(duration)), " to complete."));
|
|
79
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "ThreadItem", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: ()=>ThreadItem
|
|
8
|
+
});
|
|
9
|
+
const _react = /*#__PURE__*/ _interopRequireWildcard(require("react"));
|
|
10
|
+
const _ink = require("ink");
|
|
11
|
+
function _getRequireWildcardCache(nodeInterop) {
|
|
12
|
+
if (typeof WeakMap !== "function") return null;
|
|
13
|
+
var cacheBabelInterop = new WeakMap();
|
|
14
|
+
var cacheNodeInterop = new WeakMap();
|
|
15
|
+
return (_getRequireWildcardCache = function(nodeInterop) {
|
|
16
|
+
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
|
17
|
+
})(nodeInterop);
|
|
18
|
+
}
|
|
19
|
+
function _interopRequireWildcard(obj, nodeInterop) {
|
|
20
|
+
if (!nodeInterop && obj && obj.__esModule) {
|
|
21
|
+
return obj;
|
|
22
|
+
}
|
|
23
|
+
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
|
|
24
|
+
return {
|
|
25
|
+
default: obj
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
var cache = _getRequireWildcardCache(nodeInterop);
|
|
29
|
+
if (cache && cache.has(obj)) {
|
|
30
|
+
return cache.get(obj);
|
|
31
|
+
}
|
|
32
|
+
var newObj = {};
|
|
33
|
+
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
34
|
+
for(var key in obj){
|
|
35
|
+
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
36
|
+
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|
37
|
+
if (desc && (desc.get || desc.set)) {
|
|
38
|
+
Object.defineProperty(newObj, key, desc);
|
|
39
|
+
} else {
|
|
40
|
+
newObj[key] = obj[key];
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
newObj.default = obj;
|
|
45
|
+
if (cache) {
|
|
46
|
+
cache.set(obj, newObj);
|
|
47
|
+
}
|
|
48
|
+
return newObj;
|
|
49
|
+
}
|
|
50
|
+
function ThreadItem(props) {
|
|
51
|
+
const { targetId , threadId } = props;
|
|
52
|
+
return /*#__PURE__*/ _react.createElement(_ink.Box, null, /*#__PURE__*/ _react.createElement(_ink.Box, {
|
|
53
|
+
width: "2"
|
|
54
|
+
}, /*#__PURE__*/ _react.createElement(_ink.Text, null, threadId)), targetId ? /*#__PURE__*/ _react.createElement(_ink.Text, {
|
|
55
|
+
color: "whiteBright"
|
|
56
|
+
}, targetId, " ") : /*#__PURE__*/ _react.createElement(_ink.Text, {
|
|
57
|
+
color: "gray"
|
|
58
|
+
}, "IDLE"));
|
|
59
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { LogEntry } from "@lage-run/logger";
|
|
2
|
+
import type { SchedulerRunSummary } from "@lage-run/scheduler-types";
|
|
3
|
+
export interface Progress {
|
|
4
|
+
waiting: number;
|
|
5
|
+
completed: number;
|
|
6
|
+
total: number;
|
|
7
|
+
}
|
|
8
|
+
export interface ThreadInfo {
|
|
9
|
+
[threadId: string]: string;
|
|
10
|
+
}
|
|
11
|
+
export interface SummaryWithLogs {
|
|
12
|
+
schedulerRunSummary: SchedulerRunSummary;
|
|
13
|
+
logEntries: Map<string, LogEntry[]>;
|
|
14
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lage-run/reporters",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.43",
|
|
4
4
|
"description": "Log reporters for Lage",
|
|
5
5
|
"repository": {
|
|
6
6
|
"url": "https://github.com/microsoft/lage"
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"react": "^18.2.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@types/react": "18.0.
|
|
29
|
+
"@types/react": "18.0.26",
|
|
30
30
|
"memory-streams": "0.1.3"
|
|
31
31
|
},
|
|
32
32
|
"publishConfig": {
|