Search code examples
elasticsearchkibanavega-litevega

Change color of fill based off of datum in vega lite


I'm using ELK to visualize the logs which are coming off of our machines using MTConnect. I have a dashboard which I've set to update every sixty seconds, and I want to have a square for each machine and a field called "lastEvent". "lastEvent" can have six states: ACTIVE, READY, STOPPED, INTERRUPTED, PROGRAM_STOPPED and UNAVAILABLE. Each square is already setup to handle logs for only their machine via Elastic Search.

What I want is for the square's color to change based off of the most recent log's "lastEvent", and for this to be updated every time the dashboard refreshes. In the code below, I expect the square to be blue when ACTIVE is received, but the square is pink, which shows no condition was met.

{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {
  "url": {
    "%context%": false,
    "%timefield%": "@timestamp",
    "index": "mtconnect*",
  },
},

"height": "container",
"width": "container",

"mark": "rect",
"encoding": {
  "color": {
    "condition": [
        {"test": "datum['lastEvent'] === 'ACTIVE'", "value": "green"},
        {"test": "datum['lastEvent'] === 'STOPPED'", "value": "red"},
        {"test": "datum['lastEvent'] === 'READY'", "value": "blue"},
        {"test": "datum['lastEvent'] === 'UNAVAILABLE'", "value": "black"},
        {"test": "datum['lastEvent'] === 'PROGRAM_STOPPED'", "value": "pink"},
        {"test": "datum['lastEvent'] === 'FEED_HOLD'", "value": "purple"},
        {"test": "datum['lastEvent'] === 'INTERRUPTED'", "value": "yellow"}
        ],
    "value": "Pink"
  }
}
}

The square does display correctly, so there are no parse errors, and every log has the "lastEvent" field for their respective machine. Reducing the conditions to just one test doesn't fix the issue.

Edit: The conditions work fine. The issue instead is in taking the data from the index and having it evaluate correctly.

There are two issues which I have found. The first is the number of documents being passed. Currently every document is going through the evaluation, and I only want the most current document to be evaluated.

The second issue is 'lastEvent' being evaluated as undefined when I send the value through a text mark. When I used the test data the value was displayed correctly, but this is not the case when I try to pull from the index. For some reason "ACTIVE" from the test data is not the same as "ACTIVE" from the index.

When the data from the index is passed through to Vega, it enters a section labeled "hits". Everything from the hits is presented in one long line, so it may be a formatting issue.


Solution

  • A coworker and I figured out what was causing the issue. When the results of the filters reached Vega, it was formatted as one big line labeled "hits". We added a format section below to make hits a property, and it evaluated correctly.

    "data": {
      url": {
        "%context%": true,
        "%timefield%": "@timestamp",
        "index": "mtconnect*"
      }, 
      "format": {"property": "hits.hits"}
    }
    

    The square is now able to change color with the actual data, rather than the test data.