Skip to content

Commit 23f90be

Browse files
authored
Adds some new configuration options and remove browser timings (#123)
Configuration for rendering args and dumpio setting to ease investigation of problems. Removes browser timings due to possibly async issues.
1 parent 5ac51b2 commit 23f90be

File tree

12 files changed

+111
-192
lines changed

12 files changed

+111
-192
lines changed

default.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,15 @@
1919
"timezone": null,
2020
"chromeBin": null,
2121
"ignoresHttpsErrors": false,
22-
"timingMetrics": false,
2322
"mode": "default",
2423
"clustering": {
2524
"mode": "browser",
2625
"maxConcurrency": 5
2726
},
28-
"verboseLogging": false
27+
"verboseLogging": false,
28+
"dumpio": false,
29+
"args": [
30+
"--no-sandbox"
31+
]
2932
}
3033
}

dev.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,16 @@
1919
"timezone": null,
2020
"chromeBin": null,
2121
"ignoresHttpsErrors": false,
22-
"timingMetrics": false,
2322
"mode": "default",
2423
"clustering": {
2524
"mode": "browser",
2625
"maxConcurrency": 5
2726
},
28-
"verboseLogging": false
27+
"verboseLogging": false,
28+
"dumpio": true,
29+
"args": [
30+
"--no-sandbox",
31+
"--disable-setuid-sandbox"
32+
]
2933
}
3034
}

src/app.ts

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,14 @@ import * as _ from 'lodash';
44
import { GrpcPlugin } from './plugin/grpc-plugin';
55
import { HttpServer } from './service/http-server';
66
import { ConsoleLogger, PluginLogger } from './logger';
7-
import { NoOpBrowserTiming, createBrowser } from './browser';
7+
import { createBrowser } from './browser';
88
import * as minimist from 'minimist';
99
import { defaultPluginConfig, defaultServiceConfig, readJSONFileSync, PluginConfig, ServiceConfig } from './config';
10-
import { MetricsBrowserTimings } from './metrics_browser_timings';
1110

