dcp-worker 3.2.30-7 → 3.2.30-9
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 +0 -1
- package/bin/dcp-worker +84 -154
- package/docs/CODEOWNERS +0 -2
- package/lib/blessed-components/index.js +0 -1
- package/lib/blessed-components/log.js +0 -1
- package/lib/check-scheduler-version.js +0 -1
- package/lib/pidfile.js +1 -1
- package/lib/remote-console.js +2 -10
- package/lib/startWorkerLogger.js +62 -95
- package/lib/worker-loggers/common-types.js +24 -0
- package/lib/worker-loggers/console.js +108 -24
- package/lib/worker-loggers/dashboard.js +173 -32
- package/lib/worker-loggers/event-log.js +60 -28
- package/lib/worker-loggers/logfile.js +83 -57
- package/lib/worker-loggers/syslog.js +63 -41
- package/package.json +5 -6
- package/lib/dashboard-tui.js +0 -184
- package/lib/default-ui-events.js +0 -187
package/lib/startWorkerLogger.js
CHANGED
|
@@ -1,127 +1,94 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @file startWorkerLogger.js
|
|
3
|
-
* Start the DCP Worker logging subsystem. Sets console.log (etc) redirection, determine
|
|
4
|
-
* the correct log target (screen, TUI, syslog, windows event log, file) and redirect the
|
|
5
|
-
* output there.
|
|
6
3
|
* @author Ryan Rossiter, ryan@kingsds.network
|
|
7
4
|
* @date April 2020
|
|
8
|
-
* @author Wes Garland, wes@distributive.network
|
|
9
5
|
*/
|
|
10
|
-
'use strict';
|
|
11
6
|
|
|
12
7
|
const process = require('process');
|
|
13
8
|
const os = require('os');
|
|
14
|
-
|
|
9
|
+
require('./worker-loggers/common-types');
|
|
15
10
|
|
|
16
11
|
/**
|
|
17
12
|
* Detects and returns the appropriate logger for the environment
|
|
18
|
-
* @param {object} options - cliArgs from worker
|
|
19
13
|
* @returns {WorkerLogger}
|
|
20
14
|
*/
|
|
21
|
-
function getLogger(
|
|
22
|
-
{
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
15
|
+
function getLogger({ outputMode='detect' }) {
|
|
16
|
+
if (outputMode === 'detect') {
|
|
17
|
+
if (process.stdout.isTTY && os.platform() !== 'win32' &&
|
|
18
|
+
process.env.LANG && process.env.LANG.match(/utf-?8/i)) {
|
|
19
|
+
outputMode = 'dashboard';
|
|
20
|
+
} else {
|
|
21
|
+
outputMode = 'console';
|
|
22
|
+
}
|
|
29
23
|
}
|
|
30
24
|
|
|
31
25
|
try
|
|
32
26
|
{
|
|
33
|
-
const om = require('path').basename(
|
|
27
|
+
const om = require('path').basename(outputMode);
|
|
34
28
|
return require('./worker-loggers/' + om);
|
|
35
29
|
}
|
|
36
30
|
catch (error)
|
|
37
31
|
{
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
throw error;
|
|
32
|
+
console.error(`032: Failed to load worker logger "${outputMode}":`, error);
|
|
33
|
+
throw new Error(`Unknown outputMode "${outputMode}"`);
|
|
41
34
|
}
|
|
42
35
|
}
|
|
43
36
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
37
|
+
const workerEvents = {
|
|
38
|
+
fetchStart: 'onFetchingSlices',
|
|
39
|
+
fetchEnd: 'onFetchedSlices',
|
|
40
|
+
fetchError: 'onFetchSlicesFailed',
|
|
41
|
+
submit: 'onSubmit',
|
|
42
|
+
submitError: 'onSubmitError',
|
|
43
|
+
payment: 'onPayment',
|
|
44
|
+
}
|
|
45
|
+
const supervisorEvents = {
|
|
46
|
+
submittingResult: 'onSubmitStart',
|
|
47
|
+
}
|
|
48
|
+
const sandboxEvents = {
|
|
49
|
+
start: 'sandbox$onSliceStart',
|
|
50
|
+
sliceProgress: 'sandbox$onSliceProgress',
|
|
51
|
+
sliceFinish: 'sandbox$onSliceFinish',
|
|
52
|
+
terminated: 'sandbox$onWorkerStop',
|
|
53
|
+
}
|
|
58
54
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
*
|
|
62
|
-
* .
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
* . raw: same as at, but arguments are not formatted
|
|
70
|
-
* . any: write a log message without regard to log level
|
|
71
|
-
*
|
|
72
|
-
* All of these functions, with the exception of raw, receive only string arguments.
|
|
55
|
+
Object.assign(exports, {
|
|
56
|
+
/**
|
|
57
|
+
* This method will attach event listeners from the provided
|
|
58
|
+
* worker to a worker logger. The logger to use is
|
|
59
|
+
* determined by getLogger based on the environment.
|
|
60
|
+
*
|
|
61
|
+
* @param {Worker} worker
|
|
62
|
+
* @param {object} options
|
|
63
|
+
* @param {number} options.verbose
|
|
64
|
+
* @param {boolean} options.outputMode - which logger to use (default='detect')
|
|
73
65
|
*/
|
|
66
|
+
startWorkerLogger(worker, options={}) {
|
|
67
|
+
const logger = getLogger(options);
|
|
68
|
+
logger.init(worker, options);
|
|
74
69
|
|
|
75
|
-
|
|
76
|
-
{
|
|
77
|
-
if (logger[level])
|
|
78
|
-
console[level] = (...args) => logger[level]( ...format(...args));
|
|
79
|
-
else if (logger.at)
|
|
80
|
-
console[level] = (...args) => logger.at(level, ...format(...args));
|
|
81
|
-
else if (logger.raw)
|
|
82
|
-
console[level] = (...args) => logger.raw(level, ...args);
|
|
83
|
-
else if (logger.any)
|
|
84
|
-
console[level] = (...args) => logger.any(`${level}:`, format(...args));
|
|
85
|
-
else
|
|
70
|
+
for (const [ev, handler] of Object.entries(workerEvents))
|
|
86
71
|
{
|
|
87
|
-
|
|
88
|
-
|
|
72
|
+
if (typeof logger[handler] === 'function')
|
|
73
|
+
worker.on(ev, logger[handler].bind(logger));
|
|
89
74
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
require('./remote-console').reintercept();
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Format console.log arguments for use by a non-native logger, eg syslog. All non-string arguments are
|
|
97
|
-
* converted into the best human-readable strings we can muster.
|
|
98
|
-
*/
|
|
99
|
-
function format(...argv)
|
|
100
|
-
{
|
|
101
|
-
for (let i in argv)
|
|
102
|
-
{
|
|
103
|
-
try
|
|
75
|
+
for (const [ev, handler] of Object.entries(supervisorEvents))
|
|
104
76
|
{
|
|
105
|
-
if (typeof
|
|
106
|
-
|
|
107
|
-
if (typeof argv[i] === 'object')
|
|
108
|
-
argv[i] = util.inspect(argv[i], exports.inspectOptions);
|
|
109
|
-
if (typeof argv[i] !== 'string')
|
|
110
|
-
argv[i] = String(argv[i]);
|
|
77
|
+
if (typeof logger[handler] === 'function')
|
|
78
|
+
worker.addSupervisorEventListener(ev, logger[handler].bind(logger));
|
|
111
79
|
}
|
|
112
|
-
catch(e)
|
|
113
|
-
{
|
|
114
|
-
if (e instanceof TypeError)
|
|
115
|
-
argv[i] = '[encoding error: ' + e.message + ']';
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
80
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
81
|
+
worker.on('sandbox', (sandbox) => {
|
|
82
|
+
/**
|
|
83
|
+
* logger.onSandboxStart can return a data object that will be provided to
|
|
84
|
+
* the other sandbox event handlers
|
|
85
|
+
*/
|
|
86
|
+
const data = logger.onSandboxReady(sandbox) || {};
|
|
87
|
+
for (const [ev, handler] of Object.entries(sandboxEvents))
|
|
88
|
+
{
|
|
89
|
+
if (typeof logger[handler] === 'function')
|
|
90
|
+
sandbox.on(ev, logger[handler].bind(logger, sandbox, data));
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef WorkerLogger
|
|
3
|
+
* @property {onSandboxReady} onSandboxReady
|
|
4
|
+
* @property {function} onPayment
|
|
5
|
+
* @property {function} onFetchingSlices
|
|
6
|
+
* @property {function} onFetchedSlices
|
|
7
|
+
* @property {function} onFetchSlicesFailed
|
|
8
|
+
* @property {SandboxCallback} sandbox$onSliceStart
|
|
9
|
+
* @property {SandboxCallback} sandbox$onSliceProgress
|
|
10
|
+
* @property {SandboxCallback} sandbox$onSliceFinish
|
|
11
|
+
* @property {SandboxCallback} sandbox$onWorkerStop
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @typedef {function} onSandboxReady
|
|
16
|
+
* @param {Sandbox} sandbox
|
|
17
|
+
* @returns {object} workerData
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @typedef {function} SandboxCallback
|
|
22
|
+
* @param {Sandbox} sandbox
|
|
23
|
+
* @param {object} workerData
|
|
24
|
+
*/
|
|
@@ -1,30 +1,114 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* @file worker-loggers/console.js
|
|
3
|
+
* @author Ryan Rossiter, ryan@kingsds.network
|
|
4
|
+
* @date April 2020
|
|
5
|
+
*
|
|
6
|
+
* This worker logger uses console.log to produce
|
|
7
|
+
* simple log output.
|
|
6
8
|
*/
|
|
7
|
-
'use strict';
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
require('./common-types');
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
/**
|
|
13
|
+
* When this.enhancedDisplay is true
|
|
14
|
+
* Sandbox 1: Slice Started: slice 1, 0x5b5214D48F0428669c4E: Simple Job
|
|
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
|
+
},
|
|
14
29
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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);
|
|
44
|
+
|
|
45
|
+
const sandboxData = {
|
|
46
|
+
shortId,
|
|
28
47
|
};
|
|
29
|
-
|
|
30
|
-
}
|
|
48
|
+
|
|
49
|
+
console.log(` * Sandbox ${sandboxData.shortId}: Initialized`);
|
|
50
|
+
|
|
51
|
+
return sandboxData;
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
sandbox$onSliceStart(sandbox, sandboxData, ev) {
|
|
55
|
+
const sliceNumber = sandbox.slice ? sandbox.slice.sliceNumber : 0;
|
|
56
|
+
this.sliceMap[sandbox.id] = { slice: sliceNumber, t0: Date.now() };
|
|
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);
|
|
@@ -6,42 +6,183 @@
|
|
|
6
6
|
* This worker logger uses the blessed library to create
|
|
7
7
|
* a monitoring dashboard for the worker.
|
|
8
8
|
*/
|
|
9
|
-
'use strict';
|
|
10
9
|
|
|
10
|
+
const dcpConfig = require('dcp/dcp-config');
|
|
11
|
+
const blessed = require('blessed');
|
|
12
|
+
const contrib = require('blessed-contrib');
|
|
11
13
|
const chalk = require('chalk');
|
|
12
|
-
const
|
|
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();
|
|
14
|
+
const util = require('util');
|
|
27
15
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
16
|
+
const components = require('../blessed-components');
|
|
17
|
+
require('./common-types');
|
|
18
|
+
|
|
19
|
+
const SLICE_FETCH_STATUS = {
|
|
20
|
+
IDLE: chalk.yellow('Idle'),
|
|
21
|
+
FETCHING: chalk.blue('Fetching Work...'),
|
|
22
|
+
WORKING: chalk.green('Working'),
|
|
23
|
+
NO_WORK: chalk.red('No Work Available'),
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** @type {WorkerLogger} */
|
|
27
|
+
const dashboardLogger = {
|
|
28
|
+
init(worker, options) {
|
|
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
|
+
});
|
|
45
|
+
|
|
46
|
+
console.log = console.error = console.warn = console.info = console.debug = function logWrapper() {
|
|
47
|
+
arguments = Array.from(arguments);
|
|
48
|
+
for (let i in arguments)
|
|
35
49
|
{
|
|
36
|
-
if (
|
|
37
|
-
|
|
38
|
-
else if (logLevel === 'error' && typeof argv[i] === 'string')
|
|
39
|
-
argv[i] = chalk.red(argv[i]);
|
|
50
|
+
if (arguments[i] instanceof Error)
|
|
51
|
+
arguments[i] = util.inspect(arguments[i]);
|
|
40
52
|
}
|
|
41
|
-
|
|
53
|
+
log.log.apply(log, arguments);
|
|
42
54
|
}
|
|
43
|
-
|
|
55
|
+
require('../remote-console').reintercept();
|
|
44
56
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
+
},
|
|
109
|
+
|
|
110
|
+
sandbox$onSliceStart(sandbox, sandboxData, slice) {
|
|
111
|
+
sandboxData.progressData = {
|
|
112
|
+
indeterminate: true,
|
|
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
|
+
};
|
|
187
|
+
|
|
188
|
+
Object.assign(exports, dashboardLogger);
|
|
@@ -3,42 +3,65 @@
|
|
|
3
3
|
* @author Eddie Roosenmaallen <eddie@kingsds.network>
|
|
4
4
|
* @date August 2022
|
|
5
5
|
*
|
|
6
|
-
* This logger module
|
|
7
|
-
* console logs to it.
|
|
6
|
+
* This logger module emits events to the Windows event-log, writing all
|
|
7
|
+
* console logs to it. Most worker events are passed through to be handled
|
|
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
|
|
8
13
|
*/
|
|
9
|
-
'use strict';
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
throw new Error(`Windows Event Log module is not supported on ${os.platform()}`);
|
|
15
|
+
require('./common-types');
|
|
16
|
+
const consoleLogger = require('./console');
|
|
14
17
|
|
|
15
18
|
const { EventLog } = require('node-eventlog');
|
|
16
19
|
|
|
17
20
|
// Copy the original global console object's properties onto a backup
|
|
18
21
|
const _console = Object.assign({}, console);
|
|
19
22
|
|
|
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
|
-
}
|
|
34
23
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
{
|
|
41
|
-
|
|
24
|
+
const eventlogLogger = {
|
|
25
|
+
/**
|
|
26
|
+
* Initialize the eventlog worker logger
|
|
27
|
+
*
|
|
28
|
+
* @param {Worker} worker DCP Worker object to log
|
|
29
|
+
* @param {object} options Options for logger behaviour (passed
|
|
30
|
+
* through to consoleLogger)
|
|
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
|
+
|
|
42
65
|
// Use the string log-level to look up the severity number:
|
|
43
66
|
let severity = {
|
|
44
67
|
error: 'error',
|
|
@@ -48,9 +71,18 @@ function log(level, ...items)
|
|
|
48
71
|
debug: 'info',
|
|
49
72
|
}[level];
|
|
50
73
|
|
|
51
|
-
|
|
74
|
+
// _console.debug(`074: about to actually log a line:`, strBuilder, severity);
|
|
75
|
+
return this._eventLog.log(strBuilder.join(' '), severity).catch(error => {
|
|
52
76
|
if (error)
|
|
53
77
|
_console.error('255: Unexpected error writing to event log:', error);
|
|
54
78
|
});
|
|
55
79
|
}
|
|
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);
|
|
56
87
|
}
|
|
88
|
+
Object.assign(exports, eventlogLogger);
|