<commit_before>import * as fs from 'fs';
import { Config as I18NextConfig, I18Next } from 'jovo-cms-i18next';
import {
	BaseApp,
	ExtensibleConfig,
	Host,
	Log,
	Logger,
	LogLevel
} from 'jovo-core';
import { FileDb2 } from 'jovo-db-filedb';

import _cloneDeep = require('lodash.clonedeep');
import _get = require('lodash.get');
import _merge = require('lodash.merge');
import _set = require('lodash.set');
import * as path from 'path';
import {
	Config as JovoUserConfig,
	ContextConfig,
	JovoUser,
	MetaDataConfig
} from './middleware/user/JovoUser';

import { Component, Config as ComponentConfig } from './middleware/Component';
import { Handler } from './middleware/Handler';
import { BasicLogging } from './middleware/logging/BasicLogging';
import { Config as RouterConfig, Router } from './middleware/Router';

if (process.argv.includes('--port')) {
	process.env.JOVO_PORT = process.argv[
		process.argv.indexOf('--port') + 1
	].trim();
}

if (process.argv.includes('--log-level')) {
	process.env.JOVO_LOG_LEVEL =
		Logger.getLogLevelFromString(
			process.argv[process.argv.indexOf('--log-level') + 1].trim()
		) + '';
}

if (process.argv.includes('--cwd')) {
	process.env.JOVO_CWD = process.argv[process.argv.indexOf('--cwd') + 1].trim();
}

if (process.argv.includes('--config')) {
	process.env.JOVO_CONFIG = process.argv[
		process.argv.indexOf('--config') + 1
	].trim();
}

if (process.argv.includes('--stage')) {
	process.env.JOVO_STAGE = process.argv[
		process.argv.indexOf('--stage') + 1
	].trim();
}

export class App extends BaseApp {
	config: Config = {
		enabled: true,<commit_msg>:wip: Add performance report middleware<commit_after>import * as fs from 'fs';
import { Config as I18NextConfig, I18Next } from 'jovo-cms-i18next';
import {
	BaseApp,
	ExtensibleConfig,
	Host,
	Log,
	Logger,
	LogLevel,
    Middleware
} from 'jovo-core';
import { FileDb2 } from 'jovo-db-filedb';

import _cloneDeep = require('lodash.clonedeep');
import _get = require('lodash.get');
import _merge = require('lodash.merge');
import _set = require('lodash.set');
import * as path from 'path';
import {
	Config as JovoUserConfig,
	ContextConfig,
	JovoUser,
	MetaDataConfig
} from './middleware/user/JovoUser';

import { Component, Config as ComponentConfig } from './middleware/Component';
import { Handler } from './middleware/Handler';
import { BasicLogging } from './middleware/logging/BasicLogging';
import { Config as RouterConfig, Router } from './middleware/Router';

if (process.argv.includes('--port')) {
	process.env.JOVO_PORT = process.argv[
		process.argv.indexOf('--port') + 1
	].trim();
}

if (process.argv.includes('--log-level')) {
	process.env.JOVO_LOG_LEVEL =
		Logger.getLogLevelFromString(
			process.argv[process.argv.indexOf('--log-level') + 1].trim()
		) + '';
}

if (process.argv.includes('--cwd')) {
	process.env.JOVO_CWD = process.argv[process.argv.indexOf('--cwd') + 1].trim();
}

if (process.argv.includes('--config')) {
	process.env.JOVO_CONFIG = process.argv[
		process.argv.indexOf('--config') + 1
	].trim();
}

if (process.argv.includes('--stage')) {
	process.env.JOVO_STAGE = process.argv[
		process.argv.indexOf('--stage') + 1
	].trim();
}

if (process.env.JOVO_PERFORMANCE_REPORT || process.argv.includes('--performance-report')) {

    const middlewareMap: Record<string, string[]> = {};

    function getInstallLocation(stackStr: string, parent: string, middleware: string) {
        const stackArray = stackStr.split('\n');
        for (let i = 0; i < stackArray.length; i++) {
            const stackLine = stackArray[i];
            if (stackLine.includes('Middleware.use')) {
                const nextStackLine = stackArray[i + 1];
                let pluginName = 'Object.<anonymous>';

                if (!nextStackLine.includes(pluginName)) {
                    pluginName = nextStackLine.substring(nextStackLine.indexOf('at') + 3, nextStackLine.indexOf('.install'));
                }
                let location = ' - ' + nextStackLine.substring(nextStackLine.indexOf('(') + 1, nextStackLine.indexOf(')'));
                // location = location.substring(process.cwd().length - 3);
                location = '';
                const middlewareFullKey = `${parent}.${middleware}`;


                if (!middlewareMap[middlewareFullKey]) {
                    middlewareMap[middlewareFullKey] = [];
                }

                middlewareMap[middlewareFullKey].push(`${pluginName}${location}`);

            }
        }

    }

    const oldMiddlewareUse = Middleware.prototype.use;

    Middleware.prototype.use = function(fns) {
        getInstallLocation(new Error().stack!, this.parent.constructor.name, this.name);
        oldMiddlewareUse.call(this, fns);
        return this;
    };


    const oldBaseAppHandle = BaseApp.prototype.handle;
    BaseApp.prototype.handle = async function (host) {
        Log.info();
        Log.infoStart('Handle duration ')
        await oldBaseAppHandle.call(this, host);
        Log.infoEnd('Handle duration ')
    };


    const oldMiddlewareRun = Middleware.prototype.run;

    Middleware.prototype.run = async function(object, concurrent) {
        const start = process.hrtime();
        await oldMiddlewareRun.call(this, object, concurrent);
        const end = process.hrtime();

        // duration of the complete middleware process
        let duration = (end[1] - start[1]) / 1000 / 1000; // from nano to ms

        if (duration < 0) {
            duration = 0;
        }

        Log.writeToStreams(`\b→ ${this.parent.constructor.name}.${this.name}`, 2, false);

        if (duration <= 80) { // good value
            Log.green().info(`+${duration.toFixed(0)}ms`);
        } else if (duration > 80 && duration <= 200) {  // ok value
            Log.yellow().info(`+${duration.toFixed(0)}ms`);
        } else if (duration > 200) {  // bad value
            Log.red().info(`+${duration.toFixed(0)}ms`);
        }

        const middlewareFullKey = `${this.parent.constructor.name}.${this.name}`;


        if (middlewareMap[middlewareFullKey]) {
            middlewareMap[middlewareFullKey].forEach((impl) => {
                // Log.dim().info(`↓ ${impl}`);
            })
        }
    };

}



export class App extends BaseApp {
	config: Config = {
		enabled: true,
{'fraction_non_alphanumeric': 0.1599490202325952, 'fraction_numerical': 0.008762147522701928, 'mean_word_length': 3.058177117000646, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 8, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6686441', 'n_tokens_mistral': 2048, 'n_tokens_neox': 1961, 'n_words': 390}