diff --git a/src/core_plugins/kibana/common/tutorials/instruction_variant.js b/src/core_plugins/kibana/common/tutorials/instruction_variant.js index 909def999d2b8..2a47728fcb32e 100644 --- a/src/core_plugins/kibana/common/tutorials/instruction_variant.js +++ b/src/core_plugins/kibana/common/tutorials/instruction_variant.js @@ -6,7 +6,10 @@ export const INSTRUCTION_VARIANT = { WINDOWS: 'windows', NODE: 'node', DJANGO: 'django', - FLASK: 'flask' + FLASK: 'flask', + RAILS: 'rails', + RACK: 'rack', + JS: 'js', }; const DISPLAY_MAP = { @@ -18,6 +21,9 @@ const DISPLAY_MAP = { [INSTRUCTION_VARIANT.NODE]: 'Node.js', [INSTRUCTION_VARIANT.DJANGO]: 'Django', [INSTRUCTION_VARIANT.FLASK]: 'Flask', + [INSTRUCTION_VARIANT.RAILS]: 'Ruby on Rails', + [INSTRUCTION_VARIANT.RACK]: 'Rack', + [INSTRUCTION_VARIANT.JS]: 'JS', }; /** diff --git a/src/core_plugins/kibana/common/tutorials/tutorial_category.js b/src/core_plugins/kibana/common/tutorials/tutorial_category.js index e112b3d36d251..f864b0629e9f2 100644 --- a/src/core_plugins/kibana/common/tutorials/tutorial_category.js +++ b/src/core_plugins/kibana/common/tutorials/tutorial_category.js @@ -1,5 +1,6 @@ export const TUTORIAL_CATEGORY = { LOGGING: 'logging', SECURITY: 'security', - METRICS: 'metrics' + METRICS: 'metrics', + OTHER: 'other', }; diff --git a/src/core_plugins/kibana/common/tutorials/tutorial_schema.js b/src/core_plugins/kibana/common/tutorials/tutorial_schema.js index f506d3805aa60..d27c036448e66 100644 --- a/src/core_plugins/kibana/common/tutorials/tutorial_schema.js +++ b/src/core_plugins/kibana/common/tutorials/tutorial_schema.js @@ -65,10 +65,10 @@ export const tutorialSchema = { onPrem: instructionsSchema.required(), // kibana and elastic cluster running in elastic's cloud - elasticCloud: instructionsSchema.required(), + elasticCloud: instructionsSchema, // kibana running on prem and elastic cluster running in elastic's cloud - onPremElasticCloud: instructionsSchema.required(), + onPremElasticCloud: instructionsSchema, // Elastic stack artifacts produced by product when it is setup and run. artifacts: artifactsSchema, diff --git a/src/core_plugins/kibana/public/home/components/home.js b/src/core_plugins/kibana/public/home/components/home.js index cffdfaab7d7c0..7b70e02da7366 100644 --- a/src/core_plugins/kibana/public/home/components/home.js +++ b/src/core_plugins/kibana/public/home/components/home.js @@ -28,7 +28,7 @@ import { FeatureCatalogueCategory } from 'ui/registry/feature_catalogue'; import chrome from 'ui/chrome'; const kbnBaseUrl = chrome.getInjected('kbnBaseUrl'); -export function Home({ addBasePath, directories }) { +export function Home({ addBasePath, directories, isCloudEnabled }) { const renderDirectories = (category) => { return directories @@ -54,9 +54,43 @@ export function Home({ addBasePath, directories }) { width: '250px', 'minWidth': '200px' }; + + let apmCard; + if (!isCloudEnabled) { + apmCard = ( + + + + +

+ APM +

+
+ + + APM automatically collects in-depth performance metrics and errors from inside your applications. + +
+ + + + Add APM + + +
+ ); + } return (
+ + {apmCard} + @@ -243,5 +277,6 @@ Home.propTypes = { path: PropTypes.string.isRequired, showOnHomePage: PropTypes.bool.isRequired, category: PropTypes.string.isRequired - })) + })), + isCloudEnabled: PropTypes.bool.isRequired, }; 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 4256f9a94f713..6dd3e9daaea3b 100644 --- a/src/core_plugins/kibana/public/home/components/home_app.js +++ b/src/core_plugins/kibana/public/home/components/home_app.js @@ -15,11 +15,14 @@ import chrome from 'ui/chrome'; export function HomeApp({ addBasePath, directories }) { + const isCloudEnabled = chrome.getInjected('isCloudEnabled', false); + const renderTutorialDirectory = (props) => { return ( ); }; @@ -28,7 +31,7 @@ export function HomeApp({ addBasePath, directories }) { return ( 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 8f40f1838e3f8..f8c62ed720795 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 @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`should render ELASTIC_CLOUD instructions when isCloudEnabled is true 1`] = ` +exports[`isCloudEnabled is false should not render instruction toggle when ON_PREM_ELASTIC_CLOUD instructions are not provided 1`] = ` @@ -48,7 +48,7 @@ exports[`should render ELASTIC_CLOUD instructions when isCloudEnabled is true 1` "id": "platform id", "instructions": Array [ Object { - "title": "elasticCloud instructions", + "title": "onPrem instructions", }, ], }, @@ -66,7 +66,7 @@ exports[`should render ELASTIC_CLOUD instructions when isCloudEnabled is true 1` `; -exports[`should render ON_PREM instructions with instructions cloud toggle when isCloudEnabled is false 1`] = ` +exports[`isCloudEnabled is false should render ON_PREM instructions with instruction toggle 1`] = ` @@ -149,3 +149,69 @@ exports[`should render ON_PREM instructions with instructions cloud toggle when
`; + +exports[`should render ELASTIC_CLOUD instructions when isCloudEnabled is true 1`] = ` + + + Home + + / + + Add Data + + +
+ + +
+ + + + +
+ +`; diff --git a/src/core_plugins/kibana/public/home/components/tutorial/replace_template_strings.js b/src/core_plugins/kibana/public/home/components/tutorial/replace_template_strings.js index 9c2bd557b2528..3247b9e3e4a88 100644 --- a/src/core_plugins/kibana/public/home/components/tutorial/replace_template_strings.js +++ b/src/core_plugins/kibana/public/home/components/tutorial/replace_template_strings.js @@ -21,6 +21,10 @@ mustacheWriter.escapedValue = function escapedValue(token, context) { export function replaceTemplateStrings(text, params = {}) { const variables = { + // '{' and '}' can not be used in template since they are used as template tags. + // Must use '{curlyOpen}'' and '{curlyClose}' + curlyOpen: '{', + curlyClose: '}', config: { cloud: { id: chrome.getInjected('cloudId') 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 f99208fc7bdad..01d63f9fb49f4 100644 --- a/src/core_plugins/kibana/public/home/components/tutorial/tutorial.js +++ b/src/core_plugins/kibana/public/home/components/tutorial/tutorial.js @@ -112,7 +112,7 @@ export class Tutorial extends React.Component { } renderInstructionSetsToggle = () => { - if (!this.props.isCloudEnabled) { + if (!this.props.isCloudEnabled && this.state.tutorial.onPremElasticCloud) { const radioButtons = [ { onClick: this.onPrem, label: 'On premise', dataTestSubj: 'onPremBtn' }, { onClick: this.onPremElasticCloud, label: 'Elastic Cloud', dataTestSubj: 'onPremElasticCloudBtn' }, 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 c20f83e272f41..240be93bf0588 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 @@ -43,18 +43,60 @@ const replaceTemplateStrings = (text) => { return text; }; -test('should render ON_PREM instructions with instructions cloud toggle when isCloudEnabled is false', () => { - const component = shallow(); - loadTutorialPromise.then(() => { - component.update(); - expect(component).toMatchSnapshot(); // eslint-disable-line +describe('isCloudEnabled is false', () => { + + test('should render ON_PREM instructions with instruction toggle', () => { + const component = shallow(); + loadTutorialPromise.then(() => { + component.update(); + expect(component).toMatchSnapshot(); // eslint-disable-line + }); }); + + test('should not render instruction toggle when ON_PREM_ELASTIC_CLOUD instructions are not provided', () => { + const loadBasicTutorialPromise = Promise.resolve({ + name: 'jest test tutorial', + longDescription: 'tutorial used to drive jest tests', + elasticCloud: buildInstructionSet('elasticCloud'), + onPrem: buildInstructionSet('onPrem') + }); + const getBasicTutorial = () => { + return loadBasicTutorialPromise; + }; + const component = shallow(); + loadBasicTutorialPromise.then(() => { + component.update(); + expect(component).toMatchSnapshot(); // eslint-disable-line + }); + }); + + test('should display ON_PREM_ELASTIC_CLOUD instructions when toggle is clicked', () => { + const component = mount(); + loadTutorialPromise.then(() => { + component.update(); + findTestSubject(component, 'onPremElasticCloudBtn').simulate('click'); + expect(component.state('visibleInstructions')).toBe('onPremElasticCloud'); + }); + }); + }); test('should render ELASTIC_CLOUD instructions when isCloudEnabled is true', () => { @@ -70,18 +112,3 @@ test('should render ELASTIC_CLOUD instructions when isCloudEnabled is true', () expect(component).toMatchSnapshot(); // eslint-disable-line }); }); - -test('should display ON_PREM_ELASTIC_CLOUD instructions when cloud toggle is clicked', () => { - const component = mount(); - loadTutorialPromise.then(() => { - component.update(); - findTestSubject(component, 'onPremElasticCloudBtn').simulate('click'); - expect(component.state('visibleInstructions')).toBe('onPremElasticCloud'); - }); -}); diff --git a/src/core_plugins/kibana/public/home/components/tutorial_directory.js b/src/core_plugins/kibana/public/home/components/tutorial_directory.js index 030624d59e889..cfb9fbd80982c 100644 --- a/src/core_plugins/kibana/public/home/components/tutorial_directory.js +++ b/src/core_plugins/kibana/public/home/components/tutorial_directory.js @@ -1,3 +1,4 @@ +import _ from 'lodash'; import React from 'react'; import PropTypes from 'prop-types'; import { Synopsis } from './synopsis'; @@ -47,7 +48,12 @@ export class TutorialDirectory extends React.Component { } async componentWillMount() { - const tutorials = await getTutorials(); + let tutorials = await getTutorials(); + if (this.props.isCloudEnabled) { + tutorials = tutorials.filter(tutorial => { + return _.has(tutorial, 'elasticCloud'); + }); + } tutorials.sort((a, b) => { return a.name.toLowerCase().localeCompare(b.name.toLowerCase()); }); @@ -126,5 +132,6 @@ export class TutorialDirectory extends React.Component { TutorialDirectory.propTypes = { addBasePath: PropTypes.func.isRequired, - openTab: PropTypes.string + openTab: PropTypes.string, + isCloudEnabled: PropTypes.bool.isRequired, }; diff --git a/src/core_plugins/kibana/server/tutorials/apm/apm_client_instructions.js b/src/core_plugins/kibana/server/tutorials/apm/apm_client_instructions.js new file mode 100644 index 0000000000000..4bd1bd81d6b7d --- /dev/null +++ b/src/core_plugins/kibana/server/tutorials/apm/apm_client_instructions.js @@ -0,0 +1,189 @@ +export const NODE_CLIENT_INSTRUCTIONS = [ + { + title: 'Install the APM agent', + textPre: 'Install the APM agent for Node.js as a dependency to your application.', + commands: [ + 'npm install elastic-apm-node --save' + ] + }, + { + title: 'Configure the agent', + textPre: 'Agents are libraries that run inside of your application process.' + + ' APM services are created programmatically based on the `serviceName`.' + + ' This agent supports Express, Koa, hapi, and custom Node.js.', + commands: [ + `// Add this to the VERY top of the first file loaded in your app`, + `var apm = require('elastic-apm-node').start({curlyOpen}`, + ` // Set required service name (allowed characters: a-z, A-Z, 0-9, -, _, and space)`, + ` serviceName: '',`, + ` `, + ` // Use if APM Server requires a token`, + ` secretToken: '',`, + ` `, + ` // Set custom APM Server URL (default: http://localhost:8200)`, + ` serverUrl: ''`, + `{curlyClose})`, + ], + textPost: 'See [the documentation]({config.docs.base_url}guide/en/apm/agent/nodejs/1.x/index.html)' + + ' for advanced usage. Babel users, please refer to [the documentation]' + + '({config.docs.base_url}guide/en/apm/agent/nodejs/1.x/advanced-setup.html#es-modules).' + } +]; + +export const DJANGO_CLIENT_INSTRUCTIONS = [ + { + title: 'Install the APM agent', + textPre: 'Install the APM agent for Python as a dependency.', + commands: [ + '$ pip install elastic-apm' + ] + }, + { + title: 'Configure the agent', + textPre: 'Agents are libraries that run inside of your application process.' + + ' APM services are created programmatically based on the `SERVICE_NAME`.', + commands: [ + `# Add the agent to the installed apps`, + `INSTALLED_APPS = (`, + ` 'elasticapm.contrib.django',`, + ` # ...`, + `)`, + ` `, + `# Choose a service name and optionally a secret token`, + `ELASTIC_APM = {curlyOpen}`, + ` 'SERVICE_NAME': '',`, + ` 'SECRET_TOKEN': '',`, + `{curlyClose}`, + ` `, + `# To send performance metrics, add our tracing middleware:`, + `MIDDLEWARE = (`, + ` 'elasticapm.contrib.django.middleware.TracingMiddleware',`, + ` #...`, + `)` + ], + textPost: 'See the [documentation]' + + '({config.docs.base_url}guide/en/apm/agent/python/2.x/django-support.html) for advanced usage.' + } +]; + +export const FLASK_CLIENT_INSTRUCTIONS = [ + { + title: 'Install the APM agent', + textPre: 'Install the APM agent for Python as a dependency.', + commands: [ + '$ pip install elastic-apm[flask]' + ] + }, + { + title: 'Configure the agent', + textPre: 'Agents are libraries that run inside of your application process.' + + ' APM services are created programmatically based on the `SERVICE_NAME`.', + commands: [ + `# initialize using environment variables`, + `from elasticapm.contrib.flask import ElasticAPM`, + `app = Flask(__name__)`, + `apm = ElasticAPM(app)`, + ` `, + `# or configure to use ELASTIC_APM in your application's settings`, + `from elasticapm.contrib.flask import ElasticAPM`, + `app.config['ELASTIC_APM'] = {curlyOpen}`, + ` # allowed characters in SERVICE_NAME: a-z, A-Z, 0-9, -, _, and space`, + ` 'SERVICE_NAME': '',`, + ` 'SECRET_TOKEN': '',`, + `{curlyClose}`, + ` `, + `apm = ElasticAPM(app)`, + ], + textPost: 'See the [documentation]' + + '({config.docs.base_url}guide/en/apm/agent/python/2.x/flask-support.html) for advanced usage.' + } +]; + +export const RAILS_CLIENT_INSTRUCTIONS = [ + { + title: 'Install the APM agent', + textPre: 'Add the agent to your Gemfile.', + commands: [ + `gem 'elastic-apm'` + ] + }, + { + title: 'Configure the agent', + textPre: 'APM is automatically installed. Configure the agent, by creating the config file `config/elastic_apm.yml`', + commands: [ + `# config/elastic_apm.yml`, + `server_url: 'http://localhost:8200'`, + ], + textPost: 'See the [documentation]' + + '({config.docs.base_url}guide/en/apm/agent/ruby/1.x/index.html) for configuration options and advanced usage.\n\n' + + '**Warning: The Ruby agent is currently in Beta and not meant for production use.**' + } +]; + +export const RACK_CLIENT_INSTRUCTIONS = [ + { + title: 'Install the APM agent', + textPre: 'Add the agent to your Gemfile.', + commands: [ + `gem 'elastic-apm'` + ] + }, + { + title: 'Configure the agent', + textPre: 'Rack or compatible framework (like Sinatra). Include the middleware in your app and start the agent', + commands: [ + `# config.ru`, + `require 'sinatra/base'`, + `class MySinatraApp < Sinatra::Base`, + ` use ElasticAPM::Middleware`, + ` `, + ` # ...`, + `end`, + `# Takes optional ElasticAPM::Config values`, + `ElasticAPM.start(`, + ` app: MySinatraApp, # required`, + ` server_url: 'http://localhost:8200'`, + `)`, + `run MySinatraApp`, + `at_exit {curlyOpen} ElasticAPM.stop {curlyClose}`, + ], + textPost: 'See the [documentation]' + + '({config.docs.base_url}guide/en/apm/agent/ruby/1.x/index.html) for configuration options and advanced usage.\n\n' + + '**Warning: The Rack agent is currently in Beta and not meant for production use.**' + } +]; + +export const JS_CLIENT_INSTRUCTIONS = [ + { + title: 'Enable experimental frontend support in the APM server', + textPre: 'Please refer to [the documentation]({config.docs.base_url}guide/en/apm/server/{config.docs.version}/frontend.html).' + }, + { + title: 'Install the APM agent', + textPre: 'Install the APM agent for JavaScript as a dependency to your application:', + commands: [ + `npm install elastic-apm-js-base --save` + ] + }, + { + title: 'Configure the agent', + textPre: 'Agents are libraries that run inside of your application.', + commands: [ + `import {curlyOpen} init as initApm {curlyClose} from 'elastic-apm-js-base'`, + `var apm = initApm({curlyOpen}`, + ` `, + ` // Set custom APM Server URL (default: http://localhost:8200)`, + ` serverUrl: 'http://localhost:8200',`, + ` `, + ` // Set required service name`, + ` serviceName: 'service-name',`, + ` `, + ` // Set service version (required for sourcemap feature)`, + ` serviceVersion: 'service-version'`, + `{curlyClose})`, + ], + textPost: 'See the [documentation]' + + '({config.docs.base_url}guide/en/apm/agent/js-base/0.x/index.html) for advanced usage.\n\n' + + '**Warning: The JS agent is currently in Alpha and not meant for production use.**' + } +]; diff --git a/src/core_plugins/kibana/server/tutorials/apm/apm_server_instructions.js b/src/core_plugins/kibana/server/tutorials/apm/apm_server_instructions.js new file mode 100644 index 0000000000000..ea38747daca5c --- /dev/null +++ b/src/core_plugins/kibana/server/tutorials/apm/apm_server_instructions.js @@ -0,0 +1,65 @@ +const EDIT_CONFIG = { + title: 'Edit the configuration', + textPre: `If you're using an X-Pack secured version of Elastic Stack, you need to specify` + + `credentials in the apm-server.yml config file.`, + commands: [ + 'output.elasticsearch:', + ' hosts: [""]', + ' username: ', + ' password: ' + ] +}; + +const IMPORT_DASHBOARD = { + title: 'Import dashboards', + textPre: 'APM Server ships with pre-configured dashboards' +}; + +const START_SERVER = { + title: 'Start APM Server', + textPre: 'The server processes and stores application performance metrics in Elasticsearch' +}; + +export const DOWNLOAD_SERVER = { + title: 'Download and unpack APM Server', +}; + +export const UNIX_FAMILY_SERVER_INSTRUCTIONS = [ + { + ...IMPORT_DASHBOARD, + commands: [ + './apm-server setup' + ] + }, + EDIT_CONFIG, + { + ...START_SERVER, + commands: [ + './apm-server -e' + ] + } +]; + +export const WINDOWS_SERVER_INSTRUCTIONS = [ + { + ...DOWNLOAD_SERVER, + commands: [ + 'curl -L -O https://artifacts.elastic.co/downloads/apm-server/apm-server-6.2.0-windows-x86_64.zip', + 'sudo dpkg -i apm-server-6.2.0-windows-x86_64.zip' + ], + textPost: 'Looking for the 32 bits packages? See the [Download page]({config.docs.base_url}downloads/apm/apm-server).' + }, + { + ...IMPORT_DASHBOARD, + commands: [ + 'apm-server.exe setup' + ] + }, + EDIT_CONFIG, + { + ...START_SERVER, + commands: [ + 'apm-server.exe -e' + ] + } +]; diff --git a/src/core_plugins/kibana/server/tutorials/apm/index.js b/src/core_plugins/kibana/server/tutorials/apm/index.js new file mode 100644 index 0000000000000..636969d342d49 --- /dev/null +++ b/src/core_plugins/kibana/server/tutorials/apm/index.js @@ -0,0 +1,29 @@ +import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; +import { ON_PREM_INSTRUCTIONS } from './on_prem'; + +export function apmSpecProvider() { + return { + id: 'apm', + name: 'APM', + category: TUTORIAL_CATEGORY.OTHER, + shortDescription: 'APM (Application Performance Monitoring) automatically collects in-depth' + + ' performance metrics and errors from inside your applications.', + longDescription: 'APM consists of three components - the Agents, the Server, and the UI:\n' + + '* The Agents are libraries in your application that run inside of your application process.\n' + + '* The Server processes data from agents and stores the application data in Elasticsearch.\n' + + '* The UI is the dedicated APM UI (X-Pack Basic) and preconfigured dashboards.\n\n' + + 'For more information, [please see our documentation]' + + '({config.docs.base_url}guide/en/apm/get-started/{config.docs.version}/index.html).' + + ' To get started, follow the steps below.', + artifacts: { + dashboards: [ + { + title: '[APM] Services', + linkLabel: 'APM Services dashboard', + isOverview: true + } + ] + }, + onPrem: ON_PREM_INSTRUCTIONS, + }; +} diff --git a/src/core_plugins/kibana/server/tutorials/apm/on_prem.js b/src/core_plugins/kibana/server/tutorials/apm/on_prem.js new file mode 100644 index 0000000000000..12d9dbe180ace --- /dev/null +++ b/src/core_plugins/kibana/server/tutorials/apm/on_prem.js @@ -0,0 +1,99 @@ +import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; +import { + DOWNLOAD_SERVER, + WINDOWS_SERVER_INSTRUCTIONS, + UNIX_FAMILY_SERVER_INSTRUCTIONS +} from './apm_server_instructions'; +import { + NODE_CLIENT_INSTRUCTIONS, + DJANGO_CLIENT_INSTRUCTIONS, + FLASK_CLIENT_INSTRUCTIONS, + RAILS_CLIENT_INSTRUCTIONS, + RACK_CLIENT_INSTRUCTIONS, + JS_CLIENT_INSTRUCTIONS, +} from './apm_client_instructions'; + +export const ON_PREM_INSTRUCTIONS = { + instructionSets: [ + { + title: 'APM Server', + instructionVariants: [ + { + id: INSTRUCTION_VARIANT.OSX, + instructions: [ + { + ...DOWNLOAD_SERVER, + commands: [ + 'curl -L -O https://artifacts.elastic.co/downloads/apm-server/apm-server-6.2.0-darwin-x86_64.tar.gz', + 'tar xzvf apm-server-6.2.0-darwin-x86_64.tar.gz', + 'cd apm-server-6.2.0-darwin-x86_64/', + ] + }, + ...UNIX_FAMILY_SERVER_INSTRUCTIONS + ] + }, + { + id: INSTRUCTION_VARIANT.DEB, + instructions: [ + { + ...DOWNLOAD_SERVER, + commands: [ + 'curl -L -O https://artifacts.elastic.co/downloads/apm-server/apm-server-6.2.0-amd64.deb', + 'sudo dpkg -i apm-server-6.2.0-amd64.deb', + ], + textPost: 'Looking for the 32 bits packages? See the [Download page]({config.docs.base_url}downloads/apm/apm-server).' + }, + ...UNIX_FAMILY_SERVER_INSTRUCTIONS + ] + }, + { + id: INSTRUCTION_VARIANT.RPM, + instructions: [ + { + ...DOWNLOAD_SERVER, + commands: [ + 'curl -L -O https://artifacts.elastic.co/downloads/apm-server/apm-server-6.2.0-x86_64.rpm', + 'sudo dpkg -i apm-server-6.2.0-x86_64.rpm' + ], + textPost: 'Looking for the 32 bits packages? See the [Download page]({config.docs.base_url}downloads/apm/apm-server).' + }, + ...UNIX_FAMILY_SERVER_INSTRUCTIONS + ] + }, + { + id: INSTRUCTION_VARIANT.WINDOWS, + instructions: WINDOWS_SERVER_INSTRUCTIONS + } + ] + }, + { + title: 'APM Client', + 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 + } + ] + } + ] +}; diff --git a/src/core_plugins/kibana/server/tutorials/register.js b/src/core_plugins/kibana/server/tutorials/register.js index 3399ff80df171..ca4ed62b1ba6e 100644 --- a/src/core_plugins/kibana/server/tutorials/register.js +++ b/src/core_plugins/kibana/server/tutorials/register.js @@ -11,6 +11,7 @@ import { redisMetricsSpecProvider } from './redis_metrics'; import { dockerMetricsSpecProvider } from './docker_metrics'; import { kubernetesMetricsSpecProvider } from './kubernetes_metrics'; import { netflowSpecProvider } from './netflow'; +import { apmSpecProvider } from './apm'; export function registerTutorials(server) { server.registerTutorial(systemLogsSpecProvider); @@ -26,4 +27,5 @@ export function registerTutorials(server) { server.registerTutorial(dockerMetricsSpecProvider); server.registerTutorial(kubernetesMetricsSpecProvider); server.registerTutorial(netflowSpecProvider); + server.registerTutorial(apmSpecProvider); }