@allurereport/core 3.9.0 → 3.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/report.js CHANGED
@@ -9,7 +9,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
9
9
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
- var _AllureReport_instances, _AllureReport_ci, _AllureReport_store, _AllureReport_readers, _AllureReport_plugins, _AllureReport_reportFiles, _AllureReport_realtimeChannel, _AllureReport_realtimeUpdateScheduler, _AllureReport_realTime, _AllureReport_hideLabels, _AllureReport_output, _AllureReport_history, _AllureReport_allureServiceClient, _AllureReport_qualityGate, _AllureReport_dump, _AllureReport_categories, _AllureReport_environments, _AllureReport_globalAttachments, _AllureReport_dumpTempDirs, _AllureReport_state, _AllureReport_executionStage, _AllureReport_historyDataPoint, _AllureReport_summaryPath, _AllureReport_summariesByPluginId, _AllureReport_publishedRemoteHrefs, _AllureReport_published, _AllureReport_publish, _AllureReport_runRealtimeUpdate, _AllureReport_getReportsToPublish, _AllureReport_cleanupFailedRemoteReport, _AllureReport_logPublishError, _AllureReport_applyPublishLinksToSummaries, _AllureReport_cloneSummariesByPluginId, _AllureReport_writeSummaryFiles, _AllureReport_generateRootSummary, _AllureReport_eachPlugin, _AllureReport_getPluginState;
12
+ var _AllureReport_instances, _AllureReport_ci, _AllureReport_store, _AllureReport_readers, _AllureReport_plugins, _AllureReport_reportFiles, _AllureReport_realtimeChannel, _AllureReport_realtimeUpdateScheduler, _AllureReport_realTime, _AllureReport_hideLabels, _AllureReport_output, _AllureReport_history, _AllureReport_allureServiceClient, _AllureReport_qualityGate, _AllureReport_dump, _AllureReport_categories, _AllureReport_environments, _AllureReport_globalAttachments, _AllureReport_dumpTempDirs, _AllureReport_state, _AllureReport_executionStage, _AllureReport_historyDataPoint, _AllureReport_summaryPath, _AllureReport_summariesByPluginId, _AllureReport_publishedRemoteHrefs, _AllureReport_published, _AllureReport_endGeneratePerfSpan, _AllureReport_publish, _AllureReport_runRealtimeUpdate, _AllureReport_getReportsToPublish, _AllureReport_cleanupFailedRemoteReport, _AllureReport_logPublishError, _AllureReport_applyPublishLinksToSummaries, _AllureReport_cloneSummariesByPluginId, _AllureReport_writeSummaryFiles, _AllureReport_generateRootSummary, _AllureReport_finishGeneratePerfSpan, _AllureReport_finishPerfMetrics, _AllureReport_eachPlugin, _AllureReport_getPluginState;
13
13
  import console from "node:console";
14
14
  import { randomUUID } from "node:crypto";
15
15
  import { once } from "node:events";
@@ -35,6 +35,7 @@ import { QualityGate } from "./qualityGate/index.js";
35
35
  import { DefaultAllureStore } from "./store/store.js";
36
36
  import { createUploadProgressBarCounter } from "./utils/cli.js";
37
37
  import { environmentIdentityById, environmentIdentityByName } from "./utils/environment.js";
38
+ import { measurePerf, PERF_METRIC_NAMES, PERF_METRIC_PREFIXES, startPerfSpan, writePerfMetrics } from "./utils/perf.js";
38
39
  import { RealtimeChannel } from "./utils/realtimeChannel.js";
39
40
  import { RealtimeUpdateScheduler } from "./utils/realtimeUpdateScheduler.js";
40
41
  import { resolveDumpAttachmentPath, UnsafeDumpPathError } from "./utils/safeDumpPath.js";
