Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Region map visualization #10937

Merged
merged 57 commits into from
May 31, 2017
Merged

Conversation

thomasneirynck
Copy link
Contributor

@thomasneirynck thomasneirynck commented Mar 29, 2017

Summary: Kibana now has the Region Map Visualization. These are thematic maps in which boundary vector shapes are colored using a gradient, with higher intensity colors indicating larger values and lower intensity colors indicating smaller values. These are also known as choropleth maps. In order to color these layers, users specify a terms aggregation that matches a field in the vector layer. Kibana offers two vector layers by default; one for countries of the world and one for US Shapes. Users can also bring in their own vector layers by configuring the Kibana-configuration file to point to any GeoJson file that is hosted on a CORS-enabled server.

image


[EDIT]: see last comment for update wrt. data loading: #10937 (comment)

Feedback (round 2):

  • docs
  • play button shouldn't be enabled when configuration isn't valid
  • tests
  • get new icon (no longer use font-awesome)
  • make error messages consistent with Coordinate Map
  • desaturatization seems to be broken in coordinate map
  • manifest loading tests are broken due to refactor
  • ensure data isn't loaded twice

Feedback:

  • show warning when not all data can be joined to vector map
  • improve color ranges (whites are too faint)
  • tooltip disappears when changing vector maps
  • default zoom level (0) shows world 5 times .... 2 seems more appropriate
  • metrics have no title, looks a bit empty
  • only one metric is possible, it should be expanded agreed to do this in separate PR since same issue occurs in other viz as well
  • shape field + aggregation type (term) should be pre selected as its the only possibility see above
  • parent pipeline aggregations should be excluded from the metric agg list
  • does geocentroid metric make sense ? no, since we are not querying for geo-fields in ES
  • custom labels are broken
  • add labeling on map (decided to skip this until long term outlook of map-component is worked out).
  • trim default files for speedier loading
  • add alpha3 and numeric iso country codes
  • 2 letter country code instead of 2 letter abbreviation

Todos:

  • add tests

@thomasneirynck thomasneirynck changed the title add vector map Vector Map Mar 29, 2017
@tbragin tbragin added the Feature:Visualizations Generic visualization features (in case no more specific feature label is available) label Apr 4, 2017
@thomasneirynck thomasneirynck force-pushed the vector_map branch 2 times, most recently from f60d556 to f597c30 Compare April 10, 2017 04:55
'visualization:vectormap:showWarnings': {
value: true,
description: 'Should the vector map show a warning when terms cannot be joined to a shape on the map.'
},
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not 100% sure of this.

Since we're mashing up 2 datasets, the join might not succeed (partially or completely). The odds of having one or more results not being present on the map can be high, especially when the data is not very clean. That's why I introduced an advanced setting to turn these warnings on/off.

import _ from 'lodash';
import AggConfigResult from 'ui/vis/agg_config_result';
import KibanaMap from 'ui/vis_maps/kibana_map';
import FilterBarFilterBarClickHandlerProvider from 'ui/filter_bar/filter_bar_click_handler';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think you might not actually need to import this, it should be available on vis.listeners.click




function getValue(metricsAgg, bucket) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move on top ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved it up

});

