[Reporting] Remove PNG V1 (#162517)

## Summary

Closes https://github.com/elastic/kibana/issues/162293 and partially
addresses [154601](https://github.com/elastic/kibana/issues/154601)

Removes the screenshot diagnostic tool but keeps the browser check
Removes PngV1ExportType from core and the export types registry

### Before
There were two steps so the EuiSteps component definitely made more
sense.

![Screenshot 2023-07-31 at 8 38 50
AM](f054f024-9148-4343-be45-9ddf175b8c71)

![Screenshot 2023-07-31 at 8 41 53
AM](71c6de8a-723c-462a-a7ad-51a4ca45f58f)


### After
I removed the use of the EuiSteps component since there's only the
browser check. Since the EuiSteps also showed some validation, I added a
callout to let users know the status of the diagnostic.

![Screenshot 2023-07-31 at 8 35 05
AM](fce09be1-ec2d-43bf-ab7d-f90df82c0579)

![Screenshot 2023-07-31 at 1 51 00
PM](3fdeb41e-5d3a-4e99-b9aa-63d2d739715f)

### Checklist

Delete any items that are not applicable to this PR.

- [x] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Rachel Shen 2023-08-02 14:30:41 -06:00 committed by GitHub
parent 787454a146
commit d8078b625d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 91 additions and 1245 deletions

1
.github/CODEOWNERS vendored
View file

@ -559,7 +559,6 @@ packages/kbn-repo-source-classifier @elastic/kibana-operations
packages/kbn-repo-source-classifier-cli @elastic/kibana-operations
packages/kbn-reporting/common @elastic/appex-sharedux
x-pack/examples/reporting_example @elastic/appex-sharedux
x-pack/plugins/reporting_export_types @elastic/appex-sharedux
x-pack/plugins/reporting @elastic/appex-sharedux
x-pack/test/plugin_functional/plugins/resolver_test @elastic/security-solution
examples/response_stream @elastic/ml-ui

View file

@ -685,10 +685,6 @@ Elastic.
|An awesome Kibana reporting plugin
|{kib-repo}blob/{branch}/x-pack/plugins/reporting_export_types/README.md[reportingExportTypes]
|This plugin is intended to be a central point for the export types of reporting to convene before hitting the reporting plugin.
|{kib-repo}blob/{branch}/x-pack/plugins/rollup/README.md[rollup]
|Welcome to the Kibana rollup plugin! This plugin provides Kibana support for Elasticsearch's rollup feature. Please refer to the Elasticsearch documentation to understand rollup indices and how to create rollup jobs.

View file

@ -562,7 +562,6 @@
"@kbn/repo-packages": "link:packages/kbn-repo-packages",
"@kbn/reporting-common": "link:packages/kbn-reporting/common",
"@kbn/reporting-example-plugin": "link:x-pack/examples/reporting_example",
"@kbn/reporting-export-types-plugin": "link:x-pack/plugins/reporting_export_types",
"@kbn/reporting-plugin": "link:x-pack/plugins/reporting",
"@kbn/resolver-test-plugin": "link:x-pack/test/plugin_functional/plugins/resolver_test",
"@kbn/response-stream-plugin": "link:examples/response_stream",

View file

@ -1112,8 +1112,6 @@
"@kbn/reporting-common/*": ["packages/kbn-reporting/common/*"],
"@kbn/reporting-example-plugin": ["x-pack/examples/reporting_example"],
"@kbn/reporting-example-plugin/*": ["x-pack/examples/reporting_example/*"],
"@kbn/reporting-export-types-plugin": ["x-pack/plugins/reporting_export_types"],
"@kbn/reporting-export-types-plugin/*": ["x-pack/plugins/reporting_export_types/*"],
"@kbn/reporting-plugin": ["x-pack/plugins/reporting"],
"@kbn/reporting-plugin/*": ["x-pack/plugins/reporting/*"],
"@kbn/resolver-test-plugin": ["x-pack/test/plugin_functional/plugins/resolver_test"],

View file

@ -6,19 +6,16 @@
*/
import { i18n } from '@kbn/i18n';
import React, { useState, Fragment } from 'react';
import React, { useState } from 'react';
import { FormattedMessage } from '@kbn/i18n-react';
import {
EuiButton,
EuiButtonEmpty,
EuiCallOut,
EuiCodeBlock,
EuiFlyout,
EuiFlyoutBody,
EuiFlyoutHeader,
EuiMarkdownFormat,
EuiSpacer,
EuiSteps,
EuiText,
EuiTitle,
} from '@elastic/eui';
@ -38,7 +35,6 @@ enum statuses {
interface State {
isFlyoutVisible: boolean;
chromeStatus: ResultStatus;
screenshotStatus: ResultStatus;
help: string[];
logs: string;
isBusy: boolean;
@ -47,7 +43,6 @@ interface State {
const initialState: State = {
[statuses.chromeStatus]: 'incomplete',
[statuses.screenshotStatus]: 'incomplete',
isFlyoutVisible: false,
help: [],
logs: '',
@ -62,7 +57,7 @@ export const ReportDiagnostic = ({ apiClient }: Props) => {
...state,
...s,
});
const { isBusy, screenshotStatus, chromeStatus, isFlyoutVisible, help, logs, success } = state;
const { isBusy, chromeStatus, isFlyoutVisible } = state;
const closeFlyout = () => setState({ ...initialState, isFlyoutVisible: false });
const showFlyout = () => setState({ isFlyoutVisible: true });
@ -94,17 +89,68 @@ export const ReportDiagnostic = ({ apiClient }: Props) => {
});
};
const steps = [
{
title: i18n.translate('xpack.reporting.listing.diagnosticBrowserTitle', {
defaultMessage: 'Check browser',
}),
children: (
<Fragment>
<FormattedMessage
id="xpack.reporting.listing.diagnosticBrowserMessage"
defaultMessage="Reporting uses a headless browser to generate PDF and PNGs. Validate that the browser can launch successfully."
/>
let flyout;
if (isFlyoutVisible) {
let outcomeCallout;
if (state.success && chromeStatus === 'complete') {
outcomeCallout = (
<EuiCallOut
id="xpack.reporting.listing.diagnosticSuccessMessage"
color="success"
title={i18n.translate('xpack.reporting.listing.diagnosticSuccessMessage', {
defaultMessage: 'Everything looks good for reporting to function.',
})}
/>
);
} else if (!state.success && chromeStatus === 'complete') {
outcomeCallout = (
<EuiCallOut
id="xpack.reporting.listing.diagnosticFailureTitle"
iconType="warning"
color="danger"
title={i18n.translate('xpack.reporting.listing.diagnosticFailureTitle', {
defaultMessage: "Something isn't working properly.",
})}
/>
);
}
flyout = (
<EuiFlyout onClose={closeFlyout} aria-labelledby="reportingHelperTitle" size="m">
<EuiFlyoutHeader hasBorder>
<EuiTitle size="m">
<h2>
<FormattedMessage
id="xpack.reporting.listing.diagnosticTitle"
defaultMessage="Screenshotting Diagnostics"
/>
</h2>
</EuiTitle>
<EuiSpacer size="s" />
<EuiText color="subdued">
<FormattedMessage
id="xpack.reporting.listing.diagnosticDescription"
defaultMessage="Run diagnostics to automatically troubleshoot common reporting problems."
/>
</EuiText>
</EuiFlyoutHeader>
<EuiFlyoutBody banner={outcomeCallout}>
<EuiTitle size="s">
<h2>
<FormattedMessage
id="xpack.reporting.listing.diagnosticBrowserTitle"
defaultMessage="Check browser"
/>
</h2>
</EuiTitle>
<EuiSpacer size="s" />
<EuiText color="subdued">
<FormattedMessage
id="xpack.reporting.listing.diagnosticBrowserMessage"
defaultMessage="Reporting uses a headless browser to generate PDF and PNGs. Validate that the browser can launch successfully."
/>
</EuiText>
<EuiSpacer />
<EuiButton
disabled={isBusy || chromeStatus === 'complete'}
@ -117,114 +163,6 @@ export const ReportDiagnostic = ({ apiClient }: Props) => {
defaultMessage="Check browser"
/>
</EuiButton>
</Fragment>
),
status: !success && chromeStatus !== 'complete' ? 'danger' : chromeStatus,
},
];
if (chromeStatus === 'complete') {
steps.push({
title: i18n.translate('xpack.reporting.listing.diagnosticScreenshotTitle', {
defaultMessage: 'Check screen capture',
}),
children: (
<Fragment>
<FormattedMessage
id="xpack.reporting.listing.diagnosticScreenshotMessage"
defaultMessage="Ensure that the headless browser can capture a screenshot of a page."
/>
<EuiSpacer />
<EuiButton
disabled={isBusy || screenshotStatus === 'complete'}
onClick={apiWrapper(() => apiClient.verifyScreenCapture(), statuses.screenshotStatus)}
isLoading={isBusy && screenshotStatus === 'incomplete'}
iconType={screenshotStatus === 'complete' ? 'check' : undefined}
>
<FormattedMessage
id="xpack.reporting.listing.diagnosticScreenshotButton"
defaultMessage="Capture screenshot"
/>
</EuiButton>
</Fragment>
),
status: !success && screenshotStatus !== 'complete' ? 'danger' : screenshotStatus,
});
}
if (screenshotStatus === 'complete') {
steps.push({
title: i18n.translate('xpack.reporting.listing.diagnosticSuccessTitle', {
defaultMessage: 'All set!',
}),
children: (
<Fragment>
<FormattedMessage
id="xpack.reporting.listing.diagnosticSuccessMessage"
defaultMessage="Everything looks good for reporting to function."
/>
</Fragment>
),
status: !success ? 'danger' : screenshotStatus,
});
}
if (!success) {
steps.push({
title: i18n.translate('xpack.reporting.listing.diagnosticFailureTitle', {
defaultMessage: "Something isn't working properly.",
}),
children: (
<Fragment>
{help.length ? (
<Fragment>
<EuiCallOut color="danger" iconType="warning">
<p>
<EuiMarkdownFormat>{help.join('\n')}</EuiMarkdownFormat>
</p>
</EuiCallOut>
</Fragment>
) : null}
{logs.length ? (
<Fragment>
<EuiSpacer />
<FormattedMessage
id="xpack.reporting.listing.diagnosticFailureDescription"
defaultMessage="Here are some details about the issue:"
/>
<EuiSpacer />
<EuiCodeBlock>{logs}</EuiCodeBlock>
</Fragment>
) : null}
</Fragment>
),
status: 'danger',
});
}
let flyout;
if (isFlyoutVisible) {
flyout = (
<EuiFlyout onClose={closeFlyout} aria-labelledby="reportingHelperTitle" size="m">
<EuiFlyoutHeader hasBorder>
<EuiTitle size="m">
<h2>
<FormattedMessage
id="xpack.reporting.listing.diagnosticTitle"
defaultMessage="Reporting Diagnostics"
/>
</h2>
</EuiTitle>
<EuiSpacer size="s" />
<EuiText color="subdued">
<FormattedMessage
id="xpack.reporting.listing.diagnosticDescription"
defaultMessage="Run diagnostics to automatically troubleshoot common reporting problems."
/>
</EuiText>
</EuiFlyoutHeader>
<EuiFlyoutBody>
<EuiSteps steps={steps} />
</EuiFlyoutBody>
</EuiFlyout>
);
@ -235,7 +173,7 @@ export const ReportDiagnostic = ({ apiClient }: Props) => {
<EuiButtonEmpty size="xs" flush="left" onClick={showFlyout}>
<FormattedMessage
id="xpack.reporting.listing.diagnosticButton"
defaultMessage="Run reporting diagnostics"
defaultMessage="Run screenshot diagnostics"
/>
</EuiButtonEmpty>
</div>

View file

@ -46,7 +46,6 @@ import { CsvSearchSourceExportType } from './export_types/csv_searchsource';
import { CsvV2ExportType } from './export_types/csv_v2';
import { PdfV1ExportType } from './export_types/printable_pdf';
import { PdfExportType } from './export_types/printable_pdf_v2';
import { PngV1ExportType } from './export_types/png';
import { PngExportType } from './export_types/png_v2';
import { checkLicense, ExportTypesRegistry } from './lib';
import { reportingEventLoggerFactory } from './lib/event_logger/logger';
@ -135,7 +134,6 @@ export class ReportingCore {
this.exportTypes.push(new PngExportType(this.core, this.config, this.logger, this.context));
// deprecated export types for tests
this.exportTypes.push(new PdfV1ExportType(this.core, this.config, this.logger, this.context));
this.exportTypes.push(new PngV1ExportType(this.core, this.config, this.logger, this.context));
this.exportTypes.forEach((et) => {
this.exportTypesRegistry.register(et);

View file

@ -6,12 +6,11 @@
*/
import { ReportingServerInfo } from '../../core';
import { TaskPayloadPNG } from '../png/types';
import { TaskPayloadPDF } from '../printable_pdf/types';
import { getFullUrls } from './get_full_urls';
import { ReportingConfigType } from '../../config';
const getMockJob = (base: object) => base as TaskPayloadPNG & TaskPayloadPDF;
const getMockJob = (base: object) => base as TaskPayloadPDF;
const mockConfig = { kibanaServer: {} } as unknown as ReportingConfigType;
const mockServerInfo: ReportingServerInfo = {
hostname: 'localhost',
@ -29,25 +28,6 @@ test(`fails if no URL is passed`, async () => {
);
});
test(`fails if URLs are file-protocols for PNGs`, async () => {
const forceNow = '2000-01-01T00:00:00.000Z';
const relativeUrl = 'file://etc/passwd/#/something';
const fn = () => getFullUrls(mockServerInfo, mockConfig, getMockJob({ relativeUrl, forceNow }));
expect(fn).toThrowErrorMatchingInlineSnapshot(
`"Found invalid URL(s), all URLs must be relative: file://etc/passwd/#/something"`
);
});
test(`fails if URLs are absolute for PNGs`, async () => {
const forceNow = '2000-01-01T00:00:00.000Z';
const relativeUrl =
'http://169.254.169.254/latest/meta-data/iam/security-credentials/profileName/#/something';
const fn = () => getFullUrls(mockServerInfo, mockConfig, getMockJob({ relativeUrl, forceNow }));
expect(fn).toThrowErrorMatchingInlineSnapshot(
`"Found invalid URL(s), all URLs must be relative: http://169.254.169.254/latest/meta-data/iam/security-credentials/profileName/#/something"`
);
});
test(`fails if URLs are file-protocols for PDF`, async () => {
const forceNow = '2000-01-01T00:00:00.000Z';
const relativeUrl = 'file://etc/passwd/#/something';
@ -95,7 +75,11 @@ test(`fails if any URLs are absolute or file's for PDF`, async () => {
test(`fails if URL does not route to a visualization`, async () => {
const fn = () =>
getFullUrls(mockServerInfo, mockConfig, getMockJob({ relativeUrl: '/app/phoney' }));
getFullUrls(
mockServerInfo,
mockConfig,
getMockJob({ objects: [{ relativeUrl: '/app/phoney' }] })
);
expect(fn).toThrowErrorMatchingInlineSnapshot(
`"No valid hash in the URL! A hash is expected for the application to route to the intended visualization."`
);
@ -106,7 +90,7 @@ test(`adds forceNow to hash's query, if it exists`, async () => {
const urls = getFullUrls(
mockServerInfo,
mockConfig,
getMockJob({ relativeUrl: '/app/kibana#/something', forceNow })
getMockJob({ objects: [{ relativeUrl: '/app/kibana#/something' }], forceNow })
);
expect(urls[0]).toEqual(
@ -120,7 +104,7 @@ test(`appends forceNow to hash's query, if it exists`, async () => {
const urls = getFullUrls(
mockServerInfo,
mockConfig,
getMockJob({ relativeUrl: '/app/kibana#/something?_g=something', forceNow })
getMockJob({ objects: [{ relativeUrl: '/app/kibana#/something?_g=something' }], forceNow })
);
expect(urls[0]).toEqual(
@ -132,7 +116,7 @@ test(`doesn't append forceNow query to url, if it doesn't exists`, async () => {
const urls = getFullUrls(
mockServerInfo,
mockConfig,
getMockJob({ relativeUrl: '/app/kibana#/something' })
getMockJob({ objects: [{ relativeUrl: '/app/kibana#/something' }] })
);
expect(urls[0]).toEqual('http://localhost:5601/sbp/app/kibana#/something');

View file

@ -13,22 +13,14 @@ import {
} from 'url';
import { ReportingConfigType } from '../../config';
import { ReportingServerInfo } from '../../core';
import { TaskPayloadPNG } from '../png/types';
import { TaskPayloadPDF } from '../printable_pdf/types';
import { getAbsoluteUrlFactory } from './get_absolute_url';
import { validateUrls } from './validate_urls';
function isPngJob(job: TaskPayloadPNG | TaskPayloadPDF): job is TaskPayloadPNG {
return (job as TaskPayloadPNG).relativeUrl !== undefined;
}
function isPdfJob(job: TaskPayloadPNG | TaskPayloadPDF): job is TaskPayloadPDF {
return (job as TaskPayloadPDF).objects !== undefined;
}
export function getFullUrls(
serverInfo: ReportingServerInfo,
config: ReportingConfigType,
job: TaskPayloadPDF | TaskPayloadPNG
job: TaskPayloadPDF
) {
const {
kibanaServer: { protocol, hostname, port },
@ -40,19 +32,15 @@ export function getFullUrls(
port: port ?? serverInfo.port,
});
// PDF and PNG job params put in the url differently
let relativeUrls: string[] = [];
if (isPngJob(job)) {
relativeUrls = [job.relativeUrl];
} else if (isPdfJob(job)) {
try {
relativeUrls = job.objects.map((obj) => obj.relativeUrl);
} else {
} catch (error) {
throw new Error(
`No valid URL fields found in Job Params! Expected \`job.relativeUrl\` or \`job.objects[{ relativeUrl }]\``
);
}
validateUrls(relativeUrls);
const urls = relativeUrls.map((relativeUrl) => {

View file

@ -1,8 +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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
export { PngV1ExportType } from './png';

View file

@ -1,120 +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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import * as Rx from 'rxjs';
import { coreMock, elasticsearchServiceMock, loggingSystemMock } from '@kbn/core/server/mocks';
import { Writable } from 'stream';
import { CancellationToken } from '@kbn/reporting-common';
import { cryptoFactory } from '../../lib';
import { createMockConfigSchema, createMockReportingCore } from '../../test_helpers';
import { generatePngObservable } from '../common';
import { TaskPayloadPNG } from './types';
import { PngV1ExportType } from './png';
import { ScreenshottingStart } from '@kbn/screenshotting-plugin/server';
jest.mock('../common/generate_png');
let content: string;
let mockPngExportType: PngV1ExportType;
let stream: jest.Mocked<Writable>;
const cancellationToken = {
on: jest.fn(),
} as unknown as CancellationToken;
const mockLogger = loggingSystemMock.createLogger();
const mockEncryptionKey = 'abcabcsecuresecret';
const encryptHeaders = async (headers: Record<string, string>) => {
const crypto = cryptoFactory(mockEncryptionKey);
return await crypto.encrypt(headers);
};
const getBasePayload = (baseObj: any) => baseObj as TaskPayloadPNG;
beforeEach(async () => {
content = '';
stream = { write: jest.fn((chunk) => (content += chunk)) } as unknown as typeof stream;
const configType = createMockConfigSchema({ encryptionKey: mockEncryptionKey });
const context = coreMock.createPluginInitializerContext(configType);
const mockCoreSetup = coreMock.createSetup();
const mockCoreStart = coreMock.createStart();
const mockReportingCore = await createMockReportingCore(createMockConfigSchema());
mockPngExportType = new PngV1ExportType(mockCoreSetup, configType, mockLogger, context);
mockPngExportType.setup({
basePath: { set: jest.fn() },
});
mockPngExportType.start({
esClient: elasticsearchServiceMock.createClusterClient(),
savedObjects: mockCoreStart.savedObjects,
uiSettings: mockCoreStart.uiSettings,
screenshotting: {} as unknown as ScreenshottingStart,
reporting: mockReportingCore.getContract(),
});
});
afterEach(() => (generatePngObservable as jest.Mock).mockReset());
test(`passes browserTimezone to generatePng`, async () => {
const encryptedHeaders = await encryptHeaders({});
(generatePngObservable as jest.Mock).mockReturnValue(Rx.of({ buffer: Buffer.from('') }));
const browserTimezone = 'UTC';
await mockPngExportType.runTask(
'pngJobId',
getBasePayload({
relativeUrl: '/app/kibana#/something',
browserTimezone,
headers: encryptedHeaders,
}),
cancellationToken,
stream
);
expect(generatePngObservable).toHaveBeenCalledWith(
expect.anything(),
expect.anything(),
expect.objectContaining({
urls: ['http://localhost:80/mock-server-basepath/app/kibana#/something'],
browserTimezone: 'UTC',
headers: {},
})
);
});
test(`returns content_type of application/png`, async () => {
const encryptedHeaders = await encryptHeaders({});
(generatePngObservable as jest.Mock).mockReturnValue(Rx.of({ buffer: Buffer.from('foo') }));
const { content_type: contentType } = await mockPngExportType.runTask(
'pngJobId',
getBasePayload({ relativeUrl: '/app/kibana#/something', headers: encryptedHeaders }),
cancellationToken,
stream
);
expect(contentType).toBe('image/png');
});
test(`returns content of generatePng`, async () => {
const testContent = 'raw string from get_screenhots';
(generatePngObservable as jest.Mock).mockReturnValue(Rx.of({ buffer: Buffer.from(testContent) }));
const encryptedHeaders = await encryptHeaders({});
await mockPngExportType.runTask(
'pngJobId',
getBasePayload({ relativeUrl: '/app/kibana#/something', headers: encryptedHeaders }),
cancellationToken,
stream
);
expect(content).toEqual(testContent);
});

View file

@ -1,122 +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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { LicenseType } from '@kbn/licensing-plugin/server';
import { CancellationToken, TaskRunResult } from '@kbn/reporting-common';
import apm from 'elastic-apm-node';
import { Writable } from 'stream';
import {
fromEventPattern,
mergeMap,
finalize,
takeUntil,
tap,
map,
Observable,
of,
lastValueFrom,
} from 'rxjs';
import { JobParamsPNGDeprecated, TaskPayloadPNG } from './types';
import { decryptJobHeaders, ExportType, generatePngObservable, getFullUrls } from '../common';
import { validateUrls } from '../common/validate_urls';
import {
LICENSE_TYPE_TRIAL,
LICENSE_TYPE_CLOUD_STANDARD,
LICENSE_TYPE_GOLD,
LICENSE_TYPE_PLATINUM,
LICENSE_TYPE_ENTERPRISE,
PNG_JOB_TYPE,
REPORTING_TRANSACTION_TYPE,
} from '../../../common/constants';
/**
* @deprecated
* Used for the Reporting Diagnostic
*/
export class PngV1ExportType extends ExportType<JobParamsPNGDeprecated, TaskPayloadPNG> {
id = 'png';
name = 'PNG';
jobType = PNG_JOB_TYPE;
jobContentEncoding? = 'base64' as const;
jobContentExtension = 'png' as const;
validLicenses: LicenseType[] = [
LICENSE_TYPE_TRIAL,
LICENSE_TYPE_CLOUD_STANDARD,
LICENSE_TYPE_GOLD,
LICENSE_TYPE_PLATINUM,
LICENSE_TYPE_ENTERPRISE,
];
constructor(...args: ConstructorParameters<typeof ExportType>) {
super(...args);
this.logger = this.logger.get('png-export-v1');
}
public createJob = async (jobParams: JobParamsPNGDeprecated) => {
validateUrls([jobParams.relativeUrl]);
return {
...jobParams,
isDeprecated: true,
forceNow: new Date().toISOString(),
};
};
public runTask = (
jobId: string,
job: TaskPayloadPNG,
cancellationToken: CancellationToken,
stream: Writable
) => {
const apmTrans = apm.startTransaction('execute-job-png', REPORTING_TRANSACTION_TYPE);
const apmGetAssets = apmTrans?.startSpan('get-assets', 'setup');
let apmGeneratePng: { end: () => void } | null | undefined;
const { encryptionKey } = this.config;
const jobLogger = this.logger.get(`execute:${jobId}`);
const process$: Observable<TaskRunResult> = of(1).pipe(
mergeMap(() => decryptJobHeaders(encryptionKey, job.headers, jobLogger)),
mergeMap((headers) => {
const [url] = getFullUrls(this.getServerInfo(), this.config, job);
apmGetAssets?.end();
apmGeneratePng = apmTrans?.startSpan('generate-png-pipeline', 'execute');
return generatePngObservable(
() =>
this.startDeps.reporting.getScreenshots({
headers,
urls: [url],
browserTimezone: job.browserTimezone,
layout: {
...job.layout,
id: 'preserve_layout',
},
}),
jobLogger,
{
headers,
urls: [url],
browserTimezone: job.browserTimezone,
layout: {
...job.layout,
id: 'preserve_layout',
},
}
);
}),
tap(({ buffer }) => stream.write(buffer)),
map(({ metrics, warnings }) => ({
content_type: 'image/png',
metrics: { png: metrics },
warnings,
})),
tap({ error: (error) => jobLogger.error(error) }),
finalize(() => apmGeneratePng?.end())
);
const stop$ = fromEventPattern(cancellationToken.on);
return lastValueFrom(process$.pipe(takeUntil(stop$)));
};
}

View file

@ -1,11 +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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
export type {
JobParamsPNGDeprecated,
TaskPayloadPNG,
} from '../../../common/types/export_types/png';

View file

@ -70,10 +70,9 @@ test(`passes browserTimezone to generatePdf`, async () => {
await mockPdfExportType.runTask(
'pdfJobId',
getBasePayload({
title: 'PDF Params Timezone Test',
relativeUrl: '/app/kibana#/something',
browserTimezone,
headers: encryptedHeaders,
objects: [{ relativeUrl: '/app/kibana#/something' }],
}),
cancellationToken,
stream

View file

@ -8,11 +8,9 @@
import type { Logger } from '@kbn/core/server';
import type { ReportingCore } from '../../../core';
import { registerDiagnoseBrowser } from './browser';
import { registerDiagnoseScreenshot } from './screenshot';
export const registerDiagnosticRoutes = (reporting: ReportingCore, logger: Logger) => {
registerDiagnoseBrowser(reporting, logger);
registerDiagnoseScreenshot(reporting, logger);
};
export interface DiagnosticResponse {

View file

@ -1,122 +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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { setupServer } from '@kbn/core-test-helpers-test-utils';
import { loggingSystemMock } from '@kbn/core/server/mocks';
import { defer } from 'rxjs';
import supertest from 'supertest';
import { ReportingCore } from '../../../..';
import { INTERNAL_ROUTES } from '../../../../../common/constants';
import { generatePngObservable } from '../../../../export_types/common';
import { reportingMock } from '../../../../mocks';
import {
createMockConfigSchema,
createMockPluginSetup,
createMockReportingCore,
} from '../../../../test_helpers';
import type { ReportingRequestHandlerContext } from '../../../../types';
import { registerDiagnoseScreenshot } from '../screenshot';
jest.mock('../../../../export_types/common/generate_png');
type SetupServerReturn = Awaited<ReturnType<typeof setupServer>>;
/**
* Tests internal diagnostic API endpoints
*/
describe('POST /diagnose/screenshot', () => {
const reportingSymbol = Symbol('reporting');
let server: SetupServerReturn['server'];
let httpSetup: SetupServerReturn['httpSetup'];
let core: ReportingCore;
const setScreenshotResponse = (resp: object | Error) => {
const generateMock = {
pipe: () =>
defer(() => (resp instanceof Error ? Promise.reject(resp) : Promise.resolve(resp))),
};
(generatePngObservable as jest.Mock).mockReturnValue(generateMock);
};
const config = createMockConfigSchema({ queue: { timeout: 120000 } });
const mockLogger = loggingSystemMock.createLogger();
beforeEach(async () => {
({ server, httpSetup } = await setupServer(reportingSymbol));
httpSetup.registerRouteHandlerContext<ReportingRequestHandlerContext, 'reporting'>(
reportingSymbol,
'reporting',
() => reportingMock.createStart()
);
core = await createMockReportingCore(
config,
createMockPluginSetup({
router: httpSetup.createRouter(''),
security: null,
})
);
});
afterEach(async () => {
await server.stop();
});
it('returns a 200 by default', async () => {
registerDiagnoseScreenshot(core, mockLogger);
setScreenshotResponse({ warnings: [] });
await server.start();
await supertest(httpSetup.server.listener)
.post(INTERNAL_ROUTES.DIAGNOSE.SCREENSHOT)
.expect(200)
.then(({ body }) => {
expect(body).toMatchInlineSnapshot(`
Object {
"help": Array [],
"logs": "",
"success": true,
}
`);
});
});
it('returns a 200 when it fails and sets success to false', async () => {
registerDiagnoseScreenshot(core, mockLogger);
setScreenshotResponse({ warnings: [`Timeout waiting for .dank to load`] });
await server.start();
await supertest(httpSetup.server.listener)
.post(INTERNAL_ROUTES.DIAGNOSE.SCREENSHOT)
.expect(200)
.then(({ body }) => {
expect(body).toMatchInlineSnapshot(`
Object {
"help": Array [],
"logs": Array [
"Timeout waiting for .dank to load",
],
"success": false,
}
`);
});
});
it('catches errors and returns a well formed response', async () => {
registerDiagnoseScreenshot(core, mockLogger);
setScreenshotResponse(new Error('Failure to start chromium!'));
await server.start();
await supertest(httpSetup.server.listener)
.post(INTERNAL_ROUTES.DIAGNOSE.SCREENSHOT)
.expect(200)
.then(({ body }) => {
expect(body.help).toContain(`We couldn't screenshot your Kibana install.`);
expect(body.logs).toContain(`Failure to start chromium!`);
});
});
});

View file

@ -1,104 +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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import type { Logger } from '@kbn/core/server';
import { APP_WRAPPER_CLASS } from '@kbn/core/server';
import { i18n } from '@kbn/i18n';
import { lastValueFrom } from 'rxjs';
import type { ReportingCore } from '../../..';
import { INTERNAL_ROUTES } from '../../../../common/constants';
import { generatePngObservable } from '../../../export_types/common';
import { getAbsoluteUrlFactory } from '../../../export_types/common/get_absolute_url';
import { authorizedUserPreRouting, getCounters } from '../../common';
const path = INTERNAL_ROUTES.DIAGNOSE.SCREENSHOT;
export const registerDiagnoseScreenshot = (reporting: ReportingCore, logger: Logger) => {
const setupDeps = reporting.getPluginSetupDeps();
const { router } = setupDeps;
router.post(
{
path,
validate: {},
options: { access: 'internal' },
},
authorizedUserPreRouting(reporting, async (_user, _context, req, res) => {
const counters = getCounters(req.route.method, path, reporting.getUsageCounter());
const { basePath, protocol, hostname, port } = reporting.getServerInfo();
const getAbsoluteUrl = getAbsoluteUrlFactory({ basePath, protocol, hostname, port });
const hashUrl = getAbsoluteUrl({ path: '/', hash: '', search: '' });
// Hack the layout to make the base/login page work
const layout = {
dimensions: {
width: 1440,
height: 2024,
},
selectors: {
screenshot: `.${APP_WRAPPER_CLASS}`,
renderComplete: `.${APP_WRAPPER_CLASS}`,
itemsCountAttribute: 'data-test-subj="kibanaChrome"',
timefilterDurationAttribute: 'data-test-subj="kibanaChrome"',
},
};
const screenshotFn = () =>
reporting.getScreenshots({
layout,
request: req,
browserTimezone: 'America/Los_Angeles',
urls: [hashUrl],
});
return lastValueFrom(
generatePngObservable(screenshotFn, logger, {
layout,
request: req,
browserTimezone: 'America/Los_Angeles',
urls: [hashUrl],
})
// Pipe is required to ensure that we can subscribe to it
.pipe()
)
.then((screenshot) => {
counters.usageCounter();
// NOTE: the screenshot could be returned as a string using `data:image/png;base64,` + results.buffer.toString('base64')
if (screenshot.warnings.length) {
return res.ok({
body: {
success: false,
help: [],
logs: screenshot.warnings,
},
});
}
return res.ok({
body: {
success: true,
help: [],
logs: '',
},
});
})
.catch((error) => {
counters.errorCounter();
return res.ok({
body: {
success: false,
help: [
i18n.translate('xpack.reporting.diagnostic.screenshotFailureMessage', {
defaultMessage: `We couldn't screenshot your Kibana install.`,
}),
],
logs: error.message,
},
});
});
})
);
};

View file

@ -2722,43 +2722,6 @@ Object {
exports[`data modeling usage data with meta.isDeprecated jobTypes 1`] = `
Object {
"PNG": Object {
"app": Object {
"canvas workpad": 0,
"dashboard": 0,
"search": 0,
"visualization": 0,
},
"available": true,
"deprecated": 0,
"error_codes": undefined,
"execution_times": undefined,
"layout": undefined,
"metrics": Object {
"png_cpu": Object {
"50.0": null,
"75.0": null,
"95.0": null,
"99.0": null,
},
"png_memory": Object {
"50.0": null,
"75.0": null,
"95.0": null,
"99.0": null,
},
},
"output_size": Object {
"1.0": null,
"25.0": null,
"5.0": null,
"50.0": null,
"75.0": null,
"95.0": null,
"99.0": null,
},
"total": 0,
},
"PNGV2": Object {
"app": Object {
"canvas workpad": 0,
@ -2862,43 +2825,6 @@ Object {
},
"enabled": true,
"last7Days": Object {
"PNG": Object {
"app": Object {
"canvas workpad": 0,
"dashboard": 0,
"search": 0,
"visualization": 0,
},
"available": true,
"deprecated": 0,
"error_codes": undefined,
"execution_times": undefined,
"layout": undefined,
"metrics": Object {
"png_cpu": Object {
"50.0": null,
"75.0": null,
"95.0": null,
"99.0": null,
},
"png_memory": Object {
"50.0": null,
"75.0": null,
"95.0": null,
"99.0": null,
},
},
"output_size": Object {
"1.0": null,
"25.0": null,
"5.0": null,
"50.0": null,
"75.0": null,
"95.0": null,
"99.0": null,
},
"total": 0,
},
"PNGV2": Object {
"app": Object {
"canvas workpad": 0,
@ -3219,43 +3145,6 @@ Object {
exports[`data modeling with empty data 1`] = `
Object {
"PNG": Object {
"app": Object {
"canvas workpad": 0,
"dashboard": 0,
"search": 0,
"visualization": 0,
},
"available": true,
"deprecated": 0,
"error_codes": undefined,
"execution_times": undefined,
"layout": undefined,
"metrics": Object {
"png_cpu": Object {
"50.0": null,
"75.0": null,
"95.0": null,
"99.0": null,
},
"png_memory": Object {
"50.0": null,
"75.0": null,
"95.0": null,
"99.0": null,
},
},
"output_size": Object {
"1.0": null,
"25.0": null,
"5.0": null,
"50.0": null,
"75.0": null,
"95.0": null,
"99.0": null,
},
"total": 0,
},
"PNGV2": Object {
"app": Object {
"canvas workpad": 0,
@ -3359,43 +3248,6 @@ Object {
},
"enabled": true,
"last7Days": Object {
"PNG": Object {
"app": Object {
"canvas workpad": 0,
"dashboard": 0,
"search": 0,
"visualization": 0,
},
"available": true,
"deprecated": 0,
"error_codes": undefined,
"execution_times": undefined,
"layout": undefined,
"metrics": Object {
"png_cpu": Object {
"50.0": null,
"75.0": null,
"95.0": null,
"99.0": null,
},
"png_memory": Object {
"50.0": null,
"75.0": null,
"95.0": null,
"99.0": null,
},
},
"output_size": Object {
"1.0": null,
"25.0": null,
"5.0": null,
"50.0": null,
"75.0": null,
"95.0": null,
"99.0": null,
},
"total": 0,
},
"PNGV2": Object {
"app": Object {
"canvas workpad": 0,
@ -3704,43 +3556,6 @@ Object {
exports[`data modeling with metrics and execution times in the data 1`] = `
Object {
"PNG": Object {
"app": Object {
"canvas workpad": 0,
"dashboard": 0,
"search": 0,
"visualization": 0,
},
"available": true,
"deprecated": 0,
"error_codes": undefined,
"execution_times": undefined,
"layout": undefined,
"metrics": Object {
"png_cpu": Object {
"50.0": null,
"75.0": null,
"95.0": null,
"99.0": null,
},
"png_memory": Object {
"50.0": null,
"75.0": null,
"95.0": null,
"99.0": null,
},
},
"output_size": Object {
"1.0": null,
"25.0": null,
"5.0": null,
"50.0": null,
"75.0": null,
"95.0": null,
"99.0": null,
},
"total": 0,
},
"PNGV2": Object {
"app": Object {
"canvas workpad": 0,
@ -3844,43 +3659,6 @@ Object {
},
"enabled": true,
"last7Days": Object {
"PNG": Object {
"app": Object {
"canvas workpad": 0,
"dashboard": 0,
"search": 0,
"visualization": 0,
},
"available": true,
"deprecated": 0,
"error_codes": undefined,
"execution_times": undefined,
"layout": undefined,
"metrics": Object {
"png_cpu": Object {
"50.0": null,
"75.0": null,
"95.0": null,
"99.0": null,
},
"png_memory": Object {
"50.0": null,
"75.0": null,
"95.0": null,
"99.0": null,
},
},
"output_size": Object {
"1.0": null,
"25.0": null,
"5.0": null,
"50.0": null,
"75.0": null,
"95.0": null,
"99.0": null,
},
"total": 0,
},
"PNGV2": Object {
"app": Object {
"canvas workpad": 0,
@ -4223,43 +4001,6 @@ Object {
exports[`data modeling with sparse data 1`] = `
Object {
"PNG": Object {
"app": Object {
"canvas workpad": 0,
"dashboard": 0,
"search": 0,
"visualization": 0,
},
"available": true,
"deprecated": 0,
"error_codes": Object {},
"execution_times": Object {},
"layout": undefined,
"metrics": Object {
"png_cpu": Object {
"50.0": null,
"75.0": null,
"95.0": null,
"99.0": null,
},
"png_memory": Object {
"50.0": null,
"75.0": null,
"95.0": null,
"99.0": null,
},
},
"output_size": Object {
"1.0": null,
"25.0": null,
"5.0": null,
"50.0": null,
"75.0": null,
"95.0": null,
"99.0": null,
},
"total": 1,
},
"PNGV2": Object {
"app": Object {
"canvas workpad": 0,
@ -4363,43 +4104,6 @@ Object {
},
"enabled": true,
"last7Days": Object {
"PNG": Object {
"app": Object {
"canvas workpad": 0,
"dashboard": 0,
"search": 0,
"visualization": 0,
},
"available": true,
"deprecated": 0,
"error_codes": Object {},
"execution_times": Object {},
"layout": undefined,
"metrics": Object {
"png_cpu": Object {
"50.0": null,
"75.0": null,
"95.0": null,
"99.0": null,
},
"png_memory": Object {
"50.0": null,
"75.0": null,
"95.0": null,
"99.0": null,
},
},
"output_size": Object {
"1.0": null,
"25.0": null,
"5.0": null,
"50.0": null,
"75.0": null,
"95.0": null,
"99.0": null,
},
"total": 1,
},
"PNGV2": Object {
"app": Object {
"canvas workpad": 0,
@ -4730,43 +4434,6 @@ Object {
exports[`data modeling with usage data from the reporting/archived_reports es archive 1`] = `
Object {
"PNG": Object {
"app": Object {
"canvas workpad": 0,
"dashboard": 0,
"search": 0,
"visualization": 0,
},
"available": true,
"deprecated": 0,
"error_codes": Object {},
"execution_times": Object {},
"layout": undefined,
"metrics": Object {
"png_cpu": Object {
"50.0": null,
"75.0": null,
"95.0": null,
"99.0": null,
},
"png_memory": Object {
"50.0": null,
"75.0": null,
"95.0": null,
"99.0": null,
},
},
"output_size": Object {
"1.0": null,
"25.0": null,
"5.0": null,
"50.0": null,
"75.0": null,
"95.0": null,
"99.0": null,
},
"total": 1,
},
"PNGV2": Object {
"app": Object {
"canvas workpad": 0,
@ -4870,43 +4537,6 @@ Object {
},
"enabled": true,
"last7Days": Object {
"PNG": Object {
"app": Object {
"canvas workpad": 0,
"dashboard": 0,
"search": 0,
"visualization": 0,
},
"available": true,
"deprecated": 0,
"error_codes": undefined,
"execution_times": undefined,
"layout": undefined,
"metrics": Object {
"png_cpu": Object {
"50.0": null,
"75.0": null,
"95.0": null,
"99.0": null,
},
"png_memory": Object {
"50.0": null,
"75.0": null,
"95.0": null,
"99.0": null,
},
},
"output_size": Object {
"1.0": null,
"25.0": null,
"5.0": null,
"50.0": null,
"75.0": null,
"95.0": null,
"99.0": null,
},
"total": 0,
},
"PNGV2": Object {
"app": Object {
"canvas workpad": 0,

View file

@ -110,35 +110,7 @@ test('Model of jobTypes', () => {
exportTypesHandler
);
expect(result.PNG).toMatchInlineSnapshot(`
Object {
"app": Object {
"canvas workpad": 0,
"dashboard": 0,
"search": 0,
"visualization": 3,
},
"available": true,
"deprecated": 0,
"error_codes": Object {},
"execution_times": undefined,
"layout": undefined,
"metrics": Object {
"png_cpu": Object {},
"png_memory": Object {},
},
"output_size": Object {
"1.0": 5093470,
"25.0": 5093470,
"5.0": 5093470,
"50.0": 8514532,
"75.0": 11935594,
"95.0": 11935594,
"99.0": 11935594,
},
"total": 3,
}
`);
expect(result.PNG).toMatchInlineSnapshot(`undefined`);
expect(result.csv_searchsource).toMatchInlineSnapshot(`
Object {
"app": Object {
@ -219,35 +191,7 @@ test('PNG counts, provided count of deprecated jobs explicitly', () => {
featureMap,
exportTypesHandler
);
expect(result.PNG).toMatchInlineSnapshot(`
Object {
"app": Object {
"canvas workpad": 0,
"dashboard": 0,
"search": 0,
"visualization": 0,
},
"available": true,
"deprecated": 5,
"error_codes": Object {},
"execution_times": undefined,
"layout": undefined,
"metrics": Object {
"png_cpu": Object {},
"png_memory": Object {},
},
"output_size": Object {
"1.0": 5093470,
"25.0": 5093470,
"5.0": 5093470,
"50.0": 8514532,
"75.0": 11935594,
"95.0": 11935594,
"99.0": 11935594,
},
"total": 15,
}
`);
expect(result.PNG).toMatchInlineSnapshot(`undefined`);
});
test('Incorporate queue times', () => {

View file

@ -1,3 +0,0 @@
# exportTypePlugin
This plugin is intended to be a central point for the export types of reporting to convene before hitting the reporting plugin.

View file

@ -1,25 +0,0 @@
{
"type": "plugin",
"id": "@kbn/reporting-export-types-plugin",
"owner": "@elastic/appex-sharedux",
"description": "Currently PDF, PNG or CSV export types for the reporting plugin",
"plugin": {
"id": "reportingExportTypes",
"server": true,
"browser": false,
"configPath": [
"xpack",
"reporting"
],
"requiredPlugins": [
"reporting"
],
"optionalPlugins": [
"security",
"spaces",
"usageCollection"
],
"requiredBundles": [
]
}
}

View file

@ -1,18 +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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { PluginInitializerContext, Logger } from '@kbn/core/server';
import { ExportTypesPlugin } from './plugin';
// This exports static code and TypeScript types,
// as well as, Kibana Platform `plugin()` initializer.
export function plugin(initializerContext: PluginInitializerContext, logger: Logger) {
return new ExportTypesPlugin(initializerContext, logger);
}
export type { ExportTypesPluginSetup, ExportTypesPluginStart } from './types';

View file

@ -1,40 +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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { PluginInitializerContext, CoreSetup, CoreStart, Plugin, Logger } from '@kbn/core/server';
import { ConfigSchema } from '@kbn/reporting-plugin/server/config';
import { ExportTypesPluginSetup, ExportTypesPluginStart } from './types';
export class ExportTypesPlugin
implements Plugin<{}, {}, ExportTypesPluginSetup, ExportTypesPluginStart>
{
exportTypes = [
// new CsvExportType(),
// new PdfExportType(),
// new PngExportType(),
];
constructor(initializerContext: PluginInitializerContext<typeof ConfigSchema>, logger: Logger) {
logger = initializerContext.logger.get();
}
public setup(core: CoreSetup, pluginsSetup: ExportTypesPluginSetup) {
const { reporting } = pluginsSetup;
this.exportTypes.forEach((eType) => {
reporting.registerExportTypes(eType);
});
return {};
}
public start(core: CoreStart, plugins: ExportTypesPluginStart) {
this.exportTypes.forEach((eType) => {});
return {};
}
public stop() {}
}

View file

@ -1,14 +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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import type { ReportingSetup, ReportingStart } from '@kbn/reporting-plugin/server/types';
export interface ExportTypesPluginSetup {
reporting: ReportingSetup;
}
export interface ExportTypesPluginStart {
reporting: ReportingStart;
}

View file

@ -1,16 +0,0 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "target/types"
},
"include": [
"common/**/*",
"server/**/*",
"../../../typings/**/*"
],
"kbn_references": [
"@kbn/core",
"@kbn/reporting-plugin",
],
"exclude": ["target/**/*"]
}

View file

@ -28617,7 +28617,6 @@
"xpack.reporting.deprecations.reportingRoleUsers.manualStepOne": "Définissez \"xpack.reporting.roles.enabled\" sur \"false\" dans le fichier kibana.yml.",
"xpack.reporting.deprecations.reportingRoleUsers.manualStepThree": "Sous Gestion > Sécurité > Rôles, créez un ou plusieurs rôles permettant d'accorder le privilège de l'application Kibana à Reporting.",
"xpack.reporting.deprecations.reportingRoleUsers.manualStepTwo": "Supprimez le paramètre \"xpack.reporting.roles.allow\" du fichier kibana.yml, le cas échéant.",
"xpack.reporting.diagnostic.screenshotFailureMessage": "Impossible d'effectuer une capture d'écran de votre installation Kibana.",
"xpack.reporting.errorHandler.unknownError": "Erreur inconnue",
"xpack.reporting.exportTypes.common.missingJobHeadersErrorMessage": "Les en-têtes de tâche sont manquants",
"xpack.reporting.jobCreatedBy.unknownUserPlaceholderText": "Inconnu",
@ -28644,13 +28643,8 @@
"xpack.reporting.listing.diagnosticBrowserTitle": "Vérifier le navigateur",
"xpack.reporting.listing.diagnosticButton": "Exécuter le diagnostic de reporting",
"xpack.reporting.listing.diagnosticDescription": "Exécutez le diagnostic pour résoudre automatiquement les problèmes courants de reporting.",
"xpack.reporting.listing.diagnosticFailureDescription": "Voici quelques détails sur le problème :",
"xpack.reporting.listing.diagnosticFailureTitle": "Quelque chose ne fonctionne pas correctement.",
"xpack.reporting.listing.diagnosticScreenshotButton": "Faire une capture d'écran",
"xpack.reporting.listing.diagnosticScreenshotMessage": "Assurez-vous que le navigateur sans affichage peut effectuer une capture d'écran d'une page.",
"xpack.reporting.listing.diagnosticScreenshotTitle": "Vérifier la capture d'écran",
"xpack.reporting.listing.diagnosticSuccessMessage": "Tout semble correct pour le bon fonctionnement du reporting.",
"xpack.reporting.listing.diagnosticSuccessTitle": "Tout est prêt !",
"xpack.reporting.listing.diagnosticTitle": "Diagnostic de reporting",
"xpack.reporting.listing.flyout.closeButtonLabel": "Fermer",
"xpack.reporting.listing.ilmPolicyCallout.migrateIndicesErrorTitle": "Impossible de migrer les index de reporting",

View file

@ -28618,7 +28618,6 @@
"xpack.reporting.deprecations.reportingRoleUsers.manualStepOne": "kibana.ymlで「xpack.reporting.roles.enabled」をfalseに設定します。",
"xpack.reporting.deprecations.reportingRoleUsers.manualStepThree": "[管理]>[セキュリティ]>ロールから、レポートのKibanaアプリケーション権限を付与する1つ以上のロールを作成します。",
"xpack.reporting.deprecations.reportingRoleUsers.manualStepTwo": "存在する場合は、kibana.ymlで「xpack.reporting.roles.allow」を削除します。",
"xpack.reporting.diagnostic.screenshotFailureMessage": "Kibanaインストールのスクリーンショットを作成できませんでした。",
"xpack.reporting.errorHandler.unknownError": "不明なエラー",
"xpack.reporting.exportTypes.common.missingJobHeadersErrorMessage": "ジョブヘッダーがありません",
"xpack.reporting.jobCreatedBy.unknownUserPlaceholderText": "不明",
@ -28645,13 +28644,8 @@
"xpack.reporting.listing.diagnosticBrowserTitle": "ブラウザーを確認",
"xpack.reporting.listing.diagnosticButton": "レポート診断を実行",
"xpack.reporting.listing.diagnosticDescription": "診断を実行し、一般的なレポートの問題を自動的にトラブルシューティングします。",
"xpack.reporting.listing.diagnosticFailureDescription": "次に、一部の問題の詳細を示します。",
"xpack.reporting.listing.diagnosticFailureTitle": "正常に動作していない項目があります。",
"xpack.reporting.listing.diagnosticScreenshotButton": "スクリーンショットを作成",
"xpack.reporting.listing.diagnosticScreenshotMessage": "ヘッドレスブラウザーがページのスクリーンショットを作成できることを確認してください。",
"xpack.reporting.listing.diagnosticScreenshotTitle": "画面キャプチャを確認",
"xpack.reporting.listing.diagnosticSuccessMessage": "すべて問題なく、レポートは機能します。",
"xpack.reporting.listing.diagnosticSuccessTitle": "準備できました。",
"xpack.reporting.listing.diagnosticTitle": "レポート診断",
"xpack.reporting.listing.flyout.closeButtonLabel": "閉じる",
"xpack.reporting.listing.ilmPolicyCallout.migrateIndicesErrorTitle": "レポートインデックスを移行できませんでした",

View file

@ -28615,7 +28615,6 @@
"xpack.reporting.deprecations.reportingRoleUsers.manualStepOne": "在 kibana.yml 中将“xpack.reporting.roles.enabled”设置为“false”。",
"xpack.reporting.deprecations.reportingRoleUsers.manualStepThree": "前往“管理”>“安全性”>“角色”以创建一个或多个针对 Reporting 授予 Kibana 应用程序权限的角色。",
"xpack.reporting.deprecations.reportingRoleUsers.manualStepTwo": "移除 kibana.yml 中的“xpack.reporting.roles.allow”如果存在。",
"xpack.reporting.diagnostic.screenshotFailureMessage": "我们无法拍摄 Kibana 安装的屏幕截图。",
"xpack.reporting.errorHandler.unknownError": "未知错误",
"xpack.reporting.exportTypes.common.missingJobHeadersErrorMessage": "作业标头缺失",
"xpack.reporting.jobCreatedBy.unknownUserPlaceholderText": "未知",
@ -28642,13 +28641,8 @@
"xpack.reporting.listing.diagnosticBrowserTitle": "检查浏览器",
"xpack.reporting.listing.diagnosticButton": "运行报告诊断",
"xpack.reporting.listing.diagnosticDescription": "运行诊断以自动解决常见报告问题。",
"xpack.reporting.listing.diagnosticFailureDescription": "下面是一些有关该问题的详细信息:",
"xpack.reporting.listing.diagnosticFailureTitle": "某些功能无法正常运行。",
"xpack.reporting.listing.diagnosticScreenshotButton": "捕获屏幕截图",
"xpack.reporting.listing.diagnosticScreenshotMessage": "确保无标头浏览器可以捕获页面的屏幕截图。",
"xpack.reporting.listing.diagnosticScreenshotTitle": "检查屏幕捕获",
"xpack.reporting.listing.diagnosticSuccessMessage": "一切都好,可以报告。",
"xpack.reporting.listing.diagnosticSuccessTitle": "准备就绪!",
"xpack.reporting.listing.diagnosticTitle": "报告诊断",
"xpack.reporting.listing.flyout.closeButtonLabel": "关闭",
"xpack.reporting.listing.ilmPolicyCallout.migrateIndicesErrorTitle": "无法迁移报告索引",

View file

@ -115,12 +115,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
"report": "[Flights] Global Flight Dashboard",
"status": "Done, warnings detected",
},
Object {
"actions": "",
"createdAt": "2021-07-19 @ 06:38 PM",
"report": "[Flights] Global Flight Dashboard",
"status": "Done, warnings detected",
},
Object {
"actions": "",
"createdAt": "2021-07-19 @ 06:38 PM",
@ -139,6 +133,12 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
"report": "[Flights] Global Flight Dashboard",
"status": "Failed",
},
Object {
"actions": "",
"createdAt": "2020-04-21 @ 07:01 PM",
"report": "[Logs] File Type Scatter Plot",
"status": "Done",
},
]
`);
});

View file

@ -155,7 +155,7 @@ export default function ({ getService }: FtrProviderContext) {
it('should complete a job of PNG export of a dashboard in non-default space', async () => {
const downloadPath = await reportingAPI.postJobJSON(
`/s/non_default_space/api/reporting/generate/png`,
`/s/non_default_space/api/reporting/generate/pngV2`,
{
jobParams: `(browserTimezone:UTC,layout:(dimensions:(height:512,width:2402),id:png),objectType:dashboard,relativeUrl:'/s/non_default_space/app/dashboards#/view/3c9ee360-e7ee-11ea-a730-d58e9ea7581b?_g=(filters:!!(),refreshInterval:(pause:!!t,value:0),time:(from:!'2019-06-10T03:17:28.800Z!',to:!'2019-07-14T19:25:06.385Z!'))&_a=(description:!'!',filters:!!(),fullScreenMode:!!f,options:(hidePanelTitles:!!f,useMargins:!!t),query:(language:kuery,query:!'!'),timeRestore:!!t,title:!'Ecom%20Dashboard%20Non%20Default%20Space!',viewMode:view)',title:'Ecom Dashboard Non Default Space')`,
}

View file

@ -8,7 +8,7 @@
import { INTERNAL_ROUTES } from '@kbn/reporting-plugin/common/constants/routes';
import { JobParamsCSV } from '@kbn/reporting-plugin/server/export_types/csv_searchsource/types';
import { JobParamsDownloadCSV } from '@kbn/reporting-plugin/server/export_types/csv_searchsource_immediate/types';
import { JobParamsPNGDeprecated } from '@kbn/reporting-plugin/server/export_types/png/types';
import { JobParamsPNGV2 } from '@kbn/reporting-plugin/server/export_types/png_v2/types';
import { JobParamsPDFDeprecated } from '@kbn/reporting-plugin/server/export_types/printable_pdf/types';
import rison from '@kbn/rison';
import { FtrProviderContext } from '../ftr_provider_context';
@ -147,10 +147,10 @@ export function createScenarios({ getService }: Pick<FtrProviderContext, 'getSer
.set('kbn-xsrf', 'xxx')
.send({ jobParams });
};
const generatePng = async (username: string, password: string, job: JobParamsPNGDeprecated) => {
const generatePng = async (username: string, password: string, job: JobParamsPNGV2) => {
const jobParams = rison.encode(job);
return await supertestWithoutAuth
.post(`/api/reporting/generate/png`)
.post(`/api/reporting/generate/pngV2`)
.auth(username, password)
.set('kbn-xsrf', 'xxx')
.send({ jobParams });

View file

@ -69,7 +69,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
await testSubjects.existOrFail('reportJobListing', { timeout: 200000 });
// post new job
const { status } = await postJobJSON(`/api/reporting/generate/png`, {
const { status } = await postJobJSON(`/api/reporting/generate/pngV2`, {
jobParams: JOB_PARAMS_ECOM_MARKDOWN,
});
expect(status).to.be(200);

View file

@ -5057,10 +5057,6 @@
version "0.0.0"
uid ""
"@kbn/reporting-export-types-plugin@link:x-pack/plugins/reporting_export_types":
version "0.0.0"
uid ""
"@kbn/reporting-plugin@link:x-pack/plugins/reporting":
version "0.0.0"
uid ""