[Telemetry] Move to OSS (#45769)

* update paths and licenses

* localization collector in oss

* node-crypto typings in oss

* update telemetry i18n labels

* update translation rc files

* remove duplicate components in home for telemetry

* update tests

* finalize collection + move csp collector to oss

* self review

* use apm instead of beats

* xpack collection

* fix collection tests

* remove space specific settings

* mock npSetup and npStart

* disable banner in tests

* remove commented mock

* monitoring np telemetry fixes

* replace telemetryOptedIn in oss instead of xpack_main

* fix telemetry OptIn test
This commit is contained in:
Ahmad Bamieh 2019-10-16 10:24:20 +03:00 committed by GitHub
parent 68a2fdc7c3
commit a42a767285
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
155 changed files with 2128 additions and 1406 deletions

View file

@ -28,6 +28,7 @@
"kbnESQuery": "packages/kbn-es-query", "kbnESQuery": "packages/kbn-es-query",
"inspector": "src/plugins/inspector", "inspector": "src/plugins/inspector",
"kibana-react": "src/plugins/kibana_react", "kibana-react": "src/plugins/kibana_react",
"telemetry": "src/legacy/core_plugins/telemetry",
"esUi": "src/plugins/es_ui_shared", "esUi": "src/plugins/es_ui_shared",
"uiActions": "src/plugins/ui_actions" "uiActions": "src/plugins/ui_actions"
}, },

View file

@ -54,7 +54,7 @@ Specifies the password that {kib} uses for authentication when it retrieves data
from the monitoring cluster. If not set, {kib} uses the value of the from the monitoring cluster. If not set, {kib} uses the value of the
`elasticsearch.password` setting. `elasticsearch.password` setting.
`xpack.telemetry.enabled`:: `telemetry.enabled`::
Set to `true` (default) to send cluster statistics to Elastic. Reporting your Set to `true` (default) to send cluster statistics to Elastic. Reporting your
cluster statistics helps us improve your user experience. Your data is never cluster statistics helps us improve your user experience. Your data is never
shared with anyone. Set to `false` to disable statistics reporting from any shared with anyone. Set to `false` to disable statistics reporting from any

View file

@ -180,7 +180,7 @@ kibana_vars=(
xpack.security.encryptionKey xpack.security.encryptionKey
xpack.security.secureCookies xpack.security.secureCookies
xpack.security.sessionTimeout xpack.security.sessionTimeout
xpack.telemetry.enabled telemetry.enabled
) )
longopts='' longopts=''

View file

@ -38,6 +38,7 @@ import * as systemApi from './server/lib/system_api';
import mappings from './mappings.json'; import mappings from './mappings.json';
import { getUiSettingDefaults } from './ui_setting_defaults'; import { getUiSettingDefaults } from './ui_setting_defaults';
import { makeKQLUsageCollector } from './server/lib/kql_usage_collector'; import { makeKQLUsageCollector } from './server/lib/kql_usage_collector';
import { registerCspCollector } from './server/lib/csp_usage_collector';
import { injectVars } from './inject_vars'; import { injectVars } from './inject_vars';
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
@ -344,6 +345,7 @@ export default function (kibana) {
registerFieldFormats(server); registerFieldFormats(server);
registerTutorials(server); registerTutorials(server);
makeKQLUsageCollector(server); makeKQLUsageCollector(server);
registerCspCollector(server);
server.expose('systemApi', systemApi); server.expose('systemApi', systemApi);
server.injectUiAppVars('kibana', () => injectVars(server)); server.injectUiAppVars('kibana', () => injectVars(server));
}, },

View file

