From 0483ac8ae9956d175da76285bbdf26d40db76b7a Mon Sep 17 00:00:00 2001 From: Rob Russo Date: Thu, 8 Jul 2021 14:24:30 -0400 Subject: [PATCH 01/28] adding settings that will allow direct control over the protocols and ports used to connect to the workers. --- README.md | 8 ++++++++ htdocs/js/pages/JobDetails.class.js | 8 ++++---- lib/api/config.js | 2 ++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e0705d2b..c851a944 100644 --- a/README.md +++ b/README.md @@ -607,6 +607,14 @@ Setting this parameter to `true` will force Cronicle's Web UI to connect to the This property only takes effect if [web_direct_connect](#web_direct_connect) is also set to `true`. +### web_connect_proto + +This controls the protocol used to connect to workers. It should mirror the setup used in the workers WebServer section. + +### web_connect_port + +This controls the port used to connect to workers. It should mirror the setup used in the workers WebServer section. + ### socket_io_transports This is an advanced configuration property that you will probably never need to worry about. This allows you to customize the [socket.io transports](https://socket.io/docs/client-api/) used to connect to the server for real-time updates. By default, this property is set internally to an array containing the `websocket` transport only, e.g. diff --git a/htdocs/js/pages/JobDetails.class.js b/htdocs/js/pages/JobDetails.class.js index 10c9a156..6191d129 100644 --- a/htdocs/js/pages/JobDetails.class.js +++ b/htdocs/js/pages/JobDetails.class.js @@ -865,14 +865,14 @@ Class.subclass( Page.Base, "Page.JobDetails", { html += ''; // live job log tail - var remote_api_url = app.proto + job.hostname + ':' + app.port + config.base_api_uri; + var remote_api_url = config.worker_connect_proto + job.hostname + ':' + config.worker_connect_port + config.base_api_uri; if (config.custom_live_log_socket_url) { // custom websocket URL for single-master systems behind an LB remote_api_url = config.custom_live_log_socket_url + config.base_api_uri; } else if (!config.web_socket_use_hostnames && app.servers && app.servers[job.hostname] && app.servers[job.hostname].ip) { // use ip if available, may work better in some setups - remote_api_url = app.proto + app.servers[job.hostname].ip + ':' + app.port + config.base_api_uri; + remote_api_url = config.worker_connect_proto + app.servers[job.hostname].ip + ':' + config.worker_connect_port + config.base_api_uri; } html += '
'; @@ -1044,14 +1044,14 @@ Class.subclass( Page.Base, "Page.JobDetails", { var chunk_count = 0; var error_shown = false; - var url = app.proto + job.hostname + ':' + app.port; + var url = config.worker_connect_proto + job.hostname + ':' + config.worker_connect_port; if (config.custom_live_log_socket_url) { // custom websocket URL for single-master systems behind an LB url = config.custom_live_log_socket_url; } else if (!config.web_socket_use_hostnames && app.servers && app.servers[job.hostname] && app.servers[job.hostname].ip) { // use ip if available, may work better in some setups - url = app.proto + app.servers[job.hostname].ip + ':' + app.port; + url = config.worker_connect_proto + app.servers[job.hostname].ip + ':' + config.worker_connect_port; } $('#d_live_job_log').append( diff --git a/lib/api/config.js b/lib/api/config.js index f8f34a3f..07c0d3a2 100644 --- a/lib/api/config.js +++ b/lib/api/config.js @@ -36,6 +36,8 @@ module.exports = Class.create({ external_user_api: this.usermgr.config.get('external_user_api') || '', web_socket_use_hostnames: this.server.config.get('web_socket_use_hostnames') || 0, web_direct_connect: this.server.config.get('web_direct_connect') || 0, + worker_connect_proto: this.server.config.get('worker_connect_proto') || 'http', + worker_connect_port: this.server.config.get('worker_connect_port') || '3012', socket_io_transports: this.server.config.get('socket_io_transports') || 0 } ), port: args.request.headers.ssl ? this.web.config.get('https_port') : this.web.config.get('http_port'), From 9a7ebd7515475deeecc3667c7a2c920afb85de35 Mon Sep 17 00:00:00 2001 From: Rob Russo Date: Thu, 8 Jul 2021 14:26:53 -0400 Subject: [PATCH 02/28] update version number --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f812c419..09885783 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "Cronicle", - "version": "0.8.62", + "version": "0.8.63", "description": "A simple, distributed task scheduler and runner with a web based UI.", "author": "Joseph Huckaby ", "homepage": "https://github.com/jhuckaby/Cronicle", From 18dc7f8e037c07db1418c3fe93d30d7875d5a071 Mon Sep 17 00:00:00 2001 From: Rob Russo Date: Thu, 8 Jul 2021 14:27:37 -0400 Subject: [PATCH 03/28] add example config --- sample_conf/config.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sample_conf/config.json b/sample_conf/config.json index 0af18d1e..f44cdd65 100644 --- a/sample_conf/config.json +++ b/sample_conf/config.json @@ -30,6 +30,8 @@ "server_comm_use_hostnames": false, "web_direct_connect": false, "web_socket_use_hostnames": false, + "worker_connect_proto": "http", + "worker_connect_port": 3012, "job_memory_max": 1073741824, "job_memory_sustain": 0, From fa2b80ca1266918eeb330273917b5b0b72f7a65e Mon Sep 17 00:00:00 2001 From: Rob Russo Date: Thu, 8 Jul 2021 14:43:27 -0400 Subject: [PATCH 04/28] fix proto string --- htdocs/js/pages/JobDetails.class.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/js/pages/JobDetails.class.js b/htdocs/js/pages/JobDetails.class.js index 6191d129..0fd65dc9 100644 --- a/htdocs/js/pages/JobDetails.class.js +++ b/htdocs/js/pages/JobDetails.class.js @@ -865,14 +865,14 @@ Class.subclass( Page.Base, "Page.JobDetails", { html += '
'; // live job log tail - var remote_api_url = config.worker_connect_proto + job.hostname + ':' + config.worker_connect_port + config.base_api_uri; + var remote_api_url = config.worker_connect_proto + '://' + job.hostname + ':' + config.worker_connect_port + config.base_api_uri; if (config.custom_live_log_socket_url) { // custom websocket URL for single-master systems behind an LB remote_api_url = config.custom_live_log_socket_url + config.base_api_uri; } else if (!config.web_socket_use_hostnames && app.servers && app.servers[job.hostname] && app.servers[job.hostname].ip) { // use ip if available, may work better in some setups - remote_api_url = config.worker_connect_proto + app.servers[job.hostname].ip + ':' + config.worker_connect_port + config.base_api_uri; + remote_api_url = config.worker_connect_proto + '://' + app.servers[job.hostname].ip + ':' + config.worker_connect_port + config.base_api_uri; } html += '
'; @@ -1044,14 +1044,14 @@ Class.subclass( Page.Base, "Page.JobDetails", { var chunk_count = 0; var error_shown = false; - var url = config.worker_connect_proto + job.hostname + ':' + config.worker_connect_port; + var url = config.worker_connect_proto + '://' + job.hostname + ':' + config.worker_connect_port; if (config.custom_live_log_socket_url) { // custom websocket URL for single-master systems behind an LB url = config.custom_live_log_socket_url; } else if (!config.web_socket_use_hostnames && app.servers && app.servers[job.hostname] && app.servers[job.hostname].ip) { // use ip if available, may work better in some setups - url = config.worker_connect_proto + app.servers[job.hostname].ip + ':' + config.worker_connect_port; + url = config.worker_connect_proto + '://' + app.servers[job.hostname].ip + ':' + config.worker_connect_port; } $('#d_live_job_log').append( From 148fec2a6a387e063acc58f315f6d2e8a723133b Mon Sep 17 00:00:00 2001 From: Rob Russo Date: Fri, 9 Jul 2021 11:20:47 -0400 Subject: [PATCH 05/28] implement pull through proxy --- README.md | 8 +- htdocs/js/pages/JobDetails.class.js | 123 ++++++++++------------------ lib/api/config.js | 3 +- lib/api/job.js | 65 +++++++++++++++ sample_conf/config.json | 3 +- 5 files changed, 111 insertions(+), 91 deletions(-) diff --git a/README.md b/README.md index c851a944..bef43bb4 100644 --- a/README.md +++ b/README.md @@ -607,13 +607,9 @@ Setting this parameter to `true` will force Cronicle's Web UI to connect to the This property only takes effect if [web_direct_connect](#web_direct_connect) is also set to `true`. -### web_connect_proto +### worker_proxy_logs -This controls the protocol used to connect to workers. It should mirror the setup used in the workers WebServer section. - -### web_connect_port - -This controls the port used to connect to workers. It should mirror the setup used in the workers WebServer section. +Use this setting to force live log polling to occur as a pull through proxy on the master. ### socket_io_transports diff --git a/htdocs/js/pages/JobDetails.class.js b/htdocs/js/pages/JobDetails.class.js index 0fd65dc9..70768709 100644 --- a/htdocs/js/pages/JobDetails.class.js +++ b/htdocs/js/pages/JobDetails.class.js @@ -531,6 +531,7 @@ Class.subclass( Page.Base, "Page.JobDetails", { ], backgroundColor: [ (cpu_avg < jcm*0.5) ? this.pie_colors.cool : + (cpu_avg < jcm*0.5) ? this.pie_colors.cool : ((cpu_avg < jcm*0.75) ? this.pie_colors.warm : this.pie_colors.hot), this.pie_colors.empty ], @@ -865,20 +866,25 @@ Class.subclass( Page.Base, "Page.JobDetails", { html += '
'; // live job log tail - var remote_api_url = config.worker_connect_proto + '://' + job.hostname + ':' + config.worker_connect_port + config.base_api_uri; + var remote_api_url = app.proto + '://' + job.hostname + ':' + app.port + config.base_api_uri; + var job_log_function = "get_live_job_log" if (config.custom_live_log_socket_url) { // custom websocket URL for single-master systems behind an LB remote_api_url = config.custom_live_log_socket_url + config.base_api_uri; } else if (!config.web_socket_use_hostnames && app.servers && app.servers[job.hostname] && app.servers[job.hostname].ip) { // use ip if available, may work better in some setups - remote_api_url = config.worker_connect_proto + '://' + app.servers[job.hostname].ip + ':' + config.worker_connect_port + config.base_api_uri; + remote_api_url = app.proto + '://' + app.servers[job.hostname].ip + ':' + app.port + config.base_api_uri; + } + else if (config.worker_proxy_logs) { + // Use master address instead + remote_api_url = "" + job_log_function = "api_get_live_job_log_proxy" } html += '
'; html += 'Live Job Event Log'; - html += ''; - html += ''; + html += ''; html += '
'; html += '
'; @@ -1040,91 +1046,46 @@ Class.subclass( Page.Base, "Page.JobDetails", { start_live_log_watcher: function(job) { // open special websocket to target server for live log feed var self = this; - var $cont = null; - var chunk_count = 0; - var error_shown = false; + var $cont = $('#d_live_job_log'); - var url = config.worker_connect_proto + '://' + job.hostname + ':' + config.worker_connect_port; + var url = app.proto + '://' + job.hostname + ':' + app.port; + var job_log_function = "get_live_job_log_tail" if (config.custom_live_log_socket_url) { // custom websocket URL for single-master systems behind an LB url = config.custom_live_log_socket_url; } else if (!config.web_socket_use_hostnames && app.servers && app.servers[job.hostname] && app.servers[job.hostname].ip) { // use ip if available, may work better in some setups - url = config.worker_connect_proto + '://' + app.servers[job.hostname].ip + ':' + config.worker_connect_port; + url = app.proto + '://' + app.servers[job.hostname].ip + ':' + app.port; } - - $('#d_live_job_log').append( - '
Log Watcher: Connecting to server: ' + url + '...
' - ); - - this.socket = io( url, { - forceNew: true, - transports: config.socket_io_transports || ['websocket'], - reconnection: true, - reconnectionDelay: 1000, - reconnectionDelayMax: 5000, - reconnectionAttempts: 9999, - timeout: 5000 - } ); - - this.socket.on('connect', function() { - Debug.trace("JobDetails socket.io connected successfully: " + url); - - // cache this for later - $cont = $('#d_live_job_log'); - - $cont.append( - '
Log Watcher: Connected successfully!
' - ); - - // get auth token from master server (uses session) - app.api.post( 'app/get_log_watch_auth', { id: job.id }, function(resp) { - // now request log watch stream on target server - self.socket.emit( 'watch_job_log', { - token: resp.token, - id: job.id - } ); - }); // api.post - } ); - this.socket.on('connect_error', function(err) { - Debug.trace("JobDetails socket.io connect error: " + err); - $('#d_live_job_log').append( - '
Log Watcher: Server Connect Error: ' + err + ' (' + url + ')
' - ); - error_shown = true; - } ); - this.socket.on('connect_timeout', function(err) { - Debug.trace("JobDetails socket.io connect timeout"); - if (!error_shown) $('#d_live_job_log').append( - '
Log Watcher: Server Connect Timeout: ' + err + ' (' + url + ')
' - ); - } ); - this.socket.on('reconnect', function() { - Debug.trace("JobDetails socket.io reconnected successfully"); - } ); - - this.socket.on('log_data', function(lines) { - // received log data, as array of lines - var scroll_y = $cont.scrollTop(); - var scroll_max = Math.max(0, $cont.prop('scrollHeight') - $cont.height()); - var need_scroll = ((scroll_max - scroll_y) <= 10); - - $cont.append( - '
' + 
-					lines.map( function(line) { return line.replace(/' 
-			);
-			
-			// only show newest 1K chunks
-			chunk_count++;
-			if (chunk_count >= 1000) {
-				$cont.children().first().remove();
-				chunk_count--;
-			}
-			
-			if (need_scroll) $cont.scrollTop( $cont.prop('scrollHeight') );
-		} );
+		else if (config.worker_proxy_logs) {
+			// Use master address instead
+			url = app.proto + '://' + config.base_api_uri + ':' + app.port
+			job_log_function = "api_get_live_job_log_proxy"
+		}
+
+		self.curr_live_log_job = job.id;
+
+		// poll live_console api until job is running or some error occur
+		function refresh() {
+			if(self.curr_live_log_job != job.id) return; // prevent double logging
+			app.api.post(url + '/api/app/job_log_function', { id: job.id, tail: parseInt(app.config.ui.live_log_tail_size) || 80 }
+				, (data) => {  // success callback
+					if (!data.data) return; // stop polling if no data
+					$cont.append('
' + data.data + '
'); + pollInterval = parseInt(app.config.ui.live_log) + if(!pollInterval || pollInterval < 1000) pollInterval = 1000; + setTimeout(refresh, 1000); + } + // stop polling on error, report unexpected errors + , (e) => { + if(e.code != 'job') console.error('Live log poll error: ', e) + return + } + ) + } + + refresh(); }, update_live_progress: function(job) { diff --git a/lib/api/config.js b/lib/api/config.js index 07c0d3a2..a547c5e0 100644 --- a/lib/api/config.js +++ b/lib/api/config.js @@ -36,8 +36,7 @@ module.exports = Class.create({ external_user_api: this.usermgr.config.get('external_user_api') || '', web_socket_use_hostnames: this.server.config.get('web_socket_use_hostnames') || 0, web_direct_connect: this.server.config.get('web_direct_connect') || 0, - worker_connect_proto: this.server.config.get('worker_connect_proto') || 'http', - worker_connect_port: this.server.config.get('worker_connect_port') || '3012', + worker_proxy_logs: this.server.config.get('worker_proxy_logs') || 0, socket_io_transports: this.server.config.get('socket_io_transports') || 0 } ), port: args.request.headers.ssl ? this.web.config.get('https_port') : this.web.config.get('http_port'), diff --git a/lib/api/job.js b/lib/api/job.js index fe96d8f9..a1513289 100644 --- a/lib/api/job.js +++ b/lib/api/job.js @@ -5,6 +5,7 @@ var fs = require('fs'); var assert = require("assert"); var async = require('async'); +var readLastLines = require('read-last-lines'); var Class = require("pixl-class"); var Tools = require("pixl-tools"); @@ -81,6 +82,70 @@ module.exports = Class.create({ callback( "200 OK", headers, stream ); } ); }, + + api_get_live_job_log_proxy: function(args, callback) { + // get live job logs from a remote worker + // client API, no auth + var self = this; + + self.loadSession(args, function (err, session, user) { + if (err) return self.doError('session', err.message, callback); + if (!self.requireValidUser(session, user, callback)) return; + + let params = Tools.mergeHashes(args.params, args.query); + if (!self.requireParams(params, { + id: /^\w+$/ + }, callback)) return; + + var job = self.findJob(query); + if (!job) return self.doError('job', "Failed to locate job: " + query.id, callback); + + var api_url = this.getServerBaseAPIURL( slave.hostname, slave.ip ) + '/app/get_live_job_log'; + var tailSize = parseInt(params.tail) || 80; + var auth = Tools.digestHex(params.id + self.server.config.get('secret_key')) + var reqParams = { id: job.id, tail: tailSize, download: params.download || 0, auth: auth } + + self.request.json(api_url, reqParams, (err, resp, data) => { + if (err) return self.doError('job', "Failed to fetch live job log: " + err.message, callback); + data.hostname = job.hostname; + data.event_title = job.event_title; + callback(data); + }); + }); + }, + + api_get_live_log_tail: function (args, callback) { + // internal api, runs on target machine + const self = this; + + let params = Tools.mergeHashes(args.params, args.query); + + if (!this.requireParams(params, { + id: /^\w+$/, + auth: /^\w+$/ + }, callback)) return; + + if (params.auth != Tools.digestHex(params.id + self.server.config.get('secret_key'))) { + return callback("403 Forbidden", {}, "Authentication failure.\n"); + } + + // see if log file exists on this server + var log_file = self.server.config.get('log_dir') + '/jobs/' + params.id + '.log'; + + let tailSize = parseInt(params.tail) || 80; + if (params.download == 1) { // read entire file + fs.readFile(log_file, { encoding: 'utf-8' }, (err, data) => { + if (err) return self.doError('job', "Failed to fetch job log: invalid or completed job", callback); + callback({ data: data }); + }); + + } + else { + readLastLines.read(log_file, tailSize ) + .then( lines => callback({data: lines})) + .catch(e => { return self.doError('job', "Failed to fetch job log: invalid or completed job", callback)}) + } + }, api_get_live_job_log: function(args, callback) { // get live job job, as it is being written diff --git a/sample_conf/config.json b/sample_conf/config.json index f44cdd65..2643fb97 100644 --- a/sample_conf/config.json +++ b/sample_conf/config.json @@ -30,8 +30,7 @@ "server_comm_use_hostnames": false, "web_direct_connect": false, "web_socket_use_hostnames": false, - "worker_connect_proto": "http", - "worker_connect_port": 3012, + "worker_proxy_logs": false, "job_memory_max": 1073741824, "job_memory_sustain": 0, From 948bde4798f8e07e710bd2eb1b49fa5763d59dab Mon Sep 17 00:00:00 2001 From: Rob Russo Date: Fri, 9 Jul 2021 11:22:51 -0400 Subject: [PATCH 06/28] update deps --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 09885783..cf2069a5 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,8 @@ "pixl-server-storage": "^2.0.10", "pixl-server-web": "^1.1.7", "pixl-server-api": "^1.0.2", - "pixl-server-user": "^1.0.9" + "pixl-server-user": "^1.0.9", + "read-last-lines": "^1.8.0" }, "devDependencies": { "pixl-unit": "^1.0.10" From 61c1daa903a9199d0e84e72e35492888e043e1d0 Mon Sep 17 00:00:00 2001 From: Rob Russo Date: Fri, 9 Jul 2021 11:28:33 -0400 Subject: [PATCH 07/28] fix tail size --- htdocs/js/pages/JobDetails.class.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/js/pages/JobDetails.class.js b/htdocs/js/pages/JobDetails.class.js index 70768709..79723b1b 100644 --- a/htdocs/js/pages/JobDetails.class.js +++ b/htdocs/js/pages/JobDetails.class.js @@ -1069,7 +1069,7 @@ Class.subclass( Page.Base, "Page.JobDetails", { // poll live_console api until job is running or some error occur function refresh() { if(self.curr_live_log_job != job.id) return; // prevent double logging - app.api.post(url + '/api/app/job_log_function', { id: job.id, tail: parseInt(app.config.ui.live_log_tail_size) || 80 } + app.api.post(url + '/api/app/job_log_function', { id: job.id } , (data) => { // success callback if (!data.data) return; // stop polling if no data $cont.append('
' + data.data + '
'); From 889085e7e148a40a473be3706a1c72ad242d23ed Mon Sep 17 00:00:00 2001 From: Rob Russo Date: Fri, 9 Jul 2021 11:47:41 -0400 Subject: [PATCH 08/28] fix function name --- htdocs/js/pages/JobDetails.class.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/js/pages/JobDetails.class.js b/htdocs/js/pages/JobDetails.class.js index 79723b1b..29647390 100644 --- a/htdocs/js/pages/JobDetails.class.js +++ b/htdocs/js/pages/JobDetails.class.js @@ -1069,7 +1069,7 @@ Class.subclass( Page.Base, "Page.JobDetails", { // poll live_console api until job is running or some error occur function refresh() { if(self.curr_live_log_job != job.id) return; // prevent double logging - app.api.post(url + '/api/app/job_log_function', { id: job.id } + app.api.post(url + '/api/app/' + job_log_function, { id: job.id } , (data) => { // success callback if (!data.data) return; // stop polling if no data $cont.append('
' + data.data + '
'); From da1307a05588e2951f36e553edceb2dcc4b85aee Mon Sep 17 00:00:00 2001 From: Rob Russo Date: Fri, 9 Jul 2021 11:51:55 -0400 Subject: [PATCH 09/28] debug url --- htdocs/js/pages/JobDetails.class.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/htdocs/js/pages/JobDetails.class.js b/htdocs/js/pages/JobDetails.class.js index 29647390..86f99f7c 100644 --- a/htdocs/js/pages/JobDetails.class.js +++ b/htdocs/js/pages/JobDetails.class.js @@ -1063,13 +1063,15 @@ Class.subclass( Page.Base, "Page.JobDetails", { url = app.proto + '://' + config.base_api_uri + ':' + app.port job_log_function = "api_get_live_job_log_proxy" } + var api_url = url + '/api/app/' + job_log_function + console.error(api_url) self.curr_live_log_job = job.id; // poll live_console api until job is running or some error occur function refresh() { if(self.curr_live_log_job != job.id) return; // prevent double logging - app.api.post(url + '/api/app/' + job_log_function, { id: job.id } + app.api.post(api_url, { id: job.id } , (data) => { // success callback if (!data.data) return; // stop polling if no data $cont.append('
' + data.data + '
'); From 91f8be7e48f7ba41c93f77c8cd5a3f3324891e74 Mon Sep 17 00:00:00 2001 From: Rob Russo Date: Fri, 9 Jul 2021 11:52:52 -0400 Subject: [PATCH 10/28] fix url --- htdocs/js/pages/JobDetails.class.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/htdocs/js/pages/JobDetails.class.js b/htdocs/js/pages/JobDetails.class.js index 86f99f7c..e4d1a36e 100644 --- a/htdocs/js/pages/JobDetails.class.js +++ b/htdocs/js/pages/JobDetails.class.js @@ -1060,11 +1060,10 @@ Class.subclass( Page.Base, "Page.JobDetails", { } else if (config.worker_proxy_logs) { // Use master address instead - url = app.proto + '://' + config.base_api_uri + ':' + app.port + url = config.base_api_uri job_log_function = "api_get_live_job_log_proxy" } var api_url = url + '/api/app/' + job_log_function - console.error(api_url) self.curr_live_log_job = job.id; From 52e5fa80ccc2874d9b41559b2d6349494b500587 Mon Sep 17 00:00:00 2001 From: Rob Russo Date: Fri, 9 Jul 2021 11:55:16 -0400 Subject: [PATCH 11/28] debug --- htdocs/js/pages/JobDetails.class.js | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/js/pages/JobDetails.class.js b/htdocs/js/pages/JobDetails.class.js index e4d1a36e..bcc26c24 100644 --- a/htdocs/js/pages/JobDetails.class.js +++ b/htdocs/js/pages/JobDetails.class.js @@ -1064,6 +1064,7 @@ Class.subclass( Page.Base, "Page.JobDetails", { job_log_function = "api_get_live_job_log_proxy" } var api_url = url + '/api/app/' + job_log_function + console.error(api_url) self.curr_live_log_job = job.id; From d3b416cd28bfb2fda69a6e4d69d2d5dd41260656 Mon Sep 17 00:00:00 2001 From: Rob Russo Date: Fri, 9 Jul 2021 12:01:49 -0400 Subject: [PATCH 12/28] change proxy config --- htdocs/js/pages/JobDetails.class.js | 36 +++++++++++++++-------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/htdocs/js/pages/JobDetails.class.js b/htdocs/js/pages/JobDetails.class.js index bcc26c24..d0e69ed9 100644 --- a/htdocs/js/pages/JobDetails.class.js +++ b/htdocs/js/pages/JobDetails.class.js @@ -866,20 +866,21 @@ Class.subclass( Page.Base, "Page.JobDetails", { html += ''; // live job log tail - var remote_api_url = app.proto + '://' + job.hostname + ':' + app.port + config.base_api_uri; + var port = self.server.config.get('WebServer').http_port; + var remote_api_url = 'http://' + job.hostname + ':' + port + config.base_api_uri; var job_log_function = "get_live_job_log" - if (config.custom_live_log_socket_url) { + if (config.worker_proxy_logs) { + // Use master address instead + remote_api_url = "" + job_log_function = "api_get_live_job_log_proxy" + } + else if (config.custom_live_log_socket_url) { // custom websocket URL for single-master systems behind an LB remote_api_url = config.custom_live_log_socket_url + config.base_api_uri; } else if (!config.web_socket_use_hostnames && app.servers && app.servers[job.hostname] && app.servers[job.hostname].ip) { // use ip if available, may work better in some setups - remote_api_url = app.proto + '://' + app.servers[job.hostname].ip + ':' + app.port + config.base_api_uri; - } - else if (config.worker_proxy_logs) { - // Use master address instead - remote_api_url = "" - job_log_function = "api_get_live_job_log_proxy" + remote_api_url = 'http://' + app.servers[job.hostname].ip + ':' + port + config.base_api_uri; } html += '
'; @@ -1047,21 +1048,22 @@ Class.subclass( Page.Base, "Page.JobDetails", { // open special websocket to target server for live log feed var self = this; var $cont = $('#d_live_job_log'); - - var url = app.proto + '://' + job.hostname + ':' + app.port; + + var port = self.server.config.get('WebServer').http_port; + var url = 'http://' + job.hostname + ':' + port; var job_log_function = "get_live_job_log_tail" - if (config.custom_live_log_socket_url) { + if (config.worker_proxy_logs) { + // Use master address instead + url = config.base_api_uri + job_log_function = "api_get_live_job_log_proxy" + } + else if (config.custom_live_log_socket_url) { // custom websocket URL for single-master systems behind an LB url = config.custom_live_log_socket_url; } else if (!config.web_socket_use_hostnames && app.servers && app.servers[job.hostname] && app.servers[job.hostname].ip) { // use ip if available, may work better in some setups - url = app.proto + '://' + app.servers[job.hostname].ip + ':' + app.port; - } - else if (config.worker_proxy_logs) { - // Use master address instead - url = config.base_api_uri - job_log_function = "api_get_live_job_log_proxy" + url = 'http://' + app.servers[job.hostname].ip + ':' + port; } var api_url = url + '/api/app/' + job_log_function console.error(api_url) From eab75f0ef95329017bbf9c3e7f1fa907d244fe36 Mon Sep 17 00:00:00 2001 From: Rob Russo Date: Fri, 9 Jul 2021 12:04:23 -0400 Subject: [PATCH 13/28] change config --- htdocs/js/pages/JobDetails.class.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/js/pages/JobDetails.class.js b/htdocs/js/pages/JobDetails.class.js index d0e69ed9..01008245 100644 --- a/htdocs/js/pages/JobDetails.class.js +++ b/htdocs/js/pages/JobDetails.class.js @@ -866,7 +866,7 @@ Class.subclass( Page.Base, "Page.JobDetails", { html += '
'; // live job log tail - var port = self.server.config.get('WebServer').http_port; + var port = config.get('WebServer').http_port; var remote_api_url = 'http://' + job.hostname + ':' + port + config.base_api_uri; var job_log_function = "get_live_job_log" if (config.worker_proxy_logs) { @@ -1049,7 +1049,7 @@ Class.subclass( Page.Base, "Page.JobDetails", { var self = this; var $cont = $('#d_live_job_log'); - var port = self.server.config.get('WebServer').http_port; + var port = config.get('WebServer').http_port; var url = 'http://' + job.hostname + ':' + port; var job_log_function = "get_live_job_log_tail" if (config.worker_proxy_logs) { From 8e5196041395389c539f5fac4e968a34ffe20dc5 Mon Sep 17 00:00:00 2001 From: Rob Russo Date: Fri, 9 Jul 2021 16:21:38 -0400 Subject: [PATCH 14/28] add port and proto --- README.md | 9 +++++++++ htdocs/js/pages/JobDetails.class.js | 10 ++++------ lib/api/config.js | 2 ++ 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index bef43bb4..bf9afbbf 100644 --- a/README.md +++ b/README.md @@ -607,10 +607,19 @@ Setting this parameter to `true` will force Cronicle's Web UI to connect to the This property only takes effect if [web_direct_connect](#web_direct_connect) is also set to `true`. +### web_connect_proto + +This controls the protocol used to connect to workers. It should mirror the setup used in the workers WebServer section. + +### web_connect_port + +This controls the port used to connect to workers. It should mirror the setup used in the workers WebServer section. + ### worker_proxy_logs Use this setting to force live log polling to occur as a pull through proxy on the master. + ### socket_io_transports This is an advanced configuration property that you will probably never need to worry about. This allows you to customize the [socket.io transports](https://socket.io/docs/client-api/) used to connect to the server for real-time updates. By default, this property is set internally to an array containing the `websocket` transport only, e.g. diff --git a/htdocs/js/pages/JobDetails.class.js b/htdocs/js/pages/JobDetails.class.js index 01008245..308a8057 100644 --- a/htdocs/js/pages/JobDetails.class.js +++ b/htdocs/js/pages/JobDetails.class.js @@ -866,8 +866,7 @@ Class.subclass( Page.Base, "Page.JobDetails", { html += ''; // live job log tail - var port = config.get('WebServer').http_port; - var remote_api_url = 'http://' + job.hostname + ':' + port + config.base_api_uri; + var remote_api_url = config.worker_connect_proto + '://' + job.hostname + ':' + config.worker_connect_port + config.base_api_uri; var job_log_function = "get_live_job_log" if (config.worker_proxy_logs) { // Use master address instead @@ -880,7 +879,7 @@ Class.subclass( Page.Base, "Page.JobDetails", { } else if (!config.web_socket_use_hostnames && app.servers && app.servers[job.hostname] && app.servers[job.hostname].ip) { // use ip if available, may work better in some setups - remote_api_url = 'http://' + app.servers[job.hostname].ip + ':' + port + config.base_api_uri; + remote_api_url = config.worker_connect_proto + '://' + app.servers[job.hostname].ip + ':' + config.worker_connect_port + config.base_api_uri; } html += '
'; @@ -1049,8 +1048,7 @@ Class.subclass( Page.Base, "Page.JobDetails", { var self = this; var $cont = $('#d_live_job_log'); - var port = config.get('WebServer').http_port; - var url = 'http://' + job.hostname + ':' + port; + var url = config.worker_connect_port + '://' + job.hostname + ':' + config.worker_connect_port; var job_log_function = "get_live_job_log_tail" if (config.worker_proxy_logs) { // Use master address instead @@ -1063,7 +1061,7 @@ Class.subclass( Page.Base, "Page.JobDetails", { } else if (!config.web_socket_use_hostnames && app.servers && app.servers[job.hostname] && app.servers[job.hostname].ip) { // use ip if available, may work better in some setups - url = 'http://' + app.servers[job.hostname].ip + ':' + port; + url = config.worker_connect_port + '://' + app.servers[job.hostname].ip + ':' + config.worker_connect_port; } var api_url = url + '/api/app/' + job_log_function console.error(api_url) diff --git a/lib/api/config.js b/lib/api/config.js index a547c5e0..26bd5518 100644 --- a/lib/api/config.js +++ b/lib/api/config.js @@ -36,6 +36,8 @@ module.exports = Class.create({ external_user_api: this.usermgr.config.get('external_user_api') || '', web_socket_use_hostnames: this.server.config.get('web_socket_use_hostnames') || 0, web_direct_connect: this.server.config.get('web_direct_connect') || 0, + worker_connect_proto: this.server.config.get('worker_connect_proto') || 'http', + worker_connect_port: this.server.config.get('worker_connect_port') || '3012', worker_proxy_logs: this.server.config.get('worker_proxy_logs') || 0, socket_io_transports: this.server.config.get('socket_io_transports') || 0 } ), From 0b416d356e699bd990acb53223853ddb7b990101 Mon Sep 17 00:00:00 2001 From: Rob Russo Date: Fri, 9 Jul 2021 16:23:31 -0400 Subject: [PATCH 15/28] update example config --- sample_conf/config.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sample_conf/config.json b/sample_conf/config.json index 2643fb97..1d091c5f 100644 --- a/sample_conf/config.json +++ b/sample_conf/config.json @@ -30,6 +30,8 @@ "server_comm_use_hostnames": false, "web_direct_connect": false, "web_socket_use_hostnames": false, + "worker_connect_proto": "http", + "worker_connect_port": 3012, "worker_proxy_logs": false, "job_memory_max": 1073741824, From 05fe9fe4a20d75a0fe971225b0bb18892e2403a1 Mon Sep 17 00:00:00 2001 From: Rob Russo Date: Fri, 9 Jul 2021 16:26:28 -0400 Subject: [PATCH 16/28] remove extra uri --- htdocs/js/pages/JobDetails.class.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/js/pages/JobDetails.class.js b/htdocs/js/pages/JobDetails.class.js index 308a8057..989725e4 100644 --- a/htdocs/js/pages/JobDetails.class.js +++ b/htdocs/js/pages/JobDetails.class.js @@ -1052,7 +1052,7 @@ Class.subclass( Page.Base, "Page.JobDetails", { var job_log_function = "get_live_job_log_tail" if (config.worker_proxy_logs) { // Use master address instead - url = config.base_api_uri + url = "" job_log_function = "api_get_live_job_log_proxy" } else if (config.custom_live_log_socket_url) { From 1a6a2bc5d8ce909bd6d4511a5c464be6c430593d Mon Sep 17 00:00:00 2001 From: Rob Russo Date: Fri, 9 Jul 2021 16:28:39 -0400 Subject: [PATCH 17/28] fix api uri --- htdocs/js/pages/JobDetails.class.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/js/pages/JobDetails.class.js b/htdocs/js/pages/JobDetails.class.js index 989725e4..d4385d21 100644 --- a/htdocs/js/pages/JobDetails.class.js +++ b/htdocs/js/pages/JobDetails.class.js @@ -871,7 +871,7 @@ Class.subclass( Page.Base, "Page.JobDetails", { if (config.worker_proxy_logs) { // Use master address instead remote_api_url = "" - job_log_function = "api_get_live_job_log_proxy" + job_log_function = "get_live_job_log_proxy" } else if (config.custom_live_log_socket_url) { // custom websocket URL for single-master systems behind an LB @@ -1053,7 +1053,7 @@ Class.subclass( Page.Base, "Page.JobDetails", { if (config.worker_proxy_logs) { // Use master address instead url = "" - job_log_function = "api_get_live_job_log_proxy" + job_log_function = "get_live_job_log_proxy" } else if (config.custom_live_log_socket_url) { // custom websocket URL for single-master systems behind an LB From d64c56e81c8be0d6617469cabc8563e47cbb6ae7 Mon Sep 17 00:00:00 2001 From: Rob Russo Date: Fri, 9 Jul 2021 16:33:08 -0400 Subject: [PATCH 18/28] fix var name --- lib/api/job.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/api/job.js b/lib/api/job.js index a1513289..5dc6bbc9 100644 --- a/lib/api/job.js +++ b/lib/api/job.js @@ -97,8 +97,8 @@ module.exports = Class.create({ id: /^\w+$/ }, callback)) return; - var job = self.findJob(query); - if (!job) return self.doError('job', "Failed to locate job: " + query.id, callback); + var job = self.findJob(params); + if (!job) return self.doError('job', "Failed to locate job: " + params.id, callback); var api_url = this.getServerBaseAPIURL( slave.hostname, slave.ip ) + '/app/get_live_job_log'; var tailSize = parseInt(params.tail) || 80; From 9425a440d83fe7e1a31811812990d673a305af63 Mon Sep 17 00:00:00 2001 From: Rob Russo Date: Fri, 9 Jul 2021 16:37:12 -0400 Subject: [PATCH 19/28] add slave lookup --- lib/api/job.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/api/job.js b/lib/api/job.js index 5dc6bbc9..b856242f 100644 --- a/lib/api/job.js +++ b/lib/api/job.js @@ -100,6 +100,12 @@ module.exports = Class.create({ var job = self.findJob(params); if (!job) return self.doError('job', "Failed to locate job: " + params.id, callback); + var slave = this.slaves[ job.hostname ]; + if (!slave) { + this.logError('job', "Failed to locate slave: " + job.hostname + " for job: " + job.id); + slave = { hostname: job.hostname }; // hail mary + } + var api_url = this.getServerBaseAPIURL( slave.hostname, slave.ip ) + '/app/get_live_job_log'; var tailSize = parseInt(params.tail) || 80; var auth = Tools.digestHex(params.id + self.server.config.get('secret_key')) From 70c27515124a0b2ebad57599c7d9531fc1525a77 Mon Sep 17 00:00:00 2001 From: Rob Russo Date: Fri, 9 Jul 2021 16:46:14 -0400 Subject: [PATCH 20/28] find slave --- lib/api/job.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/api/job.js b/lib/api/job.js index b856242f..f8388aa2 100644 --- a/lib/api/job.js +++ b/lib/api/job.js @@ -100,7 +100,7 @@ module.exports = Class.create({ var job = self.findJob(params); if (!job) return self.doError('job', "Failed to locate job: " + params.id, callback); - var slave = this.slaves[ job.hostname ]; + var slave = self.slaves[ job.hostname ]; if (!slave) { this.logError('job', "Failed to locate slave: " + job.hostname + " for job: " + job.id); slave = { hostname: job.hostname }; // hail mary From 75f7fa7adb31bc6d8e497c4fa46db576b8405da5 Mon Sep 17 00:00:00 2001 From: Rob Russo Date: Fri, 9 Jul 2021 16:49:28 -0400 Subject: [PATCH 21/28] update function call --- lib/api/job.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/api/job.js b/lib/api/job.js index f8388aa2..712ccba1 100644 --- a/lib/api/job.js +++ b/lib/api/job.js @@ -106,7 +106,7 @@ module.exports = Class.create({ slave = { hostname: job.hostname }; // hail mary } - var api_url = this.getServerBaseAPIURL( slave.hostname, slave.ip ) + '/app/get_live_job_log'; + var api_url = self.getServerBaseAPIURL( slave.hostname, slave.ip ) + '/app/get_live_job_log'; var tailSize = parseInt(params.tail) || 80; var auth = Tools.digestHex(params.id + self.server.config.get('secret_key')) var reqParams = { id: job.id, tail: tailSize, download: params.download || 0, auth: auth } From d4546d28e4d80be53555f1f822189d4a1ff24b58 Mon Sep 17 00:00:00 2001 From: Rob Russo Date: Mon, 12 Jul 2021 12:37:46 -0400 Subject: [PATCH 22/28] update job --- lib/api/job.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/lib/api/job.js b/lib/api/job.js index 712ccba1..bb80520a 100644 --- a/lib/api/job.js +++ b/lib/api/job.js @@ -92,13 +92,12 @@ module.exports = Class.create({ if (err) return self.doError('session', err.message, callback); if (!self.requireValidUser(session, user, callback)) return; - let params = Tools.mergeHashes(args.params, args.query); - if (!self.requireParams(params, { + if (!this.requireParams(args.query, { id: /^\w+$/ }, callback)) return; - var job = self.findJob(params); - if (!job) return self.doError('job', "Failed to locate job: " + params.id, callback); + var job = self.findJob(args.query); + if (!job) return self.doError('job', "Failed to locate job: " + args.query.id, callback); var slave = self.slaves[ job.hostname ]; if (!slave) { @@ -107,8 +106,8 @@ module.exports = Class.create({ } var api_url = self.getServerBaseAPIURL( slave.hostname, slave.ip ) + '/app/get_live_job_log'; - var tailSize = parseInt(params.tail) || 80; - var auth = Tools.digestHex(params.id + self.server.config.get('secret_key')) + var tailSize = parseInt(args.query.tail) || 80; + var auth = Tools.digestHex(args.query.id + self.server.config.get('secret_key')) var reqParams = { id: job.id, tail: tailSize, download: params.download || 0, auth: auth } self.request.json(api_url, reqParams, (err, resp, data) => { @@ -122,11 +121,11 @@ module.exports = Class.create({ api_get_live_log_tail: function (args, callback) { // internal api, runs on target machine - const self = this; + var self = this; let params = Tools.mergeHashes(args.params, args.query); - if (!this.requireParams(params, { + if (!self.requireParams(params, { id: /^\w+$/, auth: /^\w+$/ }, callback)) return; From b72d1cda5f90280814fe00a12a9749e89d5a3037 Mon Sep 17 00:00:00 2001 From: Rob Russo Date: Mon, 12 Jul 2021 12:42:53 -0400 Subject: [PATCH 23/28] use self for params --- lib/api/job.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/api/job.js b/lib/api/job.js index bb80520a..49938a9a 100644 --- a/lib/api/job.js +++ b/lib/api/job.js @@ -92,7 +92,7 @@ module.exports = Class.create({ if (err) return self.doError('session', err.message, callback); if (!self.requireValidUser(session, user, callback)) return; - if (!this.requireParams(args.query, { + if (!self.requireParams(args.query, { id: /^\w+$/ }, callback)) return; From e542740a6f543c6c36ab765ae481fdd411d14791 Mon Sep 17 00:00:00 2001 From: Rob Russo Date: Mon, 12 Jul 2021 12:47:06 -0400 Subject: [PATCH 24/28] merge params --- lib/api/job.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/api/job.js b/lib/api/job.js index 49938a9a..f70f1657 100644 --- a/lib/api/job.js +++ b/lib/api/job.js @@ -88,16 +88,18 @@ module.exports = Class.create({ // client API, no auth var self = this; + var params = Tools.mergeHashes(args.params, args.query); + self.loadSession(args, function (err, session, user) { if (err) return self.doError('session', err.message, callback); if (!self.requireValidUser(session, user, callback)) return; - if (!self.requireParams(args.query, { + if (!self.requireParams(params, { id: /^\w+$/ }, callback)) return; - var job = self.findJob(args.query); - if (!job) return self.doError('job', "Failed to locate job: " + args.query.id, callback); + var job = self.findJob(params); + if (!job) return self.doError('job', "Failed to locate job: " + params.id, callback); var slave = self.slaves[ job.hostname ]; if (!slave) { From ed2ea5b1f786dc26e24f68500aa8d9b85e45ee6d Mon Sep 17 00:00:00 2001 From: Rob Russo Date: Mon, 12 Jul 2021 12:52:16 -0400 Subject: [PATCH 25/28] fix jopb params --- lib/api/job.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/api/job.js b/lib/api/job.js index f70f1657..1077f794 100644 --- a/lib/api/job.js +++ b/lib/api/job.js @@ -107,9 +107,9 @@ module.exports = Class.create({ slave = { hostname: job.hostname }; // hail mary } - var api_url = self.getServerBaseAPIURL( slave.hostname, slave.ip ) + '/app/get_live_job_log'; - var tailSize = parseInt(args.query.tail) || 80; - var auth = Tools.digestHex(args.query.id + self.server.config.get('secret_key')) + var api_url = self.getServerBaseAPIURL( slave.hostname, slave.ip ) + '/app/get_live_log_tail'; + var tailSize = parseInt(params.tail) || 80; + var auth = Tools.digestHex(params.id + self.server.config.get('secret_key')) var reqParams = { id: job.id, tail: tailSize, download: params.download || 0, auth: auth } self.request.json(api_url, reqParams, (err, resp, data) => { From fdcc6f02f43e68466851649bb0a717121cb063a4 Mon Sep 17 00:00:00 2001 From: Rob Russo Date: Mon, 12 Jul 2021 13:03:03 -0400 Subject: [PATCH 26/28] set poll interval config --- README.md | 13 ++-------- htdocs/js/pages/JobDetails.class.js | 39 +++-------------------------- lib/api/config.js | 4 +-- sample_conf/config.json | 4 +-- 4 files changed, 7 insertions(+), 53 deletions(-) diff --git a/README.md b/README.md index bf9afbbf..1d9169f1 100644 --- a/README.md +++ b/README.md @@ -607,18 +607,9 @@ Setting this parameter to `true` will force Cronicle's Web UI to connect to the This property only takes effect if [web_direct_connect](#web_direct_connect) is also set to `true`. -### web_connect_proto - -This controls the protocol used to connect to workers. It should mirror the setup used in the workers WebServer section. - -### web_connect_port - -This controls the port used to connect to workers. It should mirror the setup used in the workers WebServer section. - -### worker_proxy_logs - -Use this setting to force live log polling to occur as a pull through proxy on the master. +#### live_log_poll_interval +The interval at which live logs are polled from the running job. ### socket_io_transports diff --git a/htdocs/js/pages/JobDetails.class.js b/htdocs/js/pages/JobDetails.class.js index d4385d21..12fdc78b 100644 --- a/htdocs/js/pages/JobDetails.class.js +++ b/htdocs/js/pages/JobDetails.class.js @@ -865,26 +865,9 @@ Class.subclass( Page.Base, "Page.JobDetails", { html += '
'; - // live job log tail - var remote_api_url = config.worker_connect_proto + '://' + job.hostname + ':' + config.worker_connect_port + config.base_api_uri; - var job_log_function = "get_live_job_log" - if (config.worker_proxy_logs) { - // Use master address instead - remote_api_url = "" - job_log_function = "get_live_job_log_proxy" - } - else if (config.custom_live_log_socket_url) { - // custom websocket URL for single-master systems behind an LB - remote_api_url = config.custom_live_log_socket_url + config.base_api_uri; - } - else if (!config.web_socket_use_hostnames && app.servers && app.servers[job.hostname] && app.servers[job.hostname].ip) { - // use ip if available, may work better in some setups - remote_api_url = config.worker_connect_proto + '://' + app.servers[job.hostname].ip + ':' + config.worker_connect_port + config.base_api_uri; - } - html += '
'; html += 'Live Job Event Log'; - html += ''; + html += ''; html += '
'; html += '
'; @@ -1048,23 +1031,7 @@ Class.subclass( Page.Base, "Page.JobDetails", { var self = this; var $cont = $('#d_live_job_log'); - var url = config.worker_connect_port + '://' + job.hostname + ':' + config.worker_connect_port; - var job_log_function = "get_live_job_log_tail" - if (config.worker_proxy_logs) { - // Use master address instead - url = "" - job_log_function = "get_live_job_log_proxy" - } - else if (config.custom_live_log_socket_url) { - // custom websocket URL for single-master systems behind an LB - url = config.custom_live_log_socket_url; - } - else if (!config.web_socket_use_hostnames && app.servers && app.servers[job.hostname] && app.servers[job.hostname].ip) { - // use ip if available, may work better in some setups - url = config.worker_connect_port + '://' + app.servers[job.hostname].ip + ':' + config.worker_connect_port; - } - var api_url = url + '/api/app/' + job_log_function - console.error(api_url) + var api_url = '/api/app/job_log_function' self.curr_live_log_job = job.id; @@ -1075,7 +1042,7 @@ Class.subclass( Page.Base, "Page.JobDetails", { , (data) => { // success callback if (!data.data) return; // stop polling if no data $cont.append('
' + data.data + '
'); - pollInterval = parseInt(app.config.ui.live_log) + pollInterval = parseInt(config.live_log_poll_interval) if(!pollInterval || pollInterval < 1000) pollInterval = 1000; setTimeout(refresh, 1000); } diff --git a/lib/api/config.js b/lib/api/config.js index 26bd5518..bb6f6b20 100644 --- a/lib/api/config.js +++ b/lib/api/config.js @@ -36,9 +36,7 @@ module.exports = Class.create({ external_user_api: this.usermgr.config.get('external_user_api') || '', web_socket_use_hostnames: this.server.config.get('web_socket_use_hostnames') || 0, web_direct_connect: this.server.config.get('web_direct_connect') || 0, - worker_connect_proto: this.server.config.get('worker_connect_proto') || 'http', - worker_connect_port: this.server.config.get('worker_connect_port') || '3012', - worker_proxy_logs: this.server.config.get('worker_proxy_logs') || 0, + live_log_poll_interval: this.server.config.get('live_log_poll_interval') || 1000, socket_io_transports: this.server.config.get('socket_io_transports') || 0 } ), port: args.request.headers.ssl ? this.web.config.get('https_port') : this.web.config.get('http_port'), diff --git a/sample_conf/config.json b/sample_conf/config.json index 1d091c5f..62069922 100644 --- a/sample_conf/config.json +++ b/sample_conf/config.json @@ -30,9 +30,7 @@ "server_comm_use_hostnames": false, "web_direct_connect": false, "web_socket_use_hostnames": false, - "worker_connect_proto": "http", - "worker_connect_port": 3012, - "worker_proxy_logs": false, + "live_log_poll_interval": 1000, "job_memory_max": 1073741824, "job_memory_sustain": 0, From ea39f546486ede8b6abf79be27a52118536b6041 Mon Sep 17 00:00:00 2001 From: Rob Russo Date: Mon, 12 Jul 2021 13:07:08 -0400 Subject: [PATCH 27/28] fix api name --- htdocs/js/pages/JobDetails.class.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/htdocs/js/pages/JobDetails.class.js b/htdocs/js/pages/JobDetails.class.js index 12fdc78b..527607fa 100644 --- a/htdocs/js/pages/JobDetails.class.js +++ b/htdocs/js/pages/JobDetails.class.js @@ -1031,14 +1031,12 @@ Class.subclass( Page.Base, "Page.JobDetails", { var self = this; var $cont = $('#d_live_job_log'); - var api_url = '/api/app/job_log_function' - self.curr_live_log_job = job.id; // poll live_console api until job is running or some error occur function refresh() { if(self.curr_live_log_job != job.id) return; // prevent double logging - app.api.post(api_url, { id: job.id } + app.api.post('/api/app/get_live_job_log_proxy', { id: job.id } , (data) => { // success callback if (!data.data) return; // stop polling if no data $cont.append('
' + data.data + '
'); From 6fcfed1e6cc9e7734968dfa049c9205a28bc2001 Mon Sep 17 00:00:00 2001 From: Rob Russo Date: Mon, 12 Jul 2021 13:30:15 -0400 Subject: [PATCH 28/28] prevent duplicate log lines --- htdocs/js/pages/JobDetails.class.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/htdocs/js/pages/JobDetails.class.js b/htdocs/js/pages/JobDetails.class.js index 527607fa..34b7ab5a 100644 --- a/htdocs/js/pages/JobDetails.class.js +++ b/htdocs/js/pages/JobDetails.class.js @@ -1033,13 +1033,21 @@ Class.subclass( Page.Base, "Page.JobDetails", { self.curr_live_log_job = job.id; + var previous_data = [] + // poll live_console api until job is running or some error occur function refresh() { if(self.curr_live_log_job != job.id) return; // prevent double logging app.api.post('/api/app/get_live_job_log_proxy', { id: job.id } , (data) => { // success callback if (!data.data) return; // stop polling if no data - $cont.append('
' + data.data + '
'); + + // Prevent short logs from showing duplicate lines + var new_data = data.data.split(/\r?\n/) + var trimmed_data = new_data.filter((item) => previous_data.indexOf(item)< 0) + previous_data = previous_data.concat(trimmed_data) + + $cont.append('
' + trimmed_data.join('\n') + '
'); pollInterval = parseInt(config.live_log_poll_interval) if(!pollInterval || pollInterval < 1000) pollInterval = 1000; setTimeout(refresh, 1000);