diff --git a/x-pack/plugins/screenshotting/server/formats/pdf/index.ts b/x-pack/plugins/screenshotting/server/formats/pdf/index.ts index 7364ec210313a..b7718155c5424 100644 --- a/x-pack/plugins/screenshotting/server/formats/pdf/index.ts +++ b/x-pack/plugins/screenshotting/server/formats/pdf/index.ts @@ -7,7 +7,7 @@ import { groupBy } from 'lodash'; import type { Values } from '@kbn/utility-types'; -import type { Logger } from 'src/core/server'; +import type { Logger, PackageInfo } from 'src/core/server'; import type { LayoutParams } from '../../../common'; import { LayoutTypes } from '../../../common'; import type { Layout } from '../../layouts'; @@ -93,6 +93,7 @@ function getTimeRange(results: CaptureResult['results']) { export async function toPdf( logger: Logger, + packageInfo: PackageInfo, layout: Layout, { logo, title }: PdfScreenshotOptions, { metrics, results }: CaptureResult @@ -104,6 +105,7 @@ export async function toPdf( results, layout, logo, + packageInfo, logger, }); diff --git a/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/index.ts b/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/index.ts index ce5ea3cab813c..2c5439267ffc4 100644 --- a/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/index.ts +++ b/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { Logger } from 'src/core/server'; +import type { Logger, PackageInfo } from 'src/core/server'; import { PdfMaker } from './pdfmaker'; import type { Layout } from '../../../layouts'; import { getTracker } from './tracker'; @@ -14,6 +14,7 @@ import type { CaptureResult } from '../../../screenshots'; interface PngsToPdfArgs { results: CaptureResult['results']; layout: Layout; + packageInfo: PackageInfo; logger: Logger; logo?: string; title?: string; @@ -24,9 +25,10 @@ export async function pngsToPdf({ layout, logo, title, + packageInfo, logger, }: PngsToPdfArgs): Promise<{ buffer: Buffer; pages: number }> { - const pdfMaker = new PdfMaker(layout, logo, logger); + const pdfMaker = new PdfMaker(layout, logo, packageInfo, logger); const tracker = getTracker(); if (title) { pdfMaker.setTitle(title); diff --git a/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/integration_tests/pdfmaker.test.ts b/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/integration_tests/pdfmaker.test.ts index d3c9f2003dd4e..e08cf808abbc5 100644 --- a/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/integration_tests/pdfmaker.test.ts +++ b/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/integration_tests/pdfmaker.test.ts @@ -7,11 +7,12 @@ /* eslint-disable max-classes-per-file */ +import { PackageInfo } from 'kibana/server'; import path from 'path'; import { loggingSystemMock } from 'src/core/server/mocks'; import { isUint8Array } from 'util/types'; -import { createMockLayout } from '../../../../layouts/mock'; import { errors } from '../../../../../common'; +import { createMockLayout } from '../../../../layouts/mock'; import { PdfMaker } from '../pdfmaker'; const imageBase64 = Buffer.from( @@ -23,11 +24,19 @@ describe('PdfMaker', () => { let layout: ReturnType; let pdf: PdfMaker; let logger: ReturnType; + let packageInfo: Readonly; beforeEach(() => { layout = createMockLayout(); logger = loggingSystemMock.createLogger(); - pdf = new PdfMaker(layout, undefined, logger); + packageInfo = { + branch: 'screenshot-test', + buildNum: 567891011, + buildSha: 'screenshot-dfdfed0a', + dist: false, + version: '1000.0.0', + }; + pdf = new PdfMaker(layout, undefined, packageInfo, logger); }); describe('generate', () => { @@ -56,14 +65,14 @@ describe('PdfMaker', () => { protected workerMaxOldHeapSizeMb = 2; protected workerMaxYoungHeapSizeMb = 2; protected workerModulePath = path.resolve(__dirname, './memory_leak_worker.js'); - })(layout, undefined, logger); + })(layout, undefined, packageInfo, logger); await expect(leakyMaker.generate()).rejects.toBeInstanceOf(errors.PdfWorkerOutOfMemoryError); }); it('restarts the PDF worker if it crashes', async () => { const buggyMaker = new (class BuggyPdfMaker extends PdfMaker { protected workerModulePath = path.resolve(__dirname, './buggy_worker.js'); - })(layout, undefined, logger); + })(layout, undefined, packageInfo, logger); await expect(buggyMaker.generate()).rejects.toThrowError(new Error('This is a bug')); await expect(buggyMaker.generate()).rejects.toThrowError(new Error('This is a bug')); diff --git a/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/pdfmaker.ts b/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/pdfmaker.ts index f32bec1e3ed38..a10f259e5c9e5 100644 --- a/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/pdfmaker.ts +++ b/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/pdfmaker.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { Logger } from 'src/core/server'; +import type { Logger, PackageInfo } from 'src/core/server'; import { SerializableRecord } from '@kbn/utility-types'; import path from 'path'; import { Content, ContentImage, ContentText } from 'pdfmake/interfaces'; @@ -34,7 +34,7 @@ export class PdfMaker { private worker?: Worker; private pageCount: number = 0; - protected workerModulePath = path.resolve(__dirname, './worker.js'); + protected workerModulePath: string; /** * The maximum heap size for old memory region of the worker thread. @@ -65,10 +65,18 @@ export class PdfMaker { constructor( private readonly layout: Layout, private readonly logo: string | undefined, + { dist }: PackageInfo, private readonly logger: Logger ) { this.title = ''; this.content = []; + + // running in dist: `worker.ts` becomes `worker.js` + // running in source: `worker_src_harness.ts` needs to be wrapped in JS and have a ts-node environment initialized. + this.workerModulePath = path.resolve( + __dirname, + dist ? './worker.js' : './worker_src_harness.js' + ); } _addContents(contents: Content[]) { diff --git a/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/worker.js b/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/worker_src_harness.js similarity index 64% rename from x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/worker.js rename to x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/worker_src_harness.js index d3dfa3e9accf8..e180c130bc4af 100644 --- a/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/worker.js +++ b/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/worker_src_harness.js @@ -5,5 +5,10 @@ * 2.0. */ +/** + * This file is the harness for importing worker.ts with Kibana running in dev mode. + * The TS file needs to be compiled on the fly, unlike when Kibana is running as a dist. + */ + require('../../../../../../../src/setup_node_env'); require('./worker.ts'); diff --git a/x-pack/plugins/screenshotting/server/plugin.ts b/x-pack/plugins/screenshotting/server/plugin.ts index 3f97de22d5e4b..2f675335d4393 100755 --- a/x-pack/plugins/screenshotting/server/plugin.ts +++ b/x-pack/plugins/screenshotting/server/plugin.ts @@ -11,6 +11,7 @@ import type { CoreSetup, CoreStart, Logger, + PackageInfo, Plugin, PluginInitializerContext, } from 'src/core/server'; @@ -45,6 +46,7 @@ export interface ScreenshottingStart { export class ScreenshottingPlugin implements Plugin { private config: ConfigType; private logger: Logger; + private packageInfo: PackageInfo; private screenshotMode!: ScreenshotModePluginSetup; private browserDriverFactory!: Promise; private screenshots!: Promise; @@ -52,6 +54,7 @@ export class ScreenshottingPlugin implements Plugin) { this.logger = context.logger.get(); this.config = context.config.get(); + this.packageInfo = context.env.packageInfo; } setup({ http }: CoreSetup, { screenshotMode }: SetupDeps) { @@ -82,7 +85,7 @@ export class ScreenshottingPlugin implements Plugin {}); diff --git a/x-pack/plugins/screenshotting/server/screenshots/index.test.ts b/x-pack/plugins/screenshotting/server/screenshots/index.test.ts index 84a0974b0f8bc..eef98ceea34ba 100644 --- a/x-pack/plugins/screenshotting/server/screenshots/index.test.ts +++ b/x-pack/plugins/screenshotting/server/screenshots/index.test.ts @@ -6,7 +6,7 @@ */ import { of, throwError } from 'rxjs'; -import type { Logger } from 'src/core/server'; +import type { Logger, PackageInfo } from 'src/core/server'; import { httpServiceMock } from 'src/core/server/mocks'; import { SCREENSHOTTING_APP_ID, @@ -31,6 +31,7 @@ describe('Screenshot Observable Pipeline', () => { let http: ReturnType; let layout: ReturnType; let logger: jest.Mocked; + let packageInfo: Readonly; let options: ScreenshotOptions; let screenshots: Screenshots; @@ -44,6 +45,13 @@ describe('Screenshot Observable Pipeline', () => { error: jest.fn(), info: jest.fn(), } as unknown as jest.Mocked; + packageInfo = { + branch: 'screenshot-test', + buildNum: 567891011, + buildSha: 'screenshot-dfdfed0a', + dist: false, + version: '5000.0.0', + }; options = { browserTimezone: 'UTC', headers: {}, @@ -56,7 +64,9 @@ describe('Screenshot Observable Pipeline', () => { }, urls: ['/welcome/home/start/index.htm'], } as unknown as typeof options; - screenshots = new Screenshots(driverFactory, logger, http, { poolSize: 1 } as ConfigType); + screenshots = new Screenshots(driverFactory, logger, packageInfo, http, { + poolSize: 1, + } as ConfigType); jest.spyOn(Layouts, 'createLayout').mockReturnValue(layout); diff --git a/x-pack/plugins/screenshotting/server/screenshots/index.ts b/x-pack/plugins/screenshotting/server/screenshots/index.ts index 8672babe8b514..cfd5c76093d3b 100644 --- a/x-pack/plugins/screenshotting/server/screenshots/index.ts +++ b/x-pack/plugins/screenshotting/server/screenshots/index.ts @@ -22,7 +22,7 @@ import { tap, toArray, } from 'rxjs/operators'; -import type { HttpServiceSetup, KibanaRequest, Logger } from 'src/core/server'; +import type { HttpServiceSetup, KibanaRequest, Logger, PackageInfo } from 'src/core/server'; import type { ExpressionAstExpression } from 'src/plugins/expressions/common'; import { LayoutParams, @@ -99,6 +99,7 @@ export class Screenshots { constructor( private readonly browserDriverFactory: HeadlessChromiumDriverFactory, private readonly logger: Logger, + private readonly packageInfo: PackageInfo, private readonly http: HttpServiceSetup, { poolSize }: ConfigType ) { @@ -214,7 +215,7 @@ export class Screenshots { mergeMap((result) => { switch (options.format) { case 'pdf': - return toPdf(this.logger, layout, options, result); + return toPdf(this.logger, this.packageInfo, layout, options, result); default: return toPng(result); }