mirror of
https://github.com/elastic/kibana.git
synced 2025-04-25 02:09:32 -04:00
[Maps] Track geo_shape agg usage (#71759)
Tracks how many users are using geo_shape aggs.
This commit is contained in:
parent
b75bf5f585
commit
8a21d11f08
3 changed files with 175 additions and 30 deletions
|
@ -22,6 +22,7 @@ describe('buildMapsTelemetry', () => {
|
||||||
indexPatternsWithGeoFieldCount: 0,
|
indexPatternsWithGeoFieldCount: 0,
|
||||||
indexPatternsWithGeoPointFieldCount: 0,
|
indexPatternsWithGeoPointFieldCount: 0,
|
||||||
indexPatternsWithGeoShapeFieldCount: 0,
|
indexPatternsWithGeoShapeFieldCount: 0,
|
||||||
|
geoShapeAggLayersCount: 0,
|
||||||
attributesPerMap: {
|
attributesPerMap: {
|
||||||
dataSourcesCount: {
|
dataSourcesCount: {
|
||||||
avg: 0,
|
avg: 0,
|
||||||
|
@ -50,48 +51,49 @@ describe('buildMapsTelemetry', () => {
|
||||||
indexPatternsWithGeoFieldCount: 3,
|
indexPatternsWithGeoFieldCount: 3,
|
||||||
indexPatternsWithGeoPointFieldCount: 2,
|
indexPatternsWithGeoPointFieldCount: 2,
|
||||||
indexPatternsWithGeoShapeFieldCount: 1,
|
indexPatternsWithGeoShapeFieldCount: 1,
|
||||||
|
geoShapeAggLayersCount: 2,
|
||||||
attributesPerMap: {
|
attributesPerMap: {
|
||||||
dataSourcesCount: {
|
dataSourcesCount: {
|
||||||
avg: 2.6666666666666665,
|
avg: 2,
|
||||||
max: 3,
|
max: 3,
|
||||||
min: 2,
|
min: 1,
|
||||||
},
|
},
|
||||||
emsVectorLayersCount: {
|
emsVectorLayersCount: {
|
||||||
canada_provinces: {
|
canada_provinces: {
|
||||||
avg: 0.3333333333333333,
|
avg: 0.2,
|
||||||
max: 1,
|
max: 1,
|
||||||
min: 1,
|
min: 1,
|
||||||
},
|
},
|
||||||
france_departments: {
|
france_departments: {
|
||||||
avg: 0.3333333333333333,
|
avg: 0.2,
|
||||||
max: 1,
|
max: 1,
|
||||||
min: 1,
|
min: 1,
|
||||||
},
|
},
|
||||||
italy_provinces: {
|
italy_provinces: {
|
||||||
avg: 0.3333333333333333,
|
avg: 0.2,
|
||||||
max: 1,
|
max: 1,
|
||||||
min: 1,
|
min: 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
layerTypesCount: {
|
layerTypesCount: {
|
||||||
TILE: {
|
TILE: {
|
||||||
avg: 1,
|
avg: 0.6,
|
||||||
max: 1,
|
max: 1,
|
||||||
min: 1,
|
min: 1,
|
||||||
},
|
},
|
||||||
VECTOR: {
|
VECTOR: {
|
||||||
avg: 1.6666666666666667,
|
avg: 1.2,
|
||||||
max: 2,
|
max: 2,
|
||||||
min: 1,
|
min: 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
layersCount: {
|
layersCount: {
|
||||||
avg: 2.6666666666666665,
|
avg: 2,
|
||||||
max: 3,
|
max: 3,
|
||||||
min: 2,
|
min: 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mapsTotalCount: 3,
|
mapsTotalCount: 5,
|
||||||
settings: {
|
settings: {
|
||||||
showMapVisualizationTypes: false,
|
showMapVisualizationTypes: false,
|
||||||
},
|
},
|
||||||
|
|
|
@ -6,13 +6,25 @@
|
||||||
|
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import {
|
import {
|
||||||
SavedObjectsClientContract,
|
|
||||||
SavedObjectAttributes,
|
|
||||||
SavedObjectAttribute,
|
SavedObjectAttribute,
|
||||||
|
SavedObjectAttributes,
|
||||||
|
SavedObjectsClientContract,
|
||||||
} from 'kibana/server';
|
} from 'kibana/server';
|
||||||
import { IFieldType, IIndexPattern } from 'src/plugins/data/public';
|
import { IFieldType, IIndexPattern } from 'src/plugins/data/public';
|
||||||
import { SOURCE_TYPES, ES_GEO_FIELD_TYPE, MAP_SAVED_OBJECT_TYPE } from '../../common/constants';
|
import {
|
||||||
import { LayerDescriptor } from '../../common/descriptor_types';
|
ES_GEO_FIELD_TYPE,
|
||||||
|
LAYER_TYPE,
|
||||||
|
MAP_SAVED_OBJECT_TYPE,
|
||||||
|
SCALING_TYPES,
|
||||||
|
SOURCE_TYPES,
|
||||||
|
} from '../../common/constants';
|
||||||
|
import {
|
||||||
|
AbstractSourceDescriptor,
|
||||||
|
ESGeoGridSourceDescriptor,
|
||||||
|
ESSearchSourceDescriptor,
|
||||||
|
LayerDescriptor,
|
||||||
|
SourceDescriptor,
|
||||||
|
} from '../../common/descriptor_types';
|
||||||
import { MapSavedObject } from '../../common/map_saved_object_type';
|
import { MapSavedObject } from '../../common/map_saved_object_type';
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { getInternalRepository } from '../kibana_server_services';
|
import { getInternalRepository } from '../kibana_server_services';
|
||||||
|
@ -82,6 +94,111 @@ function getIndexPatternsWithGeoFieldCount(indexPatterns: IIndexPattern[]) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getEMSLayerCount(layerLists: LayerDescriptor[][]): ILayerTypeCount[] {
|
||||||
|
return layerLists.map((layerList: LayerDescriptor[]) => {
|
||||||
|
const emsLayers = layerList.filter((layer: LayerDescriptor) => {
|
||||||
|
return (
|
||||||
|
layer.sourceDescriptor !== null &&
|
||||||
|
layer.sourceDescriptor.type === SOURCE_TYPES.EMS_FILE &&
|
||||||
|
(layer.sourceDescriptor as AbstractSourceDescriptor).id
|
||||||
|
);
|
||||||
|
});
|
||||||
|
const emsCountsById = _(emsLayers).countBy((layer: LayerDescriptor) => {
|
||||||
|
return (layer.sourceDescriptor as AbstractSourceDescriptor).id;
|
||||||
|
});
|
||||||
|
|
||||||
|
const layerTypeCount = emsCountsById.value();
|
||||||
|
return layerTypeCount as ILayerTypeCount;
|
||||||
|
}) as ILayerTypeCount[];
|
||||||
|
}
|
||||||
|
|
||||||
|
function isFieldGeoShape(
|
||||||
|
indexPatterns: IIndexPattern[],
|
||||||
|
indexPatternId: string,
|
||||||
|
geoField: string | undefined
|
||||||
|
): boolean {
|
||||||
|
if (!geoField) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const matchIndexPattern = indexPatterns.find((indexPattern: IIndexPattern) => {
|
||||||
|
return indexPattern.id === indexPatternId;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!matchIndexPattern) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fieldList: IFieldType[] =
|
||||||
|
matchIndexPattern.attributes && matchIndexPattern.attributes.fields
|
||||||
|
? JSON.parse(matchIndexPattern.attributes.fields)
|
||||||
|
: [];
|
||||||
|
|
||||||
|
const matchField = fieldList.find((field: IFieldType) => {
|
||||||
|
return field.name === geoField;
|
||||||
|
});
|
||||||
|
|
||||||
|
return !!matchField && matchField.type === ES_GEO_FIELD_TYPE.GEO_SHAPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isGeoShapeAggLayer(indexPatterns: IIndexPattern[], layer: LayerDescriptor): boolean {
|
||||||
|
if (layer.sourceDescriptor === null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
layer.type !== LAYER_TYPE.VECTOR &&
|
||||||
|
layer.type !== LAYER_TYPE.BLENDED_VECTOR &&
|
||||||
|
layer.type !== LAYER_TYPE.HEATMAP
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sourceDescriptor: SourceDescriptor = layer.sourceDescriptor;
|
||||||
|
if (sourceDescriptor.type === SOURCE_TYPES.ES_GEO_GRID) {
|
||||||
|
return isFieldGeoShape(
|
||||||
|
indexPatterns,
|
||||||
|
(sourceDescriptor as ESGeoGridSourceDescriptor).indexPatternId,
|
||||||
|
(sourceDescriptor as ESGeoGridSourceDescriptor).geoField
|
||||||
|
);
|
||||||
|
} else if (
|
||||||
|
sourceDescriptor.type === SOURCE_TYPES.ES_SEARCH &&
|
||||||
|
(sourceDescriptor as ESSearchSourceDescriptor).scalingType === SCALING_TYPES.CLUSTERS
|
||||||
|
) {
|
||||||
|
return isFieldGeoShape(
|
||||||
|
indexPatterns,
|
||||||
|
(sourceDescriptor as ESSearchSourceDescriptor).indexPatternId,
|
||||||
|
(sourceDescriptor as ESSearchSourceDescriptor).geoField
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getGeoShapeAggCount(
|
||||||
|
layerLists: LayerDescriptor[][],
|
||||||
|
indexPatterns: IIndexPattern[]
|
||||||
|
): number {
|
||||||
|
const countsPerMap: number[] = layerLists.map((layerList: LayerDescriptor[]) => {
|
||||||
|
const geoShapeAggLayers = layerList.filter((layerDescriptor) => {
|
||||||
|
return isGeoShapeAggLayer(indexPatterns, layerDescriptor);
|
||||||
|
});
|
||||||
|
return geoShapeAggLayers.length;
|
||||||
|
});
|
||||||
|
|
||||||
|
return _.sum(countsPerMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getLayerLists(mapSavedObjects: MapSavedObject[]): LayerDescriptor[][] {
|
||||||
|
return mapSavedObjects.map((savedMapObject) => {
|
||||||
|
const layerList =
|
||||||
|
savedMapObject.attributes && savedMapObject.attributes.layerListJSON
|
||||||
|
? JSON.parse(savedMapObject.attributes.layerListJSON)
|
||||||
|
: [];
|
||||||
|
return layerList as LayerDescriptor[];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function buildMapsTelemetry({
|
export function buildMapsTelemetry({
|
||||||
mapSavedObjects,
|
mapSavedObjects,
|
||||||
indexPatternSavedObjects,
|
indexPatternSavedObjects,
|
||||||
|
@ -91,17 +208,13 @@ export function buildMapsTelemetry({
|
||||||
indexPatternSavedObjects: IIndexPattern[];
|
indexPatternSavedObjects: IIndexPattern[];
|
||||||
settings: SavedObjectAttribute;
|
settings: SavedObjectAttribute;
|
||||||
}): SavedObjectAttributes {
|
}): SavedObjectAttributes {
|
||||||
const layerLists = mapSavedObjects.map((savedMapObject) =>
|
const layerLists: LayerDescriptor[][] = getLayerLists(mapSavedObjects);
|
||||||
savedMapObject.attributes && savedMapObject.attributes.layerListJSON
|
|
||||||
? JSON.parse(savedMapObject.attributes.layerListJSON)
|
|
||||||
: []
|
|
||||||
);
|
|
||||||
const mapsCount = layerLists.length;
|
const mapsCount = layerLists.length;
|
||||||
|
|
||||||
const dataSourcesCount = layerLists.map((lList) => {
|
const dataSourcesCount = layerLists.map((layerList: LayerDescriptor[]) => {
|
||||||
// todo: not every source-descriptor has an id
|
// todo: not every source-descriptor has an id
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const sourceIdList = lList.map((layer: LayerDescriptor) => layer.sourceDescriptor.id);
|
const sourceIdList = layerList.map((layer: LayerDescriptor) => layer.sourceDescriptor.id);
|
||||||
return _.uniq(sourceIdList).length;
|
return _.uniq(sourceIdList).length;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -109,15 +222,7 @@ export function buildMapsTelemetry({
|
||||||
const layerTypesCount = layerLists.map((lList) => _.countBy(lList, 'type'));
|
const layerTypesCount = layerLists.map((lList) => _.countBy(lList, 'type'));
|
||||||
|
|
||||||
// Count of EMS Vector layers used
|
// Count of EMS Vector layers used
|
||||||
const emsLayersCount = layerLists.map((lList) =>
|
const emsLayersCount = getEMSLayerCount(layerLists);
|
||||||
_(lList)
|
|
||||||
.countBy((layer: LayerDescriptor) => {
|
|
||||||
const isEmsFile = _.get(layer, 'sourceDescriptor.type') === SOURCE_TYPES.EMS_FILE;
|
|
||||||
return isEmsFile && _.get(layer, 'sourceDescriptor.id');
|
|
||||||
})
|
|
||||||
.pickBy((val, key) => key !== 'false')
|
|
||||||
.value()
|
|
||||||
) as ILayerTypeCount[];
|
|
||||||
|
|
||||||
const dataSourcesCountSum = _.sum(dataSourcesCount);
|
const dataSourcesCountSum = _.sum(dataSourcesCount);
|
||||||
const layersCountSum = _.sum(layersCount);
|
const layersCountSum = _.sum(layersCount);
|
||||||
|
@ -127,11 +232,16 @@ export function buildMapsTelemetry({
|
||||||
indexPatternsWithGeoPointFieldCount,
|
indexPatternsWithGeoPointFieldCount,
|
||||||
indexPatternsWithGeoShapeFieldCount,
|
indexPatternsWithGeoShapeFieldCount,
|
||||||
} = getIndexPatternsWithGeoFieldCount(indexPatternSavedObjects);
|
} = getIndexPatternsWithGeoFieldCount(indexPatternSavedObjects);
|
||||||
|
|
||||||
|
// Tracks whether user users Gold+ only functionality
|
||||||
|
const geoShapeAggLayersCount = getGeoShapeAggCount(layerLists, indexPatternSavedObjects);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
settings,
|
settings,
|
||||||
indexPatternsWithGeoFieldCount,
|
indexPatternsWithGeoFieldCount,
|
||||||
indexPatternsWithGeoPointFieldCount,
|
indexPatternsWithGeoPointFieldCount,
|
||||||
indexPatternsWithGeoShapeFieldCount,
|
indexPatternsWithGeoShapeFieldCount,
|
||||||
|
geoShapeAggLayersCount,
|
||||||
// Total count of maps
|
// Total count of maps
|
||||||
mapsTotalCount: mapsCount,
|
mapsTotalCount: mapsCount,
|
||||||
// Time of capture
|
// Time of capture
|
||||||
|
|
|
@ -43,5 +43,38 @@
|
||||||
],
|
],
|
||||||
"updated_at": "2019-01-31T23:19:55.855Z",
|
"updated_at": "2019-01-31T23:19:55.855Z",
|
||||||
"version": 1
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "gis-map",
|
||||||
|
"id": "643da1e6-c628-11ea-87d0-0242ac130003",
|
||||||
|
"attributes": {
|
||||||
|
"title": "Single cluster layer with geo_shape field",
|
||||||
|
"description": "",
|
||||||
|
"mapStateJSON": "{\"zoom\":2.12,\"center\":{\"lon\":-88.67592,\"lat\":34.23257},\"timeFilters\":{\"from\":\"now-15m\",\"to\":\"now\",\"mode\":\"quick\"},\"refreshConfig\":{\"isPaused\":false,\"interval\":0},\"query\":{\"query\":\"\",\"language\":\"lucene\"}}",
|
||||||
|
"layerListJSON": "[{\"sourceDescriptor\":{\"type\":\"ES_GEO_GRID\",\"id\":\"51afb7d0-c628-11ea-87d0-0242ac130003\",\"geoField\":\"geometry\",\"metrics\":[{\"type\":\"count\"}],\"requestType\":\"point\",\"resolution\":\"COARSE\",\"indexPatternId\":\"4a7f6010-0aed-11ea-9dd2-95afd7ad44d4\"},\"style\":{\"type\":\"VECTOR\",\"properties\":{\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"marker\"}},\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"color\":\"Blues\",\"colorCategory\":\"palette_0\",\"field\":{\"name\":\"doc_count\",\"origin\":\"source\"},\"fieldMetaOptions\":{\"isEnabled\":true,\"sigma\":3},\"type\":\"ORDINAL\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":0}},\"iconSize\":{\"type\":\"DYNAMIC\",\"options\":{\"minSize\":7,\"maxSize\":32,\"field\":{\"name\":\"doc_count\",\"origin\":\"source\"},\"fieldMetaOptions\":{\"isEnabled\":true,\"sigma\":3}}},\"iconOrientation\":{\"type\":\"STATIC\",\"options\":{\"orientation\":0}},\"labelText\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"name\":\"doc_count\",\"origin\":\"source\"}}},\"labelColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#000000\"}},\"labelSize\":{\"type\":\"STATIC\",\"options\":{\"size\":14}},\"labelBorderColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"labelBorderSize\":{\"options\":{\"size\":\"SMALL\"}}},\"isTimeAware\":true},\"id\":\"8d384d5d-6353-468f-b8f8-8eaa487358c4\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"alpha\":1,\"visible\":true,\"type\":\"VECTOR\",\"joins\":[]}]",
|
||||||
|
"uiStateJSON": "{}"
|
||||||
|
},
|
||||||
|
"references": [
|
||||||
|
],
|
||||||
|
"updated_at": "2019-01-31T23:19:55.855Z",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "gis-map",
|
||||||
|
"id": "5efd136a-c628-11ea-87d0-0242ac130003",
|
||||||
|
"attributes": {
|
||||||
|
"title": "Single heatmap layer with geo_shape field",
|
||||||
|
"description": "",
|
||||||
|
"mapStateJSON": "{\"zoom\":2.12,\"center\":{\"lon\":-88.67592,\"lat\":34.23257},\"timeFilters\":{\"from\":\"now-15m\",\"to\":\"now\",\"mode\":\"quick\"},\"refreshConfig\":{\"isPaused\":false,\"interval\":0},\"query\":{\"query\":\"\",\"language\":\"lucene\"}}",
|
||||||
|
"layerListJSON": "[{\"sourceDescriptor\":{\"type\":\"ES_GEO_GRID\",\"id\":\"51afb7d0-c628-11ea-87d0-0242ac130003\",\"geoField\":\"geometry\",\"metrics\":[{\"type\":\"count\"}],\"requestType\":\"heatmap\",\"resolution\":\"COARSE\",\"indexPatternId\":\"4a7f6010-0aed-11ea-9dd2-95afd7ad44d4\"},\"id\":\"52eade74-1c78-4e18-8670-2061f38b613b\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"alpha\":0.75,\"visible\":true,\"style\":{\"type\":\"HEATMAP\",\"colorRampName\":\"theclassic\"},\"type\":\"HEATMAP\",\"joins\":[]}]",
|
||||||
|
"uiStateJSON": "{}"
|
||||||
|
},
|
||||||
|
"references": [
|
||||||
|
],
|
||||||
|
"updated_at": "2019-01-31T23:19:55.855Z",
|
||||||
|
"version": 1
|
||||||
}
|
}
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue