[APM] Shim new platform (#34531)

This commit is contained in:
Søren Louv-Jansen 2019-04-10 14:41:20 +02:00 committed by GitHub
parent fcfd6e5a8d
commit 93549e6b60
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 155 additions and 64 deletions

View file

@ -7,13 +7,9 @@
import { i18n } from '@kbn/i18n';
import { Server } from 'hapi';
import { resolve } from 'path';
import { CoreSetup, PluginInitializerContext } from 'src/core/server/index.js';
import mappings from './mappings.json';
import { makeApmUsageCollector } from './server/lib/apm_telemetry';
import { initErrorsApi } from './server/routes/errors';
import { initMetricsApi } from './server/routes/metrics';
import { initServicesApi } from './server/routes/services';
import { initTracesApi } from './server/routes/traces';
import { initTransactionGroupsApi } from './server/routes/transaction_groups';
import { plugin } from './server/new-platform/index';
// TODO: get proper types
export function apm(kibana: any) {
@ -73,13 +69,14 @@ export function apm(kibana: any) {
},
// TODO: get proper types
init(server: any) {
initTransactionGroupsApi(server);
initTracesApi(server);
initServicesApi(server);
initErrorsApi(server);
initMetricsApi(server);
makeApmUsageCollector(server);
init(server: Server) {
const initializerContext = {} as PluginInitializerContext;
const core = {
http: {
server
}
} as CoreSetup;
plugin(initializerContext).setup(core);
}
});
}

View file

