Skip to content

Instantly share code, notes, and snippets.

@nyurik
Last active April 16, 2020 18:05
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nyurik/3c579fb8e81c8a981d4b267ad1767227 to your computer and use it in GitHub Desktop.
Save nyurik/3c579fb8e81c8a981d4b267ad1767227 to your computer and use it in GitHub Desktop.
{
$schema: https://vega.github.io/schema/vega/v3.json
data: [
{
name: esdata
url: {
%context%: true
%timefield%: @timestamp
index: logstash-*
body: {
aggs: {
extensions: {
terms: {field: "extension.keyword", size: 4}
aggs: {
time_buckets: {
date_histogram: {
field: @timestamp
interval: {%autointerval%: true}
extended_bounds: {
min: {%timefilter%: "min"}
max: {%timefilter%: "max"}
}
min_doc_count: 0
}
}
}
}
}
size: 0
}
}
format: {property: "aggregations.extensions.buckets"}
}
{
name: flatdata
source: esdata
transform: [
{
type: flatten
fields: ["time_buckets.buckets"]
as: ["val"]
}
]
}
{
name: hasSelection
values: [
{}
]
transform: [
{type: "filter", expr: "selected[0] != selected[1]"}
]
}
]
scales: [
{
name: groupScale
type: band
padding: 0.1
domain: {data: "esdata", field: "key", sort: true}
range: height
}
{
name: xScale
type: time
domain: {data: "flatdata", field: "val.key"}
range: width
padding: 5
}
{
name: yScale
type: linear
domain: {data: "flatdata", field: "val.doc_count"}
range: [
{signal: "bandwidth('groupScale')"}
0
]
}
{
name: colorScale
type: ordinal
domain: {data: "esdata", field: "key", sort: true}
range: category
}
]
axes: [
{orient: "bottom", scale: "xScale", tickCount: 5}
]
signals: [
{
name: currentX
value: -1
on: [
{events: "view:mousemove", update: "clamp(x(), 0, width)"}
{events: "view:mouseout", update: "-1"}
]
}
{
name: selected
value: [0, 0]
on: [
{events: "@grapharea:mousedown", update: "[x(), x()]"}
{
events: "[@grapharea:mousedown, window:mouseup] > window:mousemove!"
update: "[selected[0], clamp(x(), 0, width)]"
}
{
events: {signal: "delta"}
update: clampRange([anchor[0] + delta, anchor[1] + delta], 0, width)
}
{
events: "[@leftEdge:mousedown, window:mouseup] > window:mousemove!"
update: "[clamp(x(), 0, width), selected[1]]"
}
{
events: "[@rightEdge:mousedown, window:mouseup] > window:mousemove!"
update: "[selected[0], clamp(x(), 0, width)]"
}
]
}
{
name: anchor
value: null
on: [
{events: "@selectedRect:mousedown", update: "selected"}
]
}
{
name: xDown
value: 0
on: [
{events: "@selectedRect:mousedown", update: "x()"}
]
}
{
name: delta
value: 0
on: [
{events: "[@selectedRect:mousedown, window:mouseup] > window:mousemove!", update: "x() - xDown"}
]
}
{
name: applyTimeFilter
on: [
{
events: @applyTimeFilterButton:click, @selectedRect:dblclick
update:
'''
kibanaSetTimeFilter(
invert('xScale',selected[0]),
invert('xScale',selected[1]))
'''
}
{events: "@grapharea:dblclick", update: "kibanaSetTimeFilter('now-15d', 'now')"}
]
}
]
marks: [
{
name: grapharea
type: group
from: {
facet: {name: "facets", data: "esdata", field: "time_buckets.buckets"}
}
encode: {
update: {
y: {scale: "groupScale", field: "key"}
height: {scale: "groupScale", band: 1}
x: {value: 0}
width: {signal: "width"}
fillOpacity: {value: 0}
fill: {value: "#000"}
}
}
axes: [
{
orient: left
scale: yScale
title: {signal: "parent.key"}
tickCount: 7
encode: {
title: {
name: extFilter
interactive: true
update: {
cursor: {value: "pointer"}
fontSize: {value: 14}
fill: {value: "steelblue"}
}
hover: {
fill: {value: "firebrick"}
}
}
}
}
]
signals: [
{
name: updateFilterObj
on: [
{
events: {source: "scope", markname: "extFilter", type: "click"}
update:
'''
{
match: {
'extension.keyword': {
query: parent.key,
type: 'phrase'
}}}
'''
}
]
}
{
name: applyFilterObj
on: [
{
events: {signal: "updateFilterObj"}
update: length(domain('groupScale')) > 1 ? kibanaAddFilter(updateFilterObj) : kibanaRemoveFilter(updateFilterObj)
}
]
}
]
marks: [
{
type: line
from: {data: "facets"}
interactive: false
encode: {
update: {
x: {scale: "xScale", field: "key"}
y: {scale: "yScale", field: "doc_count"}
stroke: {
scale: colorScale
field: {parent: "key"}
}
}
}
}
{
type: group
from: {data: "hasSelection"}
marks: [
{
name: selectedRect
type: rect
encode: {
update: {
height: {scale: "groupScale", band: 1}
fill: {value: "#333"}
fillOpacity: {value: 0.2}
cursor: {value: "move"}
x: {signal: "selected[0]"}
x2: {signal: "selected[1]"}
}
}
}
{
name: leftEdge
type: rect
encode: {
update: {
height: {scale: "groupScale", band: 1}
width: {value: 2}
fill: {value: "firebrick"}
cursor: {value: "ew-resize"}
x: {signal: "selected[0]"}
}
}
}
{
name: rightEdge
type: rect
encode: {
update: {
height: {scale: "groupScale", band: 1}
width: {value: 2}
fill: {value: "firebrick"}
cursor: {value: "ew-resize"}
x: {signal: "selected[1]"}
}
}
}
]
}
]
}
{
type: group
name: applyTimeFilterButton
from: {data: "hasSelection"}
encode: {
update: {
cursor: {value: "pointer"}
cornerRadius: {value: 6}
fill: {value: "#f5f5f5"}
stroke: {value: "#c1c1c1"}
strokeWidth: {value: 2}
xc: {signal: "width/2"}
y: {value: 30}
width: {value: 80}
height: {value: 30}
opacity: {value: 1}
}
hover: {
opacity: {value: 0.7}
}
}
marks: [
{
type: text
interactive: false
encode: {
update: {
xc: {
field: {group: "width"}
mult: 0.5
}
yc: {
field: {group: "height"}
mult: 0.5
offset: 2
}
align: {value: "center"}
baseline: {value: "middle"}
fontWeight: {value: "bold"}
text: {value: "Apply Filter"}
}
}
}
]
}
{
type: rule
interactive: false
encode: {
update: {
y: {value: 0}
y2: {signal: "height"}
stroke: {value: "gray"}
strokeDash: {
value: [2, 1]
}
x: {signal: "max(currentX,0)"}
strokeOpacity: {signal: "currentX > 0 ? 1 : 0"}
}
}
}
]
}
@stephanie-cherba
Copy link

This example doesn't work. When I try to run the graph in Kibana, it can't read property extensions of undefined.

@nyurik
Copy link
Author

nyurik commented Jun 26, 2019

I suspect this is because you don't have logstash data. What result do you see if you run the above query in the dev tools (you will need to remove all params with the % in them)

@stephanie-cherba
Copy link

Yes, sorry, thank you! I just needed to switch to a different data source. Sorry!

@stephanie-cherba
Copy link

Sorry to keep commenting here, but there isn't a whole lot on the web about these filtering capabilities, so you seem to be the only resource I can find. The thing I'm really struggling with is how to set the range of the groupScale when dealing with a visualization that doesn't have nested graphs to make the visualization take up the whole height of the graph when the scale type is band (which I know is necessary for the click and drag capability). I did it by setting the range to a step, but the step number would change for every graph and one would have to estimate this number and play with it to get it right. I originally had the range set to height, but then the visualization only takes up a small fraction of the areas height, and is at the far top.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment