UNPKG

5.8 kBJavaScriptView Raw
1// Load modules
2
3var Squeeze = require('good-squeeze').Squeeze;
4var Hoek = require('hoek');
5var Moment = require('moment');
6var SafeStringify = require('json-stringify-safe');
7var Through = require('through2');
8
9// Declare internals
10
11var internals = {
12 defaults: {
13 format: 'YYMMDD/HHmmss.SSS',
14 utc: true,
15 color: true
16 }
17};
18
19module.exports = internals.GoodConsole = function (events, config) {
20
21 if (!(this instanceof internals.GoodConsole)) {
22 return new internals.GoodConsole(events, config);
23 }
24 config = config || {};
25 this._settings = Hoek.applyToDefaults(internals.defaults, config);
26 this._filter = new Squeeze(events);
27};
28
29internals.GoodConsole.prototype.init = function (stream, emitter, callback) {
30
31 var self = this;
32
33 if (!stream._readableState.objectMode) {
34 return callback(new Error('stream must be in object mode'));
35 }
36
37 stream.pipe(this._filter).pipe(Through.obj(function goodConsoleTransform (data, enc, next) {
38
39 var eventName = data.event;
40 var tags = [];
41
42 /*eslint-disable */
43 if (Array.isArray(data.tags)) {
44 tags = data.tags.concat([]);
45 } else if (data.tags != null) {
46 tags = [data.tags];
47 }
48 /*eslint-enable */
49
50 tags.unshift(eventName);
51
52 if (eventName === 'response') {
53 this.push(self._formatResponse(data, tags));
54 return next();
55 }
56
57 if (eventName === 'wreck') {
58 this.push(self._formatWreck(data, tags));
59 return next();
60 }
61
62 var eventPrintData = {
63 timestamp: data.timestamp || Date.now(),
64 tags: tags,
65 data: undefined
66 };
67
68 if (eventName === 'ops') {
69 eventPrintData.data = Hoek.format('memory: %sMb, uptime (seconds): %s, load: %s',
70 Math.round(data.proc.mem.rss / (1024 * 1024)),
71 data.proc.uptime,
72 data.os.load);
73
74 this.push(self._printEvent(eventPrintData));
75 return next();
76 }
77
78 if (eventName === 'error') {
79 eventPrintData.data = 'message: ' + data.error.message + ' stack: ' + data.error.stack;
80
81 this.push(self._printEvent(eventPrintData));
82 return next();
83 }
84
85 if (eventName === 'request' || eventName === 'log') {
86 eventPrintData.data = 'data: ' + (typeof data.data === 'object' ? SafeStringify(data.data) : data.data);
87
88 this.push(self._printEvent(eventPrintData));
89 return next();
90 }
91
92 // Event that is unknown to good-console, try a defualt.
93 if (data.data) {
94 eventPrintData.data = 'data: ' + (typeof data.data === 'object' ? SafeStringify(data.data) : data.data);
95 }
96 else {
97 eventPrintData.data = 'data: (none)';
98 }
99
100 this.push(self._printEvent(eventPrintData));
101 return next();
102 })).pipe(process.stdout);
103
104 callback();
105};
106
107internals.GoodConsole.prototype._printEvent = function (event) {
108
109 var m = Moment(parseInt(event.timestamp, 10));
110 if (!this._settings.utc) { m.local(); }
111
112 var timestring = m.format(this._settings.format);
113 var data = event.data;
114 var output = timestring + ', [' + event.tags.toString() + '], ' + data;
115
116 return output + '\n';
117};
118
119internals.GoodConsole.prototype._formatResponse = function (event, tags) {
120
121 var query = event.query ? JSON.stringify(event.query) : '';
122 var responsePayload = '';
123
124 if (typeof event.responsePayload === 'object' && event.responsePayload) {
125 responsePayload = 'response payload: ' + SafeStringify(event.responsePayload);
126 }
127
128 var method = this._formatMethod(event.method);
129 var statusCode = this._formatStatusCode(event.statusCode) || '';
130
131 return this._printEvent({
132 timestamp: event.timestamp,
133 tags: tags,
134 //instance, method, path, query, statusCode, responseTime, responsePayload
135 data: Hoek.format('%s: %s %s %s %s (%sms) %s', event.instance, method, event.path, query, statusCode, event.responseTime, responsePayload)
136 });
137};
138
139internals.GoodConsole.prototype._formatWreck = function (event, tags) {
140
141 var data, method, statusCode;
142 method = this._formatMethod(event.request.method);
143
144 if (event.error) {
145 data = Hoek.format('%s: %s (%sms) error: %s stack: %s', method, event.request.url, event.timeSpent, event.error.message, event.error.stack);
146 } else {
147 statusCode = this._formatStatusCode(event.response.statusCode);
148 data = Hoek.format('%s: %s %s %s (%sms)', method, event.request.url, statusCode, event.response.statusMessage, event.timeSpent);
149 }
150
151
152 return this._printEvent({
153 timestamp: event.timestamp,
154 tags: tags,
155 data: data
156 });
157};
158
159internals.GoodConsole.prototype._formatMethod = function (method) {
160
161 var color;
162 var methodColors = {
163 get: 32,
164 delete: 31,
165 put: 36,
166 post: 33
167 };
168 var formattedMethod = method.toLowerCase();
169 if (this._settings.color) {
170 color = methodColors[method.toLowerCase()] || 34;
171 formattedMethod = '\x1b[1;' + color + 'm' + formattedMethod + '\x1b[0m';
172 }
173 return formattedMethod;
174};
175
176internals.GoodConsole.prototype._formatStatusCode = function (statusCode) {
177
178 var color;
179 if (statusCode && this._settings.color) {
180 color = 32;
181 if (statusCode >= 500) {
182 color = 31;
183 } else if (statusCode >= 400) {
184 color = 33;
185 } else if (statusCode >= 300) {
186 color = 36;
187 }
188 return '\x1b[' + color + 'm' + statusCode + '\x1b[0m';
189 }
190 return statusCode;
191};
192
193internals.GoodConsole.attributes = {
194 pkg: require('../package.json')
195};