From 58cba87ddbce03a92172ab127d72bc88d40bc422 Mon Sep 17 00:00:00 2001 From: Krzysztof Date: Fri, 18 Oct 2024 14:13:02 +0200 Subject: [PATCH 1/2] Add type to GeneratePdfResponse --- .../server/formats/pdf/pdf_maker/worker.ts | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/worker.ts b/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/worker.ts index 98c10598703ae..ba6793621c682 100644 --- a/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/worker.ts +++ b/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/worker.ts @@ -34,21 +34,23 @@ export interface GeneratePdfRequest { data: GenerateReportRequestData; } -export type GeneratePdfResponse = SuccessResponse | ErrorResponse; - -export interface SuccessResponse { - error?: undefined; - data: { - buffer: Uint8Array; - metrics: { - pages: number; - }; +export interface GeneratePdfData { + buffer: Uint8Array; + metrics: { + pages: number; }; } -export interface ErrorResponse { - error: string; - data: null; +export enum GeneratePdfResponseType { + Log, + Data, +} + +export interface GeneratePdfResponse { + type: GeneratePdfResponseType; + data?: GeneratePdfData; + error?: string; + message?: string; } if (!isMainThread) { @@ -133,7 +135,8 @@ async function execute({ data: { layout, logo, title, content } }: GeneratePdfRe pdfDoc.end(); }); - const successResponse: SuccessResponse = { + const successResponse: GeneratePdfResponse = { + type: GeneratePdfResponseType.Data, data: { buffer, metrics: { @@ -143,7 +146,10 @@ async function execute({ data: { layout, logo, title, content } }: GeneratePdfRe }; port.postMessage(successResponse, [buffer.buffer /* Transfer buffer instead of copying */]); } catch (error) { - const errorResponse: ErrorResponse = { error: error.message, data: null }; + const errorResponse: GeneratePdfResponse = { + type: GeneratePdfResponseType.Data, + error: error.message, + }; port.postMessage(errorResponse); } finally { process.nextTick(() => { From 8f0689382ba41fc7fca6021a9f308ef7eb263c01 Mon Sep 17 00:00:00 2001 From: Krzysztof Date: Mon, 21 Oct 2024 10:09:39 +0200 Subject: [PATCH 2/2] Add logging --- .../server/formats/pdf/pdf_maker/pdfmaker.ts | 35 ++++++++++--- .../server/formats/pdf/pdf_maker/worker.ts | 50 +++++++++++++++++-- 2 files changed, 74 insertions(+), 11 deletions(-) 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 2eda655509f71..65765d8fc78c8 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 @@ -22,7 +22,12 @@ import { } from './constants'; import { REPORTING_TABLE_LAYOUT } from './get_doc_options'; import { getFont } from './get_font'; -import type { GeneratePdfRequest, GeneratePdfResponse, WorkerData } from './worker'; +import { + GeneratePdfResponseType, + type GeneratePdfRequest, + type WorkerData, + GeneratePdfResponse, +} from './worker'; // Ensure that all dependencies are included in the release bundle. import './worker_dependencies'; @@ -32,6 +37,8 @@ export class PdfMaker { private content: Content[]; private worker?: Worker; + private workerLogger: Logger; + private pageCount: number = 0; private transferList: ArrayBuffer[] = []; @@ -71,6 +78,7 @@ export class PdfMaker { ) { this.title = ''; this.content = []; + this.workerLogger = logger.get('pdf-worker'); // 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. @@ -209,26 +217,37 @@ export class PdfMaker { const { port1: myPort, port2: theirPort } = new MessageChannel(); this.worker = this.createWorker(theirPort); this.worker.on('error', (workerError: NodeJS.ErrnoException) => { + this.workerLogger.error(`Worker error: ${workerError}`); if (workerError.code === 'ERR_WORKER_OUT_OF_MEMORY') { reject(new errors.PdfWorkerOutOfMemoryError(workerError.message)); } else { reject(workerError); } }); - this.worker.on('exit', () => {}); + this.worker.on('exit', () => { + this.workerLogger.debug('Worker exited'); + }); - // We expect one message from the worker generating the PDF buffer. - myPort.on('message', ({ error, data }: GeneratePdfResponse) => { - if (error) { + myPort.on('message', ({ type, error, data, message }: GeneratePdfResponse) => { + if (type === GeneratePdfResponseType.Log && message) { + this.workerLogger.debug(message); + return; + } + + if (type === GeneratePdfResponseType.Error) { reject(new Error(`PDF worker returned the following error: ${error}`)); return; } - if (!data) { + + if (type === GeneratePdfResponseType.Data && !data) { reject(new Error(`Worker did not generate a PDF!`)); return; } - this.pageCount = data.metrics.pages; - resolve(data.buffer); + + if (data) { + this.pageCount = data.metrics.pages; + resolve(data.buffer); + } }); // Send the request diff --git a/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/worker.ts b/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/worker.ts index ba6793621c682..2599a57cdac97 100644 --- a/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/worker.ts +++ b/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/worker.ts @@ -44,15 +44,34 @@ export interface GeneratePdfData { export enum GeneratePdfResponseType { Log, Data, + Error, } -export interface GeneratePdfResponse { - type: GeneratePdfResponseType; +interface GeneratePdfLogResponse { + type: GeneratePdfResponseType.Log; data?: GeneratePdfData; error?: string; message?: string; } +interface GeneratePdfDataResponse { + type: GeneratePdfResponseType.Data; + data?: GeneratePdfData; + error?: string; + message?: string; +} + +interface GeneratePdfErrorResponse { + type: GeneratePdfResponseType.Error; + data?: GeneratePdfData; + error?: string; + message?: string; +} +export type GeneratePdfResponse = + | GeneratePdfLogResponse + | GeneratePdfDataResponse + | GeneratePdfErrorResponse; + if (!isMainThread) { const { port } = workerData as WorkerData; port.on('message', execute); @@ -70,6 +89,11 @@ const getPageCount = (pdfDoc: PDFKit.PDFDocument): number => { async function execute({ data: { layout, logo, title, content } }: GeneratePdfRequest) { const { port } = workerData as WorkerData; + port.postMessage({ + type: GeneratePdfResponseType.Log, + message: 'Starting execution', + }); + try { const tableBorderWidth = 1; @@ -91,6 +115,11 @@ async function execute({ data: { layout, logo, title, content } }: GeneratePdfRe }, }; + port.postMessage({ + type: GeneratePdfResponseType.Log, + message: 'Initializing PDF printer', + }); + const printer = new Printer(fonts); const docDefinition = _.assign(getTemplate(layout, logo, title, tableBorderWidth, assetPath), { @@ -105,6 +134,11 @@ async function execute({ data: { layout, logo, title, content } }: GeneratePdfRe ), }); + port.postMessage({ + type: GeneratePdfResponseType.Log, + message: 'Generating document stream', + }); + const pdfDoc = printer.createPdfKitDocument(docDefinition, { tableLayouts: { noBorder: { @@ -123,6 +157,11 @@ async function execute({ data: { layout, logo, title, content } }: GeneratePdfRe throw new Error('Document stream has not been generated'); } + port.postMessage({ + type: GeneratePdfResponseType.Log, + message: 'Document stream has been generated', + }); + const buffer = await new Promise((resolve, reject) => { const buffers: Buffer[] = []; pdfDoc.on('error', reject); @@ -135,6 +174,11 @@ async function execute({ data: { layout, logo, title, content } }: GeneratePdfRe pdfDoc.end(); }); + port.postMessage({ + type: GeneratePdfResponseType.Log, + message: 'PDF buffer has been generated', + }); + const successResponse: GeneratePdfResponse = { type: GeneratePdfResponseType.Data, data: { @@ -147,7 +191,7 @@ async function execute({ data: { layout, logo, title, content } }: GeneratePdfRe port.postMessage(successResponse, [buffer.buffer /* Transfer buffer instead of copying */]); } catch (error) { const errorResponse: GeneratePdfResponse = { - type: GeneratePdfResponseType.Data, + type: GeneratePdfResponseType.Error, error: error.message, }; port.postMessage(errorResponse);