@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
273 lines • 23.4 kB
JavaScript
"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;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProfilerConfig = void 0;
const fs = __importStar(require("fs"));
const BaseModel_1 = require("./BaseModel");
const config_1 = require("../constants/config");
const PathUtils_1 = require("../helper/PathUtils");
const UnifiedPath_1 = require("../system/UnifiedPath");
const Crypto_1 = require("../system/Crypto");
const PermissionHelper_1 = require("../helper/PermissionHelper");
// Types
const types_1 = require("../types");
class ProfilerConfig extends BaseModel_1.BaseModel {
constructor(filePath, config) {
super();
this.filePath = filePath;
this.extends = config.extends;
this.registryOptions = config.registryOptions;
this.exportOptions = config.exportOptions;
this.projectOptions = config.projectOptions;
this.runtimeOptions = config.runtimeOptions;
}
static getDefaultConfig() {
return new ProfilerConfig(new UnifiedPath_1.UnifiedPath(process.cwd()).join(config_1.STATIC_CONFIG_FILENAME), config_1.DEFAULT_PROFILER_CONFIG);
}
getAnonymizedRuntimeOptions() {
if (this.runtimeOptions.sensorInterface) {
switch (this.runtimeOptions.sensorInterface.type) {
case types_1.SensorInterfaceType.windows:
return Object.assign(Object.assign({}, this.runtimeOptions), { sensorInterface: {
type: types_1.SensorInterfaceType.windows,
options: {
sampleInterval: this.runtimeOptions.sensorInterface.options.sampleInterval,
outputFilePath: '<anonymized>'
}
} });
case types_1.SensorInterfaceType.perf:
return Object.assign(Object.assign({}, this.runtimeOptions), { sensorInterface: {
type: types_1.SensorInterfaceType.perf,
options: {
sampleInterval: this.runtimeOptions.sensorInterface.options.sampleInterval,
outputFilePath: '<anonymized>'
}
} });
case types_1.SensorInterfaceType.powermetrics:
return Object.assign(Object.assign({}, this.runtimeOptions), { sensorInterface: {
type: types_1.SensorInterfaceType.powermetrics,
options: {
sampleInterval: this.runtimeOptions.sensorInterface.options.sampleInterval,
outputFilePath: '<anonymized>'
}
} });
}
}
return this.runtimeOptions;
}
getV8CPUSamplingInterval() {
return this.runtimeOptions.v8.cpu.sampleInterval;
}
getRegistryUploadUrl() {
return `http://${this.registryOptions.url}/upload`;
}
uploadEnabled() {
var _a, _b;
return (((_a = this.registryOptions) === null || _a === void 0 ? void 0 : _a.url) !== undefined) && ((_b = this.registryOptions) === null || _b === void 0 ? void 0 : _b.url) !== '';
}
getProjectIdentifier() {
if (!Crypto_1.Crypto.validateUniqueID(this.projectOptions.identifier)) {
throw new Error('ProfilerConfig.getProjectIdentifier: identifier should be an uuid4');
}
return this.projectOptions.identifier;
}
getRootDir() {
if (PathUtils_1.PathUtils.isAbsolute(this.exportOptions.rootDir)) {
return new UnifiedPath_1.UnifiedPath(this.exportOptions.rootDir);
}
return this.filePath.dirName().join(this.exportOptions.rootDir);
}
getOutDir() {
if (PathUtils_1.PathUtils.isAbsolute(this.exportOptions.outDir)) {
return new UnifiedPath_1.UnifiedPath(this.exportOptions.outDir);
}
return this.filePath.dirName().join(this.exportOptions.outDir);
}
getOutHistoryDir() {
if (PathUtils_1.PathUtils.isAbsolute(this.exportOptions.outHistoryDir)) {
return new UnifiedPath_1.UnifiedPath(this.exportOptions.outHistoryDir);
}
return this.filePath.dirName().join(this.exportOptions.outHistoryDir);
}
getSensorInterfaceType() {
var _a;
return (_a = this.runtimeOptions.sensorInterface) === null || _a === void 0 ? void 0 : _a.type;
}
getSensorInterfaceOptions() {
var _a;
return (_a = this.runtimeOptions.sensorInterface) === null || _a === void 0 ? void 0 : _a.options;
}
shouldExportV8Profile() {
return this.exportOptions.exportV8Profile;
}
shouldExportReport() {
return this.exportOptions.exportReport;
}
shouldExportSensorInterfaceData() {
return this.exportOptions.exportSensorInterfaceData;
}
getSeedForMathRandom() {
return this.runtimeOptions.seeds['Math.random'];
}
configAsExtended(pathDiff) {
const exportOptions = this.exportOptions;
if (exportOptions) {
if (exportOptions.outDir && !PathUtils_1.PathUtils.isAbsolute(exportOptions.outDir)) {
exportOptions.outDir = pathDiff.join(exportOptions.outDir).toString();
}
if (exportOptions.outHistoryDir && !PathUtils_1.PathUtils.isAbsolute(exportOptions.outHistoryDir)) {
exportOptions.outHistoryDir = pathDiff.join(exportOptions.outHistoryDir).toString();
}
if (exportOptions.rootDir && !PathUtils_1.PathUtils.isAbsolute(exportOptions.rootDir)) {
exportOptions.rootDir = pathDiff.join(exportOptions.rootDir).toString();
}
}
return {
exportOptions: exportOptions,
projectOptions: this.projectOptions,
runtimeOptions: this.runtimeOptions,
registryOptions: this.registryOptions
};
}
/**
* Fills unspecified values of the config with values of the given config
*
* example usage:
* - every config that gets resolved inherits values of the default config (baseConfig)
* to ensure that unspecified values are filled with the default value. This happens via:
* config.implement(baseConfig):
*
* - if a config contains the extends keyword like this:
* {
* "extends": "<config that gets extended>"
* }
* the config gets extended via:
* config.implement(<config that gets extended>):
*
* it also adjusts the inherited path values values to make them relative to the config
*
*
* @param config to inherit from
*/
implement(config) {
var _a, _b, _c, _d, _e, _f;
const pathDiff = this.filePath.dirName().pathTo(config.filePath.dirName());
const configToExtend = config.configAsExtended(pathDiff);
const newExportOptions = Object.assign(Object.assign({}, configToExtend.exportOptions), this.exportOptions);
const newProjectOptions = Object.assign(Object.assign({}, configToExtend.projectOptions), this.projectOptions);
const newRuntimeOptions = Object.assign(Object.assign(Object.assign({}, configToExtend.runtimeOptions), this.runtimeOptions), { seeds: Object.assign(Object.assign({}, (((_a = configToExtend === null || configToExtend === void 0 ? void 0 : configToExtend.runtimeOptions) === null || _a === void 0 ? void 0 : _a.seeds) || {})), (((_b = this.runtimeOptions) === null || _b === void 0 ? void 0 : _b.seeds) || {})), v8: {
cpu: Object.assign(Object.assign({}, (((_d = (_c = configToExtend.runtimeOptions) === null || _c === void 0 ? void 0 : _c.v8) === null || _d === void 0 ? void 0 : _d.cpu) || {})), (((_f = (_e = this.runtimeOptions) === null || _e === void 0 ? void 0 : _e.v8) === null || _f === void 0 ? void 0 : _f.cpu) || {}))
} });
const newRegistryOptions = Object.assign(Object.assign({}, configToExtend.registryOptions), this.registryOptions);
this.exportOptions = newExportOptions;
this.projectOptions = newProjectOptions;
this.runtimeOptions = newRuntimeOptions;
this.registryOptions = newRegistryOptions;
}
static fromJSON(json) {
let data;
if (typeof json === 'string') {
data = JSON.parse(json);
}
else {
data = json;
}
if (data.projectOptions === undefined ||
data.projectOptions.identifier === undefined) {
throw new Error('ProfilerConfig: the project has no identifier yet');
}
if (!Crypto_1.Crypto.validateUniqueID(data.projectOptions.identifier)) {
throw new Error('ProfilerConfig.getProjectIdentifier: Loaded identifier from the config should be an uuid4');
}
return new ProfilerConfig(new UnifiedPath_1.UnifiedPath(''), {
extends: data.extends,
exportOptions: data.exportOptions,
projectOptions: data.projectOptions,
runtimeOptions: data.runtimeOptions,
registryOptions: data.registryOptions
});
}
toJSON() {
return ({
extends: this.extends,
exportOptions: this.exportOptions,
projectOptions: this.projectOptions,
runtimeOptions: this.runtimeOptions,
registryOptions: this.registryOptions
});
}
storeToFile(filePath) {
if (!fs.existsSync(filePath.dirName().toPlatformString())) {
PermissionHelper_1.PermissionHelper.mkdirRecursivelyWithUserPermission(filePath.dirName().toPlatformString());
}
PermissionHelper_1.PermissionHelper.writeFileWithUserPermission(filePath.toPlatformString(), JSON.stringify(this, null, 2));
}
// loads a config from a given file path and extends it
// this method is NOT used to ensure load a valid (complete) config, use resolveFromFile to achieve that
static loadFromFile(filePath) {
if (!fs.existsSync(filePath.toPlatformString())) {
return undefined;
}
const loadedConfig = ProfilerConfig.fromJSON(fs.readFileSync(filePath.toPlatformString()).toString());
loadedConfig.filePath = filePath;
if (loadedConfig.extends) {
const configToExtendFilePath = filePath.dirName().join(loadedConfig.extends);
const configToExtend = ProfilerConfig.loadFromFile(configToExtendFilePath);
if (configToExtend) {
loadedConfig.implement(configToExtend);
return loadedConfig;
}
}
return loadedConfig;
}
// loads a config from a given file path and fills all non defined values with the resp. default values
static resolveFromFile(filePath) {
const baseConfig = ProfilerConfig.getDefaultConfig();
if (!filePath) {
return baseConfig;
}
const config = this.loadFromFile(filePath);
if (config) {
baseConfig.filePath = config.filePath;
config.implement(baseConfig);
return config;
}
return baseConfig;
}
static autoResolveFromPath(startDir) {
// Searches from the given path upwards until it finds the config file
const configFilePath = PathUtils_1.PathUtils.findUp(config_1.STATIC_CONFIG_FILENAME, startDir.toPlatformString());
if (!configFilePath) {
return ProfilerConfig.resolveFromFile(undefined);
}
return ProfilerConfig.resolveFromFile(new UnifiedPath_1.UnifiedPath(configFilePath));
}
static autoResolve() {
// Searches from the processes execution path upwards until it finds the config file
return this.autoResolveFromPath(new UnifiedPath_1.UnifiedPath(process.cwd()));
}
}
exports.ProfilerConfig = ProfilerConfig;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUHJvZmlsZXJDb25maWcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbW9kZWwvUHJvZmlsZXJDb25maWcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSx1Q0FBd0I7QUFFeEIsMkNBQXVDO0FBRXZDLGdEQUc0QjtBQUM1QixtREFBK0M7QUFDL0MsdURBQW1EO0FBQ25ELDZDQUF5QztBQUN6QyxpRUFBNkQ7QUFDN0QsUUFBUTtBQUNSLG9DQVlpQjtBQUVqQixNQUFhLGNBQWUsU0FBUSxxQkFBUztJQVE1QyxZQUFZLFFBQXFCLEVBQUUsTUFBdUI7UUFDekQsS0FBSyxFQUFFLENBQUE7UUFDUCxJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQTtRQUN4QixJQUFJLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUE7UUFDN0IsSUFBSSxDQUFDLGVBQWUsR0FBRyxNQUFNLENBQUMsZUFBZSxDQUFBO1FBQzdDLElBQUksQ0FBQyxhQUFhLEdBQUcsTUFBTSxDQUFDLGFBQWEsQ0FBQTtRQUN6QyxJQUFJLENBQUMsY0FBYyxHQUFHLE1BQU0sQ0FBQyxjQUFjLENBQUE7UUFDM0MsSUFBSSxDQUFDLGNBQWMsR0FBRyxNQUFNLENBQUMsY0FBYyxDQUFBO0lBQzVDLENBQUM7SUFFRCxNQUFNLENBQUMsZ0JBQWdCO1FBQ3RCLE9BQU8sSUFBSSxjQUFjLENBQ3hCLElBQUkseUJBQVcsQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsK0JBQXNCLENBQUMsRUFDM0QsZ0NBQXVCLENBQ3ZCLENBQUE7SUFDRixDQUFDO0lBRUQsMkJBQTJCO1FBQzFCLElBQUksSUFBSSxDQUFDLGNBQWMsQ0FBQyxlQUFlLEVBQUUsQ0FBQztZQUN6QyxRQUFRLElBQUksQ0FBQyxjQUFjLENBQUMsZUFBZSxDQUFDLElBQUksRUFBRSxDQUFDO2dCQUNsRCxLQUFLLDJC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