UNPKG

@elastic/synthetics

Version:

Elastic synthetic monitoring agent

192 lines 7.05 kB
"use strict"; /** * MIT License * * Copyright (c) 2020-present, Elastic NV * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.stripAnsiCodes = exports.renderError = exports.serializeError = exports.highLightSource = exports.prepareError = void 0; const url_1 = require("url"); const path_1 = require("path"); const fs_1 = require("fs"); const util_1 = require("util"); const colors_1 = require("kleur/colors"); const code_frame_1 = require("@babel/code-frame"); const stack_utils_1 = __importDefault(require("stack-utils")); const stackUtils = new stack_utils_1.default({ internals: stack_utils_1.default.nodeInternals() }); const SYNTHETICS_PATH = (0, path_1.resolve)(__dirname, '..', '..'); const PW_CORE_PATH = require.resolve('playwright-core'); function prepareStackFrame(line) { const frame = stackUtils.parseLine(line); if (!frame) { return; } // ignore node internals if (frame.file?.startsWith('internal') || frame.file?.startsWith('node:')) { return; } // handle relative URLs let file = frame.file?.startsWith('file://') ? (0, url_1.fileURLToPath)(frame.file) : (0, path_1.resolve)(process.cwd(), frame.file); // ignore node_modules if (file.includes(`${path_1.sep}node_modules${path_1.sep}`)) { return; } // filter library and PW files if (!filterLibInternals(file)) { return; } // When we bundle the journeys, we store the absolute path of the journey // files and write the sourcemap relative to these files. When we try to // extract the sourcemap file location, the stacktrace will be relatively // resolved to these files which would be under `journeys` folder. So we strip // these extra `journeys` from the path to get the correct file location. if (frame.file?.includes('journeys/journeys')) { file = file.replace('journeys/journeys', 'journeys'); } return { file, line: frame.line || 0, column: frame.column || 0, function: frame.function, }; } function filterLibInternals(file) { // To ignore filtering the stack trace on tests if (process.env.TEST_OVERRIDE) { return true; } if (file.startsWith(SYNTHETICS_PATH)) { return false; } // should have been filtered by node_modules, but just in case if (file.startsWith(PW_CORE_PATH)) { return false; } } function constructStackFromFrames(frames) { const stackLines = []; for (const frame of frames) { stackLines.push(` at ${frame.function ? frame.function + ' ' : ''}(${frame.file}:${frame.line}:${frame.column})`); } return stackLines; } function prepareError(error) { const stack = error.stack; const lines = stack.split('\n'); let startAt = lines.findIndex(line => line.startsWith(' at ')); if (startAt === -1) { startAt = lines.length; } const message = lines.slice(0, startAt).join('\n'); const stackLines = lines.slice(startAt); // figure out the location of the journey/step that throws the error and // correct stack line corresponding to that error const stackFrames = []; for (const line of stackLines) { const frame = prepareStackFrame(line); if (!frame || !frame.file) { continue; } stackFrames.push(frame); } let location; if (stackFrames.length) { const frame = stackFrames[0]; location = { file: frame.file, column: frame.column || 0, line: frame.line || 0, }; } return { message, stack: constructStackFromFrames(stackFrames).join('\n'), location, }; } exports.prepareError = prepareError; function highLightSource(location) { if (!location) { return; } try { const source = (0, fs_1.readFileSync)(location.file, 'utf-8'); const code = (0, code_frame_1.codeFrameColumns)(source, { start: location }, { highlightCode: true }); return code; } catch (_) { // ignore error } } exports.highLightSource = highLightSource; // serializeError prefers receiving proper Errors, but since at runtime // non Error exceptions can be thrown, it tolerates though. The // redundant type Error | any expresses that. function serializeError(error, highlightCode = true) { if (!(error instanceof Error) || !error.stack) { return { message: `thrown: ${(0, util_1.inspect)(error)}` }; } const testErr = { message: error.message }; const { message, stack, location } = prepareError(error); testErr.message = message; if (stack) { testErr.stack = stack; } if (location && highlightCode) { testErr.location = location; testErr.source = highLightSource(testErr.location); } return testErr; } exports.serializeError = serializeError; function renderError(error) { const summary = []; // push empty string to add a new line before rendering error summary.push(''); summary.push(error.message); if (error.source) { summary.push(''); summary.push(error.source); } if (error.stack) { summary.push(''); summary.push((0, colors_1.gray)(error.stack)); } summary.join(''); return summary.join('\n'); } exports.renderError = renderError; // strip color codes and ansi escape codes const ansiRegex = new RegExp([ '[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)', '(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))', ].join('|'), 'g'); function stripAnsiCodes(msg = '') { return msg.replace(ansiRegex, ''); } exports.stripAnsiCodes = stripAnsiCodes; //# sourceMappingURL=reporter-util.js.map