@@ -94,6 +95,7 @@ export class AllureReport {
94
95
  _AllureReport_summariesByPluginId.set(this, new Map());
95
96
  _AllureReport_publishedRemoteHrefs.set(this, new Set());
96
97
  _AllureReport_published.set(this, false);
98
+ _AllureReport_endGeneratePerfSpan.set(this, void 0);
97
99
  _AllureReport_publish.set(this, async () => {
98
100
  if (__classPrivateFieldGet(this, _AllureReport_published, "f")) {
99
101
  return;
@@ -126,6 +128,7 @@ export class AllureReport {
126
128
  let summariesMutated = false;
127
129
  let reportCreated = false;
128
130
  let publishErrorMessage = "Report upload has failed, the report won't be published";
131
+ const endPublishPerfSpan = startPerfSpan(PERF_METRIC_NAMES.publishUploadTotal);
129
132
  try {
130
133
  await client.createReport({
131
134
  reportUuid: this.reportUuid,
@@ -135,12 +138,12 @@ export class AllureReport {
135
138
  reportCreated = true;
136
139
  for (const report of reportsToPublish) {
137
140
  publishErrorMessage = `Plugin "${report.pluginId}" upload has failed, the plugin won't be published`;
138
- const uploadResult = await client.uploadReport({
141
+ const uploadResult = await measurePerf(`${PERF_METRIC_PREFIXES.publishUploadPlugin}${report.pluginId}`, () => client.uploadReport({
139
142
  reportUuid: this.reportUuid,
140
143
  pluginId: report.pluginId,
141
144
  files: Object.fromEntries(Object.entries(report.files).filter(([filename]) => filename !== "summary.json")),
142
145
  onProgress: () => uploadProgressBar.tick(),
143
- });
146
+ }));
144
147
  if (uploadResult.indexHref) {
145
148
  linksByPluginId[report.pluginId] = uploadResult.indexHref;
146
149
  }
@@ -199,10 +202,11 @@ export class AllureReport {
199
202
  __classPrivateFieldGet(this, _AllureReport_logPublishError, "f").call(this, publishErrorMessage, err);
200
203
  }
201
204
  finally {
205
+ endPublishPerfSpan();
202
206
  uploadProgressBar.terminate();
203
207
  }
204
208
  });
205
- this.readDirectory = async (resultsDir) => {
209
+ this.readDirectory = async (resultsDir) => measurePerf(PERF_METRIC_NAMES.generateReadResults, async () => {
206
210
  if (__classPrivateFieldGet(this, _AllureReport_executionStage, "f") !== "running") {
207
211
  throw new Error(initRequired);
208
212
  }
@@ -228,13 +232,13 @@ export class AllureReport {
228
232
  catch (e) {
229
233
  console.error("can't read directory", e);
230
234
  }
231
- };
232
- this.readFile = async (resultsFile) => {
235
+ });
236
+ this.readFile = async (resultsFile) => measurePerf(PERF_METRIC_NAMES.generateReadResults, async () => {
233
237
  if (__classPrivateFieldGet(this, _AllureReport_executionStage, "f") !== "running") {
234
238
  throw new Error(initRequired);
235
239
  }
236
240
  await this.readResult(new PathResultFile(resultsFile));
237
- };
241
+ });
238
242
  this.readResult = async (data) => {
239
243
  if (__classPrivateFieldGet(this, _AllureReport_executionStage, "f") !== "running") {
240
244
  throw new Error(initRequired);
@@ -275,6 +279,7 @@ export class AllureReport {
275
279
  throw new Error("the report is already stopped, the restart isn't supported at the moment");
276
280
  }
277
281
  __classPrivateFieldSet(this, _AllureReport_executionStage, "running", "f");
282
+ __classPrivateFieldSet(this, _AllureReport_endGeneratePerfSpan, startPerfSpan(PERF_METRIC_NAMES.generateTotal), "f");
278
283
  const cwd = resolve(process.cwd());
279
284
  const cwdWithSep = cwd.endsWith(sep) ? cwd : `${cwd}${sep}`;
280
285
  if (__classPrivateFieldGet(this, _AllureReport_globalAttachments, "f")?.length) {
@@ -440,160 +445,164 @@ export class AllureReport {
440
445
  }
441
446
  await rename(dumpTempPath, dumpPath);
442
447
  };
443
- this.restoreState = async (dumps) => {
448
+ this.restoreState = async (dumps) => measurePerf(PERF_METRIC_NAMES.restoreStateTotal, async () => {
444
449
  for (const dump of dumps) {
445
- if (!existsSync(dump)) {
446
- console.error(`Failed to restore state from "${dump}", continuing without it`);
447
- console.error("Dump file does not exist");
448
- continue;
449
- }
450
- try {
451
- const dumpArchive = new ZipReadStream.async({
452
- file: dump,
453
- });
454
- let restoreError;
450
+ await measurePerf(PERF_METRIC_NAMES.restoreStateDump, async () => {
451
+ if (!existsSync(dump)) {
452
+ console.error(`Failed to restore state from "${dump}", continuing without it`);
453
+ console.error("Dump file does not exist");
454
+ return;
455
+ }
455
456
  try {
456
- const dumpEntries = await dumpArchive.entries();
457
- const dumpEntriesList = Object.entries(dumpEntries);
458
- const requiredEntryData = async (entryName) => {
459
- if (!dumpEntries[entryName]) {
460
- throw new Error(`Missing required dump entry "${entryName}"`);
461
- }
462
- return dumpArchive.entryData(entryName);
463
- };
464
- const optionalEntryData = async (entryName) => dumpEntries[entryName] ? dumpArchive.entryData(entryName) : undefined;
465
- if (!dumpEntries[AllureStoreDumpFiles.TestResults]) {
466
- const nestedDumpEntries = dumpEntriesList.filter(([entryName, entry]) => !entry.isDirectory &&
467
- !entryName.startsWith("__MACOSX/") &&
468
- !basename(entryName).startsWith("._") &&
469
- entryName.toLowerCase().endsWith(".zip"));
470
- if (nestedDumpEntries.length > 0) {
471
- const nestedDumpsTempDir = await mkdtemp(join(tmpdir(), `${basename(dump, ".zip")}-nested-`));
472
- const nestedDumpPaths = [];
473
- __classPrivateFieldGet(this, _AllureReport_dumpTempDirs, "f").push(nestedDumpsTempDir);
474
- for (const [entryName] of nestedDumpEntries) {
475
- const nestedDumpPath = join(nestedDumpsTempDir, `${nestedDumpPaths.length}-${basename(entryName)}`);
476
- await writeFile(nestedDumpPath, await dumpArchive.entryData(entryName));
477
- nestedDumpPaths.push(nestedDumpPath);
457
+ const dumpArchive = new ZipReadStream.async({
458
+ file: dump,
459
+ });
460
+ let restoreError;
461
+ try {
462
+ const dumpEntries = await dumpArchive.entries();
463
+ const dumpEntriesList = Object.entries(dumpEntries);
464
+ const requiredEntryData = async (entryName) => {
465
+ if (!dumpEntries[entryName]) {
466
+ throw new Error(`Missing required dump entry "${entryName}"`);
467
+ }
468
+ return dumpArchive.entryData(entryName);
469
+ };
470
+ const optionalEntryData = async (entryName) => dumpEntries[entryName] ? dumpArchive.entryData(entryName) : undefined;
471
+ if (!dumpEntries[AllureStoreDumpFiles.TestResults]) {
472
+ const nestedDumpEntries = dumpEntriesList.filter(([entryName, entry]) => !entry.isDirectory &&
473
+ !entryName.startsWith("__MACOSX/") &&
474
+ !basename(entryName).startsWith("._") &&
475
+ entryName.toLowerCase().endsWith(".zip"));
476
+ if (nestedDumpEntries.length > 0) {
477
+ const nestedDumpsTempDir = await mkdtemp(join(tmpdir(), `${basename(dump, ".zip")}-nested-`));
478
+ const nestedDumpPaths = [];
479
+ __classPrivateFieldGet(this, _AllureReport_dumpTempDirs, "f").push(nestedDumpsTempDir);
480
+ for (const [entryName] of nestedDumpEntries) {
481
+ const nestedDumpPath = join(nestedDumpsTempDir, `${nestedDumpPaths.length}-${basename(entryName)}`);
482
+ await writeFile(nestedDumpPath, await dumpArchive.entryData(entryName));
483
+ nestedDumpPaths.push(nestedDumpPath);
484
+ }
485
+ await this.restoreState(nestedDumpPaths);
486
+ return;
478
487
  }
479
- await this.restoreState(nestedDumpPaths);
480
- continue;
481
488
  }
482
- }
483
- const testResultsEntry = await requiredEntryData(AllureStoreDumpFiles.TestResults);
484
- const testCasesEntry = await requiredEntryData(AllureStoreDumpFiles.TestCases);
485
- const fixturesEntry = await requiredEntryData(AllureStoreDumpFiles.Fixtures);
486
- const attachmentsEntry = await requiredEntryData(AllureStoreDumpFiles.Attachments);
487
- const checkResultsEntry = await optionalEntryData(AllureStoreDumpFiles.CheckResults);
488
- const environmentsEntry = await requiredEntryData(AllureStoreDumpFiles.Environments);
489
- const reportVariablesEntry = await requiredEntryData(AllureStoreDumpFiles.ReportVariables);
490
- const globalAttachmentsEntry = await requiredEntryData(AllureStoreDumpFiles.GlobalAttachments);
491
- const globalErrorsEntry = await requiredEntryData(AllureStoreDumpFiles.GlobalErrors);
492
- const indexAttachmentsEntry = await requiredEntryData(AllureStoreDumpFiles.IndexAttachmentsByTestResults);
493
- const indexTestResultsByHistoryId = await requiredEntryData(AllureStoreDumpFiles.IndexTestResultsByHistoryId);
494
- const indexTestResultsByTestCaseEntry = await requiredEntryData(AllureStoreDumpFiles.IndexTestResultsByTestCase);
495
- const indexAttachmentsByFixtureEntry = await requiredEntryData(AllureStoreDumpFiles.IndexAttachmentsByFixture);
496
- const indexFixturesByTestResultEntry = await requiredEntryData(AllureStoreDumpFiles.IndexFixturesByTestResult);
497
- const indexKnownByHistoryIdEntry = await requiredEntryData(AllureStoreDumpFiles.IndexKnownByHistoryId);
498
- const qualityGateResultsEntry = await requiredEntryData(AllureStoreDumpFiles.QualityGateResults);
499
- const testResultIngestOrderEntry = await optionalEntryData(AllureStoreDumpFiles.TestResultIngestOrder);
500
- const attachmentsLinks = JSON.parse(attachmentsEntry.toString("utf8"));
501
- const attachmentsEntries = dumpEntriesList.reduce((acc, [entryName, entry]) => {
502
- switch (entryName) {
503
- case AllureStoreDumpFiles.Attachments:
504
- case AllureStoreDumpFiles.CheckResults:
505
- case AllureStoreDumpFiles.TestResults:
506
- case AllureStoreDumpFiles.TestCases:
507
- case AllureStoreDumpFiles.Fixtures:
508
- case AllureStoreDumpFiles.Environments:
509
- case AllureStoreDumpFiles.ReportVariables:
510
- case AllureStoreDumpFiles.GlobalAttachments:
511
- case AllureStoreDumpFiles.GlobalErrors:
512
- case AllureStoreDumpFiles.IndexAttachmentsByTestResults:
513
- case AllureStoreDumpFiles.IndexTestResultsByHistoryId:
514
- case AllureStoreDumpFiles.IndexTestResultsByTestCase:
515
- case AllureStoreDumpFiles.IndexAttachmentsByFixture:
516
- case AllureStoreDumpFiles.IndexFixturesByTestResult:
517
- case AllureStoreDumpFiles.IndexKnownByHistoryId:
518
- case AllureStoreDumpFiles.QualityGateResults:
519
- case AllureStoreDumpFiles.TestResultIngestOrder:
520
- return acc;
521
- default:
522
- if (entry.isDirectory || !attachmentsLinks[entryName] || attachmentsLinks[entryName].missed) {
489
+ const testResultsEntry = await requiredEntryData(AllureStoreDumpFiles.TestResults);
490
+ const testCasesEntry = await requiredEntryData(AllureStoreDumpFiles.TestCases);
491
+ const fixturesEntry = await requiredEntryData(AllureStoreDumpFiles.Fixtures);
492
+ const attachmentsEntry = await requiredEntryData(AllureStoreDumpFiles.Attachments);
493
+ const checkResultsEntry = await optionalEntryData(AllureStoreDumpFiles.CheckResults);
494
+ const environmentsEntry = await requiredEntryData(AllureStoreDumpFiles.Environments);
495
+ const reportVariablesEntry = await requiredEntryData(AllureStoreDumpFiles.ReportVariables);
496
+ const globalAttachmentsEntry = await requiredEntryData(AllureStoreDumpFiles.GlobalAttachments);
497
+ const globalErrorsEntry = await requiredEntryData(AllureStoreDumpFiles.GlobalErrors);
498
+ const indexAttachmentsEntry = await requiredEntryData(AllureStoreDumpFiles.IndexAttachmentsByTestResults);
499
+ const indexTestResultsByHistoryId = await requiredEntryData(AllureStoreDumpFiles.IndexTestResultsByHistoryId);
500
+ const indexTestResultsByTestCaseEntry = await requiredEntryData(AllureStoreDumpFiles.IndexTestResultsByTestCase);
501
+ const indexAttachmentsByFixtureEntry = await requiredEntryData(AllureStoreDumpFiles.IndexAttachmentsByFixture);
502
+ const indexFixturesByTestResultEntry = await requiredEntryData(AllureStoreDumpFiles.IndexFixturesByTestResult);
503
+ const indexKnownByHistoryIdEntry = await requiredEntryData(AllureStoreDumpFiles.IndexKnownByHistoryId);
504
+ const qualityGateResultsEntry = await requiredEntryData(AllureStoreDumpFiles.QualityGateResults);
505
+ const testResultIngestOrderEntry = await optionalEntryData(AllureStoreDumpFiles.TestResultIngestOrder);
506
+ const attachmentsLinks = JSON.parse(attachmentsEntry.toString("utf8"));
507
+ const attachmentsEntries = dumpEntriesList.reduce((acc, [entryName, entry]) => {
508
+ switch (entryName) {
509
+ case AllureStoreDumpFiles.Attachments:
510
+ case AllureStoreDumpFiles.CheckResults:
511
+ case AllureStoreDumpFiles.TestResults:
512
+ case AllureStoreDumpFiles.TestCases:
513
+ case AllureStoreDumpFiles.Fixtures:
514
+ case AllureStoreDumpFiles.Environments:
515
+ case AllureStoreDumpFiles.ReportVariables:
516
+ case AllureStoreDumpFiles.GlobalAttachments:
517
+ case AllureStoreDumpFiles.GlobalErrors:
518
+ case AllureStoreDumpFiles.IndexAttachmentsByTestResults:
519
+ case AllureStoreDumpFiles.IndexTestResultsByHistoryId:
520
+ case AllureStoreDumpFiles.IndexTestResultsByTestCase:
521
+ case AllureStoreDumpFiles.IndexAttachmentsByFixture:
522
+ case AllureStoreDumpFiles.IndexFixturesByTestResult:
523
+ case AllureStoreDumpFiles.IndexKnownByHistoryId:
524
+ case AllureStoreDumpFiles.QualityGateResults:
525
+ case AllureStoreDumpFiles.TestResultIngestOrder:
523
526
  return acc;
527
+ default:
528
+ if (entry.isDirectory || !attachmentsLinks[entryName] || attachmentsLinks[entryName].missed) {
529
+ return acc;
530
+ }
531
+ return Object.assign(acc, {
532
+ [entryName]: entry,
533
+ });
534
+ }
535
+ }, {});
536
+ const dumpState = {
537
+ testResults: JSON.parse(testResultsEntry.toString("utf8")),
538
+ testCases: JSON.parse(testCasesEntry.toString("utf8")),
539
+ fixtures: JSON.parse(fixturesEntry.toString("utf8")),
540
+ attachments: attachmentsLinks,
541
+ checkResults: checkResultsEntry ? JSON.parse(checkResultsEntry.toString("utf8")) : [],
542
+ environments: JSON.parse(environmentsEntry.toString("utf8")),
543
+ reportVariables: JSON.parse(reportVariablesEntry.toString("utf8")),
544
+ globalAttachmentIds: JSON.parse(globalAttachmentsEntry.toString("utf8")),
545
+ globalErrors: JSON.parse(globalErrorsEntry.toString("utf8")),
546
+ indexAttachmentByTestResult: JSON.parse(indexAttachmentsEntry.toString("utf8")),
547
+ indexTestResultByHistoryId: JSON.parse(indexTestResultsByHistoryId.toString("utf8")),
548
+ indexTestResultByTestCase: JSON.parse(indexTestResultsByTestCaseEntry.toString("utf8")),
549
+ indexAttachmentByFixture: JSON.parse(indexAttachmentsByFixtureEntry.toString("utf8")),
550
+ indexFixturesByTestResult: JSON.parse(indexFixturesByTestResultEntry.toString("utf8")),
551
+ indexKnownByHistoryId: JSON.parse(indexKnownByHistoryIdEntry.toString("utf8")),
552
+ qualityGateResults: JSON.parse(qualityGateResultsEntry.toString("utf8")),
553
+ testResultIdsIngestOrder: testResultIngestOrderEntry
554
+ ? JSON.parse(testResultIngestOrderEntry.toString("utf8"))
555
+ : [],
556
+ };
557
+ const dumpTempDir = await mkdtemp(join(tmpdir(), basename(dump, ".zip")));
558
+ const resultsAttachments = {};
559
+ __classPrivateFieldGet(this, _AllureReport_dumpTempDirs, "f").push(dumpTempDir);
560
+ await measurePerf(PERF_METRIC_NAMES.restoreStateAttachments, async () => {
561
+ try {
562
+ for (const [attachmentId] of Object.entries(attachmentsEntries)) {
563
+ const attachmentContentEntry = await dumpArchive.entryData(attachmentId);
564
+ const attachmentFilePath = resolveDumpAttachmentPath(dumpTempDir, attachmentId);
565
+ await writeFile(attachmentFilePath, attachmentContentEntry);
566
+ resultsAttachments[attachmentId] = new PathResultFile(attachmentFilePath, attachmentId);
524
567
  }
525
- return Object.assign(acc, {
526
- [entryName]: entry,
527
- });
528
- }
529
- }, {});
530
- const dumpState = {
531
- testResults: JSON.parse(testResultsEntry.toString("utf8")),
532
- testCases: JSON.parse(testCasesEntry.toString("utf8")),
533
- fixtures: JSON.parse(fixturesEntry.toString("utf8")),
534
- attachments: attachmentsLinks,
535
- checkResults: checkResultsEntry ? JSON.parse(checkResultsEntry.toString("utf8")) : [],
536
- environments: JSON.parse(environmentsEntry.toString("utf8")),
537
- reportVariables: JSON.parse(reportVariablesEntry.toString("utf8")),
538
- globalAttachmentIds: JSON.parse(globalAttachmentsEntry.toString("utf8")),
539
- globalErrors: JSON.parse(globalErrorsEntry.toString("utf8")),
540
- indexAttachmentByTestResult: JSON.parse(indexAttachmentsEntry.toString("utf8")),
541
- indexTestResultByHistoryId: JSON.parse(indexTestResultsByHistoryId.toString("utf8")),
542
- indexTestResultByTestCase: JSON.parse(indexTestResultsByTestCaseEntry.toString("utf8")),
543
- indexAttachmentByFixture: JSON.parse(indexAttachmentsByFixtureEntry.toString("utf8")),
544
- indexFixturesByTestResult: JSON.parse(indexFixturesByTestResultEntry.toString("utf8")),
545
- indexKnownByHistoryId: JSON.parse(indexKnownByHistoryIdEntry.toString("utf8")),
546
- qualityGateResults: JSON.parse(qualityGateResultsEntry.toString("utf8")),
547
- testResultIdsIngestOrder: testResultIngestOrderEntry
548
- ? JSON.parse(testResultIngestOrderEntry.toString("utf8"))
549
- : [],
550
- };
551
- const dumpTempDir = await mkdtemp(join(tmpdir(), basename(dump, ".zip")));
552
- const resultsAttachments = {};
553
- __classPrivateFieldGet(this, _AllureReport_dumpTempDirs, "f").push(dumpTempDir);
554
- try {
555
- for (const [attachmentId] of Object.entries(attachmentsEntries)) {
556
- const attachmentContentEntry = await dumpArchive.entryData(attachmentId);
557
- const attachmentFilePath = resolveDumpAttachmentPath(dumpTempDir, attachmentId);
558
- await writeFile(attachmentFilePath, attachmentContentEntry);
559
- resultsAttachments[attachmentId] = new PathResultFile(attachmentFilePath, attachmentId);
560
- }
568
+ }
569
+ catch (err) {
570
+ if (err instanceof UnsafeDumpPathError) {
571
+ console.error(`Cannot restore dump from "${dump}": the archive lists attachment paths that would write outside the extract directory (unsafe zip paths such as "../" or absolute names).`);
572
+ console.error(err.message);
573
+ console.error("Only use dump archives produced by this tool; do not load untrusted or third-party --dump zip files.");
574
+ throw err;
575
+ }
576
+ console.error(`Can't restore attachment contents from "${dump}", continuing without them`);
577
+ console.error(errorDetails(err));
578
+ }
579
+ });
580
+ await measurePerf(PERF_METRIC_NAMES.restoreStateStoreRestore, async () => __classPrivateFieldGet(this, _AllureReport_store, "f").restoreState(dumpState, resultsAttachments));
581
+ console.info(`Successfully restored state from "${dump}"`);
561
582
  }
562
583
  catch (err) {
563
- if (err instanceof UnsafeDumpPathError) {
564
- console.error(`Cannot restore dump from "${dump}": the archive lists attachment paths that would write outside the extract directory (unsafe zip paths such as "../" or absolute names).`);
565
- console.error(err.message);
566
- console.error("Only use dump archives produced by this tool; do not load untrusted or third-party --dump zip files.");
567
- throw err;
584
+ restoreError = err;
585
+ throw err;
586
+ }
587
+ finally {
588
+ try {
589
+ await dumpArchive.close();
590
+ }
591
+ catch (err) {
592
+ if (!restoreError) {
593
+ console.error(`Failed to close dump archive "${dump}"`);
594
+ console.error(errorDetails(err));
595
+ }
568
596
  }
569
- console.error(`Can't restore attachment contents from "${dump}", continuing without them`);
570
- console.error(errorDetails(err));
571
597
  }
572
- await __classPrivateFieldGet(this, _AllureReport_store, "f").restoreState(dumpState, resultsAttachments);
573
- console.info(`Successfully restored state from "${dump}"`);
574
598
  }
575
599
  catch (err) {
576
- restoreError = err;
577
- throw err;
600
+ console.error(`Failed to restore state from "${dump}", continuing without it`);
601
+ console.error(errorDetails(err));
578
602
  }
579
- finally {
580
- try {
581
- await dumpArchive.close();
582
- }
583
- catch (err) {
584
- if (!restoreError) {
585
- console.error(`Failed to close dump archive "${dump}"`);
586
- console.error(errorDetails(err));
587
- }
588
- }
589
- }
590
- }
591
- catch (err) {
592
- console.error(`Failed to restore state from "${dump}", continuing without it`);
593
- console.error(errorDetails(err));
594
- }
603
+ });
595
604
  }
596
- };
605
+ });
597
606
  _AllureReport_getReportsToPublish.set(this, async () => {
598
607
  const reports = [];
599
608
  for (const { enabled, id, options } of __classPrivateFieldGet(this, _AllureReport_plugins, "f")) {
@@ -663,7 +672,7 @@ export class AllureReport {
663
672
  _AllureReport_generateRootSummary.set(this, async () => {
664
673
  const summaries = [...__classPrivateFieldGet(this, _AllureReport_summariesByPluginId, "f").values()].map(clonePluginSummary);
665
674
  if (summaries.length > 1) {
666
- __classPrivateFieldSet(this, _AllureReport_summaryPath, await generateSummary(__classPrivateFieldGet(this, _AllureReport_output, "f"), summaries), "f");
675
+ __classPrivateFieldSet(this, _AllureReport_summaryPath, await measurePerf(PERF_METRIC_NAMES.summaryGenerate, async () => generateSummary(__classPrivateFieldGet(this, _AllureReport_output, "f"), summaries)), "f");
667
676
  }
668
677
  else {
669
678
  __classPrivateFieldSet(this, _AllureReport_summaryPath, undefined, "f");
@@ -674,96 +683,119 @@ export class AllureReport {
674
683
  if (__classPrivateFieldGet(this, _AllureReport_executionStage, "f") !== "running") {
675
684
  throw new Error(initRequired);
676
685
  }
677
- const testResults = await __classPrivateFieldGet(this, _AllureReport_store, "f").allTestResults();
678
- const testCases = await __classPrivateFieldGet(this, _AllureReport_store, "f").allTestCases();
679
- __classPrivateFieldSet(this, _AllureReport_historyDataPoint, createHistory(this.reportUuid, this.reportName, testCases, testResults, this.reportUrl), "f");
680
- __classPrivateFieldGet(this, _AllureReport_realtimeChannel, "f").close();
681
686
  try {
682
- await __classPrivateFieldGet(this, _AllureReport_realtimeUpdateScheduler, "f").close();
683
- }
684
- catch (e) {
685
- console.error("realtime update failed during shutdown", e);
686
- }
687
- __classPrivateFieldSet(this, _AllureReport_executionStage, "done", "f");
688
- if (__classPrivateFieldGet(this, _AllureReport_dump, "f")) {
689
- await this.dumpState();
690
- return;
691
- }
692
- await __classPrivateFieldGet(this, _AllureReport_eachPlugin, "f").call(this, false, async (plugin, context) => {
693
- await plugin.done?.(context, __classPrivateFieldGet(this, _AllureReport_store, "f"));
694
- });
695
- await __classPrivateFieldGet(this, _AllureReport_eachPlugin, "f").call(this, false, async (plugin, context) => {
696
- const summary = await plugin?.info?.(context, __classPrivateFieldGet(this, _AllureReport_store, "f"));
697
- if (!summary) {
687
+ const testResults = await __classPrivateFieldGet(this, _AllureReport_store, "f").allTestResults();
688
+ const testCases = await __classPrivateFieldGet(this, _AllureReport_store, "f").allTestCases();
689
+ __classPrivateFieldSet(this, _AllureReport_historyDataPoint, createHistory(this.reportUuid, this.reportName, testCases, testResults, this.reportUrl), "f");
690
+ __classPrivateFieldGet(this, _AllureReport_realtimeChannel, "f").close();
691
+ try {
692
+ await __classPrivateFieldGet(this, _AllureReport_realtimeUpdateScheduler, "f").close();
693
+ }
694
+ catch (e) {
695
+ console.error("realtime update failed during shutdown", e);
696
+ }
697
+ __classPrivateFieldSet(this, _AllureReport_executionStage, "done", "f");
698
+ if (__classPrivateFieldGet(this, _AllureReport_dump, "f")) {
699
+ await this.dumpState();
698
700
  return;
699
701
  }
700
- summary.pluginId = context.id;
701
- summary.pullRequestHref = __classPrivateFieldGet(this, _AllureReport_ci, "f")?.pullRequestUrl;
702
- summary.jobHref = __classPrivateFieldGet(this, _AllureReport_ci, "f")?.jobRunUrl;
703
- summaries.push({
704
- ...summary,
705
- href: `${context.id}/`,
702
+ await measurePerf(PERF_METRIC_NAMES.generatePluginsDone, async () => {
703
+ await __classPrivateFieldGet(this, _AllureReport_eachPlugin, "f").call(this, false, async (plugin, context) => {
704
+ await measurePerf(`${PERF_METRIC_PREFIXES.generatePluginDone}${context.id}`, async () => {
705
+ await plugin.done?.(context, __classPrivateFieldGet(this, _AllureReport_store, "f"));
706
+ });
707
+ });
706
708
  });
707
- });
708
- __classPrivateFieldSet(this, _AllureReport_summariesByPluginId, new Map(summaries
709
- .filter((summary) => !!summary.pluginId)
710
- .map((summary) => [summary.pluginId, summary])), "f");
711
- await __classPrivateFieldGet(this, _AllureReport_publish, "f").call(this);
712
- let outputDirFiles = [];
713
- try {
714
- outputDirFiles = await readdir(__classPrivateFieldGet(this, _AllureReport_output, "f"));
715
- }
716
- catch { }
717
- if (outputDirFiles.length === 0) {
718
- return;
719
- }
720
- const reportPath = join(__classPrivateFieldGet(this, _AllureReport_output, "f"), outputDirFiles[0]);
721
- const reportStats = await lstat(reportPath);
722
- const outputEntriesStats = await Promise.all(outputDirFiles.map((file) => lstat(join(__classPrivateFieldGet(this, _AllureReport_output, "f"), file))));
723
- const outputDirectoryEntries = outputEntriesStats.filter((entry) => entry.isDirectory());
724
- if (reportStats.isDirectory() && outputDirectoryEntries.length === 1) {
725
- const reportContent = await readdir(reportPath);
726
- for (const entry of reportContent) {
727
- const currentFilePath = join(reportPath, entry);
728
- const newFilePath = resolve(dirname(currentFilePath), "..", entry);
729
- await rename(currentFilePath, newFilePath);
730
- }
731
- await rm(reportPath, { recursive: true });
732
- }
733
- for (const dir of __classPrivateFieldGet(this, _AllureReport_dumpTempDirs, "f")) {
709
+ __classPrivateFieldGet(this, _AllureReport_finishGeneratePerfSpan, "f").call(this);
710
+ await __classPrivateFieldGet(this, _AllureReport_eachPlugin, "f").call(this, false, async (plugin, context) => {
711
+ const summary = await plugin?.info?.(context, __classPrivateFieldGet(this, _AllureReport_store, "f"));
712
+ if (!summary) {
713
+ return;
714
+ }
715
+ summary.pluginId = context.id;
716
+ summary.pullRequestHref = __classPrivateFieldGet(this, _AllureReport_ci, "f")?.pullRequestUrl;
717
+ summary.jobHref = __classPrivateFieldGet(this, _AllureReport_ci, "f")?.jobRunUrl;
718
+ summaries.push({
719
+ ...summary,
720
+ href: `${context.id}/`,
721
+ });
722
+ });
723
+ __classPrivateFieldSet(this, _AllureReport_summariesByPluginId, new Map(summaries
724
+ .filter((summary) => !!summary.pluginId)
725
+ .map((summary) => [summary.pluginId, summary])), "f");
726
+ await __classPrivateFieldGet(this, _AllureReport_publish, "f").call(this);
727
+ let outputDirFiles = [];
734
728
  try {
735
- await rm(dir, { recursive: true });
729
+ outputDirFiles = await readdir(__classPrivateFieldGet(this, _AllureReport_output, "f"));
736
730
  }
737
731
  catch { }
738
- }
739
- if (__classPrivateFieldGet(this, _AllureReport_history, "f")) {
740
- try {
741
- await __classPrivateFieldGet(this, _AllureReport_store, "f").appendHistory(__classPrivateFieldGet(this, _AllureReport_historyDataPoint, "f"));
732
+ if (outputDirFiles.length === 0) {
733
+ return;
742
734
  }
743
- catch (err) {
744
- if (err instanceof KnownError) {
745
- console.error("Failed to append history", err.message);
735
+ const reportPath = join(__classPrivateFieldGet(this, _AllureReport_output, "f"), outputDirFiles[0]);
736
+ const reportStats = await lstat(reportPath);
737
+ const outputEntriesStats = await Promise.all(outputDirFiles.map((file) => lstat(join(__classPrivateFieldGet(this, _AllureReport_output, "f"), file))));
738
+ const outputDirectoryEntries = outputEntriesStats.filter((entry) => entry.isDirectory());
739
+ if (reportStats.isDirectory() && outputDirectoryEntries.length === 1) {
740
+ const reportContent = await readdir(reportPath);
741
+ for (const entry of reportContent) {
742
+ const currentFilePath = join(reportPath, entry);
743
+ const newFilePath = resolve(dirname(currentFilePath), "..", entry);
744
+ await rename(currentFilePath, newFilePath);
746
745
  }
747
- else if (err instanceof UnknownError) {
748
- console.error("Failed to append history due to unexpected error", err.message);
746
+ await rm(reportPath, { recursive: true });
747
+ }
748
+ for (const dir of __classPrivateFieldGet(this, _AllureReport_dumpTempDirs, "f")) {
749
+ try {
750
+ await rm(dir, { recursive: true });
749
751
  }
750
- else {
751
- throw err;
752
+ catch { }
753
+ }
754
+ if (__classPrivateFieldGet(this, _AllureReport_history, "f")) {
755
+ try {
756
+ await __classPrivateFieldGet(this, _AllureReport_store, "f").appendHistory(__classPrivateFieldGet(this, _AllureReport_historyDataPoint, "f"));
757
+ }
758
+ catch (err) {
759
+ if (err instanceof KnownError) {
760
+ console.error("Failed to append history", err.message);
761
+ }
762
+ else if (err instanceof UnknownError) {
763
+ console.error("Failed to append history due to unexpected error", err.message);
764
+ }
765
+ else {
766
+ throw err;
767
+ }
752
768
  }
753
769
  }
770
+ if (__classPrivateFieldGet(this, _AllureReport_publishedRemoteHrefs, "f").size > 0) {
771
+ console.info("Next reports have been published:");
772
+ __classPrivateFieldGet(this, _AllureReport_publishedRemoteHrefs, "f").forEach((href) => {
773
+ console.info(`- ${href}`);
774
+ });
775
+ }
776
+ if (!__classPrivateFieldGet(this, _AllureReport_qualityGate, "f")) {
777
+ return;
778
+ }
779
+ const qualityGateResults = await __classPrivateFieldGet(this, _AllureReport_store, "f").qualityGateResultsByEnv();
780
+ await writeFile(join(__classPrivateFieldGet(this, _AllureReport_output, "f"), "quality-gate.json"), JSON.stringify(qualityGateResults));
754
781
  }
755
- if (__classPrivateFieldGet(this, _AllureReport_publishedRemoteHrefs, "f").size > 0) {
756
- console.info("Next reports have been published:");
757
- __classPrivateFieldGet(this, _AllureReport_publishedRemoteHrefs, "f").forEach((href) => {
758
- console.info(`- ${href}`);
759
- });
760
- }
761
- if (!__classPrivateFieldGet(this, _AllureReport_qualityGate, "f")) {
762
- return;
782
+ finally {
783
+ await __classPrivateFieldGet(this, _AllureReport_finishPerfMetrics, "f").call(this);
763
784
  }
764
- const qualityGateResults = await __classPrivateFieldGet(this, _AllureReport_store, "f").qualityGateResultsByEnv();
765
- await writeFile(join(__classPrivateFieldGet(this, _AllureReport_output, "f"), "quality-gate.json"), JSON.stringify(qualityGateResults));
766
785
  };
786
+ _AllureReport_finishGeneratePerfSpan.set(this, () => {
787
+ __classPrivateFieldGet(this, _AllureReport_endGeneratePerfSpan, "f")?.call(this);
788
+ __classPrivateFieldSet(this, _AllureReport_endGeneratePerfSpan, undefined, "f");
789
+ });
790
+ _AllureReport_finishPerfMetrics.set(this, async () => {
791
+ __classPrivateFieldGet(this, _AllureReport_finishGeneratePerfSpan, "f").call(this);
792
+ try {
793
+ await writePerfMetrics(__classPrivateFieldGet(this, _AllureReport_output, "f"));
794
+ }
795
+ catch (err) {
796
+ console.error("Failed to write Allure performance metrics", err);
797
+ }
798
+ });
767
799
  _AllureReport_eachPlugin.set(this, async (initState, consumer) => {
768
800
  if (initState) {
769
801
  __classPrivateFieldSet(this, _AllureReport_state, {}, "f");
@@ -886,6 +918,6 @@ export class AllureReport {
886
918
  return __classPrivateFieldGet(this, _AllureReport_realtimeChannel, "f").dispatcher;
887
919
  }
888
920
  }
889
- _AllureReport_ci = new WeakMap(), _AllureReport_store = new WeakMap(), _AllureReport_readers = new WeakMap(), _AllureReport_plugins = new WeakMap(), _AllureReport_reportFiles = new WeakMap(), _AllureReport_realtimeChannel = new WeakMap(), _AllureReport_realtimeUpdateScheduler = new WeakMap(), _AllureReport_realTime = new WeakMap(), _AllureReport_hideLabels = new WeakMap(), _AllureReport_output = new WeakMap(), _AllureReport_history = new WeakMap(), _AllureReport_allureServiceClient = new WeakMap(), _AllureReport_qualityGate = new WeakMap(), _AllureReport_dump = new WeakMap(), _AllureReport_categories = new WeakMap(), _AllureReport_environments = new WeakMap(), _AllureReport_globalAttachments = new WeakMap(), _AllureReport_dumpTempDirs = new WeakMap(), _AllureReport_state = new WeakMap(), _AllureReport_executionStage = new WeakMap(), _AllureReport_historyDataPoint = new WeakMap(), _AllureReport_summaryPath = new WeakMap(), _AllureReport_summariesByPluginId = new WeakMap(), _AllureReport_publishedRemoteHrefs = new WeakMap(), _AllureReport_published = new WeakMap(), _AllureReport_publish = new WeakMap(), _AllureReport_runRealtimeUpdate = new WeakMap(), _AllureReport_getReportsToPublish = new WeakMap(), _AllureReport_cleanupFailedRemoteReport = new WeakMap(), _AllureReport_logPublishError = new WeakMap(), _AllureReport_applyPublishLinksToSummaries = new WeakMap(), _AllureReport_cloneSummariesByPluginId = new WeakMap(), _AllureReport_writeSummaryFiles = new WeakMap(), _AllureReport_generateRootSummary = new WeakMap(), _AllureReport_eachPlugin = new WeakMap(), _AllureReport_instances = new WeakSet(), _AllureReport_getPluginState = function _AllureReport_getPluginState(init, id) {
921
+ _AllureReport_ci = new WeakMap(), _AllureReport_store = new WeakMap(), _AllureReport_readers = new WeakMap(), _AllureReport_plugins = new WeakMap(), _AllureReport_reportFiles = new WeakMap(), _AllureReport_realtimeChannel = new WeakMap(), _AllureReport_realtimeUpdateScheduler = new WeakMap(), _AllureReport_realTime = new WeakMap(), _AllureReport_hideLabels = new WeakMap(), _AllureReport_output = new WeakMap(), _AllureReport_history = new WeakMap(), _AllureReport_allureServiceClient = new WeakMap(), _AllureReport_qualityGate = new WeakMap(), _AllureReport_dump = new WeakMap(), _AllureReport_categories = new WeakMap(), _AllureReport_environments = new WeakMap(), _AllureReport_globalAttachments = new WeakMap(), _AllureReport_dumpTempDirs = new WeakMap(), _AllureReport_state = new WeakMap(), _AllureReport_executionStage = new WeakMap(), _AllureReport_historyDataPoint = new WeakMap(), _AllureReport_summaryPath = new WeakMap(), _AllureReport_summariesByPluginId = new WeakMap(), _AllureReport_publishedRemoteHrefs = new WeakMap(), _AllureReport_published = new WeakMap(), _AllureReport_endGeneratePerfSpan = new WeakMap(), _AllureReport_publish = new WeakMap(), _AllureReport_runRealtimeUpdate = new WeakMap(), _AllureReport_getReportsToPublish = new WeakMap(), _AllureReport_cleanupFailedRemoteReport = new WeakMap(), _AllureReport_logPublishError = new WeakMap(), _AllureReport_applyPublishLinksToSummaries = new WeakMap(), _AllureReport_cloneSummariesByPluginId = new WeakMap(), _AllureReport_writeSummaryFiles = new WeakMap(), _AllureReport_generateRootSummary = new WeakMap(), _AllureReport_finishGeneratePerfSpan = new WeakMap(), _AllureReport_finishPerfMetrics = new WeakMap(), _AllureReport_eachPlugin = new WeakMap(), _AllureReport_instances = new WeakSet(), _AllureReport_getPluginState = function _AllureReport_getPluginState(init, id) {
890
922
  return init ? new DefaultPluginState({}) : __classPrivateFieldGet(this, _AllureReport_state, "f")?.[id];
891
923
  };
@@ -0,0 +1,42 @@
1
+ export declare const PERF_METRICS_FILE = "allure-perf-metrics.json";
2
+ export type PerfMetricSpan = {
3
+ name: string;
4
+ startTimeMs: number;
5
+ durationMs: number;
6
+ };
7
+ export type PerfMetricSummary = {
8
+ name: string;
9
+ count: number;
10
+ totalMs: number;
11
+ minMs: number;
12
+ maxMs: number;
13
+ avgMs: number;
14
+ };
15
+ export type PerfMetricsPayload = {
16
+ version: 1;
17
+ generatedAt: string;
18
+ timeOriginMs: number;
19
+ spans: PerfMetricSpan[];
20
+ summary: PerfMetricSummary[];
21
+ };
22
+ export declare const PERF_METRIC_NAMES: {
23
+ readonly restoreStateTotal: "restoreState.total";
24
+ readonly restoreStateDump: "restoreState.dump";
25
+ readonly restoreStateAttachments: "restoreState.attachments";
26
+ readonly restoreStateStoreRestore: "restoreState.storeRestore";
27
+ readonly generateTotal: "generate.total";
28
+ readonly generateReadResults: "generate.readResults";
29
+ readonly generatePluginsDone: "generate.plugins.done";
30
+ readonly publishUploadTotal: "publish.upload.total";
31
+ readonly summaryGenerate: "summary.generate";
32
+ };
33
+ export declare const PERF_METRIC_PREFIXES: {
34
+ readonly generatePluginDone: "generate.plugin.done.";
35
+ readonly publishUploadPlugin: "publish.upload.plugin.";
36
+ };
37
+ export declare const isPerfMetricsEnabled: () => boolean;
38
+ export declare const startPerfSpan: (name: string) => (() => void);
39
+ export declare const measurePerf: <T>(name: string, fn: () => Promise<T>) => Promise<T>;
40
+ export declare const getPerfMetricsPayload: () => PerfMetricsPayload;
41
+ export declare const writePerfMetrics: (output: string) => Promise<boolean>;
42
+ export declare const resetPerfMetrics: () => void;
@@ -0,0 +1,122 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { performance } from "node:perf_hooks";
4
+ export const PERF_METRICS_FILE = "allure-perf-metrics.json";
5
+ const MARK_PREFIX = "allure:perf:";
6
+ const ENABLED_VALUES = new Set(["1", "true", "yes", "on"]);
7
+ const SPANS = [];
8
+ const MARKS = new Set();
9
+ const MEASURES = new Set();
10
+ let sequence = 0;
11
+ const round = (value) => Number(value.toFixed(3));
12
+ export const PERF_METRIC_NAMES = {
13
+ restoreStateTotal: "restoreState.total",
14
+ restoreStateDump: "restoreState.dump",
15
+ restoreStateAttachments: "restoreState.attachments",
16
+ restoreStateStoreRestore: "restoreState.storeRestore",
17
+ generateTotal: "generate.total",
18
+ generateReadResults: "generate.readResults",
19
+ generatePluginsDone: "generate.plugins.done",
20
+ publishUploadTotal: "publish.upload.total",
21
+ summaryGenerate: "summary.generate",
22
+ };
23
+ export const PERF_METRIC_PREFIXES = {
24
+ generatePluginDone: "generate.plugin.done.",
25
+ publishUploadPlugin: "publish.upload.plugin.",
26
+ };
27
+ export const isPerfMetricsEnabled = () => ENABLED_VALUES.has((process.env.ALLURE_PERF_METRICS ?? "").toLowerCase());
28
+ export const startPerfSpan = (name) => {
29
+ if (!isPerfMetricsEnabled()) {
30
+ return () => { };
31
+ }
32
+ const id = `${MARK_PREFIX}${sequence++}:${name}`;
33
+ const startMark = `${id}:start`;
34
+ const endMark = `${id}:end`;
35
+ let ended = false;
36
+ MARKS.add(startMark);
37
+ MARKS.add(endMark);
38
+ MEASURES.add(id);
39
+ performance.mark(startMark);
40
+ return () => {
41
+ if (ended) {
42
+ return;
43
+ }
44
+ ended = true;
45
+ performance.mark(endMark);
46
+ performance.measure(id, startMark, endMark);
47
+ const entry = performance.getEntriesByName(id, "measure").at(-1);
48
+ if (entry) {
49
+ SPANS.push({
50
+ name,
51
+ startTimeMs: round(entry.startTime),
52
+ durationMs: round(entry.duration),
53
+ });
54
+ }
55
+ performance.clearMarks(startMark);
56
+ performance.clearMarks(endMark);
57
+ performance.clearMeasures(id);
58
+ MARKS.delete(startMark);
59
+ MARKS.delete(endMark);
60
+ MEASURES.delete(id);
61
+ };
62
+ };
63
+ export const measurePerf = async (name, fn) => {
64
+ if (!isPerfMetricsEnabled()) {
65
+ return fn();
66
+ }
67
+ const end = startPerfSpan(name);
68
+ try {
69
+ return await fn();
70
+ }
71
+ finally {
72
+ end();
73
+ }
74
+ };
75
+ export const getPerfMetricsPayload = () => {
76
+ const byName = new Map();
77
+ for (const span of SPANS) {
78
+ const current = byName.get(span.name) ?? [];
79
+ current.push(span);
80
+ byName.set(span.name, current);
81
+ }
82
+ return {
83
+ version: 1,
84
+ generatedAt: new Date().toISOString(),
85
+ timeOriginMs: round(performance.timeOrigin),
86
+ spans: [...SPANS],
87
+ summary: [...byName.entries()].map(([name, group]) => {
88
+ const durations = group.map(({ durationMs }) => durationMs);
89
+ const totalMs = durations.reduce((acc, duration) => acc + duration, 0);
90
+ return {
91
+ name,
92
+ count: group.length,
93
+ totalMs: round(totalMs),
94
+ minMs: round(Math.min(...durations)),
95
+ maxMs: round(Math.max(...durations)),
96
+ avgMs: round(totalMs / group.length),
97
+ };
98
+ }),
99
+ };
100
+ };
101
+ export const writePerfMetrics = async (output) => {
102
+ if (!isPerfMetricsEnabled()) {
103
+ return false;
104
+ }
105
+ const payload = getPerfMetricsPayload();
106
+ await mkdir(output, { recursive: true });
107
+ await writeFile(join(output, PERF_METRICS_FILE), `${JSON.stringify(payload, null, 2)}\n`, "utf8");
108
+ resetPerfMetrics();
109
+ return true;
110
+ };
111
+ export const resetPerfMetrics = () => {
112
+ SPANS.length = 0;
113
+ sequence = 0;
114
+ for (const mark of MARKS) {
115
+ performance.clearMarks(mark);
116
+ }
117
+ for (const measure of MEASURES) {
118
+ performance.clearMeasures(measure);
119
+ }
120
+ MARKS.clear();
121
+ MEASURES.clear();
122
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allurereport/core",
3
- "version": "3.9.0",
3
+ "version": "3.10.0",
4
4
  "description": "Collection of generic Allure utilities used across the entire project",
5
5
  "keywords": [
6
6
  "allure"
@@ -25,25 +25,25 @@
25
25
  "lint:fix": "oxlint --import-plugin --fix src test features stories"
26
26
  },
27
27
  "dependencies": {
28
- "@allurereport/ci": "3.9.0",
29
- "@allurereport/core-api": "3.9.0",
30
- "@allurereport/plugin-agent": "3.9.0",
31
- "@allurereport/plugin-allure2": "3.9.0",
32
- "@allurereport/plugin-api": "3.9.0",
33
- "@allurereport/plugin-awesome": "3.9.0",
34
- "@allurereport/plugin-classic": "3.9.0",
35
- "@allurereport/plugin-csv": "3.9.0",
36
- "@allurereport/plugin-dashboard": "3.9.0",
37
- "@allurereport/plugin-jira": "3.9.0",
38
- "@allurereport/plugin-log": "3.9.0",
39
- "@allurereport/plugin-progress": "3.9.0",
40
- "@allurereport/plugin-slack": "3.9.0",
41
- "@allurereport/plugin-testops": "3.9.0",
42
- "@allurereport/plugin-testplan": "3.9.0",
43
- "@allurereport/reader": "3.9.0",
44
- "@allurereport/reader-api": "3.9.0",
45
- "@allurereport/service": "3.9.0",
46
- "@allurereport/summary": "3.9.0",
28
+ "@allurereport/ci": "3.10.0",
29
+ "@allurereport/core-api": "3.10.0",
30
+ "@allurereport/plugin-agent": "3.10.0",
31
+ "@allurereport/plugin-allure2": "3.10.0",
32
+ "@allurereport/plugin-api": "3.10.0",
33
+ "@allurereport/plugin-awesome": "3.10.0",
34
+ "@allurereport/plugin-classic": "3.10.0",
35
+ "@allurereport/plugin-csv": "3.10.0",
36
+ "@allurereport/plugin-dashboard": "3.10.0",
37
+ "@allurereport/plugin-jira": "3.10.0",
38
+ "@allurereport/plugin-log": "3.10.0",
39
+ "@allurereport/plugin-progress": "3.10.0",
40
+ "@allurereport/plugin-slack": "3.10.0",
41
+ "@allurereport/plugin-testops": "3.10.0",
42
+ "@allurereport/plugin-testplan": "3.10.0",
43
+ "@allurereport/reader": "3.10.0",
44
+ "@allurereport/reader-api": "3.10.0",
45
+ "@allurereport/service": "3.10.0",
46
+ "@allurereport/summary": "3.10.0",
47
47
  "glob": "^13.0.6",
48
48
  "handlebars": "^4.7.9",
49
49
  "node-stream-zip": "^1.15.0",
@@ -53,15 +53,15 @@
53
53
  "zip-stream": "^7.0.2"
54
54
  },
55
55
  "devDependencies": {
56
- "@types/node": "^20.17.9",
56
+ "@types/node": "^20",
57
57
  "@types/zip-stream": "^7.0.0",
58
- "@vitest/runner": "^2.1.9",
58
+ "@vitest/runner": "^2",
59
59
  "@vitest/snapshot": "^2.1.9",
60
- "allure-js-commons": "^3.3.3",
61
- "allure-vitest": "^3.3.3",
62
- "rimraf": "^6.0.1",
60
+ "allure-js-commons": "^3",
61
+ "allure-vitest": "^3",
62
+ "rimraf": "^6",
63
63
  "tslib": "^2.7.0",
64
- "typescript": "^5.6.3",
65
- "vitest": "^2.1.9"
64
+ "typescript": "^5",
65
+ "vitest": "^4.1.0"
66
66
  }
67
67
  }