"use strict";
exports.id = "ConsoleTimelinePlugin";
exports.ids = ["ConsoleTimelinePlugin"];
exports.modules = {

/***/ 713196
/*!************************************************************************!*\
  !*** ./lib-intermediate-esm/logic/operations/ConsoleTimelinePlugin.js ***!
  \************************************************************************/
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   ConsoleTimelinePlugin: () => (/* binding */ ConsoleTimelinePlugin),
/* harmony export */   _printTimeline: () => (/* binding */ _printTimeline)
/* harmony export */ });
/* harmony import */ var _rushstack_terminal__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @rushstack/terminal */ 367587);
/* harmony import */ var _rushstack_terminal__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_rushstack_terminal__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _OperationStatus__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./OperationStatus */ 743278);
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
// See LICENSE in the project root for license information.


const PLUGIN_NAME = 'ConsoleTimelinePlugin';
/* Sample output:
==============================================================================================================================
          @rushstack/tree-pattern (build) ###########-------------------------------------------------------------------- 3.3s
          @rushstack/eslint-patch (build) ########----------------------------------------------------------------------- 2.2s
           @rushstack/eslint-patch (test) -------%----------------------------------------------------------------------- 0.0s
@rushstack/eslint-plugin-security (build) ----------########################--------------------------------------------- 6.8s
@rushstack/eslint-plugin-packlets (build) ----------############################----------------------------------------- 8.1s
         @rushstack/eslint-plugin (build) ----------##############################--------------------------------------- 8.7s
           @rushstack/tree-pattern (test) ----------#####---------------------------------------------------------------- 1.2s
 @rushstack/eslint-plugin-security (test) ---------------------------------############---------------------------------- 3.3s
 @rushstack/eslint-plugin-packlets (test) -------------------------------------#####------------------------------------- 1.1s
         @rushstack/eslint-config (build) ---------------------------------------%--------------------------------------- 0.0s
          @rushstack/eslint-plugin (test) ---------------------------------------#############--------------------------- 3.8s
          @rushstack/eslint-config (test) ---------------------------------------%--------------------------------------- 0.0s
     @rushstack/node-core-library (build) ---------------------------------------################################-------- 9.5s
      @rushstack/node-core-library (test) ----------------------------------------------------------------------######### 2.2s
==============================================================================================================================
LEGEND:                                                                                                      Total Work: 50.3s
  [#] Success  [!] Failed/warnings  [%] Skipped/cached/no-op                                                 Wall Clock: 23.7s
                                                                                                       Max Parallelism Used: 5
                                                                                                     Avg Parallelism Used: 2.1
BY PHASE:
      _phase:build 38.6s
       _phase:test 11.7s
*/
/**
 * Phased command plugin that emits a timeline to the console.
 */
class ConsoleTimelinePlugin {
    constructor(terminal) {
        this._terminal = terminal;
    }
    apply(hooks) {
        hooks.afterExecuteOperations.tap(PLUGIN_NAME, (result, context) => {
            _printTimeline({
                terminal: this._terminal,
                result,
                cobuildConfiguration: context.cobuildConfiguration
            });
        });
    }
}
/**
 * Timeline - a wider column width for printing the timeline summary
 */
const TIMELINE_WIDTH = 109;
/**
 * Timeline - symbols representing each operation status
 */
