Vega-lite - how to clip bars that extend beyond view range


(Neil Andrassy) #1

I've been trying to build a Gantt style chart showing the execution periods of a bunch of tasks using Vega-lite in Kibana 6.3 (similar to Gantt Visualization Using Vega) with some success. The time window is controlled by Kibana.

When I query the data points I want to include all tasks that 1) started before the end of the window and 2) ended after the start of window (which makes sense once you think about it, honestly!). The issue I'm facing is that I want the x axis of my plot limited to just the time window (say, the last 12 hours), so that the parts of the bars outside the selected window are clipped. The image below shows an example of my problem. The tiny bars on the right are correct, but a handful of long-running task bars caused the plot to stretch back in time further than I want.

While I can use {"%timefilter%": "max|min"} within the query to Elastic, I can't see a way of using these in setting axis bounds. Any suggestions?

Thank-you in advance, Kibana community!


(kulkarni) #2

@nyuriks can u please help here ?

Thanks
Rashmi


(Yuri Astrakhan) #3

Hi @andrassy, could you post your code together with the data, in the same style as I did in the Gantt discussion referenced above? This will make it possible to see the data you are getting, and also better understand what you are trying to do. Thx!


(Neil Andrassy) #4

I think the follow demonstrates my question (but I've embedded the data for ease rather than query from Elastic).

{
  "$schema": "https://vega.github.io/schema/vega-lite/v2.json",
  "title": "Gantt Visualization Using Vega",
  "data": {
    "values": [
      {
        "_source": {
          "id": "totally_inside",
          "start_time": "2018-07-05T12:30:00",
          "end_time": "2018-07-05T13:30:00"
        }
      },
      {
        "_source": {
          "id": "extends_before_and_after",
          "start_time": "2018-07-05T00:00:00",
          "end_time": "2018-07-06T00:00:00"
        }
      },
      {
        "_source": {
          "id": "extends_before",
          "start_time": "2018-07-05T00:00:00",
          "end_time": "2018-07-05T13:00:00"
        }
      },
      {
        "_source": {
          "id": "extends_after",
          "start_time": "2018-07-05T13:00:00",
          "end_time": "2018-07-06T00:00:00"
        }
      }
      
    ]
  },
  "transform": [
    {"calculate": "toDate(datum._source.start_time)", "as": "start"},
    {"calculate": "toDate(datum._source.end_time)", "as": "end"}
  ],
  "mark": {"type": "bar", "filled": true, "clip": true},
  "encoding": {
    "y": {"field": "_source.id", "type": "nominal"},
    "x": {"field": "start", "type": "temporal", 
            "scale": {"domain": ["2018-07-05T12:00:00","2018-07-05T14:00:00"]}
    },
    "x2": {"field": "end", "type": "temporal"}
  }
}

I've added a scale element to the x encoding and limited the domain (so that clipping works). You'll see that of the four bars, three have data that crosses the boundaries of the domain, so get clipped. Essentially,I'd like to know if it's possible to get the domain extents provided by the currently selected time window in Kibana, rather than me providing them - something like this (which doesn't work)...

  "scale":{
    "domain":[{ %timefilter%: "min" },{ %timefilter%: "max" }]
  }

(Neil Andrassy) #5

Hi @nyuriks. Any thoughts on the above?


(Yuri Astrakhan) #6

@andrassy, so sorry missed your message. Now it makes much more sense :slight_smile: So basically it is not really the data-driven domain that you want to use, it is the dashboard time filter context that you need to use in your code. I do not believe it is possible at this point, but I do think it would be easy enough (and worthwhile) to add. Could you add a request to Kibana github, and include the above short snippet frist, followed by the main code?

In the mean time - I wonder if you can construct ES query in such a way so that the server would do this work? Since you already can pass in the timefilter values, you might be able to instruct ES to dynamically calculate the values - e.g. if the value is before timefilter, set it to timefilter? I don't know if its possible though, e.g. if the trimming has to be done as part of a script rather than declarative.


(Neil Andrassy) #7

(Neil Andrassy) #8

I tried to use script_fields functionality of Elastic to make this work, but once again I needed {%timefilter%:min} to be expanded (this time in the params section of the script). Unfortunately this only happens in the query and the aggs elements at present but it does look like a really easy fix. As a quick test of my theory I've simply added a single line of code into Kibana's vega core plugin after line 91 in src\core_plugins\vega\public\data_model\es_query_parser.js, flushed the optimizer cache and restarted Kibana and now it's working!

this._injectContextVars(body.script_fields, false);

To me this looks like it could be a simple addition to the code-base and is reasonably back portable from 7.x to 6.3.x too? What do you think @nyuriks?


(Yuri Astrakhan) #9

@andrassy yep, makes sense. I am not sure how far back i will be allowed to backport it. I might also try to migrate it to the plugin, allowing older version usage. BTW, feel free to submit a PR to expedite it :slight_smile: I will be on vacation for the next week, but will try to work on it afterwards. Lets continue discussion in the github task, i'll add some implementation ideas there


(system) #10

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.