mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
Closes issue #340. Legend now has human readable date formats. I've passed in the field formatters to format the values. The solution however is not ideal as I have had to duplicate code in several places. This fix should work without fault, but it needs to be revised in the future.
This commit is contained in:
parent
eeb94f03ff
commit
8c9a36f91e
9 changed files with 66 additions and 32 deletions
|
@ -25,7 +25,7 @@ Kibana is an open source (Apache Licensed), browser based analytics and search d
|
|||
|
||||
You're up and running! Fantastic! Kibana is now running on port 5601, so point your browser at http://YOURDOMAIN.com:5601.
|
||||
|
||||
The first screen you arrive at will ask you to configure an **index pattern**. An index pattern describes to Kibana how to access your data. We make the guess that you're working with log data, and we hope (because it's awesome) that you're working with Logstash. By default, we fill in `logstash-*` as your index pattern, thus the only thing you need to do is select which field contains the timestamp you'd like to use. Kibana reads your Elasticsearch mapping to find your time fields - select one from the list and hit *Create*.
|
||||
The first screen you arrive at will ask you to configure an **index pattern**. An index pattern describes to kibana how to access your data. We make the guess that you're working with log data, and we hope (because it's awesome) that you're working with Logstash. By default, we fill in `logstash-*` as your index pattern, thus the only thing you need to do is select which field contains the timestamp you'd like to use. Kibana reads your Elasticsearch mapping to find your time fields - select one from the list and hit *Create*.
|
||||
|
||||
**Tip:** there's an optimization in the way of the *Use event times to create index names* option. Since Logstash creates an index every day, Kibana uses that fact to only search indices that could possibly contain data in your selected time range.
|
||||
|
||||
|
@ -128,7 +128,7 @@ Or HTML
|
|||
status:[400 TO 499] AND (extension:php OR extension:html)
|
||||
```
|
||||
|
||||
While Lucene query syntax is simple and very powerful, Kibana also supports the full Elasticsearch, JSON based, Query DSL. See the [Elasticsearch documentation](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html#query-string-syntax) for usage and examples.
|
||||
While lucene query syntax is simple and very powerful, Kibana also supports the full elasticsearch, JSON based, query DSL. See the [Elasticsearch documentation](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html#query-string-syntax) for usage and examples.
|
||||
<!-- /include -->
|
||||
<!-- include {"path":"docs/visualize.md"} -->
|
||||
## Visualize
|
||||
|
@ -163,7 +163,7 @@ To the right of the search box there are a row of icons for creating new visuali
|
|||
|
||||
#### Aggregation Builder
|
||||
|
||||
The aggregation builder on the left of the screen is used for configuring the [metric](http://www.elasticsearch.org/guide/en/elasticsearch/reference/1.x/search-aggregations.html#_metrics_aggregations) and [bucket](http://www.elasticsearch.org/guide/en/elasticsearch/reference/1.x/search-aggregations.html#_bucket_aggregations) aggregations used to create a visualization. (If you are coming from the SQL world, buckets are similar to group-bys. Check out the [Elasticsearch docs](http://www.elasticsearch.org/guide/en/elasticsearch/reference/1.x/search-aggregations.html) for more info) For a bar chart or line chart the *metric* is used for the y-axis and the *buckets* are used for the x-axis, segment bar colors, and row/column splits. For pie charts the "metric" is used for the size of the slice and the *bucket* is used for the number of slices. Other visualizations may use these in new and different ways.
|
||||
The aggregation builder on the left of the screen is used for configuring the [metric](http://www.elasticsearch.org/guide/en/elasticsearch/reference/1.x/search-aggregations.html#_metrics_aggregations) and [bucket](http://www.elasticsearch.org/guide/en/elasticsearch/reference/1.x/search-aggregations.html#_bucket_aggregations) aggregations used to create a visualization. (If you are coming from the SQL world, buckets are similar to group-bys. Check out the [elasticsearch docs](http://www.elasticsearch.org/guide/en/elasticsearch/reference/1.x/search-aggregations.html) for more info) For a bar chart or line chart the *metric* is used for the y-axis and the *buckets* are used for the x-axis, segment bar colors, and row/column splits. For pie charts the "metric" is used for the size of the slice and the *bucket* is used for the number of slices. Other visualizations may use these in new and different ways.
|
||||
|
||||
For the remainder of this documentation we are going to use the bar chart as our example when discussing the features of the aggregation panel. The same concepts apply to the other visualizations but the bar chart is the workhorse of the visualization world.
|
||||
|
||||
|
@ -314,4 +314,4 @@ Clicking on the *View* action loads that item in the associated applications. Re
|
|||
Clicking *Edit* will allow you to change the title, description and other settings of the saved object. You can also edit the schema of the stored object.
|
||||
|
||||
*Note:* this operation is for advanced users only - making changes here can break large portions of the application.
|
||||
<!-- /include -->
|
||||
<!-- /include -->
|
|
@ -20,8 +20,17 @@ define(function (require) {
|
|||
throw new Error('LabelUtil expects an object');
|
||||
}
|
||||
|
||||
var raw;
|
||||
var fieldIndex;
|
||||
if (obj.raw) {
|
||||
raw = obj.raw.columns;
|
||||
fieldIndex = _.findIndex(raw, {'categoryName': 'group'});
|
||||
}
|
||||
|
||||
var fieldFormatter = raw && raw[fieldIndex] ? raw[fieldIndex].field.format.convert : function (d) { return d; };
|
||||
|
||||
// Returns an array of unique chart labels
|
||||
return getArrOfUniqLabels(getArr(obj));
|
||||
return getArrOfUniqLabels(getArr(obj), fieldFormatter);
|
||||
};
|
||||
};
|
||||
});
|
||||
|
|
|
@ -3,13 +3,19 @@ define(function (require) {
|
|||
var _ = require('lodash');
|
||||
|
||||
// Takes an array of objects
|
||||
return function (arr) {
|
||||
return function (arr, formatter) {
|
||||
if (!_.isArray(arr)) {
|
||||
throw TypeError('UniqLabelUtil expects an array of objects');
|
||||
}
|
||||
|
||||
// Returns a array of unique chart labels
|
||||
return _.uniq(_.pluck(arr, 'label'));
|
||||
return _(arr)
|
||||
.pluck('label')
|
||||
.unique()
|
||||
.map(function (d) {
|
||||
return formatter(d);
|
||||
})
|
||||
.value();
|
||||
};
|
||||
};
|
||||
});
|
||||
|
|
|
@ -170,17 +170,18 @@ define(function (require) {
|
|||
// Helper function for getNames
|
||||
// Returns an array of objects with a name (key) value and an index value.
|
||||
// The index value allows us to sort the names in the correct nested order.
|
||||
Data.prototype.returnNames = function (array, index) {
|
||||
Data.prototype.returnNames = function (array, index, columns) {
|
||||
var names = [];
|
||||
var self = this;
|
||||
|
||||
_.forEach(array, function (obj) {
|
||||
names.push({ key: obj.name, index: index });
|
||||
var fieldFormatter = columns[index].field.format.convert;
|
||||
names.push({ key: fieldFormatter(obj.name), index: index });
|
||||
|
||||
if (obj.children) {
|
||||
var plusIndex = index + 1;
|
||||
|
||||
_.forEach(self.returnNames(obj.children, plusIndex), function (namedObj) {
|
||||
_.forEach(self.returnNames(obj.children, plusIndex, columns), function (namedObj) {
|
||||
names.push(namedObj);
|
||||
});
|
||||
}
|
||||
|
@ -194,9 +195,10 @@ define(function (require) {
|
|||
// Returns an array with names sorted by the index value.
|
||||
Data.prototype.getNames = function () {
|
||||
var data = this.data.slices;
|
||||
var columns = this.data.raw.columns;
|
||||
|
||||
if (data.children) {
|
||||
var namedObj = this.returnNames(data.children, 0);
|
||||
var namedObj = this.returnNames(data.children, 0, columns);
|
||||
|
||||
return _(namedObj)
|
||||
.sortBy(function (obj) {
|
||||
|
|
|
@ -33,16 +33,6 @@ define(function (require) {
|
|||
'defaultOpacity' : 1,
|
||||
'isOpen' : true
|
||||
});
|
||||
|
||||
// Adding field formatter for formatting legend labels
|
||||
var raw;
|
||||
var fieldIndex;
|
||||
if (this.vis.data.raw) {
|
||||
raw = this.vis.data.raw.columns;
|
||||
fieldIndex = _.findIndex(raw, {'categoryName': 'group'});
|
||||
}
|
||||
|
||||
this.fieldFormatter = raw && raw[fieldIndex] ? raw[fieldIndex].field.format.convert : function (d) { return d; };
|
||||
}
|
||||
|
||||
// Add legend header
|
||||
|
@ -77,7 +67,7 @@ define(function (require) {
|
|||
})
|
||||
.html(function (d) {
|
||||
// return the appropriate color for each dot
|
||||
return '<span class="dots" style="background:' + args.color(d) + '"></span>' + self.fieldFormatter(d);
|
||||
return '<span class="dots" style="background:' + args.color(d) + '"></span>' + d;
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -18,6 +18,16 @@ define(function (require) {
|
|||
return new ColumnChart(handler, chartEl, chartData);
|
||||
}
|
||||
|
||||
var raw;
|
||||
var fieldIndex;
|
||||
|
||||
if (chartData.raw) {
|
||||
raw = chartData.raw.columns;
|
||||
fieldIndex = _.findIndex(raw, {'categoryName': 'group'});
|
||||
}
|
||||
|
||||
this.fieldFormatter = raw && raw[fieldIndex] ? raw[fieldIndex].field.format.convert : function (d) { return d; };
|
||||
|
||||
ColumnChart.Super.apply(this, arguments);
|
||||
// Column chart specific attributes
|
||||
this._attr = _.defaults(handler._attr || {}, {
|
||||
|
@ -75,10 +85,10 @@ define(function (require) {
|
|||
bars.enter()
|
||||
.append('rect')
|
||||
.attr('class', function (d) {
|
||||
return self.colorToClass(color(d.label));
|
||||
return self.colorToClass(color(self.fieldFormatter(d.label)));
|
||||
})
|
||||
.attr('fill', function (d) {
|
||||
return color(d.label);
|
||||
return color(self.fieldFormatter(d.label));
|
||||
});
|
||||
|
||||
// update
|
||||
|
|
|
@ -14,6 +14,16 @@ define(function (require) {
|
|||
return new LineChart(handler, chartEl, chartData);
|
||||
}
|
||||
|
||||
var raw;
|
||||
var fieldIndex;
|
||||
|
||||
if (chartData.raw) {
|
||||
raw = chartData.raw.columns;
|
||||
fieldIndex = _.findIndex(raw, {'categoryName': 'group'});
|
||||
}
|
||||
|
||||
this.fieldFormatter = raw && raw[fieldIndex] ? raw[fieldIndex].field.format.convert : function (d) { return d; };
|
||||
|
||||
LineChart.Super.apply(this, arguments);
|
||||
// Line chart specific attributes
|
||||
this._attr = _.defaults(handler._attr || {}, {
|
||||
|
@ -88,13 +98,13 @@ define(function (require) {
|
|||
.enter()
|
||||
.append('circle')
|
||||
.attr('class', function circleClass(d) {
|
||||
return self.colorToClass(color(d.label));
|
||||
return self.colorToClass(color(self.fieldFormatter(d.label)));
|
||||
})
|
||||
.attr('fill', function (d) {
|
||||
return color(d.label);
|
||||
return color(self.fieldFormatter(d.label));
|
||||
})
|
||||
.attr('stroke', function strokeColor(d) {
|
||||
return color(d.label);
|
||||
return color(self.fieldFormatter(d.label));
|
||||
})
|
||||
.attr('stroke-width', circleStrokeWidth);
|
||||
|
||||
|
@ -149,14 +159,14 @@ define(function (require) {
|
|||
|
||||
lines.append('path')
|
||||
.attr('class', function lineClass(d) {
|
||||
return self.colorToClass(color(d.label));
|
||||
return self.colorToClass(color(self.fieldFormatter(d.label)));
|
||||
})
|
||||
.attr('d', function lineD(d) {
|
||||
return line(d.values);
|
||||
})
|
||||
.attr('fill', 'none')
|
||||
.attr('stroke', function lineStroke(d) {
|
||||
return color(d.label);
|
||||
return color(self.fieldFormatter(d.label));
|
||||
})
|
||||
.attr('stroke-width', 2);
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@ define(function (require) {
|
|||
}
|
||||
PieChart.Super.apply(this, arguments);
|
||||
|
||||
this.columns = chartData.raw.columns;
|
||||
|
||||
this._attr = _.defaults(handler._attr || {}, {
|
||||
getSize: function (d) { return d.size; },
|
||||
dispatch: d3.dispatch('brush', 'click', 'hover', 'mouseenter', 'mouseleave', 'mouseover', 'mouseout')
|
||||
|
@ -84,6 +86,7 @@ define(function (require) {
|
|||
var isTooltip = this._attr.addTooltip;
|
||||
var self = this;
|
||||
var path;
|
||||
var fieldFormatter;
|
||||
|
||||
path = svg
|
||||
.datum(slices)
|
||||
|
@ -94,12 +97,16 @@ define(function (require) {
|
|||
.attr('d', arc)
|
||||
.attr('class', function (d) {
|
||||
if (d.depth === 0) { return; }
|
||||
return self.colorToClass(color(d.name));
|
||||
|
||||
fieldFormatter = self.columns[d.depth - 1].field.format.convert;
|
||||
return self.colorToClass(color(fieldFormatter(d.name)));
|
||||
})
|
||||
.style('stroke', '#fff')
|
||||
.style('fill', function (d) {
|
||||
if (d.depth === 0) { return 'none'; }
|
||||
return color(d.name);
|
||||
|
||||
fieldFormatter = self.columns[d.depth - 1].field.format.convert;
|
||||
return color(fieldFormatter(d.name));
|
||||
});
|
||||
|
||||
// Add tooltip
|
||||
|
|
|
@ -224,7 +224,7 @@ define(function (require) {
|
|||
beforeEach(function () {
|
||||
inject(function (d3, Private) {
|
||||
uniqLabels = Private(require('components/vislib/components/labels/uniq_labels'));
|
||||
uniq = uniqLabels(arrObj);
|
||||
uniq = uniqLabels(arrObj, function (d) { return d; });
|
||||
testArr = _.isArray(uniq);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue