2017-12-15 21:39:18 +00:00
|
|
|
import { inject as service } from '@ember/service';
|
|
|
|
import Component from '@ember/component';
|
2020-06-10 13:49:16 +00:00
|
|
|
import { action, computed } from '@ember/object';
|
2018-02-26 20:23:01 +00:00
|
|
|
import RSVP from 'rsvp';
|
2017-11-15 20:45:11 +00:00
|
|
|
import { logger } from 'nomad-ui/utils/classes/log';
|
2018-02-26 20:23:01 +00:00
|
|
|
import timeout from 'nomad-ui/utils/timeout';
|
2020-06-10 13:49:16 +00:00
|
|
|
import { classNames } from '@ember-decorators/component';
|
|
|
|
import classic from 'ember-classic-decorator';
|
2020-04-28 04:03:33 +00:00
|
|
|
|
2020-06-25 03:46:30 +00:00
|
|
|
class MockAbortController {
|
|
|
|
abort() {
|
|
|
|
/* noop */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-10 13:49:16 +00:00
|
|
|
@classic
|
|
|
|
@classNames('boxed-section', 'task-log')
|
|
|
|
export default class TaskLog extends Component {
|
|
|
|
@service token;
|
2017-11-15 17:13:17 +00:00
|
|
|
|
2020-06-10 13:49:16 +00:00
|
|
|
allocation = null;
|
|
|
|
task = null;
|
2017-11-15 17:13:17 +00:00
|
|
|
|
2018-02-27 21:38:31 +00:00
|
|
|
// When true, request logs from the server agent
|
2020-06-10 13:49:16 +00:00
|
|
|
useServer = false;
|
2018-02-26 20:23:01 +00:00
|
|
|
|
2018-02-27 21:38:31 +00:00
|
|
|
// When true, logs cannot be fetched from either the client or the server
|
2020-06-10 13:49:16 +00:00
|
|
|
noConnection = false;
|
2018-02-27 21:38:31 +00:00
|
|
|
|
2020-06-10 13:49:16 +00:00
|
|
|
clientTimeout = 1000;
|
|
|
|
serverTimeout = 5000;
|
2018-02-27 21:38:31 +00:00
|
|
|
|
2020-06-10 13:49:16 +00:00
|
|
|
isStreaming = true;
|
|
|
|
streamMode = 'streaming';
|
2017-11-15 20:45:11 +00:00
|
|
|
|
2020-06-10 13:49:16 +00:00
|
|
|
mode = 'stdout';
|
2017-11-15 17:13:17 +00:00
|
|
|
|
2020-06-10 13:49:16 +00:00
|
|
|
@computed('allocation.{id,node.httpAddr}', 'useServer')
|
|
|
|
get logUrl() {
|
2017-11-15 17:13:17 +00:00
|
|
|
const address = this.get('allocation.node.httpAddr');
|
|
|
|
const allocation = this.get('allocation.id');
|
|
|
|
|
2018-02-26 20:23:01 +00:00
|
|
|
const url = `/v1/client/fs/logs/${allocation}`;
|
2019-03-26 07:46:44 +00:00
|
|
|
return this.useServer ? url : `//${address}${url}`;
|
2020-06-10 13:49:16 +00:00
|
|
|
}
|
2017-11-15 17:13:17 +00:00
|
|
|
|
2020-06-10 13:49:16 +00:00
|
|
|
@computed('task', 'mode')
|
|
|
|
get logParams() {
|
2017-11-15 17:13:17 +00:00
|
|
|
return {
|
2019-03-26 07:46:44 +00:00
|
|
|
task: this.task,
|
|
|
|
type: this.mode,
|
2017-11-15 17:13:17 +00:00
|
|
|
};
|
2020-06-10 13:49:16 +00:00
|
|
|
}
|
2017-11-15 17:13:17 +00:00
|
|
|
|
2020-06-10 13:49:16 +00:00
|
|
|
@logger('logUrl', 'logParams', function logFetch() {
|
2018-02-26 20:23:01 +00:00
|
|
|
// If the log request can't settle in one second, the client
|
|
|
|
// must be unavailable and the server should be used instead
|
2020-04-28 04:03:33 +00:00
|
|
|
|
2020-06-25 03:46:30 +00:00
|
|
|
const aborter = window.AbortController ? new AbortController() : new MockAbortController();
|
2019-03-26 07:46:44 +00:00
|
|
|
const timing = this.useServer ? this.serverTimeout : this.clientTimeout;
|
2020-04-28 06:34:01 +00:00
|
|
|
|
|
|
|
// Capture the state of useServer at logger create time to avoid a race
|
|
|
|
// between the stdout logger and stderr logger running at once.
|
|
|
|
const useServer = this.useServer;
|
2018-02-26 20:23:01 +00:00
|
|
|
return url =>
|
2020-04-28 04:03:33 +00:00
|
|
|
RSVP.race([
|
|
|
|
this.token.authorizedRequest(url, { signal: aborter.signal }),
|
|
|
|
timeout(timing),
|
|
|
|
]).then(
|
|
|
|
response => {
|
|
|
|
return response;
|
|
|
|
},
|
2018-02-26 20:23:01 +00:00
|
|
|
error => {
|
2020-04-28 04:03:33 +00:00
|
|
|
aborter.abort();
|
2020-04-28 06:34:01 +00:00
|
|
|
if (useServer) {
|
2018-02-27 21:38:31 +00:00
|
|
|
this.set('noConnection', true);
|
|
|
|
} else {
|
|
|
|
this.send('failoverToServer');
|
|
|
|
}
|
2018-02-26 20:23:01 +00:00
|
|
|
throw error;
|
|
|
|
}
|
|
|
|
);
|
2020-06-10 13:49:16 +00:00
|
|
|
})
|
|
|
|
logger;
|
|
|
|
|
|
|
|
@action
|
|
|
|
setMode(mode) {
|
|
|
|
if (this.mode === mode) return;
|
|
|
|
this.logger.stop();
|
|
|
|
this.set('mode', mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
@action
|
|
|
|
toggleStream() {
|
|
|
|
this.set('streamMode', 'streaming');
|
|
|
|
this.toggleProperty('isStreaming');
|
|
|
|
}
|
|
|
|
|
|
|
|
@action
|
|
|
|
gotoHead() {
|
|
|
|
this.set('streamMode', 'head');
|
|
|
|
this.set('isStreaming', false);
|
|
|
|
}
|
|
|
|
|
|
|
|
@action
|
|
|
|
gotoTail() {
|
|
|
|
this.set('streamMode', 'tail');
|
|
|
|
this.set('isStreaming', false);
|
|
|
|
}
|
|
|
|
|
|
|
|
@action
|
|
|
|
failoverToServer() {
|
|
|
|
this.set('useServer', true);
|
|
|
|
}
|
|
|
|
}
|