github.com/emate/nomad@v0.8.2-wo-binpacking/ui/app/components/task-log.js (about)

     1  import { inject as service } from '@ember/service';
     2  import Component from '@ember/component';
     3  import { computed } from '@ember/object';
     4  import { run } from '@ember/runloop';
     5  import RSVP from 'rsvp';
     6  import { task } from 'ember-concurrency';
     7  import { logger } from 'nomad-ui/utils/classes/log';
     8  import WindowResizable from 'nomad-ui/mixins/window-resizable';
     9  import timeout from 'nomad-ui/utils/timeout';
    10  
    11  export default Component.extend(WindowResizable, {
    12    token: service(),
    13  
    14    classNames: ['boxed-section', 'task-log'],
    15  
    16    allocation: null,
    17    task: null,
    18  
    19    // When true, request logs from the server agent
    20    useServer: false,
    21  
    22    // When true, logs cannot be fetched from either the client or the server
    23    noConnection: false,
    24  
    25    clientTimeout: 1000,
    26    serverTimeout: 5000,
    27  
    28    didReceiveAttrs() {
    29      if (this.get('allocation') && this.get('task')) {
    30        this.send('toggleStream');
    31      }
    32    },
    33  
    34    didInsertElement() {
    35      this.fillAvailableHeight();
    36    },
    37  
    38    windowResizeHandler() {
    39      run.once(this, this.fillAvailableHeight);
    40    },
    41  
    42    fillAvailableHeight() {
    43      // This math is arbitrary and far from bulletproof, but the UX
    44      // of having the log window fill available height is worth the hack.
    45      const cliWindow = this.$('.cli-window');
    46      cliWindow.height(window.innerHeight - cliWindow.offset().top - 25);
    47    },
    48  
    49    mode: 'stdout',
    50  
    51    logUrl: computed('allocation.id', 'allocation.node.httpAddr', 'useServer', function() {
    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.get('useServer') ? url : `//${address}${url}`;
    57    }),
    58  
    59    logParams: computed('task', 'mode', function() {
    60      return {
    61        task: this.get('task'),
    62        type: this.get('mode'),
    63      };
    64    }),
    65  
    66    logger: logger('logUrl', 'logParams', function logFetch() {
    67      // If the log request can't settle in one second, the client
    68      // must be unavailable and the server should be used instead
    69      const timing = this.get('useServer') ? this.get('serverTimeout') : this.get('clientTimeout');
    70      return url =>
    71        RSVP.race([this.get('token').authorizedRequest(url), timeout(timing)]).then(
    72          response => response,
    73          error => {
    74            if (this.get('useServer')) {
    75              this.set('noConnection', true);
    76            } else {
    77              this.send('failoverToServer');
    78              this.get('stream').perform();
    79            }
    80            throw error;
    81          }
    82        );
    83    }),
    84  
    85    head: task(function*() {
    86      yield this.get('logger.gotoHead').perform();
    87      run.scheduleOnce('afterRender', () => {
    88        this.$('.cli-window').scrollTop(0);
    89      });
    90    }),
    91  
    92    tail: task(function*() {
    93      yield this.get('logger.gotoTail').perform();
    94      run.scheduleOnce('afterRender', () => {
    95        const cliWindow = this.$('.cli-window');
    96        cliWindow.scrollTop(cliWindow[0].scrollHeight);
    97      });
    98    }),
    99  
   100    stream: task(function*() {
   101      this.get('logger').on('tick', () => {
   102        run.scheduleOnce('afterRender', () => {
   103          const cliWindow = this.$('.cli-window');
   104          cliWindow.scrollTop(cliWindow[0].scrollHeight);
   105        });
   106      });
   107  
   108      yield this.get('logger').startStreaming();
   109      this.get('logger').off('tick');
   110    }),
   111  
   112    willDestroy() {
   113      this.get('logger').stop();
   114    },
   115  
   116    actions: {
   117      setMode(mode) {
   118        this.get('logger').stop();
   119        this.set('mode', mode);
   120        this.get('stream').perform();
   121      },
   122      toggleStream() {
   123        if (this.get('logger.isStreaming')) {
   124          this.get('logger').stop();
   125        } else {
   126          this.get('stream').perform();
   127        }
   128      },
   129      failoverToServer() {
   130        this.set('useServer', true);
   131      },
   132    },
   133  });