Skip to content

Commit ceed5fb

Browse files
authored
feat: log individual download times during parsing (#1767)
1 parent 82b079d commit ceed5fb

2 files changed

Lines changed: 20 additions & 8 deletions

File tree

src/parser-includes.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import chalk from "chalk-template";
88
import {Parser} from "./parser.js";
99
import axios from "axios";
1010
import path from "path";
11+
import prettyHrtime from "pretty-hrtime";
1112
import semver from "semver";
1213
import {RE2JS} from "re2js";
1314

@@ -61,7 +62,7 @@ export class ParserIncludes {
6162
);
6263
let includeDatas: any[] = [];
6364
const promises = [];
64-
const {stateDir, cwd, fetchIncludes, gitData, expandVariables} = opts;
65+
const {stateDir, cwd, fetchIncludes, gitData, expandVariables, writeStreams} = opts;
6566
// cache the parsed component, because parseIncludeComponent is expensive and we would call it twice otherwise
6667
const componentParseCache = new Map<number, ParsedComponent>();
6768

@@ -79,20 +80,20 @@ export class ParserIncludes {
7980
}
8081
if (value["file"]) {
8182
for (const fileValue of Array.isArray(value["file"]) ? value["file"] : [value["file"]]) {
82-
promises.push(this.downloadIncludeProjectFile(cwd, stateDir, value["project"], value["ref"] || "HEAD", fileValue, gitData, fetchIncludes));
83+
promises.push(this.downloadIncludeProjectFile(opts, value["project"], value["ref"] || "HEAD", fileValue));
8384
}
8485
} else if (value["template"]) {
8586
const {project, ref, file, domain} = this.covertTemplateToProjectFile(value["template"]);
8687
const url = `https://${domain}/${project}/-/raw/${ref}/${file}`;
87-
promises.push(this.downloadIncludeRemote(cwd, stateDir, url, fetchIncludes));
88+
promises.push(this.downloadIncludeRemote(cwd, stateDir, url, fetchIncludes, writeStreams));
8889
} else if (value["remote"]) {
89-
promises.push(this.downloadIncludeRemote(cwd, stateDir, value["remote"], fetchIncludes));
90+
promises.push(this.downloadIncludeRemote(cwd, stateDir, value["remote"], fetchIncludes, writeStreams));
9091
} else if (value["component"]) {
9192
const component = this.parseIncludeComponent(value["component"], gitData);
9293
componentParseCache.set(index, component);
9394
if (!component.isLocal)
9495
{
95-
promises.push(this.downloadIncludeComponent(cwd, stateDir, component.projectPath, component.ref, component.name, gitData, fetchIncludes));
96+
promises.push(this.downloadIncludeComponent(opts, component.projectPath, component.ref, component.name));
9697
}
9798
}
9899

@@ -281,28 +282,32 @@ export class ParserIncludes {
281282
return updatedIncludes;
282283
}
283284

284-
static async downloadIncludeRemote (cwd: string, stateDir: string, url: string, fetchIncludes: boolean): Promise<void> {
285+
static async downloadIncludeRemote (cwd: string, stateDir: string, url: string, fetchIncludes: boolean, writeStreams: WriteStreams): Promise<void> {
285286
const fsUrl = Utils.fsUrl(url);
286287
try {
287288
const target = `${cwd}/${stateDir}/includes/${fsUrl}`;
288289
if (await fs.pathExists(target) && !fetchIncludes) return;
290+
const time = process.hrtime();
289291
const res = await axios.get(url, {
290292
headers: {"User-Agent": "gitlab-ci-local"},
291293
...Utils.getAxiosProxyConfig(),
292294
});
293295
await fs.outputFile(target, res.data);
296+
writeStreams.stderr(chalk`{grey downloaded ${url} in ${prettyHrtime(process.hrtime(time))}}\n`);
294297
} catch (e) {
295298
throw new AssertionError({message: `Remote include could not be fetched ${url}\n${e}`});
296299
}
297300
}
298301

299-
static async downloadIncludeProjectFile (cwd: string, stateDir: string, project: string, ref: string, file: string, gitData: GitData, fetchIncludes: boolean): Promise<void> {
302+
static async downloadIncludeProjectFile (opts: ParserIncludesInitOptions, project: string, ref: string, file: string): Promise<void> {
303+
const {cwd, stateDir, gitData, fetchIncludes, writeStreams} = opts;
300304
const remote = gitData.remote;
301305
const normalizedFile = file.replace(/^\/+/, "");
302306
let tmpDir = null;
303307
try {
304308
const target = `${stateDir}/includes/${remote.host}/${project}/${ref}`;
305309
if (await fs.pathExists(`${cwd}/${target}/${normalizedFile}`) && !fetchIncludes) return;
310+
const time = process.hrtime();
306311

307312
if (remote.schema.startsWith("http")) {
308313
const ext = "tmp-" + Math.random();
@@ -323,6 +328,7 @@ export class ParserIncludes {
323328
await fs.mkdirp(`${cwd}/${target}`);
324329
await Utils.bash(`set -eou pipefail; git archive --remote=ssh://git@${remote.host}:${remote.port}/${project}.git ${ref} ${normalizedFile} | tar -f - -xC ${target}/`, cwd);
325330
}
331+
writeStreams.stderr(chalk`{grey downloaded ${project} ${ref} ${normalizedFile} in ${prettyHrtime(process.hrtime(time))}}\n`);
326332
} catch (e) {
327333
throw new AssertionError({message: `Project include could not be fetched { project: ${project}, ref: ${ref}, file: ${normalizedFile} }\n${e}`});
328334
} finally {
@@ -333,14 +339,16 @@ export class ParserIncludes {
333339
}
334340
}
335341

336-
static async downloadIncludeComponent (cwd: string, stateDir: string, project: string, ref: string, componentName: string, gitData: GitData, fetchIncludes: boolean): Promise<void> {
342+
static async downloadIncludeComponent (opts: ParserIncludesInitOptions, project: string, ref: string, componentName: string): Promise<void> {
343+
const {cwd, stateDir, gitData, fetchIncludes, writeStreams} = opts;
337344
const remote = gitData.remote;
338345
const files = [`${componentName}.yml`, `${componentName}/template.yml`];
339346
let tmpDir = null;
340347
try {
341348
const target = `${stateDir}/includes/${remote.host}/${project}/${ref}`;
342349

343350
if (!fetchIncludes && (await fs.pathExists(`${cwd}/${target}/${files[0]}`) || await fs.pathExists(`${cwd}/${target}/${files[1]}`))) return;
351+
const time = process.hrtime();
344352

345353
if (remote.schema.startsWith("http")) {
346354
const ext = "tmp-" + Math.random();
@@ -367,6 +375,7 @@ export class ParserIncludes {
367375
await fs.mkdirp(`${cwd}/${target}`);
368376
await Utils.bash(`set -eou pipefail; git archive --remote=ssh://git@${remote.host}:${remote.port}/${project}.git ${ref} ${componentWildcard} | tar -f - -xC ${target}/`, cwd);
369377
}
378+
writeStreams.stderr(chalk`{grey downloaded ${project} ${ref} ${componentName} in ${prettyHrtime(process.hrtime(time))}}\n`);
370379
} catch (e) {
371380
throw new AssertionError({message: `Component include could not be fetched { project: ${project}, ref: ${ref}, file: ${files} }\n${e}`});
372381
} finally {

src/variables-from-files.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {GitData} from "./git-data.js";
33
import fs from "fs-extra";
44
import * as yaml from "js-yaml";
55
import chalk from "chalk-template";
6+
import prettyHrtime from "pretty-hrtime";
67
import {Argv} from "./argv.js";
78
import assert from "assert";
89
import {Utils} from "./utils.js";
@@ -40,7 +41,9 @@ export class VariablesFromFiles {
4041
const url = match.groups?.url;
4142
const file = match.groups?.file;
4243
const ref = match.groups?.ref;
44+
const time = process.hrtime();
4345
const res = await Utils.bash(`set -eou pipefail; git archive --remote=${url} ${ref} ${file} | tar -xO ${file}`, cwd);
46+
writeStreams.stderr(chalk`{grey downloaded ${url} ${ref} ${file} in ${prettyHrtime(process.hrtime(time))}}\n`);
4447
const loadedYaml = yaml.load(`${res.stdout}`);
4548
// Check if loadedYaml is an object
4649
if (typeof loadedYaml === "object" && loadedYaml !== null) {

0 commit comments

Comments
 (0)