const TIMELINE_CHART_SYMBOLS = {
    [_OperationStatus__WEBPACK_IMPORTED_MODULE_1__.OperationStatus.Waiting]: '?',
    [_OperationStatus__WEBPACK_IMPORTED_MODULE_1__.OperationStatus.Ready]: '?',
    [_OperationStatus__WEBPACK_IMPORTED_MODULE_1__.OperationStatus.Queued]: '?',
    [_OperationStatus__WEBPACK_IMPORTED_MODULE_1__.OperationStatus.Executing]: '?',
    [_OperationStatus__WEBPACK_IMPORTED_MODULE_1__.OperationStatus.Success]: '#',
    [_OperationStatus__WEBPACK_IMPORTED_MODULE_1__.OperationStatus.SuccessWithWarning]: '!',
    [_OperationStatus__WEBPACK_IMPORTED_MODULE_1__.OperationStatus.Failure]: '!',
    [_OperationStatus__WEBPACK_IMPORTED_MODULE_1__.OperationStatus.Blocked]: '.',
    [_OperationStatus__WEBPACK_IMPORTED_MODULE_1__.OperationStatus.Skipped]: '%',
    [_OperationStatus__WEBPACK_IMPORTED_MODULE_1__.OperationStatus.FromCache]: '%',
    [_OperationStatus__WEBPACK_IMPORTED_MODULE_1__.OperationStatus.NoOp]: '%',
    [_OperationStatus__WEBPACK_IMPORTED_MODULE_1__.OperationStatus.Aborted]: '@'
};
const COBUILD_REPORTABLE_STATUSES = new Set([
    _OperationStatus__WEBPACK_IMPORTED_MODULE_1__.OperationStatus.Success,
    _OperationStatus__WEBPACK_IMPORTED_MODULE_1__.OperationStatus.SuccessWithWarning,
    _OperationStatus__WEBPACK_IMPORTED_MODULE_1__.OperationStatus.Failure,
    _OperationStatus__WEBPACK_IMPORTED_MODULE_1__.OperationStatus.Blocked
]);
/**
 * Timeline - colorizer for each operation status
 */
const TIMELINE_CHART_COLORIZER = {
    [_OperationStatus__WEBPACK_IMPORTED_MODULE_1__.OperationStatus.Waiting]: _rushstack_terminal__WEBPACK_IMPORTED_MODULE_0__.Colorize.yellow,
    [_OperationStatus__WEBPACK_IMPORTED_MODULE_1__.OperationStatus.Ready]: _rushstack_terminal__WEBPACK_IMPORTED_MODULE_0__.Colorize.yellow,
    [_OperationStatus__WEBPACK_IMPORTED_MODULE_1__.OperationStatus.Queued]: _rushstack_terminal__WEBPACK_IMPORTED_MODULE_0__.Colorize.yellow,
    [_OperationStatus__WEBPACK_IMPORTED_MODULE_1__.OperationStatus.Executing]: _rushstack_terminal__WEBPACK_IMPORTED_MODULE_0__.Colorize.yellow,
    [_OperationStatus__WEBPACK_IMPORTED_MODULE_1__.OperationStatus.Success]: _rushstack_terminal__WEBPACK_IMPORTED_MODULE_0__.Colorize.green,
    [_OperationStatus__WEBPACK_IMPORTED_MODULE_1__.OperationStatus.SuccessWithWarning]: _rushstack_terminal__WEBPACK_IMPORTED_MODULE_0__.Colorize.yellow,
    [_OperationStatus__WEBPACK_IMPORTED_MODULE_1__.OperationStatus.Failure]: _rushstack_terminal__WEBPACK_IMPORTED_MODULE_0__.Colorize.red,
    [_OperationStatus__WEBPACK_IMPORTED_MODULE_1__.OperationStatus.Blocked]: _rushstack_terminal__WEBPACK_IMPORTED_MODULE_0__.Colorize.red,
    [_OperationStatus__WEBPACK_IMPORTED_MODULE_1__.OperationStatus.Skipped]: _rushstack_terminal__WEBPACK_IMPORTED_MODULE_0__.Colorize.green,
    [_OperationStatus__WEBPACK_IMPORTED_MODULE_1__.OperationStatus.FromCache]: _rushstack_terminal__WEBPACK_IMPORTED_MODULE_0__.Colorize.green,
    [_OperationStatus__WEBPACK_IMPORTED_MODULE_1__.OperationStatus.NoOp]: _rushstack_terminal__WEBPACK_IMPORTED_MODULE_0__.Colorize.gray,
    [_OperationStatus__WEBPACK_IMPORTED_MODULE_1__.OperationStatus.Aborted]: _rushstack_terminal__WEBPACK_IMPORTED_MODULE_0__.Colorize.red
};
/**
 * Print a more detailed timeline and analysis of CPU usage for the build.
 * @internal
 */
