From ba7b9c19de00e481a59fb7f03701720fd80afe25 Mon Sep 17 00:00:00 2001 From: Larry Gregory Date: Mon, 9 Jul 2018 15:12:46 -0400 Subject: [PATCH 1/7] basic telemetry for spaces --- x-pack/plugins/spaces/common/constants.js | 6 + x-pack/plugins/spaces/index.js | 4 + .../server/lib/get_spaces_usage_collector.js | 55 +++++++ .../lib/get_spaces_usage_collector.test.js | 149 ++++++++++++++++++ 4 files changed, 214 insertions(+) create mode 100644 x-pack/plugins/spaces/server/lib/get_spaces_usage_collector.js create mode 100644 x-pack/plugins/spaces/server/lib/get_spaces_usage_collector.test.js diff --git a/x-pack/plugins/spaces/common/constants.js b/x-pack/plugins/spaces/common/constants.js index c4d8931871b97..2ebd080964c42 100644 --- a/x-pack/plugins/spaces/common/constants.js +++ b/x-pack/plugins/spaces/common/constants.js @@ -15,3 +15,9 @@ export const SPACE_SEARCH_COUNT_THRESHOLD = 8; * The maximum number of characters allowed in the Space Avatar's initials */ export const MAX_SPACE_INITIALS = 2; + +/** + * The type name used within the Monitoring index to publish spaces stats. + * @type {string} + */ +export const KIBANA_SPACES_MONITORING_TYPE = 'spaces_stats'; diff --git a/x-pack/plugins/spaces/index.js b/x-pack/plugins/spaces/index.js index 38d2e84cc992f..a24140eefe03f 100644 --- a/x-pack/plugins/spaces/index.js +++ b/x-pack/plugins/spaces/index.js @@ -12,6 +12,7 @@ import { initSpacesRequestInterceptors } from './server/lib/space_request_interc import { createDefaultSpace } from './server/lib/create_default_space'; import { mirrorPluginStatus } from '../../server/lib/mirror_plugin_status'; import { getActiveSpace } from './server/lib/get_active_space'; +import { getSpacesUsageCollector } from './server/lib/get_spaces_usage_collector'; import { wrapError } from './server/lib/errors'; import mappings from './mappings.json'; @@ -78,6 +79,9 @@ export const spaces = (kibana) => new kibana.Plugin({ initSpacesRequestInterceptors(server); + // Register a function with server to manage the collection of usage stats + server.usage.collectorSet.register(getSpacesUsageCollector(server)); + await createDefaultSpace(server); } }); diff --git a/x-pack/plugins/spaces/server/lib/get_spaces_usage_collector.js b/x-pack/plugins/spaces/server/lib/get_spaces_usage_collector.js new file mode 100644 index 0000000000000..0fb8dfc6fb30b --- /dev/null +++ b/x-pack/plugins/spaces/server/lib/get_spaces_usage_collector.js @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { KIBANA_SPACES_MONITORING_TYPE } from '../../common/constants'; + +/** + * + * @param callCluster + * @param server + * @param {boolean} reportingAvailable - if true, we track some of the counts as 0 instead of undefined. + * @param withinDayRange + * @return {ReportingUsageStats} + */ +async function getSpacesUsage(callCluster, server, spacesAvailable) { + if (!spacesAvailable) return {}; + + const { getSavedObjectsRepository } = server.savedObjects; + + const savedObjectsRepository = getSavedObjectsRepository(callCluster); + + const { saved_objects: spaces } = await savedObjectsRepository.find({ type: 'space' }); + + return { + count: spaces.length, + }; +} + +/* + * @param {Object} server + * @return {Object} kibana usage stats type collection object + */ +export function getSpacesUsageCollector(server) { + const { collectorSet } = server.usage; + return collectorSet.makeUsageCollector({ + type: KIBANA_SPACES_MONITORING_TYPE, + fetch: async callCluster => { + const xpackInfo = server.plugins.xpack_main.info; + const config = server.config(); + const available = xpackInfo && xpackInfo.isAvailable(); // some form of spaces is available for all valid licenses + const enabled = config.get('xpack.spaces.enabled'); // follow ES behavior: if its not available then its not enabled + const spacesAvailable = available && enabled; + + const usageStats = await getSpacesUsage(callCluster, server, spacesAvailable); + + return { + available, + enabled: available && enabled, // similar behavior as _xpack API in ES + ...usageStats, + }; + } + }); +} diff --git a/x-pack/plugins/spaces/server/lib/get_spaces_usage_collector.test.js b/x-pack/plugins/spaces/server/lib/get_spaces_usage_collector.test.js new file mode 100644 index 0000000000000..490c1c13ec7ab --- /dev/null +++ b/x-pack/plugins/spaces/server/lib/get_spaces_usage_collector.test.js @@ -0,0 +1,149 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { getSpacesUsageCollector } from './get_spaces_usage_collector'; + +function getServerMock(customization) { + class MockUsageCollector { + constructor(_server, { fetch }) { + this.fetch = fetch; + } + } + + const getLicenseCheckResults = jest.fn().mockReturnValue({}); + const defaultServerMock = { + plugins: { + security: { + isAuthenticated: jest.fn().mockReturnValue(true) + }, + xpack_main: { + info: { + isAvailable: jest.fn().mockReturnValue(true), + feature: () => ({ + getLicenseCheckResults + }), + license: { + isOneOf: jest.fn().mockReturnValue(false), + getType: jest.fn().mockReturnValue('platinum'), + }, + toJSON: () => ({ b: 1 }) + } + } + }, + expose: () => { }, + log: () => { }, + config: () => ({ + get: key => { + if (key === 'xpack.spaces.enabled') { + return true; + } + } + }), + usage: { + collectorSet: { + makeUsageCollector: options => { + return new MockUsageCollector(this, options); + } + } + }, + savedObjects: { + getSavedObjectsRepository: jest.fn(() => { + return { + find() { + return { + saved_objects: ['a', 'b'] + }; + } + }; + }) + } + }; + return Object.assign(defaultServerMock, customization); +} + +test('sets enabled to false when spaces is turned off', async () => { + const mockConfigGet = jest.fn(key => { + if (key === 'xpack.spaces.enabled') { + return false; + } else if (key.indexOf('xpack.spaces') >= 0) { + throw new Error('Unknown config key!'); + } + }); + const serverMock = getServerMock({ config: () => ({ get: mockConfigGet }) }); + const callClusterMock = jest.fn(); + const { fetch: getSpacesUsage } = getSpacesUsageCollector(serverMock); + const usageStats = await getSpacesUsage(callClusterMock); + expect(usageStats.enabled).toBe(false); +}); + +describe('with a basic license', async () => { + let usageStats; + beforeAll(async () => { + const serverWithBasicLicenseMock = getServerMock(); + serverWithBasicLicenseMock.plugins.xpack_main.info.license.getType = jest.fn().mockReturnValue('basic'); + const callClusterMock = jest.fn(() => Promise.resolve({})); + const { fetch: getSpacesUsage } = getSpacesUsageCollector(serverWithBasicLicenseMock); + usageStats = await getSpacesUsage(callClusterMock); + }); + + test('sets enabled to true', async () => { + expect(usageStats.enabled).toBe(true); + }); + + test('sets available to true', async () => { + expect(usageStats.available).toBe(true); + }); + + test('sets the number of spaces', async () => { + expect(usageStats.count).toBe(2); + }); +}); + +describe('with no license', async () => { + let usageStats; + beforeAll(async () => { + const serverWithNoLicenseMock = getServerMock(); + serverWithNoLicenseMock.plugins.xpack_main.info.isAvailable = jest.fn().mockReturnValue(false); + const callClusterMock = jest.fn(() => Promise.resolve({})); + const { fetch: getSpacesUsage } = getSpacesUsageCollector(serverWithNoLicenseMock); + usageStats = await getSpacesUsage(callClusterMock); + }); + + test('sets enabled to false', async () => { + expect(usageStats.enabled).toBe(false); + }); + + test('sets available to false', async () => { + expect(usageStats.available).toBe(false); + }); + + test('does not set the number of spaces', async () => { + expect(usageStats.count).toBeUndefined(); + }); +}); + +describe('with platinum license', async () => { + let usageStats; + beforeAll(async () => { + const serverWithPlatinumLicenseMock = getServerMock(); + serverWithPlatinumLicenseMock.plugins.xpack_main.info.license.getType = jest.fn().mockReturnValue('platinum'); + const callClusterMock = jest.fn(() => Promise.resolve({})); + const { fetch: getSpacesUsage } = getSpacesUsageCollector(serverWithPlatinumLicenseMock); + usageStats = await getSpacesUsage(callClusterMock); + }); + + test('sets enabled to true', async () => { + expect(usageStats.enabled).toBe(true); + }); + + test('sets available to true', async () => { + expect(usageStats.available).toBe(true); + }); + + test('sets the number of spaces', async () => { + expect(usageStats.count).toBe(2); + }); +}); From f2e1dad4d460c8900ad15ae16c113167d97d7a38 Mon Sep 17 00:00:00 2001 From: Larry Gregory Date: Tue, 10 Jul 2018 10:57:07 -0400 Subject: [PATCH 2/7] cleanup stale comment --- x-pack/plugins/spaces/server/lib/get_spaces_usage_collector.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/spaces/server/lib/get_spaces_usage_collector.js b/x-pack/plugins/spaces/server/lib/get_spaces_usage_collector.js index 0fb8dfc6fb30b..303fbd89c2917 100644 --- a/x-pack/plugins/spaces/server/lib/get_spaces_usage_collector.js +++ b/x-pack/plugins/spaces/server/lib/get_spaces_usage_collector.js @@ -10,7 +10,7 @@ import { KIBANA_SPACES_MONITORING_TYPE } from '../../common/constants'; * * @param callCluster * @param server - * @param {boolean} reportingAvailable - if true, we track some of the counts as 0 instead of undefined. + * @param {boolean} spacesAvailable * @param withinDayRange * @return {ReportingUsageStats} */ From ced769affdc46d62b9fca1ee49d02750006a30f2 Mon Sep 17 00:00:00 2001 From: Larry Gregory Date: Wed, 18 Jul 2018 08:14:52 -0400 Subject: [PATCH 3/7] fix spaces telemetry reporting --- .../__tests__/get_collector_types_combiner.js | 25 ++++++++++++++----- .../lib/get_collector_types_combiner.js | 17 +++++++++---- .../server/routes/api/v1/kibana_stats.js | 8 ++++-- 3 files changed, 37 insertions(+), 13 deletions(-) diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/lib/__tests__/get_collector_types_combiner.js b/x-pack/plugins/monitoring/server/kibana_monitoring/lib/__tests__/get_collector_types_combiner.js index 4bf5c2a37c9a6..8530f1c886735 100644 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/lib/__tests__/get_collector_types_combiner.js +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/lib/__tests__/get_collector_types_combiner.js @@ -62,6 +62,14 @@ const getInitial = () => { } } ], + [ + { 'index': { '_type': 'spaces_stats' } }, + { + 'available': true, + 'enabled': true, + 'count': 1 + } + ], [ { 'index': { '_type': 'kibana_settings' } }, { 'xpack': { 'defaultAdminEmail': 'tim@elastic.co' } } @@ -124,6 +132,11 @@ const getResult = () => { 'available': true, 'count': 30, } + }, + 'spaces': { + 'available': true, + 'enabled': true, + 'count': 1 } } } @@ -175,11 +188,11 @@ describe('Collector Types Combiner', () => { it('provides combined stats/usage data', () => { // default gives all the data types const initial = getInitial(); - const trimmedInitial = [ initial[0], initial[1], initial[2] ]; // just stats, usage and reporting, no settings + const trimmedInitial = [initial[0], initial[1], initial[2], initial[3]]; // just stats, usage and reporting, no settings const combiner = getCollectorTypesCombiner(kbnServerMock, configMock, sourceKibanaMock); const result = combiner(trimmedInitial); const expectedResult = getResult(); - const trimmedExpectedResult = [ expectedResult[0] ]; // single combined item + const trimmedExpectedResult = [expectedResult[0]]; // single combined item expect(result).to.eql(trimmedExpectedResult); }); }); @@ -187,12 +200,12 @@ describe('Collector Types Combiner', () => { it('provides settings, and stats data', () => { // default gives all the data types const initial = getInitial(); - const trimmedInitial = [ initial[0], initial[3] ]; // just stats and settings, no usage or reporting + const trimmedInitial = [initial[0], initial[4]]; // just stats and settings, no usage or reporting const combiner = getCollectorTypesCombiner(kbnServerMock, configMock, sourceKibanaMock); const result = combiner(trimmedInitial); const expectedResult = getResult(); delete expectedResult[0][1].usage; // usage stats should not be present in the result - const trimmedExpectedResult = [ expectedResult[0], expectedResult[1] ]; + const trimmedExpectedResult = [expectedResult[0], expectedResult[1]]; expect(result).to.eql(trimmedExpectedResult); }); }); @@ -200,11 +213,11 @@ describe('Collector Types Combiner', () => { it('provides settings data', () => { // default gives all the data types const initial = getInitial(); - const trimmedInitial = [ initial[3] ]; // just settings + const trimmedInitial = [initial[4]]; // just settings const combiner = getCollectorTypesCombiner(kbnServerMock, configMock, sourceKibanaMock); const result = combiner(trimmedInitial); const expectedResult = getResult(); - const trimmedExpectedResult = [ expectedResult[1] ]; // just settings + const trimmedExpectedResult = [expectedResult[1]]; // just settings expect(result).to.eql(trimmedExpectedResult); }); }); diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/lib/get_collector_types_combiner.js b/x-pack/plugins/monitoring/server/kibana_monitoring/lib/get_collector_types_combiner.js index f50b080a9afc9..2547171e38013 100644 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/lib/get_collector_types_combiner.js +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/lib/get_collector_types_combiner.js @@ -11,6 +11,7 @@ import { KIBANA_USAGE_TYPE, } from '../../../common/constants'; import { KIBANA_REPORTING_TYPE } from '../../../../reporting/common/constants'; +import { KIBANA_SPACES_MONITORING_TYPE } from '../../../../spaces/common/constants'; import { sourceKibana } from './source_kibana'; /* @@ -39,17 +40,20 @@ export function getCollectorTypesCombiner(kbnServer, config, _sourceKibana = sou // kibana usage and stats let statsResult; - const [ statsHeader, statsPayload ] = findItem(KIBANA_STATS_TYPE); - const [ reportingHeader, reportingPayload ] = findItem(KIBANA_REPORTING_TYPE); + const [statsHeader, statsPayload] = findItem(KIBANA_STATS_TYPE); + const [reportingHeader, reportingPayload] = findItem(KIBANA_REPORTING_TYPE); + const [spacesHeader, spacesPayload] = findItem(KIBANA_SPACES_MONITORING_TYPE); // sourceKibana uses "host" from the kibana stats payload const host = get(statsPayload, 'host'); const kibana = _sourceKibana(kbnServer, config, host); if (statsHeader && statsPayload) { - const [ usageHeader, usagePayload ] = findItem(KIBANA_USAGE_TYPE); + const [usageHeader, usagePayload] = findItem(KIBANA_USAGE_TYPE); const kibanaUsage = (usageHeader && usagePayload) ? usagePayload : null; const reportingUsage = (reportingHeader && reportingPayload) ? reportingPayload : null; // this is an abstraction leak + const spacesUsage = (spacesHeader && spacesPayload) ? spacesPayload : null; //this is an abstraction leak + statsResult = [ statsHeader, { @@ -63,11 +67,14 @@ export function getCollectorTypesCombiner(kbnServer, config, _sourceKibana = sou if (reportingUsage) { set(statsResult, '[1].usage.xpack.reporting', reportingUsage); // this is an abstraction leak } + if (spacesUsage) { + set(statsResult, '[1].usage.xpack.spaces', spacesUsage); // this is an abstraction leak + } } // kibana settings let settingsResult; - const [ settingsHeader, settingsPayload ] = findItem(KIBANA_SETTINGS_TYPE); + const [settingsHeader, settingsPayload] = findItem(KIBANA_SETTINGS_TYPE); if (settingsHeader && settingsPayload) { settingsResult = [ settingsHeader, @@ -81,7 +88,7 @@ export function getCollectorTypesCombiner(kbnServer, config, _sourceKibana = sou // return new payload with the combined data // adds usage data to stats data // strips usage out as a top-level type - const result = [ statsResult, settingsResult ]; + const result = [statsResult, settingsResult]; // remove result items that are undefined return result.filter(Boolean); diff --git a/x-pack/plugins/xpack_main/server/routes/api/v1/kibana_stats.js b/x-pack/plugins/xpack_main/server/routes/api/v1/kibana_stats.js index 0ee49cb07214b..d6ce188263647 100644 --- a/x-pack/plugins/xpack_main/server/routes/api/v1/kibana_stats.js +++ b/x-pack/plugins/xpack_main/server/routes/api/v1/kibana_stats.js @@ -11,6 +11,7 @@ import { wrap } from 'boom'; import { callClusterFactory } from '../../../lib/call_cluster_factory'; import { getKibanaUsageCollector } from '../../../../../monitoring/server/kibana_monitoring/collectors'; import { getReportingUsageCollector } from '../../../../../reporting/server/usage'; +import { getSpacesUsageCollector } from '../../../../../spaces/server/lib/get_spaces_usage_collector'; export function kibanaStatsRoute(server) { server.route({ @@ -24,17 +25,20 @@ export function kibanaStatsRoute(server) { try { const kibanaUsageCollector = getKibanaUsageCollector(server); const reportingUsageCollector = getReportingUsageCollector(server); + const spacesUsageCollector = getSpacesUsageCollector(server); - const [ kibana, reporting ] = await Promise.all([ + const [kibana, reporting, spaces] = await Promise.all([ kibanaUsageCollector.fetch(callCluster), reportingUsageCollector.fetch(callCluster), + spacesUsageCollector.fetch(callCluster), ]); reply({ kibana, reporting, + spaces, }); - } catch(err) { + } catch (err) { req.log(['error'], err); if (err.isBoom) { From c3994bfd175cb747468ce2660a176c377f7a94a6 Mon Sep 17 00:00:00 2001 From: Larry Gregory Date: Thu, 19 Jul 2018 16:42:45 -0400 Subject: [PATCH 4/7] fix implementation to use new BulkUploader --- ...bulk_uploader.combine_stats_legacy.test.js | 19 +++++++-------- .../server/kibana_monitoring/bulk_uploader.js | 23 ++++++++++++------- x-pack/plugins/spaces/common/constants.js | 2 +- .../server/lib/get_spaces_usage_collector.js | 8 +++---- 4 files changed, 30 insertions(+), 22 deletions(-) diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/bulk_uploader.combine_stats_legacy.test.js b/x-pack/plugins/monitoring/server/kibana_monitoring/bulk_uploader.combine_stats_legacy.test.js index e44b8730510b5..3eaf1e3ea3d50 100644 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/bulk_uploader.combine_stats_legacy.test.js +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/bulk_uploader.combine_stats_legacy.test.js @@ -6,6 +6,7 @@ import { KIBANA_STATS_TYPE_MONITORING, KIBANA_USAGE_TYPE, KIBANA_SETTINGS_TYPE } from '../../common/constants'; import { KIBANA_REPORTING_TYPE } from '../../../reporting/common/constants'; +import { KIBANA_SPACES_MONITORING_TYPE } from '../../../spaces/common/constants'; import { BulkUploader } from './bulk_uploader'; const getInitial = () => { @@ -64,7 +65,7 @@ const getInitial = () => { } ], [ - { 'index': { '_type': 'spaces_stats' } }, + { 'index': { '_type': KIBANA_SPACES_MONITORING_TYPE } }, { 'available': true, 'enabled': true, @@ -157,10 +158,10 @@ describe('Collector Types Combiner', () => { it('provides combined stats/usage data', () => { // default gives all the data types const initial = getInitial(); - const trimmedInitial = [ initial[0], initial[1], initial[2] ]; // just stats, usage and reporting, no settings + const trimmedInitial = [initial[0], initial[1], initial[2], initial[3]]; // just stats, usage reporting, and spaces, no settings const result = BulkUploader.combineStatsLegacy(trimmedInitial); const expectedResult = getResult(); - const trimmedExpectedResult = [ expectedResult[0] ]; // single combined item + const trimmedExpectedResult = [expectedResult[0]]; // single combined item expect(result).toEqual(trimmedExpectedResult); }); }); @@ -168,11 +169,11 @@ describe('Collector Types Combiner', () => { it('provides settings, and stats data', () => { // default gives all the data types const initial = getInitial(); - const trimmedInitial = [ initial[0], initial[3] ]; // just stats and settings, no usage or reporting + const trimmedInitial = [initial[0], initial[4]]; // just stats and settings, no usage or reporting const result = BulkUploader.combineStatsLegacy(trimmedInitial); const expectedResult = getResult(); delete expectedResult[0][1].usage; // usage stats should not be present in the result - const trimmedExpectedResult = [ expectedResult[0], expectedResult[1] ]; + const trimmedExpectedResult = [expectedResult[0], expectedResult[1]]; expect(result).toEqual(trimmedExpectedResult); }); }); @@ -180,10 +181,10 @@ describe('Collector Types Combiner', () => { it('provides settings data', () => { // default gives all the data types const initial = getInitial(); - const trimmedInitial = [ initial[3] ]; // just settings + const trimmedInitial = [initial[4]]; // just settings const result = BulkUploader.combineStatsLegacy(trimmedInitial); const expectedResult = getResult(); - const trimmedExpectedResult = [ expectedResult[1] ]; // just settings + const trimmedExpectedResult = [expectedResult[1]]; // just settings expect(result).toEqual(trimmedExpectedResult); }); }); @@ -191,12 +192,12 @@ describe('Collector Types Combiner', () => { it('throws an error if duplicate types are registered', () => { const combineWithDuplicate = () => { const initial = getInitial(); - const withDuplicate = [ initial[0] ].concat(initial); + const withDuplicate = [initial[0]].concat(initial); return BulkUploader.combineStatsLegacy(withDuplicate); }; expect(combineWithDuplicate).toThrow( 'Duplicate collector type identifiers found in payload! ' + - 'kibana_stats_monitoring,kibana_stats_monitoring,kibana,reporting,kibana_settings' + 'kibana_stats_monitoring,kibana_stats_monitoring,kibana,reporting,spaces,kibana_settings' ); }); }); diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/bulk_uploader.js b/x-pack/plugins/monitoring/server/kibana_monitoring/bulk_uploader.js index c95baa056c8d6..0dda3fa0707f4 100644 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/bulk_uploader.js +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/bulk_uploader.js @@ -18,6 +18,7 @@ import { sendBulkPayload, monitoringBulk, } from './lib'; +import { KIBANA_SPACES_MONITORING_TYPE } from '../../../spaces/common/constants'; const LOGGING_TAGS = [LOGGING_TAG, KIBANA_MONITORING_LOGGING_TAG]; @@ -43,7 +44,7 @@ export class BulkUploader { throw new Error('interval number of milliseconds is required'); } - this._timer = null; + this._timer = null; this._interval = interval; this._log = { debug: message => server.log(['debug', ...LOGGING_TAGS], message), @@ -147,34 +148,40 @@ export class BulkUploader { // kibana usage and stats let statsResult; - const [ statsHeader, statsPayload ] = findItem(KIBANA_STATS_TYPE_MONITORING); - const [ reportingHeader, reportingPayload ] = findItem(KIBANA_REPORTING_TYPE); + const [statsHeader, statsPayload] = findItem(KIBANA_STATS_TYPE_MONITORING); + const [reportingHeader, reportingPayload] = findItem(KIBANA_REPORTING_TYPE); + const [spacesHeader, spacesPayload] = findItem(KIBANA_SPACES_MONITORING_TYPE); if (statsHeader && statsPayload) { statsHeader.index._type = 'kibana_stats'; // HACK to convert kibana_stats_monitoring to just kibana_stats for bwc - const [ usageHeader, usagePayload ] = findItem(KIBANA_USAGE_TYPE); + const [usageHeader, usagePayload] = findItem(KIBANA_USAGE_TYPE); const kibanaUsage = (usageHeader && usagePayload) ? usagePayload : null; const reportingUsage = (reportingHeader && reportingPayload) ? reportingPayload : null; - statsResult = [ statsHeader, statsPayload ]; + const spacesUsage = (spacesHeader && spacesPayload) ? spacesPayload : null; + statsResult = [statsHeader, statsPayload]; + if (kibanaUsage) { set(statsResult, '[1].usage', kibanaUsage); } if (reportingUsage) { set(statsResult, '[1].usage.xpack.reporting', reportingUsage); } + if (spacesUsage) { + set(statsResult, '[1].usage.xpack.spaces', spacesUsage); + } } // kibana settings let settingsResult; - const [ settingsHeader, settingsPayload ] = findItem(KIBANA_SETTINGS_TYPE); + const [settingsHeader, settingsPayload] = findItem(KIBANA_SETTINGS_TYPE); if (settingsHeader && settingsPayload) { - settingsResult = [ settingsHeader, settingsPayload ]; + settingsResult = [settingsHeader, settingsPayload]; } // return new payload with the combined data // adds usage data to stats data // strips usage out as a top-level type - const result = [ statsResult, settingsResult ]; + const result = [statsResult, settingsResult]; // remove result items that are undefined return result.filter(Boolean); diff --git a/x-pack/plugins/spaces/common/constants.js b/x-pack/plugins/spaces/common/constants.js index 2ebd080964c42..f55b49470e583 100644 --- a/x-pack/plugins/spaces/common/constants.js +++ b/x-pack/plugins/spaces/common/constants.js @@ -20,4 +20,4 @@ export const MAX_SPACE_INITIALS = 2; * The type name used within the Monitoring index to publish spaces stats. * @type {string} */ -export const KIBANA_SPACES_MONITORING_TYPE = 'spaces_stats'; +export const KIBANA_SPACES_MONITORING_TYPE = 'spaces'; diff --git a/x-pack/plugins/spaces/server/lib/get_spaces_usage_collector.js b/x-pack/plugins/spaces/server/lib/get_spaces_usage_collector.js index 303fbd89c2917..d835170eb20c7 100644 --- a/x-pack/plugins/spaces/server/lib/get_spaces_usage_collector.js +++ b/x-pack/plugins/spaces/server/lib/get_spaces_usage_collector.js @@ -40,14 +40,14 @@ export function getSpacesUsageCollector(server) { const xpackInfo = server.plugins.xpack_main.info; const config = server.config(); const available = xpackInfo && xpackInfo.isAvailable(); // some form of spaces is available for all valid licenses - const enabled = config.get('xpack.spaces.enabled'); // follow ES behavior: if its not available then its not enabled - const spacesAvailable = available && enabled; + const enabled = config.get('xpack.spaces.enabled'); + const spacesAvailableAndEnabled = available && enabled; - const usageStats = await getSpacesUsage(callCluster, server, spacesAvailable); + const usageStats = await getSpacesUsage(callCluster, server, spacesAvailableAndEnabled); return { available, - enabled: available && enabled, // similar behavior as _xpack API in ES + enabled: spacesAvailableAndEnabled, // similar behavior as _xpack API in ES ...usageStats, }; } From a970ca9de5bd88e42dbe70d856aac1dbdb55bee6 Mon Sep 17 00:00:00 2001 From: Larry Gregory Date: Fri, 20 Jul 2018 16:39:18 -0400 Subject: [PATCH 5/7] organize imports --- .../monitoring/server/kibana_monitoring/bulk_uploader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/bulk_uploader.js b/x-pack/plugins/monitoring/server/kibana_monitoring/bulk_uploader.js index 0dda3fa0707f4..ecd71b1fbf1ca 100644 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/bulk_uploader.js +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/bulk_uploader.js @@ -14,11 +14,11 @@ import { KIBANA_USAGE_TYPE, } from '../../common/constants'; import { KIBANA_REPORTING_TYPE } from '../../../reporting/common/constants'; +import { KIBANA_SPACES_MONITORING_TYPE } from '../../../spaces/common/constants'; import { sendBulkPayload, monitoringBulk, } from './lib'; -import { KIBANA_SPACES_MONITORING_TYPE } from '../../../spaces/common/constants'; const LOGGING_TAGS = [LOGGING_TAG, KIBANA_MONITORING_LOGGING_TAG]; From 361a2bec2e3cb217a27feaf006d9dbaa7ea3e827 Mon Sep 17 00:00:00 2001 From: Larry Gregory Date: Fri, 24 Aug 2018 10:28:20 -0400 Subject: [PATCH 6/7] implement formatForBulkUpload --- .../server/lib/get_spaces_usage_collector.js | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/x-pack/plugins/spaces/server/lib/get_spaces_usage_collector.js b/x-pack/plugins/spaces/server/lib/get_spaces_usage_collector.js index d835170eb20c7..e1bcce24da77c 100644 --- a/x-pack/plugins/spaces/server/lib/get_spaces_usage_collector.js +++ b/x-pack/plugins/spaces/server/lib/get_spaces_usage_collector.js @@ -5,6 +5,7 @@ */ import { KIBANA_SPACES_MONITORING_TYPE } from '../../common/constants'; +import { KIBANA_STATS_TYPE_MONITORING } from '../../../monitoring/common/constants'; /** * @@ -50,6 +51,25 @@ export function getSpacesUsageCollector(server) { enabled: spacesAvailableAndEnabled, // similar behavior as _xpack API in ES ...usageStats, }; + }, + + /* + * Format the response data into a model for internal upload + * 1. Make this data part of the "kibana_stats" type + * 2. Organize the payload in the usage.xpack.spaces namespace of the data payload + */ + formatForBulkUpload: result => { + return { + type: KIBANA_STATS_TYPE_MONITORING, + payload: { + usage: { + xpacl: { + spaces: result + } + } + } + }; + } }); } From 6a6539b30853b4eaaef58cf277fe5d53f179a2e5 Mon Sep 17 00:00:00 2001 From: Larry Gregory Date: Tue, 28 Aug 2018 09:03:37 -0400 Subject: [PATCH 7/7] start addressing PR feedback --- x-pack/plugins/spaces/common/constants.ts | 2 +- x-pack/plugins/spaces/index.js | 2 -- .../plugins/spaces/server/lib/get_spaces_usage_collector.js | 6 +++--- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/spaces/common/constants.ts b/x-pack/plugins/spaces/common/constants.ts index f55b49470e583..50423517bc918 100644 --- a/x-pack/plugins/spaces/common/constants.ts +++ b/x-pack/plugins/spaces/common/constants.ts @@ -20,4 +20,4 @@ export const MAX_SPACE_INITIALS = 2; * The type name used within the Monitoring index to publish spaces stats. * @type {string} */ -export const KIBANA_SPACES_MONITORING_TYPE = 'spaces'; +export const KIBANA_SPACES_STATS_TYPE = 'spaces'; diff --git a/x-pack/plugins/spaces/index.js b/x-pack/plugins/spaces/index.js index 485dd24201e45..2ce815db27db6 100644 --- a/x-pack/plugins/spaces/index.js +++ b/x-pack/plugins/spaces/index.js @@ -94,7 +94,5 @@ export const spaces = (kibana) => new kibana.Plugin({ // Register a function with server to manage the collection of usage stats server.usage.collectorSet.register(getSpacesUsageCollector(server)); - - await createDefaultSpace(server); } }); diff --git a/x-pack/plugins/spaces/server/lib/get_spaces_usage_collector.js b/x-pack/plugins/spaces/server/lib/get_spaces_usage_collector.js index e1bcce24da77c..455d2f0932b32 100644 --- a/x-pack/plugins/spaces/server/lib/get_spaces_usage_collector.js +++ b/x-pack/plugins/spaces/server/lib/get_spaces_usage_collector.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { KIBANA_SPACES_MONITORING_TYPE } from '../../common/constants'; +import { KIBANA_SPACES_STATS_TYPE } from '../../common/constants'; import { KIBANA_STATS_TYPE_MONITORING } from '../../../monitoring/common/constants'; /** @@ -36,7 +36,7 @@ async function getSpacesUsage(callCluster, server, spacesAvailable) { export function getSpacesUsageCollector(server) { const { collectorSet } = server.usage; return collectorSet.makeUsageCollector({ - type: KIBANA_SPACES_MONITORING_TYPE, + type: KIBANA_SPACES_STATS_TYPE, fetch: async callCluster => { const xpackInfo = server.plugins.xpack_main.info; const config = server.config(); @@ -63,7 +63,7 @@ export function getSpacesUsageCollector(server) { type: KIBANA_STATS_TYPE_MONITORING, payload: { usage: { - xpacl: { + xpack: { spaces: result } }