UNPKG

@oaklean/profiler-core

Version:

Part of the @oaklean suite. It provides all basic functions to work with the `.oak` file format. It allows parsing the `.oak` file format as well as tools for analyzing the measurement values. It also provides all necessary capabilities required for prec

291 lines 27.6 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ProjectReport = void 0; const fs = __importStar(require("fs")); const axios_1 = __importDefault(require("axios")); const form_data_1 = __importDefault(require("form-data")); const NodeModule_1 = require("./NodeModule"); const ProfilerConfig_1 = require("./ProfilerConfig"); const Report_1 = require("./Report"); const SystemInformation_1 = require("./SystemInformation"); const GlobalIndex_1 = require("./index/GlobalIndex"); const GitHelper_1 = require("../helper/GitHelper"); const UnifiedPath_1 = require("../system/UnifiedPath"); const Crypto_1 = require("../system/Crypto"); const BufferHelper_1 = require("../helper/BufferHelper"); const AuthenticationHelper_1 = require("../helper/AuthenticationHelper"); const InsertCPUProfileHelper_1 = require("../helper/InsertCPUProfileHelper"); const app_1 = require("../constants/app"); // Types const types_1 = require("../types"); class ProjectReport extends Report_1.Report { constructor(executionDetails, kind, projectMetaData, globalIndex, config) { let index = globalIndex; if (index === undefined) { index = new GlobalIndex_1.GlobalIndex(new NodeModule_1.NodeModule(executionDetails.languageInformation.name, executionDetails.languageInformation.version)); } super(index.getModuleIndex('upsert'), kind); this.globalIndex = index; const usedConfig = config !== undefined ? config : ProfilerConfig_1.ProfilerConfig.autoResolve(); this.executionDetails = executionDetails; if (projectMetaData) { this.projectMetaData = projectMetaData; } else { if (usedConfig === null) { throw new Error('ProjectReport: no config was provided'); } this.projectMetaData = { projectID: usedConfig.getProjectIdentifier() }; } } normalize() { const newGlobalIndex = new GlobalIndex_1.GlobalIndex(this.engineModule); super.normalize(newGlobalIndex); this.globalIndex = newGlobalIndex; } get engineModule() { return this.globalIndex.engineModule; } isCompatibleWith(other) { return this.reportVersion === other.reportVersion; } static merge(moduleIndex, ...args) { if (args.length === 0) { throw new Error('ProjectReport.merge: no ProjectReports were given'); } const systemInformationList = args.map((x) => x.executionDetails.systemInformation); if (!SystemInformation_1.SystemInformation.sameSystem(...systemInformationList)) { throw new Error('ProjectReport.merge: cannot merge ProjectReports from different systems'); } const executionDetails = args[0].executionDetails; for (const currentProjectReport of args) { if (currentProjectReport.executionDetails.commitHash !== executionDetails.commitHash) { throw new Error('ProjectReport.merge: Project reports commit hashs are not the same'); } if (currentProjectReport.executionDetails.origin !== executionDetails.origin) { throw new Error('ProjectReport.merge: Project reports have different origins'); } if (executionDetails.uncommittedChanges || currentProjectReport.executionDetails.uncommittedChanges) { executionDetails.uncommittedChanges = true; } if (currentProjectReport.executionDetails.timestamp < executionDetails.timestamp) { // set execution timestamp to the earliest // if e.g. multiple test reports are merged, the first report marks the first test execution executionDetails.timestamp = currentProjectReport.executionDetails.timestamp; // only keep the system information of the first report executionDetails.systemInformation = currentProjectReport.executionDetails.systemInformation; } } const result = Object.assign(new ProjectReport(executionDetails, types_1.ReportKind.accumulated), Report_1.Report.merge(moduleIndex, ...args)); result.globalIndex = moduleIndex.globalIndex; return result; } toJSON() { if (process.env.NODE_ENV === 'test') { this.validate(); } const reportJSON = super.toJSON(); const result = { projectMetaData: this.projectMetaData, executionDetails: this.executionDetails, globalIndex: this.globalIndex.toJSON() }; return Object.assign(result, reportJSON); } static fromJSON(json) { let data; if (typeof json === 'string') { data = JSON.parse(json); } else { data = json; } const projectReport = new ProjectReport(data.executionDetails, data.kind, data.projectMetaData, GlobalIndex_1.GlobalIndex.fromJSON(data.globalIndex, new NodeModule_1.NodeModule(data.executionDetails.languageInformation.name, data.executionDetails.languageInformation.version)), null); const result = Object.assign(projectReport, Report_1.Report.fromJSONReport(data, projectReport.moduleIndex)); return result; } static loadFromFile(filePath, kind) { if (!fs.existsSync(filePath.toPlatformString())) { return undefined; } switch (kind) { case 'json': return ProjectReport.fromJSON(fs.readFileSync(filePath.toPlatformString()).toString()); case 'bin': { const { instance } = ProjectReport.consumeFromBuffer(fs.readFileSync(filePath.toPlatformString())); return instance; } default: break; } } trackUncommittedFiles(rootDir) { var _a; return __awaiter(this, void 0, void 0, function* () { // if git is not available, set default value of uncommitted changes to undefined this.executionDetails.uncommittedChanges = undefined; const uncommittedFiles = GitHelper_1.GitHelper.uncommittedFiles(); if (uncommittedFiles === undefined) { return; } // git is available, set default value of uncommitted changes to false this.executionDetails.uncommittedChanges = false; for (const uncommittedFile of uncommittedFiles) { const pureRelativeOriginalSourcePath = rootDir.pathTo(new UnifiedPath_1.UnifiedPath(uncommittedFile)); const pathIndex = (_a = this.globalIndex.getModuleIndex('get')) === null || _a === void 0 ? void 0 : _a.getFilePathIndex('get', pureRelativeOriginalSourcePath.toString()); if (pathIndex === undefined) { continue; } pathIndex.containsUncommittedChanges = true; // if one file has uncommitted changes, the whole project has uncommitted changes this.executionDetails.uncommittedChanges = true; } }); } insertCPUProfile(rootDir, profile, transformerAdapter, metricsDataCollection) { return __awaiter(this, void 0, void 0, function* () { yield InsertCPUProfileHelper_1.InsertCPUProfileHelper.insertCPUProfile(this, rootDir, profile, transformerAdapter, metricsDataCollection); }); } storeToFile(filePath, kind, config) { super.storeToFileReport(filePath, kind, types_1.ReportType.ProjectReport, config); } toBuffer() { const buffers = [ app_1.BIN_FILE_MAGIC, BufferHelper_1.BufferHelper.String2LToBuffer(this.reportVersion), BufferHelper_1.BufferHelper.String2LToBuffer(JSON.stringify(this.executionDetails)), BufferHelper_1.BufferHelper.String2LToBuffer(JSON.stringify(this.projectMetaData)), BufferHelper_1.BufferHelper.String4LToBuffer(JSON.stringify(this.globalIndex)), super.toBuffer(types_1.ReportType.ProjectReport) ]; return Buffer.concat(buffers); } shouldBeStoredInRegistry() { return __awaiter(this, void 0, void 0, function* () { // every accumulated report should be stored in the registry // and every report that was not created in the jest environment should be stored in the registry return this.executionDetails.origin !== types_1.ProjectReportOrigin.jestEnv || this.kind === types_1.ReportKind.accumulated; }); } static versionFromBinFile(filePath) { if (!fs.existsSync(filePath.toPlatformString())) { return undefined; } return ProjectReport.versionFromBuffer(fs.readFileSync(filePath.toPlatformString())); } static versionFromBuffer(buffer) { let remainingBuffer = buffer; if (buffer.byteLength < 2) { throw new Error('ProjectReport.consumeFromBuffer: not enough bytes remaining'); } const magic = buffer.subarray(0, app_1.BIN_FILE_MAGIC.length); if (magic.compare(app_1.BIN_FILE_MAGIC) !== 0) { throw new Error('ProjectReport.consumeFromBuffer: not a binary .oak format'); } remainingBuffer = buffer.subarray(app_1.BIN_FILE_MAGIC.length); const { instance: reportVersion, remainingBuffer: newRemainingBuffer0 } = BufferHelper_1.BufferHelper.String2LFromBuffer(remainingBuffer); remainingBuffer = newRemainingBuffer0; return reportVersion; } static consumeFromBuffer(buffer, config) { let remainingBuffer = buffer; if (buffer.byteLength < 2) { throw new Error('ProjectReport.consumeFromBuffer: not enough bytes remaining'); } const magic = buffer.subarray(0, app_1.BIN_FILE_MAGIC.length); if (magic.compare(app_1.BIN_FILE_MAGIC) !== 0) { throw new Error('ProjectReport.consumeFromBuffer: not a binary .oak format'); } remainingBuffer = buffer.subarray(app_1.BIN_FILE_MAGIC.length); const { instance: reportVersion, remainingBuffer: newRemainingBuffer0 } = BufferHelper_1.BufferHelper.String2LFromBuffer(remainingBuffer); remainingBuffer = newRemainingBuffer0; const { instance: executionDetails_JSON_string, remainingBuffer: newRemainingBuffer1 } = BufferHelper_1.BufferHelper.String2LFromBuffer(remainingBuffer); remainingBuffer = newRemainingBuffer1; const executionDetails = JSON.parse(executionDetails_JSON_string); const { instance: projectMetaData_JSON_string, remainingBuffer: newRemainingBuffer2 } = BufferHelper_1.BufferHelper.String2LFromBuffer(remainingBuffer); remainingBuffer = newRemainingBuffer2; const projectMetaData = JSON.parse(projectMetaData_JSON_string); const { instance: globalIndex_JSON_string, remainingBuffer: newRemainingBuffer3 } = BufferHelper_1.BufferHelper.String4LFromBuffer(remainingBuffer); remainingBuffer = newRemainingBuffer3; const globalIndex = GlobalIndex_1.GlobalIndex.fromJSON(globalIndex_JSON_string, new NodeModule_1.NodeModule(executionDetails.languageInformation.name, executionDetails.languageInformation.version)); const { instance: report, type: reportType, remainingBuffer: newRemainingBuffer4 } = Report_1.Report.consumeFromBufferReport(remainingBuffer, globalIndex.getModuleIndex('get')); remainingBuffer = newRemainingBuffer4; const result = Object.assign(new ProjectReport(executionDetails, report.kind, projectMetaData, globalIndex, null), report); return { instance: result, type: reportType, remainingBuffer }; } hash() { return Crypto_1.Crypto.hash(this.toBuffer()); } static hashFromBinFile(filePath) { if (!fs.existsSync(filePath.toPlatformString())) { return undefined; } return Crypto_1.Crypto.hash(fs.readFileSync(filePath.toPlatformString())); } uploadToRegistry(config) { return __awaiter(this, void 0, void 0, function* () { const usedConfig = config !== undefined ? config : ProfilerConfig_1.ProfilerConfig.autoResolve(); if (!usedConfig.uploadEnabled()) { return; } const compressedBuffer = yield BufferHelper_1.BufferHelper.compressBuffer(this.toBuffer()); const formData = new form_data_1.default(); formData.append('file', compressedBuffer, 'filename.txt'); formData.append('auth', AuthenticationHelper_1.AuthenticationHelper.getAuthentication()); try { const result = yield axios_1.default.post(usedConfig.getRegistryUploadUrl(), formData, { timeout: 5000, // Set a timeout of 5 seconds headers: { 'Content-Type': 'multipart/form-data' } }); return result; } catch (_a) { } }); } } exports.ProjectReport = ProjectReport; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUHJvamVjdFJlcG9ydC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9tb2RlbC9Qcm9qZWN0UmVwb3J0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsdUNBQXdCO0FBRXhCLGtEQUF5QjtBQUN6QiwwREFBZ0M7QUFFaEMsNkNBQXlDO0FBQ3pDLHFEQUFpRDtBQUNqRCxxQ0FBaUM7QUFDakMsMkRBQXVEO0FBRXZELHFEQUFpRDtBQUlqRCxtREFBK0M7QUFFL0MsdURBQW1EO0FBQ25ELDZDQUF5QztBQUN6Qyx5REFBcUQ7QUFDckQseUVBQXFFO0FBQ3JFLDZFQUF5RTtBQUN6RSwwQ0FBaUQ7QUFDakQsUUFBUTtBQUNSLG9DQU9pQjtBQUVqQixNQUFhLGFBQWMsU0FBUSxlQUFNO0lBS3hDLFlBQ0MsZ0JBQWdELEVBQ2hELElBQWdCLEVBQ2hCLGVBQWtDLEVBQ2xDLFdBQXlCLEVBQ3pCLE1BQThCO1FBRTlCLElBQUksS0FBSyxHQUFHLFdBQVcsQ0FBQTtRQUN2QixJQUFJLEtBQUssS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUN6QixLQUFLLEdBQUcsSUFBSSx5QkFBVyxDQUFDLElBQUksdUJBQVUsQ0FDckMsZ0JBQWdCLENBQUMsbUJBQW1CLENBQUMsSUFBSSxFQUN6QyxnQkFBZ0IsQ0FBQyxtQkFBbUIsQ0FBQyxPQUFPLENBQzVDLENBQUMsQ0FBQTtRQUNILENBQUM7UUFDRCxLQUFLLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQTtRQUMzQyxJQUFJLENBQUMsV0FBVyxHQUFHLEtBQUssQ0FBQTtRQUV4QixNQUFNLFVBQVUsR0FBRyxNQUFNLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLCtCQUFjLENBQUMsV0FBVyxFQUFFLENBQUE7UUFFL0UsSUFBSSxDQUFDLGdCQUFn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