1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 | 'use strict';
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 | var log = require('winston');
|
23 | var eyes = require('eyes');
|
24 | var os = require('os');
|
25 | var Table = require('easy-table');
|
26 | var util = require('util');
|
27 | var wrap = require('wordwrap');
|
28 | var path = require('path');
|
29 |
|
30 | var utilsCore = require('./utilsCore');
|
31 |
|
32 |
|
33 | log.cli();
|
34 |
|
35 | log.add(log.transports.File, {
|
36 | name: 'silly',
|
37 | filename: path.join(utilsCore.azureDir(), 'azure.details.log'),
|
38 | level: 'silly',
|
39 | json: false,
|
40 | colorize:false,
|
41 | padlevel: false,
|
42 | timestamp: false,
|
43 | stripColors: true,
|
44 | silent: process.env.AZURE_CLI_DISABLE_LOG_CAPTURE,
|
45 | options: { flags: 'w' },
|
46 | formatter: function (options) {
|
47 | var code = /\u001b\[(\d+(;\d+)*)?m/g;
|
48 | var msg = (undefined !== options.message ? options.message.replace(code, '') : '');
|
49 | return options.level + ': '+ msg +
|
50 | (options.meta && Object.keys(options.meta).length ? '\n' + JSON.stringify(options.meta, null, 2) : '');
|
51 | }
|
52 | });
|
53 |
|
54 | var jsonMode;
|
55 |
|
56 | log.format = function (options) {
|
57 | var consoleTransport = log['default'].transports['console'];
|
58 | var testTransport = log['default'].transports['memory'];
|
59 | if (consoleTransport && testTransport) {
|
60 | throw new Error('Internal error: both console and memory transports are specified.');
|
61 | }
|
62 | var defaultTransport = consoleTransport || testTransport;
|
63 | if (!defaultTransport) {
|
64 | throw new Error('Internal error: missing winston transport.');
|
65 | }
|
66 | defaultTransport.colorize = process.stdout.isTTY;
|
67 | if (arguments.length === 0) {
|
68 | return {
|
69 | json: jsonMode,
|
70 | level: defaultTransport.level,
|
71 | };
|
72 | }
|
73 |
|
74 | if (options.json) {
|
75 | log.padLevels = false;
|
76 | log.stripColors = true;
|
77 | jsonMode = true;
|
78 | defaultTransport.formatter = function (options) {
|
79 | if (options.meta && Object.keys(options.meta).length || !options.message) {
|
80 | return options.meta ? JSON.stringify(options.meta, null, 2) : '';
|
81 | } else if (options.message) {
|
82 | return options.level + ': ' + options.message.replace(/\x1b\[[0-9]+m/g, '');
|
83 | }
|
84 | };
|
85 |
|
86 |
|
87 | } else {
|
88 | log.padLevels = true;
|
89 | log.stripColors = false;
|
90 | jsonMode = false;
|
91 | defaultTransport.formatter = null;
|
92 | }
|
93 | if (options.level) {
|
94 | defaultTransport.level = options.level;
|
95 | }
|
96 | };
|
97 |
|
98 | log.json = function (level, data) {
|
99 | if (arguments.length == 1) {
|
100 | data = level;
|
101 | level = 'data';
|
102 | }
|
103 |
|
104 | if (log.format().json) {
|
105 | if (!data) {
|
106 | log.log(level, '');
|
107 | } else {
|
108 | log.log(level, '', data);
|
109 | }
|
110 | } else {
|
111 | var lines = eyes.inspect(data, level, { stream: false });
|
112 | lines.split('\n').forEach(function (line) {
|
113 |
|
114 |
|
115 |
|
116 |
|
117 | log.log(level, line[eyes.defaults.styles.all]);
|
118 | });
|
119 | }
|
120 | };
|
121 |
|
122 | log.table = function (level, data, transform) {
|
123 | if (arguments.length == 2) {
|
124 | transform = data;
|
125 | data = level;
|
126 | level = 'data';
|
127 | }
|
128 |
|
129 | if (log.format().json) {
|
130 | log.log(level, 'table', data);
|
131 | } else {
|
132 | var table = new Table();
|
133 | table.LeftPadder = Table.LeftPadder;
|
134 | table.padLeft = Table.padLeft;
|
135 | table.RightPadder = Table.RightPadder;
|
136 | table.padRight = Table.padRight;
|
137 |
|
138 | if (data && data.forEach) {
|
139 | data.forEach(function (item) { transform(table, item); table.newLine(); });
|
140 | } else if (data) {
|
141 | for (var item in data) {
|
142 | transform(table, item);
|
143 | table.newLine();
|
144 | }
|
145 | }
|
146 |
|
147 | for (var i in table.lines) {
|
148 | for (var column in table.columns) {
|
149 | if (!table.lines[i].hasOwnProperty(column)) {
|
150 | table.lines[i][column] = '';
|
151 | }
|
152 | }
|
153 | }
|
154 |
|
155 | var lines = table.toString();
|
156 | lines.substring(0, lines.length - 1).split('\n').forEach(function (line) {
|
157 | log.log(level, line);
|
158 | });
|
159 | }
|
160 | };
|
161 |
|
162 | log.nameValue = function (name, value, indent, displayNullValue) {
|
163 | var delimiter = ': ';
|
164 | if (!displayNullValue) displayNullValue = false;
|
165 | if (!indent) indent = 0;
|
166 | var key = spaces(indent) + name;
|
167 | key += spaces(32 - key.length);
|
168 |
|
169 | if (value !== undefined && value !== null) {
|
170 | log.data(key + delimiter + value);
|
171 | } else if (displayNullValue) {
|
172 | log.data(key + delimiter + '""');
|
173 | }
|
174 | };
|
175 |
|
176 | log.header = function (header, indent, newLine) {
|
177 | var delimiter = ':';
|
178 | if (newLine) {
|
179 | log.data('');
|
180 | }
|
181 | log.data(spaces(indent) + header + delimiter);
|
182 | };
|
183 |
|
184 | log.list = function (items, indent, newLine) {
|
185 | items.forEach(function (item) {
|
186 | log.listItem(item, indent, newLine);
|
187 | });
|
188 | };
|
189 |
|
190 | log.listItem = function (item, indent, newLine) {
|
191 | if (newLine) {
|
192 | log.data('');
|
193 | }
|
194 | log.data(spaces(indent) + item);
|
195 | };
|
196 |
|
197 |
|
198 |
|
199 |
|
200 | var originalWarn = log.warn;
|
201 | log.warn = function() {
|
202 | if (!log.format().json) {
|
203 | originalWarn.apply(this, arguments);
|
204 | }
|
205 | };
|
206 |
|
207 | function getProperty(value, propertyName) {
|
208 | if (typeof value === 'undefined' || value === null) {
|
209 | return '';
|
210 | }
|
211 |
|
212 | if (!propertyName) {
|
213 | return value;
|
214 | }
|
215 |
|
216 | var first = propertyName.split('.')[0];
|
217 | var rest = propertyName.slice(first.length + 1);
|
218 | return getProperty(value[first], rest);
|
219 | }
|
220 |
|
221 | function spaces(num) {
|
222 | if (num > 0) {
|
223 | return new Array(num + 1).join(' ');
|
224 | }
|
225 | return '';
|
226 | }
|
227 |
|
228 | function toWidth(string, width) {
|
229 | var pad = width - string.length;
|
230 | return string + spaces(pad);
|
231 | }
|
232 |
|
233 | function defaultFormat(data) {
|
234 | if (typeof data === 'undefined' || data === null) {
|
235 | return '';
|
236 | }
|
237 | if (data instanceof Array) {
|
238 | if (data.length === 0) {
|
239 | return '[]';
|
240 | }
|
241 | return data.join(', ');
|
242 | }
|
243 |
|
244 | return data.toString();
|
245 | }
|
246 |
|
247 | function doReport(indentation, reportFormat, data, outfn) {
|
248 | if (reportFormat.length === 0) {
|
249 | return;
|
250 | }
|
251 |
|
252 | var maxWidth = 80;
|
253 | if (process.stdout.isTTY) {
|
254 | maxWidth = process.stdout.columns;
|
255 | }
|
256 |
|
257 | var headerWidth = Math.max.apply(null,
|
258 | reportFormat.map(function (item) { return item[0].length; })
|
259 | ) + 2;
|
260 |
|
261 | reportFormat.forEach(function (item) {
|
262 | var title = item[0] + ':';
|
263 | var field = item[1];
|
264 | var formatter = item[2] || defaultFormat;
|
265 |
|
266 | var value = getProperty(data, field);
|
267 | if (formatter instanceof Array) {
|
268 | outfn(spaces(indentation) + toWidth(title, headerWidth));
|
269 | doReport(indentation + headerWidth, formatter, value, outfn);
|
270 | } else {
|
271 | var leftIndentation = 'verbose: '.length + indentation + headerWidth;
|
272 | var formatted = wrap.hard(leftIndentation, maxWidth)(formatter(value));
|
273 | formatted = spaces(indentation) + toWidth(title, headerWidth) +
|
274 | formatted.slice(leftIndentation);
|
275 | outfn(formatted);
|
276 | }
|
277 | });
|
278 | }
|
279 |
|
280 | log.report = function (reportFormat, data) {
|
281 | if (log.format().json) {
|
282 | log.log('data', 'table', data);
|
283 | } else {
|
284 | doReport(0, reportFormat, data, log.data.bind(log));
|
285 | }
|
286 | };
|
287 |
|
288 | log.report.allProperties = function (data) {
|
289 | if (typeof data === 'undefined' || data === null || data === '') {
|
290 | return '[]';
|
291 | }
|
292 | var subreport = Object.keys(data).map(function (key) {
|
293 | return [key, key];
|
294 | });
|
295 | var result = [];
|
296 | doReport(0, subreport, data, function (o) { result.push(o); });
|
297 | result.push('');
|
298 | return result.join(os.EOL);
|
299 | };
|
300 |
|
301 | log.report.asDate = function (data) {
|
302 | return new Date(Date.parse(data)).toString();
|
303 | };
|
304 |
|
305 | log.report.inspect = function (data) {
|
306 | return util.inspect(data, {depth: null});
|
307 | };
|
308 |
|
309 | log.createLogFilter = function () {
|
310 | return function handle(resource, next, callback) {
|
311 | log.silly('requestOptions');
|
312 | try {
|
313 | var loggedResource = JSON.parse(JSON.stringify(resource));
|
314 | if (loggedResource.headers && loggedResource.headers.Authorization) {
|
315 | delete loggedResource.headers.Authorization;
|
316 | }
|
317 | if (loggedResource.body &&
|
318 | (loggedResource.body.length > 2 * 1024 * 1024 || loggedResource.body.type === 'Buffer')) {
|
319 | loggedResource.body = 'REQUEST BODY DATA OMMITTED FROM LOG DUE TO SIZE';
|
320 | }
|
321 | log.json('silly', loggedResource);
|
322 | } catch (error) {
|
323 | return callback (error);
|
324 | }
|
325 | return next(resource, function (err, response, body) {
|
326 | log.silly('returnObject');
|
327 | if (response) {
|
328 | var bodyToLog = body;
|
329 | if (body && (body.length > 2 * 1024 * 1024 || body.type === 'Buffer')) {
|
330 | bodyToLog = 'RESPONSE BODY DATA OMMITTED FROM LOG DUE TO SIZE';
|
331 | }
|
332 | log.json('silly', {
|
333 | statusCode: response.statusCode,
|
334 | header: response.headers,
|
335 | body: bodyToLog
|
336 | });
|
337 | }
|
338 |
|
339 | callback(err, response, body);
|
340 | });
|
341 | };
|
342 | };
|
343 | log.spaces = spaces;
|
344 |
|
345 | module.exports = log; |
\ | No newline at end of file |