Skip to content

Commit b642f4f

Browse files
[Maps] Track geo_shape agg usage (#71759) (#71935)
Tracks how many layers are using geo_shape aggs.
1 parent 5f8cf46 commit b642f4f

3 files changed

Lines changed: 175 additions & 30 deletions

File tree

x-pack/plugins/maps/server/maps_telemetry/maps_telemetry.test.js

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ describe('buildMapsTelemetry', () => {
2222
indexPatternsWithGeoFieldCount: 0,
2323
indexPatternsWithGeoPointFieldCount: 0,
2424
indexPatternsWithGeoShapeFieldCount: 0,
25+
geoShapeAggLayersCount: 0,
2526
attributesPerMap: {
2627
dataSourcesCount: {
2728
avg: 0,
@@ -50,48 +51,49 @@ describe('buildMapsTelemetry', () => {
5051
indexPatternsWithGeoFieldCount: 3,
5152
indexPatternsWithGeoPointFieldCount: 2,
5253
indexPatternsWithGeoShapeFieldCount: 1,
54+
geoShapeAggLayersCount: 2,
5355
attributesPerMap: {
5456
dataSourcesCount: {
55-
avg: 2.6666666666666665,
57+
avg: 2,
5658
max: 3,
57-
min: 2,
59+
min: 1,
5860
},
5961
emsVectorLayersCount: {
6062
canada_provinces: {
61-
avg: 0.3333333333333333,
63+
avg: 0.2,
6264
max: 1,
6365
min: 1,
6466
},
6567
france_departments: {
66-
avg: 0.3333333333333333,
68+
avg: 0.2,
6769
max: 1,
6870
min: 1,
6971
},
7072
italy_provinces: {
71-
avg: 0.3333333333333333,
73+
avg: 0.2,
7274
max: 1,
7375
min: 1,
7476
},
7577
},
7678
layerTypesCount: {
7779
TILE: {
78-
avg: 1,
80+
avg: 0.6,
7981
max: 1,
8082
min: 1,
8183
},
8284
VECTOR: {
83-
avg: 1.6666666666666667,
85+
avg: 1.2,
8486
max: 2,
8587
min: 1,
8688
},
8789
},
8890
layersCount: {
89-
avg: 2.6666666666666665,
91+
avg: 2,
9092
max: 3,
91-
min: 2,
93+
min: 1,
9294
},
9395
},
94-
mapsTotalCount: 3,
96+
mapsTotalCount: 5,
9597
settings: {
9698
showMapVisualizationTypes: false,
9799
},

x-pack/plugins/maps/server/maps_telemetry/maps_telemetry.ts

Lines changed: 130 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,25 @@
66

77
import _ from 'lodash';
88
import {
9-
SavedObjectsClientContract,
10-
SavedObjectAttributes,
119
SavedObjectAttribute,
10+
SavedObjectAttributes,
11+
SavedObjectsClientContract,
1212
} from 'kibana/server';
1313
import { IFieldType, IIndexPattern } from 'src/plugins/data/public';
14-
import { SOURCE_TYPES, ES_GEO_FIELD_TYPE, MAP_SAVED_OBJECT_TYPE } from '../../common/constants';
15-
import { LayerDescriptor } from '../../common/descriptor_types';
14+
import {
15+
ES_GEO_FIELD_TYPE,
16+
LAYER_TYPE,
17+
MAP_SAVED_OBJECT_TYPE,
18+
SCALING_TYPES,
19+
SOURCE_TYPES,
20+
} from '../../common/constants';
21+
import {
22+
AbstractSourceDescriptor,
23+
ESGeoGridSourceDescriptor,
24+
ESSearchSourceDescriptor,
25+
LayerDescriptor,
26+
SourceDescriptor,
27+
} from '../../common/descriptor_types';
1628
import { MapSavedObject } from '../../common/map_saved_object_type';
1729
// @ts-ignore
1830
import { getInternalRepository } from '../kibana_server_services';
@@ -82,6 +94,111 @@ function getIndexPatternsWithGeoFieldCount(indexPatterns: IIndexPattern[]) {
8294
};
8395
}
8496

97+
function getEMSLayerCount(layerLists: LayerDescriptor[][]): ILayerTypeCount[] {
98+
return layerLists.map((layerList: LayerDescriptor[]) => {
99+
const emsLayers = layerList.filter((layer: LayerDescriptor) => {
100+
return (
101+
layer.sourceDescriptor !== null &&
102+
layer.sourceDescriptor.type === SOURCE_TYPES.EMS_FILE &&
103+
(layer.sourceDescriptor as AbstractSourceDescriptor).id
104+
);
105+
});
106+
const emsCountsById = _(emsLayers).countBy((layer: LayerDescriptor) => {
107+
return (layer.sourceDescriptor as AbstractSourceDescriptor).id;
108+
});
109+
110+
const layerTypeCount = emsCountsById.value();
111+
return layerTypeCount as ILayerTypeCount;
112+
}) as ILayerTypeCount[];
113+
}
114+
115+
function isFieldGeoShape(
116+
indexPatterns: IIndexPattern[],
117+
indexPatternId: string,
118+
geoField: string | undefined
119+
): boolean {
120+
if (!geoField) {
121+
return false;
122+
}
123+
124+
const matchIndexPattern = indexPatterns.find((indexPattern: IIndexPattern) => {
125+
return indexPattern.id === indexPatternId;
126+
});
127+
128+
if (!matchIndexPattern) {
129+
return false;
130+
}
131+
132+
const fieldList: IFieldType[] =
133+
matchIndexPattern.attributes && matchIndexPattern.attributes.fields
134+
? JSON.parse(matchIndexPattern.attributes.fields)
135+
: [];
136+
137+
const matchField = fieldList.find((field: IFieldType) => {
138+
return field.name === geoField;
139+
});
140+
141+
return !!matchField && matchField.type === ES_GEO_FIELD_TYPE.GEO_SHAPE;
142+
}
143+
144+
function isGeoShapeAggLayer(indexPatterns: IIndexPattern[], layer: LayerDescriptor): boolean {
145+
if (layer.sourceDescriptor === null) {
146+
return false;
147+
}
148+
149+
if (
150+
layer.type !== LAYER_TYPE.VECTOR &&
151+
layer.type !== LAYER_TYPE.BLENDED_VECTOR &&
152+
layer.type !== LAYER_TYPE.HEATMAP
153+
) {
154+
return false;
155+
}
156+
157+
const sourceDescriptor: SourceDescriptor = layer.sourceDescriptor;
158+
if (sourceDescriptor.type === SOURCE_TYPES.ES_GEO_GRID) {
159+
return isFieldGeoShape(
160+
indexPatterns,
161+
(sourceDescriptor as ESGeoGridSourceDescriptor).indexPatternId,
162+
(sourceDescriptor as ESGeoGridSourceDescriptor).geoField
163+
);
164+
} else if (
165+
sourceDescriptor.type === SOURCE_TYPES.ES_SEARCH &&
166+
(sourceDescriptor as ESSearchSourceDescriptor).scalingType === SCALING_TYPES.CLUSTERS
167+
) {
168+
return isFieldGeoShape(
169+
indexPatterns,
170+
(sourceDescriptor as ESSearchSourceDescriptor).indexPatternId,
171+
(sourceDescriptor as ESSearchSourceDescriptor).geoField
172+
);
173+
} else {
174+
return false;
175+
}
176+
}
177+
178+
function getGeoShapeAggCount(
179+
layerLists: LayerDescriptor[][],
180+
indexPatterns: IIndexPattern[]
181+
): number {
182+
const countsPerMap: number[] = layerLists.map((layerList: LayerDescriptor[]) => {
183+
const geoShapeAggLayers = layerList.filter((layerDescriptor) => {
184+
return isGeoShapeAggLayer(indexPatterns, layerDescriptor);
185+
});
186+
return geoShapeAggLayers.length;
187+
});
188+
189+
return _.sum(countsPerMap);
190+
}
191+
192+
export function getLayerLists(mapSavedObjects: MapSavedObject[]): LayerDescriptor[][] {
193+
return mapSavedObjects.map((savedMapObject) => {
194+
const layerList =
195+
savedMapObject.attributes && savedMapObject.attributes.layerListJSON
196+
? JSON.parse(savedMapObject.attributes.layerListJSON)
197+
: [];
198+
return layerList as LayerDescriptor[];
199+
});
200+
}
201+
85202
export function buildMapsTelemetry({
86203
mapSavedObjects,
87204
indexPatternSavedObjects,
@@ -91,33 +208,21 @@ export function buildMapsTelemetry({
91208
indexPatternSavedObjects: IIndexPattern[];
92209
settings: SavedObjectAttribute;
93210
}): SavedObjectAttributes {
94-
const layerLists = mapSavedObjects.map((savedMapObject) =>
95-
savedMapObject.attributes && savedMapObject.attributes.layerListJSON
96-
? JSON.parse(savedMapObject.attributes.layerListJSON)
97-
: []
98-
);
211+
const layerLists: LayerDescriptor[][] = getLayerLists(mapSavedObjects);
99212
const mapsCount = layerLists.length;
100213

101-
const dataSourcesCount = layerLists.map((lList) => {
214+
const dataSourcesCount = layerLists.map((layerList: LayerDescriptor[]) => {
102215
// todo: not every source-descriptor has an id
103216
// @ts-ignore
104-
const sourceIdList = lList.map((layer: LayerDescriptor) => layer.sourceDescriptor.id);
217+
const sourceIdList = layerList.map((layer: LayerDescriptor) => layer.sourceDescriptor.id);
105218
return _.uniq(sourceIdList).length;
106219
});
107220

108221
const layersCount = layerLists.map((lList) => lList.length);
109222
const layerTypesCount = layerLists.map((lList) => _.countBy(lList, 'type'));
110223

111224
// Count of EMS Vector layers used
112-
const emsLayersCount = layerLists.map((lList) =>
113-
_(lList)
114-
.countBy((layer: LayerDescriptor) => {
115-
const isEmsFile = _.get(layer, 'sourceDescriptor.type') === SOURCE_TYPES.EMS_FILE;
116-
return isEmsFile && _.get(layer, 'sourceDescriptor.id');
117-
})
118-
.pickBy((val, key) => key !== 'false')
119-
.value()
120-
) as ILayerTypeCount[];
225+
const emsLayersCount = getEMSLayerCount(layerLists);
121226

122227
const dataSourcesCountSum = _.sum(dataSourcesCount);
123228
const layersCountSum = _.sum(layersCount);
@@ -127,11 +232,16 @@ export function buildMapsTelemetry({
127232
indexPatternsWithGeoPointFieldCount,
128233
indexPatternsWithGeoShapeFieldCount,
129234
} = getIndexPatternsWithGeoFieldCount(indexPatternSavedObjects);
235+
236+
// Tracks whether user users Gold+ only functionality
237+
const geoShapeAggLayersCount = getGeoShapeAggCount(layerLists, indexPatternSavedObjects);
238+
130239
return {
131240
settings,
132241
indexPatternsWithGeoFieldCount,
133242
indexPatternsWithGeoPointFieldCount,
134243
indexPatternsWithGeoShapeFieldCount,
244+
geoShapeAggLayersCount,
135245
// Total count of maps
136246
mapsTotalCount: mapsCount,
137247
// Time of capture

x-pack/plugins/maps/server/maps_telemetry/test_resources/sample_map_saved_objects.json

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,38 @@
4343
],
4444
"updated_at": "2019-01-31T23:19:55.855Z",
4545
"version": 1
46+
},
47+
{
48+
"type": "gis-map",
49+
"id": "643da1e6-c628-11ea-87d0-0242ac130003",
50+
"attributes": {
51+
"title": "Single cluster layer with geo_shape field",
52+
"description": "",
53+
"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\"}}",
54+
"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\":[]}]",
55+
"uiStateJSON": "{}"
56+
},
57+
"references": [
58+
],
59+
"updated_at": "2019-01-31T23:19:55.855Z",
60+
"version": 1
61+
},
62+
{
63+
"type": "gis-map",
64+
"id": "5efd136a-c628-11ea-87d0-0242ac130003",
65+
"attributes": {
66+
"title": "Single heatmap layer with geo_shape field",
67+
"description": "",
68+
"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\"}}",
69+
"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\":[]}]",
70+
"uiStateJSON": "{}"
71+
},
72+
"references": [
73+
],
74+
"updated_at": "2019-01-31T23:19:55.855Z",
75+
"version": 1
4676
}
77+
4778
]
79+
80+

0 commit comments

Comments
 (0)