From 08adc1510212c4a35ccd2c61036e6e0b1db42c30 Mon Sep 17 00:00:00 2001 From: Timothy Sullivan Date: Tue, 21 Jan 2020 11:03:50 -0700 Subject: [PATCH] [Reporting/New Platform] Use the logger service from core --- .../export_types/csv/server/execute_job.ts | 13 ++-- .../server/create_job/create_job.ts | 13 ++-- .../server/execute_job.ts | 21 ++--- .../png/server/execute_job/index.ts | 7 +- .../printable_pdf/server/execute_job/index.ts | 7 +- x-pack/legacy/plugins/reporting/index.ts | 4 +- .../browsers/create_browser_driver_factory.ts | 9 +-- .../reporting/server/lib/create_queue.ts | 14 ++-- .../server/lib/create_tagged_logger.ts | 32 ++++---- .../server/lib/create_worker.test.ts | 7 +- .../reporting/server/lib/create_worker.ts | 6 +- .../reporting/server/lib/enqueue_job.ts | 6 +- .../plugins/reporting/server/lib/get_user.ts | 6 +- .../reporting/server/lib/level_logger.ts | 32 ++++---- .../legacy/plugins/reporting/server/plugin.ts | 22 ++++-- .../server/routes/generate_from_jobparams.ts | 8 +- .../routes/generate_from_savedobject.ts | 7 +- .../generate_from_savedobject_immediate.ts | 6 +- .../reporting/server/routes/generation.ts | 10 +-- .../plugins/reporting/server/routes/jobs.ts | 6 +- .../routes/lib/authorized_user_pre_routing.ts | 14 ++-- .../server/routes/lib/get_document_payload.ts | 14 +++- .../server/routes/lib/job_response_handler.js | 48 ------------ .../server/routes/lib/job_response_handler.ts | 78 +++++++++++++++++++ .../lib/reporting_feature_pre_routing.ts | 7 +- .../routes/lib/route_config_factories.ts | 36 ++++++--- x-pack/legacy/plugins/reporting/types.d.ts | 7 +- 27 files changed, 249 insertions(+), 191 deletions(-) delete mode 100644 x-pack/legacy/plugins/reporting/server/routes/lib/job_response_handler.js create mode 100644 x-pack/legacy/plugins/reporting/server/routes/lib/job_response_handler.ts diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts index f35ffa0e45bfe1..b949be384b2aee 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts @@ -5,25 +5,26 @@ */ import { i18n } from '@kbn/i18n'; +import { CSV_JOB_TYPE } from '../../../common/constants'; +import { cryptoFactory } from '../../../server/lib'; import { - ExecuteJobFactory, ESQueueWorkerExecuteFn, + ExecuteJobFactory, FieldFormats, + Logger, ServerFacade, } from '../../../types'; -import { CSV_JOB_TYPE, PLUGIN_ID } from '../../../common/constants'; -import { cryptoFactory, LevelLogger } from '../../../server/lib'; import { JobDocPayloadDiscoverCsv } from '../types'; -import { createGenerateCsv } from './lib/generate_csv'; import { fieldFormatMapFactory } from './lib/field_format_map'; +import { createGenerateCsv } from './lib/generate_csv'; export const executeJobFactory: ExecuteJobFactory> = function executeJobFactoryFn(server: ServerFacade) { +>> = function executeJobFactoryFn(server: ServerFacade, parentLogger: Logger) { const { callWithRequest } = server.plugins.elasticsearch.getCluster('data'); const crypto = cryptoFactory(server); const config = server.config(); - const logger = LevelLogger.createForServer(server, [PLUGIN_ID, CSV_JOB_TYPE, 'execute-job']); + const logger = parentLogger.clone([CSV_JOB_TYPE, 'execute-job']); const serverBasePath = config.get('server.basePath'); return async function executeJob( diff --git a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/create_job/create_job.ts b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/create_job/create_job.ts index 8443be2b25f4f9..a270e3e0329fe8 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/create_job/create_job.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/create_job/create_job.ts @@ -6,13 +6,14 @@ import { notFound, notImplemented } from 'boom'; import { get } from 'lodash'; -import { PLUGIN_ID, CSV_FROM_SAVEDOBJECT_JOB_TYPE } from '../../../../common/constants'; -import { cryptoFactory, LevelLogger } from '../../../../server/lib'; +import { CSV_FROM_SAVEDOBJECT_JOB_TYPE } from '../../../../common/constants'; +import { cryptoFactory } from '../../../../server/lib'; import { CreateJobFactory, ImmediateCreateJobFn, ServerFacade, RequestFacade, + Logger, } from '../../../../types'; import { SavedObject, @@ -34,13 +35,9 @@ interface VisData { export const createJobFactory: CreateJobFactory> = function createJobFactoryFn(server: ServerFacade) { +>> = function createJobFactoryFn(server: ServerFacade, parentLogger: Logger) { const crypto = cryptoFactory(server); - const logger = LevelLogger.createForServer(server, [ - PLUGIN_ID, - CSV_FROM_SAVEDOBJECT_JOB_TYPE, - 'create-job', - ]); + const logger = parentLogger.clone([CSV_FROM_SAVEDOBJECT_JOB_TYPE, 'create-job']); return async function createJob( jobParams: JobParamsPanelCsv, diff --git a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/execute_job.ts b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/execute_job.ts index 69d9a173d40b38..38c1c27c1deae6 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/execute_job.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/execute_job.ts @@ -5,32 +5,25 @@ */ import { i18n } from '@kbn/i18n'; -import { cryptoFactory, LevelLogger } from '../../../server/lib'; +import { CONTENT_TYPE_CSV, CSV_FROM_SAVEDOBJECT_JOB_TYPE } from '../../../common/constants'; +import { cryptoFactory } from '../../../server/lib'; import { ExecuteJobFactory, ImmediateExecuteFn, JobDocOutputExecuted, - ServerFacade, + Logger, RequestFacade, + ServerFacade, } from '../../../types'; -import { - CONTENT_TYPE_CSV, - CSV_FROM_SAVEDOBJECT_JOB_TYPE, - PLUGIN_ID, -} from '../../../common/constants'; import { CsvResultFromSearch } from '../../csv/types'; -import { JobParamsPanelCsv, SearchPanel, JobDocPayloadPanelCsv, FakeRequest } from '../types'; +import { FakeRequest, JobDocPayloadPanelCsv, JobParamsPanelCsv, SearchPanel } from '../types'; import { createGenerateCsv } from './lib'; export const executeJobFactory: ExecuteJobFactory> = function executeJobFactoryFn(server: ServerFacade) { +>> = function executeJobFactoryFn(server: ServerFacade, parentLogger: Logger) { const crypto = cryptoFactory(server); - const logger = LevelLogger.createForServer(server, [ - PLUGIN_ID, - CSV_FROM_SAVEDOBJECT_JOB_TYPE, - 'execute-job', - ]); + const logger = parentLogger.clone([CSV_FROM_SAVEDOBJECT_JOB_TYPE, 'execute-job']); return async function executeJob( jobId: string | null, diff --git a/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.ts b/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.ts index c2fda05fbe3e93..7d5c69655c362f 100644 --- a/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.ts +++ b/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.ts @@ -6,14 +6,14 @@ import * as Rx from 'rxjs'; import { catchError, map, mergeMap, takeUntil } from 'rxjs/operators'; -import { PLUGIN_ID, PNG_JOB_TYPE } from '../../../../common/constants'; +import { PNG_JOB_TYPE } from '../../../../common/constants'; import { ServerFacade, ExecuteJobFactory, ESQueueWorkerExecuteFn, HeadlessChromiumDriverFactory, + Logger, } from '../../../../types'; -import { LevelLogger } from '../../../../server/lib'; import { decryptJobHeaders, omitBlacklistedHeaders, @@ -27,10 +27,11 @@ type QueuedPngExecutorFactory = ExecuteJobFactory { uiSettingsServiceFactory: server.uiSettingsServiceFactory, // @ts-ignore Property 'fieldFormatServiceFactory' does not exist on type 'Server'. fieldFormatServiceFactory: server.fieldFormatServiceFactory, - log: server.log.bind(server), }; - const plugin: ReportingPlugin = reportingPluginFactory(__LEGACY, this); + const initializerContext = server.newPlatform.coreContext; + const plugin: ReportingPlugin = reportingPluginFactory(initializerContext, __LEGACY, this); await plugin.setup(coreSetup, pluginsSetup); }, diff --git a/x-pack/legacy/plugins/reporting/server/browsers/create_browser_driver_factory.ts b/x-pack/legacy/plugins/reporting/server/browsers/create_browser_driver_factory.ts index a253988b01952e..128df4d318c764 100644 --- a/x-pack/legacy/plugins/reporting/server/browsers/create_browser_driver_factory.ts +++ b/x-pack/legacy/plugins/reporting/server/browsers/create_browser_driver_factory.ts @@ -6,17 +6,16 @@ import { ensureBrowserDownloaded } from './download'; import { installBrowser } from './install'; -import { LevelLogger } from '../lib/level_logger'; -import { ServerFacade, CaptureConfig } from '../../types'; -import { PLUGIN_ID, BROWSER_TYPE } from '../../common/constants'; +import { ServerFacade, CaptureConfig, Logger } from '../../types'; +import { BROWSER_TYPE } from '../../common/constants'; import { chromium } from './index'; import { HeadlessChromiumDriverFactory } from './chromium/driver_factory'; export async function createBrowserDriverFactory( - server: ServerFacade + server: ServerFacade, + logger: Logger ): Promise { const config = server.config(); - const logger = LevelLogger.createForServer(server, [PLUGIN_ID, 'browser-driver']); const dataDir: string = config.get('path.data'); const captureConfig: CaptureConfig = config.get('xpack.reporting.capture'); diff --git a/x-pack/legacy/plugins/reporting/server/lib/create_queue.ts b/x-pack/legacy/plugins/reporting/server/lib/create_queue.ts index 4a9b0c7cd2ebb3..05b760c0c3bd6c 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/create_queue.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/create_queue.ts @@ -4,17 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import { PLUGIN_ID } from '../../common/constants'; import { ServerFacade, ExportTypesRegistry, HeadlessChromiumDriverFactory, QueueConfig, + Logger, } from '../../types'; // @ts-ignore import { Esqueue } from './esqueue'; import { createWorkerFactory } from './create_worker'; -import { LevelLogger } from './level_logger'; import { createTaggedLogger } from './create_tagged_logger'; // TODO remove createTaggedLogger once esqueue is removed interface CreateQueueFactoryOpts { @@ -24,6 +23,7 @@ interface CreateQueueFactoryOpts { export function createQueueFactory( server: ServerFacade, + logger: Logger, { exportTypesRegistry, browserDriverFactory }: CreateQueueFactoryOpts ): Esqueue { const queueConfig: QueueConfig = server.config().get('xpack.reporting.queue'); @@ -34,23 +34,25 @@ export function createQueueFactory( timeout: queueConfig.timeout, dateSeparator: '.', client: server.plugins.elasticsearch.getCluster('admin'), - logger: createTaggedLogger(server, [PLUGIN_ID, 'esqueue', 'queue-worker']), + logger: createTaggedLogger(logger, ['esqueue', 'queue-worker']), }; const queue: Esqueue = new Esqueue(index, queueOptions); if (queueConfig.pollEnabled) { // create workers to poll the index for idle jobs waiting to be claimed and executed - const createWorker = createWorkerFactory(server, { exportTypesRegistry, browserDriverFactory }); + const createWorker = createWorkerFactory(server, logger, { + exportTypesRegistry, + browserDriverFactory, + }); createWorker(queue); } else { - const logger = LevelLogger.createForServer(server, [PLUGIN_ID, 'create_queue']); logger.info( 'xpack.reporting.queue.pollEnabled is set to false. This Kibana instance ' + 'will not poll for idle jobs to claim and execute. Make sure another ' + 'Kibana instance with polling enabled is running in this cluster so ' + 'reporting jobs can complete.', - ['info'] + ['create_queue'] ); } diff --git a/x-pack/legacy/plugins/reporting/server/lib/create_tagged_logger.ts b/x-pack/legacy/plugins/reporting/server/lib/create_tagged_logger.ts index 40a1cd8203d2fe..97b34dfe40830c 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/create_tagged_logger.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/create_tagged_logger.ts @@ -4,23 +4,23 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ServerFacade } from '../../types'; +import { Logger } from '../../types'; -/** - * @function taggedLogger - * @param {string} message - * @param {string[]} [additionalTags] - */ - -/** - * Creates a taggedLogger function with tags, allows the consumer to optionally provide additional tags - * - * @param {Server} server - * @param {string[]} tags - tags to always be passed into the `logger` function - * @returns taggedLogger - */ -export function createTaggedLogger(server: ServerFacade, tags: string[]) { +export function createTaggedLogger(logger: Logger, tags: string[]) { return (msg: string, additionalTags = []) => { - server.log([...tags, ...additionalTags], msg); + const allTags = [...tags, ...additionalTags]; + + if (allTags.includes('info')) { + const newTags = allTags.filter(t => t !== 'info'); // Ensure 'info' is not included twice + logger.info(msg, newTags); + } else if (allTags.includes('debug')) { + const newTags = allTags.filter(t => t !== 'debug'); + logger.debug(msg, newTags); + } else if (allTags.includes('warn') || allTags.includes('warning')) { + const newTags = allTags.filter(t => t !== 'warn' && t !== 'warning'); + logger.warn(msg, newTags); + } else { + logger.error(msg, allTags); + } }; } diff --git a/x-pack/legacy/plugins/reporting/server/lib/create_worker.test.ts b/x-pack/legacy/plugins/reporting/server/lib/create_worker.test.ts index 8f843752491ecb..6a5c93db32376a 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/create_worker.test.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/create_worker.test.ts @@ -25,10 +25,11 @@ const executeJobFactoryStub = sinon.stub(); const getMockServer = (): ServerFacade => { return ({ - log: sinon.stub(), config: () => ({ get: configGetStub }), } as unknown) as ServerFacade; }; +const getMockLogger = jest.fn(); + const getMockExportTypesRegistry = ( exportTypes: any[] = [{ executeJobFactory: executeJobFactoryStub }] ) => ({ @@ -47,7 +48,7 @@ describe('Create Worker', () => { test('Creates a single Esqueue worker for Reporting', async () => { const exportTypesRegistry = getMockExportTypesRegistry(); - const createWorker = createWorkerFactory(getMockServer(), { + const createWorker = createWorkerFactory(getMockServer(), getMockLogger(), { exportTypesRegistry: exportTypesRegistry as ExportTypesRegistry, browserDriverFactory: {} as HeadlessChromiumDriverFactory, }); @@ -81,7 +82,7 @@ Object { { executeJobFactory: executeJobFactoryStub }, { executeJobFactory: executeJobFactoryStub }, ]); - const createWorker = createWorkerFactory(getMockServer(), { + const createWorker = createWorkerFactory(getMockServer(), getMockLogger(), { exportTypesRegistry: exportTypesRegistry as ExportTypesRegistry, browserDriverFactory: {} as HeadlessChromiumDriverFactory, }); diff --git a/x-pack/legacy/plugins/reporting/server/lib/create_worker.ts b/x-pack/legacy/plugins/reporting/server/lib/create_worker.ts index 1326e411b6c5c7..67869016a250be 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/create_worker.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/create_worker.ts @@ -17,10 +17,10 @@ import { JobSource, RequestFacade, ServerFacade, + Logger, } from '../../types'; // @ts-ignore untyped dependency import { events as esqueueEvents } from './esqueue'; -import { LevelLogger } from './level_logger'; interface CreateWorkerFactoryOpts { exportTypesRegistry: ExportTypesRegistry; @@ -29,11 +29,11 @@ interface CreateWorkerFactoryOpts { export function createWorkerFactory( server: ServerFacade, + logger: Logger, { exportTypesRegistry, browserDriverFactory }: CreateWorkerFactoryOpts ) { type JobDocPayloadType = JobDocPayload; const config = server.config(); - const logger = LevelLogger.createForServer(server, [PLUGIN_ID, 'queue-worker']); const queueConfig: QueueConfig = config.get('xpack.reporting.queue'); const kibanaName: string = config.get('server.name'); const kibanaId: string = config.get('server.uuid'); @@ -50,7 +50,7 @@ export function createWorkerFactory( ExportTypeDefinition >) { // TODO: the executeJobFn should be unwrapped in the register method of the export types registry - const jobExecutor = exportType.executeJobFactory(server, { browserDriverFactory }); + const jobExecutor = exportType.executeJobFactory(server, logger, { browserDriverFactory }); jobExecutors.set(exportType.jobType, jobExecutor); } diff --git a/x-pack/legacy/plugins/reporting/server/lib/enqueue_job.ts b/x-pack/legacy/plugins/reporting/server/lib/enqueue_job.ts index 2d044ab31a160e..14c57fa35dcf4e 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/enqueue_job.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/enqueue_job.ts @@ -35,8 +35,10 @@ interface EnqueueJobFactoryOpts { export function enqueueJobFactory( server: ServerFacade, + parentLogger: Logger, { exportTypesRegistry, esqueue }: EnqueueJobFactoryOpts ): EnqueueJobFn { + const logger = parentLogger.clone(['queue-job']); const config = server.config(); const captureConfig: CaptureConfig = config.get('xpack.reporting.capture'); const browserType = captureConfig.browser.type; @@ -44,7 +46,6 @@ export function enqueueJobFactory( const queueConfig: QueueConfig = config.get('xpack.reporting.queue'); return async function enqueueJob( - parentLogger: Logger, exportTypeId: string, jobParams: JobParamsType, user: string, @@ -53,7 +54,6 @@ export function enqueueJobFactory( ): Promise { type CreateJobFn = ESQueueCreateJobFn | ImmediateCreateJobFn; - const logger = parentLogger.clone(['queue-job']); const exportType = exportTypesRegistry.getById(exportTypeId); if (exportType == null) { @@ -61,7 +61,7 @@ export function enqueueJobFactory( } // TODO: the createJobFn should be unwrapped in the register method of the export types registry - const createJob = exportType.createJobFactory(server) as CreateJobFn; + const createJob = exportType.createJobFactory(server, logger) as CreateJobFn; const payload = await createJob(jobParams, headers, request); const options = { diff --git a/x-pack/legacy/plugins/reporting/server/lib/get_user.ts b/x-pack/legacy/plugins/reporting/server/lib/get_user.ts index e2921de795012b..fac1177afff741 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/get_user.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/get_user.ts @@ -5,9 +5,9 @@ */ import { Legacy } from 'kibana'; -import { ServerFacade } from '../../types'; +import { Logger, ServerFacade } from '../../types'; -export function getUserFactory(server: ServerFacade) { +export function getUserFactory(server: ServerFacade, logger: Logger) { /* * Legacy.Request because this is called from routing middleware */ @@ -19,7 +19,7 @@ export function getUserFactory(server: ServerFacade) { try { return await server.plugins.security.getUser(request); } catch (err) { - server.log(['reporting', 'getUser', 'error'], err); + logger.error(err); return null; } }; diff --git a/x-pack/legacy/plugins/reporting/server/lib/level_logger.ts b/x-pack/legacy/plugins/reporting/server/lib/level_logger.ts index 839fa16a716b7d..d015d500363c12 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/level_logger.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/level_logger.ts @@ -4,48 +4,46 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ServerFacade } from '../../types'; +import { LoggerFactory } from 'src/core/server'; const trimStr = (toTrim: string) => { return typeof toTrim === 'string' ? toTrim.trim() : toTrim; }; export class LevelLogger { - private _logger: any; + private _logger: LoggerFactory; private _tags: string[]; + public warning: (msg: string, tags?: string[]) => void; - public warn: (msg: string, tags?: string[]) => void; - - static createForServer(server: ServerFacade, tags: string[]) { - const serverLog: ServerFacade['log'] = (tgs: string[], msg: string) => server.log(tgs, msg); - return new LevelLogger(serverLog, tags); - } - - constructor(logger: ServerFacade['log'], tags: string[]) { + constructor(logger: LoggerFactory, tags?: string[]) { this._logger = logger; - this._tags = tags; + this._tags = tags || []; /* * This shortcut provides maintenance convenience: Reporting code has been * using both .warn and .warning */ - this.warn = this.warning.bind(this); + this.warning = this.warn.bind(this); + } + + private getLogger(tags: string[]) { + return this._logger.get(...this._tags, ...tags); } public error(err: string | Error, tags: string[] = []) { - this._logger([...this._tags, ...tags, 'error'], err); + this.getLogger(tags).error(err); } - public warning(msg: string, tags: string[] = []) { - this._logger([...this._tags, ...tags, 'warning'], trimStr(msg)); + public warn(msg: string, tags: string[] = []) { + this.getLogger(tags).warn(msg); } public debug(msg: string, tags: string[] = []) { - this._logger([...this._tags, ...tags, 'debug'], trimStr(msg)); + this.getLogger(tags).debug(msg); } public info(msg: string, tags: string[] = []) { - this._logger([...this._tags, ...tags, 'info'], trimStr(msg)); + this.getLogger(tags).info(trimStr(msg)); } public clone(tags: string[]) { diff --git a/x-pack/legacy/plugins/reporting/server/plugin.ts b/x-pack/legacy/plugins/reporting/server/plugin.ts index 934a3487209c42..b0dc56dd8d8d0e 100644 --- a/x-pack/legacy/plugins/reporting/server/plugin.ts +++ b/x-pack/legacy/plugins/reporting/server/plugin.ts @@ -5,7 +5,7 @@ */ import { Legacy } from 'kibana'; -import { CoreSetup, CoreStart, Plugin } from 'src/core/server'; +import { CoreSetup, CoreStart, Plugin, LoggerFactory } from 'src/core/server'; import { IUiSettingsClient } from 'src/core/server'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { XPackMainPlugin } from '../../xpack_main/server/xpack_main'; @@ -14,11 +14,15 @@ import { mirrorPluginStatus } from '../../../server/lib/mirror_plugin_status'; import { PLUGIN_ID } from '../common/constants'; import { ReportingPluginSpecOptions } from '../types.d'; import { registerRoutes } from './routes'; -import { LevelLogger, checkLicenseFactory, getExportTypesRegistry, runValidations } from './lib'; +import { checkLicenseFactory, getExportTypesRegistry, runValidations, LevelLogger } from './lib'; import { createBrowserDriverFactory } from './browsers'; import { registerReportingUsageCollector } from './usage'; import { logConfiguration } from '../log_configuration'; +export interface ReportingInitializerContext { + logger: LoggerFactory; +} + // For now there is no exposed functionality to other plugins export type ReportingSetup = object; export type ReportingStart = object; @@ -33,7 +37,6 @@ type LegacyPlugins = Legacy.Server['plugins']; export interface LegacySetup { config: Legacy.Server['config']; info: Legacy.Server['info']; - log: Legacy.Server['log']; plugins: { elasticsearch: LegacyPlugins['elasticsearch']; security: LegacyPlugins['security']; @@ -59,10 +62,17 @@ export type ReportingPlugin = Plugin< * into `setup`. The factory parameters take the legacy dependencies, and the * `setup` method gets it from enclosure */ export function reportingPluginFactory( + initializerContext: ReportingInitializerContext, __LEGACY: LegacySetup, legacyPlugin: ReportingPluginSpecOptions ) { return new (class ReportingPlugin implements ReportingPlugin { + private initializerContext: ReportingInitializerContext; + + constructor(context: ReportingInitializerContext) { + this.initializerContext = context; + } + public async setup(core: CoreSetup, plugins: ReportingSetupDeps): Promise { const exportTypesRegistry = getExportTypesRegistry(); @@ -76,8 +86,8 @@ export function reportingPluginFactory( exportTypesRegistry ); - const logger = LevelLogger.createForServer(__LEGACY, [PLUGIN_ID]); - const browserDriverFactory = await createBrowserDriverFactory(__LEGACY); + const logger = new LevelLogger(this.initializerContext.logger.get('reporting')); + const browserDriverFactory = await createBrowserDriverFactory(__LEGACY, logger); logConfiguration(__LEGACY, logger); runValidations(__LEGACY, logger, browserDriverFactory); @@ -103,5 +113,5 @@ export function reportingPluginFactory( public start(core: CoreStart, plugins: ReportingStartDeps): ReportingStart { return {}; } - })(); + })(initializerContext); } diff --git a/x-pack/legacy/plugins/reporting/server/routes/generate_from_jobparams.ts b/x-pack/legacy/plugins/reporting/server/routes/generate_from_jobparams.ts index c9225dfee69788..d920015c4290c0 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/generate_from_jobparams.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/generate_from_jobparams.ts @@ -9,7 +9,7 @@ import boom from 'boom'; import Joi from 'joi'; import rison from 'rison-node'; import { API_BASE_URL } from '../../common/constants'; -import { ServerFacade, ReportingResponseToolkit } from '../../types'; +import { ServerFacade, ReportingResponseToolkit, Logger } from '../../types'; import { getRouteConfigFactoryReportingPre, GetRouteConfigFactoryFn, @@ -23,11 +23,13 @@ const BASE_GENERATE = `${API_BASE_URL}/generate`; export function registerGenerateFromJobParams( server: ServerFacade, handler: HandlerFunction, - handleError: HandlerErrorFunction + handleError: HandlerErrorFunction, + logger: Logger ) { const getRouteConfig = () => { const getOriginalRouteConfig: GetRouteConfigFactoryFn = getRouteConfigFactoryReportingPre( - server + server, + logger ); const routeConfigFactory: RouteConfigFactory = getOriginalRouteConfig( ({ params: { exportType } }) => exportType diff --git a/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject.ts b/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject.ts index 2c509136b1b441..0da8e40ea29c0f 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject.ts @@ -7,7 +7,7 @@ import { Legacy } from 'kibana'; import { get } from 'lodash'; import { API_BASE_GENERATE_V1, CSV_FROM_SAVEDOBJECT_JOB_TYPE } from '../../common/constants'; -import { ServerFacade, ReportingResponseToolkit } from '../../types'; +import { ServerFacade, ReportingResponseToolkit, Logger } from '../../types'; import { HandlerErrorFunction, HandlerFunction, QueuedJobPayload } from './types'; import { getRouteOptionsCsv } from './lib/route_config_factories'; import { makeRequestFacade } from './lib/make_request_facade'; @@ -25,9 +25,10 @@ import { getJobParamsFromRequest } from '../../export_types/csv_from_savedobject export function registerGenerateCsvFromSavedObject( server: ServerFacade, handleRoute: HandlerFunction, - handleRouteError: HandlerErrorFunction + handleRouteError: HandlerErrorFunction, + logger: Logger ) { - const routeOptions = getRouteOptionsCsv(server); + const routeOptions = getRouteOptionsCsv(server, logger); server.route({ path: `${API_BASE_GENERATE_V1}/csv/saved-object/{savedObjectType}:{savedObjectId}`, diff --git a/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject_immediate.ts b/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject_immediate.ts index 8d1c84664cbe9d..369d466a53d245 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject_immediate.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject_immediate.ts @@ -33,7 +33,7 @@ export function registerGenerateCsvFromSavedObjectImmediate( server: ServerFacade, parentLogger: Logger ) { - const routeOptions = getRouteOptionsCsv(server); + const routeOptions = getRouteOptionsCsv(server, parentLogger); /* * CSV export with the `immediate` option does not queue a job with Reporting's ESQueue to run the job async. Instead, this does: @@ -55,8 +55,8 @@ export function registerGenerateCsvFromSavedObjectImmediate( * * Calling an execute job factory requires passing a browserDriverFactory option, so we should not call the factory from here */ - const createJobFn = createJobFactory(server); - const executeJobFn = executeJobFactory(server, { + const createJobFn = createJobFactory(server, logger); + const executeJobFn = executeJobFactory(server, logger, { browserDriverFactory: {} as HeadlessChromiumDriverFactory, }); const jobDocPayload: JobDocPayloadPanelCsv = await createJobFn( diff --git a/x-pack/legacy/plugins/reporting/server/routes/generation.ts b/x-pack/legacy/plugins/reporting/server/routes/generation.ts index 21af54ddf11e36..2a3102d0dd1590 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/generation.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/generation.ts @@ -31,8 +31,8 @@ export function registerJobGenerationRoutes( // @ts-ignore TODO const { errors: esErrors } = server.plugins.elasticsearch.getCluster('admin'); - const esqueue = createQueueFactory(server, { exportTypesRegistry, browserDriverFactory }); - const enqueueJob = enqueueJobFactory(server, { exportTypesRegistry, esqueue }); + const esqueue = createQueueFactory(server, logger, { exportTypesRegistry, browserDriverFactory }); + const enqueueJob = enqueueJobFactory(server, logger, { exportTypesRegistry, esqueue }); /* * Generates enqueued job details to use in responses @@ -47,7 +47,7 @@ export function registerJobGenerationRoutes( const user = request.pre.user; const headers = request.headers; - const job = await enqueueJob(logger, exportTypeId, jobParams, user, headers, request); + const job = await enqueueJob(exportTypeId, jobParams, user, headers, request); // return the queue's job information const jobJson = job.toJSON(); @@ -73,11 +73,11 @@ export function registerJobGenerationRoutes( return err; } - registerGenerateFromJobParams(server, handler, handleError); + registerGenerateFromJobParams(server, handler, handleError, logger); // Register beta panel-action download-related API's if (config.get('xpack.reporting.csv.enablePanelActionDownload')) { - registerGenerateCsvFromSavedObject(server, handler, handleError); + registerGenerateCsvFromSavedObject(server, handler, handleError, logger); registerGenerateCsvFromSavedObjectImmediate(server, logger); } } diff --git a/x-pack/legacy/plugins/reporting/server/routes/jobs.ts b/x-pack/legacy/plugins/reporting/server/routes/jobs.ts index 6084ca613d10ed..952d4f099fd24e 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/jobs.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/jobs.ts @@ -16,9 +16,7 @@ import { JobSource, ListQuery, } from '../../types'; -// @ts-ignore import { jobsQueryFactory } from '../lib/jobs_query'; -// @ts-ignore import { jobResponseHandlerFactory } from './lib/job_response_handler'; import { getRouteConfigFactoryDownloadPre, @@ -34,8 +32,8 @@ export function registerJobInfoRoutes( logger: Logger ) { const jobsQuery = jobsQueryFactory(server); - const getRouteConfig = getRouteConfigFactoryManagementPre(server); - const getRouteConfigDownload = getRouteConfigFactoryDownloadPre(server); + const getRouteConfig = getRouteConfigFactoryManagementPre(server, logger); + const getRouteConfigDownload = getRouteConfigFactoryDownloadPre(server, logger); // list jobs in the queue, paginated server.route({ diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.ts b/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.ts index eb473e0bc76d45..906f266290a421 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.ts @@ -8,7 +8,7 @@ import Boom from 'boom'; import { Legacy } from 'kibana'; import { AuthenticatedUser } from '../../../../../../plugins/security/server'; import { getUserFactory } from '../../lib/get_user'; -import { ServerFacade } from '../../../types'; +import { ServerFacade, Logger } from '../../../types'; const superuserRole = 'superuser'; @@ -17,19 +17,19 @@ export type PreRoutingFunction = ( ) => Promise | AuthenticatedUser | null>; export const authorizedUserPreRoutingFactory = function authorizedUserPreRoutingFn( - server: ServerFacade + server: ServerFacade, + logger: Logger ) { - const getUser = getUserFactory(server); + const getUser = getUserFactory(server, logger); const config = server.config(); return async function authorizedUserPreRouting(request: Legacy.Request) { const xpackInfo = server.plugins.xpack_main.info; if (!xpackInfo || !xpackInfo.isAvailable()) { - server.log( - ['reporting', 'authorizedUserPreRouting', 'debug'], - 'Unable to authorize user before xpack info is available.' - ); + logger.warn('Unable to authorize user before xpack info is available.', [ + 'authorizedUserPreRouting', + ]); return Boom.notFound(); } diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/get_document_payload.ts b/x-pack/legacy/plugins/reporting/server/routes/lib/get_document_payload.ts index c3a30f9dda4543..2a849776183b6b 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/lib/get_document_payload.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/lib/get_document_payload.ts @@ -20,10 +20,17 @@ interface ICustomHeaders { [x: string]: any; } -const DEFAULT_TITLE = 'report'; - type ExportTypeType = ExportTypeDefinition; +interface Payload { + statusCode: number; + content: any; + contentType: string; + headers: Record; +} + +const DEFAULT_TITLE = 'report'; + const getTitle = (exportType: ExportTypeType, title?: string): string => `${title || DEFAULT_TITLE}.${exportType.jobContentExtension}`; @@ -78,6 +85,7 @@ export function getDocumentPayloadFactory( reason: output.content, }, contentType: 'application/json', + headers: {}, }; } @@ -92,7 +100,7 @@ export function getDocumentPayloadFactory( return function getDocumentPayload(doc: { _source: JobDocExecuted<{ output: JobDocOutputExecuted }>; - }) { + }): Payload { const { status, jobtype: jobType, payload: { title } = { title: '' } } = doc._source; const { output } = doc._source; diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/job_response_handler.js b/x-pack/legacy/plugins/reporting/server/routes/lib/job_response_handler.js deleted file mode 100644 index e2da3235461136..00000000000000 --- a/x-pack/legacy/plugins/reporting/server/routes/lib/job_response_handler.js +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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 boom from 'boom'; -import { jobsQueryFactory } from '../../lib/jobs_query'; -import { WHITELISTED_JOB_CONTENT_TYPES } from '../../../common/constants'; -import { getDocumentPayloadFactory } from './get_document_payload'; - -export function jobResponseHandlerFactory(server, exportTypesRegistry) { - const jobsQuery = jobsQueryFactory(server); - const getDocumentPayload = getDocumentPayloadFactory(server, exportTypesRegistry); - - return function jobResponseHandler(validJobTypes, user, h, params, opts = {}) { - const { docId } = params; - return jobsQuery.get(user, docId, { includeContent: !opts.excludeContent }).then(doc => { - if (!doc) return boom.notFound(); - - const { jobtype: jobType } = doc._source; - if (!validJobTypes.includes(jobType)) { - return boom.unauthorized(`Sorry, you are not authorized to download ${jobType} reports`); - } - - const output = getDocumentPayload(doc); - - if (!WHITELISTED_JOB_CONTENT_TYPES.includes(output.contentType)) { - return boom.badImplementation( - `Unsupported content-type of ${output.contentType} specified by job output` - ); - } - - const response = h - .response(output.content) - .type(output.contentType) - .code(output.statusCode); - - if (output.headers) { - Object.keys(output.headers).forEach(key => { - response.header(key, output.headers[key]); - }); - } - - return response; - }); - }; -} diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/job_response_handler.ts b/x-pack/legacy/plugins/reporting/server/routes/lib/job_response_handler.ts new file mode 100644 index 00000000000000..0599e1fdad7319 --- /dev/null +++ b/x-pack/legacy/plugins/reporting/server/routes/lib/job_response_handler.ts @@ -0,0 +1,78 @@ +/* + * 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 boom from 'boom'; +import { ResponseToolkit } from 'hapi'; +import { + ServerFacade, + ExportTypesRegistry, + JobDocExecuted, + JobDocOutputExecuted, +} from '../../../types'; +import { jobsQueryFactory } from '../../lib/jobs_query'; +import { WHITELISTED_JOB_CONTENT_TYPES } from '../../../common/constants'; +import { getDocumentPayloadFactory } from './get_document_payload'; + +interface JobResponseHandlerParams { + docId: string; +} + +interface JobResponseHandlerOpts { + excludeContent?: boolean; +} + +type JobResponse = void | { + _source: JobDocExecuted<{ output: JobDocOutputExecuted }>; +}; + +export function jobResponseHandlerFactory( + server: ServerFacade, + exportTypesRegistry: ExportTypesRegistry +) { + const jobsQuery = jobsQueryFactory(server); + const getDocumentPayload = getDocumentPayloadFactory(server, exportTypesRegistry); + + return function jobResponseHandler( + validJobTypes: string[], + user: any, + h: ResponseToolkit, + params: JobResponseHandlerParams, + opts: JobResponseHandlerOpts = {} + ) { + const { docId } = params; + return jobsQuery + .get(user, docId, { includeContent: !opts.excludeContent }) + .then((doc: JobResponse) => { + if (!doc) return boom.notFound(); + + const { jobtype: jobType } = doc._source; + if (!validJobTypes.includes(jobType)) { + return boom.unauthorized(`Sorry, you are not authorized to download ${jobType} reports`); + } + + const output = getDocumentPayload(doc); + + if (!WHITELISTED_JOB_CONTENT_TYPES.includes(output.contentType)) { + return boom.badImplementation( + `Unsupported content-type of ${output.contentType} specified by job output` + ); + } + + const response = h + .response(output.content) + .type(output.contentType) + .code(output.statusCode); + + if (output.headers) { + Object.keys(output.headers).forEach(key => { + response.header(key, output.headers[key]); + }); + } + + return response; + }); + }; +} diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/reporting_feature_pre_routing.ts b/x-pack/legacy/plugins/reporting/server/routes/lib/reporting_feature_pre_routing.ts index 6efac818981efa..88c5e4edc12f87 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/lib/reporting_feature_pre_routing.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/lib/reporting_feature_pre_routing.ts @@ -6,12 +6,13 @@ import Boom from 'boom'; import { Legacy } from 'kibana'; -import { ServerFacade } from '../../../types'; +import { Logger, ServerFacade } from '../../../types'; export type GetReportingFeatureIdFn = (request: Legacy.Request) => string; export const reportingFeaturePreRoutingFactory = function reportingFeaturePreRoutingFn( - server: ServerFacade + server: ServerFacade, + logger: Logger ) { const xpackMainPlugin = server.plugins.xpack_main; const pluginId = 'reporting'; @@ -20,7 +21,7 @@ export const reportingFeaturePreRoutingFactory = function reportingFeaturePreRou return function reportingFeaturePreRouting(getReportingFeatureId: GetReportingFeatureIdFn) { return function licensePreRouting(request: Legacy.Request) { const licenseCheckResults = xpackMainPlugin.info.feature(pluginId).getLicenseCheckResults(); - const reportingFeatureId = getReportingFeatureId(request); + const reportingFeatureId = getReportingFeatureId(request) as string; const reportingFeature = licenseCheckResults[reportingFeatureId]; if (!reportingFeature.showLinks || !reportingFeature.enableLinks) { throw Boom.forbidden(reportingFeature.message); diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/route_config_factories.ts b/x-pack/legacy/plugins/reporting/server/routes/lib/route_config_factories.ts index caf24bf64f6023..ba10814e9787da 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/lib/route_config_factories.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/lib/route_config_factories.ts @@ -5,8 +5,9 @@ */ import Joi from 'joi'; +import { Legacy } from 'kibana'; import { CSV_FROM_SAVEDOBJECT_JOB_TYPE } from '../../../common/constants'; -import { ServerFacade } from '../../../types'; +import { ServerFacade, Logger } from '../../../types'; import { authorizedUserPreRoutingFactory } from './authorized_user_pre_routing'; import { reportingFeaturePreRoutingFactory } from './reporting_feature_pre_routing'; import { GetReportingFeatureIdFn } from './reporting_feature_pre_routing'; @@ -21,15 +22,20 @@ export interface RouteConfigFactory { }; } +type GetFeatureFunction = (request: Legacy.Request) => any; + export type GetRouteConfigFactoryFn = ( getFeatureId?: GetReportingFeatureIdFn ) => RouteConfigFactory; -export function getRouteConfigFactoryReportingPre(server: ServerFacade): GetRouteConfigFactoryFn { - const authorizedUserPreRouting = authorizedUserPreRoutingFactory(server); - const reportingFeaturePreRouting = reportingFeaturePreRoutingFactory(server); +export function getRouteConfigFactoryReportingPre( + server: ServerFacade, + logger: Logger +): GetRouteConfigFactoryFn { + const authorizedUserPreRouting = authorizedUserPreRoutingFactory(server, logger); + const reportingFeaturePreRouting = reportingFeaturePreRoutingFactory(server, logger); - return (getFeatureId?: GetReportingFeatureIdFn): RouteConfigFactory => { + return (getFeatureId?: GetFeatureFunction): RouteConfigFactory => { const preRouting: any[] = [{ method: authorizedUserPreRouting, assign: 'user' }]; if (getFeatureId) { preRouting.push(reportingFeaturePreRouting(getFeatureId)); @@ -42,8 +48,8 @@ export function getRouteConfigFactoryReportingPre(server: ServerFacade): GetRout }; } -export function getRouteOptionsCsv(server: ServerFacade) { - const getRouteConfig = getRouteConfigFactoryReportingPre(server); +export function getRouteOptionsCsv(server: ServerFacade, logger: Logger) { + const getRouteConfig = getRouteConfigFactoryReportingPre(server, logger); return { ...getRouteConfig(() => CSV_FROM_SAVEDOBJECT_JOB_TYPE), validate: { @@ -63,9 +69,12 @@ export function getRouteOptionsCsv(server: ServerFacade) { }; } -export function getRouteConfigFactoryManagementPre(server: ServerFacade): GetRouteConfigFactoryFn { - const authorizedUserPreRouting = authorizedUserPreRoutingFactory(server); - const reportingFeaturePreRouting = reportingFeaturePreRoutingFactory(server); +export function getRouteConfigFactoryManagementPre( + server: ServerFacade, + logger: Logger +): GetRouteConfigFactoryFn { + const authorizedUserPreRouting = authorizedUserPreRoutingFactory(server, logger); + const reportingFeaturePreRouting = reportingFeaturePreRoutingFactory(server, logger); const managementPreRouting = reportingFeaturePreRouting(() => 'management'); return (): RouteConfigFactory => { @@ -83,8 +92,11 @@ export function getRouteConfigFactoryManagementPre(server: ServerFacade): GetRou // TOC at the end of the PDF, but it's sending multiple cookies and causing our auth to fail with a 401. // Additionally, the range-request doesn't alleviate any performance issues on the server as the entire // download is loaded into memory. -export function getRouteConfigFactoryDownloadPre(server: ServerFacade): GetRouteConfigFactoryFn { - const getManagementRouteConfig = getRouteConfigFactoryManagementPre(server); +export function getRouteConfigFactoryDownloadPre( + server: ServerFacade, + logger: Logger +): GetRouteConfigFactoryFn { + const getManagementRouteConfig = getRouteConfigFactoryManagementPre(server, logger); return (): RouteConfigFactory => ({ ...getManagementRouteConfig(), tags: [API_TAG], diff --git a/x-pack/legacy/plugins/reporting/types.d.ts b/x-pack/legacy/plugins/reporting/types.d.ts index 47f384250dd537..9a43a5279c5c22 100644 --- a/x-pack/legacy/plugins/reporting/types.d.ts +++ b/x-pack/legacy/plugins/reporting/types.d.ts @@ -74,7 +74,6 @@ export type ServerFacade = LegacySetup; export type ReportingPluginSpecOptions = Legacy.PluginSpecOptions; export type EnqueueJobFn = ( - parentLogger: LevelLogger, exportTypeId: string, jobParams: JobParamsType, user: string, @@ -302,9 +301,13 @@ export interface ESQueueInstance { ) => ESQueueWorker; } -export type CreateJobFactory = (server: ServerFacade) => CreateJobFnType; +export type CreateJobFactory = ( + server: ServerFacade, + logger: LevelLogger +) => CreateJobFnType; export type ExecuteJobFactory = ( server: ServerFacade, + logger: LevelLogger, opts: { browserDriverFactory: HeadlessChromiumDriverFactory; }