diff --git a/src/core_plugins/kibana/common/tutorials/tutorial_schema.js b/src/core_plugins/kibana/common/tutorials/tutorial_schema.js index 5a95f14b57fdf..83a5cd18510cf 100644 --- a/src/core_plugins/kibana/common/tutorials/tutorial_schema.js +++ b/src/core_plugins/kibana/common/tutorials/tutorial_schema.js @@ -109,4 +109,8 @@ export const tutorialSchema = { // Elastic stack artifacts produced by product when it is setup and run. artifacts: artifactsSchema, + + // saved objects used by data module. + savedObjects: Joi.array().items(), + savedObjectsInstallMsg: Joi.string(), }; diff --git a/src/core_plugins/kibana/public/home/components/home_app.js b/src/core_plugins/kibana/public/home/components/home_app.js index a6fbf6fdde642..06d3cae228371 100644 --- a/src/core_plugins/kibana/public/home/components/home_app.js +++ b/src/core_plugins/kibana/public/home/components/home_app.js @@ -40,6 +40,7 @@ export function HomeApp({ getConfig, setConfig, clearIndexPatternsCache, + bulkCreate, }) { const isCloudEnabled = chrome.getInjected('isCloudEnabled', false); @@ -66,6 +67,7 @@ export function HomeApp({ getTutorial={getTutorial} replaceTemplateStrings={replaceTemplateStrings} tutorialId={props.match.params.id} + bulkCreate={bulkCreate} /> ); }; @@ -119,4 +121,5 @@ HomeApp.propTypes = { getConfig: PropTypes.func.isRequired, setConfig: PropTypes.func.isRequired, clearIndexPatternsCache: PropTypes.func.isRequired, + bulkCreate: PropTypes.func.isRequired, }; diff --git a/src/core_plugins/kibana/public/home/components/tutorial/__snapshots__/saved_objects_installer.test.js.snap b/src/core_plugins/kibana/public/home/components/tutorial/__snapshots__/saved_objects_installer.test.js.snap new file mode 100644 index 0000000000000..11f4b043679a8 --- /dev/null +++ b/src/core_plugins/kibana/public/home/components/tutorial/__snapshots__/saved_objects_installer.test.js.snap @@ -0,0 +1,531 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`bulkCreate should display error message when bulkCreate request fails 1`] = ` + + + + + +

+ Imports index pattern, visualizations and pre-defined dashboards. +

+
+
+ + + Load Kibana objects + + +
+ + + , + "key": "installStep", + "status": "incomplete", + "title": "Load Kibana objects", + }, + ] + } + > +
+ +
+ + + Step + + +
+ +

+ Load Kibana objects +

+
+
+ +
+ +
+ +
+

+ Imports index pattern, visualizations and pre-defined dashboards. +

+
+
+
+
+ +
+ + + +
+
+
+
+ +
+ + +
+
+ + Request failed, Error: simulated bulkRequest error + +
+
+
+
+
+ +
+ + +`; + +exports[`bulkCreate should display success message when bulkCreate is successful 1`] = ` + + + + + +

+ Imports index pattern, visualizations and pre-defined dashboards. +

+
+
+ + + Load Kibana objects + + +
+ + + , + "key": "installStep", + "status": "complete", + "title": "Load Kibana objects", + }, + ] + } + > +
+ +
+ + + Step + + +
+ + + + + + + + + + +
+ +

+ Load Kibana objects +

+
+
+ +
+ +
+ +
+

+ Imports index pattern, visualizations and pre-defined dashboards. +

+
+
+
+
+ +
+ + + +
+
+
+
+ +
+ + +
+
+ + 1 saved objects successfully added + +
+
+
+
+
+ +
+ + +`; + +exports[`renders 1`] = ` + + + + +

+ Imports index pattern, visualizations and pre-defined dashboards. +

