UNPKG

4.64 kBJavaScriptView Raw
1/**
2 * Copyright 2016-2018 F5 Networks, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17'use strict';
18
19const winston = require('winston');
20
21/**
22 * @module
23 */
24module.exports = {
25 /**
26 * Returns a logger.
27 *
28 * @param {Object} [options] - Options for configuring the logger
29 * @param {Boolean} [options.console] - Whether or not to log to the console. Default true.
30 * @param {String} [options.logLevel] - The log level to use.
31 * (error, warn, info, verbose, debug, silly).
32 * Defaults to warn.
33 * @param {String} [options.fileName] - File to log to. Defaults to none (console only).
34 * @param {Object} [options.module] - The module the logger is used from. Used to put the
35 * file name in the log message.
36 * @param {Boolean} [options.json] - Whether or not to format message as JSON. Default false.
37 * @param {Boolean} [options.verboseLabel] - Whether or not to include the verbose label in log.
38 * Default false.
39 *
40 * @returns An instance of a logger
41 */
42 getLogger(options) {
43 const logToConsole = options ? options.console : true;
44 const logLevel = options ? options.logLevel : 'warn';
45 const fileName = options ? options.fileName : '';
46 const moduleLogging = options ? options.module : {};
47 const logJson = (options && typeof options.json !== 'undefined') ? options.json : false;
48 const verboseLabel =
49 (options && typeof options.verboseLabel !== 'undefined') ? options.verboseLabel : false;
50
51 const transportOptions = {
52 level: logLevel,
53 timestamp() {
54 return new Date().toISOString();
55 },
56 json: logJson,
57 handleExceptions: false,
58 humanReadableUnhandledException: true,
59 label: getLabel(logLevel, moduleLogging, verboseLabel),
60 formatter(formatOptions) {
61 return getMessage.call(this, formatOptions);
62 }
63 };
64
65 const transports = [];
66
67 if (logToConsole) {
68 transports.push(new (winston.transports.Console)(transportOptions));
69 }
70
71 if (fileName) {
72 const fileOptions = transportOptions;
73 fileOptions.filename = fileName;
74 fileOptions.maxsize = 10485760; // 10 Mb
75 fileOptions.maxFiles = 10;
76 fileOptions.tailable = true;
77
78 transports.push(new (winston.transports.File)(fileOptions));
79 }
80
81 return new (winston.Logger)({ transports });
82 }
83};
84
85// Return the last folder name in the path and the calling
86// module's filename.
87function getLabel(logLevel, moduleLogging, verboseLabel) {
88 let parts;
89 let label = '';
90
91 if (moduleLogging) {
92 if (logLevel === 'debug' || logLevel === 'silly' || verboseLabel) {
93 parts = moduleLogging.filename.split('/');
94 label = `${parts[parts.length - 2]}/${parts.pop()}`;
95 }
96 }
97
98 return label;
99}
100
101function getMessage(options) {
102 const messageOptions = Object.assign({}, options);
103
104 if (messageOptions.meta) {
105 const keys = Object.keys(messageOptions.meta);
106 const maskRegex = new RegExp('^pass(word|phrase)$', 'i');
107 keys.forEach((key) => {
108 if (maskRegex.test(key)) {
109 messageOptions.meta[key] = '********';
110 }
111 });
112 }
113
114 const label = this.label ? `[pid: ${process.pid}] [${this.label}]` : '';
115 const metaData =
116 messageOptions.meta && Object.keys(messageOptions.meta).length ?
117 `${JSON.stringify(messageOptions.meta)}` : '';
118 let message =
119 (messageOptions.message ? messageOptions.message.replace(/password=.+/g, 'password=********') : '');
120 message = message.replace(/passphrase=.+/g, 'passphrase=********');
121
122 return `${messageOptions.timestamp()} ${this.level}: ${label} ${message} ${metaData}`;
123}