1211
async function main() {
1312
const argv = minimist(process.argv.slice(2));
1413
const env = Object.assign({}, process.env);
1514
const command = argv._[0];
16-
let timings = new NoOpBrowserTiming();
1715

1816
if (command === undefined) {
1917
const config: PluginConfig = defaultPluginConfig;
@@ -29,7 +27,7 @@ async function main() {
2927
}
3028

3129
const logger = new PluginLogger();
32-
const browser = createBrowser(config.rendering, logger, timings);
30+
const browser = createBrowser(config.rendering, logger);
3331
const plugin = new GrpcPlugin(config, logger, browser);
3432
plugin.start();
3533
} else if (command === 'server') {
@@ -47,12 +45,8 @@ async function main() {
4745

4846
populateServiceConfigFromEnv(config, env);
4947

50-
if (config.service.metrics.enabled && config.rendering.timingMetrics) {
51-
timings = new MetricsBrowserTimings();
52-
}
53-
5448
const logger = new ConsoleLogger(config.service.logging);
55-
const browser = createBrowser(config.rendering, logger, timings);
49+
const browser = createBrowser(config.rendering, logger);
5650
const server = new HttpServer(config, logger, browser);
5751

5852
await server.start();
@@ -136,4 +130,18 @@ function populateServiceConfigFromEnv(config: ServiceConfig, env: NodeJS.Process
136130
if (env['RENDERING_VERBOSE_LOGGING']) {
137131
config.rendering.verboseLogging = env['RENDERING_VERBOSE_LOGGING'] === 'true';
138132
}
133+
134+
if (env['RENDERING_DUMPIO']) {
135+
config.rendering.dumpio = env['RENDERING_DUMPIO'] === 'true';
136+
}
137+
138+
if (env['RENDERING_ARGS']) {
139+
const args = env['RENDERING_ARGS'] as string;
140+
if (args.length > 0) {
141+
const argsList = args.split(',');
142+
if (argsList.length > 0) {
143+
config.rendering.args = argsList;
144+
}
145+
}
146+
}
139147
}

src/browser/browser.ts

Lines changed: 43 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -21,43 +21,37 @@ export interface RenderResponse {
2121
filePath: string;
2222
}
2323

24-
export interface BrowserTimings {
25-
launch(callback: () => Promise<PuppeteerBrowser>): Promise<PuppeteerBrowser>;
26-
newPage(callback: () => Promise<Page>): Promise<Page>;
27-
navigate(callback: () => Promise<void>): Promise<void>;
28-
panelsRendered(callback: () => Promise<void>): Promise<void>;
29-
screenshot(callback: () => Promise<void>): Promise<void>;
30-
}
31-
32-
export class NoOpBrowserTiming {
33-
async launch(callback: () => Promise<PuppeteerBrowser>) {
34-
return await callback();
35-
}
36-
37-
async newPage(callback: () => Promise<void>) {
38-
return await callback();
39-
}
40-
41-
async navigate(callback: () => Promise<void>) {
42-
return await callback();
43-
}
44-
45-
async panelsRendered(callback: () => Promise<void>) {
46-
return await callback();
47-
}
48-
49-
async screenshot(callback: () => Promise<void>) {
50-
return await callback();
51-
}
52-
}
53-
5424
export class Browser {
55-
constructor(protected config: RenderingConfig, protected log: Logger, protected timings: BrowserTimings) {}
25+
constructor(protected config: RenderingConfig, protected log: Logger) {
26+
this.log.info(
27+
'Browser initiated',
28+
'chromeBin',
29+
this.config.chromeBin,
30+
'ignoresHttpsErrors',
31+
this.config.ignoresHttpsErrors,
32+
'timezone',
33+
this.config.timezone,
34+
'args',
35+
this.config.args,
36+
'dumpio',
37+
this.config.dumpio,
38+
'verboseLogging',
39+
this.config.verboseLogging
40+
);
41+
}
5642

5743
async getBrowserVersion(): Promise<string> {
58-
const launcherOptions = this.getLauncherOptions({});
59-
const browser = await puppeteer.launch(launcherOptions);
60-
return browser.version();
44+
let browser;
45+
46+
try {
47+
const launcherOptions = this.getLauncherOptions({});
48+
browser = await puppeteer.launch(launcherOptions);
49+
return await browser.version();
50+
} finally {
51+
if (browser) {
52+
await browser.close();
53+
}
54+
}
6155
}
6256

6357
async start(): Promise<void> {}
@@ -84,7 +78,8 @@ export class Browser {
8478
const launcherOptions: any = {
8579
env: env,
8680
ignoreHTTPSErrors: this.config.ignoresHttpsErrors,
87-
args: ['--no-sandbox'],
81+
dumpio: this.config.dumpio,
82+
args: this.config.args,
8883
};
8984

9085
if (this.config.chromeBin) {
@@ -101,18 +96,8 @@ export class Browser {
10196
try {
10297
this.validateOptions(options);
10398
const launcherOptions = this.getLauncherOptions(options);
104-
105-
browser = await this.timings.launch(
106-
async () =>
107-
// launch browser
108-
await puppeteer.launch(launcherOptions)
109-
);
110-
page = await this.timings.newPage(
111-
async () =>
112-
// open a new page
113-
await browser.newPage()
114-
);
115-
99+
browser = await puppeteer.launch(launcherOptions);
100+
page = await browser.newPage();
116101
this.addPageListeners(page);
117102

118103
return await this.takeScreenshot(page, options);
@@ -139,32 +124,22 @@ export class Browser {
139124
domain: options.domain,
140125
});
141126
await page.mouse.move(options.width, options.height);
142-
143-
await this.timings.navigate(async () => {
144-
// wait until all data was loaded
145-
await page.goto(options.url, { waitUntil: 'networkidle0' });
146-
});
147-
148-
await this.timings.panelsRendered(async () => {
149-
// wait for all panels to render
150-
await page.waitForFunction(
151-
() => {
152-
const panelCount = document.querySelectorAll('.panel').length || document.querySelectorAll('.panel-container').length;
153-
return (window as any).panelsRendered >= panelCount;
154-
},
155-
{
156-
timeout: options.timeout * 1000,
157-
}
158-
);
159-
});
127+
await page.goto(options.url, { waitUntil: 'networkidle0' });
128+
await page.waitForFunction(
129+
() => {
130+
const panelCount = document.querySelectorAll('.panel').length || document.querySelectorAll('.panel-container').length;
131+
return (window as any).panelsRendered >= panelCount;
132+
},
133+
{
134+
timeout: options.timeout * 1000,
135+
}
136+
);
160137

161138
if (!options.filePath) {
162139
options.filePath = uniqueFilename(os.tmpdir()) + '.png';
163140
}
164141

165-
await this.timings.screenshot(async () => {
166-
await page.screenshot({ path: options.filePath });
167-
});
142+
await page.screenshot({ path: options.filePath });
168143

169144
return { filePath: options.filePath };
170145
}

src/browser/clustered.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Cluster } from 'puppeteer-cluster';
2-
import { Browser, RenderResponse, BrowserTimings, RenderOptions } from './browser';
2+
import { Browser, RenderResponse, RenderOptions } from './browser';
33
import { Logger } from '../logger';
44
import { RenderingConfig, ClusteringConfig } from '../config';
55

@@ -8,8 +8,8 @@ export class ClusteredBrowser extends Browser {
88
clusteringConfig: ClusteringConfig;
99
concurrency: number;
1010

11-
constructor(config: RenderingConfig, log: Logger, timings: BrowserTimings) {
12-
super(config, log, timings);
11+
constructor(config: RenderingConfig, log: Logger) {
12+
super(config, log);
1313

1414
this.clusteringConfig = config.clustering;
1515
this.concurrency = Cluster.CONCURRENCY_BROWSER;

src/browser/index.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
import { RenderingConfig } from '../config';
22
import { Logger } from '../logger';
3-
import { Browser, BrowserTimings, NoOpBrowserTiming } from './browser';
3+
import { Browser } from './browser';
44
import { ClusteredBrowser } from './clustered';
55
import { ReusableBrowser } from './reusable';
66

7-
export function createBrowser(config: RenderingConfig, log: Logger, timings: BrowserTimings): Browser {
7+
export function createBrowser(config: RenderingConfig, log: Logger): Browser {
88
if (config.mode === 'clustered') {
99
log.info('using clustered browser', 'mode', config.clustering.mode, 'maxConcurrency', config.clustering.maxConcurrency);
10-
return new ClusteredBrowser(config, log, timings);
10+
return new ClusteredBrowser(config, log);
1111
}
1212

1313
if (config.mode === 'reusable') {
1414
log.info('using reusable browser');
15-
return new ReusableBrowser(config, log, timings);
15+
return new ReusableBrowser(config, log);
1616
}
1717

18-
return new Browser(config, log, timings);
18+
return new Browser(config, log);
1919
}
2020

21-
export { Browser, NoOpBrowserTiming };
21+
export { Browser };

src/browser/reusable.ts

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,18 @@
11
import * as puppeteer from 'puppeteer';
2-
import { Browser, RenderResponse, BrowserTimings, RenderOptions } from './browser';
2+
import { Browser, RenderResponse, RenderOptions } from './browser';
33
import { Logger } from '../logger';
44
import { RenderingConfig } from '../config';
55

66
export class ReusableBrowser extends Browser {
77
browser: puppeteer.Browser;
88

9-
constructor(config: RenderingConfig, log: Logger, timings: BrowserTimings) {
10-
super(config, log, timings);
9+
constructor(config: RenderingConfig, log: Logger) {
10+
super(config, log);
1111
}
1212

1313
async start(): Promise<void> {
1414
const launcherOptions = this.getLauncherOptions({});
15-
16-
this.browser = await this.timings.launch(
17-
async () =>
18-
// launch browser
19-
await puppeteer.launch(launcherOptions)
20-
);
15+
this.browser = await puppeteer.launch(launcherOptions);
2116
}
2217

2318
async render(options: RenderOptions): Promise<RenderResponse> {
@@ -27,12 +22,7 @@ export class ReusableBrowser extends Browser {
2722
try {
2823
this.validateOptions(options);
2924
context = await this.browser.createIncognitoBrowserContext();
30-
31-
page = await this.timings.newPage(
32-
async () =>
33-
// open a new page
34-
await context.newPage()
35-
);
25+
page = await context.newPage();
3626

3727
if (options.timezone) {
3828
// set timezone

src/config.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ export interface RenderingConfig {
99
timezone?: string;
1010
chromeBin?: string;
1111
ignoresHttpsErrors: boolean;
12-
timingMetrics: boolean;
1312
mode: string;
1413
clustering: ClusteringConfig;
1514
verboseLogging: boolean;
15+
dumpio: boolean;
16+
args: string[];
1617
}
1718

1819
export interface MetricsConfig {
@@ -56,13 +57,14 @@ const defaultRenderingConfig: RenderingConfig = {
5657
timezone: undefined,
5758
chromeBin: undefined,
5859
ignoresHttpsErrors: false,
59-
timingMetrics: false,
6060
mode: 'default',
6161
clustering: {
6262
mode: 'browser',
6363
maxConcurrency: 5,
6464
},
6565
verboseLogging: false,
66+
dumpio: false,
67+
args: ['--no-sandbox'],
6668
};
6769

6870
export const defaultServiceConfig: ServiceConfig = {

0 commit comments

Comments
 (0)