github.com/siglens/siglens@v0.0.0-20240328180423-f7ce9ae441ed/static/js/service-health.js (about)

     1  /*
     2  Copyright 2023.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  'use strict';
    18  
    19  let redMetricsData ={
    20      "indexName":  "red-traces",
    21  }
    22  $(document).ready(() => {
    23      if (Cookies.get("theme")) {
    24          theme = Cookies.get("theme");
    25          $("body").attr("data-theme", theme);
    26      }
    27      $(".theme-btn").on("click", themePickerHandler);
    28  
    29      let stDate = "now-15m";
    30      let endDate = "now";
    31      datePickerHandler(stDate, endDate, stDate);
    32      $('.range-item').on('click', isServiceHealthDatePickerHandler);
    33      let data = getTimeRange();
    34      redMetricsData = {... redMetricsData, ... data};
    35      getAllServices();
    36      
    37      $('.search-input').on('input', filterServicesBySearch);
    38  });
    39  
    40  function isServiceHealthDatePickerHandler(evt) {
    41      evt.preventDefault();
    42      $.each($(".range-item.active"), function () {
    43          $(this).removeClass('active');
    44      });
    45      $(evt.currentTarget).addClass('active');
    46      datePickerHandler($(this).attr('id'), "now", $(this).attr('id'))
    47      getAllServices();
    48      $('#daterangepicker').hide();
    49  }
    50  
    51  function getTimeRange() {
    52      return {
    53          'startEpoch': filterStartDate || "now-1h",
    54          'endEpoch': filterEndDate || "now",
    55      };
    56  }
    57  let gridDiv = null;
    58  let serviceRowData = [];
    59  const columnDefs=[
    60      { headerName: "Service", field: "service"},
    61      { headerName: "Rate (Request per Second)", field: "rate"},
    62      { headerName: "Error (% of Rate)", field: "error"},
    63      { headerName: 'P50 (in ms)', field: 'p50' },
    64      { headerName: 'P90 (in ms)', field: 'p90' },
    65      { headerName: 'P99 (in ms)', field: 'p99' },
    66  ];
    67  
    68  const gridOptions = {
    69      rowData: serviceRowData ,
    70      onRowClicked: onRowClicked,
    71      headerHeight:32,
    72      rowHeight: 42,
    73      defaultColDef: {
    74      cellClass: 'align-center-grid',
    75        resizable: true,
    76        sortable: true,
    77        animateRows: true,
    78        readOnlyEdit: true,
    79        autoHeight: true,
    80        icons: {
    81            sortAscending: '<i class="fa fa-sort-alpha-down"/>',
    82            sortDescending: '<i class="fa fa-sort-alpha-up"/>',
    83          },
    84      },
    85      columnDefs:columnDefs,
    86  };
    87  
    88  function filterServicesBySearch() {
    89      const searchValue = $('.search-input').val().toLowerCase();
    90      const filteredData = serviceRowData.filter(service => 
    91          service.service.toLowerCase().startsWith(searchValue)
    92      );
    93      gridOptions.api.setRowData(filteredData);
    94  }
    95  
    96  function processRedMetricsData(metricsData) {
    97      let latestMetrics = {};
    98      metricsData.forEach(metric => {
    99          const serviceName = metric.service;
   100          const metricTimestamp = metric.timestamp;
   101  
   102          if (!latestMetrics[serviceName] || latestMetrics[serviceName].timestamp < metricTimestamp) {
   103              latestMetrics[serviceName] = metric;
   104          }
   105      });
   106  
   107      return Object.values(latestMetrics);
   108  }
   109  
   110  function getAllServices(){
   111      data = getTimeRange();
   112      redMetricsData = {... redMetricsData, ... data}
   113      $.ajax({
   114          method: "POST",
   115          url: "api/search",
   116          headers: {
   117              'Content-Type': 'application/json; charset=utf-8',
   118              'Accept': '*/*'
   119          },
   120          data: JSON.stringify(redMetricsData),
   121          dataType: 'json',
   122          crossDomain: true,
   123      }).then(function (res) {
   124          const processedData = processRedMetricsData(res.hits.records);
   125          displayServiceHealthTable(processedData);
   126      })
   127  }
   128  
   129  function displayServiceHealthTable(res){
   130      if (gridDiv === null) {
   131          gridDiv = document.querySelector('#ag-grid');
   132          new agGrid.Grid(gridDiv, gridOptions);
   133      }
   134      gridOptions.api.setColumnDefs(columnDefs);
   135      let newRow = new Map()
   136      serviceRowData=[]
   137      $.each(res, function (key, value) {
   138          newRow.set("rowId", key);
   139          newRow.set("service", value.service);
   140          newRow.set("rate", (Math.abs(value.rate) % 1 === 0 ? Math.abs(value.rate) : Number(value.rate).toFixed(2)).toLocaleString("en-US"));
   141          newRow.set("error", (Math.abs(value.error_rate) % 1 === 0 ? Math.abs(value.error_rate) : Number(value.error_rate).toFixed(2)).toLocaleString("en-US"));
   142          newRow.set("p50", value.p50.toLocaleString("en-US"));
   143          newRow.set("p90", value.p90.toLocaleString("en-US"));
   144          newRow.set("p99", value.p99.toLocaleString("en-US"));
   145  
   146          serviceRowData = _.concat(serviceRowData, Object.fromEntries(newRow));
   147      })
   148      gridOptions.api.setRowData(serviceRowData);
   149      gridOptions.api.sizeColumnsToFit();
   150      gridOptions.columnApi.applyColumnState({
   151          state: [{ colId: 'error', sort: 'desc' }],
   152          defaultState: { sort: null },
   153      });
   154  }
   155  
   156  function onRowClicked(event) {
   157      const serviceName = event.data.service; 
   158      window.location.href = 'service-health-overview.html?service=' + encodeURIComponent(serviceName);
   159  }
   160  
   161