@ -6,9 +6,8 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { Router } from 'react-router-dom';
import 'react-vis/dist/style.css';
import { CoreSetup } from 'src/core/public';
import 'ui/autoload/all';
import 'ui/autoload/styles';
import chrome from 'ui/chrome';
@ -17,11 +16,10 @@ import { I18nContext } from 'ui/i18n';
import { uiModules } from 'ui/modules';
import 'uiExports/autocompleteProviders';
import { GlobalHelpExtension } from './components/app/GlobalHelpExtension';
import { Main } from './components/app/Main';
import { history } from './components/shared/Links/url_helpers';
import { LocationProvider } from './context/LocationContext';
// @ts-ignore
import configureStore from './store/config/configureStore';
import { plugin } from './new-platform';
import { REACT_APP_ROOT_ID } from './new-platform/plugin';
import './style/global_overrides.css';
import template from './templates/index.html';
@ -32,34 +30,26 @@ chrome.helpExtension.set(domElement => {
ReactDOM.unmountComponentAtNode(domElement);
};
});
const REACT_APP_ROOT_ID = 'react-apm-root';
type PromiseResolver = (value?: {} | PromiseLike<{}> | undefined) => void;
// @ts-ignore
chrome.setRootTemplate(template);
const store = configureStore();
const checkForRoot = (resolve: PromiseResolver) => {
const ready = !!document.getElementById(REACT_APP_ROOT_ID);
if (ready) {
resolve();
} else {
setTimeout(() => checkForRoot(resolve), 10);
}
};
const waitForRoot = new Promise(resolve => checkForRoot(resolve));
waitForRoot.then(() => {
ReactDOM.render(
<I18nContext>
<Provider store={store}>
<Router history={history}>
<LocationProvider history={history}>
<Main />
</LocationProvider>
</Router>
</Provider>
</I18nContext>,
document.getElementById(REACT_APP_ROOT_ID)
);
const checkForRoot = () => {
return new Promise(resolve => {
const ready = !!document.getElementById(REACT_APP_ROOT_ID);
if (ready) {
resolve();
} else {
setTimeout(() => resolve(checkForRoot()), 10);
}
});
};
checkForRoot().then(() => {
const core = {
i18n: {
Context: I18nContext
}
} as CoreSetup;
plugin().setup(core);
});

View file

@ -0,0 +1,11 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { Plugin } from './plugin';
export function plugin() {
return new Plugin();
}

View file

@ -0,0 +1,37 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { Router } from 'react-router-dom';
import { CoreSetup } from 'src/core/public';
import { Main } from '../components/app/Main';
import { history } from '../components/shared/Links/url_helpers';
import { LocationProvider } from '../context/LocationContext';
// @ts-ignore
import configureStore from '../store/config/configureStore';
export const REACT_APP_ROOT_ID = 'react-apm-root';
export class Plugin {
public setup(core: CoreSetup) {
const { i18n } = core;
const store = configureStore();
ReactDOM.render(
<i18n.Context>
<Provider store={store}>
<Router history={history}>
<LocationProvider history={history}>
<Main />
</LocationProvider>
</Router>
</Provider>
</i18n.Context>,
document.getElementById(REACT_APP_ROOT_ID)
);
}
}

View file

@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { Server } from 'hapi';
import { CoreSetup } from 'src/core/server';
import {
APM_TELEMETRY_DOC_ID,
createApmTelementry,
@ -12,16 +12,22 @@ import {
} from './apm_telemetry';
// TODO this type should be defined by the platform
interface KibanaHapiServer extends Server {
usage: {
collectorSet: {
makeUsageCollector: (options: unknown) => unknown;
register: (options: unknown) => unknown;
export interface CoreSetupWithUsageCollector extends CoreSetup {
http: CoreSetup['http'] & {
server: {
usage: {
collectorSet: {
makeUsageCollector: (options: unknown) => unknown;
register: (options: unknown) => unknown;
};
};
};
};
}
export function makeApmUsageCollector(server: KibanaHapiServer): void {
export function makeApmUsageCollector(core: CoreSetupWithUsageCollector) {
const { server } = core.http;
const apmUsageCollector = server.usage.collectorSet.makeUsageCollector({
type: 'apm',
fetch: async () => {

View file

@ -0,0 +1,12 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { PluginInitializerContext } from 'src/core/server';
import { Plugin } from './plugin';
export function plugin(initializerContext: PluginInitializerContext) {
return new Plugin();
}

View file

@ -0,0 +1,25 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { CoreSetup } from 'src/core/server';
import { makeApmUsageCollector } from '../lib/apm_telemetry';
import { CoreSetupWithUsageCollector } from '../lib/apm_telemetry/make_apm_usage_collector';
import { initErrorsApi } from '../routes/errors';
import { initMetricsApi } from '../routes/metrics';
import { initServicesApi } from '../routes/services';
import { initTracesApi } from '../routes/traces';
import { initTransactionGroupsApi } from '../routes/transaction_groups';
export class Plugin {
public setup(core: CoreSetup) {
initTransactionGroupsApi(core);
initTracesApi(core);
initServicesApi(core);
initErrorsApi(core);
initMetricsApi(core);
makeApmUsageCollector(core as CoreSetupWithUsageCollector);
}
}

View file

@ -4,8 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { Server } from 'hapi';
import { flatten } from 'lodash';
import { CoreSetup } from 'src/core/server';
import { initErrorsApi } from '../errors';
import { initServicesApi } from '../services';
import { initTracesApi } from '../traces';
@ -13,9 +13,14 @@ import { initTracesApi } from '../traces';
describe('route handlers should fail with a Boom error', () => {
let consoleErrorSpy: any;
async function testRouteFailures(init: (server: Server) => void) {
async function testRouteFailures(init: (core: CoreSetup) => void) {
const mockServer = { route: jest.fn() };
init((mockServer as unknown) as Server);
const mockCore = ({
http: {
server: mockServer
}
} as unknown) as CoreSetup;
init(mockCore);
expect(mockServer.route).toHaveBeenCalled();
const mockCluster = {

View file

@ -5,9 +5,9 @@
*/
import Boom from 'boom';
import { Server } from 'hapi';
import Joi from 'joi';
import { Legacy } from 'kibana';
import { CoreSetup } from 'src/core/server';
import { getDistribution } from '../lib/errors/distribution/get_distribution';
import { getErrorGroup } from '../lib/errors/get_error_group';
import { getErrorGroups } from '../lib/errors/get_error_groups';
@ -21,7 +21,8 @@ const defaultErrorHandler = (err: Error) => {
throw Boom.boomify(err, { statusCode: 400 });
};
export function initErrorsApi(server: Server) {
export function initErrorsApi(core: CoreSetup) {
const { server } = core.http;
server.route({
method: 'GET',
path: ROOT,

View file

@ -5,7 +5,7 @@
*/
import Boom from 'boom';
import { Server } from 'hapi';
import { CoreSetup } from 'src/core/server';
import { withDefaultValidators } from '../lib/helpers/input_validation';
import { setupRequest } from '../lib/helpers/setup_request';
import { getAllMetricsChartData } from '../lib/metrics/get_all_metrics_chart_data';
@ -16,7 +16,8 @@ const defaultErrorHandler = (err: Error) => {
throw Boom.boomify(err, { statusCode: 400 });
};
export function initMetricsApi(server: Server) {
export function initMetricsApi(core: CoreSetup) {
const { server } = core.http;
server.route({
method: 'GET',
path: `/api/apm/services/{serviceName}/metrics/charts`,

View file

@ -5,7 +5,7 @@
*/
import Boom from 'boom';
import { Server } from 'hapi';
import { CoreSetup } from 'src/core/server';
import { AgentName } from '../../typings/es_schemas/ui/fields/Agent';
import { createApmTelementry, storeApmTelemetry } from '../lib/apm_telemetry';
import { withDefaultValidators } from '../lib/helpers/input_validation';
@ -20,7 +20,8 @@ const defaultErrorHandler = (err: Error) => {
throw Boom.boomify(err, { statusCode: 400 });
};
export function initServicesApi(server: Server) {
export function initServicesApi(core: CoreSetup) {
const { server } = core.http;
server.route({
method: 'GET',
path: ROOT,

View file

@ -5,7 +5,8 @@
*/
import Boom from 'boom';
import { Server } from 'hapi';
import { CoreSetup } from 'src/core/server';
import { withDefaultValidators } from '../lib/helpers/input_validation';
import { setupRequest } from '../lib/helpers/setup_request';
import { getTopTraces } from '../lib/traces/get_top_traces';
@ -18,7 +19,9 @@ const defaultErrorHandler = (err: Error) => {
throw Boom.boomify(err, { statusCode: 400 });
};
export function initTracesApi(server: Server) {
export function initTracesApi(core: CoreSetup) {
const { server } = core.http;
// Get trace list
server.route({
method: 'GET',

View file

@ -5,8 +5,8 @@
*/
import Boom from 'boom';
import { Server } from 'hapi';
import Joi from 'joi';
import { CoreSetup } from 'src/core/server';
import { withDefaultValidators } from '../lib/helpers/input_validation';
import { setupRequest } from '../lib/helpers/setup_request';
import { getChartsData } from '../lib/transactions/charts';
@ -19,7 +19,9 @@ const defaultErrorHandler = (err: Error) => {
throw Boom.boomify(err, { statusCode: 400 });
};
export function initTransactionGroupsApi(server: Server) {
export function initTransactionGroupsApi(core: CoreSetup) {
const { server } = core.http;
server.route({
method: 'GET',
path: