[Stack Monitoring] Adds optional debug logging for Stack Monitoring (#107711)

This commit is contained in:
Jason Rhodes 2021-08-10 00:09:26 -04:00 committed by GitHub
parent 6b29ca1ce8
commit 3d6aa9f44d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 129 additions and 29 deletions

View file

@ -7,8 +7,7 @@
import fs from 'fs';
import { when } from 'jest-when';
import { createConfig, configSchema } from './config';
import { configSchema, createConfig } from './config';
const MOCKED_PATHS = [
'/proc/self/cgroup',
@ -71,6 +70,8 @@ describe('config schema', () => {
"enabled": false,
},
},
"debug_log_path": "",
"debug_mode": false,
"elasticsearch": Object {
"apiVersion": "master",
"customHeaders": Object {},

View file

@ -25,6 +25,8 @@ export const configSchema = schema.object({
enabled: schema.boolean({ defaultValue: true }),
ui: schema.object({
enabled: schema.boolean({ defaultValue: true }),
debug_mode: schema.boolean({ defaultValue: false }),
debug_log_path: schema.string({ defaultValue: '' }),
ccs: schema.object({
enabled: schema.boolean({ defaultValue: true }),
}),

View file

@ -0,0 +1,85 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import fs from 'fs';
import { MonitoringConfig } from './config';
import { RouteDependencies } from './types';
export function decorateDebugServer(
_server: any,
config: MonitoringConfig,
logger: RouteDependencies['logger']
) {
// bail if the proper config value is not set (extra protection)
if (!config.ui.debug_mode) {
return _server;
}
// create a debug logger that will either write to file (if debug_log_path exists) or log out via logger
const debugLog = createDebugLogger({ path: config.ui.debug_log_path, logger });
return {
// maintain the rest of _server untouched
..._server,
// TODO: replace any
route: (options: any) => {
const apiPath = options.path;
return _server.route({
...options,
// TODO: replace any
handler: async (req: any) => {
const { elasticsearch: cached } = req.server.plugins;
const apiRequestHeaders = req.headers;
req.server.plugins.elasticsearch = {
...req.server.plugins.elasticsearch,
getCluster: (name: string) => {
const cluster = cached.getCluster(name);
return {
...cluster,
// TODO: better types?
callWithRequest: async (_req: typeof req, type: string, params: any) => {
const result = await cluster.callWithRequest(_req, type, params);
// log everything about this request -> query -> result
debugLog({
api_path: apiPath,
referer_url: apiRequestHeaders.referer,
query: {
params,
result,
},
});
return result;
},
};
},
};
return options.handler(req);
},
});
},
};
}
function createDebugLogger({
path,
logger,
}: {
path: string;
logger: RouteDependencies['logger'];
}) {
if (path.length > 0) {
const stream = fs.createWriteStream('./stack_monitoring_debug_log.ndjson', { flags: 'a' });
return function logToFile(line: any) {
stream.write(JSON.stringify(line));
};
} else {
return function logToStdOut(line: any) {
logger.info(JSON.stringify(line));
};
}
}

View file

@ -6,53 +6,52 @@
*/
import Boom from '@hapi/boom';
import { i18n } from '@kbn/i18n';
import { has, get } from 'lodash';
import { TypeOf } from '@kbn/config-schema';
import { i18n } from '@kbn/i18n';
import {
Logger,
PluginInitializerContext,
KibanaRequest,
KibanaResponseFactory,
CoreSetup,
ICustomClusterClient,
CoreStart,
CustomHttpResponseOptions,
ResponseError,
ICustomClusterClient,
KibanaRequest,
KibanaResponseFactory,
Logger,
Plugin,
PluginInitializerContext,
ResponseError,
SharedGlobalConfig,
} from 'kibana/server';
import { get, has } from 'lodash';
import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/server';
import {
LOGGING_TAG,
ALERTS,
KIBANA_MONITORING_LOGGING_TAG,
KIBANA_STATS_TYPE_MONITORING,
ALERTS,
LOGGING_TAG,
SAVED_OBJECT_TELEMETRY,
} from '../common/constants';
import { MonitoringConfig, createConfig, configSchema } from './config';
import { requireUIRoutes } from './routes';
import { initBulkUploader } from './kibana_monitoring';
import { initInfraSource } from './lib/logs/init_infra_source';
import { registerCollectors } from './kibana_monitoring/collectors';
import { registerMonitoringTelemetryCollection } from './telemetry_collection';
import { LicenseService } from './license_service';
import { AlertsFactory } from './alerts';
import { configSchema, createConfig, MonitoringConfig } from './config';
import { instantiateClient } from './es_client/instantiate_client';
import { initBulkUploader } from './kibana_monitoring';
import { registerCollectors } from './kibana_monitoring/collectors';
import { initInfraSource } from './lib/logs/init_infra_source';
import { LicenseService } from './license_service';
import { requireUIRoutes } from './routes';
import { EndpointTypes, Globals } from './static_globals';
import { registerMonitoringTelemetryCollection } from './telemetry_collection';
import {
IBulkUploader,
LegacyRequest,
LegacyShimDependencies,
MonitoringCore,
MonitoringLicenseService,
MonitoringPluginSetup,
LegacyShimDependencies,
IBulkUploader,
PluginsSetup,
PluginsStart,
LegacyRequest,
RequestHandlerContextMonitoringPlugin,
} from './types';
import { Globals, EndpointTypes } from './static_globals';
import { instantiateClient } from './es_client/instantiate_client';
// This is used to test the version of kibana
const snapshotRegex = /-snapshot/i;
@ -192,7 +191,11 @@ export class MonitoringPlugin
plugins
);
requireUIRoutes(this.monitoringCore, {
if (config.ui.debug_mode) {
this.log.info('MONITORING DEBUG MODE: ON');
}
requireUIRoutes(this.monitoringCore, config, {
cluster,
router,
licenseService: this.licenseService,

View file

@ -4,14 +4,23 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
/* eslint import/namespace: ['error', { allowComputed: true }]*/
import { MonitoringConfig } from '../config';
import { decorateDebugServer } from '../debug_logger';
import { RouteDependencies } from '../types';
// @ts-ignore
import * as uiRoutes from './api/v1/ui'; // namespace import
import { RouteDependencies } from '../types';
export function requireUIRoutes(server: any, npRoute: RouteDependencies) {
export function requireUIRoutes(
_server: any,
config: MonitoringConfig,
npRoute: RouteDependencies
) {
const routes = Object.keys(uiRoutes);
const server = config.ui.debug_mode
? decorateDebugServer(_server, config, npRoute.logger)
: _server;
routes.forEach((route) => {
const registerRoute = uiRoutes[route]; // computed reference to module objects imported via namespace