diff --git a/src/core_plugins/kibana/common/tutorials/tutorial_schema.js b/src/core_plugins/kibana/common/tutorials/tutorial_schema.js
index 9baebd8c85678..58fb0ba9e14a1 100644
--- a/src/core_plugins/kibana/common/tutorials/tutorial_schema.js
+++ b/src/core_plugins/kibana/common/tutorials/tutorial_schema.js
@@ -25,6 +25,18 @@ const artifactsSchema = Joi.object({
}),
});
+const statusCheckSchema = Joi.object({
+ title: Joi.string(),
+ text: Joi.string(),
+ btnLabel: Joi.string(),
+ success: Joi.string(),
+ error: Joi.string(),
+ esHitsCheck: Joi.object({
+ index: Joi.string().required(),
+ query: Joi.object().required(),
+ }).required(),
+});
+
const instructionSchema = Joi.object({
title: Joi.string(),
textPre: Joi.string(),
@@ -40,7 +52,8 @@ const instructionVariantSchema = Joi.object({
const instructionSetSchema = Joi.object({
title: Joi.string(),
// Variants (OSes, languages, etc.) for which tutorial instructions are specified.
- instructionVariants: Joi.array().items(instructionVariantSchema).required()
+ instructionVariants: Joi.array().items(instructionVariantSchema).required(),
+ statusCheck: statusCheckSchema,
});
const paramSchema = Joi.object({
diff --git a/src/core_plugins/kibana/public/home/components/tutorial/__snapshots__/instruction_set.test.js.snap b/src/core_plugins/kibana/public/home/components/tutorial/__snapshots__/instruction_set.test.js.snap
new file mode 100644
index 0000000000000..e574f575a5517
--- /dev/null
+++ b/src/core_plugins/kibana/public/home/components/tutorial/__snapshots__/instruction_set.test.js.snap
@@ -0,0 +1,731 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`render 1`] = `
+
+
+
+
+ title1
+
+
+
+
+
+
+ OSX
+
+
+ Windows
+
+
+
+
,
+ "key": 0,
+ "title": "step 1",
+ },
+ Object {
+ "children":
,
+ "key": 1,
+ "title": "step 2",
+ },
+ ]
+ }
+ />
+
+`;
+
+exports[`statusCheckState checking status 1`] = `
+
+
+
+
+ title1
+
+
+
+
+
+
+ OSX
+
+
+ Windows
+
+
+
+
,
+ "key": 0,
+ "title": "step 1",
+ },
+ Object {
+ "children":
,
+ "key": 1,
+ "title": "step 2",
+ },
+ Object {
+ "children":
+
+
+
+
+ custom status check description
+
+
+
+
+
+ custom btn label
+
+
+
+
+ ,
+ "key": "checkStatusStep",
+ "status": "incomplete",
+ "title": "custom title",
+ },
+ ]
+ }
+ />
+
+`;
+
+exports[`statusCheckState failed status check - error 1`] = `
+
+
+
+
+ title1
+
+
+
+
+
+
+ OSX
+
+
+ Windows
+
+
+
+
,
+ "key": 0,
+ "title": "step 1",
+ },
+ Object {
+ "children":
,
+ "key": 1,
+ "title": "step 2",
+ },
+ Object {
+ "children":
+
+
+
+
+ custom status check description
+
+
+
+
+
+ custom btn label
+
+
+
+
+
+ ,
+ "key": "checkStatusStep",
+ "status": "complete",
+ "title": "custom title",
+ },
+ ]
+ }
+ />
+
+`;
+
+exports[`statusCheckState failed status check - no data 1`] = `
+
+
+
+
+ title1
+
+
+
+
+
+
+ OSX
+
+
+ Windows
+
+
+
+
,
+ "key": 0,
+ "title": "step 1",
+ },
+ Object {
+ "children":
,
+ "key": 1,
+ "title": "step 2",
+ },
+ Object {
+ "children":
+
+
+
+
+ custom status check description
+
+
+
+
+
+ custom btn label
+
+
+
+
+
+ ,
+ "key": "checkStatusStep",
+ "status": "complete",
+ "title": "custom title",
+ },
+ ]
+ }
+ />
+
+`;
+
+exports[`statusCheckState initial state - no check has been attempted 1`] = `
+
+
+
+
+ title1
+
+
+
+
+
+
+ OSX
+
+
+ Windows
+
+
+
+
,
+ "key": 0,
+ "title": "step 1",
+ },
+ Object {
+ "children":
,
+ "key": 1,
+ "title": "step 2",
+ },
+ Object {
+ "children":
+
+
+
+
+ custom status check description
+
+
+
+
+
+ custom btn label
+
+
+
+
+ ,
+ "key": "checkStatusStep",
+ "status": "incomplete",
+ "title": "custom title",
+ },
+ ]
+ }
+ />
+
+`;
+
+exports[`statusCheckState successful status check 1`] = `
+
+
+
+
+ title1
+
+
+
+
+
+
+ OSX
+
+
+ Windows
+
+
+
+
,
+ "key": 0,
+ "title": "step 1",
+ },
+ Object {
+ "children":
,
+ "key": 1,
+ "title": "step 2",
+ },
+ Object {
+ "children":
+
+
+
+
+ custom status check description
+
+
+
+
+
+ custom btn label
+
+
+
+
+
+ ,
+ "key": "checkStatusStep",
+ "status": "complete",
+ "title": "custom title",
+ },
+ ]
+ }
+ />
+
+`;
diff --git a/src/core_plugins/kibana/public/home/components/tutorial/__snapshots__/tutorial.test.js.snap b/src/core_plugins/kibana/public/home/components/tutorial/__snapshots__/tutorial.test.js.snap
index f765acc65c36c..807ab76357adc 100644
--- a/src/core_plugins/kibana/public/home/components/tutorial/__snapshots__/tutorial.test.js.snap
+++ b/src/core_plugins/kibana/public/home/components/tutorial/__snapshots__/tutorial.test.js.snap
@@ -56,9 +56,11 @@ exports[`isCloudEnabled is false should not render instruction toggle when ON_PR
}
key="0"
offset={1}
+ onStatusCheck={[Function]}
paramValues={Object {}}
replaceTemplateStrings={[Function]}
setParameter={[Function]}
+ statusCheckState="NOT_CHECKED"
title="Instruction title"
/>
@@ -141,9 +143,11 @@ exports[`isCloudEnabled is false should render ON_PREM instructions with instruc
}
key="0"
offset={1}
+ onStatusCheck={[Function]}
paramValues={Object {}}
replaceTemplateStrings={[Function]}
setParameter={[Function]}
+ statusCheckState="NOT_CHECKED"
title="Instruction title"
/>
@@ -208,9 +212,11 @@ exports[`should render ELASTIC_CLOUD instructions when isCloudEnabled is true 1`
}
key="0"
offset={1}
+ onStatusCheck={[Function]}
paramValues={Object {}}
replaceTemplateStrings={[Function]}
setParameter={[Function]}
+ statusCheckState="NOT_CHECKED"
title="Instruction title"
/>
diff --git a/src/core_plugins/kibana/public/home/components/tutorial/instruction_set.js b/src/core_plugins/kibana/public/home/components/tutorial/instruction_set.js
index a8a1918506a19..b8e585bbbff9f 100644
--- a/src/core_plugins/kibana/public/home/components/tutorial/instruction_set.js
+++ b/src/core_plugins/kibana/public/home/components/tutorial/instruction_set.js
@@ -1,5 +1,5 @@
import classNames from 'classnames';
-import React from 'react';
+import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import {
KuiBar,
@@ -13,7 +13,13 @@ import {
EuiTab,
EuiSpacer,
EuiSteps,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiText,
+ EuiButton,
+ EuiCallOut,
} from '@elastic/eui';
+import * as StatusCheckStates from './status_check_states';
export class InstructionSet extends React.Component {
@@ -58,6 +64,72 @@ export class InstructionSet extends React.Component {
{tab.name}
));
+ };
+
+ renderStatusCheckMessage() {
+ let message;
+ let color;
+ switch (this.props.statusCheckState) {
+ case StatusCheckStates.NOT_CHECKED:
+ case StatusCheckStates.FETCHING:
+ return null; // Don't show any message while fetching or if you haven't yet checked.
+ case StatusCheckStates.HAS_DATA:
+ message = this.props.statusCheckConfig.success ? this.props.statusCheckConfig.success : 'Success';
+ color = 'success';
+ break;
+ case StatusCheckStates.ERROR:
+ case StatusCheckStates.NO_DATA:
+ message = this.props.statusCheckConfig.error ? this.props.statusCheckConfig.error : 'No data found';
+ color = 'warning';
+ break;
+ }
+ return (
+
+ );
+ }
+
+ renderStatusCheck() {
+ const { statusCheckState, statusCheckConfig, onStatusCheck } = this.props;
+ const checkStatusStep = (
+
+
+
+
+
+ {statusCheckConfig.text}
+
+
+
+
+
+
+ {statusCheckConfig.btnLabel || 'Check status'}
+
+
+
+
+
+
+ {this.renderStatusCheckMessage()}
+
+ );
+
+ const stepStatus = statusCheckState === StatusCheckStates.NOT_CHECKED ||
+ statusCheckState === StatusCheckStates.FETCHING ? 'incomplete' : 'complete';
+ return {
+ title: statusCheckConfig.title || 'Status Check',
+ status: stepStatus,
+ children: checkStatusStep,
+ key: 'checkStatusStep'
+ };
}
renderInstructions = () => {
@@ -85,13 +157,17 @@ export class InstructionSet extends React.Component {
};
});
+ if (this.props.statusCheckConfig) {
+ steps.push(this.renderStatusCheck());
+ }
+
return (
);
- }
+ };
renderHeader = () => {
let paramsVisibilityToggle;
@@ -129,7 +205,7 @@ export class InstructionSet extends React.Component {
);
- }
+ };
render() {
let paramsForm;
@@ -175,9 +251,26 @@ const instructionVariantShape = PropTypes.shape({
instructions: PropTypes.arrayOf(instructionShape).isRequired,
});
+const statusCheckConfigShape = PropTypes.shape({
+ success: PropTypes.string,
+ error: PropTypes.string,
+ title: PropTypes.string,
+ text: PropTypes.string,
+ btnLabel: PropTypes.string,
+});
+
InstructionSet.propTypes = {
title: PropTypes.string.isRequired,
instructionVariants: PropTypes.arrayOf(instructionVariantShape).isRequired,
+ statusCheckConfig: statusCheckConfigShape,
+ statusCheckState: PropTypes.oneOf([
+ StatusCheckStates.FETCHING,
+ StatusCheckStates.NOT_CHECKED,
+ StatusCheckStates.HAS_DATA,
+ StatusCheckStates.NO_DATA,
+ StatusCheckStates.ERROR,
+ ]),
+ onStatusCheck: PropTypes.func.isRequired,
offset: PropTypes.number.isRequired,
params: PropTypes.array,
paramValues: PropTypes.object.isRequired,
diff --git a/src/core_plugins/kibana/public/home/components/tutorial/instruction_set.test.js b/src/core_plugins/kibana/public/home/components/tutorial/instruction_set.test.js
new file mode 100644
index 0000000000000..12769dc6f2c6d
--- /dev/null
+++ b/src/core_plugins/kibana/public/home/components/tutorial/instruction_set.test.js
@@ -0,0 +1,125 @@
+import React from 'react';
+import { shallow } from 'enzyme';
+
+import {
+ InstructionSet,
+} from './instruction_set';
+import * as StatusCheckStates from './status_check_states';
+
+const instructions = [
+ {
+ title: 'step 1',
+ commands: [
+ 'do stuff in command line',
+ ],
+ },
+ {
+ title: 'step 2',
+ commands: [
+ 'do more stuff in command line',
+ ],
+ }
+];
+
+const instructionVariants = [
+ {
+ id: 'OSX',
+ instructions: instructions
+ },
+ {
+ id: 'windows',
+ instructions: instructions,
+ }
+];
+
+test('render', () => {
+ const component = shallow( {}}
+ offset={1}
+ paramValues={{}}
+ replaceTemplateStrings={() => {}}
+ />);
+ expect(component).toMatchSnapshot(); // eslint-disable-line
+});
+
+describe('statusCheckState', () => {
+ const statusCheckConfig = {
+ success: 'custom success msg',
+ error: 'custom error msg',
+ title: 'custom title',
+ text: 'custom status check description',
+ btnLabel: 'custom btn label',
+ };
+
+ test('initial state - no check has been attempted', () => {
+ const component = shallow( {}}
+ offset={1}
+ paramValues={{}}
+ statusCheckConfig={statusCheckConfig}
+ replaceTemplateStrings={() => {}}
+ statusCheckState={StatusCheckStates.FETCHING}
+ />);
+ expect(component).toMatchSnapshot(); // eslint-disable-line
+ });
+
+ test('checking status', () => {
+ const component = shallow( {}}
+ offset={1}
+ paramValues={{}}
+ statusCheckConfig={statusCheckConfig}
+ replaceTemplateStrings={() => {}}
+ statusCheckState={StatusCheckStates.FETCHING}
+ />);
+ expect(component).toMatchSnapshot(); // eslint-disable-line
+ });
+
+ test('failed status check - error', () => {
+ const component = shallow( {}}
+ offset={1}
+ paramValues={{}}
+ statusCheckConfig={statusCheckConfig}
+ replaceTemplateStrings={() => {}}
+ statusCheckState={StatusCheckStates.ERROR}
+ />);
+ expect(component).toMatchSnapshot(); // eslint-disable-line
+ });
+
+ test('failed status check - no data', () => {
+ const component = shallow( {}}
+ offset={1}
+ paramValues={{}}
+ statusCheckConfig={statusCheckConfig}
+ replaceTemplateStrings={() => {}}
+ statusCheckState={StatusCheckStates.NO_DATA}
+ />);
+ expect(component).toMatchSnapshot(); // eslint-disable-line
+ });
+
+ test('successful status check', () => {
+ const component = shallow( {}}
+ offset={1}
+ paramValues={{}}
+ statusCheckConfig={statusCheckConfig}
+ replaceTemplateStrings={() => {}}
+ statusCheckState={StatusCheckStates.HAS_DATA}
+ />);
+ expect(component).toMatchSnapshot(); // eslint-disable-line
+ });
+});
diff --git a/src/core_plugins/kibana/public/home/components/tutorial/status_check_states.js b/src/core_plugins/kibana/public/home/components/tutorial/status_check_states.js
new file mode 100644
index 0000000000000..5ae6f4a16faa3
--- /dev/null
+++ b/src/core_plugins/kibana/public/home/components/tutorial/status_check_states.js
@@ -0,0 +1,5 @@
+export const HAS_DATA = 'has_data';
+export const FETCHING = 'FETCHING';
+export const NO_DATA = 'NO_DATA';
+export const NOT_CHECKED = 'NOT_CHECKED';
+export const ERROR = 'ERROR';
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 f2c5cc4d9e083..2ed2285929e4e 100644
--- a/src/core_plugins/kibana/public/home/components/tutorial/tutorial.js
+++ b/src/core_plugins/kibana/public/home/components/tutorial/tutorial.js
@@ -7,6 +7,7 @@ import { Introduction } from './introduction';
import { InstructionSet } from './instruction_set';
import { RadioButtonGroup } from './radio_button_group';
import { EuiSpacer, EuiPage, EuiPanel, EuiLink, EuiText } from '@elastic/eui';
+import * as StatusCheckStates from './status_check_states';
const INSTRUCTIONS_TYPE = {
ELASTIC_CLOUD: 'elasticCloud',
@@ -22,6 +23,7 @@ export class Tutorial extends React.Component {
this.state = {
notFound: false,
paramValues: {},
+ statusCheckStates: [],
tutorial: null
};
@@ -51,7 +53,7 @@ export class Tutorial extends React.Component {
// eslint-disable-next-line react/no-did-mount-set-state
this.setState({
tutorial: tutorial
- }, this.setParamDefaults);
+ }, this.initInstructionsState);
} else {
// eslint-disable-next-line react/no-did-mount-set-state
this.setState({
@@ -75,26 +77,33 @@ export class Tutorial extends React.Component {
default:
throw new Error(`Unhandled instruction type ${this.state.visibleInstructions}`);
}
- }
+ };
+
+ getInstructionSets = () => this.getInstructions().instructionSets;
- setParamDefaults = () => {
+ initInstructionsState = () => {
const instructions = this.getInstructions();
+
const paramValues = {};
if (instructions.params) {
instructions.params.forEach((param => {
paramValues[param.id] = param.defaultValue;
}));
}
+
+ const statusCheckStates = new Array(instructions.instructionSets.length).fill(StatusCheckStates.NOT_CHECKED);
+
this.setState({
- paramValues: paramValues
+ paramValues,
+ statusCheckStates,
});
- }
+ };
setVisibleInstructions = (instructionsType) => {
this.setState({
visibleInstructions: instructionsType
- }, this.setParamDefaults);
- }
+ }, this.initInstructionsState);
+ };
setParameter = (paramId, newValue) => {
this.setState(previousState => {
@@ -102,15 +111,59 @@ export class Tutorial extends React.Component {
paramValues[paramId] = newValue;
return { paramValues: paramValues };
});
- }
+ };
+
+ checkInstructionSetStatus = async (instructionSetIndex) => {
+ const instructionSet = this.getInstructionSets()[instructionSetIndex];
+ const esHitsCheckConfig = _.get(instructionSet, `statusCheck.esHitsCheck`);
+
+ if (esHitsCheckConfig) {
+ const statusCheckState = await this.fetchEsHitsStatus(esHitsCheckConfig);
+
+ this.setState((prevState) => ({
+ statusCheckStates: {
+ ...prevState.statusCheckStates,
+ [instructionSetIndex]: statusCheckState,
+ }
+ }));
+ }
+ };
+
+ /**
+ *
+ * @param esHitsCheckConfig
+ * @return {Promise}
+ */
+ fetchEsHitsStatus = async (esHitsCheckConfig) => {
+ const searchHeader = JSON.stringify({ index: esHitsCheckConfig.index });
+ const searchBody = JSON.stringify({ query: esHitsCheckConfig.query, size: 1 });
+ const response = await fetch(this.props.addBasePath('/elasticsearch/_msearch'), {
+ method: 'post',
+ body: `${searchHeader}\n${searchBody}\n`,
+ headers: {
+ accept: 'application/json',
+ 'content-type': 'application/x-ndjson',
+ 'kbn-xsrf': 'kibana',
+ },
+ credentials: 'same-origin'
+ });
+
+ if (response.status > 300) {
+ return StatusCheckStates.ERROR;
+ }
+
+ const results = await response.json();
+ const numHits = _.get(results, 'responses.[0].hits.hits.length', 0);
+ return numHits === 0 ? StatusCheckStates.NO_DATA : StatusCheckStates.HAS_DATA;
+ };
onPrem = () => {
this.setVisibleInstructions(INSTRUCTIONS_TYPE.ON_PREM);
- }
+ };
onPremElasticCloud = () => {
this.setVisibleInstructions(INSTRUCTIONS_TYPE.ON_PREM_ELASTIC_CLOUD);
- }
+ };
renderInstructionSetsToggle = () => {
if (!this.props.isCloudEnabled && this.state.tutorial.onPremElasticCloud) {
@@ -125,17 +178,33 @@ export class Tutorial extends React.Component {
/>
);
}
- }
+ };
+
+ onStatusCheck = (instructionSetIndex) => {
+ this.setState(
+ (prevState) => ({
+ statusCheckStates: {
+ ...prevState.statusCheckStates,
+ [instructionSetIndex]: StatusCheckStates.FETCHING,
+ }
+ }),
+ this.checkInstructionSetStatus.bind(null, instructionSetIndex)
+ );
+ };
renderInstructionSets = (instructions) => {
let offset = 1;
return instructions.instructionSets.map((instructionSet, index) => {
const currentOffset = offset;
offset += instructionSet.instructionVariants[0].instructions.length;
+
return (
{ this.onStatusCheck(index); }}
offset={currentOffset}
params={instructions.params}
paramValues={this.state.paramValues}
@@ -145,7 +214,7 @@ export class Tutorial extends React.Component {
/>
);
});
- }
+ };
renderFooter = () => {
let label;
@@ -171,7 +240,7 @@ export class Tutorial extends React.Component {
/>
);
}
- }
+ };
render() {
let content;
@@ -238,5 +307,5 @@ Tutorial.propTypes = {
isCloudEnabled: PropTypes.bool.isRequired,
getTutorial: PropTypes.func.isRequired,
replaceTemplateStrings: PropTypes.func.isRequired,
- tutorialId: PropTypes.string.isRequired
+ tutorialId: PropTypes.string.isRequired,
};
diff --git a/src/core_plugins/kibana/server/tutorials/apm/index.js b/src/core_plugins/kibana/server/tutorials/apm/index.js
index 2e4de77510598..b6bf922bdb458 100644
--- a/src/core_plugins/kibana/server/tutorials/apm/index.js
+++ b/src/core_plugins/kibana/server/tutorials/apm/index.js
@@ -1,5 +1,5 @@
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
-import { ON_PREM_INSTRUCTIONS } from './on_prem';
+import { onPremInstructions } from './on_prem';
import { ELASTIC_CLOUD_INSTRUCTIONS } from './elastic_cloud';
const apmIntro = 'Collect in-depth performance metrics and errors from inside your applications.';
@@ -42,7 +42,7 @@ 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: ON_PREM_INSTRUCTIONS,
+ onPrem: onPremInstructions(server),
elasticCloud: ELASTIC_CLOUD_INSTRUCTIONS,
previewImagePath: '/plugins/kibana/home/tutorial_resources/apm/apm.png',
};
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 34f517aed6788..42d12c3a321f1 100644
--- a/src/core_plugins/kibana/server/tutorials/apm/on_prem.js
+++ b/src/core_plugins/kibana/server/tutorials/apm/on_prem.js
@@ -17,72 +17,122 @@ import {
JS_CLIENT_INSTRUCTIONS,
} from './apm_client_instructions';
-export const ON_PREM_INSTRUCTIONS = {
- instructionSets: [
- {
- title: 'APM Server',
- instructionVariants: [
- {
- id: INSTRUCTION_VARIANT.OSX,
- instructions: [
- DOWNLOAD_SERVER_OSX,
- IMPORT_DASHBOARD_UNIX,
- EDIT_CONFIG,
- START_SERVER_UNIX,
- ],
- },
- {
- id: INSTRUCTION_VARIANT.DEB,
- instructions: [
- DOWNLOAD_SERVER_DEB,
- IMPORT_DASHBOARD_UNIX,
- EDIT_CONFIG,
- START_SERVER_UNIX,
- ],
- },
- {
- id: INSTRUCTION_VARIANT.RPM,
- instructions: [
- DOWNLOAD_SERVER_RPM,
- IMPORT_DASHBOARD_UNIX,
- EDIT_CONFIG,
- START_SERVER_UNIX,
- ],
- },
- {
- id: INSTRUCTION_VARIANT.WINDOWS,
- instructions: WINDOWS_SERVER_INSTRUCTIONS,
- },
- ],
- },
- {
- title: 'APM Agents',
- instructionVariants: [
- {
- id: INSTRUCTION_VARIANT.NODE,
- instructions: NODE_CLIENT_INSTRUCTIONS,
- },
- {
- id: INSTRUCTION_VARIANT.DJANGO,
- instructions: DJANGO_CLIENT_INSTRUCTIONS,
- },
- {
- id: INSTRUCTION_VARIANT.FLASK,
- instructions: FLASK_CLIENT_INSTRUCTIONS,
- },
- {
- id: INSTRUCTION_VARIANT.RAILS,
- instructions: RAILS_CLIENT_INSTRUCTIONS,
- },
- {
- id: INSTRUCTION_VARIANT.RACK,
- instructions: RACK_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.
+ }
+
+ return {
+ instructionSets: [
+ {
+ title: 'APM Server',
+ instructionVariants: [
+ {
+ id: INSTRUCTION_VARIANT.OSX,
+ instructions: [
+ DOWNLOAD_SERVER_OSX,
+ IMPORT_DASHBOARD_UNIX,
+ EDIT_CONFIG,
+ START_SERVER_UNIX,
+ ],
+ },
+ {
+ id: INSTRUCTION_VARIANT.DEB,
+ instructions: [
+ DOWNLOAD_SERVER_DEB,
+ IMPORT_DASHBOARD_UNIX,
+ EDIT_CONFIG,
+ START_SERVER_UNIX,
+ ],
+ },
+ {
+ id: INSTRUCTION_VARIANT.RPM,
+ instructions: [
+ DOWNLOAD_SERVER_RPM,
+ IMPORT_DASHBOARD_UNIX,
+ EDIT_CONFIG,
+ START_SERVER_UNIX,
+ ],
+ },
+ {
+ id: INSTRUCTION_VARIANT.WINDOWS,
+ instructions: WINDOWS_SERVER_INSTRUCTIONS,
+ },
+ ],
+ statusCheck: {
+ title: 'APM Server status',
+ text:
+ 'Make sure APM Server is running before you start implementing the APM agents.',
+ btnLabel: 'Check APM Server status',
+ success: 'You have correctly setup APM-Server',
+ error: 'APM-Server has still not connected to Elasticsearch',
+ esHitsCheck: {
+ index: apmIndexPattern,
+ query: {
+ bool: {
+ filter: {
+ exists: {
+ field: 'listening',
+ },
+ },
+ },
+ },
+ },
},
- {
- id: INSTRUCTION_VARIANT.JS,
- instructions: JS_CLIENT_INSTRUCTIONS,
+ },
+ {
+ title: 'APM Agents',
+ instructionVariants: [
+ {
+ id: INSTRUCTION_VARIANT.NODE,
+ instructions: NODE_CLIENT_INSTRUCTIONS,
+ },
+ {
+ id: INSTRUCTION_VARIANT.DJANGO,
+ instructions: DJANGO_CLIENT_INSTRUCTIONS,
+ },
+ {
+ id: INSTRUCTION_VARIANT.FLASK,
+ instructions: FLASK_CLIENT_INSTRUCTIONS,
+ },
+ {
+ id: INSTRUCTION_VARIANT.RAILS,
+ instructions: RAILS_CLIENT_INSTRUCTIONS,
+ },
+ {
+ id: INSTRUCTION_VARIANT.RACK,
+ instructions: RACK_CLIENT_INSTRUCTIONS,
+ },
+ {
+ id: INSTRUCTION_VARIANT.JS,
+ instructions: JS_CLIENT_INSTRUCTIONS,
+ },
+ ],
+ statusCheck: {
+ title: 'Agent status',
+ text:
+ 'Make sure you application is running, and the agents are sending data',
+ btnLabel: 'Check agent status',
+ success: 'Data succesfully received from one or more agents',
+ error: `No data has been received from agents yet`,
+ esHitsCheck: {
+ index: apmIndexPattern,
+ query: {
+ bool: {
+ filter: {
+ exists: {
+ field: 'processor.name',
+ },
+ },
+ },
+ },
+ },
},
- ],
- },
- ],
-};
+ },
+ ],
+ };
+}