1 | ;
|
2 | /*
|
3 | * Copyright (c) 2018, salesforce.com, inc.
|
4 | * All rights reserved.
|
5 | * SPDX-License-Identifier: BSD-3-Clause
|
6 | * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
7 | */
|
8 | Object.defineProperty(exports, "__esModule", { value: true });
|
9 | // tslint:disable-next-line:ordered-imports
|
10 | // @ts-ignore No typings available for our copy of bunyan
|
11 | const Bunyan = require("@salesforce/bunyan");
|
12 | const kit_1 = require("@salesforce/kit");
|
13 | const ts_types_1 = require("@salesforce/ts-types");
|
14 | const Debug = require("debug");
|
15 | const events_1 = require("events");
|
16 | const os = require("os");
|
17 | const path = require("path");
|
18 | const stream_1 = require("stream");
|
19 | const global_1 = require("./global");
|
20 | const sfdxError_1 = require("./sfdxError");
|
21 | const fs_1 = require("./util/fs");
|
22 | /**
|
23 | * Standard `Logger` levels.
|
24 | *
|
25 | * **See** {@link https://github.com/forcedotcom/node-bunyan#levels|Bunyan Levels}
|
26 | */
|
27 | var LoggerLevel;
|
28 | (function (LoggerLevel) {
|
29 | LoggerLevel[LoggerLevel["TRACE"] = 10] = "TRACE";
|
30 | LoggerLevel[LoggerLevel["DEBUG"] = 20] = "DEBUG";
|
31 | LoggerLevel[LoggerLevel["INFO"] = 30] = "INFO";
|
32 | LoggerLevel[LoggerLevel["WARN"] = 40] = "WARN";
|
33 | LoggerLevel[LoggerLevel["ERROR"] = 50] = "ERROR";
|
34 | LoggerLevel[LoggerLevel["FATAL"] = 60] = "FATAL";
|
35 | })(LoggerLevel = exports.LoggerLevel || (exports.LoggerLevel = {}));
|
36 | /**
|
37 | * A logging abstraction powered by {@link https://github.com/forcedotcom/node-bunyan|Bunyan} that provides both a default
|
38 | * logger configuration that will log to `sfdx.log`, and a way to create custom loggers based on the same foundation.
|
39 | *
|
40 | * ```
|
41 | * // Gets the root sfdx logger
|
42 | * const logger = await Logger.root();
|
43 | *
|
44 | * // Creates a child logger of the root sfdx logger with custom fields applied
|
45 | * const childLogger = await Logger.child('myRootChild', {tag: 'value'});
|
46 | *
|
47 | * // Creates a custom logger unaffiliated with the root logger
|
48 | * const myCustomLogger = new Logger('myCustomLogger');
|
49 | *
|
50 | * // Creates a child of a custom logger unaffiliated with the root logger with custom fields applied
|
51 | * const myCustomChildLogger = myCustomLogger.child('myCustomChild', {tag: 'value'});
|
52 | * ```
|
53 | * **See** https://github.com/forcedotcom/node-bunyan
|
54 | *
|
55 | * **See** https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_cli_log_messages.htm
|
56 | */
|
57 | class Logger {
|
58 | /**
|
59 | * Constructs a new `Logger`.
|
60 | *
|
61 | * @param optionsOrName A set of `LoggerOptions` or name to use with the default options.
|
62 | *
|
63 | * **Throws** *{@link SfdxError}{ name: 'RedundantRootLogger' }* More than one attempt is made to construct the root
|
64 | * `Logger`.
|
65 | */
|
66 | constructor(optionsOrName) {
|
67 | this.uncaughtExceptionHandler = (err) => {
|
68 | // W-7558552
|
69 | // Only log uncaught exceptions in root logger
|
70 | if (this === Logger.rootLogger) {
|
71 | // log the exception
|
72 | // FIXME: good chance this won't be logged because
|
73 | // process.exit was called before this is logged
|
74 | // https://github.com/trentm/node-bunyan/issues/95
|
75 | this.fatal(err);
|
76 | }
|
77 | };
|
78 | this.exitHandler = () => {
|
79 | this.close();
|
80 | };
|
81 | let options;
|
82 | if (typeof optionsOrName === 'string') {
|
83 | options = {
|
84 | name: optionsOrName,
|
85 | level: Logger.DEFAULT_LEVEL,
|
86 | serializers: Bunyan.stdSerializers
|
87 | };
|
88 | }
|
89 | else {
|
90 | options = optionsOrName;
|
91 | }
|
92 | if (Logger.rootLogger && options.name === Logger.ROOT_NAME) {
|
93 | throw new sfdxError_1.SfdxError('RedundantRootLogger');
|
94 | }
|
95 | this.bunyan = new Bunyan(options);
|
96 | this.bunyan.name = options.name;
|
97 | this.bunyan.filters = [];
|
98 | this.bunyan.streams = [];
|
99 | // all SFDX loggers must filter sensitive data
|
100 | this.addFilter((...args) => _filter(...args));
|
101 | if (global_1.Global.getEnvironmentMode() !== global_1.Mode.TEST) {
|
102 | Logger.lifecycle.on('uncaughtException', this.uncaughtExceptionHandler);
|
103 | Logger.lifecycle.on('exit', this.exitHandler);
|
104 | }
|
105 | this.trace(`Created '${this.getName()}' logger instance`);
|
106 | }
|
107 | /**
|
108 | * Gets the root logger with the default level and file stream.
|
109 | */
|
110 | static async root() {
|
111 | if (this.rootLogger) {
|
112 | return this.rootLogger;
|
113 | }
|
114 | const rootLogger = (this.rootLogger = new Logger(Logger.ROOT_NAME).setLevel());
|
115 | // disable log file writing, if applicable
|
116 | if (process.env.SFDX_DISABLE_LOG_FILE !== 'true' && global_1.Global.getEnvironmentMode() !== global_1.Mode.TEST) {
|
117 | await rootLogger.addLogFileStream(global_1.Global.LOG_FILE_PATH);
|
118 | }
|
119 | // The debug library does this for you, but no point setting up the stream if it isn't there
|
120 | if (process.env.DEBUG) {
|
121 | const debuggers = {};
|
122 | debuggers.core = Debug(`${rootLogger.getName()}:core`);
|
123 | rootLogger.addStream({
|
124 | name: 'debug',
|
125 | stream: new stream_1.Writable({
|
126 | write: (chunk, encoding, next) => {
|
127 | const json = kit_1.parseJsonMap(chunk.toString());
|
128 | let debuggerName = 'core';
|
129 | if (ts_types_1.isString(json.log)) {
|
130 | debuggerName = json.log;
|
131 | if (!debuggers[debuggerName]) {
|
132 | debuggers[debuggerName] = Debug(`${rootLogger.getName()}:${debuggerName}`);
|
133 | }
|
134 | }
|
135 | const level = LoggerLevel[ts_types_1.ensureNumber(json.level)];
|
136 | ts_types_1.ensure(debuggers[debuggerName])(`${level} ${json.msg}`);
|
137 | next();
|
138 | }
|
139 | }),
|
140 | // Consume all levels
|
141 | level: 0
|
142 | });
|
143 | }
|
144 | return rootLogger;
|
145 | }
|
146 | /**
|
147 | * Destroys the root `Logger`.
|
148 | *
|
149 | * @ignore
|
150 | */
|
151 | static destroyRoot() {
|
152 | if (this.rootLogger) {
|
153 | this.rootLogger.close();
|
154 | this.rootLogger = undefined;
|
155 | }
|
156 | }
|
157 | /**
|
158 | * Create a child of the root logger, inheriting this instance's configuration such as `level`, `streams`, etc.
|
159 | *
|
160 | * @param name The name of the child logger.
|
161 | * @param fields Additional fields included in all log lines.
|
162 | */
|
163 | static async child(name, fields) {
|
164 | return (await Logger.root()).child(name, fields);
|
165 | }
|
166 | /**
|
167 | * Gets a numeric `LoggerLevel` value by string name.
|
168 | *
|
169 | * @param {string} levelName The level name to convert to a `LoggerLevel` enum value.
|
170 | *
|
171 | * **Throws** *{@link SfdxError}{ name: 'UnrecognizedLoggerLevelName' }* The level name was not case-insensitively recognized as a valid `LoggerLevel` value.
|
172 | * @see {@Link LoggerLevel}
|
173 | */
|
174 | static getLevelByName(levelName) {
|
175 | levelName = levelName.toUpperCase();
|
176 | if (!ts_types_1.isKeyOf(LoggerLevel, levelName)) {
|
177 | throw new sfdxError_1.SfdxError('UnrecognizedLoggerLevelName');
|
178 | }
|
179 | return LoggerLevel[levelName];
|
180 | }
|
181 | /**
|
182 | * Adds a stream.
|
183 | *
|
184 | * @param stream The stream configuration to add.
|
185 | * @param defaultLevel The default level of the stream.
|
186 | */
|
187 | addStream(stream, defaultLevel) {
|
188 | this.bunyan.addStream(stream, defaultLevel);
|
189 | }
|
190 | /**
|
191 | * Adds a file stream to this logger. Resolved or rejected upon completion of the addition.
|
192 | *
|
193 | * @param logFile The path to the log file. If it doesn't exist it will be created.
|
194 | */
|
195 | async addLogFileStream(logFile) {
|
196 | try {
|
197 | // Check if we have write access to the log file (i.e., we created it already)
|
198 | await fs_1.fs.access(logFile, fs_1.fs.constants.W_OK);
|
199 | }
|
200 | catch (err1) {
|
201 | try {
|
202 | await fs_1.fs.mkdirp(path.dirname(logFile), {
|
203 | mode: fs_1.fs.DEFAULT_USER_DIR_MODE
|
204 | });
|
205 | }
|
206 | catch (err2) {
|
207 | // noop; directory exists already
|
208 | }
|
209 | try {
|
210 | await fs_1.fs.writeFile(logFile, '', { mode: fs_1.fs.DEFAULT_USER_FILE_MODE });
|
211 | }
|
212 | catch (err3) {
|
213 | throw sfdxError_1.SfdxError.wrap(err3);
|
214 | }
|
215 | }
|
216 | // avoid multiple streams to same log file
|
217 | if (!this.bunyan.streams.find(
|
218 | // tslint:disable-next-line:no-any No bunyan typings
|
219 | (stream) => stream.type === 'file' && stream.path === logFile)) {
|
220 | // TODO: rotating-file
|
221 | // https://github.com/trentm/node-bunyan#stream-type-rotating-file
|
222 | this.addStream({
|
223 | type: 'file',
|
224 | path: logFile,
|
225 | level: this.bunyan.level()
|
226 | });
|
227 | }
|
228 | }
|
229 | /**
|
230 | * Gets the name of this logger.
|
231 | */
|
232 | getName() {
|
233 | return this.bunyan.name;
|
234 | }
|
235 | /**
|
236 | * Gets the current level of this logger.
|
237 | */
|
238 | getLevel() {
|
239 | return this.bunyan.level();
|
240 | }
|
241 | /**
|
242 | * Set the logging level of all streams for this logger. If a specific `level` is not provided, this method will
|
243 | * attempt to read it from the environment variable `SFDX_LOG_LEVEL`, and if not found,
|
244 | * {@link Logger.DEFAULT_LOG_LEVEL} will be used instead. For convenience `this` object is returned.
|
245 | *
|
246 | * @param {LoggerLevelValue} [level] The logger level.
|
247 | *
|
248 | * **Throws** *{@link SfdxError}{ name: 'UnrecognizedLoggerLevelName' }* A value of `level` read from `SFDX_LOG_LEVEL`
|
249 | * was invalid.
|
250 | *
|
251 | * ```
|
252 | * // Sets the level from the environment or default value
|
253 | * logger.setLevel()
|
254 | *
|
255 | * // Set the level from the INFO enum
|
256 | * logger.setLevel(LoggerLevel.INFO)
|
257 | *
|
258 | * // Sets the level case-insensitively from a string value
|
259 | * logger.setLevel(Logger.getLevelByName('info'))
|
260 | * ```
|
261 | */
|
262 | setLevel(level) {
|
263 | if (level == null) {
|
264 | level = process.env.SFDX_LOG_LEVEL ? Logger.getLevelByName(process.env.SFDX_LOG_LEVEL) : Logger.DEFAULT_LEVEL;
|
265 | }
|
266 | this.bunyan.level(level);
|
267 | return this;
|
268 | }
|
269 | /**
|
270 | * Gets the underlying Bunyan logger.
|
271 | */
|
272 | // tslint:disable-next-line:no-any
|
273 | getBunyanLogger() {
|
274 | return this.bunyan;
|
275 | }
|
276 | /**
|
277 | * Compares the requested log level with the current log level. Returns true if
|
278 | * the requested log level is greater than or equal to the current log level.
|
279 | *
|
280 | * @param level The requested log level to compare against the currently set log level.
|
281 | */
|
282 | shouldLog(level) {
|
283 | if (typeof level === 'string') {
|
284 | level = Bunyan.levelFromName(level);
|
285 | }
|
286 | return level >= this.getLevel();
|
287 | }
|
288 | /**
|
289 | * Use in-memory logging for this logger instance instead of any parent streams. Useful for testing.
|
290 | * For convenience this object is returned.
|
291 | *
|
292 | * **WARNING: This cannot be undone for this logger instance.**
|
293 | */
|
294 | useMemoryLogging() {
|
295 | this.bunyan.streams = [];
|
296 | this.bunyan.ringBuffer = new Bunyan.RingBuffer({ limit: 5000 });
|
297 | this.addStream({
|
298 | type: 'raw',
|
299 | stream: this.bunyan.ringBuffer,
|
300 | level: this.bunyan.level()
|
301 | });
|
302 | return this;
|
303 | }
|
304 | /**
|
305 | * Gets an array of log line objects. Each element is an object that corresponds to a log line.
|
306 | */
|
307 | getBufferedRecords() {
|
308 | if (this.bunyan.ringBuffer) {
|
309 | return this.bunyan.ringBuffer.records;
|
310 | }
|
311 | return [];
|
312 | }
|
313 | /**
|
314 | * Reads a text blob of all the log lines contained in memory or the log file.
|
315 | */
|
316 | readLogContentsAsText() {
|
317 | if (this.bunyan.ringBuffer) {
|
318 | return this.getBufferedRecords().reduce((accum, line) => {
|
319 | accum += JSON.stringify(line) + os.EOL;
|
320 | return accum;
|
321 | }, '');
|
322 | }
|
323 | else {
|
324 | let content = '';
|
325 | // tslint:disable-next-line:no-any No bunyan typings
|
326 | this.bunyan.streams.forEach(async (stream) => {
|
327 | if (stream.type === 'file') {
|
328 | content += await fs_1.fs.readFile(stream.path, 'utf8');
|
329 | }
|
330 | });
|
331 | return content;
|
332 | }
|
333 | }
|
334 | /**
|
335 | * Adds a filter to be applied to all logged messages.
|
336 | *
|
337 | * @param filter A function with signature `(...args: any[]) => any[]` that transforms log message arguments.
|
338 | */
|
339 | addFilter(filter) {
|
340 | // tslint:disable-line:no-any
|
341 | if (!this.bunyan.filters) {
|
342 | this.bunyan.filters = [];
|
343 | }
|
344 | this.bunyan.filters.push(filter);
|
345 | }
|
346 | /**
|
347 | * Close the logger, including any streams, and remove all listeners.
|
348 | *
|
349 | * @param fn A function with signature `(stream: LoggerStream) => void` to call for each stream with
|
350 | * the stream as an arg.
|
351 | */
|
352 | close(fn) {
|
353 | if (this.bunyan.streams) {
|
354 | try {
|
355 | this.bunyan.streams.forEach((entry) => {
|
356 | if (fn) {
|
357 | fn(entry);
|
358 | }
|
359 | // close file streams, flush buffer to disk
|
360 | if (entry.type === 'file' && entry.stream && ts_types_1.isFunction(entry.stream.end)) {
|
361 | entry.stream.end();
|
362 | }
|
363 | });
|
364 | }
|
365 | finally {
|
366 | Logger.lifecycle.removeListener('uncaughtException', this.uncaughtExceptionHandler);
|
367 | Logger.lifecycle.removeListener('exit', this.exitHandler);
|
368 | }
|
369 | }
|
370 | }
|
371 | /**
|
372 | * Create a child logger, typically to add a few log record fields. For convenience this object is returned.
|
373 | *
|
374 | * @param name The name of the child logger that is emitted w/ log line as `log:<name>`.
|
375 | * @param fields Additional fields included in all log lines for the child logger.
|
376 | */
|
377 | child(name, fields = {}) {
|
378 | if (!name) {
|
379 | throw new sfdxError_1.SfdxError('LoggerNameRequired');
|
380 | }
|
381 | fields.log = name;
|
382 | const child = new Logger(name);
|
383 | // only support including additional fields on log line (no config)
|
384 | child.bunyan = this.bunyan.child(fields, true);
|
385 | child.bunyan.name = name;
|
386 | child.bunyan.filters = this.bunyan.filters;
|
387 | this.trace(`Setup child '${name}' logger instance`);
|
388 | return child;
|
389 | }
|
390 | /**
|
391 | * Add a field to all log lines for this logger. For convenience `this` object is returned.
|
392 | *
|
393 | * @param name The name of the field to add.
|
394 | * @param value The value of the field to be logged.
|
395 | */
|
396 | addField(name, value) {
|
397 | this.bunyan.fields[name] = value;
|
398 | return this;
|
399 | }
|
400 | /**
|
401 | * Logs at `trace` level with filtering applied. For convenience `this` object is returned.
|
402 | *
|
403 | * @param args Any number of arguments to be logged.
|
404 | */
|
405 | // tslint:disable-next-line:no-any
|
406 | trace(...args) {
|
407 | this.bunyan.trace(this.applyFilters(LoggerLevel.TRACE, ...args));
|
408 | return this;
|
409 | }
|
410 | /**
|
411 | * Logs at `debug` level with filtering applied. For convenience `this` object is returned.
|
412 | *
|
413 | * @param args Any number of arguments to be logged.
|
414 | */
|
415 | debug(...args) {
|
416 | this.bunyan.debug(this.applyFilters(LoggerLevel.DEBUG, ...args));
|
417 | return this;
|
418 | }
|
419 | /**
|
420 | * Logs at `debug` level with filtering applied.
|
421 | *
|
422 | * @param cb A callback that returns on array objects to be logged.
|
423 | */
|
424 | debugCallback(cb) {
|
425 | if (this.getLevel() === LoggerLevel.DEBUG || process.env.DEBUG) {
|
426 | const result = cb();
|
427 | if (ts_types_1.isArray(result)) {
|
428 | this.bunyan.debug(this.applyFilters(LoggerLevel.DEBUG, ...result));
|
429 | }
|
430 | else {
|
431 | this.bunyan.debug(this.applyFilters(LoggerLevel.DEBUG, ...[result]));
|
432 | }
|
433 | }
|
434 | }
|
435 | /**
|
436 | * Logs at `info` level with filtering applied. For convenience `this` object is returned.
|
437 | *
|
438 | * @param args Any number of arguments to be logged.
|
439 | */
|
440 | info(...args) {
|
441 | this.bunyan.info(this.applyFilters(LoggerLevel.INFO, ...args));
|
442 | return this;
|
443 | }
|
444 | /**
|
445 | * Logs at `warn` level with filtering applied. For convenience `this` object is returned.
|
446 | *
|
447 | * @param args Any number of arguments to be logged.
|
448 | */
|
449 | warn(...args) {
|
450 | this.bunyan.warn(this.applyFilters(LoggerLevel.WARN, ...args));
|
451 | return this;
|
452 | }
|
453 | /**
|
454 | * Logs at `error` level with filtering applied. For convenience `this` object is returned.
|
455 | *
|
456 | * @param args Any number of arguments to be logged.
|
457 | */
|
458 | error(...args) {
|
459 | this.bunyan.error(this.applyFilters(LoggerLevel.ERROR, ...args));
|
460 | return this;
|
461 | }
|
462 | /**
|
463 | * Logs at `fatal` level with filtering applied. For convenience `this` object is returned.
|
464 | *
|
465 | * @param args Any number of arguments to be logged.
|
466 | */
|
467 | fatal(...args) {
|
468 | // always show fatal to stderr
|
469 | console.error(...args);
|
470 | this.bunyan.fatal(this.applyFilters(LoggerLevel.FATAL, ...args));
|
471 | return this;
|
472 | }
|
473 | applyFilters(logLevel, ...args) {
|
474 | if (this.shouldLog(logLevel)) {
|
475 | // tslint:disable-next-line:no-any No bunyan typings
|
476 | this.bunyan.filters.forEach((filter) => (args = filter(...args)));
|
477 | }
|
478 | return args && args.length === 1 ? args[0] : args;
|
479 | }
|
480 | }
|
481 | /**
|
482 | * The name of the root sfdx `Logger`.
|
483 | */
|
484 | Logger.ROOT_NAME = 'sfdx';
|
485 | /**
|
486 | * The default `LoggerLevel` when constructing new `Logger` instances.
|
487 | */
|
488 | Logger.DEFAULT_LEVEL = LoggerLevel.WARN;
|
489 | /**
|
490 | * A list of all lower case `LoggerLevel` names.
|
491 | *
|
492 | * **See** {@link LoggerLevel}
|
493 | */
|
494 | Logger.LEVEL_NAMES = Object.values(LoggerLevel)
|
495 | .filter(ts_types_1.isString)
|
496 | .map(v => v.toLowerCase());
|
497 | // Rollup all instance-specific process event listeners together to prevent global `MaxListenersExceededWarning`s.
|
498 | Logger.lifecycle = (() => {
|
499 | const events = new events_1.EventEmitter();
|
500 | events.setMaxListeners(0); // never warn on listener counts
|
501 | process.on('uncaughtException', err => events.emit('uncaughtException', err));
|
502 | process.on('exit', () => events.emit('exit'));
|
503 | return events;
|
504 | })();
|
505 | exports.Logger = Logger;
|
506 | // Ok to log clientid
|
507 | const FILTERED_KEYS = [
|
508 | 'sid',
|
509 | 'Authorization',
|
510 | // Any json attribute that contains the words "access" and "token" will have the attribute/value hidden
|
511 | { name: 'access_token', regex: 'access[^\'"]*token' },
|
512 | // Any json attribute that contains the words "refresh" and "token" will have the attribute/value hidden
|
513 | { name: 'refresh_token', regex: 'refresh[^\'"]*token' },
|
514 | 'clientsecret',
|
515 | // Any json attribute that contains the words "sfdx", "auth", and "url" will have the attribute/value hidden
|
516 | { name: 'sfdxauthurl', regex: 'sfdx[^\'"]*auth[^\'"]*url' }
|
517 | ];
|
518 | // SFDX code and plugins should never show tokens or connect app information in the logs
|
519 | const _filter = (...args) => {
|
520 | return args.map(arg => {
|
521 | if (ts_types_1.isArray(arg)) {
|
522 | return _filter(...arg);
|
523 | }
|
524 | if (arg) {
|
525 | let _arg;
|
526 | // Normalize all objects into a string. This include errors.
|
527 | if (arg instanceof Buffer) {
|
528 | _arg = '<Buffer>';
|
529 | }
|
530 | else if (ts_types_1.isObject(arg)) {
|
531 | _arg = JSON.stringify(arg);
|
532 | }
|
533 | else if (ts_types_1.isString(arg)) {
|
534 | _arg = arg;
|
535 | }
|
536 | else {
|
537 | _arg = '';
|
538 | }
|
539 | const HIDDEN = 'HIDDEN';
|
540 | FILTERED_KEYS.forEach((key) => {
|
541 | let expElement = key;
|
542 | let expName = key;
|
543 | // Filtered keys can be strings or objects containing regular expression components.
|
544 | if (ts_types_1.isPlainObject(key)) {
|
545 | expElement = key.regex;
|
546 | expName = key.name;
|
547 | }
|
548 | const hiddenAttrMessage = `"<${expName} - ${HIDDEN}>"`;
|
549 | // Match all json attribute values case insensitive: ex. {" Access*^&(*()^* Token " : " 45143075913458901348905 \n\t" ...}
|
550 | const regexTokens = new RegExp(`(['"][^'"]*${expElement}[^'"]*['"]\\s*:\\s*)['"][^'"]*['"]`, 'gi');
|
551 | _arg = _arg.replace(regexTokens, `$1${hiddenAttrMessage}`);
|
552 | // Match all key value attribute case insensitive: ex. {" key\t" : ' access_token ' , " value " : " dsafgasr431 " ....}
|
553 | const keyRegex = new RegExp(`(['"]\\s*key\\s*['"]\\s*:)\\s*['"]\\s*${expElement}\\s*['"]\\s*.\\s*['"]\\s*value\\s*['"]\\s*:\\s*['"]\\s*[^'"]*['"]`, 'gi');
|
554 | _arg = _arg.replace(keyRegex, `$1${hiddenAttrMessage}`);
|
555 | });
|
556 | // This is a jsforce message we are masking. This can be removed after the following pull request is committed
|
557 | // and pushed to a jsforce release.
|
558 | //
|
559 | // Looking For: "Refreshed access token = ..."
|
560 | // Related Jsforce pull requests:
|
561 | // https://github.com/jsforce/jsforce/pull/598
|
562 | // https://github.com/jsforce/jsforce/pull/608
|
563 | // https://github.com/jsforce/jsforce/pull/609
|
564 | const jsForceTokenRefreshRegEx = new RegExp('Refreshed(.*)access(.*)token(.*)=\\s*[^\'"\\s*]*');
|
565 | _arg = _arg.replace(jsForceTokenRefreshRegEx, `<refresh_token - ${HIDDEN}>`);
|
566 | _arg = _arg.replace(/sid=(.*)/, `sid=<${HIDDEN}>`);
|
567 | // return an object if an object was logged; otherwise return the filtered string.
|
568 | return ts_types_1.isObject(arg) ? kit_1.parseJson(_arg) : _arg;
|
569 | }
|
570 | else {
|
571 | return arg;
|
572 | }
|
573 | });
|
574 | };
|
575 | //# sourceMappingURL=logger.js.map |
\ | No newline at end of file |