mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
Merge branch 'master' of github.com:elastic/kibana into add/jscs
This commit is contained in:
commit
da16712f7b
187 changed files with 2638 additions and 597 deletions
1
.node-version
Normal file
1
.node-version
Normal file
|
@ -0,0 +1 @@
|
|||
0.10.x
|
|
@ -9,8 +9,8 @@ script:
|
|||
- npm test
|
||||
notifications:
|
||||
email:
|
||||
- rashid.khan@elasticsearch.com
|
||||
- spencer.alger@elasticsearch.com
|
||||
- rashid.khan@elastic.co
|
||||
- spencer.alger@elastic.co
|
||||
hipchat:
|
||||
rooms:
|
||||
secure: UKrVR+5KztHarodQruQe97UJfwftutD6RNdXlVkr+oIr2GqccisDIIN9pAzS/kxl+eAnP1uT6VHzc9YI/jgbrmiSkz3DHViw+MwDwY2aIDgI8aHEbd/4B2ihtb15+OYTVbb+lytyz4+W8A8hSmbkTR/P/uFIJ+EYcBeYZfw1elo=
|
||||
|
|
|
@ -6,7 +6,7 @@ The process for contributing to any of the Elasticsearch repositories is similar
|
|||
|
||||
### Sign the contributor license agreement
|
||||
|
||||
Please make sure you have signed the [Contributor License Agreement](http://www.elasticsearch.org/contributor-agreement/). We are not asking you to assign copyright to us, but to give us the right to distribute your code without restriction. We ask this of all contributors in order to assure our users of the origin and continuing existence of the code. You only need to sign the CLA once.
|
||||
Please make sure you have signed the [Contributor License Agreement](http://www.elastic.co/contributor-agreement/). We are not asking you to assign copyright to us, but to give us the right to distribute your code without restriction. We ask this of all contributors in order to assure our users of the origin and continuing existence of the code. You only need to sign the CLA once.
|
||||
|
||||
### Development Environment Setup
|
||||
|
||||
|
|
14
Gruntfile.js
14
Gruntfile.js
|
@ -37,6 +37,20 @@ module.exports = function (grunt) {
|
|||
'<%= src %>/server/*.js',
|
||||
'<%= src %>/kibana/{components,directives,factories,filters,plugins,registry,services,utils}/**/*.js',
|
||||
'<%= unitTestDir %>/**/*.js'
|
||||
],
|
||||
lessFiles: [
|
||||
'<%= src %>/kibana/components/*/*.less',
|
||||
'<%= src %>/kibana/styles/main.less',
|
||||
'<%= src %>/kibana/components/vislib/styles/main.less',
|
||||
'<%= plugins %>/dashboard/styles/main.less',
|
||||
'<%= plugins %>/discover/styles/main.less',
|
||||
'<%= plugins %>/settings/styles/main.less',
|
||||
'<%= plugins %>/visualize/styles/main.less',
|
||||
'<%= plugins %>/visualize/styles/visualization.less',
|
||||
'<%= plugins %>/visualize/styles/main.less',
|
||||
'<%= plugins %>/table_vis/table_vis.less',
|
||||
'<%= plugins %>/metric_vis/metric_vis.less',
|
||||
'<%= plugins %>/markdown_vis/markdown_vis.less'
|
||||
]
|
||||
};
|
||||
|
||||
|
|
19
README.md
19
README.md
|
@ -1,8 +1,8 @@
|
|||
# Kibana 4.1.0-snapshot
|
||||
|
||||
[](https://travis-ci.org/elasticsearch/kibana?branch=master)
|
||||
[](https://travis-ci.org/elastic/kibana?branch=master)
|
||||
|
||||
Kibana is an open source ([Apache Licensed](https://github.com/elasticsearch/kibana/blob/master/LICENSE.md)), browser based analytics and search dashboard for Elasticsearch. Kibana is a snap to setup and start using. Kibana strives to be easy to get started with, while also being flexible and powerful, just like Elasticsearch.
|
||||
Kibana is an open source ([Apache Licensed](https://github.com/elastic/kibana/blob/master/LICENSE.md)), browser based analytics and search dashboard for Elasticsearch. Kibana is a snap to setup and start using. Kibana strives to be easy to get started with, while also being flexible and powerful, just like Elasticsearch.
|
||||
|
||||
## Requirements
|
||||
|
||||
|
@ -11,7 +11,7 @@ Kibana is an open source ([Apache Licensed](https://github.com/elasticsearch/kib
|
|||
|
||||
## Installation
|
||||
|
||||
* Download: [http://www.elasticsearch.org/overview/kibana/installation/](http://www.elasticsearch.org/overview/kibana/installation/)
|
||||
* Download: [http://www.elastic.co/downloads/kibana](http://www.elastic.co/downloads/kibana)
|
||||
* Run `bin/kibana` on unix, or `bin\kibana.bat` on Windows.
|
||||
* Visit [http://localhost:5601](http://localhost:5601)
|
||||
|
||||
|
@ -31,4 +31,15 @@ Now that you've configured an index pattern, you're ready to hop over to the [Di
|
|||
|
||||
## Documentation
|
||||
|
||||
Visit [Elasticsearch.org](http://www.elasticsearch.org/guide/en/kibana/current/index.html) for the full Kibana documentation.
|
||||
Visit [Elastic.co](http://www.elastic.co/guide/en/kibana/current/index.html) for the full Kibana documentation.
|
||||
|
||||
## Snapshot Builds
|
||||
|
||||
For the daring, snapshot builds are available. These builds are created after each commit to the master branch, and therefore are not something you should run in production.
|
||||
|
||||
| platform | | |
|
||||
| --- | --- | --- |
|
||||
| OSX | [tar](http://download.elastic.co/kibana/kibana/kibana-4.1.0-snapshot-darwin-x64.tar.gz) | [zip](http://download.elastic.co/kibana/kibana/kibana-4.1.0-snapshot-darwin-x64.zip) |
|
||||
| Linux x64 | [tar](http://download.elastic.co/kibana/kibana/kibana-4.1.0-snapshot-linux-x64.tar.gz) | [zip](http://download.elastic.co/kibana/kibana/kibana-4.1.0-snapshot-linux-x64.zip) |
|
||||
| Linux x86 | [tar](http://download.elastic.co/kibana/kibana/kibana-4.1.0-snapshot-linux-x86.tar.gz) | [zip](http://download.elastic.co/kibana/kibana/kibana-4.1.0-snapshot-linux-x86.zip) |
|
||||
| Windows | [tar](http://download.elastic.co/kibana/kibana/kibana-4.1.0-snapshot-windows.tar.gz) | [zip](http://download.elastic.co/kibana/kibana/kibana-4.1.0-snapshot-windows.zip) |
|
|
@ -11,7 +11,7 @@
|
|||
"elasticsearch"
|
||||
],
|
||||
"license": "Apache 2.0",
|
||||
"homepage": "http://www.elasticsearch.org/overview/kibana/",
|
||||
"homepage": "http://www.elastic.co/products/kibana",
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
|
|
|
@ -7,7 +7,7 @@ specify the port number. For example, `localhost:5601` or `http://YOURDOMAIN.com
|
|||
|
||||
When you access Kibana, the Discover page loads by default with the default index
|
||||
pattern selected. The time filter is set to the last 15 minutes and the search
|
||||
query is set to match-all (*).
|
||||
query is set to match-all (\*).
|
||||
|
||||
If you don't see any documents, try setting the time filter to a wider time range.
|
||||
If you still don't see any results, it's possible that you don't *have* any documents.
|
||||
If you still don't see any results, it's possible that you don't *have* any documents.
|
62
docs/area.asciidoc
Normal file
62
docs/area.asciidoc
Normal file
|
@ -0,0 +1,62 @@
|
|||
[[area-chart]]
|
||||
=== Area Charts
|
||||
|
||||
This chart's Y axis is the _metrics_ axis. The following aggregations are available for this axis:
|
||||
|
||||
*Count*:: The {ref}/search-aggregations-metrics-valuecount-aggregation.html[_count_] aggregation returns a raw count of
|
||||
the elements in the selected index pattern.
|
||||
*Average*:: This aggregation returns the {ref}/search-aggregations-metrics-avg-aggregation.html[_average_] of a numeric
|
||||
field. Select a field from the drop-down.
|
||||
*Sum*:: The {ref}/search-aggregations-metrics-sum-aggregation.html[_sum_] aggregation returns the total sum of a numeric
|
||||
field. Select a field from the drop-down.
|
||||
*Min*:: The {ref}/search-aggregations-metrics-min-aggregation.html[_min_] aggregation returns the minimum value of a
|
||||
numeric field. Select a field from the drop-down.
|
||||
*Max*:: The {ref}/search-aggregations-metrics-max-aggregation.html[_max_] aggregation returns the maximum value of a
|
||||
numeric field. Select a field from the drop-down.
|
||||
*Unique Count*:: The {ref}/search-aggregations-metrics-cardinality-aggregation.html[_cardinality_] aggregation returns
|
||||
the number of unique values in a field. Select a field from the drop-down.
|
||||
*Percentile*:: The {ref}/search-aggregations-metrics-percentile-rank-aggregation.html[_percentile_] aggregation returns
|
||||
the percentile rank of values in a numeric field. Select a field from the drop-down, then specify a range in the
|
||||
*Percentiles* fields. Click the *X* to remove a percentile field. Click *+ Add Percent* to add a percentile field.
|
||||
|
||||
You can add an aggregation by clicking the *+ Add Aggregation* button.
|
||||
|
||||
include::x-axis-aggs.asciidoc[]
|
||||
For example, a chart of dates with incident counts can display dates in chronological order, or you can raise the
|
||||
priority of the incident-reporting aggregation to show the most active dates first. The chronological order might show
|
||||
a time-dependent pattern in incident count, and sorting by active dates can reveal particular outliers in your data.
|
||||
|
||||
You can click the *Advanced* link to display more customization options for your metrics or bucket aggregation:
|
||||
|
||||
*Exclude Pattern*:: Specify a pattern in this field to exclude from the results.
|
||||
*Exclude Pattern Flags*:: A standard set of Java flags for the exclusion pattern.
|
||||
*Include Pattern*:: Specify a pattern in this field to include in the results.
|
||||
*Include Pattern Flags*:: A standard set of Java flags for the inclusion pattern.
|
||||
*JSON Input*:: A text field where you can add specific JSON-formatted properties to merge with the aggregation
|
||||
definition, as in the following example:
|
||||
|
||||
[source,shell]
|
||||
{ "script" : "doc['grade'].value * 1.2" }
|
||||
|
||||
NOTE: In Elasticsearch releases 1.4.3 and later, this functionality requires you to enable
|
||||
{ref}/modules-scripting[dynamic Groovy scripting].
|
||||
|
||||
The availability of these options varies depending on the aggregation you choose.
|
||||
|
||||
Select *view options* to change the following aspects of the table:
|
||||
|
||||
*Chart Mode*:: When you have multiple Y-axis aggregations defined for your chart, you can use this drop-down to affect
|
||||
how the aggregations display on the chart:
|
||||
|
||||
_stacked_:: Stacks the aggregations on top of each other.
|
||||
_overlap_:: The aggregations overlap, with translucency indicating areas of overlap.
|
||||
_wiggle_:: Displays the aggregations as a https://en.wikipedia.org/wiki/Streamgraph[streamgraph].
|
||||
_percentage_:: Displays each aggregation as a proportion of the total.
|
||||
_silhouette_:: Displays each aggregation as variance from a central line.
|
||||
|
||||
Checkboxes are available to enable and disable the following behaviors:
|
||||
|
||||
*Show Tooltip*:: Check this box to enable the display of tooltips.
|
||||
*Show Legend*:: Check this box to enable the display of a legend next to the chart.
|
||||
*Scale Y-Axis to Data Bounds*:: The default Y axis bounds are zero and the maximum value returned in the data. Check
|
||||
this box to change both upper and lower bounds to match the values returned in the data.
|
63
docs/datatable.asciidoc
Normal file
63
docs/datatable.asciidoc
Normal file
|
@ -0,0 +1,63 @@
|
|||
[[data-table]]
|
||||
=== Data Table
|
||||
|
||||
include::y-axis-aggs.asciidoc[]
|
||||
|
||||
The rows of the data table are called _buckets_. You can define buckets to split the table into rows or to split
|
||||
the table into additional tables.
|
||||
|
||||
Each bucket type supports the following aggregations:
|
||||
|
||||
*Date Histogram*:: A {ref}/search-aggregations-bucket-datehistogram-aggregation.html[_date histogram_] is built from a
|
||||
numeric field and organized by date. You can specify a time frame for the intervals in seconds, minutes, hours, days,
|
||||
weeks, months, or years.
|
||||
*Histogram*:: A standard {ref}/search-aggregations-bucket-histogram-aggregation.html[_histogram_] is built from a
|
||||
numeric field. Specify an integer interval for this field. Select the *Show empty buckets* checkbox to include empty
|
||||
intervals in the histogram.
|
||||
*Range*:: With a {ref}/search-aggregations-bucket-range-aggregation.html[_range_] aggregation, you can specify ranges
|
||||
of values for a numeric field. Click *Add Range* to add a set of range endpoints. Click the red *(x)* symbol to remove
|
||||
a range.
|
||||
*Terms*:: A {ref}/search-aggregations-bucket-terms-aggregation.html[_terms_] aggregation enables you to specify the top
|
||||
or bottom _n_ elements of a given field to display, ordered by count or a custom metric.
|
||||
*Filters*:: You can specify a set of {ref}/search-aggregations-bucket-filters-aggregation.html[_filters_] for the data.
|
||||
You can specify a filter as a query string or in JSON format, just as in the Discover search bar. Click *Add Filter* to
|
||||
add another filter.
|
||||
*Significant Terms*:: Displays the results of the experimental
|
||||
{ref}/search-aggregations-bucket-significantterms-aggregation.html[_significant terms_] aggregation. The value of the
|
||||
*Size* parameter defines the number of entries this aggregation returns.
|
||||
*Geohash*:: The {ref}/search-aggregations-bucket-geohashgrid-aggregation.html[_geohash_] aggregation displays points
|
||||
based on the geohash coordinates.
|
||||
|
||||
Once you've specified a bucket type aggregation, you can define sub-aggregations to refine the visualization. Click
|
||||
*+ Add Sub Aggregation* to define a sub-aggregation, then choose *Split Rows* or *Split Table*, then select a
|
||||
sub-aggregation from the list of types.
|
||||
|
||||
You can use the up or down arrows to the right of the aggregation's type to change the aggregation's priority.
|
||||
|
||||
You can click the *Advanced* link to display more customization options for your metrics or bucket aggregation:
|
||||
|
||||
*Exclude Pattern*:: Specify a pattern in this field to exclude from the results.
|
||||
*Exclude Pattern Flags*:: A standard set of Java flags for the exclusion pattern.
|
||||
*Include Pattern*:: Specify a pattern in this field to include in the results.
|
||||
*Include Pattern Flags*:: A standard set of Java flags for the inclusion pattern.
|
||||
*JSON Input*:: A text field where you can add specific JSON-formatted properties to merge with the aggregation
|
||||
definition, as in the following example:
|
||||
|
||||
[source,shell]
|
||||
{ "script" : "doc['grade'].value * 1.2" }
|
||||
|
||||
NOTE: In Elasticsearch releases 1.4.3 and later, this functionality requires you to enable
|
||||
{ref}/modules-scripting[dynamic Groovy scripting].
|
||||
|
||||
The availability of these options varies depending on the aggregation you choose.
|
||||
|
||||
Select *view options* to change the following aspects of the table:
|
||||
|
||||
*Per Page*:: This field controls the pagination of the table. The default value is ten rows per page.
|
||||
|
||||
Checkboxes are available to enable and disable the following behaviors:
|
||||
|
||||
*Show metrics for every bucket/level*:: Check this box to display the intermediate results for each bucket aggregation.
|
||||
*Show partial rows*:: Check this box to display a row even when there is no result.
|
||||
|
||||
NOTE: Enabling these behaviors may have a substantial effect on performance.
|
|
@ -32,7 +32,7 @@ You can use the browser Back button to undo your changes.
|
|||
[[search]]
|
||||
=== Searching Your Data
|
||||
You can search the indices that match the current index pattern by submitting a search from the Discover page.
|
||||
You can enter simple query strings, use the Lucene https://lucene.apache.org/core/2_9_4/queryparsersyntax.html[query syntax], or use the full JSON-based http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl.html[Elasticsearch Query DSL].
|
||||
You can enter simple query strings, use the Lucene https://lucene.apache.org/core/2_9_4/queryparsersyntax.html[query syntax], or use the full JSON-based http://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html[Elasticsearch Query DSL].
|
||||
|
||||
When you submit a search, the histogram, Documents table, and Fields list are updated to reflect
|
||||
the search results. The total number of hits (matching documents) is shown in the upper right corner of the
|
||||
|
@ -51,7 +51,7 @@ To search your data:
|
|||
* To specify more complex search criteria, you can use the Boolean operators `AND`, `OR`, and `NOT`. For example,
|
||||
to find entries that have 4xx status codes and have an extension of `php` or `html`, you could enter `status:[400 TO 499] AND (extension:php OR extension:html)`.
|
||||
+
|
||||
NOTE: These examples use the Lucene query syntax. You can also submit queries using the Elasticsearch Query DSL. For examples, see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html#query-string-syntax[query string syntax] in the Elasticsearch Reference.
|
||||
NOTE: These examples use the Lucene query syntax. You can also submit queries using the Elasticsearch Query DSL. For examples, see http://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html#query-string-syntax[query string syntax] in the Elasticsearch Reference.
|
||||
+
|
||||
. Press *Enter* or click the *Search* button to submit your search query.
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[[kibana-guide]]
|
||||
= Kibana User Guide
|
||||
|
||||
:ref: http://www.elasticsearch.org/guide/en/elasticsearch/reference/current
|
||||
:ref: http://www.elastic.co/guide/en/elasticsearch/reference/current
|
||||
|
||||
include::introduction.asciidoc[]
|
||||
|
||||
|
@ -19,4 +19,4 @@ include::settings.asciidoc[]
|
|||
|
||||
include::production.asciidoc[]
|
||||
|
||||
include::whats-new.asciidoc[]
|
||||
include::whats-new.asciidoc[]
|
|
@ -15,7 +15,7 @@ Elasticsearch indices in minutes--no code, no additional infrastructure required
|
|||
|
||||
NOTE: This guide describes how to use Kibana 4. For information about what's new
|
||||
in Kibana 4, see <<whats-new>>. For information about Kibana 3,
|
||||
see the http://www.elasticsearch.org/guide/en/kibana/current/index.html[Kibana 3 User Guide].
|
||||
see the http://www.elastic.co/guide/en/kibana/current/index.html[Kibana 3 User Guide].
|
||||
|
||||
[float]
|
||||
[[data-discovery]]
|
||||
|
|
35
docs/line.asciidoc
Normal file
35
docs/line.asciidoc
Normal file
|
@ -0,0 +1,35 @@
|
|||
[[line-chart]]
|
||||
=== Line Charts
|
||||
|
||||
This chart's Y axis is the _metrics_ axis. The following aggregations are available for this axis:
|
||||
|
||||
include::y-axis-aggs.asciidoc[]
|
||||
|
||||
Before you choose a buckets aggregation, specify if you are splitting slices within a single chart or splitting into
|
||||
multiple charts. A multiple chart split must run before any other aggregations. When you split a chart, you can change
|
||||
if the splits are displayed in a row or a column by clicking the *Rows | Columns* selector.
|
||||
|
||||
include::x-axis-aggs.asciidoc[]
|
||||
|
||||
You can click the *Advanced* link to display more customization options for your metrics or bucket aggregation:
|
||||
|
||||
*Exclude Pattern*:: Specify a pattern in this field to exclude from the results.
|
||||
*Exclude Pattern Flags*:: A standard set of Java flags for the exclusion pattern.
|
||||
*Include Pattern*:: Specify a pattern in this field to include in the results.
|
||||
*Include Pattern Flags*:: A standard set of Java flags for the inclusion pattern.
|
||||
*JSON Input*:: A text field where you can add specific JSON-formatted properties to merge with the aggregation
|
||||
definition, as in the following example:
|
||||
|
||||
[source,shell]
|
||||
{ "script" : "doc['grade'].value * 1.2" }
|
||||
|
||||
NOTE: In Elasticsearch releases 1.4.3 and later, this functionality requires you to enable
|
||||
{ref}/modules-scripting[dynamic Groovy scripting].
|
||||
|
||||
The availability of these options varies depending on the aggregation you choose.
|
||||
Select *view options* to change the following aspects of the table:
|
||||
|
||||
*Show Tooltip*:: Check this box to enable the display of tooltips.
|
||||
*Show Legend*:: Check this box to enable the display of a legend next to the chart.
|
||||
*Scale Y-Axis to Data Bounds*:: The default Y axis bounds are zero and the maximum value returned in the data. Check
|
||||
this box to change both upper and lower bounds to match the values returned in the data.
|
7
docs/markdown.asciidoc
Normal file
7
docs/markdown.asciidoc
Normal file
|
@ -0,0 +1,7 @@
|
|||
[[markdown-widget]]
|
||||
=== Markdown Widget
|
||||
|
||||
The Markdown widget is a text entry field that accepts GitHub-flavored Markdown text. Kibana renders the text you enter
|
||||
in this field and displays the results on the dashboard. You can click the *Help* link to go to the
|
||||
https://help.github.com/articles/github-flavored-markdown/[help page] for GitHub flavored Markdown. Click *Apply* to
|
||||
display the rendered text in the Preview pane or *Discard* to revert to a previous version.
|
24
docs/metric.asciidoc
Normal file
24
docs/metric.asciidoc
Normal file
|
@ -0,0 +1,24 @@
|
|||
[[metric-chart]]
|
||||
=== Metric
|
||||
|
||||
A metric visualization displays a single number for each aggregation you select:
|
||||
|
||||
include::y-axis-aggs.asciidoc[]
|
||||
You can click the *Advanced* link to display more customization options:
|
||||
|
||||
*Exclude Pattern*:: Specify a pattern in this field to exclude from the results.
|
||||
*Exclude Pattern Flags*:: A standard set of Java flags for the exclusion pattern.
|
||||
*Include Pattern*:: Specify a pattern in this field to include in the results.
|
||||
*Include Pattern Flags*:: A standard set of Java flags for the inclusion pattern.
|
||||
*JSON Input*:: A text field where you can add specific JSON-formatted properties to merge with the aggregation
|
||||
definition, as in the following example:
|
||||
|
||||
[source,shell]
|
||||
{ "script" : "doc['grade'].value * 1.2" }
|
||||
|
||||
NOTE: In Elasticsearch releases 1.4.3 and later, this functionality requires you to enable
|
||||
{ref}/modules-scripting[dynamic Groovy scripting].
|
||||
|
||||
The availability of these options varies depending on the aggregation you choose.
|
||||
|
||||
Click *view options* to change the font used to display the metrics.
|
68
docs/pie.asciidoc
Normal file
68
docs/pie.asciidoc
Normal file
|
@ -0,0 +1,68 @@
|
|||
[[pie-chart]]
|
||||
=== Pie Charts
|
||||
|
||||
The slice size of a pie chart is determined by the _metrics_ aggregation. The following aggregations are available for
|
||||
this axis:
|
||||
|
||||
*Count*:: The {ref}/search-aggregations-metrics-valuecount-aggregation.html[_count_] aggregation returns a raw count of
|
||||
the elements in the selected index pattern.
|
||||
*Sum*:: The {ref}/search-aggregations-metrics-sum-aggregation.html[_sum_] aggregation returns the total sum of a numeric
|
||||
field. Select a field from the drop-down.
|
||||
*Unique Count*:: The {ref}/search-aggregations-metrics-cardinality-aggregation.html[_cardinality_] aggregation returns
|
||||
the number of unique values in a field. Select a field from the drop-down.
|
||||
|
||||
The _buckets_ aggregations determine what information is being retrieved from your data set.
|
||||
|
||||
Before you choose a buckets aggregation, specify if you are splitting slices within a single chart or splitting into
|
||||
multiple charts. A multiple chart split must run before any other aggregations. When you split a chart, you can change
|
||||
if the splits are displayed in a row or a column by clicking the *Rows | Columns* selector.
|
||||
|
||||
You can specify any of the following bucket aggregations for your pie chart:
|
||||
|
||||
*Date Histogram*:: A {ref}/search-aggregations-bucket-datehistogram-aggregation.html[_date histogram_] is built from a
|
||||
numeric field and organized by date. You can specify a time frame for the intervals in seconds, minutes, hours, days,
|
||||
weeks, months, or years.
|
||||
*Histogram*:: A standard {ref}/search-aggregations-bucket-histogram-aggregation.html[_histogram_] is built from a
|
||||
numeric field. Specify an integer interval for this field. Select the *Show empty buckets* checkbox to include empty
|
||||
intervals in the histogram.
|
||||
*Range*:: With a {ref}/search-aggregations-bucket-range-aggregation.html[_range_] aggregation, you can specify ranges
|
||||
of values for a numeric field. Click *Add Range* to add a set of range endpoints. Click the red *(x)* symbol to remove
|
||||
a range.
|
||||
*Terms*:: A {ref}/search-aggregations-bucket-terms-aggregation.html[_terms_] aggregation enables you to specify the top
|
||||
or bottom _n_ elements of a given field to display, ordered by count or a custom metric.
|
||||
*Filters*:: You can specify a set of {ref}/search-aggregations-bucket-filters-aggregation.html[_filters_] for the data.
|
||||
You can specify a filter as a query string or in JSON format, just as in the Discover search bar. Click *Add Filter* to
|
||||
add another filter.
|
||||
*Significant Terms*:: Displays the results of the experimental
|
||||
{ref}/search-aggregations-bucket-significantterms-aggregation.html[_significant terms_] aggregation. The value of the
|
||||
*Size* parameter defines the number of entries this aggregation returns.
|
||||
|
||||
After defining an initial bucket aggregation, you can define sub-aggregations to refine the visualization. Click *+ Add
|
||||
Sub Aggregation* to define a sub-aggregation, then choose *Split Slices* to select a sub-aggregation from the list of
|
||||
types.
|
||||
|
||||
When multiple aggregations are defined on a chart's axis, you can use the up or down arrows to the right of the
|
||||
aggregation's type to change the aggregation's priority.
|
||||
|
||||
You can click the *Advanced* link to display more customization options for your metrics or bucket aggregation:
|
||||
|
||||
*Exclude Pattern*:: Specify a pattern in this field to exclude from the results.
|
||||
*Exclude Pattern Flags*:: A standard set of Java flags for the exclusion pattern.
|
||||
*Include Pattern*:: Specify a pattern in this field to include in the results.
|
||||
*Include Pattern Flags*:: A standard set of Java flags for the inclusion pattern.
|
||||
*JSON Input*:: A text field where you can add specific JSON-formatted properties to merge with the aggregation
|
||||
definition, as in the following example:
|
||||
|
||||
[source,shell]
|
||||
{ "script" : "doc['grade'].value * 1.2" }
|
||||
|
||||
NOTE: In Elasticsearch releases 1.4.3 and later, this functionality requires you to enable
|
||||
{ref}/modules-scripting[dynamic Groovy scripting].
|
||||
|
||||
The availability of these options varies depending on the aggregation you choose.
|
||||
|
||||
Select *view options* to change the following aspects of the table:
|
||||
|
||||
*Donut*:: Display the chart as a sliced ring instead of a sliced pie.
|
||||
*Show Tooltip*:: Check this box to enable the display of tooltips.
|
||||
*Show Legend*:: Check this box to enable the display of a legend next to the chart.
|
|
@ -24,7 +24,7 @@ If you are using Shield to authenticate Elasticsearch users, you need to provide
|
|||
the Kibana server with credentials so it can access the `.kibana` index and monitor
|
||||
the cluster.
|
||||
|
||||
To configure credentials the Kibana server, set the `kibana_elasticsearch_username` and
|
||||
To configure credentials for the Kibana server, set the `kibana_elasticsearch_username` and
|
||||
`kibana_elasticsearch_password` properties in `kibana.yml`:
|
||||
|
||||
----
|
||||
|
@ -34,7 +34,7 @@ kibana_elasticsearch_password: kibana4
|
|||
----
|
||||
|
||||
For information about assigning the Kibana server the necessary permissions in Shield,
|
||||
see https://www.elasticsearch.org/guide/en/shield/current/_shield_with_kibana_4.html[Shield with Kibana 4]
|
||||
see https://www.elastic.co/guide/en/shield/current/_shield_with_kibana_4.html[Shield with Kibana 4]
|
||||
in the Shield documentation.
|
||||
|
||||
[float]
|
||||
|
@ -73,7 +73,7 @@ ca: /path/to/your/ca/cacert.pem
|
|||
[float]
|
||||
[[controlling-access]]
|
||||
=== Controlling access
|
||||
You can use http://www.elasticsearch.org/overview/shield/[Elasticsearch Shield]
|
||||
You can use http://www.elastic.co/overview/shield/[Elasticsearch Shield]
|
||||
(Shield) to control what Elasticsearch data users can access through Kibana.
|
||||
Shield provides index-level access control. If a user isn't authorized to run
|
||||
the query that populates a Kibana visualization, the user just sees an empty
|
||||
|
@ -81,7 +81,7 @@ visualization.
|
|||
|
||||
To configure access to Kibana using Shield, you create Shield roles
|
||||
for Kibana using the `kibana4` default role as a starting point. For more
|
||||
information, see http://www.elasticsearch.org/guide/en/shield/current/_shield_with_kibana_4.html[Using Shield with Kibana 4].
|
||||
information, see http://www.elastic.co/guide/en/shield/current/_shield_with_kibana_4.html[Using Shield with Kibana 4].
|
||||
|
||||
[float]
|
||||
[[load-balancing]]
|
||||
|
@ -90,7 +90,7 @@ If you have multiple nodes in your Elasticsearch cluster, the easiest way to dis
|
|||
across the nodes is to run an Elasticsearch _client_ node on the same machine as Kibana.
|
||||
Elasticsearch client nodes are essentially smart load balancers that are part of the cluster. They
|
||||
process incoming HTTP requests, redirect operations to the other nodes in the cluster as needed, and
|
||||
gather and return the results. For more information, see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-node.html[Node] in the Elasticsearch reference.
|
||||
gather and return the results. For more information, see http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-node.html[Node] in the Elasticsearch reference.
|
||||
|
||||
To use a local client node to load balance Kibana requests:
|
||||
|
||||
|
@ -117,9 +117,4 @@ cluster.name: "my_cluster"
|
|||
--------
|
||||
# The Elasticsearch instance to use for all your queries.
|
||||
elasticsearch_url: "http://localhost:9200"
|
||||
--------
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
--------
|
|
@ -172,7 +172,7 @@ buggy, you'll get exceptions whenever you try to view the dynamically generated
|
|||
data.
|
||||
|
||||
Scripted fields use the Lucene expression syntax. For more information,
|
||||
see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-scripting.html#_lucene_expressions_scripts[Lucene Expressions Scripts].
|
||||
see http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting.html#_lucene_expressions_scripts[Lucene Expressions Scripts].
|
||||
|
||||
You can reference any single value numeric field in your expressions, for example:
|
||||
|
||||
|
@ -192,7 +192,10 @@ from your index data.
|
|||
. Click *Save Scripted Field*.
|
||||
|
||||
For more information about scripted fields in Elasticsearch, see
|
||||
http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-scripting.html[Scripting].
|
||||
http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting.html[Scripting].
|
||||
|
||||
NOTE: In Elasticsearch releases 1.4.3 and later, this functionality requires you to enable
|
||||
{ref}/modules-scripting[dynamic Groovy scripting].
|
||||
|
||||
[float]
|
||||
[[update-scripted-field]]
|
||||
|
|
|
@ -4,27 +4,27 @@ You can set up Kibana and start exploring your Elasticsearch indices in minutes.
|
|||
All you need is:
|
||||
|
||||
* Elasticsearch 1.4.4 or later
|
||||
* A modern web browser - http://www.elasticsearch.com/support/matrix[Supported Browsers].
|
||||
* Information about your Elasticsearch installation:
|
||||
* A modern web browser - http://www.elastic.co/subscriptions/matrix#matrix_browsers[Supported Browsers].
|
||||
* Information about your Elasticsearch installation:
|
||||
** URL of the Elasticsearch instance you want to connect to.
|
||||
** Which Elasticsearch indices you want to search.
|
||||
** Which Elasticsearch indices you want to search.
|
||||
|
||||
NOTE: If your Elasticsearch installation is protected by http://www.elasticsearch.org/overview/shield/[Shield] see https://www.elasticsearch.org/guide/en/shield/current/_shield_with_kibana_4.html[Shield with Kibana 4] for additional setup instructions.
|
||||
NOTE: If your Elasticsearch installation is protected by http://www.elastic.co/overview/shield/[Shield] see https://www.elastic.co/guide/en/shield/current/_shield_with_kibana_4.html[Shield with Kibana 4] for additional setup instructions.
|
||||
|
||||
[float]
|
||||
[[install]]
|
||||
=== Install and Start Kibana
|
||||
To get Kibana up and running:
|
||||
|
||||
. Download the http://www.elasticsearch.org/overview/kibana/installation/[Kibana 4 binary package] for your platform.
|
||||
. Download the https://www.elastic.co/downloads/kibana[Kibana 4 binary package] for your platform.
|
||||
. Extract the `.zip` or `tar.gz` archive file.
|
||||
. Run Kibana from the install directory: `bin/kibana` (Linux/MacOSX) or `bin\kibana.bat` (Windows).
|
||||
|
||||
That's it! Kibana is now running on port 5601.
|
||||
That's it! Kibana is now running on port 5601.
|
||||
|
||||
[float]
|
||||
[[connect]]
|
||||
=== Connect Kibana with Elasticsearch
|
||||
=== Connect Kibana with Elasticsearch
|
||||
Before you can start using Kibana, you need to tell it which Elasticsearch indices you want to explore. The first time you access Kibana, you are prompted to define an _index pattern_ that matches the name of one or more of your indices. That's it. That's all you need to configure to start using Kibana. You can add index patterns at any time from the <<settings-create-pattern,Settings tab>>.
|
||||
|
||||
TIP: By default, Kibana connects to the Elasticsearch instance running on `localhost`. To connect to a different Elasticsearch instance, modify the Elasticsearch URL in the `kibana.yml` configuration file and restart Kibana. For information about using Kibana with your production nodes, see <<production>>.
|
||||
|
@ -35,10 +35,10 @@ To configure the Elasticsearch indices you want to access with Kibana:
|
|||
+
|
||||
image:images/Start-Page.jpg[Kibana start page]
|
||||
+
|
||||
. Specify an index pattern that matches the name of one or more of your Elasticsearch indices. By default, Kibana guesses that you're you're working with data being fed into Elasticsearch by Logstash. If that's the case, you can use the default `logstash-*` as your index pattern. The asterisk (*) matches zero or more characters in an index's name. If your Elasticsearch indices follow some other naming convention, enter an appropriate pattern. The "pattern" can also simply be the name of a single index.
|
||||
. Select the index field that contains the timestamp that you want to use to perform time-based comparisons. Kibana reads the index mapping to list all of the fields that contain a timestamp. If your index doesn't have time-based data, disable the *Index contains time-based events* option.
|
||||
. Specify an index pattern that matches the name of one or more of your Elasticsearch indices. By default, Kibana guesses that you're working with data being fed into Elasticsearch by Logstash. If that's the case, you can use the default `logstash-*` as your index pattern. The asterisk (*) matches zero or more characters in an index's name. If your Elasticsearch indices follow some other naming convention, enter an appropriate pattern. The "pattern" can also simply be the name of a single index.
|
||||
. Select the index field that contains the timestamp that you want to use to perform time-based comparisons. Kibana reads the index mapping to list all of the fields that contain a timestamp. If your index doesn't have time-based data, disable the *Index contains time-based events* option.
|
||||
. If new indices are generated periodically and have a timestamp appended to the name, select the *Use event times to create index names* option and select the *Index pattern interval*. This improves search performance by enabling Kibana to search only those indices that could contain data in the time range you specify. This is primarily applicable if you are using Logstash to feed data into Elasticsearch.
|
||||
. Click *Create* to add the index pattern. This first pattern is automatically configured as the default. When you have more than one index pattern, you can designate which one to use as the default from *Settings > Indices*.
|
||||
. Click *Create* to add the index pattern. This first pattern is automatically configured as the default. When you have more than one index pattern, you can designate which one to use as the default from *Settings > Indices*.
|
||||
|
||||
Voila! Kibana is now connected to your Elasticsearch data. Kibana displays a read-only list of fields configured for the matching index.
|
||||
|
||||
|
@ -47,6 +47,6 @@ Voila! Kibana is now connected to your Elasticsearch data. Kibana displays a rea
|
|||
=== Start Exploring your Data!
|
||||
You're ready to dive in to your data:
|
||||
|
||||
* Search and browse your data interactively from the <<discover,Discover>> page.
|
||||
* Chart and map your data from the <<visualize, Visualize>> page.
|
||||
* Create and view custom dashboards from the <<dashboard, Dashboard>> page.
|
||||
* Search and browse your data interactively from the <<discover,Discover>> page.
|
||||
* Chart and map your data from the <<visualize, Visualize>> page.
|
||||
* Create and view custom dashboards from the <<dashboard, Dashboard>> page.
|
75
docs/tilemap.asciidoc
Normal file
75
docs/tilemap.asciidoc
Normal file
|
@ -0,0 +1,75 @@
|
|||
[[tilemap]]
|
||||
=== Tile Maps
|
||||
|
||||
A tile map displays a geographic area overlaid with circles keyed to the data determined by the buckets you specify.
|
||||
|
||||
The default _metrics_ aggregation for a tile map is the *Count* aggregation. You can select any of the following
|
||||
aggregations as the metrics aggregation:
|
||||
|
||||
*Count*:: The {ref}/search-aggregations-metrics-valuecount-aggregation.html[_count_] aggregation returns a raw count of
|
||||
the elements in the selected index pattern.
|
||||
*Average*:: This aggregation returns the {ref}/search-aggregations-metrics-avg-aggregation.html[_average_] of a numeric
|
||||
field. Select a field from the drop-down.
|
||||
*Sum*:: The {ref}/search-aggregations-metrics-sum-aggregation.html[_sum_] aggregation returns the total sum of a numeric
|
||||
field. Select a field from the drop-down.
|
||||
*Min*:: The {ref}/search-aggregations-metrics-min-aggregation.html[_min_] aggregation returns the minimum value of a
|
||||
numeric field. Select a field from the drop-down.
|
||||
*Max*:: The {ref}/search-aggregations-metrics-max-aggregation.html[_max_] aggregation returns the maximum value of a
|
||||
numeric field. Select a field from the drop-down.
|
||||
*Unique Count*:: The {ref}/search-aggregations-metrics-cardinality-aggregation.html[_cardinality_] aggregation returns
|
||||
the number of unique values in a field. Select a field from the drop-down.
|
||||
|
||||
The _buckets_ aggregations determine what information is being retrieved from your data set.
|
||||
|
||||
Before you choose a buckets aggregation, specify if you are splitting the chart or displaying the buckets as *Geo
|
||||
Coordinates* on a single chart. A multiple chart split must run before any other aggregations.
|
||||
|
||||
Tile maps use the *Geohash* aggregation as their initial aggregation. Select a field, typically coordinates, from the
|
||||
drop-down. The *Precision* slider determines the granularity of the results displayed on the map.
|
||||
|
||||
Once you've specified a buckets aggregation, you can define sub-aggregations to refine the visualization. Tile maps
|
||||
only support sub-aggregations as split charts. Click *+ Add Sub Aggregation*, then *Split Chart* to select a
|
||||
sub-aggregation from the list of types:
|
||||
|
||||
*Date Histogram*:: A {ref}/search-aggregations-bucket-datehistogram-aggregation.html[_date histogram_] is built from a
|
||||
numeric field and organized by date. You can specify a time frame for the intervals in seconds, minutes, hours, days,
|
||||
weeks, months, or years.
|
||||
*Histogram*:: A standard {ref}/search-aggregations-bucket-histogram-aggregation.html[_histogram_] is built from a
|
||||
numeric field. Specify an integer interval for this field. Select the *Show empty buckets* checkbox to include empty
|
||||
intervals in the histogram.
|
||||
*Range*:: With a {ref}/search-aggregations-bucket-range-aggregation.html[_range_] aggregation, you can specify ranges
|
||||
of values for a numeric field. Click *Add Range* to add a set of range endpoints. Click the red *(x)* symbol to remove
|
||||
a range.
|
||||
*Terms*:: A {ref}/search-aggregations-bucket-terms-aggregation.html[_terms_] aggregation enables you to specify the top
|
||||
or bottom _n_ elements of a given field to display, ordered by count or a custom metric.
|
||||
*Filters*:: You can specify a set of {ref}/search-aggregations-bucket-filters-aggregation.html[_filters_] for the data.
|
||||
You can specify a filter as a query string or in JSON format, just as in the Discover search bar. Click *Add Filter* to
|
||||
add another filter.
|
||||
*Significant Terms*:: Displays the results of the experimental
|
||||
{ref}/search-aggregations-bucket-significantterms-aggregation.html[_significant terms_] aggregation. The value of the
|
||||
*Size* parameter defines the number of entries this aggregation returns.
|
||||
*Geohash*:: The {ref}/search-aggregations-bucket-geohashgrid-aggregation.html[_geohash_] aggregation displays points
|
||||
based on the geohash coordinates.
|
||||
|
||||
You can click the *Advanced* link to display more customization options for your metrics or bucket aggregation:
|
||||
|
||||
*Exclude Pattern*:: Specify a pattern in this field to exclude from the results.
|
||||
*Exclude Pattern Flags*:: A standard set of Java flags for the exclusion pattern.
|
||||
*Include Pattern*:: Specify a pattern in this field to include in the results.
|
||||
*Include Pattern Flags*:: A standard set of Java flags for the inclusion pattern.
|
||||
*JSON Input*:: A text field where you can add specific JSON-formatted properties to merge with the aggregation
|
||||
definition, as in the following example:
|
||||
|
||||
[source,shell]
|
||||
{ "script" : "doc['grade'].value * 1.2" }
|
||||
|
||||
NOTE: In Elasticsearch releases 1.4.3 and later, this functionality requires you to enable
|
||||
{ref}/modules-scripting[dynamic Groovy scripting].
|
||||
|
||||
The availability of these options varies depending on the aggregation you choose.
|
||||
|
||||
Select *view options* to change the following aspects of the table:
|
||||
|
||||
*Shaded Circle Markers*:: Displays the markers with different shades based on the metric aggregation's value.
|
||||
*Scaled Circle Markers*:: Scale the size of the markers based on the metric aggregation's value.
|
||||
*Desaturate Map*:: Desaturate the map's color in order to make the markers stand out more clearly.
|
47
docs/vertbar.asciidoc
Normal file
47
docs/vertbar.asciidoc
Normal file
|
@ -0,0 +1,47 @@
|
|||
[[vertical-bar-chart]]
|
||||
=== Vertical Bar Charts
|
||||
|
||||
This chart's Y axis is the _metrics_ axis. The following aggregations are available for this axis:
|
||||
|
||||
include::y-axis-aggs.asciidoc[]
|
||||
|
||||
The _buckets_ aggregations determine what information is being retrieved from your data set.
|
||||
|
||||
Before you choose a buckets aggregation, specify if you are splitting slices within a single chart or splitting into
|
||||
multiple charts. A multiple chart split must run before any other aggregations. When you split a chart, you can change
|
||||
if the splits are displayed in a row or a column by clicking the *Rows | Columns* selector.
|
||||
|
||||
include::x-axis-aggs.asciidoc[]
|
||||
|
||||
You can click the *Advanced* link to display more customization options for your metrics or bucket aggregation:
|
||||
|
||||
*Exclude Pattern*:: Specify a pattern in this field to exclude from the results.
|
||||
*Exclude Pattern Flags*:: A standard set of Java flags for the exclusion pattern.
|
||||
*Include Pattern*:: Specify a pattern in this field to include in the results.
|
||||
*Include Pattern Flags*:: A standard set of Java flags for the inclusion pattern.
|
||||
*JSON Input*:: A text field where you can add specific JSON-formatted properties to merge with the aggregation
|
||||
definition, as in the following example:
|
||||
|
||||
[source,shell]
|
||||
{ "script" : "doc['grade'].value * 1.2" }
|
||||
|
||||
NOTE: In Elasticsearch releases 1.4.3 and later, this functionality requires you to enable
|
||||
{ref}/modules-scripting[dynamic Groovy scripting].
|
||||
|
||||
The availability of these options varies depending on the aggregation you choose.
|
||||
|
||||
Select *view options* to change the following aspects of the table:
|
||||
|
||||
*Bar Mode*:: When you have multiple Y-axis aggregations defined for your chart, you can use this drop-down to affect
|
||||
how the aggregations display on the chart:
|
||||
|
||||
_stacked_:: Stacks the aggregations on top of each other.
|
||||
_percentage_:: Displays each aggregation as a proportion of the total.
|
||||
_grouped_:: Groups the results horizontally by the lowest-priority sub-aggregation.
|
||||
|
||||
Checkboxes are available to enable and disable the following behaviors:
|
||||
|
||||
*Show Tooltip*:: Check this box to enable the display of tooltips.
|
||||
*Show Legend*:: Check this box to enable the display of a legend next to the chart.
|
||||
*Scale Y-Axis to Data Bounds*:: The default Y axis bounds are zero and the maximum value returned in the data. Check
|
||||
this box to change both upper and lower bounds to match the values returned in the data.
|
20
docs/visualize-config.asciidoc
Normal file
20
docs/visualize-config.asciidoc
Normal file
|
@ -0,0 +1,20 @@
|
|||
[[vizconf]]
|
||||
== Visualization Configuration
|
||||
|
||||
This sections deals with the configuration options for visualizations in Kibana.
|
||||
|
||||
include::area.asciidoc[]
|
||||
|
||||
include::datatable.asciidoc[]
|
||||
|
||||
include::line.asciidoc[]
|
||||
|
||||
include::markdown.asciidoc[]
|
||||
|
||||
include::metric.asciidoc[]
|
||||
|
||||
include::pie.asciidoc[]
|
||||
|
||||
include::tilemap.asciidoc[]
|
||||
|
||||
include::vertbar.asciidoc[]
|
|
@ -9,7 +9,7 @@ data source types:
|
|||
* A saved search
|
||||
* An existing saved visualization
|
||||
|
||||
Visualizations are based on the {ref}/search-aggregations.html[aggregation] feature introduced in Elasticsearch 1.
|
||||
Visualizations are based on the {ref}/search-aggregations.html[aggregation] feature introduced in Elasticsearch 1.x.
|
||||
|
||||
[float]
|
||||
[[createvis]]
|
||||
|
@ -23,9 +23,19 @@ button] in the toolbar to the right of the search bar. The wizard guides you thr
|
|||
[[newvis01]]
|
||||
==== Step 1: Choose the Visualization Type
|
||||
|
||||
The New Visualization wizard starts with the following page:
|
||||
Choose a visualization type when you start the New Visualization wizard:
|
||||
|
||||
image:images/NewViz01.jpg[]
|
||||
[horizontal]
|
||||
<<area-chart,Area chart>>:: Use area charts to visualize the total contribution of several different series.
|
||||
<<data-table,Data table>>:: Use data tables to display the raw data of a composed aggregation. You can display the data
|
||||
table for several other visualizations by clicking at the bottom of the visualization.
|
||||
<<line-chart,Line chart>>:: Use line charts to compare different series.
|
||||
<<markdown-widget,Markdown widget>>:: Use the Markdown widget to display free-form information or instructions about your
|
||||
dashboard.
|
||||
<<metric-chart,Metric>>:: Use the metric visualization to display a single number on your dashboard.
|
||||
<<pie-chart,Pie chart>>:: Use pie charts to display each source's contribution to a total.
|
||||
<<tilemap,Tile map>>:: Use tile maps to associate the results of an aggregation with geographic points.
|
||||
<<vertical-bar-chart,Vertical bar chart>>:: Use vertical bar charts as a general-purpose chart.
|
||||
|
||||
You can also load a saved visualization that you created earlier. The saved visualization selector includes a text
|
||||
field to filter by visualization name and a link to the Object Editor, accessible through *Settings > Edit Saved
|
||||
|
@ -124,3 +134,19 @@ To render the visualization on the _preview canvas_, click the *Apply* button at
|
|||
|
||||
The preview canvas displays a preview of the visualization you've defined in the aggregation builder. To refresh the
|
||||
visualization preview, clicking the *Refresh* button image:images/K4Refresh.png[Refresh button] on the toolbar.
|
||||
|
||||
include::area.asciidoc[]
|
||||
|
||||
include::datatable.asciidoc[]
|
||||
|
||||
include::line.asciidoc[]
|
||||
|
||||
include::markdown.asciidoc[]
|
||||
|
||||
include::metric.asciidoc[]
|
||||
|
||||
include::pie.asciidoc[]
|
||||
|
||||
include::tilemap.asciidoc[]
|
||||
|
||||
include::vertbar.asciidoc[]
|
29
docs/x-axis-aggs.asciidoc
Normal file
29
docs/x-axis-aggs.asciidoc
Normal file
|
@ -0,0 +1,29 @@
|
|||
The X axis of this chart is the _buckets_ axis. You can define buckets for the X axis, for a split area on the
|
||||
chart, or for split charts.
|
||||
|
||||
This chart's X axis supports the following aggregations. Click the linked name of each aggregation to visit the main
|
||||
Elasticsearch documentation for that aggregation.
|
||||
|
||||
*Date Histogram*:: A {ref}/search-aggregations-bucket-datehistogram-aggregation.html[_date histogram_] is built from a
|
||||
numeric field and organized by date. You can specify a time frame for the intervals in seconds, minutes, hours, days,
|
||||
weeks, months, or years.
|
||||
*Histogram*:: A standard {ref}/search-aggregations-bucket-histogram-aggregation.html[_histogram_] is built from a
|
||||
numeric field. Specify an integer interval for this field. Select the *Show empty buckets* checkbox to include empty
|
||||
intervals in the histogram.
|
||||
*Range*:: With a {ref}/search-aggregations-bucket-range-aggregation.html[_range_] aggregation, you can specify ranges
|
||||
of values for a numeric field. Click *Add Range* to add a set of range endpoints. Click the red *(x)* symbol to remove
|
||||
a range.
|
||||
*Terms*:: A {ref}/search-aggregations-bucket-terms-aggregation.html[_terms_] aggregation enables you to specify the top
|
||||
or bottom _n_ elements of a given field to display, ordered by count or a custom metric.
|
||||
*Filters*:: You can specify a set of {ref}/search-aggregations-bucket-filters-aggregation.html[_filters_] for the data.
|
||||
You can specify a filter as a query string or in JSON format, just as in the Discover search bar. Click *Add Filter* to
|
||||
add another filter.
|
||||
*Significant Terms*:: Displays the results of the experimental
|
||||
{ref}/search-aggregations-bucket-significantterms-aggregation.html[_significant terms_] aggregation.
|
||||
|
||||
Once you've specified an X axis aggregation, you can define sub-aggregations to refine the visualization. Click *+ Add
|
||||
Sub Aggregation* to define a sub-aggregation, then choose *Split Area* or *Split Chart*, then select a sub-aggregation
|
||||
from the list of types.
|
||||
|
||||
When multiple aggregations are defined on a chart's axis, you can use the up or down arrows to the right of the
|
||||
aggregation's type to change the aggregation's priority.
|
18
docs/y-axis-aggs.asciidoc
Normal file
18
docs/y-axis-aggs.asciidoc
Normal file
|
@ -0,0 +1,18 @@
|
|||
*Count*:: The {ref}/search-aggregations-metrics-valuecount-aggregation.html[_count_] aggregation returns a raw count of
|
||||
the elements in the selected index pattern.
|
||||
*Average*:: This aggregation returns the {ref}/search-aggregations-metrics-avg-aggregation.html[_average_] of a numeric
|
||||
field. Select a field from the drop-down.
|
||||
*Sum*:: The {ref}/search-aggregations-metrics-sum-aggregation.html[_sum_] aggregation returns the total sum of a numeric
|
||||
field. Select a field from the drop-down.
|
||||
*Min*:: The {ref}/search-aggregations-metrics-min-aggregation.html[_min_] aggregation returns the minimum value of a
|
||||
numeric field. Select a field from the drop-down.
|
||||
*Max*:: The {ref}/search-aggregations-metrics-max-aggregation.html[_max_] aggregation returns the maximum value of a
|
||||
numeric field. Select a field from the drop-down.
|
||||
*Unique Count*:: The {ref}/search-aggregations-metrics-cardinality-aggregation.html[_cardinality_] aggregation returns
|
||||
the number of unique values in a field. Select a field from the drop-down.
|
||||
*Standard Deviation*:: The {ref}/search-aggregations-metrics-extendedstats-aggregation.html[_extended stats_]
|
||||
aggregation returns the standard deviation of data in a numeric field. Select a field from the drop-down.
|
||||
*Percentile*:: The {ref}/search-aggregations-metrics-percentile-rank-aggregation.html[_percentile_] aggregation returns
|
||||
the percentile rank of values in a numeric field. Select a field from the drop-down, then specify a range in the *Percentiles* fields. Click the *X* to remove a percentile field. Click *+ Add Percent* to add a percentile field.
|
||||
|
||||
You can add an aggregation by clicking the *+ Add Aggregation* button.
|
19
package.json
19
package.json
|
@ -13,17 +13,20 @@
|
|||
"private": false,
|
||||
"version": "4.1.0-snapshot",
|
||||
"main": "src/server/app.js",
|
||||
"homepage": "http://www.elasticsearch.org/overview/kibana/",
|
||||
"homepage": "https://www.elastic.co/products/kibana",
|
||||
"bugs": {
|
||||
"url": "https://github.com/elasticsearch/kibana/issues"
|
||||
"url": "http://github.com/elastic/kibana/issues"
|
||||
},
|
||||
"license": "Apache 2.0",
|
||||
"author": "Rashid Khan <rashid.khan@elasticsearch.com>",
|
||||
"author": "Rashid Khan <rashid.khan@elastic.co>",
|
||||
"contributors": [
|
||||
"Spencer Alger <spencer.alger@elasticsearch.com>",
|
||||
"Chris Cowan <chris.cowan@elasticsearch.com>",
|
||||
"Joe Fleming <joe.fleming@elasticsearch.com>",
|
||||
"Lukas Olson <lukas.olson@elasticsearch.com>"
|
||||
"Spencer Alger <spencer.alger@elastic.co>",
|
||||
"Chris Cowan <chris.cowan@elastic.co>",
|
||||
"Joe Fleming <joe.fleming@elastic.co>",
|
||||
"Lukas Olson <lukas.olson@elastic.co>",
|
||||
"Juan Thomassie <juan.thomassie@elastic.co>",
|
||||
"Shleby Sturgis <shelby@elastic.co>",
|
||||
"Khalah Jones-Golden <khalah.jones@elastic.co>"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "grunt test",
|
||||
|
@ -33,7 +36,7 @@
|
|||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/elasticsearch/kibana.git"
|
||||
"url": "https://github.com/elastic/kibana.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansicolors": "^0.3.2",
|
||||
|
|
|
@ -14,7 +14,7 @@ define(function (require) {
|
|||
|
||||
// Create the new branch record
|
||||
var $parent = parent && parent.aggConfigResult;
|
||||
var aggConfigResult = new AggConfigResult(agg, $parent, value, bucket.key);
|
||||
var aggConfigResult = new AggConfigResult(agg, $parent, value, agg.getKey(bucket));
|
||||
var branch = {
|
||||
name: bucket.key,
|
||||
size: value,
|
||||
|
|
|
@ -75,7 +75,7 @@ define(function (require) {
|
|||
if (!_.isEmpty(displayName)) split.label += ': ' + displayName;
|
||||
|
||||
split.tooltipFormatter = tooltipFormatter(raw.columns);
|
||||
var aggConfigResult = new AggConfigResult(firstAgg, null, null, bucket.key);
|
||||
var aggConfigResult = new AggConfigResult(firstAgg, null, null, firstAgg.getKey(bucket));
|
||||
split.split = { aggConfig: firstAgg, aggConfigResult: aggConfigResult, key: bucket.key };
|
||||
_.each(split.slices.children, function (child) {
|
||||
child.aggConfigResult.$parent = aggConfigResult;
|
||||
|
|
|
@ -6,6 +6,8 @@ define(function (require) {
|
|||
var map = {
|
||||
segment: 'x',
|
||||
metric: 'y',
|
||||
radius: 'z',
|
||||
width: 'width',
|
||||
group: 'series'
|
||||
};
|
||||
|
||||
|
@ -54,4 +56,4 @@ define(function (require) {
|
|||
return aspects;
|
||||
};
|
||||
};
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
define(function (require) {
|
||||
return function PointSeriesGetPoint() {
|
||||
var _ = require('lodash');
|
||||
function unwrap(aggConfigResult, def) {
|
||||
return aggConfigResult ? aggConfigResult.value : def;
|
||||
}
|
||||
|
||||
return function getPoint(x, series, yScale, row, y) {
|
||||
return function getPoint(x, series, yScale, row, y, z) {
|
||||
var zRow = z && row[z.i];
|
||||
var point = {
|
||||
x: unwrap(row[x.i], '_all'),
|
||||
y: unwrap(row[y.i]),
|
||||
z: zRow && unwrap(zRow),
|
||||
aggConfigResult: row[y.i],
|
||||
extraMetrics: _.compact([zRow]),
|
||||
yScale: yScale
|
||||
};
|
||||
|
||||
|
@ -29,4 +33,4 @@ define(function (require) {
|
|||
return point;
|
||||
};
|
||||
};
|
||||
});
|
||||
});
|
||||
|
|
|
@ -14,13 +14,13 @@ define(function (require) {
|
|||
.transform(function (series, row) {
|
||||
|
||||
if (!multiY) {
|
||||
var point = partGetPoint(row, aspects.y);
|
||||
var point = partGetPoint(row, aspects.y, aspects.z);
|
||||
if (point) addToSiri(series, point, point.series);
|
||||
return;
|
||||
}
|
||||
|
||||
aspects.y.forEach(function (y) {
|
||||
var point = partGetPoint(row, y);
|
||||
var point = partGetPoint(row, y, aspects.z);
|
||||
if (!point) return;
|
||||
|
||||
var prefix = point.series ? point.series + ': ' : '';
|
||||
|
|
|
@ -13,7 +13,8 @@ define(function (require) {
|
|||
|
||||
var details = $tooltipScope.details = [];
|
||||
var result = { $parent: datum.aggConfigResult };
|
||||
while ((result = result.$parent) && result.aggConfig) {
|
||||
|
||||
function addDetail(result) {
|
||||
var agg = result.aggConfig;
|
||||
var value = result.value;
|
||||
|
||||
|
@ -32,8 +33,14 @@ define(function (require) {
|
|||
details.push(detail);
|
||||
}
|
||||
|
||||
datum.extraMetrics.forEach(addDetail);
|
||||
while ((result = result.$parent) && result.aggConfig) {
|
||||
addDetail(result);
|
||||
}
|
||||
|
||||
|
||||
$tooltipScope.$apply();
|
||||
return $tooltip[0].outerHTML;
|
||||
};
|
||||
};
|
||||
});
|
||||
});
|
||||
|
|
|
@ -187,7 +187,7 @@ define(function (require) {
|
|||
newList.unshift(injected);
|
||||
}
|
||||
|
||||
var newAcr = new AggConfigResult(acr.aggConfig, newList[0], acr.value, acr.key);
|
||||
var newAcr = new AggConfigResult(acr.aggConfig, newList[0], acr.value, acr.aggConfig.getKey(acr));
|
||||
newList.unshift(newAcr);
|
||||
|
||||
// and replace the acr in the row buffer if its there
|
||||
|
|
|
@ -38,12 +38,12 @@ define(function (require) {
|
|||
var splitting = write.canSplit && agg.schema.name === 'split';
|
||||
if (splitting) {
|
||||
write.split(agg, buckets, function forEachBucket(subBucket, key) {
|
||||
collectBucket(write, subBucket, key);
|
||||
collectBucket(write, subBucket, agg.getKey(subBucket), key);
|
||||
});
|
||||
} else {
|
||||
buckets.forEach(function (subBucket, key) {
|
||||
write.cell(agg, key, function () {
|
||||
collectBucket(write, subBucket, key);
|
||||
write.cell(agg, agg.getKey(subBucket, key), function () {
|
||||
collectBucket(write, subBucket, agg.getKey(subBucket, key));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
<div class="agg-table-controls">
|
||||
<small>Export:</small>
|
||||
<a class="small" ng-click="aggTable.exportAsCsv(false)">
|
||||
Raw <i class="fa fa-download"></i>
|
||||
Raw <i aria-hidden="true" class="fa fa-download"></i>
|
||||
</a>
|
||||
<a class="small" ng-click="aggTable.exportAsCsv(true)">
|
||||
Formatted <i class="fa fa-download"></i>
|
||||
Formatted <i aria-hidden="true" class="fa fa-download"></i>
|
||||
</a>
|
||||
<paginate-controls></paginate-controls>
|
||||
</div>
|
||||
|
|
|
@ -6,8 +6,16 @@ define(function (require) {
|
|||
_(BucketAggType).inherits(AggType);
|
||||
function BucketAggType(config) {
|
||||
BucketAggType.Super.call(this, config);
|
||||
|
||||
if (_.isFunction(config.getKey)) {
|
||||
this.getKey = config.getKey;
|
||||
}
|
||||
}
|
||||
|
||||
BucketAggType.prototype.getKey = function (bucket, key) {
|
||||
return key || bucket.key;
|
||||
};
|
||||
|
||||
return BucketAggType;
|
||||
};
|
||||
});
|
|
@ -18,31 +18,35 @@ define(function (require) {
|
|||
},
|
||||
{
|
||||
display: 'Second',
|
||||
val: 'second'
|
||||
val: 's'
|
||||
},
|
||||
{
|
||||
display: 'Minute',
|
||||
val: 'minute'
|
||||
val: 'm'
|
||||
},
|
||||
{
|
||||
display: 'Hourly',
|
||||
val: 'hour'
|
||||
val: 'h'
|
||||
},
|
||||
{
|
||||
display: 'Daily',
|
||||
val: 'day'
|
||||
val: 'd'
|
||||
},
|
||||
{
|
||||
display: 'Weekly',
|
||||
val: 'week'
|
||||
val: 'w'
|
||||
},
|
||||
{
|
||||
display: 'Monthly',
|
||||
val: 'month'
|
||||
val: 'M'
|
||||
},
|
||||
{
|
||||
display: 'Yearly',
|
||||
val: 'year'
|
||||
val: 'y'
|
||||
},
|
||||
{
|
||||
display: 'Custom',
|
||||
val: 'custom'
|
||||
}
|
||||
];
|
||||
};
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
define(function (require) {
|
||||
var dateRange = require('utils/date_range');
|
||||
|
||||
return function createDateRangeFilterProvider(config) {
|
||||
var buildRangeFilter = require('components/filter_manager/lib/range');
|
||||
|
||||
return function (agg, key) {
|
||||
var range = dateRange.parse(key, config.get('dateFormat'));
|
||||
|
||||
var filter = {};
|
||||
if (range.from) filter.gte = +range.from;
|
||||
if (range.to) filter.lt = +range.to;
|
||||
|
||||
return buildRangeFilter(agg.params.field, filter, agg.vis.indexPattern);
|
||||
};
|
||||
|
||||
};
|
||||
});
|
|
@ -4,10 +4,10 @@ define(function (require) {
|
|||
return function (aggConfig, key) {
|
||||
var splits = key.split(/\-/);
|
||||
var gte = Number(splits[0]);
|
||||
var lte = Number(splits[1]);
|
||||
var lt = Number(splits[1]);
|
||||
return buildRangeFilter(aggConfig.params.field, {
|
||||
gte: gte,
|
||||
lte: lte
|
||||
lt: lt
|
||||
}, aggConfig.vis.indexPattern);
|
||||
};
|
||||
};
|
||||
|
|
|
@ -8,6 +8,12 @@ define(function (require) {
|
|||
|
||||
var tzOffset = moment().format('Z');
|
||||
|
||||
function getInterval(agg) {
|
||||
var interval = _.get(agg, ['params', 'interval']);
|
||||
if (interval && interval.val === 'custom') interval = _.get(agg, ['params', 'customInterval']);
|
||||
return interval;
|
||||
}
|
||||
|
||||
function setBounds(agg, force) {
|
||||
if (agg.buckets._alreadySet && !force) return;
|
||||
agg.buckets._alreadySet = true;
|
||||
|
@ -37,7 +43,7 @@ define(function (require) {
|
|||
if (buckets) return buckets;
|
||||
|
||||
buckets = new TimeBuckets();
|
||||
buckets.setInterval(_.get(this, ['params', 'interval']));
|
||||
buckets.setInterval(getInterval(this));
|
||||
setBounds(this);
|
||||
|
||||
return buckets;
|
||||
|
@ -68,7 +74,7 @@ define(function (require) {
|
|||
},
|
||||
write: function (agg, output) {
|
||||
setBounds(agg);
|
||||
agg.buckets.setInterval(agg.params.interval);
|
||||
agg.buckets.setInterval(getInterval(agg));
|
||||
|
||||
var interval = agg.buckets.getInterval();
|
||||
output.bucketInterval = interval;
|
||||
|
@ -90,6 +96,12 @@ define(function (require) {
|
|||
}
|
||||
},
|
||||
|
||||
{
|
||||
name: 'customInterval',
|
||||
default: '2h',
|
||||
write: _.noop
|
||||
},
|
||||
|
||||
{
|
||||
name: 'format'
|
||||
},
|
||||
|
|
36
src/kibana/components/agg_types/buckets/date_range.js
Normal file
36
src/kibana/components/agg_types/buckets/date_range.js
Normal file
|
@ -0,0 +1,36 @@
|
|||
define(function (require) {
|
||||
var moment = require('moment');
|
||||
var dateRange = require('utils/date_range');
|
||||
require('directives/validate_date_math');
|
||||
|
||||
return function DateRangeAggDefinition(Private, config) {
|
||||
var BucketAggType = Private(require('components/agg_types/buckets/_bucket_agg_type'));
|
||||
var createFilter = Private(require('components/agg_types/buckets/create_filter/date_range'));
|
||||
|
||||
return new BucketAggType({
|
||||
name: 'date_range',
|
||||
title: 'Date Range',
|
||||
createFilter: createFilter,
|
||||
getKey: function (bucket) {
|
||||
return dateRange.toString(bucket, config.get('dateFormat'));
|
||||
},
|
||||
makeLabel: function (aggConfig) {
|
||||
return aggConfig.params.field.displayName + ' date ranges';
|
||||
},
|
||||
params: [{
|
||||
name: 'field',
|
||||
filterFieldTypes: 'date',
|
||||
default: function (agg) {
|
||||
return agg.vis.indexPattern.timeFieldName;
|
||||
}
|
||||
}, {
|
||||
name: 'ranges',
|
||||
default: [{
|
||||
from: 'now-1w/w',
|
||||
to: 'now'
|
||||
}],
|
||||
editor: require('text!components/agg_types/controls/date_ranges.html')
|
||||
}]
|
||||
});
|
||||
};
|
||||
});
|
48
src/kibana/components/agg_types/controls/date_ranges.html
Normal file
48
src/kibana/components/agg_types/controls/date_ranges.html
Normal file
|
@ -0,0 +1,48 @@
|
|||
<div>
|
||||
<small><a target="_window" href="http://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html#date-math">Accepted Date Formats <i class="fa-link fa"></i></a></small>
|
||||
|
||||
<table class="vis-editor-agg-editor-ranges form-group">
|
||||
<tr>
|
||||
<th>
|
||||
<label>From</label>
|
||||
</th>
|
||||
<th colspan="2">
|
||||
<label>To</label>
|
||||
</th>
|
||||
</tr>
|
||||
|
||||
<tr
|
||||
ng-repeat="range in agg.params.ranges track by $index">
|
||||
<td class="kbn-timepicker">
|
||||
<input
|
||||
ng-model="range.from"
|
||||
validate-date-math
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="range.from" />
|
||||
</td>
|
||||
<td class="kbn-timepicker">
|
||||
<input
|
||||
ng-model="range.to"
|
||||
validate-date-math
|
||||
class="form-control"
|
||||
name="range.to" />
|
||||
</td>
|
||||
<td>
|
||||
<button
|
||||
type="button"
|
||||
ng-click="agg.params.ranges.splice($index, 1)"
|
||||
class="btn btn-danger btn-xs">
|
||||
<i class="fa fa-ban" ></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div
|
||||
ng-click="agg.params.ranges.push({})"
|
||||
class="sidebar-item-button primary">
|
||||
Add Range
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -9,7 +9,7 @@
|
|||
</span>
|
||||
<div class="hintbox" ng-show="showAnalyzedFieldWarning">
|
||||
<p>
|
||||
<strong>Careful!</strong> The field selected contains analyzed strings. Values such as <i>foo-bar</i> will be broken into <i>foo</i> and <i>bar</i>. See <a href="http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/mapping-core-types.html" target="_blank">Mapping Core Types</a> for more information on setting this field as <i>not_analyzed</i>
|
||||
<strong>Careful!</strong> The field selected contains analyzed strings. Values such as <i>foo-bar</i> will be broken into <i>foo</i> and <i>bar</i>. See <a href="http://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-core-types.html" target="_blank">Mapping Core Types</a> for more information on setting this field as <i>not_analyzed</i>
|
||||
</p>
|
||||
|
||||
<p ng-show="indexedFields.byName[agg.params.field.name + '.raw'].analyzed == false">
|
||||
|
@ -22,8 +22,9 @@
|
|||
name="field"
|
||||
required
|
||||
ng-model="agg.params.field"
|
||||
auto-select-if-only-one="indexedFields"
|
||||
ng-options="field as field.displayName group by field.type for field in indexedFields"
|
||||
ng-change="aggParam.onChange(agg)">
|
||||
</select>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class="form-group">
|
||||
<div ng-repeat="filter in agg.params.filters">
|
||||
<label>Query {{$index + 1}}</label>
|
||||
<label>Filter {{$index + 1}}</label>
|
||||
<div class="form-group vis-editor-agg-form-row">
|
||||
<input validate-query
|
||||
ng-model="filter.input.query"
|
||||
|
@ -21,5 +21,5 @@
|
|||
click-focus="'filter'+(agg.params.filters.length-1)"
|
||||
ng-click="agg.params.filters.push({input:{}})"
|
||||
class="sidebar-item-button primary">
|
||||
Add filter
|
||||
Add Filter
|
||||
</div>
|
||||
|
|
|
@ -18,6 +18,13 @@
|
|||
name="interval">
|
||||
<option value="">-- select a valid interval --</option>
|
||||
</select>
|
||||
<input
|
||||
type="text"
|
||||
ng-model="agg.params.customInterval"
|
||||
ng-change="agg.write()"
|
||||
ng-if="agg.params.interval.val == 'custom'"
|
||||
class="form-control"
|
||||
required />
|
||||
<input
|
||||
ng-if="!aggParam.options"
|
||||
ng-model="agg.params.interval"
|
||||
|
|
|
@ -15,14 +15,16 @@
|
|||
ng-model="range.from"
|
||||
type="number"
|
||||
class="form-control"
|
||||
name="range.from" />
|
||||
name="range.from"
|
||||
step="any" />
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
ng-model="range.to"
|
||||
type="number"
|
||||
class="form-control"
|
||||
name="range.to" />
|
||||
name="range.to"
|
||||
step="any" />
|
||||
</td>
|
||||
<td>
|
||||
<button
|
||||
|
|
|
@ -17,6 +17,7 @@ define(function (require) {
|
|||
Private(require('components/agg_types/buckets/date_histogram')),
|
||||
Private(require('components/agg_types/buckets/histogram')),
|
||||
Private(require('components/agg_types/buckets/range')),
|
||||
Private(require('components/agg_types/buckets/date_range')),
|
||||
Private(require('components/agg_types/buckets/ip_range')),
|
||||
Private(require('components/agg_types/buckets/terms')),
|
||||
Private(require('components/agg_types/buckets/filters')),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
define(function (require) {
|
||||
return function MetricAggTypeProvider(Private) {
|
||||
return function MetricAggTypeProvider(Private, indexPatterns) {
|
||||
var _ = require('lodash');
|
||||
var AggType = Private(require('components/agg_types/_agg_type'));
|
||||
|
||||
|
@ -21,6 +21,15 @@ define(function (require) {
|
|||
return bucket[agg.id].value;
|
||||
};
|
||||
|
||||
MetricAggType.prototype.getFormat = function (agg) {
|
||||
var field = agg.field();
|
||||
if (field && field.type === 'date' && field.format) {
|
||||
return field.format;
|
||||
} else {
|
||||
return indexPatterns.fieldFormats.byName.number;
|
||||
}
|
||||
};
|
||||
|
||||
return MetricAggType;
|
||||
};
|
||||
});
|
|
@ -4,7 +4,7 @@ define(function (require) {
|
|||
|
||||
return new MetricAggType({
|
||||
name: 'cardinality',
|
||||
title: 'Unique count',
|
||||
title: 'Unique Count',
|
||||
makeLabel: function (aggConfig) {
|
||||
return 'Unique count of ' + aggConfig.params.field.displayName;
|
||||
},
|
||||
|
|
|
@ -11,7 +11,7 @@ define(function (require) {
|
|||
params: [
|
||||
{
|
||||
name: 'field',
|
||||
filterFieldTypes: 'number'
|
||||
filterFieldTypes: 'number,date'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
|
|
@ -11,7 +11,7 @@ define(function (require) {
|
|||
params: [
|
||||
{
|
||||
name: 'field',
|
||||
filterFieldTypes: 'number'
|
||||
filterFieldTypes: 'number,date'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
define(function (require) {
|
||||
require('css!components/collapsible_sidebar/collapsible_sidebar.css');
|
||||
|
||||
var _ = require('lodash');
|
||||
var $ = require('jquery');
|
||||
|
||||
require('modules')
|
||||
.get('kibana')
|
||||
.directive('collapsibleSidebar', function () {
|
||||
var listOfWidthClasses = 1;
|
||||
// simply a list of all of all of angulars .col-md-* classes except 12
|
||||
listOfWidthClasses = _(new Array(11)).map(function (n) { return 'col-md-' + listOfWidthClasses++; });
|
||||
|
||||
return {
|
||||
restrict: 'C',
|
||||
link: function ($scope, $elem) {
|
||||
var $collapser = $('<div class="sidebar-collapser"><div class="chevron-cont"></div></div>');
|
||||
var $siblings = $elem.siblings();
|
||||
|
||||
var siblingsClass = listOfWidthClasses.reduce(function (prev, className) {
|
||||
if (prev) return prev;
|
||||
return $siblings.hasClass(className) && className;
|
||||
}, false);
|
||||
|
||||
$collapser.on('click', function () {
|
||||
$elem.toggleClass('closed');
|
||||
// if there is are only two elements we can assume the other one will take 100% of the width
|
||||
if ($siblings.length === 1 && siblingsClass) {
|
||||
$siblings.toggleClass(siblingsClass + ' col-md-12');
|
||||
}
|
||||
})
|
||||
|
||||
.appendTo($elem);
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
|
@ -0,0 +1,58 @@
|
|||
.sidebar-container.collapsible-sidebar {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
||||
.sidebar-collapser {
|
||||
background-color: #ecf0f1;
|
||||
height: 28px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: -20px;
|
||||
width: 20px;
|
||||
border: 1px solid #ecf0f1;
|
||||
border-width: 0 1px 1px 0;
|
||||
cursor: pointer;
|
||||
z-index: -1;
|
||||
border-bottom-right-radius: 4px;
|
||||
|
||||
.chevron-cont{
|
||||
position: absolute;
|
||||
left: 4px;
|
||||
top: 5px;
|
||||
|
||||
&:before {
|
||||
font-family: FontAwesome;
|
||||
color: #333;
|
||||
content: "\F053";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.closed {
|
||||
width: 0 !important;
|
||||
border-right-width: 0;
|
||||
border-left-width: 0;
|
||||
|
||||
> * {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.sidebar-collapser {
|
||||
visibility: visible;
|
||||
.chevron-cont:before {
|
||||
content: "\F054";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 992px) {
|
||||
.sidebar-container.collapsible-sidebar {
|
||||
&.closed {
|
||||
display: none;
|
||||
}
|
||||
.sidebar-collapser {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -177,7 +177,7 @@ define(function (require) {
|
|||
this._segments.push(seg);
|
||||
|
||||
merged.took += seg.took;
|
||||
merged.hits.total = Math.max(merged.hits.total, seg.hits.total);
|
||||
merged.hits.total += seg.hits.total;
|
||||
merged.hits.max_score = Math.max(merged.hits.max_score, seg.hits.max_score);
|
||||
[].push.apply(merged.hits.hits, seg.hits.hits);
|
||||
|
||||
|
|
|
@ -6,10 +6,12 @@ define(function (require) {
|
|||
var module = require('modules').get('app/discover');
|
||||
|
||||
require('components/highlight/highlight');
|
||||
require('components/highlight/highlight_tags');
|
||||
require('components/doc_viewer/doc_viewer');
|
||||
require('filters/trust_as_html');
|
||||
require('filters/short_dots');
|
||||
|
||||
|
||||
// guestimate at the minimum number of chars wide cells in the table should be
|
||||
var MIN_LINE_LENGTH = 20;
|
||||
|
||||
|
@ -21,7 +23,7 @@ define(function (require) {
|
|||
* <tr ng-repeat="row in rows" kbn-table-row="row"></tr>
|
||||
* ```
|
||||
*/
|
||||
module.directive('kbnTableRow', function ($compile, config, highlightFilter, shortDotsFilter, courier) {
|
||||
module.directive('kbnTableRow', function ($compile, config, highlightFilter, highlightTags, shortDotsFilter, courier) {
|
||||
var openRowHtml = require('text!components/doc_table/components/table_row/open.html');
|
||||
var detailsHtml = require('text!components/doc_table/components/table_row/details.html');
|
||||
var cellTemplate = _.template(require('text!components/doc_table/components/table_row/cell.html'));
|
||||
|
@ -104,14 +106,17 @@ define(function (require) {
|
|||
|
||||
$scope.columns.forEach(function (column) {
|
||||
var formatted;
|
||||
|
||||
var sources = _.extend({}, row.$$_formatted, row.highlight);
|
||||
if (column === '_source') {
|
||||
formatted = sourceTemplate({
|
||||
source: _.mapValues(row.$$_formatted, function (val, field) {
|
||||
var sourceConfig = {
|
||||
source: _.mapValues(sources, function (val, field) {
|
||||
return _displayField(row, field, false);
|
||||
}),
|
||||
highlight: row.highlight,
|
||||
shortDotsFilter: shortDotsFilter
|
||||
});
|
||||
};
|
||||
formatted = sourceTemplate(sourceConfig);
|
||||
} else {
|
||||
formatted = _displayField(row, column, true);
|
||||
}
|
||||
|
@ -187,6 +192,16 @@ define(function (require) {
|
|||
function _getValForField(row, field) {
|
||||
var val;
|
||||
|
||||
if (row.highlight && row.highlight[field]) {
|
||||
// Strip out the highlight tags so we have the "original" value
|
||||
var untagged = _.map(row.highlight[field], function (value) {
|
||||
return value
|
||||
.split(highlightTags.pre).join('')
|
||||
.split(highlightTags.post).join('');
|
||||
});
|
||||
return _formatField(untagged, field);
|
||||
}
|
||||
|
||||
// discover formats all of the values and puts them in $$_formatted for display
|
||||
val = (row.$$_formatted || _formatRow(row))[field];
|
||||
|
||||
|
|
|
@ -25,7 +25,11 @@
|
|||
</td>
|
||||
|
||||
<td>
|
||||
<i bo-if="!mapping[field] && !showArrayInObjectsWarning(doc, field)"
|
||||
<i bo-if="!mapping[field] && field[0] === '_'"
|
||||
tooltip-placement="top"
|
||||
tooltip="Field names beginning with _ are not supported"
|
||||
class="fa fa-warning text-color-warning ng-scope doc-viewer-underscore"></i>
|
||||
<i bo-if="!mapping[field] && field[0] !== '_' && !showArrayInObjectsWarning(doc, field)"
|
||||
tooltip-placement="top"
|
||||
tooltip="No cached mapping for this field. Refresh your mapping from the Settings > Indices page"
|
||||
class="fa fa-warning text-color-warning ng-scope doc-viewer-no-mapping"></i>
|
||||
|
@ -43,4 +47,4 @@
|
|||
|
||||
<pre ng-show="mode == 'json'">{{hit | json}}</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -247,5 +247,15 @@ define(function (require) {
|
|||
};
|
||||
inherits(errors.PieContainsAllZeros, KbnError);
|
||||
|
||||
/**
|
||||
* error thrown when no results are returned from an elasticsearch query
|
||||
*/
|
||||
errors.CannotLogScaleNegVals = function CannotLogScaleNegVals() {
|
||||
KbnError.call(this,
|
||||
'Negative values cannot be displayed on a log scale',
|
||||
errors.CannotLogScaleNegVals);
|
||||
};
|
||||
inherits(errors.CannotLogScaleNegVals, KbnError);
|
||||
|
||||
return errors;
|
||||
});
|
||||
|
|
|
@ -9,9 +9,9 @@ define(function (require) {
|
|||
.get(filter.meta.index).then(function (indexPattern) {
|
||||
key = _.keys(filter.range)[0];
|
||||
field = indexPattern.fields.byName[key];
|
||||
from = filter.range[key].gte || filter.range[key].gt;
|
||||
to = filter.range[key].lte || filter.range[key].lt;
|
||||
from = (filter.range[key].gte != null) ? filter.range[key].gte : filter.range[key].gt;
|
||||
from = field.format.convert(from);
|
||||
to = (filter.range[key].lte != null) ? filter.range[key].lte : filter.range[key].lt;
|
||||
to = field.format.convert(to);
|
||||
value = from + ' to ' + to;
|
||||
return { key: key, value: value };
|
||||
|
|
24
src/kibana/components/filter_bar/lib/watchFilters.js
Normal file
24
src/kibana/components/filter_bar/lib/watchFilters.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
define(function (require) {
|
||||
return function watchFiltersProvider(Private, Promise, Notifier) {
|
||||
var _ = require('lodash');
|
||||
var onlyDisabled = require('components/filter_bar/lib/onlyDisabled');
|
||||
var EventEmitter = Private(require('factories/events'));
|
||||
var notify = new Notifier({ location: 'Fitler Bar' });
|
||||
|
||||
return function ($scope, handlers) {
|
||||
var emitter = new EventEmitter();
|
||||
|
||||
$scope.$watch('state.filters', function (newFilters, oldFilters) {
|
||||
if (newFilters === oldFilters) return;
|
||||
|
||||
return emitter.emit('update')
|
||||
.then(function () {
|
||||
if (onlyDisabled(newFilters, oldFilters)) return;
|
||||
return emitter.emit('fetch');
|
||||
});
|
||||
});
|
||||
|
||||
return emitter;
|
||||
};
|
||||
};
|
||||
});
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
|
||||
### Formatting a value
|
||||
To format a response value, you need to get ahold of the field list, which is usually available at `indexPattern.fields`. Each field object has a `format` property*, which is an object detailed in [_field_formats.js](https://github.com/elasticsearch/kibana4/blob/master/src/kibana/components/index_patterns/_field_formats.js).
|
||||
To format a response value, you need to get ahold of the field list, which is usually available at `indexPattern.fields`. Each field object has a `format` property*, which is an object detailed in [_field_formats.js](https://github.com/elastic/kibana4/blob/master/src/kibana/components/index_patterns/_field_formats.js).
|
||||
|
||||
Once you have the field that a response value came from, pass the value to `field.format.convert(value)` and a formatted string representation of the field will be returned.
|
||||
|
||||
|
@ -9,9 +9,9 @@
|
|||
|
||||
### Changing a field's format
|
||||
|
||||
Currently only one field format exists, `"string"`, which just [flattens any value down to a string](https://github.com/elasticsearch/kibana4/blob/master/src/kibana/components/index_patterns/_field_formats.js#L18-L24).
|
||||
Currently only one field format exists, `"string"`, which just [flattens any value down to a string](https://github.com/elastic/kibana4/blob/master/src/kibana/components/index_patterns/_field_formats.js#L18-L24).
|
||||
|
||||
To change the format for a specific field you can either change the default for a field type modify the [default format mapping here](https://github.com/elasticsearch/kibana4/blob/master/src/kibana/components/index_patterns/_field_formats.js#L37-L46).
|
||||
To change the format for a specific field you can either change the default for a field type modify the [default format mapping here](https://github.com/elastic/kibana4/blob/master/src/kibana/components/index_patterns/_field_formats.js#L37-L46).
|
||||
|
||||
To change the format for a specific indexPattern's field, add the field and format name to `indexPattern.customFormats` object property.
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
|||
```
|
||||
|
||||
### Passing the formats to a chart
|
||||
Currently, the [histogram formatter](https://github.com/elasticsearch/kibana4/blob/master/src/plugins/visualize/saved_visualizations/resp_converters/histogram.js) passes the formatting function as the `xAxisFormatter` and `yAxisFormatter` function.
|
||||
Currently, the [histogram formatter](https://github.com/elastic/kibana4/blob/master/src/plugins/visualize/saved_visualizations/resp_converters/histogram.js) passes the formatting function as the `xAxisFormatter` and `yAxisFormatter` function.
|
||||
|
||||
*/
|
||||
|
||||
|
|
|
@ -16,6 +16,6 @@ define(function (require) {
|
|||
}
|
||||
});
|
||||
|
||||
return hit.$$_flattened = _.merge(source, fields, _.pick(hit, self.metaFields));
|
||||
return hit.$$_flattened = _.merge(source, fields, _.pick(hit, self.metaFields), _.pick(hit.fields, self.metaFields));
|
||||
};
|
||||
});
|
||||
|
|
|
@ -87,6 +87,14 @@ define(function (require) {
|
|||
return rtn;
|
||||
}
|
||||
|
||||
// browsers format Error.stack differently; always include message
|
||||
function formatStack(err) {
|
||||
if (err.stack && !~err.stack.indexOf(err.message)) {
|
||||
return 'Error: ' + err.message + '\n' + err.stack;
|
||||
}
|
||||
return err.stack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Functionality to check that
|
||||
*/
|
||||
|
@ -187,7 +195,7 @@ define(function (require) {
|
|||
|
||||
var html = fatalToastTemplate({
|
||||
msg: formatMsg(err, this.from),
|
||||
stack: err.stack
|
||||
stack: formatStack(err)
|
||||
});
|
||||
|
||||
var $container = $('#fatal-splash-screen');
|
||||
|
@ -217,7 +225,7 @@ define(function (require) {
|
|||
title: 'Error',
|
||||
lifetime: Infinity,
|
||||
actions: ['report', 'accept'],
|
||||
stack: err.stack.indexOf(err.message) > -1 ? err.stack : (err.message + err.stack)
|
||||
stack: formatStack(err)
|
||||
}, cb);
|
||||
};
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
'fa-sort': paginatedTable.sort.columnIndex !== $index || paginatedTable.sort.direction === null
|
||||
}">
|
||||
</i>
|
||||
<i ng-if="col.filterable" class="fa fa-search" ng-click="$event.stopPropagation()" tooltip="Click on a cell to filter"></i>
|
||||
<i aria-label="Click on a cell to filter" ng-if="col.filterable" class="fa fa-search" ng-click="$event.stopPropagation()" tooltip="Click on a cell to filter"></i>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
|
|
@ -4,6 +4,7 @@ define(function (require) {
|
|||
var moment = require('moment');
|
||||
|
||||
var datemath = require('utils/datemath');
|
||||
var parseInterval = require('utils/parse_interval');
|
||||
var calcAuto = Private(require('components/time_buckets/calc_auto_interval'));
|
||||
var calcEsInterval = Private(require('components/time_buckets/calc_es_interval'));
|
||||
var tzOffset = moment().format('Z');
|
||||
|
@ -145,17 +146,16 @@ define(function (require) {
|
|||
|
||||
if (_.isString(interval)) {
|
||||
input = interval;
|
||||
interval = moment.duration(1, interval);
|
||||
interval = parseInterval(interval);
|
||||
if (+interval === 0) {
|
||||
interval = null;
|
||||
input += ' (not a valid moment unit)';
|
||||
}
|
||||
}
|
||||
|
||||
// if the value wasn't converted to a duration, and isn't
|
||||
// already a duration, we have a problem
|
||||
if (!moment.isDuration(interval)) {
|
||||
throw new TypeError('can\'t convert input ' + input + ' to a moment.duration');
|
||||
throw new TypeError('"' + input + '" is not a valid interval.');
|
||||
}
|
||||
|
||||
this._i = interval;
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
</div>
|
||||
|
||||
<div ng-switch-when="relative">
|
||||
<form ng-submit="applyRelative()" class="form-inline" name="relativeTime">
|
||||
<form role="form" ng-submit="applyRelative()" class="form-inline" name="relativeTime">
|
||||
<div class="kbn-timepicker-section">
|
||||
<label>
|
||||
From:
|
||||
|
|
|
@ -254,6 +254,10 @@ define(function (require) {
|
|||
return this.type.getValue(this, bucket);
|
||||
};
|
||||
|
||||
AggConfig.prototype.getKey = function (bucket, key) {
|
||||
return this.type.getKey(bucket, key);
|
||||
};
|
||||
|
||||
AggConfig.prototype.makeLabel = function () {
|
||||
if (!this.type) return '';
|
||||
return this.type.makeLabel(this);
|
||||
|
@ -264,12 +268,15 @@ define(function (require) {
|
|||
};
|
||||
|
||||
AggConfig.prototype.fieldFormatter = function () {
|
||||
if (this.schema && this.schema.group === 'metrics') {
|
||||
return fieldFormats.defaultByType.number.convert;
|
||||
var field = this.field();
|
||||
var format = field && field.format;
|
||||
var strFormat = fieldFormats.defaultByType.string;
|
||||
|
||||
if (this.type.getFormat) {
|
||||
format = this.type.getFormat(this) || format;
|
||||
}
|
||||
|
||||
var field = this.field();
|
||||
return field ? field.format.convert : String;
|
||||
return (format || strFormat).convert;
|
||||
};
|
||||
|
||||
AggConfig.prototype.fieldName = function () {
|
||||
|
|
|
@ -108,4 +108,4 @@ define(function (require) {
|
|||
];
|
||||
};
|
||||
};
|
||||
});
|
||||
});
|
||||
|
|
|
@ -3,6 +3,7 @@ define(function (require) {
|
|||
var _ = require('lodash');
|
||||
var $ = require('jquery');
|
||||
var numeral = require('numeral');
|
||||
var errors = require('errors');
|
||||
|
||||
var ErrorHandler = Private(require('components/vislib/lib/_error_handler'));
|
||||
|
||||
|
@ -32,6 +33,62 @@ define(function (require) {
|
|||
d3.select(this.el).selectAll('.y-axis-div').call(this.draw());
|
||||
};
|
||||
|
||||
YAxis.prototype.throwCustomError = function (message) {
|
||||
throw new Error(message);
|
||||
};
|
||||
|
||||
YAxis.prototype.throwCannotLogScaleNegVals = function () {
|
||||
throw new errors.CannotLogScaleNegVals();
|
||||
};
|
||||
|
||||
YAxis.prototype.throwNoResultsError = function () {
|
||||
throw new errors.NoResults();
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the appropriate D3 scale
|
||||
*
|
||||
* @param fnName {String} D3 scale
|
||||
* @returns {*}
|
||||
*/
|
||||
YAxis.prototype.getScaleType = function (fnName) {
|
||||
if (fnName === 'square root') fnName = 'sqrt'; // Rename 'square root' to 'sqrt'
|
||||
fnName = fnName || 'linear';
|
||||
|
||||
if (typeof d3.scale[fnName] !== 'function') return this.throwCustomError('YAxis.getScaleType: ' + fnName + ' is not a function');
|
||||
|
||||
return d3.scale[fnName]();
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the domain for log scale, i.e. the extent of the log scale.
|
||||
* Log scales must begin at 1 since the log(0) = -Infinity
|
||||
*
|
||||
* @param scale
|
||||
* @param yMin
|
||||
* @param yMax
|
||||
* @returns {*[]}
|
||||
*/
|
||||
YAxis.prototype.returnLogDomain = function (yMin, yMax) {
|
||||
if (yMin < 0 || yMax < 0) return this.throwCannotLogScaleNegVals();
|
||||
return [Math.max(1, yMin), yMax];
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the domain, i.e. the extent of the y axis
|
||||
*
|
||||
* @param scale {String} Kibana scale
|
||||
* @param yMin {Number} Y-axis minimum value
|
||||
* @param yMax {Number} Y-axis maximum value
|
||||
* @returns {*[]}
|
||||
*/
|
||||
YAxis.prototype.getDomain = function (scale, yMin, yMax) {
|
||||
if (scale === 'log') return this.returnLogDomain(yMin, yMax); // Negative values cannot be displayed with a log scale.
|
||||
if (yMin === 0 && yMax === 0) return this.throwNoResultsError(); // yMin and yMax can never both be equal to zero
|
||||
|
||||
return [Math.min(0, yMin), Math.max(0, yMax)];
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates the d3 y scale function
|
||||
*
|
||||
|
@ -40,41 +97,10 @@ define(function (require) {
|
|||
* @returns {D3.Scale.QuantitiveScale|*} D3 yScale function
|
||||
*/
|
||||
YAxis.prototype.getYScale = function (height) {
|
||||
|
||||
// yMin and yMax can never be equal for the axis
|
||||
// to render. Defaults yMin to 0 if yMin === yMax
|
||||
// and yMin is greater than or equal to zero, else
|
||||
// defaults yMax to zero.
|
||||
if (this.yMin === this.yMax) {
|
||||
if (this.yMin > 0) {
|
||||
this.yMin = 0;
|
||||
} else if (this.yMin === 0) {
|
||||
this.yMin = -1;
|
||||
this.yMax = 1;
|
||||
} else {
|
||||
this.yMax = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this._attr.defaultYExtents) {
|
||||
// if yMin and yMax are both positive, then yMin should be zero
|
||||
if (this.yMin > 0 && this.yMax > 0) {
|
||||
this.yMin = 0;
|
||||
}
|
||||
|
||||
// if yMin and yMax are both negative, then yMax should be zero
|
||||
if (this.yMin < 0 && this.yMax < 0) {
|
||||
this.yMax = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// save reference to y scale
|
||||
this.yScale = d3.scale.linear()
|
||||
.domain([this.yMin, this.yMax])
|
||||
return this.yScale = this.getScaleType(this._attr.scale)
|
||||
.domain(this.getDomain(this._attr.scale, this.yMin, this.yMax))
|
||||
.range([height, 0])
|
||||
.nice(this.tickScale(height));
|
||||
|
||||
return this.yScale;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
// margin: 10px 0 0 6px;
|
||||
min-height: 0;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* YAxis logic */
|
||||
|
|
|
@ -80,6 +80,7 @@ define(function (require) {
|
|||
// Because we have to wait for the DOM element to initialize, we do not
|
||||
// want to throw an error when the DOM `el` is zero
|
||||
if (error instanceof errors.ContainerTooSmall ||
|
||||
error instanceof errors.CannotLogScaleNegVals ||
|
||||
error instanceof errors.PieContainsAllZeros ||
|
||||
error instanceof errors.NotEnoughData ||
|
||||
error instanceof errors.NoResults) {
|
||||
|
|
|
@ -71,10 +71,18 @@ define(function (require) {
|
|||
var xScale = this.handler.xAxis.xScale;
|
||||
var yScale = this.handler.yAxis.yScale;
|
||||
var ordered = this.handler.data.get('ordered');
|
||||
var visibleRadius = 3;
|
||||
var touchableRadius = 12;
|
||||
var tooltip = this.tooltip;
|
||||
var isTooltip = this._attr.addTooltip;
|
||||
var radii = _(data)
|
||||
.map(function (series) { return _.map(series, function (point) { return point._input.z; }); })
|
||||
.flatten()
|
||||
.reduce(function (result, val) {
|
||||
if (result.min > val) result.min = val;
|
||||
if (result.max < val) result.max = val;
|
||||
return result;
|
||||
}, {min: Infinity, max: -Infinity});
|
||||
|
||||
var radiusStep = ((radii.max - radii.min) || (radii.max * 100)) / Math.pow(this._attr.radiusRatio, 2);
|
||||
|
||||
var layer = svg.selectAll('.points')
|
||||
.data(data)
|
||||
|
@ -116,11 +124,23 @@ define(function (require) {
|
|||
if (!showCircles && !isVisible) return 'none';
|
||||
return cColor(d);
|
||||
}
|
||||
function getCircleRadiusFn(modifier) {
|
||||
return function getCircleRadius(d) {
|
||||
var margin = self._attr.margin;
|
||||
var width = self._attr.width - margin.left - margin.right;
|
||||
var height = self._attr.height - margin.top - margin.bottom;
|
||||
var circleRadius = (d._input.z - radii.min) / radiusStep;
|
||||
|
||||
return _.min([Math.sqrt((circleRadius || 2) + 2), width, height]) + (modifier || 0);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
circles
|
||||
.enter()
|
||||
.append('circle')
|
||||
.attr('r', visibleRadius)
|
||||
.attr('r', getCircleRadiusFn())
|
||||
.attr('fill-opacity', (this._attr.drawLinesBetweenPoints ? 1 : 0.7))
|
||||
.attr('cx', cx)
|
||||
.attr('cy', cy)
|
||||
.attr('fill', colorCircle)
|
||||
|
@ -131,7 +151,7 @@ define(function (require) {
|
|||
circles
|
||||
.enter()
|
||||
.append('circle')
|
||||
.attr('r', touchableRadius)
|
||||
.attr('r', getCircleRadiusFn(10))
|
||||
.attr('cx', cx)
|
||||
.attr('cy', cy)
|
||||
.attr('fill', 'transparent')
|
||||
|
@ -298,7 +318,9 @@ define(function (require) {
|
|||
}
|
||||
|
||||
self.addClipPath(svg, width, height);
|
||||
lines = self.addLines(svg, data.series);
|
||||
if (self._attr.drawLinesBetweenPoints) {
|
||||
lines = self.addLines(svg, data.series);
|
||||
}
|
||||
circles = self.addCircles(svg, layers);
|
||||
self.addCircleEvents(circles, svg);
|
||||
self.createEndZones(svg);
|
||||
|
|
|
@ -71,7 +71,7 @@ define(function (require) {
|
|||
}
|
||||
|
||||
var featureLayer;
|
||||
var tileLayer = L.tileLayer('http://otile{s}.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.jpeg', {
|
||||
var tileLayer = L.tileLayer('https://otile{s}-s.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.jpeg', {
|
||||
attribution: 'Tiles by <a href="http://www.mapquest.com/">MapQuest</a> — ' +
|
||||
'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, ' +
|
||||
'<a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>',
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
class="text-center visualize-error visualize-chart">
|
||||
<div class="item top"></div>
|
||||
<div class="item">
|
||||
<h2><i class="fa fa-meh-o"></i></h2>
|
||||
<h2 aria-hidden="true"><i aria-hidden="true" class="fa fa-meh-o"></i></h2>
|
||||
<h4>No results found</h4>
|
||||
</div>
|
||||
<div class="item bottom"></div>
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
define(function (require) {
|
||||
var module = require('modules').get('kibana');
|
||||
|
||||
module.directive('autoSelectIfOnlyOne', function () {
|
||||
module.directive('autoSelectIfOnlyOne', function ($parse) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
require: 'ngModel',
|
||||
link: function (scope, element, attributes, ngModelCtrl) {
|
||||
scope.$watch(attributes.autoSelectIfOnlyOne, function (options) {
|
||||
attributes.$observe('autoSelectIfOnlyOne', function (result) {
|
||||
var options = $parse(result)(scope);
|
||||
if (options && options.length === 1) {
|
||||
ngModelCtrl.$setViewValue(options[0]);
|
||||
ngModelCtrl.$render();
|
||||
|
|
|
@ -79,4 +79,4 @@ define(function (require) {
|
|||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
29
src/kibana/directives/validate_date_math.js
Normal file
29
src/kibana/directives/validate_date_math.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
define(function (require) {
|
||||
var _ = require('lodash');
|
||||
var DateMath = require('utils/datemath');
|
||||
|
||||
require('modules').get('kibana').directive('validateDateMath', function () {
|
||||
return {
|
||||
restrict: 'A',
|
||||
require: 'ngModel',
|
||||
scope: {
|
||||
'ngModel': '='
|
||||
},
|
||||
link: function ($scope, elem, attr, ngModel) {
|
||||
ngModel.$parsers.unshift(validateDateMath);
|
||||
ngModel.$formatters.unshift(validateDateMath);
|
||||
|
||||
function validateDateMath(input) {
|
||||
if (input == null || input === '') {
|
||||
ngModel.$setValidity('validDateMath', true);
|
||||
return null;
|
||||
}
|
||||
|
||||
var moment = DateMath.parse(input);
|
||||
ngModel.$setValidity('validDateMath', moment != null && moment.isValid());
|
||||
return input;
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
|
@ -1,4 +1,4 @@
|
|||
// See https://github.com/elasticsearch/elasticsearch/issues/6736
|
||||
// See https://github.com/elastic/elasticsearch/issues/6736
|
||||
define(function (require) {
|
||||
var _ = require('lodash');
|
||||
|
||||
|
@ -38,4 +38,4 @@ define(function (require) {
|
|||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -37,6 +37,8 @@ define(function (require) {
|
|||
Promise.resolve(handler(value)).catch(notify.fatal);
|
||||
});
|
||||
}());
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -61,6 +63,8 @@ define(function (require) {
|
|||
return handler !== listener.handler;
|
||||
});
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -53,4 +53,4 @@ define(function (require) {
|
|||
}
|
||||
|
||||
return propFilter;
|
||||
});
|
||||
});
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<div class="row">
|
||||
<div class="col-md-offset-4 col-md-4 page-header initial-load">
|
||||
<center>
|
||||
<img width="128" src="images/initial_load.gif">
|
||||
<img width="128" alt="Loading Kibana" src="images/initial_load.gif">
|
||||
<h1>
|
||||
<strong>Kibana</strong>
|
||||
<small id="cache-message">is loading. Give me a moment here. I'm loading a whole bunch of code. Don't worry, all this good stuff will be cached up for next time!</small>
|
||||
|
|
|
@ -7,6 +7,6 @@
|
|||
ng-options="opt.display for opt in opts.fetchIntervals">
|
||||
</select>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-default">
|
||||
<i class="fa fa-save"></i> Save
|
||||
<button type="submit" class="btn btn-default" aria-label="Save">
|
||||
<i aria-hidden="true" class="fa fa-save"></i> Save
|
||||
</button>
|
|
@ -1,4 +1,4 @@
|
|||
<i class="fa fa-info-circle"
|
||||
<i aria-label="{{info}}" class="fa fa-info-circle"
|
||||
tooltip="{{info}}"
|
||||
tooltip-placement="{{placement}}"
|
||||
tooltip-popup-delay="250"></i>
|
|
@ -1,4 +1,4 @@
|
|||
<form>
|
||||
<form role="form">
|
||||
<div class="form-group finder-form">
|
||||
<div>
|
||||
<a class="small pull-right" ng-click="manageObject(type)">manage {{type}}</a>
|
||||
|
@ -21,7 +21,7 @@
|
|||
ng-href="{{ makeUrl(hit) }}"
|
||||
ng-click="onChoose(hit, $event)">
|
||||
<li>
|
||||
<i class="fa" ng-if="hit.icon" ng-class="hit.icon"></i> {{hit.title}}
|
||||
<i aria-hidden="true" class="fa" ng-if="hit.icon" ng-class="hit.icon"></i> {{hit.title}}
|
||||
<p ng-if="hit.description" ng-bind="hit.description"></p>
|
||||
</li>
|
||||
</a>
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
<div class="panel-heading">
|
||||
<span class="panel-title">{{savedObj.title}}</span>
|
||||
<div class="btn-group">
|
||||
<a ng-show="!appEmbedded" ng-href="{{edit}}/{{panel.id | uriescape}}"><i class="fa fa-pencil"></i></a>
|
||||
<a ng-show="!appEmbedded" ng-click="remove()"><i class="fa fa-times"></i></a>
|
||||
<a aria-label="Edit" ng-show="!appEmbedded" ng-href="{{edit}}/{{panel.id | uriescape}}"><i aria-hidden="true" class="fa fa-pencil"></i></a>
|
||||
<a aria-label="Remove" ng-show="!appEmbedded" ng-click="remove()"><i aria-hidden="true" class="fa fa-times"></i></a>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
|
||||
<div ng-if="error" class="load-error">
|
||||
<i class="fa fa-exclamation-triangle"></i>
|
||||
<i aria-hidden="true" class="fa fa-exclamation-triangle"></i>
|
||||
<span ng-bind="error"></span>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ define(function (require) {
|
|||
.get('app/dashboard')
|
||||
.directive('dashboardPanel', function (savedVisualizations, savedSearches, Notifier, Private, $compile) {
|
||||
var _ = require('lodash');
|
||||
var filterBarClickHandler = Private(require('components/filter_bar/filter_bar_click_handler'));
|
||||
var loadPanel = Private(require('plugins/dashboard/components/panel/lib/load_panel'));
|
||||
var notify = new Notifier();
|
||||
|
||||
|
|
|
@ -209,7 +209,7 @@ define(function (require) {
|
|||
g.get_widgets_from_DOM();
|
||||
// We can't call this method if the gridmap is empty. This was found
|
||||
// when the user double clicked the "New Dashboard" icon. See
|
||||
// https://github.com/elasticsearch/kibana4/issues/390
|
||||
// https://github.com/elastic/kibana4/issues/390
|
||||
if (gridster.gridmap.length > 0) g.set_dom_grid_height();
|
||||
g.drag_api.set_limits(COLS * g.min_widget_width);
|
||||
};
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
<form name="queryInput"
|
||||
class="fill inline-form"
|
||||
ng-submit="filterResults()">
|
||||
ng-submit="filterResults()"
|
||||
role="form">
|
||||
|
||||
<div class="typeahead" kbn-typeahead="dashboard">
|
||||
<div class="input-group"
|
||||
|
@ -12,13 +13,14 @@
|
|||
|
||||
<input type="text"
|
||||
placeholder="Filter..."
|
||||
aria-label="Filter input"
|
||||
class="form-control"
|
||||
ng-model="state.query"
|
||||
input-focus
|
||||
kbn-typeahead-input
|
||||
validate-query>
|
||||
<button type="submit" class="btn btn-default" ng-disabled="queryInput.$invalid">
|
||||
<span class="fa fa-search"></span>
|
||||
<button type="submit" class="btn btn-default" ng-disabled="queryInput.$invalid" aria-label="Filter dashboards">
|
||||
<span aria-hidden="true" class="fa fa-search"></span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
@ -27,21 +29,45 @@
|
|||
|
||||
</form>
|
||||
|
||||
<div class="button-group">
|
||||
<div class="button-group" role="toolbar">
|
||||
<kbn-tooltip text="New Dashboard" placement="bottom" append-to-body="1">
|
||||
<button ng-click="newDashboard()"><i class="fa fa-file-new-o"></i></button>
|
||||
<button ng-click="newDashboard()" aria-label="New Dashboard"><i aria-hidden="true" class="fa fa-file-new-o"></i></button>
|
||||
</kbn-tooltip>
|
||||
<kbn-tooltip text="Save Dashboard" placement="bottom" append-to-body="1">
|
||||
<button ng-click="configTemplate.toggle('save')"><i class="fa fa-save"></i></button>
|
||||
<button
|
||||
aria-label="Save Dashboard"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="{{ configTemplate.is('save') }}"
|
||||
ng-click="configTemplate.toggle('save');">
|
||||
<i aria-hidden="true" class="fa fa-save"></i>
|
||||
</button>
|
||||
</kbn-tooltip>
|
||||
<kbn-tooltip text="Load Saved Dashboard" placement="bottom" append-to-body="1">
|
||||
<button ng-click="configTemplate.toggle('load')"><i class="fa fa-folder-open-o"></i></button>
|
||||
<button
|
||||
aria-label="Load Saved Dashboard"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="{{ configTemplate.is('load') }}"
|
||||
ng-click="configTemplate.toggle('load');">
|
||||
<i aria-hidden="true" class="fa fa-folder-open-o"></i>
|
||||
</button>
|
||||
</kbn-tooltip>
|
||||
<kbn-tooltip text="Share" placement="bottom" append-to-body="1">
|
||||
<button ng-click="configTemplate.toggle('share')"><i class="fa fa-external-link"></i></button>
|
||||
<button
|
||||
aria-label="Share Dashboard"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="{{ configTemplate.is('share') }}"
|
||||
ng-click="configTemplate.toggle('share');">
|
||||
<i aria-hidden="true" class="fa fa-external-link"></i>
|
||||
</button>
|
||||
</kbn-tooltip>
|
||||
<kbn-tooltip text="Add Visualization" placement="bottom" append-to-body="1">
|
||||
<button ng-click="configTemplate.toggle('pickVis')"><i class="fa fa-plus-circle"></i></button>
|
||||
<button
|
||||
aria-label="Add Visualization"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="{{ configTemplate.is('pickVis') }}"
|
||||
ng-click="configTemplate.toggle('pickVis');">
|
||||
<i aria-hidden="true" class="fa fa-plus-circle"></i>
|
||||
</button>
|
||||
</kbn-tooltip>
|
||||
</div>
|
||||
</navbar>
|
||||
|
@ -52,7 +78,7 @@
|
|||
|
||||
<div ng-show="!state.panels.length" class="text-center start-screen">
|
||||
<h2>Ready to get started?</h2>
|
||||
<p>Click the <a class="btn btn-xs navbtn-inverse" ng-click="configTemplate.open('pickVis')"><i class="fa fa-plus-circle"></i></a> button in the menu bar above to add a visualization to the dashboard. <br/>If you haven't setup a visualization yet visit the <a href="#/visualize">"Visualize"</a> tab to create your first visualization.</p>
|
||||
<p>Click the <a class="btn btn-xs navbtn-inverse" ng-click="configTemplate.open('pickVis'); toggleAddVisualization = !toggleAddVisualization" aria-label="Add visualization"><i aria-hidden="true" class="fa fa-plus-circle"></i></a> button in the menu bar above to add a visualization to the dashboard. <br/>If you haven't setup a visualization yet visit the <a href="#/visualize" title="Visualize">"Visualize"</a> tab to create your first visualization.</p>
|
||||
</div>
|
||||
|
||||
<dashboard-grid></dashboard-grid>
|
||||
|
|
|
@ -3,7 +3,6 @@ define(function (require) {
|
|||
var $ = require('jquery');
|
||||
var angular = require('angular');
|
||||
var ConfigTemplate = require('utils/config_template');
|
||||
var onlyDisabled = require('components/filter_bar/lib/onlyDisabled');
|
||||
|
||||
require('directives/config');
|
||||
require('components/courier/courier');
|
||||
|
@ -51,6 +50,8 @@ define(function (require) {
|
|||
app.directive('dashboardApp', function (Notifier, courier, AppState, timefilter, kbnUrl) {
|
||||
return {
|
||||
controller: function ($scope, $route, $routeParams, $location, configFile, Private) {
|
||||
var filterBarWatchFilters = Private(require('components/filter_bar/lib/watchFilters'));
|
||||
|
||||
var notify = new Notifier({
|
||||
location: 'Dashboard'
|
||||
});
|
||||
|
@ -113,13 +114,12 @@ define(function (require) {
|
|||
}
|
||||
}
|
||||
|
||||
$scope.$watch('state.filters', function (newFilters, oldFilters) {
|
||||
if (onlyDisabled(newFilters, oldFilters)) {
|
||||
$state.save();
|
||||
return;
|
||||
}
|
||||
$scope.filterResults();
|
||||
});
|
||||
filterBarWatchFilters($scope)
|
||||
.on('update', function () {
|
||||
updateQueryOnRootSource();
|
||||
$state.save();
|
||||
})
|
||||
.on('fetch', $scope.refresh);
|
||||
|
||||
$scope.newDashboard = function () {
|
||||
kbnUrl.change('/dashboard', {});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<div ng-switch on="mode" ng-init="mode = 'visualization'" class="dashboard-panel-picker">
|
||||
<ul class="nav nav-tabs">
|
||||
<li ng-class="{active: mode == 'visualization'}"><a ng-click="mode='visualization'">Visualizations</a></li>
|
||||
<li ng-class="{active: mode == 'search'}"><a ng-click="mode='search'">Searches</a></li>
|
||||
<li ng-class="{active: mode == 'visualization'}"><a ng-click="mode='visualization'" title="Visualizations">Visualizations</a></li>
|
||||
<li ng-class="{active: mode == 'search'}"><a ng-click="mode='search'" title="Searches">Searches</a></li>
|
||||
</ul>
|
||||
|
||||
<li class="list-group-item" ng-switch-when="visualization">
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<form ng-submit="opts.save()">
|
||||
<form ng-submit="opts.save()" role="form">
|
||||
<div class="form-group">
|
||||
<label for="exampleInputEmail1">Save As</label>
|
||||
<input type="text" ng-model="opts.dashboard.title" class="form-control" placeholder="Dashboard title" input-focus="select">
|
||||
<label for="dashboardTitle">Save As</label>
|
||||
<input id="dashboardTitle" type="text" ng-model="opts.dashboard.title" class="form-control" placeholder="Dashboard title" input-focus="select">
|
||||
</div>
|
||||
<button type="submit" ng-disabled="!opts.dashboard.title" class="btn btn-primary">Save</button>
|
||||
</form>
|
||||
<button type="submit" ng-disabled="!opts.dashboard.title" class="btn btn-primary" aria-label="Save dashboard">Save</button>
|
||||
</form>
|
||||
|
|
|
@ -2,7 +2,6 @@ define(function (require) {
|
|||
var $ = require('jquery');
|
||||
var app = require('modules').get('apps/discover');
|
||||
var html = require('text!plugins/discover/components/field_chooser/discover_field.html');
|
||||
var detailsHtml = require('text!plugins/discover/components/field_chooser/discover_field_details.html');
|
||||
var _ = require('lodash');
|
||||
|
||||
require('directives/css_truncate');
|
||||
|
@ -18,6 +17,8 @@ define(function (require) {
|
|||
var detailsElem;
|
||||
var detailScope = $scope.$new();
|
||||
|
||||
var detailsHtml = require('text!plugins/discover/components/field_chooser/lib/detail_views/string.html');
|
||||
|
||||
var init = function () {
|
||||
if ($scope.field.details) {
|
||||
$scope.toggleDetails($scope.field, true);
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
</div>
|
||||
<div ng-show="showIndexPatternSelection">
|
||||
<ul class="list-unstyled sidebar-item index-pattern-selection">
|
||||
<li css-truncate class="sidebar-item-title" ng-repeat="id in indexPatternList" ng-show="indexPattern.id != id" ng-click="setIndexPattern(id)">{{id}}</li>
|
||||
<li css-truncate class="sidebar-item-title" ng-repeat="id in indexPatternList | orderBy" ng-show="indexPattern.id != id" ng-click="setIndexPattern(id)">{{id}}</li>
|
||||
</ul>
|
||||
<div ng-click="showIndexPatternSelection = !showIndexPatternSelection" class="discover-field-details-close">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
|
@ -34,19 +34,23 @@
|
|||
<i
|
||||
ng-class="{ 'fa-chevron-right': !showFields, 'fa-chevron-down': showFields }"
|
||||
ng-click="showFields = !showFields"
|
||||
aria-hidden="true"
|
||||
class="fa visible-xs visible-sm pull-right field-collapse-toggle" ></i>
|
||||
<button
|
||||
ng-class="{ 'btn-default': !filter.active, 'btn-success': filter.active, 'hidden-xs': !showFields, 'hidden-sm': !showFields }"
|
||||
class="btn btn-xs btn-default pull-right discover-field-filter-toggle"
|
||||
ng-click="showFilter = !showFilter">
|
||||
<i class="fa fa-gear"></i>
|
||||
ng-click="showFilter = !showFilter"
|
||||
aria-label="Field Settings"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="{{showFilter}}">
|
||||
<i aria-hidden="true" class="fa fa-gear"></i>
|
||||
</button>
|
||||
</h5>
|
||||
</div>
|
||||
|
||||
<div class="sidebar-item" ng-show="showFilter">
|
||||
<div ng-click="showFilter = !showFilter" class="discover-field-details-close">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
<i aria-hidden="true" class="fa fa-chevron-up"></i>
|
||||
</div>
|
||||
<form role="form" class="discover-field-details">
|
||||
<div class="form-group">
|
||||
|
|
|
@ -124,10 +124,11 @@ define(function (require) {
|
|||
|
||||
$scope.runAgg = function (field) {
|
||||
var agg = {};
|
||||
var type = 'histogram';
|
||||
var isGeoPoint = field.type === 'geo_point';
|
||||
var type = isGeoPoint ? 'tile_map' : 'histogram';
|
||||
// If we're visualizing a date field, and our index is time based (and thus has a time filter),
|
||||
// then run a date histogram
|
||||
if (field.type === 'date' && $scope.indexPattern.timeFieldName) {
|
||||
if (field.type === 'date' && $scope.indexPattern.timeFieldName === field.name) {
|
||||
agg = {
|
||||
type: 'date_histogram',
|
||||
schema: 'segment',
|
||||
|
@ -137,8 +138,7 @@ define(function (require) {
|
|||
}
|
||||
};
|
||||
|
||||
} else if (field.type === 'geo_point') {
|
||||
type = 'tile_map';
|
||||
} else if (isGeoPoint) {
|
||||
agg = {
|
||||
type: 'geohash_grid',
|
||||
schema: 'segment',
|
||||
|
@ -153,7 +153,8 @@ define(function (require) {
|
|||
schema: 'segment',
|
||||
params: {
|
||||
field: field.name,
|
||||
size: config.get('discover:aggs:terms:size', 20)
|
||||
size: config.get('discover:aggs:terms:size', 20),
|
||||
orderBy: '2'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -165,17 +166,12 @@ define(function (require) {
|
|||
filters: $scope.state.filters || [],
|
||||
query: $scope.state.query || undefined,
|
||||
vis: {
|
||||
type: type,
|
||||
aggs: [
|
||||
agg,
|
||||
{schema: 'metric', type: 'count'}
|
||||
{schema: 'metric', type: 'count', 'id': '2'}
|
||||
]
|
||||
},
|
||||
metric: [{
|
||||
agg: 'count',
|
||||
}],
|
||||
segment: [agg],
|
||||
group: [],
|
||||
split: [],
|
||||
}
|
||||
})
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div bindonce>
|
||||
<div class="discover-field-details">
|
||||
<h5 ng-show="!field.details.error">Quick Count
|
||||
<h5 ng-show="!field.details.error">Quick Count <kbn-info info="Based on documents in the table" placement="right"></kbn-info>
|
||||
<span ng-if="!field.details.error" class="small discover-field-details-count">
|
||||
(
|
||||
<a ng-show="field.indexed" ng-click="updateFilterInQuery('_exists_', field.name, '+')">{{field.details.exists}}</a>
|
||||
|
@ -18,13 +18,13 @@
|
|||
<div ng-repeat="bucket in field.details.buckets" class="discover-field-details-item">
|
||||
<div>
|
||||
<span ng-show="field.filterable" class="pull-right">
|
||||
<i class="fa fa-search-minus pull-right discover-field-details-filter"
|
||||
<i aria-hidden="true" class="fa fa-search-minus pull-right discover-field-details-filter"
|
||||
ng-click="updateFilterInQuery(field, bucket.value, '-')"></i>
|
||||
<i class="fa fa-search-plus pull-right discover-field-details-filter"
|
||||
<i aria-hidden="true" class="fa fa-search-plus pull-right discover-field-details-filter"
|
||||
ng-click="updateFilterInQuery(field, bucket.value, '+')"></i>
|
||||
</span>
|
||||
<div css-truncate css-truncate-expandable="true" class="discover-field-details-value">
|
||||
{{bucket.display}}
|
||||
{{bucket.display}} <i ng-show="bucket.display === ''">Empty string</i>
|
||||
</div>
|
||||
</div>
|
||||
<progressbar value="bucket.percent" max="100" animate="false"><span>{{bucket.percent}}%</span></progressbar>
|
||||
|
@ -38,7 +38,7 @@
|
|||
class="sidebar-item-button primary">
|
||||
Visualize
|
||||
<span class="discover-field-vis-warning" ng-show="warnings.length" tooltip="{{warnings.join(' ')}}">
|
||||
( {{warnings.length}} <ng-pluralize count="warnings.length" when="{'1':'warning', 'other':'warnings'}"></ng-pluralize> <i class="fa fa-warning"></i> )
|
||||
( {{warnings.length}} <ng-pluralize count="warnings.length" when="{'1':'warning', 'other':'warnings'}"></ng-pluralize> <i aria-hidden="true" class="fa fa-warning"></i> )
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -3,7 +3,6 @@ define(function (require) {
|
|||
var angular = require('angular');
|
||||
var moment = require('moment');
|
||||
var ConfigTemplate = require('utils/config_template');
|
||||
var onlyDisabled = require('components/filter_bar/lib/onlyDisabled');
|
||||
var filterManager = require('components/filter_manager/filter_manager');
|
||||
var getSort = require('components/doc_table/lib/get_sort');
|
||||
var rison = require('utils/rison');
|
||||
|
@ -70,6 +69,7 @@ define(function (require) {
|
|||
var docTitle = Private(require('components/doc_title/doc_title'));
|
||||
var brushEvent = Private(require('utils/brush_event'));
|
||||
var HitSortFn = Private(require('plugins/discover/_hit_sort_fn'));
|
||||
var filterBarWatchFilters = Private(require('components/filter_bar/lib/watchFilters'));
|
||||
|
||||
var notify = new Notifier({
|
||||
location: 'Discover'
|
||||
|
@ -188,16 +188,13 @@ define(function (require) {
|
|||
if (!angular.equals(sort, currentSort)) $scope.fetch();
|
||||
});
|
||||
|
||||
$scope.$watch('state.filters', function (newFilters, oldFilters) {
|
||||
if (newFilters === oldFilters) return;
|
||||
|
||||
if (onlyDisabled(newFilters, oldFilters)) {
|
||||
filterBarWatchFilters($scope)
|
||||
.on('update', function () {
|
||||
return $scope.updateDataSource().then(function () {
|
||||
$state.save();
|
||||
return;
|
||||
}
|
||||
|
||||
$scope.fetch();
|
||||
});
|
||||
});
|
||||
})
|
||||
.on('fetch', $scope.fetch);
|
||||
|
||||
$scope.$watch('opts.timefield', function (timefield) {
|
||||
timefilter.enabled = !!timefield;
|
||||
|
@ -243,7 +240,7 @@ define(function (require) {
|
|||
|
||||
$scope.searchSource.onError(function (err) {
|
||||
console.log(err);
|
||||
notify.error('An error occured with your request. Reset your inputs and try again.');
|
||||
notify.error('An error occurred with your request. Reset your inputs and try again.');
|
||||
}).catch(notify.fatal);
|
||||
|
||||
function initForTime() {
|
||||
|
@ -360,7 +357,6 @@ define(function (require) {
|
|||
});
|
||||
}
|
||||
|
||||
$scope.hits += resp.hits.total;
|
||||
var rows = $scope.rows;
|
||||
var counts = rows.fieldCounts;
|
||||
|
||||
|
@ -407,6 +403,8 @@ define(function (require) {
|
|||
|
||||
segmented.on('mergedSegment', function (merged) {
|
||||
$scope.mergedEsResp = merged;
|
||||
$scope.hits = merged.hits.total;
|
||||
|
||||
});
|
||||
|
||||
segmented.on('complete', function () {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div ng-controller="discover" class="app-container">
|
||||
<navbar>
|
||||
<form class="fill inline-form" ng-submit="fetch()" name="discoverSearch">
|
||||
<form role="form" class="fill inline-form" ng-submit="fetch()" name="discoverSearch">
|
||||
<div class="typeahead" kbn-typeahead="discover">
|
||||
<div class="input-group"
|
||||
ng-class="discoverSearch.$invalid ? 'has-error' : ''">
|
||||
|
@ -9,38 +9,56 @@
|
|||
kbn-typeahead-input
|
||||
ng-model="state.query"
|
||||
placeholder="Search..."
|
||||
aria-label="Search input"
|
||||
type="text"
|
||||
class="form-control">
|
||||
<button type="submit"
|
||||
ng-disabled="discoverSearch.$invalid">
|
||||
<span class="fa fa-search"></span></button>
|
||||
<!--<button type="button" ng-click="resetQuery()"><span class="fa fa-ban"></span></button>-->
|
||||
ng-disabled="discoverSearch.$invalid"
|
||||
aria-label="Search">
|
||||
<span aria-hidden="true" class="fa fa-search"></span></button>
|
||||
<!--<button type="button" ng-click="resetQuery()" aria-label="Reset query"><span aria-hidden="true" class="fa fa-ban"></span></button>-->
|
||||
</div>
|
||||
<kbn-typeahead-items></kbn-typeahead-items>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="button-group">
|
||||
<div class="button-group" role="toolbar">
|
||||
<kbn-tooltip text="New Search" placement="bottom" append-to-body="1">
|
||||
<button ng-click="newQuery()"><i class="fa fa-file-new-o"></i></button>
|
||||
<button
|
||||
ng-click="newQuery()"
|
||||
aria-label="New Search">
|
||||
<i aria-hidden="true" class="fa fa-file-new-o"></i>
|
||||
</button>
|
||||
</kbn-tooltip>
|
||||
<kbn-tooltip text="Save Search" placement="bottom" append-to-body="1">
|
||||
<button ng-click="configTemplate.toggle('save')"><i class="fa fa-save"></i></button>
|
||||
<button
|
||||
aria-haspopup="true"
|
||||
aria-expanded="{{ configTemplate.is('save') }}"
|
||||
ng-click="configTemplate.toggle('save');"
|
||||
aria-label="Save Search">
|
||||
<i aria-hidden="true" class="fa fa-save"></i>
|
||||
</button>
|
||||
</kbn-tooltip>
|
||||
<kbn-tooltip text="Load Saved Search" placement="bottom" append-to-body="1">
|
||||
<button ng-click="configTemplate.toggle('load')"><i class="fa fa-folder-open-o"></i></button>
|
||||
<button
|
||||
aria-haspopup="true"
|
||||
aria-expanded="{{ configTemplate.is('load') }}"
|
||||
ng-click="configTemplate.toggle('load');"
|
||||
aria-label="Load Saved Search">
|
||||
<i aria-hidden="true" class="fa fa-folder-open-o"></i>
|
||||
</button>
|
||||
</kbn-tooltip>
|
||||
</div>
|
||||
</navbar>
|
||||
|
||||
<config config-template="configTemplate" config-object="opts" config-close="configClose" config-submit="fetch"></config>
|
||||
<config config-template="configTemplate" config-object="opts" config-close="configClose"></config>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="container-fluid" role="main">
|
||||
<div class="row">
|
||||
<filter-bar state="state"></filter-bar>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-2 sidebar-container">
|
||||
<div class="col-md-2 sidebar-container collapsible-sidebar">
|
||||
<disc-field-chooser
|
||||
fields="fields"
|
||||
toggle="toggleField"
|
||||
|
@ -58,9 +76,9 @@
|
|||
<div class="discover-info">
|
||||
<span ng-show="opts.savedSearch.id" class="discover-info-title">
|
||||
<span bindonce bo-bind="opts.savedSearch.title"></span>
|
||||
<i tooltip="Reload saved query" ng-click="resetQuery();" class="fa fa-undo small"></i>
|
||||
<i aria-label="Reload saved query" tooltip="Reload saved query" ng-click="resetQuery();" class="fa fa-undo small"></i>
|
||||
</span>
|
||||
<strong class="discover-info-hits">{{(hits || 0) | number:0}}</strong>
|
||||
<strong class="discover-info-hits">{{(hits || 0) | number:0}}</strong>
|
||||
<ng-pluralize count="hits" when="{'1':'hit', 'other':'hits'}"></ng-pluralize>
|
||||
</div>
|
||||
|
||||
|
@ -69,7 +87,7 @@
|
|||
<div ng-show="resultState === 'none'">
|
||||
<div class="col-md-10 col-md-offset-1">
|
||||
|
||||
<h1>No results found <i class="fa fa-meh-o"></i></h1>
|
||||
<h1>No results found <i aria-hidden="true" class="fa fa-meh-o"></i></h1>
|
||||
|
||||
<p>
|
||||
Unfortunately I could not find any results matching your search. I tried really hard. I looked all over the place and frankly, I just couldn't find anything good. Help me, help you. Here's some ideas:
|
||||
|
@ -81,20 +99,20 @@
|
|||
<ul>
|
||||
<li ng-repeat="failure in failures | limitTo: failuresShown"><strong>Index:</strong> {{failure.index}} <strong>Shard:</strong> {{failure.shard}} <strong>Reason:</strong> {{failure.reason}} </li>
|
||||
</ul>
|
||||
<a ng-click="showAllFailures()" ng-if="failures.length > failuresShown">Show More</a>
|
||||
<a ng-click="showLessFailures()" ng-if="failures.length === failuresShown && failures.length > 5">Show Less</a>
|
||||
<a ng-click="showAllFailures()" ng-if="failures.length > failuresShown" title="Show More">Show More</a>
|
||||
<a ng-click="showLessFailures()" ng-if="failures.length === failuresShown && failures.length > 5" title="Show Less">Show Less</a>
|
||||
</div>
|
||||
|
||||
<div ng-show="opts.timefield">
|
||||
<p>
|
||||
<h3>Expand your time range</h3>
|
||||
<p>I see you are looking at an index with a date field. It is possible your query does not match anything in the current time range, or that there is not data at all in the currently selected time range. Click the button below to open the time picker. For future reference you can open the time picker by clicking the <a class="btn btn-xs navbtn" ng-click="toggleTimepicker()">time picker <i class="fa fa-clock-o"></i></a> in the top right corner of your screen.
|
||||
<p>I see you are looking at an index with a date field. It is possible your query does not match anything in the current time range, or that there is no data at all in the currently selected time range. Click the button below to open the time picker. For future reference you can open the time picker by clicking the <a class="btn btn-xs navbtn" ng-click="toggleTimepicker(); toggledTimepicker = !toggledTimepicker" aria-expanded="{{toggledTimepicker}}" aria-label="time picker">time picker <i aria-hidden="true" class="fa fa-clock-o"></i></a> in the top right corner of your screen.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h3>Refine your query</h3>
|
||||
<p>
|
||||
The search bar at the top allows Kibana uses Elasticsearch's support for Lucene Query String syntax. Let's say we're searching web server logs that have been parsed into a few fields.
|
||||
The search bar at the top uses Elasticsearch's support for Lucene Query String syntax. Let's say we're searching web server logs that have been parsed into a few fields.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
@ -165,7 +183,7 @@
|
|||
<div ng-if="rows.length == opts.sampleSize" class="discover-table-footer">
|
||||
<center>
|
||||
These are the first {{opts.sampleSize}} results matching your query,
|
||||
refine your search to see more. <a ng-click="toTop()">Back to top.</a>
|
||||
refine your search to see more. <a ng-click="toTop()" title="Back to top">Back to top.</a>
|
||||
</center>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
define(function (require, module, exports) {
|
||||
require('plugins/discover/saved_searches/saved_searches');
|
||||
require('plugins/discover/directives/timechart');
|
||||
require('components/collapsible_sidebar/collapsible_sidebar');
|
||||
require('plugins/discover/components/field_chooser/field_chooser');
|
||||
require('plugins/discover/controllers/discover');
|
||||
require('css!plugins/discover/styles/main.css');
|
||||
|
@ -13,4 +14,4 @@ define(function (require, module, exports) {
|
|||
order: 0
|
||||
};
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1 +1,3 @@
|
|||
<saved-object-finder type="searches"></saved-object-finder>
|
||||
<form role="form" class="container-fluid" ng-submit="fetch()">
|
||||
<saved-object-finder type="searches"></saved-object-finder>
|
||||
</form>
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="form-group">
|
||||
<label class="control-label">Save Search</label>
|
||||
<input ng-model="opts.savedSearch.title" input-focus="select" class="form-control" placeholder="Name this search...">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button ng-click="opts.saveDataSource()" ng-disabled="!opts.savedSearch.title" type="submit" class="btn btn-primary">
|
||||
Save
|
||||
</button>
|
||||
<form role="form" class="container-fluid" ng-submit="opts.saveDataSource()">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="form-group">
|
||||
<label for="SaveSearch" class="control-label">Save Search</label>
|
||||
<input id="SaveSearch" ng-model="opts.savedSearch.title" input-focus="select" class="form-control" placeholder="Name this search...">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button ng-disabled="!opts.savedSearch.title" type="submit" class="btn btn-primary">
|
||||
Save
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<!-- no results -->
|
||||
<div class="col-md-12" ng-if="status === 'notFound'">
|
||||
<div class="col-md-12">
|
||||
<h1>Failed to locate document. <i class="fa fa-meh-o"></i></h1>
|
||||
<h1>Failed to locate document. <i aria-hidden="true" class="fa fa-meh-o"></i></h1>
|
||||
|
||||
<p>
|
||||
Unfortunately I could not find any documents matching that id, of that type, in that index. I tried really hard. I wanted it to be there. Sometimes I swear documents grow legs and just walk out of the index. Sneaky. I wish I could offer some advice here, something to make you feel better
|
||||
|
@ -18,7 +18,7 @@
|
|||
<!-- no results -->
|
||||
<div class="col-md-12" ng-if="status === 'error'">
|
||||
<div class="col-md-12">
|
||||
<h1>This is bad. <i class="fa fa-meh-o"></i></h1>
|
||||
<h1>This is bad. <i aria-hidden="true" class="fa fa-meh-o"></i></h1>
|
||||
|
||||
<p>
|
||||
Oh no. Something went very wrong. Its not just that I couldn't find your document, I couldn't even try. The index was missing, or the type. Go check out Elasticsearch, something isn't quite right here.
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue