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