UNPKG

5.87 kBJavaScriptView Raw
1"use strict";
2var __importDefault = (this && this.__importDefault) || function (mod) {
3 return (mod && mod.__esModule) ? mod : { "default": mod };
4};
5Object.defineProperty(exports, "__esModule", { value: true });
6const fs_1 = __importDefault(require("fs"));
7const loglevel_1 = __importDefault(require("loglevel"));
8const util_1 = __importDefault(require("util"));
9const chalk_1 = __importDefault(require("chalk"));
10const loglevel_plugin_prefix_1 = __importDefault(require("loglevel-plugin-prefix"));
11const strip_ansi_1 = __importDefault(require("strip-ansi"));
12loglevel_plugin_prefix_1.default.reg(loglevel_1.default);
13const DEFAULT_LEVEL = process.env.WDIO_DEBUG
14 ? 'trace'
15 : 'info';
16const COLORS = {
17 error: 'red',
18 warn: 'yellow',
19 info: 'cyanBright',
20 debug: 'green',
21 trace: 'cyan'
22};
23const matches = {
24 COMMAND: 'COMMAND',
25 DATA: 'DATA',
26 RESULT: 'RESULT'
27};
28const SERIALIZERS = [{
29 /**
30 * display error stack
31 */
32 matches: (err) => err instanceof Error,
33 serialize: (err) => err.stack
34 }, {
35 /**
36 * color commands blue
37 */
38 matches: (log) => log === matches.COMMAND,
39 serialize: (log) => chalk_1.default.magenta(log)
40 }, {
41 /**
42 * color data yellow
43 */
44 matches: (log) => log === matches.DATA,
45 serialize: (log) => chalk_1.default.yellow(log)
46 }, {
47 /**
48 * color result cyan
49 */
50 matches: (log) => log === matches.RESULT,
51 serialize: (log) => chalk_1.default.cyan(log)
52 }];
53const loggers = loglevel_1.default.getLoggers();
54let logLevelsConfig = {};
55const logCache = new Set();
56let logFile;
57const originalFactory = loglevel_1.default.methodFactory;
58const wdioLoggerMethodFactory = function (methodName, logLevel, loggerName) {
59 const rawMethod = originalFactory(methodName, logLevel, loggerName);
60 return (...args) => {
61 /**
62 * create logFile lazily
63 */
64 if (!logFile && process.env.WDIO_LOG_PATH) {
65 logFile = fs_1.default.createWriteStream(process.env.WDIO_LOG_PATH);
66 }
67 /**
68 * split `prefixer: value` sting to `prefixer: ` and `value`
69 * so that SERIALIZERS can match certain string
70 */
71 const match = Object.values(matches).filter(x => args[0].endsWith(`: ${x}`))[0];
72 if (match) {
73 const prefixStr = args.shift().slice(0, -match.length - 1);
74 args.unshift(prefixStr, match);
75 }
76 args = args.map((arg) => {
77 for (const s of SERIALIZERS) {
78 if (s.matches(arg)) {
79 return s.serialize(arg);
80 }
81 }
82 return arg;
83 });
84 const logText = (0, strip_ansi_1.default)(`${util_1.default.format.apply(this, args)}\n`);
85 if (logFile && logFile.writable) {
86 /**
87 * empty logging cache if stuff got logged before
88 */
89 if (logCache.size) {
90 logCache.forEach((log) => {
91 if (logFile) {
92 logFile.write(log);
93 }
94 });
95 logCache.clear();
96 }
97 return logFile.write(logText);
98 }
99 logCache.add(logText);
100 rawMethod(...args);
101 };
102};
103function getLogger(name) {
104 /**
105 * check if logger was already initiated
106 */
107 if (loggers[name]) {
108 return loggers[name];
109 }
110 let logLevel = (process.env.WDIO_LOG_LEVEL || DEFAULT_LEVEL);
111 const logLevelName = getLogLevelName(name);
112 if (logLevelsConfig[logLevelName]) {
113 logLevel = logLevelsConfig[logLevelName];
114 }
115 loggers[name] = loglevel_1.default.getLogger(name);
116 loggers[name].setLevel(logLevel);
117 loggers[name].methodFactory = wdioLoggerMethodFactory;
118 loglevel_plugin_prefix_1.default.apply(loggers[name], {
119 template: '%t %l %n:',
120 timestampFormatter: (date) => chalk_1.default.gray(date.toISOString()),
121 levelFormatter: (level) => chalk_1.default[COLORS[level]](level.toUpperCase()),
122 nameFormatter: (name) => chalk_1.default.whiteBright(name)
123 });
124 return loggers[name];
125}
126exports.default = getLogger;
127/**
128 * Wait for writable stream to be flushed.
129 * Calling this prevents part of the logs in the very env to be lost.
130 */
131getLogger.waitForBuffer = async () => new Promise(resolve => {
132 // @ts-ignore
133 if (logFile && Array.isArray(logFile.writableBuffer) && logFile.writableBuffer.length !== 0) {
134 return setTimeout(async () => {
135 await getLogger.waitForBuffer();
136 resolve();
137 }, 20);
138 }
139 resolve();
140});
141getLogger.setLevel = (name, level) => loggers[name].setLevel(level);
142getLogger.clearLogger = () => {
143 if (logFile) {
144 logFile.end();
145 }
146 logFile = null;
147};
148getLogger.setLogLevelsConfig = (logLevels = {}, wdioLogLevel = DEFAULT_LEVEL) => {
149 /**
150 * set log level
151 */
152 if (process.env.WDIO_LOG_LEVEL === undefined) {
153 process.env.WDIO_LOG_LEVEL = wdioLogLevel;
154 }
155 logLevelsConfig = {};
156 /**
157 * build logLevelsConfig object
158 */
159 Object.entries(logLevels).forEach(([logName, logLevel]) => {
160 const logLevelName = getLogLevelName(logName);
161 logLevelsConfig[logLevelName] = logLevel;
162 });
163 /**
164 * set log level for each logger
165 */
166 Object.keys(loggers).forEach(logName => {
167 const logLevelName = getLogLevelName(logName);
168 /**
169 * either apply log level from logLevels object or use global logLevel
170 */
171 const logLevel = typeof logLevelsConfig[logLevelName] !== 'undefined' ? logLevelsConfig[logLevelName] : process.env.WDIO_LOG_LEVEL;
172 loggers[logName].setLevel(logLevel);
173 });
174};
175const getLogLevelName = (logName) => logName.split(':').shift();