PHP Classes
elePHPant
Icontem

File: FrontEndScripts/Controllers/MonitoringController.ts

Recommend this page to a friend!
  Classes of Aleksey Nemiro  >  PHP Small Server Administrator  >  FrontEndScripts/Controllers/MonitoringController.ts  >  Download  
File: FrontEndScripts/Controllers/MonitoringController.ts
Role: Auxiliary data
Content type: text/plain
Description: Auxiliary data
Class: PHP Small Server Administrator
Web panel for small Debian and Ubuntu servers
Author: By
Last change:
Date: 3 years ago
Size: 19,230 bytes
 

 

Contents

Class file image Download
?/*
 * Copyright  Aleksey Nemiro, 2016. All rights reserved.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
module SmallServerAdmin.Controllers {

  /**
   * Represents server monitoring controller.
   */
  export class MonitoringController implements Nemiro.IController {

    public Scope: any;
    public Context: Nemiro.AngularContext;

    /** The list of processes. */
    public get Processes(): Array<Models.Process> {
      return this.Scope.Processes;
    }
    public set Processes(value: Array<Models.Process>) {
      this.Scope.Processes = value;
    }

    /** Search string. */
    public get SearchString(): string {
      return this.Scope.SearchString;
    }
    public set SearchString(value: string) {
      this.Scope.SearchString = value;
    }

    public get SearchStringInput(): string {
      return this.Scope.SearchStringInput;
    }
    public set SearchStringInput(value: string) {
      this.Scope.SearchStringInput = value;
    }

    /** Info loading indicator. */
    public get InfoLoading(): boolean {
      return this.Scope.InfoLoading;
    }
    public set InfoLoading(value: boolean) {
      this.Scope.InfoLoading = value;
    }

    /** Loading indicator. */
    public get Loading(): boolean {
      return this.Scope.Loading;
    }
    public set Loading(value: boolean) {
      this.Scope.Loading = value;
    }

    public get DynamicsCPU(): Array<number> {
      return this.Scope.DynamicsCPU;
    }
    public set DynamicsCPU(value: Array<number>) {
      this.Scope.DynamicsCPU = value;
    }

    public get MemoryTotal(): number {
      return this.Scope.MemoryTotal;
    }
    public set MemoryTotal(value: number) {
      this.Scope.MemoryTotal = value;
    }

    public get MemoryFree(): number {
      return this.Scope.MemoryFree;
    }
    public set MemoryFree(value: number) {
      this.Scope.MemoryFree = value;
    }

    public get MemoryFreePercent(): number {
      return this.Scope.MemoryFreePercent;
    }
    public set MemoryFreePercent(value: number) {
      this.Scope.MemoryFreePercent = value;
    }

    public get DynamicsMemoryTotal(): Array<number> {
      return this.Scope.DynamicsMemoryTotal;
    }
    public set DynamicsMemoryTotal(value: Array<number>) {
      this.Scope.DynamicsMemoryTotal = value;
    }

    public get DynamicsMemoryUsage(): Array<number> {
      return this.Scope.DynamicsMemoryUsage;
    }
    public set DynamicsMemoryUsage(value: Array<number>) {
      this.Scope.DynamicsMemoryUsage = value;
    }

    public get DynamicsHDDTotal(): Array<number> {
      return this.Scope.DynamicsHDDTotal;
    }
    public set DynamicsHDDTotal(value: Array<number>) {
      this.Scope.DynamicsHDDTotal = value;
    }

    public get DynamicsHDDUsage(): Array<number> {
      return this.Scope.DynamicsHDDUsage;
    }
    public set DynamicsHDDUsage(value: Array<number>) {
      this.Scope.DynamicsHDDUsage = value;
    }

    public get HDDTotal(): number {
      return this.Scope.HDDTotal;
    }
    public set HDDTotal(value: number) {
      this.Scope.HDDTotal = value;
    }

    public get HDDFree(): number {
      return this.Scope.HDDFree;
    }
    public set HDDFree(value: number) {
      this.Scope.HDDFree = value;
    }

    public get SelectedProcessToKill(): Models.Process {
      return this.Scope.SelectedProcessToKill;
    }
    public set SelectedProcessToKill(value: Models.Process) {
      this.Scope.SelectedProcessToKill = value;
    }

    public get SortField(): string {
      return this.Scope.SortField;
    }
    public set SortField(value: string) {
      this.Scope.SortField = value;
    }

    public get SortReverse(): boolean {
      return this.Scope.SortReverse;
    }
    public set SortReverse(value: boolean) {
      this.Scope.SortReverse = value;
    }

    public get CPU(): Array<number> {
      return this.Scope.CPU;
    }
    public set CPU(value: Array<number>) {
      this.Scope.CPU = value;
    }

    public get IndicatorsRefreshInterval(): number {
      return this.Scope.IndicatorsRefreshInterval;
    }
    public set IndicatorsRefreshInterval(value: number) {
      this.Scope.IndicatorsRefreshInterval = value;
    }

    public get ProcessesRefreshInterval(): number {
      return this.Scope.ProcessesRefreshInterval;
    }
    public set ProcessesRefreshInterval(value: number) {
      this.Scope.ProcessesRefreshInterval = value;
    }

    public get RefreshDisabled(): boolean {
      return this.Scope.RefreshDisabled;
    }
    public set RefreshDisabled(value: boolean) {
      this.Scope.RefreshDisabled = value;
    }

    public get KillSignal(): string {
      return this.Scope.KillSignal;
    }
    public set KillSignal(value: string) {
      this.Scope.KillSignal = value;
    }

    private ConfirmToKillProcess: Nemiro.UI.Dialog;

    constructor(context: Nemiro.AngularContext) {
      var $this = this;

      $this.Context = context;
      $this.Scope = $this.Context.Scope;

      var settings = {};
      if ($this.Context.Window.localStorage['Monitoring'] !== undefined && $this.Context.Window.localStorage['Monitoring'] != null && $this.Context.Window.localStorage['Monitoring'] != '') {
        settings = $.parseJSON($this.Context.Window.localStorage['Monitoring']);
      }

      $this.DynamicsCPU = new Array<number>();
      $this.DynamicsMemoryUsage = new Array<number>();
      $this.DynamicsMemoryTotal = new Array<number>();
      $this.DynamicsHDDTotal = new Array<number>();
      $this.DynamicsHDDUsage = new Array<number>();
      $this.CPU = new Array<number>();

      $this.SortField = 'Name';
      $this.SortReverse = false;
      
      $this.IndicatorsRefreshInterval = (settings['IndicatorsRefreshInterval'] || 3);
      $this.ProcessesRefreshInterval = (settings['ProcessesRefreshInterval'] || 30);

      $this.SearchString = $this.SearchStringInput = $this.Context.Location.search()['search'];

      $this.ConfirmToKillProcess = Nemiro.UI.Dialog.CreateFromElement($('#confirmToKillProcess'));

      $this.Scope.SetIndicatorsRefreshInterval = (interval: number) => {
        $this.Context.Window.localStorage['Monitoring'] = $.toJSON({ IndicatorsRefreshInterval: interval, ProcessesRefreshInterval: $this.ProcessesRefreshInterval});
        $this.IndicatorsRefreshInterval = interval;

        if (interval > 0) {
          $this.Context.Timeout(() => { $this.GetInfo($this, false); }, interval * 1000);
        }
      }

      $this.Scope.SetProcessesRefreshInterval = (interval: number) => {
        $this.Context.Window.localStorage['Monitoring'] = $.toJSON({ IndicatorsRefreshInterval: $this.IndicatorsRefreshInterval, ProcessesRefreshInterval: interval });
        $this.ProcessesRefreshInterval = interval;

        if (interval > 0) {
          $this.Context.Timeout(() => { $this.Load($this); }, interval * 1000);
        }
      }

      $this.Scope.Load = () => { $this.Load($this); }
      $this.Scope.Refresh = () => {
        $this.RefreshDisabled = true;
        $this.Context.Timeout(() => { $this.RefreshDisabled = false; }, 1000);
        $this.GetInfo($this, false);
        $this.Load($this);
      }

      $this.Scope.Search = () => {
        $this.SearchString = $this.SearchStringInput;
        $this.Context.Location.search('search', $this.SearchString);
        $this.Load($this);
      }

      $this.Scope.ResetSearch = () => {
        $this.SearchString = $this.SearchStringInput = '';
        $this.Context.Location.search('search', null);
        $this.Load($this);
      }

      $this.Scope.GetProcessStatusCss = $this.GetProcessStatusCss;

      $this.Scope.ConfirmKill = (process: Models.Process) => {
        $this.KillSignal = 'SIGTERM';
        $this.SelectedProcessToKill = process;
        $this.ConfirmToKillProcess.Show();
      }

      $this.Scope.KillProcess = () => {
        $this.KillProcess($this);
      }

      // charts
      $this.InitCPUChart($this);
      $this.InitMemoryChart($this);
      $this.InitHDDChart($this);

      $this.GetInfo($this, true);
    }

    private InitCPUChart($this: MonitoringController): void {
      $this.Scope.ChartCPU = {
        options: {
          chart: {
            type: 'area',
            backgroundColor: null,
            borderWidth: 0,
            margin: [2, 0, 2, 0]
          },
          legend: {
            enabled: false
          },
          credits: {
            enabled: false
          },
          exporting: {
            enabled: false
          },
          tooltip: {
            backgroundColor: null,
            borderWidth: 0,
            shadow: false,
            useHTML: true,
            hideDelay: 0,
            shared: true,
            padding: 0,
            positioner: (w, h, point) => {
              return { x: point.plotX - w / 2, y: point.plotY - h };
            },
            //valueSuffix: '%'
            formatter: () => {
              var y = eval('this').y;
              return '<div class="chart-tooltip">' + y + '%</div>';
            }
          },
          plotOptions: {
            series: {
              marker: {
                enabled: false
              }
            }
          }
        },
        series: [{
          data: $this.DynamicsCPU
        }],
        title: {
          text: ''
        },
        loading: false,
        yAxis: {
          min: 0,
          max: 100,
          labels: {
            enabled: false
          },
          title: {
            text: null
          },
          startOnTick: false,
          endOnTick: false,
          tickPositions: []
        },
        useHighStocks: false
        /*size: {
          width: 120,
          height: 35
        }*/
      };
    }

    private InitMemoryChart($this: MonitoringController): void {
      $this.Scope.ChartMemory = {
        options: {
          chart: {
            type: 'area',
            backgroundColor: null,
            borderWidth: 0,
            margin: [2, 0, 2, 0]
          },
          legend: {
            enabled: false
          },
          credits: {
            enabled: false
          },
          exporting: {
            enabled: false
          },
          tooltip: {
            backgroundColor: null,
            borderWidth: 0,
            shadow: false,
            useHTML: true,
            hideDelay: 0,
            shared: true,
            padding: 0,
            positioner: (w, h, point) => {
              return { x: point.plotX - w / 2, y: point.plotY - h };
            },
            //valueSuffix: ' Mb',
            formatter: () => {
              var points = eval('this').points;
              return '<div class="chart-tooltip">' +
                '<strong>' + App.Resources.Total + ':</strong> ' + points[0].y + ' ' + App.Resources.Mb + '<br />' +
                (points.length > 1 ? '<strong>' + App.Resources.InUse + ':</strong> ' + points[1].y + ' ' + App.Resources.Mb + '' : '') +
                '</div>';
            }
          },
          plotOptions: {
            series: {
              marker: {
                enabled: false
              }
            }
          }
        },
        series: [{
          name: 'Total',
          data: $this.DynamicsMemoryTotal,
          color: '#90ed7d'
        }, {
          name: 'In Use',
          data: $this.DynamicsMemoryUsage,
          color: '#c0453c'
        }],
        title: {
          text: ''
        },
        loading: false,
        yAxis: {
          min: 0,
          max: $this.MemoryTotal,
          labels: {
            enabled: false
          },
          title: {
            text: null
          },
          startOnTick: false,
          endOnTick: false,
          tickPositions: []
        },
        useHighStocks: false
        /*size: {
          width: 120,
          height: 35
        }*/
      };
    }

    private InitHDDChart($this: MonitoringController): void {
      $this.Scope.ChartHDD = {
        options: {
          chart: {
            type: 'area',
            backgroundColor: null,
            borderWidth: 0,
            margin: [2, 0, 2, 0]
          },
          legend: {
            enabled: false
          },
          credits: {
            enabled: false
          },
          exporting: {
            enabled: false
          },
          tooltip: {
            backgroundColor: null,
            borderWidth: 0,
            shadow: false,
            useHTML: true,
            hideDelay: 0,
            shared: true,
            padding: 0,
            positioner: (w, h, point) => {
              return { x: point.plotX - w / 2, y: point.plotY - h };
            },
            //valueSuffix: ' Mb',
            formatter: () => {
              var points = eval('this').points;
              return '<div class="chart-tooltip">' +
                '<strong>' + App.Resources.Total + ':</strong> ' + points[0].y + ' ' + App.Resources.Gb + '<br />' +
                (points.length > 1 ? '<strong>' + App.Resources.InUse + ':</strong> ' + points[1].y + ' ' + App.Resources.Gb : '') +
                '</div>';
            }
          },
          plotOptions: {
            series: {
              marker: {
                enabled: false
              }
            }
          }
        },
        series: [{
          name: 'Total',
          data: $this.DynamicsHDDTotal,
          color: '#90ed7d'
        }, {
            name: 'In Use',
            data: $this.DynamicsHDDUsage,
            color: '#c0453c'
          }],
        title: {
          text: ''
        },
        loading: false,
        yAxis: {
          min: 0,
          max: $this.MemoryTotal,
          labels: {
            enabled: false
          },
          title: {
            text: null
          },
          startOnTick: false,
          endOnTick: false,
          tickPositions: []
        },
        useHighStocks: false
        /*size: {
          width: 120,
          height: 35
        }*/
      };
    }

    private GetInfo($this: MonitoringController, getProcessList: boolean): void {
      $this = $this || this;

      if ($this.InfoLoading) {
        return;
      }
      
      $this.InfoLoading = true;

      // create request
      var apiRequest = new ApiRequest<Models.ServerInfo>($this.Context, 'Monitoring.GetInfo');

      // handler successful response to a request to api
      apiRequest.SuccessCallback = (response) => {
        //$this.Processes = response.data;

        $this.CPU = response.data.CPU;
        $this.DynamicsCPU.push(response.data.CPU[0]);
        $this.MemoryTotal = Math.round((response.data.Memory.Total / 1024 / 1024) * 100) / 100; //.toFixed(2)
        $this.MemoryFree = Math.round((response.data.Memory.Free / 1024 / 1024) * 100) / 100;
        $this.MemoryFreePercent = ((response.data.Memory.Free * 100) / response.data.Memory.Total);
        $this.DynamicsMemoryUsage.push(Math.round(((response.data.Memory.Total - response.data.Memory.Free) / 1024 / 1024) * 100) / 100);
        //console.log('Memory', response.data.Memory.Total / 1024 / 1024, response.data.Memory.Free / 1024 / 1024, Math.round(((response.data.Memory.Total - response.data.Memory.Free) / 1024 / 1024) * 100) / 100);
        $this.DynamicsMemoryTotal.push(Math.round((response.data.Memory.Total / 1024 / 1024) * 100) / 100);

        var hddTotal = 0, hddAvailable = 0; 
        angular.forEach(response.data.HDD,(item: Models.HDDInfo) => {
          hddTotal += item.Total;
          hddAvailable += item.Available;
        });

        $this.DynamicsHDDTotal.push(Math.round((hddTotal / 1024 / 1024) * 100) / 100);
        $this.DynamicsHDDUsage.push(Math.round(((hddTotal - hddAvailable) / 1024 / 1024) * 100) / 100);

        $this.HDDTotal = Math.round((hddTotal / 1024 / 1024) * 100) / 100;
        $this.HDDFree = Math.round((hddAvailable / 1024 / 1024) * 100) / 100;

        if ($this.DynamicsCPU.length > 100) {
          $this.DynamicsCPU.shift();
        }

        if ($this.DynamicsMemoryUsage.length > 100) {
          $this.DynamicsMemoryUsage.shift();
        }

        if ($this.DynamicsMemoryTotal.length > 100) {
          $this.DynamicsMemoryTotal.shift();
        }

        if ($this.DynamicsHDDTotal.length > 100) {
          $this.DynamicsHDDTotal.shift();
        }

        if ($this.DynamicsHDDUsage.length > 100) {
          $this.DynamicsHDDUsage.shift();
        }

        if (getProcessList) {
          $this.Load($this);
        }
      };
      
      apiRequest.CompleteCallback = () => {
        $this.InfoLoading = false;

        if ($this.IndicatorsRefreshInterval > 0) {
          $this.Context.Timeout(() => {
            $this.GetInfo($this, false);
          }, $this.IndicatorsRefreshInterval * 1000);
        }
      };

      // execute
      apiRequest.Execute();
    }

    private Load($this: MonitoringController): void {
      $this = $this || this;

      if ($this.Loading) {
        return;
      }

      $this.Loading = true;

      // create request
      var apiRequest = new ApiRequest<Array<Models.Process>>($this.Context, 'Monitoring.GetProcesses', { search: $this.SearchString });

      // handler successful response to a request to api
      apiRequest.SuccessCallback = (response) => {
        $this.Processes = response.data;
      };
      
      apiRequest.CompleteCallback = () => {
        $this.Loading = false;

        if ($this.ProcessesRefreshInterval > 0) {
          $this.Context.Timeout(() => {
            $this.Load($this);
          }, $this.ProcessesRefreshInterval * 1000);
        }
      };

      // execute
      apiRequest.Execute();
    }

    private GetProcessStatusCss(status: string): string {
      if (status == null || status == '') {
        return '';
      }

      var result = '';

      if (status == 'R') {
        return 'process-status-running';
      }

      if (status == 'T') {
        return 'process-status-stopped';
      }

      if (status == 'S+') {
        return 'process-status-top';
      }

      if (status[0] == 'S') {
        return 'process-status-s';
      }

      return '';
    }

    private KillProcess($this: MonitoringController): void {
      $this.SelectedProcessToKill.Loading = true;
      $this.ConfirmToKillProcess.Close();

      var apiRequest = new ApiRequest<Array<Models.Process>>($this.Context, 'Monitoring.KillProcess', { pid: $this.SelectedProcessToKill.PID, signal: $this.KillSignal });

      apiRequest.SuccessCallback = (response) => {
        $this.Load($this);
      };

      apiRequest.CompleteCallback = () => {
        if ($this.SelectedProcessToKill != null) {
          $this.SelectedProcessToKill.Loading = false;
        }
      };

      // execute
      apiRequest.Execute();
    }

  }

}