dcp-worker 3.2.30-9 → 3.2.30
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/.gitlab-ci.yml +1 -0
- package/bin/dcp-worker +160 -95
- package/docs/CODEOWNERS +2 -0
- package/etc/dcp-worker-config.js +1 -1
- package/etc/dcp-worker-config.js.md5 +1 -1
- package/lib/blessed-components/index.js +1 -0
- package/lib/blessed-components/log.js +1 -0
- package/lib/blessed-components/sandboxes.js +10 -6
- package/lib/check-scheduler-version.js +1 -0
- package/lib/dashboard-tui.js +231 -0
- package/lib/default-ui-events.js +171 -0
- package/lib/pidfile.js +1 -1
- package/lib/remote-console.js +10 -2
- package/lib/startWorkerLogger.js +98 -62
- package/lib/utils.js +28 -0
- package/lib/worker-loggers/console.js +24 -108
- package/lib/worker-loggers/dashboard.js +32 -172
- package/lib/worker-loggers/event-log.js +28 -60
- package/lib/worker-loggers/logfile.js +57 -83
- package/lib/worker-loggers/syslog.js +41 -63
- package/package.json +16 -7
- package/lib/worker-loggers/common-types.js +0 -24
|
@@ -1,114 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* This worker logger uses console.log to produce
|
|
7
|
-
* simple log output.
|
|
2
|
+
* @file worker-loggers/console.js
|
|
3
|
+
* Logger interface which just logs to the node console on stdout/stderr.
|
|
4
|
+
* @author Wes Garland, wes@distributive.network
|
|
5
|
+
* @date June 2023
|
|
8
6
|
*/
|
|
7
|
+
'use strict';
|
|
9
8
|
|
|
10
|
-
require('
|
|
9
|
+
const process = require('process');
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
* Sandbox 1: Slice Completed: slice 1, 0x5b5214D48F0428669c4E: Simple Job: dt 114ms
|
|
16
|
-
* When this.enhancedDisplay is false
|
|
17
|
-
* Sandbox 1: Slice Started: 0x5b5214D48F0428669c4E68779896D29D77c42903 Simple Job
|
|
18
|
-
* Sandbox 1: Slice Completed: 0x5b5214D48F0428669c4E68779896D29D77c42903 Simple Job
|
|
19
|
-
* @type {WorkerLogger}
|
|
20
|
-
*/
|
|
21
|
-
const consoleLogger = {
|
|
22
|
-
init(worker, options) {
|
|
23
|
-
this.worker = worker;
|
|
24
|
-
this.options = Object.assign({}, options);
|
|
25
|
-
this.sliceMap = {}; // jobAddress --> ( sliceNumber, t0 )
|
|
26
|
-
this.enhancedDisplay = true; // When false, no timing, no sliceNumber, full jobAddress
|
|
27
|
-
this.truncationLength = 22; // Extra 2 for '0x'
|
|
28
|
-
},
|
|
29
|
-
|
|
30
|
-
id (sandbox, sliceNumber) {
|
|
31
|
-
if (!this.enhancedDisplay)
|
|
32
|
-
return sandbox.public ? `${sandbox.jobAddress} ${sandbox.public.name}` : `${sandbox.jobAddress}`;
|
|
33
|
-
|
|
34
|
-
const address = sandbox.jobAddress ? sandbox.jobAddress.slice(0, this.truncationLength) : 'null';
|
|
35
|
-
const baseInfo = sandbox.public ? `${address}: ${sandbox.public.name}` : `${address}:`;
|
|
36
|
-
|
|
37
|
-
if (!sliceNumber)
|
|
38
|
-
sliceNumber = sandbox.slice ? sandbox.slice.sliceNumber : 0;
|
|
39
|
-
return sliceNumber ? `slice ${sliceNumber}, ${baseInfo}` : baseInfo;
|
|
40
|
-
},
|
|
41
|
-
|
|
42
|
-
onSandboxReady(sandbox) {
|
|
43
|
-
const shortId = sandbox.id.toString(10).padStart(3);
|
|
11
|
+
exports.init = function console$$init(options)
|
|
12
|
+
{
|
|
13
|
+
const myConsole = new (require('console').Console)(process);
|
|
44
14
|
|
|
45
|
-
|
|
46
|
-
|
|
15
|
+
delete exports.init; // singleton
|
|
16
|
+
if (process.env.RAW_CONSOLE)
|
|
17
|
+
{
|
|
18
|
+
/* raw mode is used to debug node-inspect problems by dumping raw types directly to console.log */
|
|
19
|
+
exports.raw = function console$$raw(level, ...args) {
|
|
20
|
+
myConsole[level](...args);
|
|
47
21
|
};
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
console.log(` * Sandbox ${sandboxData.shortId}: Slice Started: ${this.id(sandbox)}`);
|
|
58
|
-
},
|
|
59
|
-
|
|
60
|
-
sandbox$onSliceProgress(sandbox, sandboxData, ev) {
|
|
61
|
-
// something
|
|
62
|
-
},
|
|
63
|
-
|
|
64
|
-
sandbox$onSliceFinish(sandbox, sandboxData, ev) {
|
|
65
|
-
const sliceInfo = this.sliceMap[sandbox.id];
|
|
66
|
-
if (sliceInfo && this.enhancedDisplay)
|
|
67
|
-
console.log(` * Sandbox ${sandboxData.shortId}: Slice Completed: ${this.id(sandbox, sliceInfo.slice)}: dt ${Date.now() - sliceInfo.t0}ms`);
|
|
68
|
-
else
|
|
69
|
-
console.log(` * Sandbox ${sandboxData.shortId}: Slice Completed: ${this.id(sandbox)}`);
|
|
70
|
-
},
|
|
71
|
-
|
|
72
|
-
sandbox$onWorkerStop(sandbox, sandboxData, ev) {
|
|
73
|
-
const sliceInfo = this.sliceMap[sandbox.id];
|
|
74
|
-
delete this.sliceMap[sandbox.id];
|
|
75
|
-
console.log(` * Sandbox ${sandboxData.shortId}: Terminated: ${this.id(sandbox, sliceInfo?.slice)}`);
|
|
76
|
-
},
|
|
77
|
-
|
|
78
|
-
onPayment({ payment }) {
|
|
79
|
-
try {
|
|
80
|
-
payment = parseFloat(payment);
|
|
81
|
-
} catch (e) {
|
|
82
|
-
console.error(" ! Failed to parse payment:", payment);
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (payment > 0) console.log(` * DCC Credit: ${payment.toFixed(3)}`);
|
|
87
|
-
},
|
|
88
|
-
|
|
89
|
-
onFetchingSlices() {
|
|
90
|
-
this.options.verbose && console.log(" * Fetching slices...");
|
|
91
|
-
},
|
|
92
|
-
|
|
93
|
-
onFetchedSlices(ev) {
|
|
94
|
-
this.options.verbose && console.log(" * Fetched", ev);
|
|
95
|
-
},
|
|
96
|
-
|
|
97
|
-
onFetchSlicesFailed(ev) {
|
|
98
|
-
console.log(" ! Failed to fetch slices:", ev);
|
|
99
|
-
},
|
|
100
|
-
|
|
101
|
-
onSubmitStart() {
|
|
102
|
-
this.options.verbose >= 2 && console.log(" * Submitting results...");
|
|
103
|
-
},
|
|
104
|
-
|
|
105
|
-
onSubmit() {
|
|
106
|
-
this.options.verbose >= 2 && console.log(" * Submitted");
|
|
107
|
-
},
|
|
108
|
-
|
|
109
|
-
onSubmitError(ev) {
|
|
110
|
-
console.log(" ! Failed to submit results:", ev);
|
|
111
|
-
},
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
Object.assign(exports, consoleLogger);
|
|
22
|
+
}
|
|
23
|
+
else
|
|
24
|
+
{
|
|
25
|
+
/* Log a single string to the console; conceptually very similar to other loggers */
|
|
26
|
+
exports.at = function console$$at(level, ...args) {
|
|
27
|
+
myConsole[level](args.join(' '));
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -6,183 +6,43 @@
|
|
|
6
6
|
* This worker logger uses the blessed library to create
|
|
7
7
|
* a monitoring dashboard for the worker.
|
|
8
8
|
*/
|
|
9
|
+
'use strict';
|
|
9
10
|
|
|
10
|
-
const dcpConfig = require('dcp/dcp-config');
|
|
11
|
-
const blessed = require('blessed');
|
|
12
|
-
const contrib = require('blessed-contrib');
|
|
13
11
|
const chalk = require('chalk');
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
this.worker = worker;
|
|
30
|
-
this.options = options;
|
|
31
|
-
this.totalDCCs = 0;
|
|
32
|
-
this.sliceFetchStatus = SLICE_FETCH_STATUS.IDLE;
|
|
33
|
-
exports.screen = this.screen = blessed.screen();
|
|
34
|
-
const grid = new contrib.grid({rows: 3, cols: 5, screen: this.screen});
|
|
35
|
-
|
|
36
|
-
const log = grid.set(0, 2, 2, 3, components.log, {
|
|
37
|
-
label: 'Worker Log',
|
|
38
|
-
scrollable: true,
|
|
39
|
-
alwaysScroll: true,
|
|
40
|
-
mouse: true,
|
|
41
|
-
scrollbar: {
|
|
42
|
-
bg: 'blue',
|
|
43
|
-
},
|
|
44
|
-
});
|
|
12
|
+
const _console = new (require('console').Console)(process);
|
|
13
|
+
|
|
14
|
+
exports.init = function dashboardLogger$$init(options)
|
|
15
|
+
{
|
|
16
|
+
function logWrapperFactory(logLevel)
|
|
17
|
+
{
|
|
18
|
+
const inspect = Symbol.for('nodejs.util.inspect.custom');
|
|
19
|
+
const dashboardTui = require('../dashboard-tui');
|
|
20
|
+
|
|
21
|
+
return function wrappedLogFun() {
|
|
22
|
+
if (!dashboardTui.logPane) /* no logPane => TUI not ready - fallback to console */
|
|
23
|
+
{
|
|
24
|
+
const consoleLogger = require('./console');
|
|
25
|
+
if (consoleLogger.init)
|
|
26
|
+
consoleLogger.init();
|
|
45
27
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
28
|
+
const logAt = consoleLogger.at || consoleLogger.raw;
|
|
29
|
+
logAt(logLevel, ...arguments);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const argv = Array.from(arguments);
|
|
34
|
+
for (let i in argv)
|
|
49
35
|
{
|
|
50
|
-
if (
|
|
51
|
-
|
|
36
|
+
if (argv[i] instanceof Error || (typeof argv[i] === 'object' && argv[i][inspect]))
|
|
37
|
+
argv[i] = util.inspect(argv[i]);
|
|
38
|
+
else if (logLevel === 'error' && typeof argv[i] === 'string')
|
|
39
|
+
argv[i] = chalk.red(argv[i]);
|
|
52
40
|
}
|
|
53
|
-
|
|
41
|
+
dashboardTui.logPane.log(...argv);
|
|
54
42
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
this.sandboxes = grid.set(0, 0, 2, 2, components.sandboxes, {
|
|
58
|
-
label: 'Sandboxes',
|
|
59
|
-
defaultProgressBars: this.worker.cpuCores,
|
|
60
|
-
scrollable: true,
|
|
61
|
-
alwaysScroll: true,
|
|
62
|
-
mouse: true,
|
|
63
|
-
scrollbar: {
|
|
64
|
-
bg: 'blue',
|
|
65
|
-
},
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
this.workerInfo = grid.set(2, 0, 1, 5, blessed.text);
|
|
69
|
-
this.updateWorkerInfo();
|
|
70
|
-
|
|
71
|
-
setInterval(() => this.screen.render(), 50).unref(); /* 50ms = 20 fps */
|
|
72
|
-
|
|
73
|
-
function raise(sig)
|
|
74
|
-
{
|
|
75
|
-
process.kill(process.pid, sig);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/* Apply key bindings which mimic canonical input mode */
|
|
79
|
-
this.screen.key(['C-c'], () => raise('SIGINT'));
|
|
80
|
-
this.screen.key(['C-z'], () => raise('SIGTSTP'));
|
|
81
|
-
this.screen.key(['\u001c'], () => raise('SIGQUIT')); /* C-\ */
|
|
82
|
-
|
|
83
|
-
this.screen.key(['escape'], () => {
|
|
84
|
-
console.log('Stopping worker...');
|
|
85
|
-
worker.stop();
|
|
86
|
-
});
|
|
87
|
-
},
|
|
88
|
-
|
|
89
|
-
updateWorkerInfo() {
|
|
90
|
-
const workerOptions = dcpConfig.worker;
|
|
91
|
-
|
|
92
|
-
this.workerInfo.setLabel(`Worker Status [${this.sliceFetchStatus}]`);
|
|
93
|
-
this.workerInfo.setContent([
|
|
94
|
-
chalk.green(` DCCs Earned: ${chalk.bold(this.totalDCCs.toFixed(7))}`),
|
|
95
|
-
'',
|
|
96
|
-
` Scheduler: ${chalk.yellow(dcpConfig.scheduler.location.href)}`,
|
|
97
|
-
` Bank: ${chalk.yellow(dcpConfig.bank.location.href)}`,
|
|
98
|
-
`Bank Account: ${chalk.yellow(this.worker.paymentAddress || 'Starting...')}`,
|
|
99
|
-
` Identity: ${chalk.yellow(this.worker.identityKeystore? this.worker.identityKeystore.address : 'Starting...')}`,
|
|
100
|
-
` Jobs: ${workerOptions.jobAddresses?.length ? workerOptions.jobAddresses.join(', ') : '<any>'}`,
|
|
101
|
-
` Priv Groups: ${Object.keys(workerOptions.computeGroups).length}`,
|
|
102
|
-
` Pub Group: ${workerOptions.leavePublicGroup ? 'no' : 'yes'}`,
|
|
103
|
-
].join('\n'));
|
|
104
|
-
},
|
|
105
|
-
|
|
106
|
-
onSandboxReady(sandbox) {
|
|
107
|
-
|
|
108
|
-
},
|
|
43
|
+
}
|
|
109
44
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
progress: 0,
|
|
114
|
-
label: sandbox.public.name,
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
this.sandboxes.data.push(sandboxData.progressData);
|
|
118
|
-
|
|
119
|
-
this.sandboxes.update();
|
|
120
|
-
},
|
|
121
|
-
|
|
122
|
-
sandbox$onSliceProgress(sandbox, sandboxData, ev) {
|
|
123
|
-
if (ev.indeterminate) {
|
|
124
|
-
sandboxData.progressData.progress = 100;
|
|
125
|
-
|
|
126
|
-
setTimeout(() => {
|
|
127
|
-
if (sandboxData.progressData.indeterminate) {
|
|
128
|
-
sandboxData.progressData.progress = 0;
|
|
129
|
-
this.sandboxes.update();
|
|
130
|
-
}
|
|
131
|
-
}, 500).unref();
|
|
132
|
-
} else {
|
|
133
|
-
sandboxData.progressData.progress = ev.progress;
|
|
134
|
-
sandboxData.progressData.indeterminate = false;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
this.sandboxes.update();
|
|
138
|
-
},
|
|
139
|
-
|
|
140
|
-
sandbox$onSliceFinish(sandbox, sandboxData, ev) {
|
|
141
|
-
this.sandboxes.data =
|
|
142
|
-
this.sandboxes.data.filter(d => d != sandboxData.progressData);
|
|
143
|
-
|
|
144
|
-
this.sandboxes.update();
|
|
145
|
-
},
|
|
146
|
-
|
|
147
|
-
sandbox$onWorkerStop(sandbox, sandboxData, ev) {
|
|
148
|
-
this.sandbox$onSliceFinish(sandbox, sandboxData, ev);
|
|
149
|
-
},
|
|
150
|
-
|
|
151
|
-
onPayment({ payment }) {
|
|
152
|
-
try {
|
|
153
|
-
payment = parseFloat(payment);
|
|
154
|
-
} catch (e) {
|
|
155
|
-
console.error("Failed to parse payment float:", payment);
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
try {
|
|
160
|
-
this.totalDCCs += payment;
|
|
161
|
-
this.updateWorkerInfo();
|
|
162
|
-
} catch(e) {
|
|
163
|
-
console.error(e.message);
|
|
164
|
-
}
|
|
165
|
-
},
|
|
166
|
-
|
|
167
|
-
onFetchingSlices() {
|
|
168
|
-
this.sliceFetchStatus = SLICE_FETCH_STATUS.FETCHING;
|
|
169
|
-
this.updateWorkerInfo();
|
|
170
|
-
},
|
|
171
|
-
|
|
172
|
-
onFetchedSlices(fetchedSliceCount) {
|
|
173
|
-
if (fetchedSliceCount === 0 && this.sandboxes.data.length === 0) {
|
|
174
|
-
this.sliceFetchStatus = SLICE_FETCH_STATUS.NO_WORK;
|
|
175
|
-
} else {
|
|
176
|
-
this.sliceFetchStatus = SLICE_FETCH_STATUS.WORKING;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
this.updateWorkerInfo();
|
|
180
|
-
},
|
|
181
|
-
|
|
182
|
-
onFetchSlicesFailed(ev) {
|
|
183
|
-
this.sliceFetchStatus = SLICE_FETCH_STATUS.NO_WORK;
|
|
184
|
-
this.updateWorkerInfo();
|
|
185
|
-
},
|
|
186
|
-
};
|
|
45
|
+
for (let level of ['log', 'warn', 'debug', 'info', 'error'])
|
|
46
|
+
exports[level] = logWrapperFactory(level);
|
|
47
|
+
}
|
|
187
48
|
|
|
188
|
-
Object.assign(exports, dashboardLogger);
|
|
@@ -3,65 +3,42 @@
|
|
|
3
3
|
* @author Eddie Roosenmaallen <eddie@kingsds.network>
|
|
4
4
|
* @date August 2022
|
|
5
5
|
*
|
|
6
|
-
* This logger module
|
|
7
|
-
* console logs to it.
|
|
8
|
-
* by the console logger.
|
|
9
|
-
*
|
|
10
|
-
* @TODO: This could likely be improved by handling worker events directly
|
|
11
|
-
* and emitting events to the event log more deliberately than just
|
|
12
|
-
* redirecting the base console output. ~ER20220831
|
|
6
|
+
* This logger module redirects logs to the Windows event-log, writing all
|
|
7
|
+
* console logs to it.
|
|
13
8
|
*/
|
|
9
|
+
'use strict';
|
|
14
10
|
|
|
15
|
-
require('
|
|
16
|
-
|
|
11
|
+
const os = require('os');
|
|
12
|
+
if (os.platform() !== 'win32')
|
|
13
|
+
throw new Error(`Windows Event Log module is not supported on ${os.platform()}`);
|
|
17
14
|
|
|
18
15
|
const { EventLog } = require('node-eventlog');
|
|
19
16
|
|
|
20
17
|
// Copy the original global console object's properties onto a backup
|
|
21
18
|
const _console = Object.assign({}, console);
|
|
22
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Initialize the eventlog worker logger
|
|
22
|
+
*
|
|
23
|
+
* @param {object} options Options for logger behaviour (passed
|
|
24
|
+
* through to consoleLogger)
|
|
25
|
+
*/
|
|
26
|
+
exports.init = function eventLog$$init(options)
|
|
27
|
+
{
|
|
28
|
+
exports._processName = require('path').basename(process.mainModule.filename || process.argv0);
|
|
29
|
+
const source = options.source || exports._processName || 'dcp-worker';
|
|
30
|
+
exports._eventLog = new EventLog(source);
|
|
31
|
+
require('../startWorkerLogger').inspectOptions.colors = false;
|
|
32
|
+
exports.at = log;
|
|
33
|
+
}
|
|
23
34
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
*/
|
|
32
|
-
init(worker, options) {
|
|
33
|
-
consoleLogger.init(worker, options);
|
|
34
|
-
|
|
35
|
-
this._processName = require('path').basename(process.mainModule.filename || process.argv0);
|
|
36
|
-
const source = options.source || this._processName || 'dcp-worker';
|
|
37
|
-
// _console.log(`036: creating new EventLog(${source}) client...`);
|
|
38
|
-
this._eventLog = new EventLog(source);
|
|
39
|
-
|
|
40
|
-
['debug','error','info','log','warn'].forEach(level => {
|
|
41
|
-
console[level] = (...args) => this._log(level, ...args);
|
|
42
|
-
});
|
|
43
|
-
},
|
|
44
|
-
|
|
45
|
-
_log(level, ...items) {
|
|
46
|
-
const strBuilder = [`${this._processName}[${process.pid}]:`];
|
|
47
|
-
|
|
48
|
-
items.forEach(i => {
|
|
49
|
-
try {
|
|
50
|
-
switch (typeof i) {
|
|
51
|
-
case 'object':
|
|
52
|
-
strBuilder.push(JSON.stringify(i));
|
|
53
|
-
break;
|
|
54
|
-
default:
|
|
55
|
-
strBuilder.push(String(i));
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
catch (e) {
|
|
59
|
-
if (e instanceof TypeError) {
|
|
60
|
-
strBuilder.push('[encoding error: ' + e.message + ']');
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
|
|
35
|
+
/**
|
|
36
|
+
* @param {string} level The node log level to log at
|
|
37
|
+
* @param {[string]} items An array of strings to log as a single message
|
|
38
|
+
*/
|
|
39
|
+
function log(level, ...items)
|
|
40
|
+
{
|
|
41
|
+
{
|
|
65
42
|
// Use the string log-level to look up the severity number:
|
|
66
43
|
let severity = {
|
|
67
44
|
error: 'error',
|
|
@@ -71,18 +48,9 @@ const eventlogLogger = {
|
|
|
71
48
|
debug: 'info',
|
|
72
49
|
}[level];
|
|
73
50
|
|
|
74
|
-
|
|
75
|
-
return this._eventLog.log(strBuilder.join(' '), severity).catch(error => {
|
|
51
|
+
return exports._eventLog.log(items.join(' '), severity).catch(error => {
|
|
76
52
|
if (error)
|
|
77
53
|
_console.error('255: Unexpected error writing to event log:', error);
|
|
78
54
|
});
|
|
79
55
|
}
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
// necessary to keep `this` pointing at the correct thing when we call
|
|
83
|
-
for (const [prop, value] of Object.entries(consoleLogger))
|
|
84
|
-
{
|
|
85
|
-
if (typeof value === 'function')
|
|
86
|
-
exports[prop] = value.bind(consoleLogger);
|
|
87
56
|
}
|
|
88
|
-
Object.assign(exports, eventlogLogger);
|
|
@@ -4,122 +4,96 @@
|
|
|
4
4
|
* @date August 2022
|
|
5
5
|
*
|
|
6
6
|
* This logger module maintains a log file, writing all console logs to it.
|
|
7
|
-
* Most worker events are passed through to the console logger.
|
|
8
7
|
*/
|
|
9
|
-
|
|
10
|
-
require('./common-types');
|
|
11
|
-
const consoleLogger = require('./console');
|
|
8
|
+
'use strict';
|
|
12
9
|
|
|
13
10
|
// Copy the original global console object's properties onto a backup
|
|
14
11
|
const _console = Object.assign({}, console);
|
|
15
12
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
init
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
this._getLogFile(true);
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
['debug','error','info','log','warn'].forEach(level => {
|
|
41
|
-
console[level] = (...args) => this._log(level, ...args);
|
|
42
|
-
});
|
|
43
|
-
},
|
|
13
|
+
/**
|
|
14
|
+
* Initialize the logfile worker logger
|
|
15
|
+
*
|
|
16
|
+
* @param {object} options Options for logger behaviour
|
|
17
|
+
* @param {string} options.filepath Path to worker file; default: ./dcp-worker.log
|
|
18
|
+
* @param {boolean} options.truncate If true, logfile will be cleared at worker startup
|
|
19
|
+
*/
|
|
20
|
+
exports.init = function init(options)
|
|
21
|
+
{
|
|
22
|
+
delete exports.init; // singleton
|
|
23
|
+
options.verbose >= 3 && _console.debug('050: constructing LogfileConsole', options.logfile, options);
|
|
24
|
+
getLogFile(options);
|
|
25
|
+
require('../startWorkerLogger').inspectOptions.colors = Boolean(process.env.FORCE_COLOR);
|
|
26
|
+
|
|
27
|
+
// on SIGHUP, close the output stream and open a new one
|
|
28
|
+
process.on('SIGHUP', () => {
|
|
29
|
+
getLogFile(options);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
exports.at = log;
|
|
33
|
+
}
|
|
44
34
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Return a handle to the WritableStream for this logger, creating one if
|
|
37
|
+
* necessary.
|
|
38
|
+
*
|
|
39
|
+
* @return {fs.WriteStream}
|
|
40
|
+
*/
|
|
41
|
+
function getLogFile(options)
|
|
42
|
+
{
|
|
43
|
+
{
|
|
54
44
|
const fs = require('fs');
|
|
55
45
|
|
|
56
|
-
if (
|
|
46
|
+
if (getLogFile._file)
|
|
57
47
|
{
|
|
58
|
-
if (!forceNew)
|
|
59
|
-
return this._file;
|
|
60
|
-
|
|
61
48
|
try
|
|
62
49
|
{
|
|
63
|
-
|
|
50
|
+
getLogFile._file.end();
|
|
64
51
|
}
|
|
65
52
|
catch (err)
|
|
66
53
|
{
|
|
67
54
|
console.error('061: failed to close old log file:', err);
|
|
68
55
|
}
|
|
69
|
-
|
|
56
|
+
getLogFile._file = false;
|
|
70
57
|
}
|
|
71
58
|
|
|
72
|
-
const
|
|
73
|
-
flags:
|
|
59
|
+
const fileOptions = {
|
|
60
|
+
flags: options.truncate ? 'w' : 'a', // NYI: cli --truncate
|
|
74
61
|
}
|
|
75
62
|
|
|
76
|
-
const file =
|
|
63
|
+
const file = getLogFile._file = fs.createWriteStream(options.logfile, fileOptions);
|
|
77
64
|
|
|
78
65
|
// On error, close & recreate the log file
|
|
79
66
|
file.on('error', err => {
|
|
80
67
|
_console.error('082: console-patch::LogFileConsole write error:', err);
|
|
81
68
|
|
|
82
|
-
|
|
69
|
+
getLogFile(options);
|
|
83
70
|
});
|
|
84
71
|
|
|
85
72
|
return file;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Write a log line to the output file.
|
|
77
|
+
*
|
|
78
|
+
* current outputStream.
|
|
79
|
+
* @param {string} level Log level.
|
|
80
|
+
* @param {any} ...items Items to log.
|
|
81
|
+
*/
|
|
82
|
+
function log(level, ...items)
|
|
83
|
+
{
|
|
84
|
+
{
|
|
85
|
+
const logPrefix = [
|
|
96
86
|
(new Date()).toISOString(),
|
|
97
87
|
level,
|
|
98
88
|
];
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
switch (typeof i) {
|
|
103
|
-
case 'object':
|
|
104
|
-
strBuilder.push(JSON.stringify(i));
|
|
105
|
-
default:
|
|
106
|
-
strBuilder.push(String(i));
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
catch (e) {
|
|
110
|
-
if (e instanceof TypeError) {
|
|
111
|
-
strBuilder.push('[encoding error: ' + e.message + ']');
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
});
|
|
115
|
-
|
|
89
|
+
|
|
90
|
+
const logElements = logPrefix.concat(items);
|
|
91
|
+
|
|
116
92
|
try {
|
|
117
|
-
|
|
93
|
+
getLogFile._file.write(logElements.join(' ') + '\n');
|
|
118
94
|
}
|
|
119
95
|
catch (error) {
|
|
120
96
|
_console.error('131: Unexpected error writing to log file:', error);
|
|
121
97
|
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
Object.assign(exports, consoleLogger, logfileLogger);
|
|
98
|
+
}
|
|
99
|
+
}
|