+
+
+ + + Load Kibana objects + + +
+ + , + "key": "installStep", + "status": "incomplete", + "title": "Load Kibana objects", + }, + ] + } +/> +`; diff --git a/src/core_plugins/kibana/public/home/components/tutorial/saved_objects_installer.js b/src/core_plugins/kibana/public/home/components/tutorial/saved_objects_installer.js new file mode 100644 index 0000000000000..fd4ac6578df3d --- /dev/null +++ b/src/core_plugins/kibana/public/home/components/tutorial/saved_objects_installer.js @@ -0,0 +1,184 @@ +/* + * 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, { Fragment } from 'react'; +import PropTypes from 'prop-types'; + +import { + EuiSteps, + EuiFlexGroup, + EuiFlexItem, + EuiText, + EuiButton, + EuiSpacer, + EuiCallOut, +} from '@elastic/eui'; + +const DEFAULT_BUTTON_LABEL = 'Load Kibana objects'; + +export class SavedObjectsInstaller extends React.Component { + state = { + isInstalling: false, + isInstalled: false, + overwrite: false, + buttonLabel: DEFAULT_BUTTON_LABEL, + }; + + componentDidMount() { + this._isMounted = true; + } + + componentWillUnmount() { + this._isMounted = false; + } + + installSavedObjects = async () => { + this.setState({ + isInstalling: true, + }); + + let resp; + try { + resp = await this.props.bulkCreate(this.props.savedObjects, { overwrite: this.state.overwrite }); + } catch (error) { + if (!this._isMounted) { + return; + } + + this.setState({ + isInstalling: false, + installStatusMsg: `Request failed, Error: ${error.message}`, + isInstalled: false, + overwrite: false, + buttonLabel: DEFAULT_BUTTON_LABEL + }); + return; + } + + if (!this._isMounted) { + return; + } + + const errors = resp.savedObjects.filter(savedObject => { + return savedObject.hasOwnProperty('error'); + }); + + const overwriteErrors = errors.filter(savedObject => { + return savedObject.error.statusCode === 409; + }); + if (overwriteErrors.length > 0) { + this.setState({ + isInstalling: false, + installStatusMsg: `${overwriteErrors.length} of ${this.props.savedObjects.length} objects already exist. ` + + `Click 'Confirm overwrite' to import and overwrite existing objects. ` + + `Any changes to the objects will be lost.`, + isInstalled: false, + overwrite: true, + buttonLabel: 'Confirm overwrite' + }); + return; + } + + const hasErrors = errors.length > 0; + const statusMsg = hasErrors + ? `Unable to add ${errors.length} of ${this.props.savedObjects.length} kibana objects, Error: ${errors[0].error.message}` + : `${this.props.savedObjects.length} saved objects successfully added`; + this.setState({ + isInstalling: false, + installStatusMsg: statusMsg, + isInstalled: !hasErrors, + overwrite: false, + buttonLabel: DEFAULT_BUTTON_LABEL, + }); + } + + renderInstallMessage() { + if (!this.state.installStatusMsg) { + return; + } + + return ( + + ); + } + + renderInstallStep = () => { + const installMsg = this.props.installMsg + ? this.props.installMsg + : 'Imports index pattern, visualizations and pre-defined dashboards.'; + const installStep = ( + + + + +

{installMsg}

+
+
+ + + + {this.state.buttonLabel} + + +
+ + + + {this.renderInstallMessage()} +
+ ); + + return { + title: 'Load Kibana objects', + status: this.state.isInstalled ? 'complete' : 'incomplete', + children: installStep, + key: 'installStep' + }; + } + + render() { + return ( + + ); + } +} + +const savedObjectShape = PropTypes.shape({ + id: PropTypes.string.isRequired, + type: PropTypes.string.isRequired, + attributes: PropTypes.object.isRequired, +}); + +SavedObjectsInstaller.propTypes = { + bulkCreate: PropTypes.func.isRequired, + savedObjects: PropTypes.arrayOf(savedObjectShape).isRequired, + installMsg: PropTypes.string, +}; diff --git a/src/core_plugins/kibana/public/home/components/tutorial/saved_objects_installer.test.js b/src/core_plugins/kibana/public/home/components/tutorial/saved_objects_installer.test.js new file mode 100644 index 0000000000000..1c28831679a24 --- /dev/null +++ b/src/core_plugins/kibana/public/home/components/tutorial/saved_objects_installer.test.js @@ -0,0 +1,79 @@ +/* + * 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 { shallow, mount } from 'enzyme'; +import { findTestSubject } from '@elastic/eui/lib/test'; + +import { SavedObjectsInstaller } from './saved_objects_installer'; + +test('renders', () => { + const component = shallow( {}} + savedObjects={[]} + />); + expect(component).toMatchSnapshot(); +}); + +describe('bulkCreate', () => { + const savedObject = { + id: '1', + type: 'index-pattern', + attributes: {} + }; + test('should display success message when bulkCreate is successful', async () => { + const bulkCreateMock = () => { + return Promise.resolve({ + savedObjects: [savedObject] + }); + }; + const component = mount(); + + findTestSubject(component, 'loadSavedObjects').simulate('click'); + + // Ensure all promises resolve + await new Promise(resolve => process.nextTick(resolve)); + // Ensure the state changes are reflected + component.update(); + + expect(component).toMatchSnapshot(); + }); + + test('should display error message when bulkCreate request fails', async () => { + const bulkCreateMock = () => { + return Promise.reject(new Error('simulated bulkRequest error')); + }; + const component = mount(); + + findTestSubject(component, 'loadSavedObjects').simulate('click'); + + // Ensure all promises resolve + await new Promise(resolve => process.nextTick(resolve)); + // Ensure the state changes are reflected + component.update(); + + expect(component).toMatchSnapshot(); + }); +}); diff --git a/src/core_plugins/kibana/public/home/components/tutorial/tutorial.js b/src/core_plugins/kibana/public/home/components/tutorial/tutorial.js index 2daf164a75b58..ff34d3f616a0c 100644 --- a/src/core_plugins/kibana/public/home/components/tutorial/tutorial.js +++ b/src/core_plugins/kibana/public/home/components/tutorial/tutorial.js @@ -25,6 +25,7 @@ import { Footer } from './footer'; import { Introduction } from './introduction'; import { InstructionSet } from './instruction_set'; import { RadioButtonGroup } from './radio_button_group'; +import { SavedObjectsInstaller } from './saved_objects_installer'; import { EuiSpacer, EuiPage, EuiPanel, EuiLink, EuiText, EuiPageBody } from '@elastic/eui'; import * as StatusCheckStates from './status_check_states'; @@ -235,6 +236,21 @@ export class Tutorial extends React.Component { }); }; + renderSavedObjectsInstaller = () => { + if (!this.state.tutorial.savedObjects) { + return; + } + + return ( + + ); + + } + renderFooter = () => { let label; let url; @@ -306,6 +322,7 @@ export class Tutorial extends React.Component { {this.renderInstructionSets(instructions)} + {this.renderSavedObjectsInstaller()} {this.renderFooter()}
@@ -333,4 +350,5 @@ Tutorial.propTypes = { getTutorial: PropTypes.func.isRequired, replaceTemplateStrings: PropTypes.func.isRequired, tutorialId: PropTypes.string.isRequired, + bulkCreate: PropTypes.func.isRequired, }; diff --git a/src/core_plugins/kibana/public/home/components/tutorial/tutorial.test.js b/src/core_plugins/kibana/public/home/components/tutorial/tutorial.test.js index 4a29fa9bd1572..040fd671fc027 100644 --- a/src/core_plugins/kibana/public/home/components/tutorial/tutorial.test.js +++ b/src/core_plugins/kibana/public/home/components/tutorial/tutorial.test.js @@ -72,6 +72,7 @@ describe('isCloudEnabled is false', () => { getTutorial={getTutorial} replaceTemplateStrings={replaceTemplateStrings} tutorialId={'my_testing_tutorial'} + bulkCreate={() => {}} />); loadTutorialPromise.then(() => { component.update(); @@ -95,6 +96,7 @@ describe('isCloudEnabled is false', () => { getTutorial={getBasicTutorial} replaceTemplateStrings={replaceTemplateStrings} tutorialId={'my_testing_tutorial'} + bulkCreate={() => {}} />); loadBasicTutorialPromise.then(() => { component.update(); @@ -109,6 +111,7 @@ describe('isCloudEnabled is false', () => { getTutorial={getTutorial} replaceTemplateStrings={replaceTemplateStrings} tutorialId={'my_testing_tutorial'} + bulkCreate={() => {}} />); loadTutorialPromise.then(() => { component.update(); @@ -126,6 +129,7 @@ test('should render ELASTIC_CLOUD instructions when isCloudEnabled is true', () getTutorial={getTutorial} replaceTemplateStrings={replaceTemplateStrings} tutorialId={'my_testing_tutorial'} + bulkCreate={() => {}} />); loadTutorialPromise.then(() => { component.update(); diff --git a/src/core_plugins/kibana/public/home/home_ng_wrapper.html b/src/core_plugins/kibana/public/home/home_ng_wrapper.html index e0baaefe64bc0..18fb52e7e733c 100644 --- a/src/core_plugins/kibana/public/home/home_ng_wrapper.html +++ b/src/core_plugins/kibana/public/home/home_ng_wrapper.html @@ -5,4 +5,5 @@ get-config="getConfig" set-config="setConfig" clear-index-patterns-cache="clearIndexPatternsCache" + bulk-create="bulkCreate" /> diff --git a/src/core_plugins/kibana/public/home/index.js b/src/core_plugins/kibana/public/home/index.js index d2855a8b8e9cf..c66409010965d 100644 --- a/src/core_plugins/kibana/public/home/index.js +++ b/src/core_plugins/kibana/public/home/index.js @@ -49,6 +49,7 @@ function getRoute() { const getter = indexPatterns.getIds; getter.clearCache(); }; + $scope.bulkCreate = chrome.getSavedObjectsClient().bulkCreate; } }; } diff --git a/src/core_plugins/kibana/server/tutorials/apm/index.js b/src/core_plugins/kibana/server/tutorials/apm/index.js index ca2661db97ee5..72224ead9c610 100644 --- a/src/core_plugins/kibana/server/tutorials/apm/index.js +++ b/src/core_plugins/kibana/server/tutorials/apm/index.js @@ -20,19 +20,32 @@ import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; import { onPremInstructions } from './on_prem'; import { ELASTIC_CLOUD_INSTRUCTIONS } from './elastic_cloud'; +import { getSavedObjects } from './saved_objects/get_saved_objects'; const apmIntro = 'Collect in-depth performance metrics and errors from inside your applications.'; -function isEnabled(config, key) { - try { - return config.get(key); - } catch (err) { - return false; +const ENABLED_KEY = 'xpack.apm.ui.enabled'; +function isEnabled(config) { + if (config.has(ENABLED_KEY)) { + return config.get(ENABLED_KEY); } + + return false; +} + +const TITLE_KEY = 'xpack.apm.indexPattern'; +const DEFAULT_TITLE = 'apm*'; +function getIndexPatternTitle(config) { + if (config.has(TITLE_KEY)) { + return config.get(TITLE_KEY); + } + + return DEFAULT_TITLE; } export function apmSpecProvider(server) { const config = server.config(); + const apmIndexPattern = getIndexPatternTitle(config); const artifacts = { dashboards: [ @@ -43,7 +56,7 @@ export function apmSpecProvider(server) { } ] }; - if (isEnabled(config, 'xpack.apm.ui.enabled')) { + if (isEnabled(config)) { artifacts.application = { path: '/app/apm', label: 'Launch APM' @@ -61,8 +74,11 @@ export function apmSpecProvider(server) { ' [Learn more]({config.docs.base_url}guide/en/apm/get-started/{config.docs.version}/index.html).', euiIconType: 'apmApp', artifacts: artifacts, - onPrem: onPremInstructions(server), + onPrem: onPremInstructions(apmIndexPattern), elasticCloud: ELASTIC_CLOUD_INSTRUCTIONS, previewImagePath: '/plugins/kibana/home/tutorial_resources/apm/apm.png', + savedObjects: getSavedObjects(apmIndexPattern), + savedObjectsInstallMsg: 'Load index pattern, visualizations, and pre-defined dashboards.' + + ' An index pattern is required for some features in the APM UI.', }; } diff --git a/src/core_plugins/kibana/server/tutorials/apm/on_prem.js b/src/core_plugins/kibana/server/tutorials/apm/on_prem.js index 4ee574f4fb292..fdbb50b12783c 100644 --- a/src/core_plugins/kibana/server/tutorials/apm/on_prem.js +++ b/src/core_plugins/kibana/server/tutorials/apm/on_prem.js @@ -38,14 +38,7 @@ import { JAVA_CLIENT_INSTRUCTIONS, } from './apm_client_instructions'; -export function onPremInstructions(server) { - let apmIndexPattern = 'apm*'; - try { - apmIndexPattern = server.config().get('xpack.apm.indexPattern'); - } catch (error) { - // ignore error when config does not contain 'xpack.apm.indexPattern'. - // This is expected when APM plugin is not running. - } +export function onPremInstructions(apmIndexPattern) { return { instructionSets: [ diff --git a/src/core_plugins/kibana/server/tutorials/apm/saved_objects/get_saved_objects.js b/src/core_plugins/kibana/server/tutorials/apm/saved_objects/get_saved_objects.js new file mode 100644 index 0000000000000..c76b1bff404c8 --- /dev/null +++ b/src/core_plugins/kibana/server/tutorials/apm/saved_objects/get_saved_objects.js @@ -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 indexPattern from './index_pattern.json'; +import staticSavedObjects from './saved_objects.json'; + +function getIndexPattern(apmIndexPattern) { + indexPattern.attributes.title = apmIndexPattern; + return indexPattern; +} + +export function getSavedObjects(server) { + return [getIndexPattern(server), ...staticSavedObjects]; +} diff --git a/src/core_plugins/kibana/server/tutorials/apm/saved_objects/get_saved_objects.test.js b/src/core_plugins/kibana/server/tutorials/apm/saved_objects/get_saved_objects.test.js new file mode 100644 index 0000000000000..19991f17877b0 --- /dev/null +++ b/src/core_plugins/kibana/server/tutorials/apm/saved_objects/get_saved_objects.test.js @@ -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 expect from 'expect.js'; +import { getSavedObjects } from './get_saved_objects'; + +const indexPatternTitle = 'dynamic index pattern title'; + +test('should dynamically set index title to "xpack.apm.indexPattern" yaml config value', () => { + const savedObjects = getSavedObjects(indexPatternTitle); + const indexPattern = savedObjects[0]; + expect(indexPattern.type).to.be('index-pattern'); + // if index pattern id changes, ensure other saved objects point to the new id + expect(indexPattern.id).to.be('12e52550-6354-11e8-9d01-ed6a4badd083'); + expect(indexPattern.attributes.title).to.be(indexPatternTitle); +}); diff --git a/src/core_plugins/kibana/server/tutorials/apm/saved_objects/index_pattern.json b/src/core_plugins/kibana/server/tutorials/apm/saved_objects/index_pattern.json new file mode 100644 index 0000000000000..f152bc9c139ac --- /dev/null +++ b/src/core_plugins/kibana/server/tutorials/apm/saved_objects/index_pattern.json @@ -0,0 +1,9 @@ +{ + "id": "12e52550-6354-11e8-9d01-ed6a4badd083", + "type": "index-pattern", + "version": 0, + "attributes": { + "timeFieldName": "@timestamp", + "fields": "[{\"name\":\"@timestamp\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"beat.hostname\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.timezone\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.process.pid\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.process.title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.request.http_version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.request.method\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.request.url.full\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.request.url.hash\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.request.url.hostname\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.request.url.pathname\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.request.url.port\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.request.url.protocol\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.request.url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.request.url.search\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.response.finished\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.response.status_code\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.service.agent.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.service.agent.version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.service.environment\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.service.framework.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.service.framework.version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.service.language.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.service.language.version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.service.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.service.runtime.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.service.runtime.version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.service.version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.system.architecture\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.system.hostname\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.system.platform\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.tags.foo\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.tags.lorem\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.tags.multi-line\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.tags.this-is-a-very-long-tag-name-without-any-spaces\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.user.email\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.user.id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"context.user.username\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.container.id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.container.image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.container.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error id icon\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error.code\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error.culprit\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"error.exception.code\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error.exception.handled\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error.exception.message\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"error.exception.module\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error.exception.type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error.grouping_key\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error.id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error.log.level\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error.log.logger_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error.log.message\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"error.log.param_message\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error.message\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"error.type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.namespace\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"listening\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.cloud.availability_zone\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.cloud.instance_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.cloud.instance_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.cloud.machine_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.cloud.project_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.cloud.provider\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.cloud.region\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"processor.event\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"processor.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"sourcemap.bundle_filepath\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"sourcemap.service.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"sourcemap.service.version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"span.duration.us\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"span.id\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"span.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"span.parent\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"span.start.us\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"span.type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tags\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.duration.us\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"transaction.name.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.result\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.sampled\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.span_count.dropped.total\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"view errors\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"view spans\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]" + } +} diff --git a/src/core_plugins/kibana/server/tutorials/apm/saved_objects/saved_objects.json b/src/core_plugins/kibana/server/tutorials/apm/saved_objects/saved_objects.json new file mode 100644 index 0000000000000..09198357cc399 --- /dev/null +++ b/src/core_plugins/kibana/server/tutorials/apm/saved_objects/saved_objects.json @@ -0,0 +1,262 @@ +[ + { + "id": "1ffc5e20-7827-11e7-8c47-65b845b5cfb3", + "type": "visualization", + "version": 1, + "attributes": { + "title": "Services [APM]", + "visState": "{\"title\":\"Services [APM]\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"transaction.duration.us\",\"customLabel\":\"Avg. Resp. Time\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"percentiles\",\"schema\":\"metric\",\"params\":{\"field\":\"transaction.duration.us\",\"percents\":[95],\"customLabel\":\"Resp. Time\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"cardinality\",\"schema\":\"metric\",\"params\":{\"field\":\"transaction.id\",\"customLabel\":\"Total Transactions\"}},{\"id\":\"6\",\"enabled\":true,\"type\":\"cardinality\",\"schema\":\"metric\",\"params\":{\"field\":\"error.id\",\"customLabel\":\"Errors\"}},{\"id\":\"5\",\"enabled\":true,\"type\":\"top_hits\",\"schema\":\"metric\",\"params\":{\"field\":\"view errors\",\"aggregate\":\"concat\",\"size\":1,\"sortField\":\"@timestamp\",\"sortOrder\":\"desc\",\"customLabel\":\"-\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"context.service.name\",\"size\":1000,\"order\":\"desc\",\"orderBy\":\"1\"}}]}", + "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"12e52550-6354-11e8-9d01-ed6a4badd083\",\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"}}" + } + } + }, + { + "id": "1bdca740-7828-11e7-8c47-65b845b5cfb3", + "type": "visualization", + "version": 2, + "attributes": { + "title": "Top Services by Response Time [APM]", + "visState": "{\"title\":\"Top Services by Response Time [APM]\",\"type\":\"metrics\",\"params\":{\"id\":\"61ca57f0-469d-11e7-af02-69e470af7417\",\"type\":\"timeseries\",\"series\":[{\"id\":\"61ca57f1-469d-11e7-af02-69e470af7417\",\"color\":\"rgba(0,156,224,1)\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"61ca57f2-469d-11e7-af02-69e470af7417\",\"type\":\"avg\",\"field\":\"transaction.duration.us\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"us,ms,0\",\"chart_type\":\"line\",\"line_width\":\"2\",\"point_size\":1,\"fill\":\"0\",\"stacked\":\"none\",\"terms_field\":\"context.service.name\",\"value_template\":\"{{value}} ms\",\"split_color_mode\":\"gradient\",\"terms_order_by\":\"61ca57f2-469d-11e7-af02-69e470af7417\"}],\"time_field\":\"@timestamp\",\"interval\":\">=1m\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"show_grid\":1},\"aggs\":[]}", + "uiStateJSON": "{}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"12e52550-6354-11e8-9d01-ed6a4badd083\",\"query\":{\"query\":\"\",\"language\":\"lucene\"}}" + } + } + }, + { + "id": "804ffc40-7828-11e7-8c47-65b845b5cfb3", + "type": "visualization", + "version": 1, + "attributes": { + "title": "Top Services by Request Per Minute [APM]", + "visState": "{\"title\":\"Top Apps by Request Per Minute [APM]\",\"type\":\"metrics\",\"params\":{\"id\":\"61ca57f0-469d-11e7-af02-69e470af7417\",\"type\":\"timeseries\",\"series\":[{\"id\":\"61ca57f1-469d-11e7-af02-69e470af7417\",\"color\":\"rgba(0,156,224,1)\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"61ca57f2-469d-11e7-af02-69e470af7417\",\"type\":\"count\"},{\"id\":\"3fcaa6c0-7828-11e7-bb25-2ff6dee07a1b\",\"type\":\"cumulative_sum\",\"field\":\"61ca57f2-469d-11e7-af02-69e470af7417\"},{\"unit\":\"1m\",\"id\":\"467f1cd0-7828-11e7-bb25-2ff6dee07a1b\",\"type\":\"derivative\",\"field\":\"3fcaa6c0-7828-11e7-bb25-2ff6dee07a1b\"},{\"unit\":\"\",\"id\":\"4bd1b8f0-7828-11e7-bb25-2ff6dee07a1b\",\"type\":\"positive_only\",\"field\":\"467f1cd0-7828-11e7-bb25-2ff6dee07a1b\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":\"2\",\"point_size\":1,\"fill\":\"0\",\"stacked\":\"none\",\"terms_field\":\"context.service.name\",\"terms_order_by\":\"_count\",\"value_template\":\"{{value}} rpm\"}],\"time_field\":\"@timestamp\",\"interval\":\">=1m\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"show_grid\":1},\"aggs\":[]}", + "uiStateJSON": "{}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"12e52550-6354-11e8-9d01-ed6a4badd083\",\"query\":{\"query\":\"\",\"language\":\"lucene\"}}" + } + } + }, + { + "id": "8d3ed660-7828-11e7-8c47-65b845b5cfb3", + "type": "dashboard", + "version": 1, + "attributes": { + "title": "[APM] Services", + "hits": 0, + "description": "", + "panelsJSON": "[{\"col\":1,\"id\":\"1ffc5e20-7827-11e7-8c47-65b845b5cfb3\",\"panelIndex\":1,\"row\":4,\"size_x\":12,\"size_y\":5,\"type\":\"visualization\"},{\"col\":1,\"id\":\"1bdca740-7828-11e7-8c47-65b845b5cfb3\",\"panelIndex\":2,\"row\":1,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"804ffc40-7828-11e7-8c47-65b845b5cfb3\",\"panelIndex\":3,\"row\":1,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"}]", + "optionsJSON": "{\"darkTheme\":false}", + "uiStateJSON": "{\"P-1\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}}", + "version": 1, + "timeRestore": false, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"language\":\"lucene\",\"query\":\"\"},\"filter\":[],\"highlightAll\":true,\"version\":true}" + } + } + }, + { + "id": "c618e4e0-7c69-11e7-aa55-3b0d52c71c60", + "type": "visualization", + "version": 1, + "attributes": { + "title": "Error Occurrences [APM]", + "visState": "{\"title\":\"Error Occurrences [APM]\",\"type\":\"metrics\",\"params\":{\"id\":\"61ca57f0-469d-11e7-af02-69e470af7417\",\"type\":\"timeseries\",\"series\":[{\"id\":\"61ca57f1-469d-11e7-af02-69e470af7417\",\"color\":\"rgba(0,156,224,1)\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"61ca57f2-469d-11e7-af02-69e470af7417\",\"type\":\"count\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"bar\",\"line_width\":\"0\",\"point_size\":1,\"fill\":\"1\",\"stacked\":\"none\",\"label\":\"Occurrences\",\"terms_field\":\"error.grouping_key\"}],\"time_field\":\"@timestamp\",\"interval\":\">=1m\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":0,\"show_grid\":1,\"filter\":\"processor.event:error\"},\"aggs\":[]}", + "uiStateJSON": "{}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"12e52550-6354-11e8-9d01-ed6a4badd083\",\"query\":{\"query\":\"\",\"language\":\"lucene\"}}" + } + } + }, + { + "id": "ceefd050-7c6a-11e7-aa55-3b0d52c71c60", + "type": "search", + "version": 1, + "attributes": { + "title": "Error Details [APM]", + "description": "", + "hits": 0, + "columns": [ + "error.culprit", + "error.exception.type", + "error.exception.message", + "error.log.message", + "error.exception.handled", + "context.service.name" + ], + "sort": [ + "@timestamp", + "desc" + ], + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"12e52550-6354-11e8-9d01-ed6a4badd083\",\"highlightAll\":true,\"version\":true,\"query\":{\"language\":\"lucene\",\"query\":\"\"},\"filter\":[{\"$state\":{\"store\":\"appState\"},\"meta\":{\"alias\":null,\"disabled\":false,\"index\":\"12e52550-6354-11e8-9d01-ed6a4badd083\",\"key\":\"processor.event\",\"negate\":false,\"params\":{\"query\":\"error\",\"type\":\"phrase\"},\"type\":\"phrase\",\"value\":\"error\"},\"query\":{\"match\":{\"processor.event\":{\"query\":\"error\",\"type\":\"phrase\"}}}}]}" + } + } + }, + { + "id": "5f08a870-7c6a-11e7-aa55-3b0d52c71c60", + "type": "dashboard", + "version": 1, + "attributes": { + "title": "[APM] Error Details", + "hits": 0, + "description": "", + "panelsJSON": "[{\"col\":1,\"id\":\"c618e4e0-7c69-11e7-aa55-3b0d52c71c60\",\"panelIndex\":1,\"row\":1,\"size_x\":12,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"columns\":[\"error.culprit\",\"error.exception.type\",\"error.exception.message\",\"error.log.message\",\"error.exception.handled\",\"context.service.name\"],\"id\":\"ceefd050-7c6a-11e7-aa55-3b0d52c71c60\",\"panelIndex\":2,\"row\":4,\"size_x\":12,\"size_y\":21,\"sort\":[\"@timestamp\",\"desc\"],\"type\":\"search\"}]", + "optionsJSON": "{\"darkTheme\":false}", + "uiStateJSON": "{}", + "version": 1, + "timeRestore": false, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"language\":\"lucene\",\"query\":\"\"},\"filter\":[],\"highlightAll\":true,\"version\":true}" + } + } + }, + { + "id": "22518e70-7c69-11e7-aa55-3b0d52c71c60", + "type": "visualization", + "version": 1, + "attributes": { + "title": "Top Errors for Time Period [APM]", + "visState": "{\"title\":\"Top Errors for Time Period [APM]\",\"type\":\"table\",\"params\":{\"perPage\":25,\"showMeticsAtAllLevels\":false,\"showPartialRows\":false,\"showTotal\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"error id icon\",\"size\":100,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"-\"}},{\"id\":\"5\",\"enabled\":true,\"type\":\"top_hits\",\"schema\":\"metric\",\"params\":{\"field\":\"error.exception.message\",\"aggregate\":\"concat\",\"size\":1,\"sortField\":\"@timestamp\",\"sortOrder\":\"desc\",\"customLabel\":\"Message\"}},{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"Number of Errors\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"top_hits\",\"schema\":\"metric\",\"params\":{\"field\":\"error.exception.type\",\"aggregate\":\"concat\",\"size\":1,\"sortField\":\"@timestamp\",\"sortOrder\":\"desc\",\"customLabel\":\"Type\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"top_hits\",\"schema\":\"metric\",\"params\":{\"field\":\"error.culprit\",\"aggregate\":\"concat\",\"size\":1,\"sortField\":\"@timestamp\",\"sortOrder\":\"desc\",\"customLabel\":\"Culprit\"}},{\"id\":\"6\",\"enabled\":true,\"type\":\"top_hits\",\"schema\":\"metric\",\"params\":{\"field\":\"context.service.name\",\"aggregate\":\"concat\",\"size\":1,\"sortField\":\"@timestamp\",\"sortOrder\":\"desc\",\"customLabel\":\"App Name\"}},{\"id\":\"7\",\"enabled\":true,\"type\":\"top_hits\",\"schema\":\"metric\",\"params\":{\"field\":\"error.grouping_key\",\"aggregate\":\"concat\",\"size\":1,\"sortField\":\"@timestamp\",\"sortOrder\":\"desc\",\"customLabel\":\"-\"}}]}", + "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"12e52550-6354-11e8-9d01-ed6a4badd083\",\"filter\":[],\"query\":{\"language\":\"lucene\",\"query\":\"\"}}" + } + } + }, + { + "id": "37f6fac0-7c6a-11e7-aa55-3b0d52c71c60", + "type": "dashboard", + "version": 1, + "attributes": { + "title": "[APM] Errors", + "hits": 0, + "description": "", + "panelsJSON": "[{\"col\":1,\"id\":\"22518e70-7c69-11e7-aa55-3b0d52c71c60\",\"panelIndex\":1,\"row\":4,\"size_x\":12,\"size_y\":10,\"type\":\"visualization\"},{\"col\":1,\"id\":\"c618e4e0-7c69-11e7-aa55-3b0d52c71c60\",\"panelIndex\":2,\"row\":1,\"size_x\":12,\"size_y\":3,\"type\":\"visualization\"}]", + "optionsJSON": "{\"darkTheme\":false}", + "uiStateJSON": "{\"P-1\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}}", + "version": 1, + "timeRestore": false, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"language\":\"lucene\",\"query\":\"\"},\"filter\":[],\"highlightAll\":true,\"version\":true}" + } + } + }, + { + "id": "a2e199b0-7820-11e7-8c47-65b845b5cfb3", + "type": "visualization", + "version": 1, + "attributes": { + "title": "Top Transactions for Time Period [APM]", + "visState": "{\"aggs\":[{\"enabled\":true,\"id\":\"2\",\"params\":{\"customLabel\":\"Transaction\",\"field\":\"transaction.name.keyword\",\"order\":\"desc\",\"orderBy\":\"1\",\"size\":1000},\"schema\":\"bucket\",\"type\":\"terms\"},{\"enabled\":true,\"id\":\"5\",\"params\":{\"aggregate\":\"concat\",\"customLabel\":\"Type\",\"field\":\"transaction.type\",\"size\":1,\"sortField\":\"@timestamp\",\"sortOrder\":\"desc\"},\"schema\":\"metric\",\"type\":\"top_hits\"},{\"enabled\":true,\"id\":\"1\",\"params\":{\"customLabel\":\"Avg. Resp Time (ms)\",\"field\":\"transaction.duration.us\"},\"schema\":\"metric\",\"type\":\"avg\"},{\"enabled\":true,\"id\":\"3\",\"params\":{\"customLabel\":\"Resp Time (ms)\",\"field\":\"transaction.duration.us\",\"percents\":[95]},\"schema\":\"metric\",\"type\":\"percentiles\"},{\"enabled\":true,\"id\":\"4\",\"params\":{\"aggregate\":\"concat\",\"customLabel\":\"View Spans\",\"field\":\"transaction.id\",\"size\":1,\"sortField\":\"@timestamp\",\"sortOrder\":\"desc\"},\"schema\":\"metric\",\"type\":\"top_hits\"}],\"params\":{\"perPage\":25,\"showMeticsAtAllLevels\":false,\"showPartialRows\":false,\"showTotal\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"totalFunc\":\"sum\"},\"title\":\"Top Transactions for Time Period [APM]\",\"type\":\"table\"}", + "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"12e52550-6354-11e8-9d01-ed6a4badd083\",\"filter\":[],\"query\":{\"language\":\"lucene\",\"query\":\"\"}}" + } + } + }, + { + "id": "09bcf890-7822-11e7-8c47-65b845b5cfb3", + "type": "visualization", + "version": 2, + "attributes": { + "title": "Response Times [APM]", + "visState": "{\"title\":\"Response Times [APM]\",\"type\":\"metrics\",\"params\":{\"id\":\"61ca57f0-469d-11e7-af02-69e470af7417\",\"type\":\"timeseries\",\"series\":[{\"id\":\"61ca57f1-469d-11e7-af02-69e470af7417\",\"color\":\"rgba(0,156,224,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"61ca57f2-469d-11e7-af02-69e470af7417\",\"type\":\"avg\",\"field\":\"transaction.duration.us\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"us,ms,0\",\"chart_type\":\"line\",\"line_width\":\"2\",\"point_size\":1,\"fill\":\"0\",\"stacked\":\"none\",\"value_template\":\"{{value}} ms\",\"label\":\"Average\"},{\"id\":\"79921480-7821-11e7-8745-07eaffcb65e5\",\"color\":\"rgba(115,216,255,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"79921481-7821-11e7-8745-07eaffcb65e5\",\"type\":\"percentile\",\"field\":\"transaction.duration.us\",\"percentiles\":[{\"value\":\"95\",\"percentile\":\"\",\"shade\":0.2,\"id\":\"858ec670-7821-11e7-8745-07eaffcb65e5\",\"mode\":\"line\"}]}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"us,ms,0\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"value_template\":\"{{value}} ms\",\"label\":\"95th Percentile\"},{\"id\":\"c1e42de0-7821-11e7-8745-07eaffcb65e5\",\"color\":\"rgba(254,146,0,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"c1e42de1-7821-11e7-8745-07eaffcb65e5\",\"type\":\"percentile\",\"field\":\"transaction.duration.us\",\"percentiles\":[{\"value\":\"99\",\"percentile\":\"\",\"shade\":0.2,\"id\":\"858ec670-7821-11e7-8745-07eaffcb65e5\",\"mode\":\"line\"}]}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"us,ms,0\",\"chart_type\":\"line\",\"line_width\":\"2\",\"point_size\":1,\"fill\":\"0\",\"stacked\":\"none\",\"value_template\":\"{{value}} ms\",\"label\":\"99th Percentile\"}],\"time_field\":\"@timestamp\",\"interval\":\">=1m\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"show_grid\":1,\"legend_position\":\"right\"},\"aggs\":[]}", + "uiStateJSON": "{}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"12e52550-6354-11e8-9d01-ed6a4badd083\",\"query\":{\"language\":\"lucene\",\"query\":\"\"}}" + } + } + }, + { + "id": "55606a60-7823-11e7-8c47-65b845b5cfb3", + "type": "visualization", + "version": 1, + "attributes": { + "title": "Request Per Minute [APM]", + "visState": "{\"title\":\"Request Per Minute [APM]\",\"type\":\"metrics\",\"params\":{\"id\":\"61ca57f0-469d-11e7-af02-69e470af7417\",\"type\":\"timeseries\",\"series\":[{\"id\":\"61ca57f1-469d-11e7-af02-69e470af7417\",\"color\":\"rgba(115,216,255,1)\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"61ca57f2-469d-11e7-af02-69e470af7417\",\"type\":\"count\"},{\"id\":\"3fcaa6c0-7828-11e7-bb25-2ff6dee07a1b\",\"type\":\"cumulative_sum\",\"field\":\"61ca57f2-469d-11e7-af02-69e470af7417\"},{\"unit\":\"1m\",\"id\":\"467f1cd0-7828-11e7-bb25-2ff6dee07a1b\",\"type\":\"derivative\",\"field\":\"3fcaa6c0-7828-11e7-bb25-2ff6dee07a1b\"},{\"unit\":\"\",\"id\":\"4bd1b8f0-7828-11e7-bb25-2ff6dee07a1b\",\"type\":\"positive_only\",\"field\":\"467f1cd0-7828-11e7-bb25-2ff6dee07a1b\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":\"2\",\"point_size\":\"0\",\"fill\":\"0\",\"stacked\":\"none\",\"label\":\"\",\"value_template\":\"{{value}} rpm\",\"terms_field\":\"transaction.result\"}],\"time_field\":\"@timestamp\",\"interval\":\">=1m\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"show_grid\":1},\"aggs\":[]}", + "uiStateJSON": "{}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"12e52550-6354-11e8-9d01-ed6a4badd083\",\"query\":{\"language\":\"lucene\",\"query\":\"\"}}" + } + } + }, + { + "id": "41b5d920-7821-11e7-8c47-65b845b5cfb3", + "type": "dashboard", + "version": 1, + "attributes": { + "title": "[APM] Transactions", + "hits": 0, + "description": "", + "panelsJSON": "[{\"col\":1,\"id\":\"a2e199b0-7820-11e7-8c47-65b845b5cfb3\",\"panelIndex\":1,\"row\":4,\"size_x\":12,\"size_y\":10,\"type\":\"visualization\"},{\"col\":1,\"id\":\"09bcf890-7822-11e7-8c47-65b845b5cfb3\",\"panelIndex\":2,\"row\":1,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"55606a60-7823-11e7-8c47-65b845b5cfb3\",\"panelIndex\":3,\"row\":1,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"}]", + "optionsJSON": "{\"darkTheme\":false}", + "uiStateJSON": "{\"P-1\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}}", + "version": 1, + "timeRestore": false, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"language\":\"lucene\",\"query\":\"\"},\"filter\":[],\"highlightAll\":true,\"version\":true}" + } + } + }, + { + "id": "d7735b90-7ddf-11e7-b115-df9c90da2df1", + "type": "search", + "version": 1, + "attributes": { + "title": "Spans [APM]", + "description": "", + "hits": 0, + "columns": [ + "span.type", + "span.name", + "span.duration.us", + "span.start.us" + ], + "sort": [ + "span.start.us", + "asc" + ], + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"12e52550-6354-11e8-9d01-ed6a4badd083\",\"highlightAll\":true,\"version\":true,\"query\":{\"language\":\"lucene\",\"query\":\"\"},\"filter\":[{\"meta\":{\"index\":\"12e52550-6354-11e8-9d01-ed6a4badd083\",\"negate\":false,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"processor.event\",\"value\":\"span\",\"params\":{\"query\":\"span\",\"type\":\"phrase\"}},\"query\":{\"match\":{\"processor.event\":{\"query\":\"span\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}]}" + } + } + }, + { + "id": "3e3de700-7de0-11e7-b115-df9c90da2df1", + "type": "dashboard", + "version": 2, + "attributes": { + "title": "[APM] Span Details", + "hits": 0, + "description": "", + "panelsJSON": "[{\"size_x\":12,\"size_y\":23,\"panelIndex\":1,\"type\":\"search\",\"id\":\"d7735b90-7ddf-11e7-b115-df9c90da2df1\",\"col\":1,\"row\":1,\"columns\":[\"span.type\",\"span.name\",\"span.duration.us\",\"span.start.us\"],\"sort\":[\"span.start.us\",\"asc\"]}]", + "optionsJSON": "{\"darkTheme\":false}", + "uiStateJSON": "{}", + "version": 1, + "timeRestore": false, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"highlightAll\":true,\"version\":true}" + } + } + } +] diff --git a/src/ui/public/saved_objects/saved_object.js b/src/ui/public/saved_objects/saved_object.js index 98704d387e4d7..8e129bfbc7ece 100644 --- a/src/ui/public/saved_objects/saved_object.js +++ b/src/ui/public/saved_objects/saved_object.js @@ -20,12 +20,15 @@ import _ from 'lodash'; export class SavedObject { - constructor(client, { id, type, version, attributes } = {}) { + constructor(client, { id, type, version, attributes, error } = {}) { this._client = client; this.id = id; this.type = type; this.attributes = attributes || {}; this._version = version; + if (error) { + this.error = error; + } } get(key) { diff --git a/test/functional/apps/home/_add_data.js b/test/functional/apps/home/_add_data.js index 0902bd8d2161c..3dddd2c584cf9 100644 --- a/test/functional/apps/home/_add_data.js +++ b/test/functional/apps/home/_add_data.js @@ -21,7 +21,7 @@ import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { const retry = getService('retry'); - const PageObjects = getPageObjects(['common', 'header', 'home']); + const PageObjects = getPageObjects(['common', 'header', 'home', 'dashboard']); describe('add data tutorials', function describeIndexTests() { @@ -34,5 +34,25 @@ export default function ({ getService, getPageObjects }) { }); }); + describe('apm', function describeIndexTests() { + + it('should install saved objects', async ()=> { + await PageObjects.common.navigateToUrl('home', 'tutorial_directory'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await retry.try(async () => { + await PageObjects.home.clickSynopsis('apm'); + }); + + await PageObjects.home.loadSavedObjects(); + + await PageObjects.common.navigateToApp('dashboard'); + + await PageObjects.dashboard.searchForDashboardWithName('APM'); + const countOfDashboards = await PageObjects.dashboard.getCountOfDashboardsInListingTable(); + expect(countOfDashboards).to.equal(5); + }); + + }); + }); } diff --git a/test/functional/page_objects/home_page.js b/test/functional/page_objects/home_page.js index 3acb03080bd8c..9b1c3d6a5c741 100644 --- a/test/functional/page_objects/home_page.js +++ b/test/functional/page_objects/home_page.js @@ -17,9 +17,9 @@ * under the License. */ - export function HomePageProvider({ getService }) { const testSubjects = getService('testSubjects'); + const retry = getService('retry'); class HomePage { @@ -63,6 +63,16 @@ export function HomePageProvider({ getService }) { await testSubjects.click(`launchSampleDataSet${id}`); } + async loadSavedObjects() { + await retry.try(async () => { + await testSubjects.click('loadSavedObjects'); + const successMsgExists = await testSubjects.exists('loadSavedObjects_success', 5000); + if (!successMsgExists) { + throw new Error('Failed to load saved objects'); + } + }); + } + } return new HomePage();