@ -24,7 +24,7 @@ import {
EuiCard, EuiCard,
EuiButton, EuiButton,
} from '@elastic/eui'; } from '@elastic/eui';
import { OptInMessage } from './opt_in_message'; import { OptInMessage } from '../../../../../telemetry/public/components/opt_in_message';
export interface Props { export interface Props {
urlBasePath: string; urlBasePath: string;

View file

@ -20,7 +20,7 @@
import { uiModules } from 'ui/modules'; import { uiModules } from 'ui/modules';
import { npStart } from 'ui/new_platform'; import { npStart } from 'ui/new_platform';
import { createUiStatsReporter, METRIC_TYPE } from '../../../ui_metric/public'; import { createUiStatsReporter, METRIC_TYPE } from '../../../ui_metric/public';
import { TelemetryOptInProvider } from './telemetry_opt_in'; import { TelemetryOptInProvider } from '../../../telemetry/public/services';
export let indexPatternService; export let indexPatternService;
export let shouldShowTelemetryOptIn; export let shouldShowTelemetryOptIn;

View file

@ -1,18 +1,35 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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 sinon from 'sinon'; import sinon from 'sinon';
import { DEFAULT_CSP_RULES } from '../../../../../../../../src/legacy/server/csp'; import { Server } from 'hapi';
import { import { DEFAULT_CSP_RULES } from '../../../../../server/csp';
getMockCallWithInternal,
getMockKbnServer,
getMockTaskFetch,
} from '../../../../test_utils';
import { createCspCollector } from './csp_collector'; import { createCspCollector } from './csp_collector';
interface MockConfig {
get: (x: string) => any;
}
const getMockKbnServer = (mockConfig: MockConfig) => ({
config: () => mockConfig,
});
test('fetches whether strict mode is enabled', async () => { test('fetches whether strict mode is enabled', async () => {
const { collector, mockConfig } = setupCollector(); const { collector, mockConfig } = setupCollector();
@ -72,7 +89,7 @@ function setupCollector() {
mockConfig.get.withArgs('csp.strict').returns(true); mockConfig.get.withArgs('csp.strict').returns(true);
mockConfig.get.withArgs('csp.warnLegacyBrowsers').returns(true); mockConfig.get.withArgs('csp.warnLegacyBrowsers').returns(true);
const mockKbnServer = getMockKbnServer(getMockCallWithInternal(), getMockTaskFetch(), mockConfig); const mockKbnServer = getMockKbnServer(mockConfig);
return { mockConfig, collector: createCspCollector(mockKbnServer) }; return { mockConfig, collector: createCspCollector(mockKbnServer as Server) };
} }

View file

@ -0,0 +1,49 @@
/*
* 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 { Server } from 'hapi';
import { createCSPRuleString, DEFAULT_CSP_RULES } from '../../../../../server/csp';
export function createCspCollector(server: Server) {
return {
type: 'csp',
isReady: () => true,
async fetch() {
const config = server.config();
// It's important that we do not send the value of csp.rules here as it
// can be customized with values that can be identifiable to given
// installs, such as URLs
const defaultRulesString = createCSPRuleString([...DEFAULT_CSP_RULES]);
const actualRulesString = createCSPRuleString(config.get('csp.rules'));
return {
strict: config.get('csp.strict'),
warnLegacyBrowsers: config.get('csp.warnLegacyBrowsers'),
rulesChangedFromDefault: defaultRulesString !== actualRulesString,
};
},
};
}
export function registerCspCollector(server: Server): void {
const { collectorSet } = server.usage;
const collector = collectorSet.makeUsageCollector(createCspCollector(server));
collectorSet.register(collector);
}

View file

@ -0,0 +1,20 @@
/*
* 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 { registerCspCollector } from './csp_collector';

View file

@ -0,0 +1,66 @@
/*
* 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 { i18n } from '@kbn/i18n';
/*
* config options opt into telemetry
* @type {string}
*/
export const CONFIG_TELEMETRY = 'telemetry:optIn';
/*
* config description for opting into telemetry
* @type {string}
*/
export const getConfigTelemetryDesc = () => {
return i18n.translate('telemetry.telemetryConfigDescription', {
defaultMessage:
'Help us improve the Elastic Stack by providing usage statistics for basic features. We will not share this data outside of Elastic.',
});
};
/**
* The amount of time, in milliseconds, to wait between reports when enabled.
*
* Currently 24 hours.
* @type {Number}
*/
export const REPORT_INTERVAL_MS = 86400000;
/*
* Key for the localStorage service
*/
export const LOCALSTORAGE_KEY = 'telemetry.data';
/**
* Link to the Elastic Telemetry privacy statement.
*/
export const PRIVACY_STATEMENT_URL = `https://www.elastic.co/legal/telemetry-privacy-statement`;
/**
* The type name used within the Monitoring index to publish localization stats.
* @type {string}
*/
export const KIBANA_LOCALIZATION_STATS_TYPE = 'localization';
/**
* UI metric usage type
* @type {string}
*/
export const UI_METRIC_USAGE_TYPE = 'ui_metric';

View file

@ -0,0 +1,41 @@
/*
* 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 { KibanaConfig } from 'src/legacy/server/kbn_server';
export function getXpackConfigWithDeprecated(config: KibanaConfig, configPath: string) {
try {
const deprecatedXpackmainConfig = config.get(`xpack.xpack_main.${configPath}`);
if (typeof deprecatedXpackmainConfig !== 'undefined') {
return deprecatedXpackmainConfig;
}
} catch (err) {
// swallow error
}
try {
const deprecatedXpackConfig = config.get(`xpack.${configPath}`);
if (typeof deprecatedXpackConfig !== 'undefined') {
return deprecatedXpackConfig;
}
} catch (err) {
// swallow error
}
return config.get(configPath);
}

View file

@ -1,7 +1,20 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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 { resolve } from 'path'; import { resolve } from 'path';
@ -9,10 +22,11 @@ import JoiNamespace from 'joi';
import { Server } from 'hapi'; import { Server } from 'hapi';
import { CoreSetup, PluginInitializerContext } from 'src/core/server'; import { CoreSetup, PluginInitializerContext } from 'src/core/server';
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
// @ts-ignore
import mappings from './mappings.json'; import mappings from './mappings.json';
import { CONFIG_TELEMETRY, getConfigTelemetryDesc, REPORT_INTERVAL_MS } from './common/constants'; import { CONFIG_TELEMETRY, getConfigTelemetryDesc } from './common/constants';
import { getXpackConfigWithDeprecated } from './common/get_xpack_config_with_deprecated'; import { getXpackConfigWithDeprecated } from './common/get_xpack_config_with_deprecated';
import { telemetryPlugin } from './server'; import { telemetryPlugin, getTelemetryOptIn } from './server';
import { import {
createLocalizationUsageCollector, createLocalizationUsageCollector,
@ -22,10 +36,10 @@ import {
const ENDPOINT_VERSION = 'v2'; const ENDPOINT_VERSION = 'v2';
export const telemetry = (kibana: any) => { const telemetry = (kibana: any) => {
return new kibana.Plugin({ return new kibana.Plugin({
id: 'telemetry', id: 'telemetry',
configPrefix: 'xpack.telemetry', configPrefix: 'telemetry',
publicDir: resolve(__dirname, 'public'), publicDir: resolve(__dirname, 'public'),
require: ['elasticsearch'], require: ['elasticsearch'],
config(Joi: typeof JoiNamespace) { config(Joi: typeof JoiNamespace) {
@ -49,7 +63,7 @@ export const telemetry = (kibana: any) => {
managementSections: ['plugins/telemetry/views/management'], managementSections: ['plugins/telemetry/views/management'],
uiSettingDefaults: { uiSettingDefaults: {
[CONFIG_TELEMETRY]: { [CONFIG_TELEMETRY]: {
name: i18n.translate('xpack.telemetry.telemetryConfigTitle', { name: i18n.translate('telemetry.telemetryConfigTitle', {
defaultMessage: 'Telemetry opt-in', defaultMessage: 'Telemetry opt-in',
}), }),
description: getConfigTelemetryDesc(), description: getConfigTelemetryDesc(),
@ -62,11 +76,20 @@ export const telemetry = (kibana: any) => {
isNamespaceAgnostic: true, isNamespaceAgnostic: true,
}, },
}, },
async replaceInjectedVars(originalInjectedVars: any, request: any) {
const telemetryOptedIn = await getTelemetryOptIn(request);
return {
...originalInjectedVars,
telemetryOptedIn,
};
},
injectDefaultVars(server: Server) { injectDefaultVars(server: Server) {
const config = server.config(); const config = server.config();
return { return {
telemetryEnabled: getXpackConfigWithDeprecated(config, 'telemetry.enabled'),
telemetryUrl: getXpackConfigWithDeprecated(config, 'telemetry.url'), telemetryUrl: getXpackConfigWithDeprecated(config, 'telemetry.url'),
telemetryBanner: config.get('xpack.telemetry.banner'), telemetryBanner: getXpackConfigWithDeprecated(config, 'telemetry.banner'),
telemetryOptedIn: null, telemetryOptedIn: null,
}; };
}, },
@ -75,8 +98,10 @@ export const telemetry = (kibana: any) => {
}, },
init(server: Server) { init(server: Server) {
const initializerContext = {} as PluginInitializerContext; const initializerContext = {} as PluginInitializerContext;
const coreSetup = ({ const coreSetup = ({
http: { server }, http: { server },
log: server.log,
} as any) as CoreSetup; } as any) as CoreSetup;
telemetryPlugin(initializerContext).setup(coreSetup); telemetryPlugin(initializerContext).setup(coreSetup);
@ -85,9 +110,9 @@ export const telemetry = (kibana: any) => {
server.usage.collectorSet.register(createLocalizationUsageCollector(server)); server.usage.collectorSet.register(createLocalizationUsageCollector(server));
server.usage.collectorSet.register(createTelemetryUsageCollector(server)); server.usage.collectorSet.register(createTelemetryUsageCollector(server));
server.usage.collectorSet.register(createUiMetricUsageCollector(server)); server.usage.collectorSet.register(createUiMetricUsageCollector(server));
// expose
server.expose('telemetryCollectionInterval', REPORT_INTERVAL_MS);
}, },
}); });
}; };
// eslint-disable-next-line import/no-default-export
export default telemetry;

View file

@ -0,0 +1,4 @@
{
"name": "telemetry",
"version": "kibana"
}

View file

@ -15,7 +15,7 @@ exports[`OptInDetailsComponent renders as expected 1`] = `
<h2> <h2>
<FormattedMessage <FormattedMessage
defaultMessage="Cluster statistics" defaultMessage="Cluster statistics"
id="xpack.telemetry.callout.clusterStatisticsTitle" id="telemetry.callout.clusterStatisticsTitle"
values={Object {}} values={Object {}}
/> />
</h2> </h2>
@ -26,7 +26,7 @@ exports[`OptInDetailsComponent renders as expected 1`] = `
<EuiText> <EuiText>
<FormattedMessage <FormattedMessage
defaultMessage="This is an example of the basic cluster statistics that we'll collect. It includes the number of indices, shards, and nodes. It also includes high-level usage statistics, such as whether monitoring is turned on." defaultMessage="This is an example of the basic cluster statistics that we'll collect. It includes the number of indices, shards, and nodes. It also includes high-level usage statistics, such as whether monitoring is turned on."
id="xpack.telemetry.callout.clusterStatisticsDescription" id="telemetry.callout.clusterStatisticsDescription"
values={Object {}} values={Object {}}
/> />
</EuiText> </EuiText>

View file

@ -16,7 +16,7 @@ exports[`TelemetryForm renders as expected 1`] = `
<h2> <h2>
<FormattedMessage <FormattedMessage
defaultMessage="Usage Data" defaultMessage="Usage Data"
id="xpack.telemetry.usageDataTitle" id="telemetry.usageDataTitle"
values={Object {}} values={Object {}}
/> />
</h2> </h2>
@ -43,7 +43,7 @@ exports[`TelemetryForm renders as expected 1`] = `
> >
<FormattedMessage <FormattedMessage
defaultMessage="See an example of what we collect" defaultMessage="See an example of what we collect"
id="xpack.telemetry.seeExampleOfWhatWeCollectLinkText" id="telemetry.seeExampleOfWhatWeCollectLinkText"
values={Object {}} values={Object {}}
/> />
</ForwardRef> </ForwardRef>
@ -55,7 +55,7 @@ exports[`TelemetryForm renders as expected 1`] = `
> >
<FormattedMessage <FormattedMessage
defaultMessage="Read our usage data privacy statement" defaultMessage="Read our usage data privacy statement"
id="xpack.telemetry.readOurUsageDataPrivacyStatementLinkText" id="telemetry.readOurUsageDataPrivacyStatementLinkText"
values={Object {}} values={Object {}}
/> />
</ForwardRef> </ForwardRef>

View file

@ -0,0 +1,24 @@
/*
* 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.
*/
// @ts-ignore
export { TelemetryForm } from './telemetry_form';
export { OptInExampleFlyout } from './opt_in_details_component';
export { OptInBanner } from './opt_in_banner_component';
export { OptInMessage } from './opt_in_message';

View file

@ -1,7 +1,20 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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 * as React from 'react'; import * as React from 'react';
@ -21,7 +34,7 @@ export class OptInBanner extends React.PureComponent<Props> {
render() { render() {
const title = ( const title = (
<FormattedMessage <FormattedMessage
id="xpack.telemetry.welcomeBanner.title" id="telemetry.welcomeBanner.title"
defaultMessage="Help us improve the Elastic Stack!" defaultMessage="Help us improve the Elastic Stack!"
/> />
); );
@ -32,18 +45,12 @@ export class OptInBanner extends React.PureComponent<Props> {
<EuiFlexGroup gutterSize="s" alignItems="center"> <EuiFlexGroup gutterSize="s" alignItems="center">
<EuiFlexItem grow={false}> <EuiFlexItem grow={false}>
<EuiButton size="s" onClick={() => this.props.optInClick(true)}> <EuiButton size="s" onClick={() => this.props.optInClick(true)}>
<FormattedMessage <FormattedMessage id="telemetry.welcomeBanner.yesButtonLabel" defaultMessage="Yes" />
id="xpack.telemetry.welcomeBanner.yesButtonLabel"
defaultMessage="Yes"
/>
</EuiButton> </EuiButton>
</EuiFlexItem> </EuiFlexItem>
<EuiFlexItem grow={false}> <EuiFlexItem grow={false}>
<EuiButton size="s" onClick={() => this.props.optInClick(false)}> <EuiButton size="s" onClick={() => this.props.optInClick(false)}>
<FormattedMessage <FormattedMessage id="telemetry.welcomeBanner.noButtonLabel" defaultMessage="No" />
id="xpack.telemetry.welcomeBanner.noButtonLabel"
defaultMessage="No"
/>
</EuiButton> </EuiButton>
</EuiFlexItem> </EuiFlexItem>
</EuiFlexGroup> </EuiFlexGroup>

View file

@ -0,0 +1,34 @@
/*
* 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 React from 'react';
import { shallowWithIntl } from 'test_utils/enzyme_helpers';
import { OptInExampleFlyout } from './opt_in_details_component';
describe('OptInDetailsComponent', () => {
it('renders as expected', () => {
expect(
shallowWithIntl(
<OptInExampleFlyout
fetchTelemetry={jest.fn(async () => ({ data: [] }))}
onClose={jest.fn()}
/>
)
).toMatchSnapshot();
});
});

View file

@ -91,7 +91,7 @@ export class OptInExampleFlyout extends React.PureComponent<Props, State> {
<EuiCallOut <EuiCallOut
title={ title={
<FormattedMessage <FormattedMessage
id="kbn.home.telemetry.callout.errorUnprivilegedUserTitle" id="telemetry.callout.errorUnprivilegedUserTitle"
defaultMessage="Error displaying cluster statistics" defaultMessage="Error displaying cluster statistics"
/> />
} }
@ -99,7 +99,7 @@ export class OptInExampleFlyout extends React.PureComponent<Props, State> {
iconType="cross" iconType="cross"
> >
<FormattedMessage <FormattedMessage
id="kbn.home.telemetry.callout.errorUnprivilegedUserDescription" id="telemetry.callout.errorUnprivilegedUserDescription"
defaultMessage="You do not have access to see unencrypted cluster statistics." defaultMessage="You do not have access to see unencrypted cluster statistics."
/> />
</EuiCallOut> </EuiCallOut>
@ -111,7 +111,7 @@ export class OptInExampleFlyout extends React.PureComponent<Props, State> {
<EuiCallOut <EuiCallOut
title={ title={
<FormattedMessage <FormattedMessage
id="kbn.home.telemetry.callout.errorLoadingClusterStatisticsTitle" id="telemetry.callout.errorLoadingClusterStatisticsTitle"
defaultMessage="Error loading cluster statistics" defaultMessage="Error loading cluster statistics"
/> />
} }
@ -119,7 +119,7 @@ export class OptInExampleFlyout extends React.PureComponent<Props, State> {
iconType="cross" iconType="cross"
> >
<FormattedMessage <FormattedMessage
id="kbn.home.telemetry.callout.errorLoadingClusterStatisticsDescription" id="telemetry.callout.errorLoadingClusterStatisticsDescription"
defaultMessage="An unexpected error occured while attempting to fetch the cluster statistics. defaultMessage="An unexpected error occured while attempting to fetch the cluster statistics.
This can occur because Elasticsearch failed, Kibana failed, or there is a network error. This can occur because Elasticsearch failed, Kibana failed, or there is a network error.
Check Kibana, then reload the page and try again." Check Kibana, then reload the page and try again."
@ -139,7 +139,7 @@ export class OptInExampleFlyout extends React.PureComponent<Props, State> {
<EuiTitle> <EuiTitle>
<h2> <h2>
<FormattedMessage <FormattedMessage
id="kbn.home.telemetry.callout.clusterStatisticsTitle" id="telemetry.callout.clusterStatisticsTitle"
defaultMessage="Cluster statistics" defaultMessage="Cluster statistics"
/> />
</h2> </h2>
@ -147,7 +147,7 @@ export class OptInExampleFlyout extends React.PureComponent<Props, State> {
<EuiTextColor color="subdued"> <EuiTextColor color="subdued">
<EuiText> <EuiText>
<FormattedMessage <FormattedMessage
id="kbn.home.telemetry.callout.clusterStatisticsDescription" id="telemetry.callout.clusterStatisticsDescription"
defaultMessage="This is an example of the basic cluster statistics that we'll collect. defaultMessage="This is an example of the basic cluster statistics that we'll collect.
It includes the number of indices, shards, and nodes. It includes the number of indices, shards, and nodes.
It also includes high-level usage statistics, such as whether monitoring is turned on." It also includes high-level usage statistics, such as whether monitoring is turned on."

View file

@ -20,6 +20,8 @@
import * as React from 'react'; import * as React from 'react';
import { EuiLink } from '@elastic/eui'; import { EuiLink } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react'; import { FormattedMessage } from '@kbn/i18n/react';
import { getConfigTelemetryDesc, PRIVACY_STATEMENT_URL } from '../../common/constants';
import { OptInExampleFlyout } from './opt_in_details_component'; import { OptInExampleFlyout } from './opt_in_details_component';
interface Props { interface Props {
@ -44,29 +46,27 @@ export class OptInMessage extends React.PureComponent<Props, State> {
}; };
render() { render() {
const { fetchTelemetry } = this.props;
const { showDetails, showExample } = this.state; const { showDetails, showExample } = this.state;
const getDetails = () => ( const getDetails = () => (
<FormattedMessage <FormattedMessage
id="kbn.home.telemetry.optInMessage.detailsDescription" id="telemetry.welcomeBanner.telemetryConfigDetailsDescription"
defaultMessage="No information about the data you process or store will be sent. This feature will periodically send basic feature usage statistics. See an {exampleLink} or read our {telemetryPrivacyStatementLink}. You can disable this feature at any time." defaultMessage="No information about the data you process or store will be sent. This feature
will periodically send basic feature usage statistics. See an {exampleLink} or read our {telemetryPrivacyStatementLink}.
You can disable this feature at any time."
values={{ values={{
exampleLink: ( exampleLink: (
<EuiLink onClick={this.toggleShowExample}> <EuiLink onClick={this.toggleShowExample}>
<FormattedMessage <FormattedMessage
id="kbn.home.telemetry.optInMessage.detailsExampleLinkText" id="telemetry.welcomeBanner.telemetryConfigDetailsDescription.exampleLinkText"
defaultMessage="example" defaultMessage="example"
/> />
</EuiLink> </EuiLink>
), ),
telemetryPrivacyStatementLink: ( telemetryPrivacyStatementLink: (
<EuiLink <EuiLink href={PRIVACY_STATEMENT_URL} target="_blank">
href="https://www.elastic.co/legal/telemetry-privacy-statement"
target="_blank"
>
<FormattedMessage <FormattedMessage
id="kbn.home.telemetry.optInMessage.detailsTelemetryPrivacyStatementLinkText" id="telemetry.welcomeBanner.telemetryConfigDetailsDescription.telemetryPrivacyStatementLinkText"
defaultMessage="telemetry privacy statement" defaultMessage="telemetry privacy statement"
/> />
</EuiLink> </EuiLink>
@ -78,14 +78,14 @@ export class OptInMessage extends React.PureComponent<Props, State> {
const getFlyoutDetails = () => ( const getFlyoutDetails = () => (
<OptInExampleFlyout <OptInExampleFlyout
onClose={() => this.setState({ showExample: false })} onClose={() => this.setState({ showExample: false })}
fetchTelemetry={fetchTelemetry} fetchTelemetry={this.props.fetchTelemetry}
/> />
); );
const getReadMore = () => ( const getReadMore = () => (
<EuiLink onClick={() => this.setState({ showDetails: true })}> <EuiLink onClick={() => this.setState({ showDetails: true })}>
<FormattedMessage <FormattedMessage
id="kbn.home.telemetry.optInMessage.readMoreLinkText" id="telemetry.welcomeBanner.telemetryConfigDescription.readMoreLinkText"
defaultMessage="Read more" defaultMessage="Read more"
/> />
</EuiLink> </EuiLink>
@ -93,13 +93,13 @@ export class OptInMessage extends React.PureComponent<Props, State> {
return ( return (
<React.Fragment> <React.Fragment>
<FormattedMessage {getConfigTelemetryDesc()} {!showDetails && getReadMore()}
id="kbn.home.telemetry.optInMessageDescription" {showDetails && (
defaultMessage="Help us improve the Elastic Stack by providing usage statistics for basic features. We will not share this data outside of Elastic." <span style={{ display: 'block', paddingTop: '10px' }}>
/>{' '} {getDetails()}
{!showDetails && getReadMore()} {showExample && getFlyoutDetails()}
{showDetails && getDetails()} </span>
{showDetails && showExample && getFlyoutDetails()} )}
</React.Fragment> </React.Fragment>
); );
} }

View file

@ -1,7 +1,20 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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 React, { Component, Fragment } from 'react'; import React, { Component, Fragment } from 'react';
@ -28,8 +41,7 @@ export class TelemetryForm extends Component {
telemetryOptInProvider: PropTypes.object.isRequired, telemetryOptInProvider: PropTypes.object.isRequired,
query: PropTypes.object, query: PropTypes.object,
onQueryMatchChange: PropTypes.func.isRequired, onQueryMatchChange: PropTypes.func.isRequired,
spacesEnabled: PropTypes.bool.isRequired, showAppliesSettingMessage: PropTypes.bool.isRequired,
activeSpace: PropTypes.object,
enableSaving: PropTypes.bool.isRequired, enableSaving: PropTypes.bool.isRequired,
}; };
@ -85,7 +97,7 @@ export class TelemetryForm extends Component {
<EuiFlexItem grow={false}> <EuiFlexItem grow={false}>
<h2> <h2>
<FormattedMessage <FormattedMessage
id="xpack.telemetry.usageDataTitle" id="telemetry.usageDataTitle"
defaultMessage="Usage Data" defaultMessage="Usage Data"
/> />
</h2> </h2>
@ -93,7 +105,7 @@ export class TelemetryForm extends Component {
</EuiFlexGroup> </EuiFlexGroup>
</EuiText> </EuiText>
{this.maybeGetSpacesWarning()} {this.maybeGetAppliesSettingMessage()}
<EuiSpacer size="s" /> <EuiSpacer size="s" />
<Field <Field
setting={{ setting={{
@ -112,8 +124,8 @@ export class TelemetryForm extends Component {
); );
} }
maybeGetSpacesWarning = () => { maybeGetAppliesSettingMessage = () => {
if (!this.props.spacesEnabled) { if (!this.props.showAppliesSettingMessage) {
return null; return null;
} }
return ( return (
@ -123,13 +135,13 @@ export class TelemetryForm extends Component {
title={ title={
<p> <p>
<FormattedMessage <FormattedMessage
id="xpack.telemetry.callout.appliesSettingTitle" id="telemetry.callout.appliesSettingTitle"
defaultMessage="This setting applies to {allOfKibanaText}" defaultMessage="This setting applies to {allOfKibanaText}"
values={{ values={{
allOfKibanaText: ( allOfKibanaText: (
<strong> <strong>
<FormattedMessage <FormattedMessage
id="xpack.telemetry.callout.appliesSettingTitle.allOfKibanaText" id="telemetry.callout.appliesSettingTitle.allOfKibanaText"
defaultMessage="all of Kibana." defaultMessage="all of Kibana."
/> />
</strong> </strong>
@ -148,7 +160,7 @@ export class TelemetryForm extends Component {
<p> <p>
<EuiLink onClick={this.toggleExample}> <EuiLink onClick={this.toggleExample}>
<FormattedMessage <FormattedMessage
id="xpack.telemetry.seeExampleOfWhatWeCollectLinkText" id="telemetry.seeExampleOfWhatWeCollectLinkText"
defaultMessage="See an example of what we collect" defaultMessage="See an example of what we collect"
/> />
</EuiLink> </EuiLink>
@ -156,7 +168,7 @@ export class TelemetryForm extends Component {
<p> <p>
<EuiLink href={PRIVACY_STATEMENT_URL} target="_blank"> <EuiLink href={PRIVACY_STATEMENT_URL} target="_blank">
<FormattedMessage <FormattedMessage
id="xpack.telemetry.readOurUsageDataPrivacyStatementLinkText" id="telemetry.readOurUsageDataPrivacyStatementLinkText"
defaultMessage="Read our usage data privacy statement" defaultMessage="Read our usage data privacy statement"
/> />
</EuiLink> </EuiLink>

View file

@ -1,14 +1,27 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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 '../services/telemetry_opt_in.test.mocks'; import '../services/telemetry_opt_in.test.mocks';
import React from 'react'; import React from 'react';
import { shallowWithIntl } from 'test_utils/enzyme_helpers'; import { shallowWithIntl } from 'test_utils/enzyme_helpers';
import { TelemetryForm } from './telemetry_form'; import { TelemetryForm } from './telemetry_form';
import { TelemetryOptInProvider } from '../services/telemetry_opt_in'; import { TelemetryOptInProvider } from '../services';
const buildTelemetryOptInProvider = () => { const buildTelemetryOptInProvider = () => {
const mockHttp = { const mockHttp = {

View file

@ -1,7 +1,20 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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 expect from '@kbn/expect'; import expect from '@kbn/expect';

View file

@ -0,0 +1,28 @@
/*
* 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 { uiModules } from 'ui/modules';
// This overrides settings for other UI tests
uiModules.get('kibana')
// disable stat reporting while running tests,
// MockInjector used in these tests is not impacted
.constant('telemetryEnabled', false)
.constant('telemetryOptedIn', null)
.constant('telemetryUrl', 'not.a.valid.url.0');

View file

@ -0,0 +1,39 @@
/*
* 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 uiChrome from 'ui/chrome';
import moment from 'moment';
/**
* Fetch Telemetry data by calling the Kibana API.
*
* @param {Object} $http The HTTP handler
* @param {String} basePath The base URI
* @param {Function} _moment moment.js, but injectable for tests
* @return {Promise} An array of cluster Telemetry objects.
*/
export function fetchTelemetry($http, { basePath = uiChrome.getBasePath(), _moment = moment, unencrypted = false } = { }) {
return $http.post(`${basePath}/api/telemetry/v2/clusters/_stats`, {
unencrypted,
timeRange: {
min: _moment().subtract(20, 'minutes').toISOString(),
max: _moment().toISOString()
}
});
}

View file

@ -1,7 +1,20 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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 { import {

View file

@ -1,7 +1,20 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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 { Telemetry } from './telemetry'; import { Telemetry } from './telemetry';

View file

@ -0,0 +1,45 @@
/*
* 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 { npStart } from 'ui/new_platform';
// @ts-ignore
import { uiModules } from 'ui/modules';
import { isUnauthenticated } from '../services';
// @ts-ignore
import { Telemetry } from './telemetry';
// @ts-ignore
import { fetchTelemetry } from './fetch_telemetry';
function telemetryInit($injector: any) {
const $http = $injector.get('$http');
const telemetryEnabled = npStart.core.injectedMetadata.getInjectedVar('telemetryEnabled');
if (telemetryEnabled) {
// no telemetry for non-logged in users
if (isUnauthenticated()) {
return;
}
const sender = new Telemetry($injector, () => fetchTelemetry($http));
sender.start();
}
}
uiModules.get('telemetry/hacks').run(telemetryInit);

View file

@ -0,0 +1,24 @@
/*
* 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 { uiModules } from 'ui/modules';
import { injectBanner } from './welcome_banner';
uiModules.get('telemetry/hacks').run(injectBanner);

View file

@ -1,7 +1,20 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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 React from 'react'; import React from 'react';
@ -41,7 +54,7 @@ export async function clickBanner(
_toastNotifications.addDanger({ _toastNotifications.addDanger({
title: ( title: (
<FormattedMessage <FormattedMessage
id="xpack.telemetry.telemetryErrorNotificationMessageTitle" id="telemetry.telemetryErrorNotificationMessageTitle"
defaultMessage="Telemetry Error" defaultMessage="Telemetry Error"
/> />
), ),
@ -49,13 +62,13 @@ export async function clickBanner(
<EuiText> <EuiText>
<p> <p>
<FormattedMessage <FormattedMessage
id="xpack.telemetry.telemetryErrorNotificationMessageDescription.unableToSaveTelemetryPreferenceText" id="telemetry.telemetryErrorNotificationMessageDescription.unableToSaveTelemetryPreferenceText"
defaultMessage="Unable to save telemetry preference." defaultMessage="Unable to save telemetry preference."
/> />
</p> </p>
<EuiText size="xs"> <EuiText size="xs">
<FormattedMessage <FormattedMessage
id="xpack.telemetry.telemetryErrorNotificationMessageDescription.tryAgainText" id="telemetry.telemetryErrorNotificationMessageDescription.tryAgainText"
defaultMessage="Check that Kibana and Elasticsearch are still running, then try again." defaultMessage="Check that Kibana and Elasticsearch are still running, then try again."
/> />
</EuiText> </EuiText>

View file

@ -1,7 +1,20 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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 { mockInjectedMetadata } from '../../services/telemetry_opt_in.test.mocks'; import { mockInjectedMetadata } from '../../services/telemetry_opt_in.test.mocks';

View file

@ -1,7 +1,20 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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 { CONFIG_TELEMETRY } from '../../../common/constants'; import { CONFIG_TELEMETRY } from '../../../common/constants';

View file

@ -1,7 +1,20 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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 { mockInjectedMetadata } from '../../services/telemetry_opt_in.test.mocks'; import { mockInjectedMetadata } from '../../services/telemetry_opt_in.test.mocks';

View file

@ -0,0 +1,20 @@
/*
* 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 { injectBanner } from './inject_banner';

View file

@ -1,15 +1,28 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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 chrome from 'ui/chrome'; import chrome from 'ui/chrome';
import { Path } from 'plugins/xpack_main/services/path';
import { fetchTelemetry } from '../fetch_telemetry'; import { fetchTelemetry } from '../fetch_telemetry';
import { renderBanner } from './render_banner'; import { renderBanner } from './render_banner';
import { shouldShowBanner } from './should_show_banner'; import { shouldShowBanner } from './should_show_banner';
import { TelemetryOptInProvider } from '../../services/telemetry_opt_in'; import { TelemetryOptInProvider, isUnauthenticated } from '../../services';
import { npStart } from 'ui/new_platform'; import { npStart } from 'ui/new_platform';
/** /**
@ -26,7 +39,7 @@ async function asyncInjectBanner($injector) {
const config = $injector.get('config'); const config = $injector.get('config');
// and no banner for non-logged in users // and no banner for non-logged in users
if (Path.isUnauthenticated()) { if (isUnauthenticated()) {
return; return;
} }

View file

@ -1,7 +1,20 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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 React from 'react'; import React from 'react';

View file

@ -0,0 +1,44 @@
/*
* 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 '../../services/telemetry_opt_in.test.mocks';
import { renderBanner } from './render_banner';
describe('render_banner', () => {
it('adds a banner to banners with priority of 10000', () => {
const bannerID = 'brucer-banner';
const telemetryOptInProvider = { setBannerId: jest.fn() };
const banners = { add: jest.fn().mockReturnValue(bannerID) };
const fetchTelemetry = jest.fn();
renderBanner(telemetryOptInProvider, fetchTelemetry, { _banners: banners });
expect(banners.add).toBeCalledTimes(1);
expect(fetchTelemetry).toBeCalledTimes(0);
expect(telemetryOptInProvider.setBannerId).toBeCalledWith(bannerID);
const bannerConfig = banners.add.mock.calls[0][0];
expect(bannerConfig.component).not.toBe(undefined);
expect(bannerConfig.priority).toBe(10000);
});
});

View file

@ -0,0 +1,33 @@
/*
* 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 { handleOldSettings } from './handle_old_settings';
/**
* Determine if the banner should be displayed.
*
* This method can have side-effects related to deprecated config settings.
*
* @param {Object} config The advanced settings config object.
* @param {Object} _handleOldSettings handleOldSettings function, but overridable for tests.
* @return {Boolean} {@code true} if the banner should be displayed. {@code false} otherwise.
*/
export async function shouldShowBanner(telemetryOptInProvider, config, { _handleOldSettings = handleOldSettings } = {}) {
return telemetryOptInProvider.getOptIn() === null && await _handleOldSettings(config, telemetryOptInProvider);
}

View file

@ -1,7 +1,20 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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 { mockInjectedMetadata } from '../../services/telemetry_opt_in.test.mocks'; import { mockInjectedMetadata } from '../../services/telemetry_opt_in.test.mocks';
@ -10,7 +23,7 @@ import sinon from 'sinon';
import { CONFIG_TELEMETRY } from '../../../common/constants'; import { CONFIG_TELEMETRY } from '../../../common/constants';
import { shouldShowBanner } from './should_show_banner'; import { shouldShowBanner } from './should_show_banner';
import { TelemetryOptInProvider } from '../../services/telemetry_opt_in'; import { TelemetryOptInProvider } from '../../services';
const getMockInjector = () => { const getMockInjector = () => {
const get = sinon.stub(); const get = sinon.stub();

View file

@ -0,0 +1,21 @@
/*
* 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 { TelemetryOptInProvider } from './telemetry_opt_in';
export { isUnauthenticated } from './path';

View file

@ -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.
*/
import chrome from 'ui/chrome';
export function isUnauthenticated() {
const path = (chrome as any).removeBasePath(window.location.pathname);
return path === '/login' || path === '/logout' || path === '/logged_out' || path === '/status';
}

View file

@ -1,8 +1,22 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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 { mockInjectedMetadata } from './telemetry_opt_in.test.mocks'; import { mockInjectedMetadata } from './telemetry_opt_in.test.mocks';
import { TelemetryOptInProvider } from './telemetry_opt_in'; import { TelemetryOptInProvider } from './telemetry_opt_in';

View file

@ -0,0 +1,50 @@
/*
* 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 {
injectedMetadataServiceMock,
notificationServiceMock,
overlayServiceMock,
} from '../../../../../core/public/mocks';
const injectedMetadataMock = injectedMetadataServiceMock.createStartContract();
export function mockInjectedMetadata({ telemetryOptedIn }) {
const mockGetInjectedVar = jest.fn().mockImplementation((key) => {
switch (key) {
case 'telemetryOptedIn': return telemetryOptedIn;
default: throw new Error(`unexpected injectedVar ${key}`);
}
});
injectedMetadataMock.getInjectedVar = mockGetInjectedVar;
}
jest.doMock('ui/new_platform', () => ({
npSetup: {
core: {
notifications: notificationServiceMock.createSetupContract(),
}
},
npStart: {
core: {
injectedMetadata: injectedMetadataMock,
overlays: overlayServiceMock.createStartContract(),
},
},
}));

View file

@ -23,16 +23,20 @@ import { toastNotifications } from 'ui/notify';
import { npStart } from 'ui/new_platform'; import { npStart } from 'ui/new_platform';
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
export function TelemetryOptInProvider($injector, chrome) { let bannerId: string | null = null;
let currentOptInStatus = npStart.core.injectedMetadata.getInjectedVar('telemetryOptedIn'); let currentOptInStatus = false;
let bannerId = null;
export function TelemetryOptInProvider($injector: any, chrome: any) {
currentOptInStatus = npStart.core.injectedMetadata.getInjectedVar('telemetryOptedIn') as boolean;
setCanTrackUiMetrics(currentOptInStatus); setCanTrackUiMetrics(currentOptInStatus);
const provider = { const provider = {
getBannerId: () => bannerId, getBannerId: () => bannerId,
getOptIn: () => currentOptInStatus, getOptIn: () => currentOptInStatus,
setBannerId(id) { bannerId = id; }, setBannerId(id: string) {
setOptIn: async (enabled) => { bannerId = id;
},
setOptIn: async (enabled: boolean) => {
setCanTrackUiMetrics(enabled); setCanTrackUiMetrics(enabled);
const $http = $injector.get('$http'); const $http = $injector.get('$http');
@ -41,10 +45,10 @@ export function TelemetryOptInProvider($injector, chrome) {
currentOptInStatus = enabled; currentOptInStatus = enabled;
} catch (error) { } catch (error) {
toastNotifications.addError(error, { toastNotifications.addError(error, {
title: i18n.translate('kbn.home.telemetry.optInErrorToastTitle', { title: i18n.translate('telemetry.optInErrorToastTitle', {
defaultMessage: 'Error', defaultMessage: 'Error',
}), }),
toastMessage: i18n.translate('kbn.home.telemetry.optInErrorToastText', { toastMessage: i18n.translate('telemetry.optInErrorToastText', {
defaultMessage: 'An error occured while trying to set the usage statistics preference.', defaultMessage: 'An error occured while trying to set the usage statistics preference.',
}), }),
}); });
@ -58,11 +62,13 @@ export function TelemetryOptInProvider($injector, chrome) {
return $http.post(chrome.addBasePath(`/api/telemetry/v2/clusters/_stats`), { return $http.post(chrome.addBasePath(`/api/telemetry/v2/clusters/_stats`), {
unencrypted: true, unencrypted: true,
timeRange: { timeRange: {
min: moment().subtract(20, 'minutes').toISOString(), min: moment()
max: moment().toISOString() .subtract(20, 'minutes')
} .toISOString(),
max: moment().toISOString(),
},
}); });
} },
}; };
return provider; return provider;

View file

@ -0,0 +1,20 @@
/*
* 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 './management';

View file

@ -0,0 +1,42 @@
/*
* 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 React from 'react';
import routes from 'ui/routes';
import { registerSettingsComponent, PAGE_FOOTER_COMPONENT } from 'ui/management';
import { TelemetryOptInProvider } from '../../services';
import { TelemetryForm } from '../../components';
routes.defaults(/\/management/, {
resolve: {
telemetryManagementSection: function (Private) {
const telemetryOptInProvider = Private(TelemetryOptInProvider);
const Component = (props) => (
<TelemetryForm
showAppliesSettingMessage={true}
telemetryOptInProvider={telemetryOptInProvider}
{...props}
/>
);
registerSettingsComponent(PAGE_FOOTER_COMPONENT, Component, true);
}
}
});

View file

@ -0,0 +1,49 @@
/*
* 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.
*/
class TelemetryCollectionManager {
private getterMethod?: any;
private collectionTitle?: string;
private getterMethodPriority = 0;
public setStatsGetter = (statsGetter: any, title: string, priority = 0) => {
if (priority >= this.getterMethodPriority) {
this.getterMethod = statsGetter;
this.collectionTitle = title;
this.getterMethodPriority = priority;
}
};
getCollectionTitle = () => {
return this.collectionTitle;
};
public getStatsGetter = () => {
if (!this.getterMethod) {
throw Error('Stats getter method not set.');
}
return {
getStats: this.getterMethod,
priority: this.getterMethodPriority,
title: this.collectionTitle,
};
};
}
export const telemetryCollectionManager = new TelemetryCollectionManager();

View file

@ -1,7 +1,20 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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 { telemetryJWKS } from './telemetry_jwks'; import { telemetryJWKS } from './telemetry_jwks';

View file

@ -0,0 +1,32 @@
/*
* 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 { createRequestEncryptor } from '@elastic/request-crypto';
import { telemetryJWKS } from './telemetry_jwks';
export function getKID(isProd = false): string {
return isProd ? 'kibana' : 'kibana_dev';
}
export async function encryptTelemetry(payload: any, isProd = false): Promise<string[]> {
const kid = getKID(isProd);
const encryptor = await createRequestEncryptor(telemetryJWKS);
const clusters = [].concat(payload);
return Promise.all(clusters.map((cluster: any) => encryptor.encrypt(kid, cluster)));
}

View file

@ -0,0 +1,20 @@
/*
* 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 { encryptTelemetry } from './encrypt';

View file

@ -1,7 +1,20 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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 { PublicJWKS } from '@elastic/request-crypto'; import { PublicJWKS } from '@elastic/request-crypto';

View file

@ -0,0 +1,23 @@
/*
* 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 { encryptTelemetry } from './encryption';
export { createTelemetryUsageCollector } from './usage';
export { createUiMetricUsageCollector } from './ui_metric';
export { createLocalizationUsageCollector } from './localization';

View file

@ -0,0 +1,41 @@
/*
* 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 { Readable } from 'stream';
jest.doMock('fs', () => ({
createReadStream(filepath: string): Readable {
if (filepath === 'ERROR') {
throw new Error('MOCK ERROR - Invalid Path');
}
const readableStream = new Readable();
const streamData = filepath.split('');
let cursor = 0;
readableStream._read = function(size) {
const current = streamData[cursor++];
if (typeof current === 'undefined') {
return this.push(null);
}
this.push(current);
};
return readableStream;
},
}));

View file

@ -1,7 +1,20 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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 './file_integrity.test.mocks'; import './file_integrity.test.mocks';

View file

@ -1,7 +1,20 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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 { createHash } from 'crypto'; import { createHash } from 'crypto';

View file

@ -0,0 +1,20 @@
/*
* 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 { createLocalizationUsageCollector } from './telemetry_localization_collector';

View file

@ -1,7 +1,20 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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.
*/ */
interface TranslationsMock { interface TranslationsMock {

View file

@ -1,7 +1,20 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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 { i18nLoader } from '@kbn/i18n'; import { i18nLoader } from '@kbn/i18n';

View file

@ -0,0 +1,20 @@
/*
* 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 { createUiMetricUsageCollector } from './telemetry_ui_metric_collector';

View file

@ -1,7 +1,20 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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 { UI_METRIC_USAGE_TYPE } from '../../../common/constants'; import { UI_METRIC_USAGE_TYPE } from '../../../common/constants';

View file

@ -1,7 +1,20 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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 { ensureDeepObject } from './ensure_deep_object'; import { ensureDeepObject } from './ensure_deep_object';

View file

@ -1,7 +1,20 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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.
*/ */
// //

View file

@ -0,0 +1,20 @@
/*
* 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 { createTelemetryUsageCollector } from './telemetry_usage_collector';

View file

@ -1,7 +1,20 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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 { writeFileSync, unlinkSync } from 'fs'; import { writeFileSync, unlinkSync } from 'fs';
@ -28,8 +41,8 @@ const serverWithConfig = (configPath: string): KibanaHapiServer & Server => {
...getMockServer(), ...getMockServer(),
config: () => ({ config: () => ({
get: (key: string) => { get: (key: string) => {
if (key !== 'xpack.telemetry.config' && key !== 'xpack.xpack_main.telemetry.config') { if (key !== 'telemetry.config' && key !== 'xpack.xpack_main.telemetry.config') {
throw new Error('Expected `xpack.telemetry.config`'); throw new Error('Expected `telemetry.config`');
} }
return configPath; return configPath;

View file

@ -1,7 +1,20 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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 { accessSync, constants, readFileSync, statSync } from 'fs'; import { accessSync, constants, readFileSync, statSync } from 'fs';

View file

@ -1,7 +1,20 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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 async function getTelemetryOptIn(request: any) { export async function getTelemetryOptIn(request: any) {

View file

@ -0,0 +1,29 @@
/*
* 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 { PluginInitializerContext } from 'src/core/server';
import { TelemetryPlugin } from './plugin';
import * as constants from '../common/constants';
export { getTelemetryOptIn } from './get_telemetry_opt_in';
export { telemetryCollectionManager } from './collection_manager';
export const telemetryPlugin = (initializerContext: PluginInitializerContext) =>
new TelemetryPlugin();
export { constants };

View file

@ -0,0 +1,30 @@
/*
* 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 { CoreSetup } from 'src/core/server';
import { registerRoutes } from './routes';
import { telemetryCollectionManager } from './collection_manager';
import { getStats } from './telemetry_collection';
export class TelemetryPlugin {
public setup(core: CoreSetup) {
telemetryCollectionManager.setStatsGetter(getStats, 'local');
registerRoutes(core);
}
}

View file

@ -0,0 +1,27 @@
/*
* 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 { CoreSetup } from 'src/core/server';
import { registerOptInRoutes } from './opt_in';
import { registerTelemetryDataRoutes } from './telemetry_stats';
export function registerRoutes(core: CoreSetup) {
registerOptInRoutes(core);
registerTelemetryDataRoutes(core);
}

View file

@ -1,7 +1,20 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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 Joi from 'joi'; import Joi from 'joi';

View file

@ -1,13 +1,27 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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 Joi from 'joi'; import Joi from 'joi';
import { boomify } from 'boom'; import { boomify } from 'boom';
import { CoreSetup } from 'src/core/server'; import { CoreSetup } from 'src/core/server';
import { getStats, encryptTelemetry } from '../collectors'; import { encryptTelemetry } from '../collectors';
import { telemetryCollectionManager } from '../collection_manager';
export function registerTelemetryDataRoutes(core: CoreSetup) { export function registerTelemetryDataRoutes(core: CoreSetup) {
const { server } = core.http as any; const { server } = core.http as any;
@ -34,13 +48,17 @@ export function registerTelemetryDataRoutes(core: CoreSetup) {
const isDev = config.get('env.dev'); const isDev = config.get('env.dev');
try { try {
const { getStats, title } = telemetryCollectionManager.getStatsGetter();
server.log(['debug', 'telemetry'], `Using Stats Getter: ${title}`);
const usageData = await getStats(req, config, start, end, unencrypted); const usageData = await getStats(req, config, start, end, unencrypted);
if (unencrypted) return usageData; if (unencrypted) return usageData;
return encryptTelemetry(usageData, isDev); return encryptTelemetry(usageData, isDev);
} catch (err) { } catch (err) {
if (isDev) { if (isDev) {
// don't ignore errors when running in dev mode // don't ignore errors when running in dev mode
return boomify(err, { statusCode: err.status }); return boomify(err, { statusCode: err.status || 500 });
} else { } else {
const statusCode = unencrypted && err.status === 403 ? 403 : 200; const statusCode = unencrypted && err.status === 403 ? 403 : 200;
// ignore errors and return empty set // ignore errors and return empty set

View file

@ -0,0 +1,41 @@
/*
* 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 expect from '@kbn/expect';
import sinon from 'sinon';
import { getClusterInfo } from '../get_cluster_info';
export function mockGetClusterInfo(callCluster, clusterInfo, req) {
callCluster.withArgs(req, 'info').returns(clusterInfo);
callCluster.withArgs('info').returns(clusterInfo);
}
describe('get_cluster_info', () => {
it('uses callCluster to get info API', () => {
const callCluster = sinon.stub();
const response = Promise.resolve({});
mockGetClusterInfo(callCluster, response);
expect(getClusterInfo(callCluster)).to.be(response);
});
});

View file

@ -0,0 +1,49 @@
/*
* 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 expect from '@kbn/expect';
import sinon from 'sinon';
import { TIMEOUT } from '../constants';
import { getClusterStats } from '../get_cluster_stats';
export function mockGetClusterStats(callCluster, clusterStats, req) {
callCluster.withArgs(req, 'cluster.stats', {
timeout: TIMEOUT
})
.returns(clusterStats);
callCluster.withArgs('cluster.stats', {
timeout: TIMEOUT
})
.returns(clusterStats);
}
describe('get_cluster_stats', () => {
it('uses callCluster to get cluster.stats API', () => {
const callCluster = sinon.stub();
const response = Promise.resolve({});
mockGetClusterStats(callCluster, response);
expect(getClusterStats(callCluster)).to.be(response);
});
});

View file

@ -1,7 +1,20 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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 expect from '@kbn/expect'; import expect from '@kbn/expect';
@ -9,7 +22,6 @@ import sinon from 'sinon';
import { mockGetClusterInfo } from './get_cluster_info'; import { mockGetClusterInfo } from './get_cluster_info';
import { mockGetClusterStats } from './get_cluster_stats'; import { mockGetClusterStats } from './get_cluster_stats';
import { mockGetXPack } from './get_xpack';
import { omit } from 'lodash'; import { omit } from 'lodash';
import { import {
@ -22,17 +34,25 @@ const getMockServer = (getCluster = sinon.stub(), kibanaUsage = {}) => ({
log(tags, message) { log(tags, message) {
console.log({ tags, message }); console.log({ tags, message });
}, },
config() {
return {
get(item) {
switch(item) {
case 'pkg.version': return '8675309-snapshot';
default: throw Error(`unexpected config.get('${item}') received.`);
}
}
};
},
usage: { collectorSet: { bulkFetch: () => kibanaUsage, toObject: data => data } }, usage: { collectorSet: { bulkFetch: () => kibanaUsage, toObject: data => data } },
plugins: { plugins: {
xpack_main: { status: { plugin: { kbnServer: { version: '8675309-snapshot' } } } },
elasticsearch: { getCluster }, elasticsearch: { getCluster },
}, },
}); });
function mockGetLocalStats(callCluster, clusterInfo, clusterStats, license, usage, req) { function mockGetLocalStats(callCluster, clusterInfo, clusterStats, req) {
mockGetClusterInfo(callCluster, clusterInfo, req); mockGetClusterInfo(callCluster, clusterInfo, req);
mockGetClusterStats(callCluster, clusterStats, req); mockGetClusterStats(callCluster, clusterStats, req);
mockGetXPack(callCluster, license, usage, req);
} }
describe('get_local_stats', () => { describe('get_local_stats', () => {
@ -53,8 +73,6 @@ describe('get_local_stats', () => {
nodes: { yup: 'abc' }, nodes: { yup: 'abc' },
random: 123 random: 123
}; };
const license = { fancy: 'license' };
const xpack = { also: 'fancy' };
const kibana = { const kibana = {
kibana: { kibana: {
great: 'googlymoogly', great: 'googlymoogly',
@ -81,9 +99,6 @@ describe('get_local_stats', () => {
collection: 'local', collection: 'local',
cluster_uuid: clusterUuid, cluster_uuid: clusterUuid,
cluster_name: clusterName, cluster_name: clusterName,
license: {
fancy: 'license'
},
version, version,
cluster_stats: omit(clusterStats, '_nodes', 'cluster_name'), cluster_stats: omit(clusterStats, '_nodes', 'cluster_name'),
stack_stats: { stack_stats: {
@ -108,7 +123,6 @@ describe('get_local_stats', () => {
snow: { chances: 0 }, snow: { chances: 0 },
} }
}, },
xpack: { also: 'fancy' },
} }
}; };
@ -121,11 +135,11 @@ describe('get_local_stats', () => {
expect(result.version).to.be('2.3.4'); expect(result.version).to.be('2.3.4');
expect(result.collection).to.be('local'); expect(result.collection).to.be('local');
expect(result.license).to.be(undefined); expect(result.license).to.be(undefined);
expect(result.stack_stats).to.eql({ kibana: undefined, xpack: undefined }); expect(result.stack_stats).to.eql({ kibana: undefined });
}); });
it('returns expected object with xpack', () => { it('returns expected object with xpack', () => {
const result = handleLocalStats(getMockServer(), clusterInfo, clusterStats, license, xpack); const result = handleLocalStats(getMockServer(), clusterInfo, clusterStats);
const { stack_stats: stack, ...cluster } = result; const { stack_stats: stack, ...cluster } = result;
expect(cluster.collection).to.be(combinedStatsResult.collection); expect(cluster.collection).to.be(combinedStatsResult.collection);
expect(cluster.cluster_uuid).to.be(combinedStatsResult.cluster_uuid); expect(cluster.cluster_uuid).to.be(combinedStatsResult.cluster_uuid);
@ -147,8 +161,6 @@ describe('get_local_stats', () => {
callClusterUsageFailed, callClusterUsageFailed,
Promise.resolve(clusterInfo), Promise.resolve(clusterInfo),
Promise.resolve(clusterStats), Promise.resolve(clusterStats),
Promise.resolve(license),
Promise.reject('usage failed')
); );
const result = await getLocalStatsWithCaller(getMockServer(), callClusterUsageFailed); const result = await getLocalStatsWithCaller(getMockServer(), callClusterUsageFailed);
@ -170,8 +182,6 @@ describe('get_local_stats', () => {
callCluster, callCluster,
Promise.resolve(clusterInfo), Promise.resolve(clusterInfo),
Promise.resolve(clusterStats), Promise.resolve(clusterStats),
Promise.resolve(license),
Promise.resolve(xpack)
); );
const result = await getLocalStatsWithCaller(getMockServer(callCluster, kibana), callCluster); const result = await getLocalStatsWithCaller(getMockServer(callCluster, kibana), callCluster);
@ -192,8 +202,6 @@ describe('get_local_stats', () => {
callWithInternalUser, callWithInternalUser,
Promise.resolve(clusterInfo), Promise.resolve(clusterInfo),
Promise.resolve(clusterStats), Promise.resolve(clusterStats),
Promise.resolve(license),
Promise.resolve(xpack)
); );
const result = await getLocalStats(req, { useInternalUser: true }); const result = await getLocalStats(req, { useInternalUser: true });
@ -213,8 +221,6 @@ describe('get_local_stats', () => {
callWithRequest, callWithRequest,
Promise.resolve(clusterInfo), Promise.resolve(clusterInfo),
Promise.resolve(clusterStats), Promise.resolve(clusterStats),
Promise.resolve(license),
Promise.resolve(xpack),
req req
); );

View file

@ -0,0 +1,23 @@
/*
* 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.
*/
/**
* The timeout used by each request, whenever a timeout can be specified.
*/
export const TIMEOUT = '30s';

View file

@ -0,0 +1,30 @@
/*
* 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.
*/
/**
* Get the cluster info from the connected cluster.
*
* This is the equivalent to GET /
*
* @param {function} callCluster The callWithInternalUser handler (exposed for testing)
* @return {Promise} The response from Elasticsearch.
*/
export function getClusterInfo(callCluster) {
return callCluster('info');
}

View file

@ -0,0 +1,34 @@
/*
* 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 { TIMEOUT } from './constants';
/**
* Get the cluster stats from the connected cluster.
*
* This is the equivalent to GET /_cluster/stats?timeout=30s.
*
* @param {function} callCluster The callWithInternalUser handler (exposed for testing)
* @return {Promise} The response from Elasticsearch equivalent to GET /_cluster/stats.
*/
export function getClusterStats(callCluster) {
return callCluster('cluster.stats', {
timeout: TIMEOUT
});
}

View file

@ -0,0 +1,58 @@
/*
* 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 { get, omit } from 'lodash';
export function handleKibanaStats(server, response) {
if (!response) {
server.log(['warning', 'telemetry', 'local-stats'], 'No Kibana stats returned from usage collectors');
return;
}
const { kibana, kibana_stats: kibanaStats, ...plugins } = response;
const platform = get(kibanaStats, 'os.platform', 'unknown');
const platformRelease = get(kibanaStats, 'os.platformRelease', 'unknown');
const version = server.config().get('pkg.version').replace(/-snapshot/i, '');
// combine core stats (os types, saved objects) with plugin usage stats
// organize the object into the same format as monitoring-enabled telemetry
return {
...omit(kibana, 'index'), // discard index
count: 1,
indices: 1,
os: {
platforms: [{ platform, count: 1 }],
platformReleases: [{ platformRelease, count: 1 }],
},
versions: [{ version, count: 1 }],
plugins,
};
}
/*
* Check user privileges for read access to monitoring
* Pass callWithInternalUser to bulkFetchUsage
*/
export async function getKibana(server, callWithInternalUser) {
const { collectorSet } = server.usage;
const usage = await collectorSet.bulkFetch(callWithInternalUser);
return collectorSet.toObject(usage);
}

View file

@ -1,13 +1,25 @@
/* /*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * Licensed to Elasticsearch B.V. under one or more contributor
* or more contributor license agreements. Licensed under the Elastic License; * license agreements. See the NOTICE file distributed with
* you may not use this file except in compliance with the Elastic License. * 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 { get, omit } from 'lodash'; import { get, omit } from 'lodash';
import { getClusterInfo } from './get_cluster_info'; import { getClusterInfo } from './get_cluster_info';
import { getClusterStats } from './get_cluster_stats'; import { getClusterStats } from './get_cluster_stats';
import { getXPack } from './get_xpack';
import { getKibana, handleKibanaStats } from './get_kibana'; import { getKibana, handleKibanaStats } from './get_kibana';
/** /**
@ -16,10 +28,9 @@ import { getKibana, handleKibanaStats } from './get_kibana';
* *
* @param {Object} clusterInfo Cluster info (GET /) * @param {Object} clusterInfo Cluster info (GET /)
* @param {Object} clusterStats Cluster stats (GET /_cluster/stats) * @param {Object} clusterStats Cluster stats (GET /_cluster/stats)
* @param {Object} xpack License and X-Pack details
* @return {Object} A combined object containing the different responses. * @return {Object} A combined object containing the different responses.
*/ */
export function handleLocalStats(server, clusterInfo, clusterStats, license, xpack, kibana) { export function handleLocalStats(server, clusterInfo, clusterStats, kibana) {
return { return {
timestamp: (new Date()).toISOString(), timestamp: (new Date()).toISOString(),
cluster_uuid: get(clusterInfo, 'cluster_uuid'), cluster_uuid: get(clusterInfo, 'cluster_uuid'),
@ -27,10 +38,8 @@ export function handleLocalStats(server, clusterInfo, clusterStats, license, xpa
version: get(clusterInfo, 'version.number'), version: get(clusterInfo, 'version.number'),
cluster_stats: omit(clusterStats, '_nodes', 'cluster_name'), cluster_stats: omit(clusterStats, '_nodes', 'cluster_name'),
collection: 'local', collection: 'local',
license,
stack_stats: { stack_stats: {
kibana: handleKibanaStats(server, kibana), kibana: handleKibanaStats(server, kibana),
xpack,
} }
}; };
} }
@ -42,18 +51,17 @@ export function handleLocalStats(server, clusterInfo, clusterStats, license, xpa
* @param {function} callCluster The callWithInternalUser handler (exposed for testing) * @param {function} callCluster The callWithInternalUser handler (exposed for testing)
* @return {Promise} The object containing the current Elasticsearch cluster's telemetry. * @return {Promise} The object containing the current Elasticsearch cluster's telemetry.
*/ */
export function getLocalStatsWithCaller(server, callCluster) { export async function getLocalStatsWithCaller(server, callCluster) {
return Promise.all([ const [ clusterInfo, clusterStats, kibana ] = await Promise.all([
getClusterInfo(callCluster), // cluster info getClusterInfo(callCluster), // cluster info
getClusterStats(callCluster), // cluster stats (not to be confused with cluster _state_) getClusterStats(callCluster), // cluster stats (not to be confused with cluster _state_)
getXPack(callCluster), // { license, xpack } getKibana(server, callCluster),
getKibana(server, callCluster) ]);
]).then(([clusterInfo, clusterStats, { license, xpack }, kibana]) => {
return handleLocalStats(server, clusterInfo, clusterStats, license, xpack, kibana); return handleLocalStats(server, clusterInfo, clusterStats, kibana);
}
);
} }
/** /**
* Get statistics for the connected Elasticsearch cluster. * Get statistics for the connected Elasticsearch cluster.
* *
@ -61,10 +69,10 @@ export function getLocalStatsWithCaller(server, callCluster) {
* @param {Boolean} useRequestUser callWithRequest, otherwise callWithInternalUser * @param {Boolean} useRequestUser callWithRequest, otherwise callWithInternalUser
* @return {Promise} The cluster object containing telemetry. * @return {Promise} The cluster object containing telemetry.
*/ */
export function getLocalStats(req, { useInternalUser = false } = {}) { export async function getLocalStats(req, { useInternalUser = false } = {}) {
const { server } = req; const { server } = req;
const { callWithRequest, callWithInternalUser } = server.plugins.elasticsearch.getCluster('data'); const { callWithRequest, callWithInternalUser } = server.plugins.elasticsearch.getCluster('data');
const callCluster = useInternalUser ? callWithInternalUser : (...args) => callWithRequest(req, ...args); const callCluster = useInternalUser ? callWithInternalUser : (...args) => callWithRequest(req, ...args);
return getLocalStatsWithCaller(server, callCluster); return await getLocalStatsWithCaller(server, callCluster);
} }

View file

@ -0,0 +1,45 @@
/*
* 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.
*/
// @ts-ignore
import { getLocalStats } from './get_local_stats';
/**
* Get the telemetry data.
*
* @param {Object} req The incoming request.
* @param {Object} config Kibana config.
* @param {String} start The start time of the request (likely 20m ago).
* @param {String} end The end time of the request.
* @param {Boolean} unencrypted Is the request payload going to be unencrypted.
* @return {Promise} An array of telemetry objects.
*/
export async function getStats(
req: any,
config: any,
start: string,
end: string,
unencrypted: boolean
) {
return [
await getLocalStats(req, {
useInternalUser: !unencrypted,
}),
];
}

View file

@ -0,0 +1,24 @@
/*
* 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.
*/
// @ts-ignore
export { getLocalStats } from './get_local_stats';
// @ts-ignore
export { getStats } from './get_stats';

View file

@ -55,6 +55,7 @@ export default function () {
`--elasticsearch.username=${servers.elasticsearch.username}`, `--elasticsearch.username=${servers.elasticsearch.username}`,
`--elasticsearch.password=${servers.elasticsearch.password}`, `--elasticsearch.password=${servers.elasticsearch.password}`,
`--kibana.disableWelcomeScreen=true`, `--kibana.disableWelcomeScreen=true`,
'--telemetry.banner=false',
`--server.maxPayloadBytes=1679958`, `--server.maxPayloadBytes=1679958`,
], ],
}, },

20
typings/elastic__node_crypto.d.ts vendored Normal file
View file

@ -0,0 +1,20 @@
/*
* 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.
*/
declare module '@elastic/node-crypto';

View file

@ -25,7 +25,6 @@
"xpack.ml": "legacy/plugins/ml", "xpack.ml": "legacy/plugins/ml",
"xpack.logstash": "legacy/plugins/logstash", "xpack.logstash": "legacy/plugins/logstash",
"xpack.main": "legacy/plugins/xpack_main", "xpack.main": "legacy/plugins/xpack_main",
"xpack.telemetry": "legacy/plugins/telemetry",
"xpack.monitoring": "legacy/plugins/monitoring", "xpack.monitoring": "legacy/plugins/monitoring",
"xpack.remoteClusters": "legacy/plugins/remote_clusters", "xpack.remoteClusters": "legacy/plugins/remote_clusters",
"xpack.reporting": "legacy/plugins/reporting", "xpack.reporting": "legacy/plugins/reporting",

View file

@ -38,7 +38,6 @@ import { upgradeAssistant } from './legacy/plugins/upgrade_assistant';
import { uptime } from './legacy/plugins/uptime'; import { uptime } from './legacy/plugins/uptime';
import { ossTelemetry } from './legacy/plugins/oss_telemetry'; import { ossTelemetry } from './legacy/plugins/oss_telemetry';
import { fileUpload } from './legacy/plugins/file_upload'; import { fileUpload } from './legacy/plugins/file_upload';
import { telemetry } from './legacy/plugins/telemetry';
import { encryptedSavedObjects } from './legacy/plugins/encrypted_saved_objects'; import { encryptedSavedObjects } from './legacy/plugins/encrypted_saved_objects';
import { snapshotRestore } from './legacy/plugins/snapshot_restore'; import { snapshotRestore } from './legacy/plugins/snapshot_restore';
import { transform } from './legacy/plugins/transform'; import { transform } from './legacy/plugins/transform';
@ -49,7 +48,6 @@ import { lens } from './legacy/plugins/lens';
module.exports = function (kibana) { module.exports = function (kibana) {
return [ return [
xpackMain(kibana), xpackMain(kibana),
telemetry(kibana),
graph(kibana), graph(kibana),
monitoring(kibana), monitoring(kibana),
reporting(kibana), reporting(kibana),

View file

@ -4,10 +4,10 @@
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
import { fetchTelemetry } from '../../../telemetry/public/hacks/fetch_telemetry'; import { fetchTelemetry } from '../../../../../../src/legacy/core_plugins/telemetry/public/hacks/fetch_telemetry';
export { PRIVACY_STATEMENT_URL } from '../../../telemetry/common/constants'; export { PRIVACY_STATEMENT_URL } from '../../../../../../src/legacy/core_plugins/telemetry/common/constants';
export { TelemetryOptInProvider } from '../../../telemetry/public/services/telemetry_opt_in'; export { TelemetryOptInProvider } from '../../../../../../src/legacy/core_plugins/telemetry/public/services';
export { OptInExampleFlyout } from '../../../telemetry/public/components'; export { OptInExampleFlyout } from '../../../../../../src/legacy/core_plugins/telemetry/public/components';
let telemetryEnabled; let telemetryEnabled;
let httpClient; let httpClient;

View file

@ -155,10 +155,7 @@ export const METRICBEAT_INDEX_NAME_UNIQUE_TOKEN = '-mb-';
// We use this for metricbeat migration to identify specific products that we do not have constants for // We use this for metricbeat migration to identify specific products that we do not have constants for
export const ELASTICSEARCH_SYSTEM_ID = 'elasticsearch'; export const ELASTICSEARCH_SYSTEM_ID = 'elasticsearch';
export const KIBANA_SYSTEM_ID = 'kibana';
export const BEATS_SYSTEM_ID = 'beats';
export const APM_SYSTEM_ID = 'apm';
export const LOGSTASH_SYSTEM_ID = 'logstash';
/** /**
* The id of the infra source owned by the monitoring plugin. * The id of the infra source owned by the monitoring plugin.
*/ */
@ -181,3 +178,47 @@ export const CODE_PATH_LOGSTASH = 'logstash';
export const CODE_PATH_APM = 'apm'; export const CODE_PATH_APM = 'apm';
export const CODE_PATH_LICENSE = 'license'; export const CODE_PATH_LICENSE = 'license';
export const CODE_PATH_LOGS = 'logs'; export const CODE_PATH_LOGS = 'logs';
/**
* The header sent by telemetry service when hitting Elasticsearch to identify query source
* @type {string}
*/
export const TELEMETRY_QUERY_SOURCE = 'TELEMETRY';
/**
* The name of the Kibana System ID used to publish and look up Kibana stats through the Monitoring system.
* @type {string}
*/
export const KIBANA_SYSTEM_ID = 'kibana';
/**
* The name of the Beats System ID used to publish and look up Beats stats through the Monitoring system.
* @type {string}
*/
export const BEATS_SYSTEM_ID = 'beats';
/**
* The name of the Apm System ID used to publish and look up Apm stats through the Monitoring system.
* @type {string}
*/
export const APM_SYSTEM_ID = 'apm';
/**
* The name of the Kibana System ID used to look up Logstash stats through the Monitoring system.
* @type {string}
*/
export const LOGSTASH_SYSTEM_ID = 'logstash';
/**
* The name of the Kibana System ID used to look up Reporting stats through the Monitoring system.
* @type {string}
*/
export const REPORTING_SYSTEM_ID = 'reporting';
/**
* The amount of time, in milliseconds, to wait between collecting kibana stats from es.
*
* Currently 24 hours kept in sync with reporting interval.
* @type {Number}
*/
export const TELEMETRY_COLLECTION_INTERVAL = 86400000;

View file

@ -49,9 +49,6 @@ describe('BulkUploader', () => {
server = { server = {
log: sinon.spy(), log: sinon.spy(),
xpackMainPlugin: {
telemetryCollectionInterval: 3000,
},
elasticsearchPlugin: { elasticsearchPlugin: {
createCluster: () => cluster, createCluster: () => cluster,
getCluster: () => cluster, getCluster: () => cluster,

View file

@ -10,7 +10,9 @@ import { callClusterFactory } from '../../../xpack_main';
import { import {
LOGGING_TAG, LOGGING_TAG,
KIBANA_MONITORING_LOGGING_TAG, KIBANA_MONITORING_LOGGING_TAG,
TELEMETRY_COLLECTION_INTERVAL,
} from '../../common/constants'; } from '../../common/constants';
import { import {
sendBulkPayload, sendBulkPayload,
monitoringBulk, monitoringBulk,
@ -36,7 +38,7 @@ const LOGGING_TAGS = [LOGGING_TAG, KIBANA_MONITORING_LOGGING_TAG];
* @param {Object} xpackInfo server.plugins.xpack_main.info object * @param {Object} xpackInfo server.plugins.xpack_main.info object
*/ */
export class BulkUploader { export class BulkUploader {
constructor({ config, log, interval, xpackMainPlugin, elasticsearchPlugin, kbnServerStatus, kbnServerVersion }) { constructor({ config, log, interval, elasticsearchPlugin, kbnServerStatus, kbnServerVersion }) {
if (typeof interval !== 'number') { if (typeof interval !== 'number') {
throw new Error('interval number of milliseconds is required'); throw new Error('interval number of milliseconds is required');
} }
@ -44,7 +46,7 @@ export class BulkUploader {
this._timer = null; this._timer = null;
this._interval = interval; this._interval = interval;
this._lastFetchUsageTime = null; this._lastFetchUsageTime = null;
this._usageInterval = xpackMainPlugin.telemetryCollectionInterval; this._usageInterval = TELEMETRY_COLLECTION_INTERVAL;
this._log = { this._log = {
debug: message => log(['debug', ...LOGGING_TAGS], message), debug: message => log(['debug', ...LOGGING_TAGS], message),

View file

@ -4,8 +4,7 @@
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
import { MONITORING_SYSTEM_API_VERSION } from '../../../common/constants'; import { MONITORING_SYSTEM_API_VERSION, KIBANA_SYSTEM_ID } from '../../../common/constants';
import { KIBANA_SYSTEM_ID } from '../../../../telemetry/common/constants';
/* /*
* Send the Kibana usage data to the ES Monitoring Bulk endpoint * Send the Kibana usage data to the ES Monitoring Bulk endpoint

View file

@ -10,6 +10,9 @@ import { requireUIRoutes } from './routes';
import { instantiateClient } from './es_client/instantiate_client'; import { instantiateClient } from './es_client/instantiate_client';
import { initMonitoringXpackInfo } from './init_monitoring_xpack_info'; import { initMonitoringXpackInfo } from './init_monitoring_xpack_info';
import { initBulkUploader } from './kibana_monitoring'; import { initBulkUploader } from './kibana_monitoring';
import { telemetryCollectionManager } from '../../../../../src/legacy/core_plugins/telemetry/server';
import { getStatsWithMonitoring } from './telemetry_collection';
import { import {
getKibanaUsageCollector, getKibanaUsageCollector,
getOpsStatsCollector, getOpsStatsCollector,
@ -36,6 +39,8 @@ export class Plugin {
collectorSet.register(getKibanaUsageCollector({ collectorSet, config })); collectorSet.register(getKibanaUsageCollector({ collectorSet, config }));
collectorSet.register(getSettingsCollector({ collectorSet, config })); collectorSet.register(getSettingsCollector({ collectorSet, config }));
telemetryCollectionManager.setStatsGetter(getStatsWithMonitoring, 'monitoring', 2);
/* /*
* Instantiate and start the internal background task that calls collector * Instantiate and start the internal background task that calls collector
* fetch methods and uploads to the ES monitoring bulk endpoint * fetch methods and uploads to the ES monitoring bulk endpoint
@ -90,7 +95,6 @@ export class Plugin {
const bulkUploader = initBulkUploader({ const bulkUploader = initBulkUploader({
elasticsearchPlugin: plugins.elasticsearch, elasticsearchPlugin: plugins.elasticsearch,
xpackMainPlugin: plugins.xpack_main,
config, config,
log: core.log, log: core.log,
kbnServerStatus: kbnServer.status, kbnServerStatus: kbnServer.status,

View file

@ -6,7 +6,7 @@
import expect from '@kbn/expect'; import expect from '@kbn/expect';
import sinon from 'sinon'; import sinon from 'sinon';
import { addStackStats, getAllStats, getAllStatsForServer, handleAllStats } from '../get_all_stats'; import { addStackStats, getAllStats, handleAllStats } from '../get_all_stats';
describe('get_all_stats', () => { describe('get_all_stats', () => {
const size = 123; const size = 123;
@ -106,7 +106,7 @@ describe('get_all_stats', () => {
} }
]; ];
describe('getAllStats / getAllStatsForServer return the same results', () => { describe('getAllStats', () => {
it('returns clusters', async () => { it('returns clusters', async () => {
const clusterUuidsResponse = { const clusterUuidsResponse = {
aggregations: { cluster_uuids: { buckets: [ { key: 'a' } ] } } aggregations: { cluster_uuids: { buckets: [ { key: 'a' } ] } }
@ -201,7 +201,6 @@ describe('get_all_stats', () => {
.onCall(3).returns(Promise.resolve(logstashStatsResponse)); .onCall(3).returns(Promise.resolve(logstashStatsResponse));
expect(await getAllStats(req, start, end)).to.eql(allClusters); expect(await getAllStats(req, start, end)).to.eql(allClusters);
expect(await getAllStatsForServer(server, start, end)).to.eql(allClusters);
}); });
it('returns empty clusters', async () => { it('returns empty clusters', async () => {
@ -213,7 +212,6 @@ describe('get_all_stats', () => {
callWithInternalUser.withArgs('search').returns(Promise.resolve(clusterUuidsResponse)); callWithInternalUser.withArgs('search').returns(Promise.resolve(clusterUuidsResponse));
expect(await getAllStats(req, start, end)).to.eql([]); expect(await getAllStats(req, start, end)).to.eql([]);
expect(await getAllStatsForServer(server, start, end)).to.eql([]);
}); });
}); });

Some files were not shown because too many files have changed in this diff Show more