Skip to content

Commit

Permalink
[kbn/optimizer][ci-stats] ship metrics separate from build (#90482)
Browse files Browse the repository at this point in the history
Co-authored-by: spalger <spalger@users.noreply.github.com>
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
3 people authored Feb 8, 2021
1 parent c306a44 commit a0ce7b5
Show file tree
Hide file tree
Showing 33 changed files with 518 additions and 353 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,7 @@
"@types/webpack": "^4.41.3",
"@types/webpack-env": "^1.15.3",
"@types/webpack-merge": "^4.1.5",
"@types/webpack-sources": "^0.1.4",
"@types/write-pkg": "^3.1.0",
"@types/xml-crypto": "^1.4.1",
"@types/xml2js": "^0.4.5",
Expand Down Expand Up @@ -843,6 +844,7 @@
"webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.11.0",
"webpack-merge": "^4.2.2",
"webpack-sources": "^1.4.1",
"write-pkg": "^4.0.0",
"xml-crypto": "^2.0.0",
"xmlbuilder": "13.0.2",
Expand Down
1 change: 1 addition & 0 deletions packages/kbn-dev-utils/src/ci_stats_reporter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
*/

export * from './ci_stats_reporter';
export * from './ship_ci_stats_cli';
48 changes: 48 additions & 0 deletions packages/kbn-dev-utils/src/ci_stats_reporter/ship_ci_stats_cli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import Path from 'path';
import Fs from 'fs';

import { CiStatsReporter } from './ci_stats_reporter';
import { run, createFlagError } from '../run';

export function shipCiStatsCli() {
run(
async ({ log, flags }) => {
let metricPaths = flags.metrics;
if (typeof metricPaths === 'string') {
metricPaths = [metricPaths];
} else if (!Array.isArray(metricPaths) || !metricPaths.every((p) => typeof p === 'string')) {
throw createFlagError('expected --metrics to be a string');
}

const reporter = CiStatsReporter.fromEnv(log);
for (const path of metricPaths) {
// resolve path from CLI relative to CWD
const abs = Path.resolve(path);
const json = Fs.readFileSync(abs, 'utf8');
await reporter.metrics(JSON.parse(json));
log.success('shipped metrics from', path);
}
},
{
description: 'ship ci-stats which have been written to files',
usage: `node scripts/ship_ci_stats`,
log: {
defaultLevel: 'debug',
},
flags: {
string: ['metrics'],
help: `
--metrics [path] A path to a JSON file that includes metrics which should be sent. Multiple instances supported
`,
},
}
);
}
17 changes: 2 additions & 15 deletions packages/kbn-optimizer/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,10 @@ import Path from 'path';

import { REPO_ROOT } from '@kbn/utils';
import { lastValueFrom } from '@kbn/std';
import { run, createFlagError, CiStatsReporter } from '@kbn/dev-utils';
import { run, createFlagError } from '@kbn/dev-utils';

import { logOptimizerState } from './log_optimizer_state';
import { OptimizerConfig } from './optimizer';
import { reportOptimizerStats } from './report_optimizer_stats';
import { runOptimizer } from './run_optimizer';
import { validateLimitsForAllBundles, updateBundleLimits } from './limits';

Expand Down Expand Up @@ -120,17 +119,7 @@ run(
return;
}

let update$ = runOptimizer(config);

if (reportStats) {
const reporter = CiStatsReporter.fromEnv(log);

if (!reporter.isEnabled()) {
log.warning('Unable to initialize CiStatsReporter from env');
}

update$ = update$.pipe(reportOptimizerStats(reporter, config, log));
}
const update$ = runOptimizer(config);

await lastValueFrom(update$.pipe(logOptimizerState(log, config)));

Expand All @@ -153,7 +142,6 @@ run(
'cache',
'profile',
'inspect-workers',
'report-stats',
'validate-limits',
'update-limits',
],
Expand All @@ -179,7 +167,6 @@ run(
--dist create bundles that are suitable for inclusion in the Kibana distributable, enabled when running with --update-limits
--scan-dir add a directory to the list of directories scanned for plugins (specify as many times as necessary)
--no-inspect-workers when inspecting the parent process, don't inspect the workers
--report-stats attempt to report stats about this execution of the build to the kibana-ci-stats service using this name
--validate-limits validate the limits.yml config to ensure that there are limits defined for every bundle
--update-limits run a build and rewrite the limits file to include the current bundle sizes +5kb
`,
Expand Down
2 changes: 2 additions & 0 deletions packages/kbn-optimizer/src/common/bundle.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ it('creates cache keys', () => {
"id": "bar",
"manifestPath": undefined,
"outputDir": "/foo/bar/target",
"pageLoadAssetSizeLimit": undefined,
"publicDirNames": Array [
"public",
],
Expand Down Expand Up @@ -79,6 +80,7 @@ it('parses bundles from JSON specs', () => {
"id": "bar",
"manifestPath": undefined,
"outputDir": "/foo/bar/target",
"pageLoadAssetSizeLimit": undefined,
"publicDirNames": Array [
"public",
],
Expand Down
16 changes: 15 additions & 1 deletion packages/kbn-optimizer/src/common/bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ export interface BundleSpec {
readonly banner?: string;
/** Absolute path to a kibana.json manifest file, if omitted we assume there are not dependenices */
readonly manifestPath?: string;
/** Maximum allowed page load asset size for the bundles page load asset */
readonly pageLoadAssetSizeLimit?: number;
}

export class Bundle {
Expand Down Expand Up @@ -63,6 +65,8 @@ export class Bundle {
* Every bundle mentioned in the `requiredBundles` must be built together.
*/
public readonly manifestPath: BundleSpec['manifestPath'];
/** Maximum allowed page load asset size for the bundles page load asset */
public readonly pageLoadAssetSizeLimit: BundleSpec['pageLoadAssetSizeLimit'];

public readonly cache: BundleCache;

Expand All @@ -75,8 +79,9 @@ export class Bundle {
this.outputDir = spec.outputDir;
this.manifestPath = spec.manifestPath;
this.banner = spec.banner;
this.pageLoadAssetSizeLimit = spec.pageLoadAssetSizeLimit;

this.cache = new BundleCache(Path.resolve(this.outputDir, '.kbn-optimizer-cache'));
this.cache = new BundleCache(this.outputDir);
}

/**
Expand Down Expand Up @@ -107,6 +112,7 @@ export class Bundle {
outputDir: this.outputDir,
manifestPath: this.manifestPath,
banner: this.banner,
pageLoadAssetSizeLimit: this.pageLoadAssetSizeLimit,
};
}

Expand Down Expand Up @@ -222,6 +228,13 @@ export function parseBundles(json: string) {
}
}

const { pageLoadAssetSizeLimit } = spec;
if (pageLoadAssetSizeLimit !== undefined) {
if (!(typeof pageLoadAssetSizeLimit === 'number')) {
throw new Error('`bundles[]` must have a numeric `pageLoadAssetSizeLimit` property');
}
}

return new Bundle({
type,
id,
Expand All @@ -231,6 +244,7 @@ export function parseBundles(json: string) {
outputDir,
banner,
manifestPath,
pageLoadAssetSizeLimit,
});
}
);
Expand Down
14 changes: 7 additions & 7 deletions packages/kbn-optimizer/src/common/bundle_cache.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ beforeEach(() => {
});

it(`doesn't complain if files are not on disk`, () => {
const cache = new BundleCache('/foo/bar.json');
const cache = new BundleCache('/foo');
expect(cache.get()).toEqual({});
});

