File

src/app/ceph/cluster/logs/logs.component.ts

Implements

OnInit OnDestroy

Metadata

selector cd-logs
styleUrls ./logs.component.scss
templateUrl ./logs.component.html

Index

Properties
Methods

Constructor

constructor(logsService: LogsService)
Parameters :
Name Type Optional
logsService LogsService No

Methods

abstractfilters
abstractfilters()
Returns : any
clearDate
clearDate()
Returns : void
clearSearchKey
clearSearchKey()
Returns : void
filterExecutor
filterExecutor(logs: Array, filters: any)
Parameters :
Name Type Optional
logs Array<any> No
filters any No
Returns : Array<any>
filterLogs
filterLogs()
Returns : void
getInfo
getInfo()
Returns : void
ngOnDestroy
ngOnDestroy()
Returns : void
ngOnInit
ngOnInit()
Returns : void

Properties

audit_log
Type : Array<any>
bsConfig
Type : object
Default value : { dateInputFormat: 'YYYY-MM-DD', containerClass: 'theme-default' }
clog
Type : Array<any>
contentData
Type : any
endTime
Type : Date
Default value : new Date()
interval
Type : number
priority
Type : string
Default value : 'All'
prioritys
Type : Array<literal type>
Default value : [ { name: 'Info', value: '[INF]' }, { name: 'Warning', value: '[WRN]' }, { name: 'Error', value: '[ERR]' }, { name: 'All', value: 'All' } ]
search
Type : string
Default value : ''
selectedDate
Type : Date
startTime
Type : Date
Default value : new Date()
import { Component, OnDestroy, OnInit } from '@angular/core';

import { LogsService } from '../../../shared/api/logs.service';

@Component({
  selector: 'cd-logs',
  templateUrl: './logs.component.html',
  styleUrls: ['./logs.component.scss']
})
export class LogsComponent implements OnInit, OnDestroy {
  contentData: any;
  clog: Array<any>;
  audit_log: Array<any>;

  interval: number;
  bsConfig = {
    dateInputFormat: 'YYYY-MM-DD',
    containerClass: 'theme-default'
  };
  prioritys: Array<{ name: string; value: string }> = [
    { name: 'Info', value: '[INF]' },
    { name: 'Warning', value: '[WRN]' },
    { name: 'Error', value: '[ERR]' },
    { name: 'All', value: 'All' }
  ];
  priority = 'All';
  search = '';
  selectedDate: Date;
  startTime: Date = new Date();
  endTime: Date = new Date();
  constructor(private logsService: LogsService) {
    this.startTime.setHours(0, 0);
    this.endTime.setHours(23, 59);
  }

  ngOnInit() {
    this.getInfo();
    this.interval = window.setInterval(() => {
      this.getInfo();
    }, 5000);
  }

  ngOnDestroy() {
    clearInterval(this.interval);
  }

  getInfo() {
    this.logsService.getLogs().subscribe((data: any) => {
      this.contentData = data;
      this.filterLogs();
    });
  }

  abstractfilters(): any {
    const priority = this.priority;
    const key = this.search.toLowerCase().replace(/,/g, '');

    let yearMonthDay: string;
    if (this.selectedDate) {
      const m = this.selectedDate.getMonth() + 1;
      const d = this.selectedDate.getDate();

      const year = this.selectedDate.getFullYear().toString();
      const month = m <= 9 ? `0${m}` : `${m}`;
      const day = d <= 9 ? `0${d}` : `${d}`;
      yearMonthDay = `${year}-${month}-${day}`;
    } else {
      yearMonthDay = '';
    }

    const sHour = this.startTime ? this.startTime.getHours() : 0;
    const sMinutes = this.startTime ? this.startTime.getMinutes() : 0;
    const sTime = sHour * 60 + sMinutes;

    const eHour = this.endTime ? this.endTime.getHours() : 23;
    const eMinutes = this.endTime ? this.endTime.getMinutes() : 59;
    const eTime = eHour * 60 + eMinutes;

    return { priority, key, yearMonthDay, sTime, eTime };
  }

  filterExecutor(logs: Array<any>, filters: any): Array<any> {
    return logs.filter((line) => {
      const hour = parseInt(line.stamp.slice(11, 13), 10);
      const minutes = parseInt(line.stamp.slice(14, 16), 10);
      let prio: string, y_m_d: string, timeSpan: number;

      prio = filters.priority === 'All' ? line.priority : filters.priority;
      y_m_d = filters.yearMonthDay ? filters.yearMonthDay : line.stamp;
      timeSpan = hour * 60 + minutes;
      return (
        line.priority === prio &&
        line.message.toLowerCase().indexOf(filters.key) !== -1 &&
        line.stamp.indexOf(y_m_d) !== -1 &&
        timeSpan >= filters.sTime &&
        timeSpan <= filters.eTime
      );
    });
  }

  filterLogs() {
    const filters = this.abstractfilters();
    this.clog = this.filterExecutor(this.contentData.clog, filters);
    this.audit_log = this.filterExecutor(this.contentData.audit_log, filters);
  }

