1 |
|
2 | import fs from "node:fs";
|
3 | import util from "node:util";
|
4 | import log from "loglevel";
|
5 | import chalk from "chalk";
|
6 | import prefix from "loglevel-plugin-prefix";
|
7 | import ansiStrip from "strip-ansi";
|
8 | prefix.reg(log);
|
9 | var DEFAULT_LEVEL = process.env.WDIO_DEBUG ? "trace" : "info";
|
10 | var COLORS = {
|
11 | error: "red",
|
12 | warn: "yellow",
|
13 | info: "cyanBright",
|
14 | debug: "green",
|
15 | trace: "cyan",
|
16 | progress: "magenta"
|
17 | };
|
18 | var matches = {
|
19 | COMMAND: "COMMAND",
|
20 | BIDICOMMAND: "BIDI COMMAND",
|
21 | DATA: "DATA",
|
22 | RESULT: "RESULT",
|
23 | BIDIRESULT: "BIDI RESULT"
|
24 | };
|
25 | var SERIALIZERS = [{
|
26 | |
27 |
|
28 |
|
29 | matches: (err) => err instanceof Error,
|
30 | serialize: (err) => err.stack
|
31 | }, {
|
32 | |
33 |
|
34 |
|
35 | matches: (log2) => log2 === matches.COMMAND || log2 === matches.BIDICOMMAND,
|
36 | serialize: (log2) => chalk.magenta(log2)
|
37 | }, {
|
38 | |
39 |
|
40 |
|
41 | matches: (log2) => log2 === matches.DATA,
|
42 | serialize: (log2) => chalk.yellow(log2)
|
43 | }, {
|
44 | |
45 |
|
46 |
|
47 | matches: (log2) => log2 === matches.RESULT || log2 === matches.BIDIRESULT,
|
48 | serialize: (log2) => chalk.cyan(log2)
|
49 | }];
|
50 | var loggers = log.getLoggers();
|
51 | var logLevelsConfig = {};
|
52 | var logCache = new Set();
|
53 | var logFile;
|
54 | var originalFactory = log.methodFactory;
|
55 | var wdioLoggerMethodFactory = function(methodName, logLevel, loggerName) {
|
56 | const rawMethod = originalFactory(methodName, logLevel, loggerName);
|
57 | return (...args) => {
|
58 | if (!logFile && process.env.WDIO_LOG_PATH) {
|
59 | logFile = fs.createWriteStream(process.env.WDIO_LOG_PATH);
|
60 | }
|
61 | const match = Object.values(matches).filter((x) => args[0].endsWith(`: ${x}`))[0];
|
62 | if (match) {
|
63 | const prefixStr = args.shift().slice(0, -match.length - 1);
|
64 | args.unshift(prefixStr, match);
|
65 | }
|
66 | args = args.map((arg) => {
|
67 | for (const s of SERIALIZERS) {
|
68 | if (s.matches(arg)) {
|
69 | return s.serialize(arg);
|
70 | }
|
71 | }
|
72 | return arg;
|
73 | });
|
74 | const logText = ansiStrip(`${util.format.apply(this, args)}
|
75 | `);
|
76 | if (logFile && logFile.writable) {
|
77 | if (logCache.size) {
|
78 | logCache.forEach((log2) => {
|
79 | if (logFile) {
|
80 | logFile.write(log2);
|
81 | }
|
82 | });
|
83 | logCache.clear();
|
84 | }
|
85 | if (!logsContainInitPackageError(logText)) {
|
86 | return logFile.write(logText);
|
87 | }
|
88 | logFile.write(logText);
|
89 | }
|
90 | logCache.add(logText);
|
91 | rawMethod(...args);
|
92 | };
|
93 | };
|
94 | var progress = function(data) {
|
95 | if (process.stdout.isTTY && this.getLevel() <= log.levels.INFO) {
|
96 | const level = "progress";
|
97 | const timestampFormatter = chalk.gray(( new Date()).toISOString());
|
98 | const levelFormatter = chalk[COLORS[level]](level.toUpperCase());
|
99 | const nameFormatter = chalk.whiteBright(this.name);
|
100 | const _data = data.length > 0 ? `${timestampFormatter} ${levelFormatter} ${nameFormatter}: ${data}` : "\r\x1B[K\x1B[?25h";
|
101 | process.stdout.write("\x1B[?25l");
|
102 | process.stdout.write(`${_data}\r`);
|
103 | }
|
104 | };
|
105 | function getLogger(name) {
|
106 | if (loggers[name]) {
|
107 | return loggers[name];
|
108 | }
|
109 | let logLevel = process.env.WDIO_LOG_LEVEL || DEFAULT_LEVEL;
|
110 | const logLevelName = getLogLevelName(name);
|
111 | if (logLevelsConfig[logLevelName]) {
|
112 | logLevel = logLevelsConfig[logLevelName];
|
113 | }
|
114 | loggers[name] = log.getLogger(name);
|
115 | loggers[name].setLevel(logLevel);
|
116 | loggers[name].methodFactory = wdioLoggerMethodFactory;
|
117 | loggers[name].progress = progress;
|
118 | prefix.apply(loggers[name], {
|
119 | template: "%t %l %n:",
|
120 | timestampFormatter: (date) => chalk.gray(date.toISOString()),
|
121 | levelFormatter: (level) => chalk[COLORS[level]](level.toUpperCase()),
|
122 | nameFormatter: (name2) => chalk.whiteBright(name2)
|
123 | });
|
124 | return loggers[name];
|
125 | }
|
126 | getLogger.waitForBuffer = async () => new Promise((resolve) => {
|
127 | if (logFile && Array.isArray(logFile.writableBuffer) && logFile.writableBuffer.length !== 0) {
|
128 | return setTimeout(async () => {
|
129 | await getLogger.waitForBuffer();
|
130 | resolve();
|
131 | }, 20);
|
132 | }
|
133 | resolve();
|
134 | });
|
135 | getLogger.setLevel = (name, level) => loggers[name].setLevel(level);
|
136 | getLogger.clearLogger = () => {
|
137 | if (logFile) {
|
138 | logFile.end();
|
139 | }
|
140 | logFile = null;
|
141 | };
|
142 | getLogger.setLogLevelsConfig = (logLevels = {}, wdioLogLevel = DEFAULT_LEVEL) => {
|
143 | if (process.env.WDIO_LOG_LEVEL === void 0) {
|
144 | process.env.WDIO_LOG_LEVEL = wdioLogLevel;
|
145 | }
|
146 | logLevelsConfig = {};
|
147 | Object.entries(logLevels).forEach(([logName, logLevel]) => {
|
148 | const logLevelName = getLogLevelName(logName);
|
149 | logLevelsConfig[logLevelName] = logLevel;
|
150 | });
|
151 | Object.keys(loggers).forEach((logName) => {
|
152 | const logLevelName = getLogLevelName(logName);
|
153 | const logLevel = typeof logLevelsConfig[logLevelName] !== "undefined" ? logLevelsConfig[logLevelName] : process.env.WDIO_LOG_LEVEL;
|
154 | loggers[logName].setLevel(logLevel);
|
155 | });
|
156 | };
|
157 | var getLogLevelName = (logName) => logName.split(":").shift();
|
158 | function logsContainInitPackageError(logText) {
|
159 | return ERROR_LOG_VALIDATOR.every((pattern) => logText.includes(pattern));
|
160 | }
|
161 | var ERROR_LOG_VALIDATOR = [
|
162 | "Couldn't find plugin",
|
163 | "neither as wdio scoped package",
|
164 | "nor as community package",
|
165 | "Please make sure you have it installed"
|
166 | ];
|
167 | export {
|
168 | getLogger as default
|
169 | };
|