Skip to content

Multigroup Trend

This demo shows how to render a Multigroup Trend chart. In this trend chart, a line is defined by the combination of multiple attributes. Use the standard trend chart when you just need to group by time and a single attribute.

If you'd like to see the demo in full screen click here

Review the complete source code and copy/paste it to create your own.
<!DOCTYPE html>
<html>

<head lang="en">
  <meta charset="UTF-8">
  <title>Multigroup Trend</title>
  <link rel="stylesheet" href="style.css">
</head>

<body>
  <div class="chart-ct widget">
    <div id="chart">
      <div class="loader"></div>
   </div>
  </div>

  <div id="imanager" class="imanager widget">
    <div class="loader"></div>
  </div>

  <div class="slicer-container">
    <div id="slicer1" class="slicer widget">
      <div class="loader"></div>
    </div>

    <div id="slicer2" class="slicer widget">
      <div class="loader"></div>
    </div>
  </div>
  
  <script src="../assets/jquery.min.js"></script>
  <script src="../../lib/cftoolkit.min.js"></script>
  <script src="../assets/cft-elasticsearch-provider.min.js"></script>
  <script src="../assets/cft-standard-charts.min.js"></script>
  <script src="../assets/cft-tables-charts.min.js"></script>       
  <script src="../assets/cft-interactive-charts.min.js"></script>      
  <script src="./index.js"></script>
  <style>
    .adt-legend .category-list-item {
      font-size: 12px;
    }
  </style>
</body>

</html>
let $ = window.$;
let cf = window.cf;
let source = 'logstash-*';

let hideLoader = function () {
    $('.loader').hide();
};

let updateChart = function (event) {
    // Define the metrics to be used
    let metrics = [];
    let metric = cf.Metric('bytes', 'avg');
    // const countMetric = cf.Metric('count');
    let grid = cf.Grid().left(80).right(50).bottom(55).top(30);

    let legend = cf.Legend()
        .position('right')
        .width(200);

    metrics.push(metric);
    // metrics.push(countMetric);

    let filter = cf.Filter('ip.keyword')
			.label('ip')
			.operation('IN')
			.value(['201.36.182.230']);

    let myChart = cf.provider('Elasticsearch')
        .source(source)
        .rows(cf.Row('@timestamp').sort('asc'),
            'ip.keyword',
            'extension.keyword'
        )
        .metrics(...metrics)
        .filter(filter)
        .graph('Multigroup Trend')
        .set('legend', legend)
        .set('grid', grid)
        .set('showMetricFunc', true)
        .element('chart');

    $('.loader').show();

    myChart.execute()
        .then(function () {
            hideLoader();
        }).catch(function (e) {
            console.log(e);
        });

    cf.provider('Elasticsearch')
            .source(source)
            .groupby(cf.Attribute('ip.keyword').limit(1000).sort('desc', 'ip.keyword'))
            .metrics(metric)
            .filter(filter)
            .slicer()
            .element('slicer1')
            .execute();

    cf.provider('Elasticsearch')
            .source(source)
            .groupby(cf.Attribute('extension.keyword').limit(100).sort('desc', 'extension.keyword'))
            .metrics(metric)
            .filter(filter)
            .slicer()
            .element('slicer2')
            .execute();

    cf.create().imanager().element('imanager').execute();

    let im = cf.getIManager();
    let api = im.get('api');

    api.setFilters([filter]);
    api.updateContent();
    // api.applyFilters();
};

$(document).ready(function () {
    let providers = [{
        name: 'Elasticsearch',
        provider: 'elasticsearch',
        url: 'https://chartfactor.com/elastic/',
        metadata: {
            [source]: {
                fields: {
                    '@timestamp': { 'label': 'Time', 'type': 'TIME', 'timestampGranularity': 'HOUR'}
                }
            }
        }
    }];

    cf.setProviders(providers);
    updateChart();
});
.chart-ct {
    height: calc(50% - 10px);
    width: calc(100% - 10px);
}

#chart{
    width: 100%;
    height: calc(100% - 5px);
}

.widget {
    background: white;
    border: 0.5px solid #CCC;
    margin: 5px;
}

.imanager {
    height: calc(20% - 10px);
    width: calc(100% - 10px);
}

.slicer {
    margin-top: 0;
    height: 100%;
    width: calc(50% - 2px);
}

.slicer-container {
    display: flex;
    height: calc(30% - 10px);
    width: 100%;
}

html, body, .row {
    height: 100%;
    overflow: hidden;
}

.loader {
    position: absolute;
    top: calc(50% - 60px);
    left: calc(50% - 60px);
    border: 16px solid #f3f3f3;
    /* Light grey */
    border-top: 16px solid #24282D;
    /* Blue */
    border-radius: 50%;
    width: 120px;
    height: 120px;
    animation: spin 2s linear infinite;
}

@keyframes spin {
    0% {
        transform: rotate(0deg);
    }
    100% {
        transform: rotate(360deg);
    }
}

body {
    background: #DDD;
}

div::-webkit-scrollbar {
    width: 5px;
    height: 5px;
    border-radius: 5px;
  }
  div::-webkit-scrollbar-track-piece {
    background: #E9ECEF;
    border-radius: 5px;
  }
  div::-webkit-scrollbar-thumb {
    background: #888;
    border-radius: 5px;
  }
  
#adt-legend-more-button {
    font-size: 9px;
}