  clearSearchKey() {
    this.search = '';
    this.filterLogs();
  }
  clearDate() {
    this.selectedDate = null;
    this.filterLogs();
  }
}
<div *ngIf="contentData">
<ng-container *ngTemplateOutlet="logFiltersTpl"></ng-container>
<tabset>
  <tab i18n-heading
       heading="Cluster Logs">
  <div class="well">
    <div *ngIf="clog">
      <p *ngFor="let line of clog">
        <span class="timestamp">{{ line.stamp }}</span>
        <span class="priority {{ line.priority | logPriority }}">{{ line.priority }}</span>
        <span class="message">{{ line.message }}</span>
      </p>
    </div>
    <div *ngIf="contentData.clog.length === 0">
      <p i18n>No entries found</p>
    </div>
  </div>
  </tab>

  <tab i18n-heading
       heading="Audit Logs">
  <div class="well">
    <div *ngIf="audit_log">
      <p *ngFor="let line of audit_log">
        <span class="timestamp">{{ line.stamp }}</span>
        <span class="priority {{ line.priority | logPriority }}">{{ line.priority }}</span>
        <span class="message">{{ line.message }}</span>
      </p>
    </div>
    <div *ngIf="contentData.audit_log.length === 0">
      <p i18n>No entries found</p>
    </div>
  </div>
  </tab>
</tabset>
</div>

<ng-template #logFiltersTpl>
  <div class="row log-filters">
    <div class="col-xs-4 col-md-2 cd-col-1 filter-box">
      <label i18n>Priority:</label>
      <select class="form-control"
              [(ngModel)]="priority"
              (ngModelChange)="filterLogs()">
        <option class="form-control" 
                *ngFor="let prio of prioritys"
                [value]="prio.value">{{ prio.name }}</option>
      </select>
    </div>
    <div class="col-xs-4 col-md-3 cd-col-3 filter-box">
      <label i18n>Keyword:</label>
      <div class="input-group">
        <span class="input-group-addon">
          <i class="glyphicon glyphicon-search"></i>
        </span>
        <input class="form-control"
               type="text"
               [(ngModel)]="search"
               (keyup)="filterLogs()">
        <span class="input-group-btn">
          <button type="button"
                  class="btn btn-default clear-input tc_clearInputBtn"
                  (click)="clearSearchKey()">
            <i class="icon-prepend fa fa-remove"></i>
          </button>
        </span>
      </div>
    </div>
    <div class="col-xs-4 col-md-3 cd-col-2 filter-box">
      <label i18n>Date:</label>
      <div class="input-group">
        <input type="text"
               class="form-control"
               i18n-placeholder
               placeholder="Datepicker"
               [bsConfig]="bsConfig"
               bsDatepicker
               [(ngModel)]="selectedDate"
               (ngModelChange)="filterLogs()">
        <span class="input-group-btn">
          <button type="button"
                  class="btn btn-default clear-input tc_clearInputBtn"
                  (click)="clearDate()">
            <i class="icon-prepend fa fa-remove"></i>
          </button>
        </span>
      </div>
    </div>
    <div class="clearfix visible-xs-block"></div>
    <div class="col-xs-8 col-md-4 cd-col-4 filter-box time-box">
      <label i18n>Time range:</label>
      <timepicker [showMeridian]="false"
                  [showSpinners]="showSpinners"
                  [minuteStep]="1"
                  [(ngModel)]="startTime"
                  (ngModelChange)="filterLogs()">
      </timepicker>
      <span>&nbsp;&mdash;&nbsp;</span>
      <timepicker [showMeridian]="false"
                  [showSpinners]="showSpinners"
                  [minuteStep]="1"
                  [(ngModel)]="endTime"
                  (ngModelChange)="filterLogs()">
      </timepicker>
    </div>
  </div>
</ng-template>

./logs.component.scss

@import '../../../../defaults';

p {
  font-family: monospace;
  color: black;
}

.well {
  div p {
    display: flex;

    &:last-child {
      margin-bottom: 0;
    }
  }

  .timestamp {
    font-weight: bold;
    flex-shrink: 0;
  }

  .priority {
    margin-left: 0.5rem;
  }

  .message {
    margin-left: 1rem;
  }

  .err {
    color: $color-pink;
  }

  .warn {
    color: $color-bright-yellow;
  }

  .info {
    color: $color-brand-teal;
  }
}

::ng-deep timepicker table tbody tr td {
  .bs-timepicker-field {
    width: 3.5rem;
    font-size: 1rem;
    padding: 4px 6px;
  }
  .btn {
    font-size: 1rem;
  }
}

.log-filters {
  margin-bottom: 5px;
  padding: 0 30px;
  * {
    box-sizing: border-box;
  }

  .filter-box {
    margin: 0;
    padding: 0 15px 5px 0;
    display: -webkit-flex;
    display: flex;
    justify-content: flex-start;
    align-items: center;
    label {
      padding-top: 5px;
      padding-right: 5px;
    }
  }

  @media (max-width: 991px) {
    .time-box {
      margin-top: 20px;
    }
  }

  @media (min-width: 1200px) {
    .cd-col-4 {
      width: 28vw;
    }

    .cd-col-3 {
      width: 20vw;
    }

    .cd-col-2 {
      width: 16vw;
    }
    .cd-col-1 {
      width: 14vw;
    }
  }

  @media (min-width: 1400px) {
    .cd-col-4 {
      width: 24vw;
    }

    .cd-col-3 {
      width: 18vw;
    }

    .cd-col-2 {
      width: 14vw;
    }
    .cd-col-1 {
      width: 12vw;
    }
  }

  @media (min-width: 1600px) {
    .cd-col-4 {
      width: 22vw;
    }

    .cd-col-3 {
      width: 16vw;
    }

    .cd-col-2 {
      width: 12vw;
    }
    .cd-col-1 {
      width: 10vw;
    }
  }

  @media (min-width: 1800px) {
    .cd-col-3 {
      width: 14vw;
    }

    .cd-col-2 {
      width: 11vw;
    }
    .cd-col-1 {
      width: 9vw;
    }
  }
}
Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""