UNPKG

3.94 kBJavaScriptView Raw
1/*
2 * Licensed under the Apache License, Version 2.0 (the "License");
3 * you may not use this file except in compliance with the License.
4 * You may obtain a copy of the License at
5 *
6 * http://www.apache.org/licenses/LICENSE-2.0
7 *
8 * Unless required by applicable law or agreed to in writing, software
9 * distributed under the License is distributed on an "AS IS" BASIS,
10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 * See the License for the specific language governing permissions and
12 * limitations under the License.
13 */
14
15'use strict';
16
17const winston = require('winston');
18const { LEVEL, MESSAGE } = require('triple-beam');
19const jsonStringify = require('fast-safe-stringify');
20const jsome = require('jsome');
21const fs = require('fs');
22const env = process.env.NODE_ENV || 'development';
23const tsFormat = () => (new Date()).toLocaleTimeString();
24
25/**
26 * Helper function to test is a string is a stringified version of a JSON object
27 * @param {string} str - the input string to test
28 * @returns {boolean} - true iff the string can be parsed as JSON
29 * @private
30 */
31function isJSON(str) {
32 try {
33 return (JSON.parse(str) && !!str);
34 } catch (e) {
35 return false;
36 }
37}
38
39jsome.params.lintable = true;
40
41const jsonColor = winston.format(info => {
42 const padding = info.padding && info.padding[info.level] || '';
43
44 if(info[LEVEL] === 'error' && info.stack) {
45 info[MESSAGE] = `${tsFormat()} - ${info.level}:${padding} ${info.message}\n${info.stack}`;
46 return info;
47 }
48
49 if (info[LEVEL] === 'info' || info[LEVEL] === 'warn') {
50 if(typeof info.message === 'object') {
51 info[MESSAGE] = `${tsFormat()} - ${info.level}:${padding}\n${jsome.getColoredString(info.message, null, 2)}`;
52 } else if(isJSON(info.message)) {
53 info[MESSAGE] =`${tsFormat()} - ${info.level}:${padding}\n${jsome.getColoredString(JSON.parse(info.message), null, 2)}`;
54 } else {
55 info[MESSAGE] = `${tsFormat()} - ${info.level}:${padding} ${info.message}`;
56 }
57 return info;
58 }
59
60 const stringifiedRest = jsonStringify(Object.assign({}, info, {
61 level: undefined,
62 message: undefined,
63 splat: undefined
64 }));
65
66 if (stringifiedRest !== '{}') {
67 info[MESSAGE] = `${tsFormat()} - ${info.level}:${padding} ${info.message} ${stringifiedRest}`;
68 } else {
69 info[MESSAGE] = `${tsFormat()} - ${info.level}:${padding} ${info.message}`;
70 }
71 return info;
72
73});
74
75const enumerateErrorFormat = winston.format(info => {
76 if (info.message instanceof Error) {
77 info.message = Object.assign({
78 message: info.message.message,
79 stack: info.message.stack
80 }, info.message);
81 }
82
83 if (info instanceof Error) {
84 return Object.assign({
85 message: info.message,
86 stack: info.stack
87 }, info);
88 }
89
90 return info;
91});
92
93let logger = winston.createLogger({
94 format: winston.format.combine(
95 winston.format.json(),
96 enumerateErrorFormat(),
97 winston.format.colorize(),
98 jsonColor(),
99 ),
100 transports: [
101 new winston.transports.Console({
102 level: 'info',
103 }),
104 ]
105});
106
107// Only write log files to disk if we're running in development
108// and not in a browser (webpack or browserify)
109const setupLogger = ((process,env,logDir) => {
110 if (env === 'development' && !process.browser) {
111 // Create the log directory if it does not exist
112 if (!fs.existsSync(logDir)) {
113 fs.mkdirSync(logDir);
114 }
115
116 logger.add(new winston.transports.File({
117 name: 'logs-file',
118 filename: `${logDir}/trace.log`,
119 level: 'debug'
120 }));
121 }
122});
123
124const logDir = 'log';
125setupLogger(process,env,logDir);
126logger.setup = setupLogger;
127logger.entry = logger.debug;
128logger.exit = logger.debug;
129
130module.exports = logger;
\No newline at end of file