Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Png output no rxjs #24098

Closed
wants to merge 11 commits into from
7 changes: 6 additions & 1 deletion x-pack/plugins/reporting/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ export const JOB_COMPLETION_NOTIFICATIONS_SESSION_KEY =

export const API_BASE_URL = '/api/reporting';

export const WHITELISTED_JOB_CONTENT_TYPES = ['application/json', 'application/pdf', 'text/csv'];
export const WHITELISTED_JOB_CONTENT_TYPES = [
'application/json',
'application/pdf',
'text/csv',
'image/png',
];

export const UI_SETTINGS_CUSTOM_PDF_LOGO = 'xpackReporting:customPdfLogo';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

import url from 'url';
import { oncePerServer } from '../../../../server/lib/once_per_server';
import { oncePerServer } from '../../../server/lib/once_per_server';

function getAbsoluteUrlFn(server) {
const config = server.config();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { KbnServer, Size } from '../../../../../types';
import { LayoutTypes } from '../../../common/constants';
import { KbnServer, Size } from '../../../types';
import { LayoutTypes } from '../constants';
import { Layout } from './layout';
import { PreserveLayout } from './preserve_layout';
import { PrintLayout } from './print_layout';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { Size, ViewZoomWidthHeight } from '../../../../../types';
import { Size, ViewZoomWidthHeight } from '../../../types';

export interface PageSizeParams {
pageMarginTop: number;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/
import path from 'path';
import { Size } from '../../../../../types';
import { LayoutTypes } from '../../../common/constants';
import { Size } from '../../../types';
import { LayoutTypes } from '../constants';
import { Layout, PageSizeParams } from './layout';

// We use a zoom of two to bump up the resolution of the screenshot a bit.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/
import path from 'path';
import { EvaluateOptions, KbnServer, Size } from '../../../../../types';
import { LayoutTypes } from '../../../common/constants';
import { EvaluateOptions, KbnServer, Size } from '../../../types';
import { LayoutTypes } from '../constants';
import { Layout } from './layout';
import { CaptureConfig } from './types';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { Size } from '../../../../../types';
import { Size } from '../../../types';

export interface CaptureConfig {
zoom: number;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
* you may not use this file except in compliance with the Elastic License.
*/

import * as Rx from 'rxjs';
import { first, tap, mergeMap } from 'rxjs/operators';
//import * as Rx from 'rxjs';
//import { first, tap, mergeMap } from 'rxjs/operators';
import fs from 'fs';
import getPort from 'get-port';
import { promisify } from 'bluebird';
import { LevelLogger } from '../../../../server/lib/level_logger';
import { LevelLogger } from '../../../server/lib/level_logger';

const fsp = {
readFile: promisify(fs.readFile, fs)
Expand Down Expand Up @@ -206,6 +206,7 @@ export function screenshotsObservableFactory(server) {
args: [layout.selectors.screenshot, { title: 'data-title', description: 'data-description' }],
returnByValue: true,
});

return elementsPositionAndAttributes;
};

Expand All @@ -223,97 +224,66 @@ export function screenshotsObservableFactory(server) {
return screenshots;
};

return function screenshotsObservable(url, headers, layout, browserTimezone) {

return Rx.defer(async () => await getPort()).pipe(
mergeMap(bridgePort => {
logger.debug(`Creating browser driver factory`);
return browserDriverFactory.create({
bridgePort,
viewport: layout.getBrowserViewport(),
zoom: layout.getBrowserZoom(),
logger,
browserTimezone,
});
}),
tap(() => logger.debug('Driver factory created')),
mergeMap(({ driver$, exit$, message$, consoleMessage$ }) => {

message$.subscribe(line => {
logger.debug(line, ['browser']);
});

consoleMessage$.subscribe(line => {
logger.debug(line, ['browserConsole']);
});


const screenshot$ = driver$.pipe(
tap(() => logger.debug(`opening ${url}`)),
mergeMap(
browser => openUrl(browser, url, headers),
browser => browser
),
tap(() => logger.debug('injecting custom css')),
mergeMap(
browser => injectCustomCss(browser, layout),
browser => browser
),
tap(() => logger.debug('waiting for elements or items count attribute; or not found to interrupt')),
mergeMap(
browser => Rx.race(
Rx.from(waitForElementOrItemsCountAttribute(browser, layout)),
Rx.from(waitForNotFoundError(browser))
),
browser => browser
),
tap(() => logger.debug('determining how many items we have')),
mergeMap(
browser => getNumberOfItems(browser, layout),
(browser, itemsCount) => ({ browser, itemsCount })
),
tap(() => logger.debug('setting viewport')),
mergeMap(
({ browser, itemsCount }) => setViewport(browser, itemsCount, layout),
({ browser, itemsCount }) => ({ browser, itemsCount }),
),
tap(({ itemsCount }) => logger.debug(`waiting for ${itemsCount} to be in the DOM`)),
mergeMap(
({ browser, itemsCount }) => waitForElementsToBeInDOM(browser, itemsCount, layout),
({ browser, itemsCount }) => ({ browser, itemsCount })
),
tap(() => logger.debug('positioning elements')),
mergeMap(
({ browser }) => positionElements(browser, layout),
({ browser }) => browser
),
tap(() => logger.debug('waiting for rendering to complete')),
mergeMap(
browser => waitForRenderComplete(browser, layout),
browser => browser
),
tap(() => logger.debug('rendering is complete')),
mergeMap(
browser => getTimeRange(browser, layout),
(browser, timeRange) => ({ browser, timeRange })
),
tap(({ timeRange }) => logger.debug(timeRange ? `timeRange from ${timeRange.from} to ${timeRange.to}` : 'no timeRange')),
mergeMap(
({ browser }) => getElementPositionAndAttributes(browser, layout),
({ browser, timeRange }, elementsPositionAndAttributes) => {
return { browser, timeRange, elementsPositionAndAttributes };
}
),
tap(() => logger.debug(`taking screenshots`)),
mergeMap(
({ browser, elementsPositionAndAttributes }) => getScreenshots({ browser, elementsPositionAndAttributes }),
({ timeRange }, screenshots) => ({ timeRange, screenshots })
)
);

return Rx.race(screenshot$, exit$);
}),
first()
);
return async function screenshotsObservable(url, headers, layout, browserTimezone, cancellationToken) {

const bridgePort = await getPort();

logger.debug(`Creating browser driver factory`);

const { browser, chromium } = await browserDriverFactory.create({
bridgePort,
viewport: layout.getBrowserViewport(),
zoom: layout.getBrowserZoom(),
logger,
browserTimezone
});

if (cancellationToken) {
cancellationToken.on(() => {
logger.debug(`Closing Chromium due to cancellation`);
chromium.close();
});
}

logger.debug('Driver factory created');

logger.debug(`opening ${url}`);
await openUrl(browser, url, headers);

logger.debug('injecting custom css');
await injectCustomCss(browser, layout);

logger.debug('waiting for elements or items count attribute; or not found to interrupt');
Promise.race([waitForElementOrItemsCountAttribute(browser, layout), waitForNotFoundError(browser)])
.then(function () {
});

logger.debug('determining how many items we have');
const itemsCount = await getNumberOfItems(browser, layout);

logger.debug('setting viewport');
await setViewport(browser, itemsCount, layout);

logger.debug(`waiting for ${itemsCount} to be in the DOM`);
await waitForElementsToBeInDOM(browser, itemsCount, layout);

logger.debug('positioning elements');
await positionElements(browser, layout);

logger.debug('waiting for rendering to complete');
await waitForRenderComplete(browser, layout);

logger.debug('rendering is complete');
const timeRange = await getTimeRange(browser, layout);

logger.debug(timeRange ? `timeRange from ${timeRange.from} to ${timeRange.to}` : 'no timeRange');
const elementsPositionAndAttributes = await getElementPositionAndAttributes(browser, layout);

logger.debug(`taking screenshots`);
const screenshots = await getScreenshots({ browser, elementsPositionAndAttributes });

await chromium.close();

return screenshots;
};
}
10 changes: 10 additions & 0 deletions x-pack/plugins/reporting/export_types/png/metadata.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* 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.
*/

export const metadata = {
id: 'png',
name: 'PNG'
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* 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 { cryptoFactory } from '../../../../server/lib/crypto';
import { oncePerServer } from '../../../../server/lib/once_per_server';

function createJobFn(server) {
const crypto = cryptoFactory(server);

return async function createJob({
objectType,
title,
relativeUrl,
browserTimezone,
layout
}, headers) {
const serializedEncryptedHeaders = await crypto.encrypt(headers);

return {
title: title,
type: objectType,
relativeUrl,
headers: serializedEncryptedHeaders,
browserTimezone,
layout,
forceNow: new Date().toISOString(),
};
};
}

export const createJobFactory = oncePerServer(createJobFn);
Loading