HighChart- Plot Stacked Bar Chart on Status for Every Minute

Viewed 68

I am trying to plot a Stacked bar chart on every minute(24 hours) status change of a process, i.e. Running or Stop. Chart is having only y-axis with series in milliseconds. But It does not seems to plot the data as expected.

The data which is coming is like below:

19  x   job  process        Stop    NULL    2020-07-14 03:01:02.137 NULL
20  x   job  process        Running NULL    2020-07-14 03:02:02.137 NULL
21  x   job  process        Running NULL    2020-07-14 07:00:00.000 NULL
22  x   job  process        Running NULL    2020-07-14 07:01:00.000 NULL
23  x   job  process        Running NULL    2020-07-14 07:02:00.000 NULL
24  x   job  process        Running NULL    2020-07-14 07:03:00.000 NULL
25  x   job  process        Running NULL    2020-07-14 07:04:00.000 NULL
26  x   job  process        Stop    NULL    2020-07-14 07:05:00.000 NULL
27  x   job  process        Running NULL    2020-07-14 07:06:00.000 NULL
28  x   job  process        Running NULL    2020-07-14 07:07:00.000 NULL
29  x   job  process        Running NULL    2020-07-14 07:08:00.000 NULL

Wher x is the job name and Running and stop is state. I am filtering this data in javascript to create my data series for chart, which is below:

data.forEach((element)=>{
         if(element.State=="Running"){
           var datetime = moment(element.CreatedDateTime).utc().valueOf();
           statusSuccess.push(datetime)
         }
         else{
          var datetime = moment(element.CreatedDateTime).utc().valueOf();
          statusFailure.push(datetime)
         }
    });

The chart plotting and options creation is below:

Highcharts.chart('container', {
      chart: {
        type: 'bar'
      },
      title: {
        text: "24 Hrs Status Variation For: "+this.resoucreName
      },
      credits: {
        enabled: false
      },
      xAxis: {
      
      },
      yAxis: {
          min:moment().subtract(1, 'days').utc().valueOf(),
          dateTimeLabelFormats: {
            second: '%A, %b %e, %H:%M:%S',
            minute: '%A, %b %e, %H:%M',
            hour: '%A, %b %e, %H',
            day: '%H:%M:%S',
            week: '%H:%M:%S',
            month: '%H:%M:%S',
            year: '%H:%M:%S'
          }
      },
      tooltip: {
          pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y:%A, %b %e, %H:%M:%S}</b><br/>',
          shared: true
      },
      legend: {
        reversed: true
    },
      plotOptions: {
          bar: {
            stacking: 'normal'
          }
      },
      series: [{
              name: 'Success',
              color:'#6FF3A3',
              data: statusSuccess,
              type: undefined,
          },
          {
              name: 'Failed',
              color:'#FF386C',
              data: statusFailure,
              type: undefined,
          }
      ]
    });

Below is the chart I am getting: Fiddle

But I am expecting like : ExpectedFiddle

2 Answers

An X-Range plot would (as you also mentioned in your comment) best suit the situation as it can be used to diplay alternating states which can't be done with a stacked bar chart. You first iterate over all job states and on state change ("running -> stop" / "stop -> running") you add the timestamps of start and end to a new array. Then add this array as the data property to the chart.

Remark: if you want to extend the last element to now you will have to add another element to the chart series array with the latest entry.datetime as "x" and new Date().getTime() as "x2".

var data = [{

    "id": 19,
    "name": "x",
    "type": "job",
    "state": "running",
    "datetime": "2020-07-14 03:01:02.137"
  },
  {
    "id": 20,
    "name": "x",
    "type": "job",
    "state": "running",
    "datetime": "2020-07-14 03:01:02.137"
  },
  {
    "id": 21,
    "name": "x",
    "type": "job",
    "state": "Stop",
    "datetime": "2020-07-14 03:02:02.137"
  },
  {
    "id": 22,
    "name": "x",
    "type": "job",
    "state": "running",
    "datetime": "2020-07-14 03:03:02.137"
  },
  {
    "id": 30,
    "name": "x",
    "type": "job",
    "state": "Stop",
    "datetime": "2020-07-14 03:04:02.137"
  },
  {
    "id": 31,
    "name": "x",
    "type": "job",
    "state": "running",
    "datetime": "2020-07-14 03:05:02.137"
  },
  {
    "id": 32,
    "name": "x",
    "type": "job",
    "state": "running",
    "datetime": "2020-07-14 03:06:02.137"
  },
  {
    "id": 33,
    "name": "x",
    "type": "job",
    "state": "running",
    "datetime": "2020-07-14 03:07:02.137"
  },
  {
    "id": 34,
    "name": "x",
    "type": "job",
    "state": "running",
    "datetime": "2020-07-14 03:08:02.137"
  },
  {
    "id": 35,
    "name": "x",
    "type": "job",
    "state": "stop",
    "datetime": "2020-07-14 03:09:02.137"
  }
];

let latestMode = false;
let startTime = false;
let seriesData = [];

for (let entry of data) {
  if (!latestMode) {
    latestMode = entry.state;
    startTime = new Date(entry.datetime);
  } else if (latestMode !== entry.state) {
    let currentTime = new Date(entry.datetime);
    seriesData.push({
      x: startTime.getTime(),
      x2: currentTime.getTime(),
      y: latestMode === 'running' ? 0 : 1

    });
    startTime = currentTime;
    latestMode = entry.state;
  }
}


Highcharts.chart('container', {
  chart: {
    type: 'xrange'
  },
  title: {
    text: 'Job state'
  },
  accessibility: {
    point: {
      descriptionFormatter: function(point) {
        var ix = point.index + 1,
          category = point.yCategory,
          from = new Date(point.x),
          to = new Date(point.x2);
        return ix + '. ' + category + ', ' + from.toDateString() +
          ' to ' + to.toDateString() + '.';
      }
    }
  },
  xAxis: {
    type: 'datetime'
  },
  yAxis: {
    title: {
      text: ''
    },
    categories: ['Running', 'Stopped'],
    reversed: true
  },
  series: [{
    name: 'Job state',
    // pointPadding: 0,
    // groupPadding: 0,
    borderColor: 'gray',
    pointWidth: 20,
    data: seriesData,
    dataLabels: {
      enabled: true
    }
  }]

});
#container {
    height: 300px;
}

.highcharts-figure, .highcharts-data-table table {
    min-width: 320px; 
    max-width: 800px;
    margin: 1em auto;
}

.highcharts-data-table table {
    font-family: Verdana, sans-serif;
    border-collapse: collapse;
    border: 1px solid #EBEBEB;
    margin: 10px auto;
    text-align: center;
    width: 100%;
    max-width: 500px;
}
.highcharts-data-table caption {
    padding: 1em 0;
    font-size: 1.2em;
    color: #555;
}
.highcharts-data-table th {
    font-weight: 600;
    padding: 0.5em;
}
.highcharts-data-table td, .highcharts-data-table th, .highcharts-data-table caption {
    padding: 0.5em;
}
.highcharts-data-table thead tr, .highcharts-data-table tr:nth-child(even) {
    background: #f8f8f8;
}
.highcharts-data-table tr:hover {
    background: #f1f7ff;
}
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/xrange.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="https://code.highcharts.com/modules/accessibility.js"></script>

<figure class="highcharts-figure">
    <div id="container"></div>
</figure>

Here's also a fiddle with the above code

Related