this._loaded = false;
$.ajax({//todo: replace with es6 fetch
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup :)

@ppisljar
Copy link
Member

this looks great! some small comments below:

  • default zoom level (0) shows world 5 times .... 2 seems more appropriate
  • metrics have no title, looks a bit empty
  • only one metric is possible, it should be expanded
  • add alpha3 and numeric iso country codes ?
  • documentation on how to add my custom vector data ?
  • shape field + aggregation type (term) should be pre selected as its the only possibility
  • 2 letter country code instead of 2 letter abbreviation ?
  • parent pipeline aggregations should be excluded from the metric agg list
  • does geocentroid metric make sense ?

@thomasneirynck
Copy link
Contributor Author

thanks @ppisljar , I'll get started on your feedback..

@alexfrancoeur
Copy link

alexfrancoeur commented Apr 11, 2017

@thomasneirynck finally had some time this morning to play around with vector map. Please see my comments below. I believe I mentioned some of these in the previous PR so they might already be on your radar.
Edit: I also now realize that I provided some duplicate feedback that Peter had. Sorry!

  • Map is still zoomed out when creating a vector map

screen shot 2017-04-11 at 9 32 41 am

  • When switching between state and country abbreviations, I lose tooltips until I refresh.
    apr-11-2017 10-20-58

  • Is geo centroid meant to be an aggregation available for a vector map? And for that matter, all visualizations? I see it everywhere but tilemap at the moment.

screen shot 2017-04-11 at 9 34 25 am

  • Somewhat related, there are pipeline aggregations that need a histogram or date histogram in order to work. Can we remove these from vector map configurations if they cannot be used?

screen shot 2017-04-11 at 9 41 17 am

  • Also if you change the aggregation, the error does not go away.

screen shot 2017-04-11 at 9 51 27 am

  • I believe you already have this as a task but the custom labels are not working at the moment.

screen shot 2017-04-11 at 9 39 25 am

Having some issues generating reports locally but will try vector maps there as well.

Copy link
Contributor

@kobelb kobelb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice job! Just a few comments, and one thing that can hopefully be removed.

I'm also unsure how I feel about calling it "choropleth" in code, but "vector map" to the end-user. I could see someone new to the project struggling to find the relevant code because of the mis-match in naming.

require('./_heatmap_chart');
require('./_point_series_options');
require('./_shared_item');
// require('./_chart_types');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll want to revert this before committing.

'intern/dojo/node!./apps/xpack',
'intern/dojo/node!./apps/discover',
'intern/dojo/node!./apps/management',
// 'intern/dojo/node!./apps/xpack',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, we don't want to commit this to master

@@ -25,6 +25,7 @@ bdd.describe('visualize app', function describeIndexTests() {
'Data Table',
'Metric',
'Tile Map',
'Vector Map',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are quite a few merge conflicts for the tests because of #10910

function getValue(metricsAgg, bucket) {
let size = metricsAgg.getValue(bucket);
if (typeof size !== 'number' || isNaN(size)) {
try {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been unable to find this code-path being hit, or other visualizations (besides tagcloud) doing something similar.

@thomasneirynck
Copy link
Contributor Author

rebasing against master, incorporating test-suite changes

@thomasneirynck
Copy link
Contributor Author

After more discussion, we want to change how we load the example json files. Instead of using Kibana to serve those, we should host them from a central repo. Apart from that change, users will continue to be able to bring in custom data layers with the same mechanism we have now.

@thomasneirynck
Copy link
Contributor Author

removing default data config.

all custom data should now be configured in the .yml.

e.g.

vectormap:
  layers:
     - name: "World Countries"
       url: "../plugins/choropleth/data/world_countries.json"
       fields:
          - name: "name"
            description: "Country name"
          - name: "iso2"
            description: "Two letter abbreviation"
          - name: "iso2"
            description: "Three letter abbreviation"
     - name: "US States"
       url: "../plugins/choropleth/data/us_states.json"
       fields:
          - name: "postal"
            description: "Two letter abbreviation"
          - name: "name"
            description: "State name"

Default layers will now be loaded from remote catalogue service (forthcoming)

@thomasneirynck
Copy link
Contributor Author

with 6b41e66, we're testing against a new metadata-service. This is just a POC now, the structure of these documents, and the endpoints are not final yet.

@thomasneirynck
Copy link
Contributor Author

@ppisljar @kobelb fyi, I've refactored this to use a new file-server infra has setup (POC just now). These changes make all the unit tests fail, but do take an initial look already if you can. I'll work on tests once we've settled with infra on the final version of the new manifest schemas.

Copy link
Contributor

@kobelb kobelb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functionally, this seems to work perfectly! Just a few comments.

Also, the optimize/.empty file looks like it was somehow deleted with this PR.

q Outdated
@@ -0,0 +1,94 @@
diff --git a/src/core_plugins/region_map/public/region_map_controller.js b/src/core_plugins/region_map/public/region_map_controller.js
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty sure this file was accidentally checked in.

@@ -6,13 +8,20 @@ export function injectVars(server) {
//keeping this logic for backward compatibilty.
const configuredUrl = server.config().get('tilemap.url');
const isOverridden = typeof configuredUrl === 'string' && configuredUrl !== '';
const tilemapConfig = serverConfig.get('tilemap');
const tilemapConfig = _.cloneDeep(serverConfig.get('tilemap'));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's your reasoning for cloning these settings? It's my understanding that these injected_vars are serialized into an HTMLElement in the initial response and then deserialized client-side, so it seems that this might be unnecessary.

@@ -6,13 +8,20 @@ export function injectVars(server) {
//keeping this logic for backward compatibilty.
const configuredUrl = server.config().get('tilemap.url');
const isOverridden = typeof configuredUrl === 'string' && configuredUrl !== '';
const tilemapConfig = serverConfig.get('tilemap');
const tilemapConfig = _.cloneDeep(serverConfig.get('tilemap'));
const vectormapsConfig = _.cloneDeep(serverConfig.get('regionmap'));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A remnant of the vectormaps naming, should be regionmapsConfig.

const mapConfig = _.cloneDeep(serverConfig.get('map'));


vectormapsConfig.layers = (vectormapsConfig.layers) ? vectormapsConfig.layers : [];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally, I've seen us using the .default() method of Joi to set defaults for the config schema, so we could do something like the following in the 'src/server/config/schema.js' to do the equivalent:

regionmap: Joi.object({
    layers: Joi.array().items(Joi.object({
      url: Joi.string(),
      type: Joi.string(),
      name: Joi.string(),
      fields: Joi.array().items(Joi.object({
        name: Joi.string(),
        description: Joi.string()
      }))
    })).default([])
  }).default()

The .default([]) portion of above should always default the layers to an empty array if they aren't specified.

}

const { min, max } = getMinMax(data);
data = data.slice();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doing data.slice() here and then doing data.splice(lastIndex, 1) below inside of the getLeafletStyleFunction is rather confusing. We're using getLeafletStyleFunction to mutate data that is also used by getMismatches, so the order that these functions are called becomes significant. Was this intentional?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, that order is significant. the getMisMatches is just for the client to be able to read out the errors of the inner-join (ie. the style function).

const TemplateVisType = Private(TemplateVisTypeProvider);
const Schemas = Private(VisSchemasProvider);

const vectorLayers = vectormapsConfig.layers.slice();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should only be being called once for the "client-side app" when it's registering all the visualization types, what are we trying to prevent with the slice()? I know before that we were having layers duplicated when creating multiple maps in a row, was this meant to address this?

link: function ($scope) {


console.log('calling the linker function...');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

console.log should be removed before merging.

@@ -161,6 +161,13 @@ module.exports = () => Joi.object({
status: Joi.object({
allowAnonymous: Joi.boolean().default(false)
}).default(),
map: Joi.object({
manifestServiceUrl: Joi.when('$dev', {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the new map.manifesetServiceUrl is used for both the tiles and the geo layers, does that mean we should be deprecating the tilemap config section?

map: Joi.object({
manifestServiceUrl: Joi.when('$dev', {
is: true,
then: Joi.string().default('https://geo.elastic.co/v1/manifest'),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dev and Non-Dev appear to be the same, was this intentional?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, for now this needs to be the same. Infra has only setup a single production server. this will likely change in the weeks to come.

@@ -0,0 +1,835 @@

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file's been moved, I think you should just be able to delete it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rebase snafu, thanks.

@ppisljar
Copy link
Member

ppisljar commented May 31, 2017

sibling pipeline aggs should be allowed (no reason why they should be disabled i think)

sample use case:
i want to show usage of windows operating system around the world

  • for the shape field i select term aggregation on geo.src (to get countries)
  • for metric i would choose sum bucket aggregation where for bucket i would choose filter aggregation with filter like machine.os.raw: win* and for metric i would choose unique count on clientIp

i would get representation of windows usage around the world.

@thomasneirynck
Copy link
Contributor Author

@ppisljar thanks, I added them.

Copy link
Member

@ppisljar ppisljar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@thomasneirynck
Copy link
Contributor Author

wrt. tilemap-config. still required, since people can override the url still to plug in a custom url. perhaps we can deprecate this configuration in 6.0, but keeping it for now.

then: Joi.string().default('https://geo.elastic.co/v1/manifest'),
otherwise: Joi.string().default('https://geo.elastic.co/v1/manifest')
})
}).default(),
tilemap: Joi.object({
manifestServiceUrl: Joi.when('$dev', {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to go.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, sorry, mistake on my part. gone!

Copy link
Contributor

@kobelb kobelb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@thomasneirynck thomasneirynck merged commit 2270a6c into elastic:master May 31, 2017
@epixa epixa changed the title Vector Map Region Map Jun 2, 2017
@epixa epixa changed the title Region Map Region Map visualization Jun 2, 2017
@epixa epixa changed the title Region Map visualization Region map visualization Jun 2, 2017
w33ble added a commit to w33ble/kibana that referenced this pull request Jun 6, 2017
elastic#10937 seems to have brought this file back, likely as part of a bad merge resolution
@w33ble w33ble mentioned this pull request Jun 6, 2017
w33ble added a commit that referenced this pull request Jun 6, 2017
#10937 seems to have brought this file back, likely as part of a bad merge resolution
w33ble added a commit that referenced this pull request Jun 6, 2017
#10937 seems to have brought this file back, likely as part of a bad merge resolution
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature:Visualizations Generic visualization features (in case no more specific feature label is available) review v5.5.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants