github.com/hernad/nomad@v1.6.112/ui/app/components/task-log.js (about) 1 /** 2 * Copyright (c) HashiCorp, Inc. 3 * SPDX-License-Identifier: MPL-2.0 4 */ 5 6 import { inject as service } from '@ember/service'; 7 import Component from '@ember/component'; 8 import { action, computed } from '@ember/object'; 9 import { alias } from '@ember/object/computed'; 10 import RSVP from 'rsvp'; 11 import { logger } from 'nomad-ui/utils/classes/log'; 12 import timeout from 'nomad-ui/utils/timeout'; 13 import { classNames } from '@ember-decorators/component'; 14 import classic from 'ember-classic-decorator'; 15 import localStorageProperty from 'nomad-ui/utils/properties/local-storage'; 16 17 class MockAbortController { 18 abort() { 19 /* noop */ 20 } 21 } 22 23 @classic 24 @classNames('boxed-section', 'task-log') 25 export default class TaskLog extends Component { 26 @service token; 27 @service userSettings; 28 29 allocation = null; 30 task = null; 31 32 // When true, request logs from the server agent 33 useServer = false; 34 35 // When true, logs cannot be fetched from either the client or the server 36 noConnection = false; 37 38 clientTimeout = 1000; 39 serverTimeout = 5000; 40 41 isStreaming = true; 42 streamMode = 'streaming'; 43 44 shouldFillHeight = true; 45 46 @localStorageProperty('nomadShouldWrapCode', false) wrapped; 47 48 @alias('userSettings.logMode') mode; 49 50 @computed('allocation.{id,node.httpAddr}', 'useServer') 51 get logUrl() { 52 const address = this.get('allocation.node.httpAddr'); 53 const allocation = this.get('allocation.id'); 54 55 const url = `/v1/client/fs/logs/${allocation}`; 56 return this.useServer ? url : `//${address}${url}`; 57 } 58 59 @computed('task', 'mode') 60 get logParams() { 61 return { 62 task: this.task, 63 type: this.mode, 64 }; 65 } 66 67 @logger('logUrl', 'logParams', function logFetch() { 68 // If the log request can't settle in one second, the client 69 // must be unavailable and the server should be used instead 70 71 const aborter = window.AbortController 72 ? new AbortController() 73 : new MockAbortController(); 74 const timing = this.useServer ? this.serverTimeout : this.clientTimeout; 75 76 // Capture the state of useServer at logger create time to avoid a race 77 // between the stdout logger and stderr logger running at once. 78 const useServer = this.useServer; 79 return (url) => 80 RSVP.race([ 81 this.token.authorizedRequest(url, { signal: aborter.signal }), 82 timeout(timing), 83 ]).then( 84 (response) => { 85 return response; 86 }, 87 (error) => { 88 aborter.abort(); 89 if (useServer) { 90 this.set('noConnection', true); 91 } else { 92 this.send('failoverToServer'); 93 } 94 throw error; 95 } 96 ); 97 }) 98 logger; 99 100 @action 101 setMode(mode) { 102 if (this.mode === mode) return; 103 this.logger.stop(); 104 this.set('mode', mode); 105 } 106 107 @action 108 toggleStream() { 109 this.set('streamMode', 'streaming'); 110 this.toggleProperty('isStreaming'); 111 } 112 113 @action 114 gotoHead() { 115 this.set('streamMode', 'head'); 116 this.set('isStreaming', false); 117 } 118 119 @action 120 gotoTail() { 121 this.set('streamMode', 'tail'); 122 this.set('isStreaming', false); 123 } 124 125 @action 126 failoverToServer() { 127 this.set('useServer', true); 128 } 129 130 @action toggleWrap() { 131 this.toggleProperty('wrapped'); 132 return false; 133 } 134 }