it(`updates files on disk when calling set()`, () => {
const cache = new BundleCache('/foo/bar.json');
const cache = new BundleCache('/foo');
cache.set(SOME_STATE);
expect(mockReadFileSync).not.toHaveBeenCalled();
expect(mockMkdirSync.mock.calls).toMatchInlineSnapshot(`
Expand All @@ -46,7 +46,7 @@ it(`updates files on disk when calling set()`, () => {
expect(mockWriteFileSync.mock.calls).toMatchInlineSnapshot(`
Array [
Array [
"/foo/bar.json",
"/foo/.kbn-optimizer-cache",
"{
\\"cacheKey\\": \\"abc\\",
\\"files\\": [
Expand All @@ -61,7 +61,7 @@ it(`updates files on disk when calling set()`, () => {
});

it(`serves updated state from memory`, () => {
const cache = new BundleCache('/foo/bar.json');
const cache = new BundleCache('/foo');
cache.set(SOME_STATE);
jest.clearAllMocks();

Expand All @@ -72,7 +72,7 @@ it(`serves updated state from memory`, () => {
});

it('reads state from disk on get() after refresh()', () => {
const cache = new BundleCache('/foo/bar.json');
const cache = new BundleCache('/foo');
cache.set(SOME_STATE);
cache.refresh();
jest.clearAllMocks();
Expand All @@ -83,15 +83,15 @@ it('reads state from disk on get() after refresh()', () => {
expect(mockReadFileSync.mock.calls).toMatchInlineSnapshot(`
Array [
Array [
"/foo/bar.json",
"/foo/.kbn-optimizer-cache",
"utf8",
],
]
`);
});

it('provides accessors to specific state properties', () => {
const cache = new BundleCache('/foo/bar.json');
const cache = new BundleCache('/foo');

expect(cache.getModuleCount()).toBe(undefined);
expect(cache.getReferencedFiles()).toEqual(undefined);
Expand Down
22 changes: 21 additions & 1 deletion packages/kbn-optimizer/src/common/bundle_cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
import Fs from 'fs';
import Path from 'path';

import webpack from 'webpack';
import { RawSource } from 'webpack-sources';

export interface State {
optimizerCacheKey?: unknown;
cacheKey?: unknown;
Expand All @@ -20,13 +23,17 @@ export interface State {

const DEFAULT_STATE: State = {};
const DEFAULT_STATE_JSON = JSON.stringify(DEFAULT_STATE);
const CACHE_FILENAME = '.kbn-optimizer-cache';

/**
* Helper to read and update metadata for bundles.
*/
export class BundleCache {
private state: State | undefined = undefined;
constructor(private readonly path: string | false) {}
private readonly path: string | false;
constructor(outputDir: string | false) {
this.path = outputDir === false ? false : Path.resolve(outputDir, CACHE_FILENAME);
}

refresh() {
this.state = undefined;
Expand Down Expand Up @@ -63,6 +70,7 @@ export class BundleCache {

set(updated: State) {
this.state = updated;

if (this.path) {
const directory = Path.dirname(this.path);
Fs.mkdirSync(directory, { recursive: true });
Expand Down Expand Up @@ -107,4 +115,16 @@ export class BundleCache {
}
}
}

public writeWebpackAsset(compilation: webpack.compilation.Compilation) {
if (!this.path) {
return;
}

const source = new RawSource(JSON.stringify(this.state, null, 2));

// see https://github.com/jantimon/html-webpack-plugin/blob/33d69f49e6e9787796402715d1b9cd59f80b628f/index.js#L266
// @ts-expect-error undocumented, used to add assets to the output
compilation.emitAsset(CACHE_FILENAME, source);
}
}
1 change: 0 additions & 1 deletion packages/kbn-optimizer/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,5 @@
export { OptimizerConfig } from './optimizer';
export * from './run_optimizer';
export * from './log_optimizer_state';
export * from './report_optimizer_stats';
export * from './node';
export * from './limits';

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit a0ce7b5

Please sign in to comment.