function _printTimeline({ terminal, result }) {
    //
    // Gather the operation records we'll be displaying. Do some inline max()
    // finding to reduce the number of times we need to loop through operations.
    //
    var _a, _b;
    const durationByPhase = new Map();
    const data = [];
    let longestNameLength = 0;
    let longestDurationLength = 0;
    let allStart = Infinity;
    let allEnd = -Infinity;
    let workDuration = 0;
    for (const [operation, operationResult] of result.operationResults) {
        if (operationResult.silent) {
            continue;
        }
        const { stopwatch } = operationResult;
        const { _operationMetadataManager: operationMetadataManager } = operationResult;
        let { startTime } = stopwatch;
        const { endTime } = stopwatch;
        const duration = { cached: undefined, uncached: stopwatch.duration };
        if (startTime && endTime) {
            const nameLength = ((_a = operation.name) === null || _a === void 0 ? void 0 : _a.length) || 0;
            if (nameLength > longestNameLength) {
                longestNameLength = nameLength;
            }
            const wasCobuilt = !!(operationMetadataManager === null || operationMetadataManager === void 0 ? void 0 : operationMetadataManager.wasCobuilt);
            if (wasCobuilt &&
                operationResult.status !== _OperationStatus__WEBPACK_IMPORTED_MODULE_1__.OperationStatus.FromCache &&
                operationResult.nonCachedDurationMs) {
                duration.cached = stopwatch.duration;
                startTime = Math.max(0, endTime - operationResult.nonCachedDurationMs);
                duration.uncached = (endTime - startTime) / 1000;
            }
            workDuration += stopwatch.duration;
            const durationString = duration.uncached.toFixed(1);
            const durationLength = durationString.length;
            if (durationLength > longestDurationLength) {
                longestDurationLength = durationLength;
            }
            if (endTime > allEnd) {
                allEnd = endTime;
            }
            if (startTime < allStart) {
                allStart = startTime;
            }
            const { associatedPhase } = operation;
            if (associatedPhase) {
                let durationRecord = durationByPhase.get(associatedPhase);
                if (!durationRecord) {
                    durationRecord = {
                        cached: undefined,
                        uncached: 0
                    };
                    durationByPhase.set(associatedPhase, durationRecord);
                }
                if (duration.cached !== undefined) {
                    durationRecord.cached = ((_b = durationRecord.cached) !== null && _b !== void 0 ? _b : 0) + duration.cached;
                }
                durationRecord.uncached += duration.uncached;
            }
            data.push({
                startTime,
                endTime,
                durationString,
                name: operation.name,
                status: operationResult.status,
                isExecuteByOtherCobuildRunner: wasCobuilt
            });
        }
    }
    data.sort((a, b) => a.startTime - b.startTime);
    //
    // Determine timing for all tasks (wall clock and execution times)
    //
    const allDuration = allEnd - allStart;
    const allDurationSeconds = allDuration / 1000;
    //
    // Do some calculations to determine what size timeline chart we need.
    //
    const maxWidth = _rushstack_terminal__WEBPACK_IMPORTED_MODULE_0__.PrintUtilities.getConsoleWidth() || TIMELINE_WIDTH;
    const chartWidth = maxWidth - longestNameLength - longestDurationLength - 4;
    //
    // Loop through all operations, assembling some statistics about operations and
    // phases, if applicable.
    //
    const busyCpus = [];
    function getOpenCPU(time) {
        const len = busyCpus.length;
        for (let i = 0; i < len; i++) {
            if (busyCpus[i] <= time) {
                return i;
            }
        }
        return len;
    }
    // Start with a newline
    terminal.writeLine('');
    terminal.writeLine('='.repeat(maxWidth));
    let hasCobuildSymbol = false;
    function getChartSymbol(record) {
        const { isExecuteByOtherCobuildRunner, status } = record;
        if (isExecuteByOtherCobuildRunner && COBUILD_REPORTABLE_STATUSES.has(status)) {
            hasCobuildSymbol = true;
            return 'C';
        }
        return TIMELINE_CHART_SYMBOLS[status];
    }
    for (const record of data) {
        const { startTime, endTime, durationString, name, status } = record;
        // Track busy CPUs
        const openCpu = getOpenCPU(startTime);
        busyCpus[openCpu] = endTime;
        // Build timeline chart
        const startIdx = Math.floor(((startTime - allStart) * chartWidth) / allDuration);
        const endIdx = Math.floor(((endTime - allStart) * chartWidth) / allDuration);
        const length = endIdx - startIdx + 1;
        const chart = _rushstack_terminal__WEBPACK_IMPORTED_MODULE_0__.Colorize.gray('-'.repeat(startIdx)) +
            TIMELINE_CHART_COLORIZER[status](getChartSymbol(record).repeat(length)) +
            _rushstack_terminal__WEBPACK_IMPORTED_MODULE_0__.Colorize.gray('-'.repeat(chartWidth - endIdx));
        terminal.writeLine(`${_rushstack_terminal__WEBPACK_IMPORTED_MODULE_0__.Colorize.cyan(name.padStart(longestNameLength))} ${chart} ${_rushstack_terminal__WEBPACK_IMPORTED_MODULE_0__.Colorize.white(durationString.padStart(longestDurationLength) + 's')}`);
    }
    terminal.writeLine('='.repeat(maxWidth));
    //
    // Format legend and summary areas
    //
    const usedCpus = busyCpus.length;
    const legend = [
        'LEGEND:',
        '  [#] Success  [!] Failed/warnings  [%] Skipped/cached/no-op',
        '',
        ''
    ];
    if (hasCobuildSymbol) {
        legend[2] = '  [C] Cobuild';
    }
    const summary = [
        `Total Work: ${workDuration.toFixed(1)}s`,
        `Wall Clock: ${allDurationSeconds.toFixed(1)}s`,
        `Max Parallelism Used: ${usedCpus}`,
        `Avg Parallelism Used: ${(workDuration / allDurationSeconds).toFixed(1)}`
    ];
    terminal.writeLine(legend[0] + summary[0].padStart(maxWidth - legend[0].length));
    terminal.writeLine(legend[1] + summary[1].padStart(maxWidth - legend[1].length));
    terminal.writeLine(legend[2] + summary[2].padStart(maxWidth - legend[2].length));
    terminal.writeLine(legend[3] + summary[3].padStart(maxWidth - legend[3].length));
    //
    // Include time-by-phase, if phases are enabled
    //
    if (durationByPhase.size > 0) {
        terminal.writeLine('BY PHASE:');
        let maxPhaseName = 16;
        for (const phase of durationByPhase.keys()) {
            const len = phase.name.length;
            if (len > maxPhaseName) {
                maxPhaseName = len;
            }
        }
        for (const [phase, duration] of durationByPhase.entries()) {
            const cachedDurationString = duration.cached
                ? `, from cache: ${duration.cached.toFixed(1)}s`
                : '';
            const durationString = `${duration.uncached.toFixed(1)}s${cachedDurationString}`;
            terminal.writeLine(`  ${_rushstack_terminal__WEBPACK_IMPORTED_MODULE_0__.Colorize.cyan(phase.name.padStart(maxPhaseName))} ${durationString}`);
        }
    }
    terminal.writeLine('');
}
//# sourceMappingURL=ConsoleTimelinePlugin.js.map

/***/ }

};
;
//# sourceMappingURL=ConsoleTimelinePlugin.js.map