Skip to content

Commit

Permalink
[Visualizations] Simplify visualization telemetry (#77145)
Browse files Browse the repository at this point in the history
* Move visualizations telemetry into visualizations plugin

* Remove x-pack oss_telemetry plugin

* Add unit tests

* Update docs

* Revert not related changes

Co-authored-by: Elastic Machine <[email protected]>
  • Loading branch information
sulemanof and elasticmachine authored Sep 14, 2020
1 parent 98c9b18 commit 44f594e
Show file tree
Hide file tree
Showing 23 changed files with 403 additions and 781 deletions.
4 changes: 0 additions & 4 deletions docs/developer/plugin-list.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -416,10 +416,6 @@ using the CURL scripts in the scripts folder.
|This plugin provides shared components and services for use across observability solutions, as well as the observability landing page UI.
|{kib-repo}blob/{branch}/x-pack/plugins/oss_telemetry[ossTelemetry]
|WARNING: Missing README.
|{kib-repo}blob/{branch}/x-pack/plugins/painless_lab[painlessLab]
|WARNING: Missing README.
Expand Down
11 changes: 10 additions & 1 deletion src/plugins/visualizations/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

import { i18n } from '@kbn/i18n';
import { schema } from '@kbn/config-schema';
import { Observable } from 'rxjs';
import { UsageCollectionSetup } from 'src/plugins/usage_collection/server';
import {
PluginInitializerContext,
CoreSetup,
Expand All @@ -32,16 +34,19 @@ import { VISUALIZE_ENABLE_LABS_SETTING } from '../common/constants';
import { visualizationSavedObjectType } from './saved_objects';

import { VisualizationsPluginSetup, VisualizationsPluginStart } from './types';
import { registerVisualizationsCollector } from './usage_collector';

export class VisualizationsPlugin
implements Plugin<VisualizationsPluginSetup, VisualizationsPluginStart> {
private readonly logger: Logger;
private readonly config: Observable<{ kibana: { index: string } }>;

constructor(initializerContext: PluginInitializerContext) {
this.logger = initializerContext.logger.get();
this.config = initializerContext.config.legacy.globalConfig$;
}

public setup(core: CoreSetup) {
public setup(core: CoreSetup, plugins: { usageCollection?: UsageCollectionSetup }) {
this.logger.debug('visualizations: Setup');

core.savedObjects.registerType(visualizationSavedObjectType);
Expand All @@ -61,6 +66,10 @@ export class VisualizationsPlugin
},
});

if (plugins.usageCollection) {
registerVisualizationsCollector(plugins.usageCollection, this.config);
}

return {};
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import moment from 'moment';
import { getPastDays } from './get_past_days';

describe('getPastDays', () => {
test('Returns 2 days that have passed from the current date', () => {
const pastDate = moment().subtract(2, 'days').startOf('day').toString();

expect(getPastDays(pastDate)).toEqual(2);
});

test('Returns 30 days that have passed from the current date', () => {
const pastDate = moment().subtract(30, 'days').startOf('day').toString();

expect(getPastDays(pastDate)).toEqual(30);
});
});
25 changes: 25 additions & 0 deletions src/plugins/visualizations/server/usage_collector/get_past_days.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

export const getPastDays = (dateString: string): number => {
const date = new Date(dateString);
const today = new Date();
const diff = Math.abs(date.getTime() - today.getTime());
return Math.trunc(diff / (1000 * 60 * 60 * 24));
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import moment from 'moment';
import { of } from 'rxjs';

import { LegacyAPICaller } from 'src/core/server';
import { getUsageCollector } from './get_usage_collector';

const defaultMockSavedObjects = [
{
_id: 'visualization:coolviz-123',
_source: {
type: 'visualization',
visualization: { visState: '{"type": "shell_beads"}' },
updated_at: moment().subtract(7, 'days').startOf('day').toString(),
},
},
];

const enlargedMockSavedObjects = [
// default space
{
_id: 'visualization:coolviz-123',
_source: {
type: 'visualization',
visualization: { visState: '{"type": "cave_painting"}' },
updated_at: moment().subtract(7, 'days').startOf('day').toString(),
},
},
{
_id: 'visualization:coolviz-456',
_source: {
type: 'visualization',
visualization: { visState: '{"type": "printing_press"}' },
updated_at: moment().subtract(20, 'days').startOf('day').toString(),
},
},
{
_id: 'meat:visualization:coolviz-789',
_source: {
type: 'visualization',
visualization: { visState: '{"type": "floppy_disk"}' },
updated_at: moment().subtract(2, 'months').startOf('day').toString(),
},
},
// meat space
{
_id: 'meat:visualization:coolviz-789',
_source: {
type: 'visualization',
visualization: { visState: '{"type": "cave_painting"}' },
updated_at: moment().subtract(89, 'days').startOf('day').toString(),
},
},
{
_id: 'meat:visualization:coolviz-789',
_source: {
type: 'visualization',
visualization: { visState: '{"type": "cuneiform"}' },
updated_at: moment().subtract(5, 'months').startOf('day').toString(),
},
},
{
_id: 'meat:visualization:coolviz-789',
_source: {
type: 'visualization',
visualization: { visState: '{"type": "cuneiform"}' },
updated_at: moment().subtract(2, 'days').startOf('day').toString(),
},
},
{
_id: 'meat:visualization:coolviz-789',
_source: {
type: 'visualization',
visualization: { visState: '{"type": "floppy_disk"}' },
updated_at: moment().subtract(7, 'days').startOf('day').toString(),
},
},
// cyber space
{
_id: 'cyber:visualization:coolviz-789',
_source: {
type: 'visualization',
visualization: { visState: '{"type": "floppy_disk"}' },
updated_at: moment().subtract(7, 'months').startOf('day').toString(),
},
},
{
_id: 'cyber:visualization:coolviz-789',
_source: {
type: 'visualization',
visualization: { visState: '{"type": "floppy_disk"}' },
updated_at: moment().subtract(3, 'days').startOf('day').toString(),
},
},
{
_id: 'cyber:visualization:coolviz-123',
_source: {
type: 'visualization',
visualization: { visState: '{"type": "cave_painting"}' },
updated_at: moment().subtract(15, 'days').startOf('day').toString(),
},
},
];

describe('Visualizations usage collector', () => {
const configMock = of({ kibana: { index: '' } });
const usageCollector = getUsageCollector(configMock);
const getMockCallCluster = (hits: unknown[]) =>
(() => Promise.resolve({ hits: { hits } }) as unknown) as LegacyAPICaller;

test('Should fit the shape', () => {
expect(usageCollector.type).toBe('visualization_types');
expect(usageCollector.isReady()).toBe(true);
expect(usageCollector.fetch).toEqual(expect.any(Function));
});

test('Summarizes visualizations response data', async () => {
const result = await usageCollector.fetch(getMockCallCluster(defaultMockSavedObjects));

expect(result).toMatchObject({
shell_beads: {
spaces_avg: 1,
spaces_max: 1,
spaces_min: 1,
total: 1,
saved_7_days_total: 1,
saved_30_days_total: 1,
saved_90_days_total: 1,
},
});
});

test('Summarizes visualizations response data per Space', async () => {
const expectedStats = {
cave_painting: {
total: 3,
spaces_min: 1,
spaces_max: 1,
spaces_avg: 1,
saved_7_days_total: 1,
saved_30_days_total: 2,
saved_90_days_total: 3,
},
printing_press: {
total: 1,
spaces_min: 1,
spaces_max: 1,
spaces_avg: 1,
saved_7_days_total: 0,
saved_30_days_total: 1,
saved_90_days_total: 1,
},
cuneiform: {
total: 2,
spaces_min: 2,
spaces_max: 2,
spaces_avg: 2,
saved_7_days_total: 1,
saved_30_days_total: 1,
saved_90_days_total: 1,
},
floppy_disk: {
total: 4,
spaces_min: 2,
spaces_max: 2,
spaces_avg: 2,
saved_7_days_total: 2,
saved_30_days_total: 2,
saved_90_days_total: 3,
},
};

const result = await usageCollector.fetch(getMockCallCluster(enlargedMockSavedObjects));

expect(result).toMatchObject(expectedStats);
});
});
Loading

0 comments on commit 44f594e

Please sign in to comment.