summaryrefslogtreecommitdiff
path: root/sflow-rt/app/browse-metrics
diff options
context:
space:
mode:
Diffstat (limited to 'sflow-rt/app/browse-metrics')
-rw-r--r--sflow-rt/app/browse-metrics/LICENSE21
-rw-r--r--sflow-rt/app/browse-metrics/README.md10
-rw-r--r--sflow-rt/app/browse-metrics/html/index.html80
-rw-r--r--sflow-rt/app/browse-metrics/html/js/app.js226
4 files changed, 337 insertions, 0 deletions
diff --git a/sflow-rt/app/browse-metrics/LICENSE b/sflow-rt/app/browse-metrics/LICENSE
new file mode 100644
index 0000000..1ee363b
--- /dev/null
+++ b/sflow-rt/app/browse-metrics/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2019 InMon Corporation
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/sflow-rt/app/browse-metrics/README.md b/sflow-rt/app/browse-metrics/README.md
new file mode 100644
index 0000000..edd31d9
--- /dev/null
+++ b/sflow-rt/app/browse-metrics/README.md
@@ -0,0 +1,10 @@
+# Browse metrics
+
+## To install
+
+1. [Download sFlow-RT](https://sflow-rt.com/download.php)
+2. Run command: `sflow-rt/get-app.sh sflow-rt browse-metrics`
+3. Restart sFlow-RT
+
+For more information, visit:
+https://sFlow-RT.com
diff --git a/sflow-rt/app/browse-metrics/html/index.html b/sflow-rt/app/browse-metrics/html/index.html
new file mode 100644
index 0000000..bbb210a
--- /dev/null
+++ b/sflow-rt/app/browse-metrics/html/index.html
@@ -0,0 +1,80 @@
+<!doctype html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+ <link rel="icon" type="image/png" href="../../../inc/img/favicon.png">
+ <link rel="stylesheet" href="../../../inc/bootstrap.min.css">
+ <link rel="stylesheet" href="../../../inc/stripchart.css">
+ <script type="text/javascript" src="../../../inc/jquery.min.js"></script>
+ <script type="text/javascript" src="../../../inc/jquery.widget.js"></script>
+ <script type="text/javascript" src="../../../inc/jquery.stripchart.js"></script>
+ <script type="text/javascript" src="../../../inc/popper.min.js"></script>
+ <script type="text/javascript" src="../../../inc/bootstrap.min.js"></script>
+ <script type="text/javascript" src="js/app.js"></script>
+ <title>Metric Browser</title>
+ </head>
+ <body>
+ <nav class="navbar navbar-dark mb-3" style="background-color: #336;">
+ <a class="navbar-brand" href="#">
+ <img src="../../../inc/img/inmon.svg" height="30" class="d-inline-block align-top">
+ Metric Browser
+ </a>
+ <form class="form-inline">
+ <button id="clone" class="btn btn-outline-light" type="button">Clone</button>
+ </form>
+ </nav>
+ <main class="container" role="main">
+ <form>
+ <div class="form-row">
+ <div class="form-group col-md-4">
+ <label for="agent">Agent</label>
+ <select class="form-control" id="agent">
+ </select>
+ </div>
+ <div class="form-group col-md-4">
+ <label for="metric">Metric</label>
+ <select class="form-control" id="metric">
+ </select>
+ </div>
+ <div class="form-group col-md-2">
+ <label for="datasource">Datasource</label>
+ <select class="form-control" id="datasource">
+ </select>
+ </div>
+ <div class="form-group col-md-2">
+ <label for="aggregation">Statistic</label>
+ <select class="form-control" id="aggregation">
+ <option value="max">max</option>
+ <option value="min">min</option>
+ <option value="sum">sum</option>
+ <option value="avg">avg</option>
+ <option value="var">var</option>
+ <option value="sdev">sdev</option>
+ <option value="med">med</option>
+ <option value="q1">q1</option>
+ <option value="q2">q2</option>
+ <option value="q3">q3</option>
+ <option value="iqr">iqr</option>
+ <option value="any">any</option>
+ </select>
+ </div>
+ </div>
+ </form>
+ <table class="table table-striped table-bordered table-sm">
+ <tbody>
+ <tr><td class="text-right font-weight-bold" style="width: 50%">Value</td><td id="metric-value" style="width: 50%"></td></tr>
+ <tr><td class="text-right font-weight-bold" style="width: 50%">N</td><td id="metric-n" style="width: 50%"></td></tr>
+ <tr><td class="text-right font-weight-bold" style="width: 50%">Agent</td><td id="metric-agent" style="width: 50%"></td></tr>
+ <tr><td class="text-right font-weight-bold" style="wdith: 50%">Datasource</td><td id="metric-datasource" style="width: 50%"></td></tr>
+ </tbody>
+ </table>
+ <div id="chart" class="trend" style="height:300px"></div>
+ </main>
+ <footer class="footer page-footer border-top mt-3">
+ <div class="footer-copyright text-center py-2">
+ <small class="text-muted">Copyright &copy; 2015-<span class="year">2019</span> InMon Corp. ALL RIGHTS RESERVED</small>
+ </div>
+ </footer>
+ </body>
+</html>
diff --git a/sflow-rt/app/browse-metrics/html/js/app.js b/sflow-rt/app/browse-metrics/html/js/app.js
new file mode 100644
index 0000000..4847897
--- /dev/null
+++ b/sflow-rt/app/browse-metrics/html/js/app.js
@@ -0,0 +1,226 @@
+$(function() {
+ var defaults = {
+ agent: 'ALL',
+ datasource: 'ALL',
+ aggregation: 'max'
+ };
+
+ var state = {};
+ $.extend(state,defaults);
+
+ function createQuery(params) {
+ var query, key, value;
+ for(key in params) {
+ value = params[key];
+ if(value === defaults[key]) continue;
+ if(query) query += '&';
+ else query = '';
+ query += encodeURIComponent(key)+'='+encodeURIComponent(value);
+ }
+ return query;
+ }
+
+ function getState(key, defVal) {
+ return window.sessionStorage.getItem('mb_'+key) || state[key] || defVal;
+ }
+
+ function setState(key, val, showQuery) {
+ state[key] = val;
+ window.sessionStorage.setItem('mb_'+key, val);
+ if(showQuery) {
+ var query = createQuery(state);
+ window.history.replaceState({},'',query ? '?' + query : './');
+ }
+ }
+
+ function setQueryParams(query) {
+ var vars = query.split('&');
+ var params = {};
+ for(var i = 0; i < vars.length; i++) {
+ var pair = vars[i].split('=');
+ if(pair.length === 2) setState(decodeURIComponent(pair[0]), decodeURIComponent(pair[1]),false);
+ }
+ }
+
+ var search = window.location.search;
+ if(search) setQueryParams(search.substring(1));
+
+ $('#clone').click(function() {
+ window.open(window.location);
+ });
+
+ var selectedAgent = getState('agent');
+ var selectedMetric = getState('metric');
+ var selectedDatasource = getState('datasource');
+ var selectedAggregation = getState('aggregation');
+
+ var names = {};
+ var maxPoints = 5 * 60;
+ var step = 1000;
+ var chartData;
+
+ var nf = $.inmon.stripchart.prototype.valueStr;
+
+ var widget = $('#chart').stripchart();
+
+ function resetChart() {
+ chartData = {times:[], values: []};
+ var i, t = Date.now();
+ for(i = 0; i < maxPoints; i++) {
+ t = t - step;
+ chartData.times.unshift(t);
+ }
+ var series = new Array(chartData.times.length);
+ for(i = 0; i < chartData.times.length; i++) series[i] = 0;
+ chartData.values.push(series);
+ }
+
+ function updateChart(data) {
+ if(!data || data.length === 0) return;
+ if(!chartData) resetChart();
+
+ var now = Date.now();
+ chartData.times.push(now);
+ var tmin = now - (maxPoints * 1.04 * step);
+ var nshift = 0;
+ while(chartData.times.length >= maxPoints || chartData.times[0] < tmin) {
+ chartData.times.shift();
+ nshift++;
+ }
+ var series = chartData.values[0];
+ var val = data[0].metricValue;
+ series.push($.isNumeric(val) ? val : 0);
+ for(var i = 0; i < nshift; i++) {
+ series.shift();
+ }
+ widget.stripchart("draw", chartData);
+ $('#metric-agent').text(data[0].agent || '');
+ $('#metric-datasource').text(data[0].dataSource || '');
+ $('#metric-value').text($.isNumeric(val) ? nf(val) : val);
+ $('#metric-n').text(data[0].metricN || '');
+ }
+
+ $(window).resize(function() {
+ widget.stripchart("draw", chartData);
+ });
+
+ function updateMetrics() {
+ names = {};
+ if('ALL' == selectedAgent) {
+ $.get('../../../metrics/json', function(metrics) {
+ var metricSelect = $('#metric');
+ var dsSelect = $('#datasource');
+ var i, metricsList = Object.keys(metrics).sort();
+ if(!metrics[selectedMetric]) {
+ selectedMetric = metricsList[0];
+ setState('metric',selectedMetric,true);
+ }
+ metricSelect.empty();
+ for(i = 0; i < metricsList.length; i++) {
+ metricSelect.append('<option value="'+metricsList[i]+'"' + (selectedMetric == metricsList[i] ? ' selected' : '') + '>'+metricsList[i]+'</option>');
+ }
+ dsSelect.empty();
+ dsSelect.append('<option value="ALL" selected>ALL</option>');
+ selectedDatasource = 'ALL';
+ setState('datasource',selectedDatasource,true);
+ resetChart();
+ });
+ } else {
+ $.get('../../../metric/'+selectedAgent+'/json',function(metrics) {
+ var metricSelect = $('#metric');
+ var dsSelect = $('#datasource');
+ var i, idx, ds, dsName, dsList, name, nameList, metricsList = Object.keys(metrics);
+ for(i = 0; i < metricsList.length; i++) {
+ idx = metricsList[i].lastIndexOf('.');
+ ds = metricsList[i].substring(0,idx);
+ name = metricsList[i].substring(idx+1);
+ dsList = names[name];
+ if(!dsList) {
+ dsList = {};
+ names[name] = dsList;
+ };
+ dsList[ds] = metrics[ds+'.vir_host_name'] || metrics[ds+'.host_name'] || metrics[ds+'.ifname'] || ds;;
+ }
+ nameList = Object.keys(names).sort();
+ if(!names[selectedMetric]) {
+ selectedMetric = nameList[0];
+ setState('metric',selectedMetric,true);
+ }
+ metricSelect.empty();
+ for(i = 0; i < nameList.length; i++) {
+ metricSelect.append('<option value="'+nameList[i]+'"' + (selectedMetric == nameList[i] ? ' selected' : '') + '>'+nameList[i]+'</option>');
+ }
+ dsList = Object.keys(names[selectedMetric]).sort((a,b) => a - b);
+ dsSelect.empty();
+ dsSelect.append('<option value="ALL"'+('ALL' === selectedDatasource ? ' selected' : '')+'>ALL</option>');
+ for(i = 0; i < dsList.length; i++) {
+ ds = dsList[i];
+ dsName = names[selectedMetric][ds];
+ dsSelect.append('<option value="'+ds+'"'+(ds === selectedDatasource ? ' selected' : '')+'>'+dsName+'</options>');
+ }
+ resetChart();
+ });
+ }
+ }
+ $('#agent').change(function(evt) {
+ selectedAgent = $('#agent').children('option:selected').val();
+ setState('agent',selectedAgent,true);
+ updateMetrics();
+ });
+ $('#metric').change(function(evt) {
+ selectedMetric = $('#metric').children('option:selected').val();
+ setState('metric',selectedMetric,true);
+ var dsSelect = $('#datasource');
+ var i, ds, dsName, dsList = Object.keys(names[selectedMetric] || {});
+ dsSelect.empty();
+ if(dsList) {
+ dsList.sort((a,b) => a - b);
+ dsSelect.append('<option value="ALL">ALL</option>');
+ for(i = 0; i < dsList.length; i++) {
+ ds = dsList[i];
+ dsName = names[selectedMetric][ds];
+ dsSelect.append('<option value="'+ds+'">'+dsName+'</options>');
+ }
+ } else {
+ dsSelect.append('<option value="ALL" selected>ALL</option>');
+ }
+ resetChart();
+ });
+ $('#datasource').change(function(evt) {
+ selectedDatasource = $('#datasource').children('option:selected').val();
+ setState('datasource',selectedDatasource,true);
+ resetChart();
+ });
+ $('#aggregation option[value="'+selectedAggregation+'"]').prop('selected',true);
+ $('#aggregation').change(function(evt) {
+ selectedAggregation = $('#aggregation').children('option:selected').val();
+ setState('aggregation',selectedAggregation,true);
+ resetChart();
+ });
+ $.get('../../../agents/json', function(agents) {
+ var agentSelect = $('#agent');
+ var i, agentList = Object.keys(agents).sort();
+ agentSelect.append('<option value="ALL"'+('ALL' === selectedAgent ? ' selected' : '')+'>ALL</option>');
+ for(i = 0; i < agentList.length; i++) {
+ agentSelect.append('<option value="'+agentList[i]+'"'+(agentList[i] === selectedAgent ? ' selected' : '')+'>'+agentList[i]+'</option>');
+ }
+ updateMetrics();
+ resetChart();
+ });
+ (function poll() {
+ var metric = (!selectedDatasource || 'ALL' === selectedDatasource ? '' : selectedDatasource + '.') + selectedMetric;
+ var url = '../../../metric/'+selectedAgent+'/'+selectedAggregation+':'+metric+'/json';
+ $.ajax({
+ url: url,
+ success: function(data) {
+ updateChart(data);
+ setTimeout(poll, step);
+ },
+ error: function(result,status,errorThrown) {
+ setTimeout(poll, 5000);
+ },
+ dataType: "json",
+ timeout: 60000
+ });
+ })();
+});