From 01f0aa29cd0cfafcb4c8ced6ea3b06917ef2d7a9 Mon Sep 17 00:00:00 2001 From: Matt Loring Date: Fri, 9 Dec 2016 15:36:24 -0800 Subject: [PATCH 1/3] Introducing a logger for common use This is a trimmed down version of the logger used by the cloud diagnostics common repository with the debug agent specific operations removed. --- packages/common/src/index.js | 6 +++ packages/common/src/logger.js | 64 ++++++++++++++++++++++++++ packages/common/test/index.js | 3 ++ packages/common/test/logger.js | 82 ++++++++++++++++++++++++++++++++++ 4 files changed, 155 insertions(+) create mode 100644 packages/common/src/logger.js create mode 100644 packages/common/test/logger.js diff --git a/packages/common/src/index.js b/packages/common/src/index.js index a56915b435c..f9ef8f47dea 100644 --- a/packages/common/src/index.js +++ b/packages/common/src/index.js @@ -32,6 +32,12 @@ exports.GrpcService = require('./grpc-service.js'); */ exports.GrpcServiceObject = require('./grpc-service-object.js'); +/** + * @type {module:common/Logger} + * @private + */ +exports.Logger = require('./logger.js'); + /** * @type {module:common/operation} * @private diff --git a/packages/common/src/logger.js b/packages/common/src/logger.js new file mode 100644 index 00000000000..7609d852a3d --- /dev/null +++ b/packages/common/src/logger.js @@ -0,0 +1,64 @@ +/** + * Copyright 2014, 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + 'use strict'; + +var slice = Array.prototype.slice; + +module.exports = { + /** @const {number} */ ERROR: 1, + /** @const {number} */ WARN: 2, + /** @const {number} */ INFO: 3, + /** @const {number} */ DEBUG: 4, + /** @const {number} */ SILLY: 5, + + /** @const {Array.} */ + LEVEL_NAMES: [null, 'ERROR', 'WARN ', 'INFO ', 'DEBUG', 'SILLY'], + + /** + * Factory method that returns a new logger. + * + * @param {number=} level Log level for reporting to the console. + * @param {?string=} prefix to use in log messages. + */ + create: function(level, prefix) { + var level_ = level || 0; + var prefix_ = prefix || ''; + + /** + * Logs any passed in arguments. + * @private + */ + var log = function(level, args) { + if (level_ < level) { + return; + } + args.unshift(module.exports.LEVEL_NAMES[level] + ':' + prefix_ + ':'); + console.log.apply(console, args); + }; + + return { + error: function() { log(module.exports.ERROR, slice.call(arguments)); }, + warn: function() { log(module.exports.WARN, slice.call(arguments)); }, + info: function() { log(module.exports.INFO, slice.call(arguments)); }, + debug: function() { log(module.exports.DEBUG, slice.call(arguments)); }, + silly: function() { log(module.exports.SILLY, slice.call(arguments)); }, + }; + } /* create */ + +}; /* module.exports */ + + diff --git a/packages/common/test/index.js b/packages/common/test/index.js index 076f6bc88d6..c521710e3b2 100644 --- a/packages/common/test/index.js +++ b/packages/common/test/index.js @@ -22,6 +22,7 @@ var proxyquire = require('proxyquire'); var fakeGrpcOperation = {}; var fakeGrpcService = {}; var fakeGrpcServiceObject = {}; +var fakeLogger = {}; var fakeOperation = {}; var fakePaginator = {}; var fakeService = {}; @@ -36,6 +37,7 @@ describe('common', function() { './grpc-operation.js': fakeGrpcOperation, './grpc-service.js': fakeGrpcService, './grpc-service-object.js': fakeGrpcServiceObject, + './logger.js': fakeLogger, './operation.js': fakeOperation, './paginator.js': fakePaginator, './service.js': fakeService, @@ -49,6 +51,7 @@ describe('common', function() { GrpcOperation: fakeGrpcOperation, GrpcService: fakeGrpcService, GrpcServiceObject: fakeGrpcServiceObject, + Logger: fakeLogger, Operation: fakeOperation, Service: fakeService, ServiceObject: fakeServiceObject, diff --git a/packages/common/test/logger.js b/packages/common/test/logger.js new file mode 100644 index 00000000000..d521b123933 --- /dev/null +++ b/packages/common/test/logger.js @@ -0,0 +1,82 @@ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; +var assert = require('assert'); + +describe('logger base-functionality', function() { + var buffer; + var logger; + var originalConsoleWrite; + + before(function() { + buffer = []; + logger = require('../src/logger.js'); + originalConsoleWrite = console._stdout.write; + /* Stub console.log for testing */ + console._stdout.write = function() { + buffer.push(arguments[0]); + if (arguments[0].indexOf('foobar') === -1) { + originalConsoleWrite.apply(this, arguments); + } + }; + }); + + after(function() { + console._stdout.write = originalConsoleWrite; + }); + + it('should return a logger through the create function', function() { + var l = logger.create(logger.DEBUG, __filename); + assert.ok(l); + assert.ok(l.error); + assert.ok(typeof l.error === 'function'); + }); + + it('should generate log messages successfully', function() { + var l = logger.create(logger.SILLY, 'foobar'); + l.error('a'); + assert.ok(/ERROR.*: a/.test(buffer.pop())); + l.warn('b', 'c'); + assert.ok(/WARN.*: b c/.test(buffer.pop())); + l.info('d', 'e', 'f'); + assert.ok(/INFO.*: d e f/.test(buffer.pop())); + l.debug('g'); + assert.ok(/DEBUG.*: g/.test(buffer.pop())); + l.silly('h'); + assert.ok(/SILLY.*: h/.test(buffer.pop())); + }); + + it('should not log when the default level is lower', function() { + buffer = []; + + var l = logger.create(logger.WARN, 'foobar'); + + l.error('a'); + assert.ok(buffer.length === 1); + buffer.pop(); + + l.warn('b'); + assert.ok(buffer.length === 1); + buffer.pop(); + + l.info('c'); + assert.ok(buffer.length === 0); + + l.debug('d'); + assert.ok(buffer.length === 0); + }); +}); From 7c71a2bfc8c3fd7f8e5ea838daeb75bb97e1e4b1 Mon Sep 17 00:00:00 2001 From: Matt Loring Date: Mon, 12 Dec 2016 13:13:35 -0800 Subject: [PATCH 2/3] Use log-driver --- packages/common/package.json | 1 + packages/common/src/logger.js | 42 ++++++++++------------------------ packages/common/test/logger.js | 6 ++--- 3 files changed, 16 insertions(+), 33 deletions(-) diff --git a/packages/common/package.json b/packages/common/package.json index c05d9bff1b9..f92f6c006c8 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -50,6 +50,7 @@ "google-proto-files": "^0.8.0", "grpc": "^1.0.0", "is": "^3.0.1", + "log-driver": "^1.2.5", "methmeth": "^1.0.0", "modelo": "^4.2.0", "request": "^2.70.0", diff --git a/packages/common/src/logger.js b/packages/common/src/logger.js index 7609d852a3d..3d140053526 100644 --- a/packages/common/src/logger.js +++ b/packages/common/src/logger.js @@ -16,47 +16,29 @@ 'use strict'; -var slice = Array.prototype.slice; +var splice = Array.prototype.splice; +var join = Array.prototype.join; +var makeLogger = require('log-driver'); module.exports = { - /** @const {number} */ ERROR: 1, - /** @const {number} */ WARN: 2, - /** @const {number} */ INFO: 3, - /** @const {number} */ DEBUG: 4, - /** @const {number} */ SILLY: 5, - - /** @const {Array.} */ - LEVEL_NAMES: [null, 'ERROR', 'WARN ', 'INFO ', 'DEBUG', 'SILLY'], - /** * Factory method that returns a new logger. * - * @param {number=} level Log level for reporting to the console. + * @param {string=} level Log level for reporting to the console. * @param {?string=} prefix to use in log messages. */ create: function(level, prefix) { - var level_ = level || 0; var prefix_ = prefix || ''; - /** - * Logs any passed in arguments. - * @private - */ - var log = function(level, args) { - if (level_ < level) { - return; + return makeLogger({ + levels: ['error', 'warn', 'info', 'debug', 'silly'], + level: level || 'error', + format: function() { + arguments[0] = arguments[0].toUpperCase(); + splice.call(arguments, 1, 0, ':', prefix_, ':'); + return join.call(arguments, ' '); } - args.unshift(module.exports.LEVEL_NAMES[level] + ':' + prefix_ + ':'); - console.log.apply(console, args); - }; - - return { - error: function() { log(module.exports.ERROR, slice.call(arguments)); }, - warn: function() { log(module.exports.WARN, slice.call(arguments)); }, - info: function() { log(module.exports.INFO, slice.call(arguments)); }, - debug: function() { log(module.exports.DEBUG, slice.call(arguments)); }, - silly: function() { log(module.exports.SILLY, slice.call(arguments)); }, - }; + }); } /* create */ }; /* module.exports */ diff --git a/packages/common/test/logger.js b/packages/common/test/logger.js index d521b123933..45b53591fe7 100644 --- a/packages/common/test/logger.js +++ b/packages/common/test/logger.js @@ -40,14 +40,14 @@ describe('logger base-functionality', function() { }); it('should return a logger through the create function', function() { - var l = logger.create(logger.DEBUG, __filename); + var l = logger.create('debug', __filename); assert.ok(l); assert.ok(l.error); assert.ok(typeof l.error === 'function'); }); it('should generate log messages successfully', function() { - var l = logger.create(logger.SILLY, 'foobar'); + var l = logger.create('silly', 'foobar'); l.error('a'); assert.ok(/ERROR.*: a/.test(buffer.pop())); l.warn('b', 'c'); @@ -63,7 +63,7 @@ describe('logger base-functionality', function() { it('should not log when the default level is lower', function() { buffer = []; - var l = logger.create(logger.WARN, 'foobar'); + var l = logger.create('warn', 'foobar'); l.error('a'); assert.ok(buffer.length === 1); From 7907d29a5e11fab989876cd0e97433f6ee6becf4 Mon Sep 17 00:00:00 2001 From: Stephen Sawchuk Date: Wed, 14 Dec 2016 10:32:55 -0500 Subject: [PATCH 3/3] style --- packages/common/src/index.js | 4 +- packages/common/src/logger.js | 78 ++++++++++++++++++----------- packages/common/test/index.js | 4 +- packages/common/test/logger.js | 91 +++++++++++++++++----------------- 4 files changed, 99 insertions(+), 78 deletions(-) diff --git a/packages/common/src/index.js b/packages/common/src/index.js index f9ef8f47dea..53f0875ed7d 100644 --- a/packages/common/src/index.js +++ b/packages/common/src/index.js @@ -33,10 +33,10 @@ exports.GrpcService = require('./grpc-service.js'); exports.GrpcServiceObject = require('./grpc-service-object.js'); /** - * @type {module:common/Logger} + * @type {module:common/logger} * @private */ -exports.Logger = require('./logger.js'); +exports.logger = require('./logger.js'); /** * @type {module:common/operation} diff --git a/packages/common/src/logger.js b/packages/common/src/logger.js index 3d140053526..1e5621afdcb 100644 --- a/packages/common/src/logger.js +++ b/packages/common/src/logger.js @@ -1,5 +1,5 @@ -/** - * Copyright 2014, 2015 Google Inc. All Rights Reserved. +/*! + * Copyright 2016 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,31 +16,53 @@ 'use strict'; -var splice = Array.prototype.splice; -var join = Array.prototype.join; -var makeLogger = require('log-driver'); - -module.exports = { - /** - * Factory method that returns a new logger. - * - * @param {string=} level Log level for reporting to the console. - * @param {?string=} prefix to use in log messages. - */ - create: function(level, prefix) { - var prefix_ = prefix || ''; - - return makeLogger({ - levels: ['error', 'warn', 'info', 'debug', 'silly'], - level: level || 'error', - format: function() { - arguments[0] = arguments[0].toUpperCase(); - splice.call(arguments, 1, 0, ':', prefix_, ':'); - return join.call(arguments, ' '); - } - }); - } /* create */ - -}; /* module.exports */ +/*! + * @module common/logger + */ + +var format = require('string-format-obj'); +var is = require('is'); +var logDriver = require('log-driver'); + +/** + * Create a logger to print output to the console. + * + * @param {string=|object=} options - Configuration object. If a string, it is + * treated as `options.level`. + * @param {string=} options.level - The minimum log level that will print to the + * console. (Default: `error`) + * @param {string=} options.tag - A tag to use in log messages. + */ +function logger(options) { + if (is.string(options)) { + options = { + level: options + }; + } + + options = options || {}; + + return logDriver({ + levels: [ + 'error', + 'warn', + 'info', + 'debug', + 'silly' + ], + + level: options.level || 'error', + + format: function() { + var args = [].slice.call(arguments); + return format('{level}{tag} {message}', { + level: args.shift().toUpperCase(), + tag: options.tag ? ':' + options.tag + ':' : '', + message: args.join(' ') + }); + } + }); +} +module.exports = logger; diff --git a/packages/common/test/index.js b/packages/common/test/index.js index c521710e3b2..24097fd3fe2 100644 --- a/packages/common/test/index.js +++ b/packages/common/test/index.js @@ -51,11 +51,11 @@ describe('common', function() { GrpcOperation: fakeGrpcOperation, GrpcService: fakeGrpcService, GrpcServiceObject: fakeGrpcServiceObject, - Logger: fakeLogger, + logger: fakeLogger, Operation: fakeOperation, + paginator: fakePaginator, Service: fakeService, ServiceObject: fakeServiceObject, - paginator: fakePaginator, util: fakeUtil }); }); diff --git a/packages/common/test/logger.js b/packages/common/test/logger.js index 45b53591fe7..b4be2efc765 100644 --- a/packages/common/test/logger.js +++ b/packages/common/test/logger.js @@ -1,5 +1,5 @@ -/** - * Copyright 2015 Google Inc. All Rights Reserved. +/*! + * Copyright 2016 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,68 +15,67 @@ */ 'use strict'; + var assert = require('assert'); +var proxyquire = require('proxyquire'); + +function fakeLogDriver(config) { + return config; +} describe('logger base-functionality', function() { - var buffer; var logger; - var originalConsoleWrite; before(function() { - buffer = []; - logger = require('../src/logger.js'); - originalConsoleWrite = console._stdout.write; - /* Stub console.log for testing */ - console._stdout.write = function() { - buffer.push(arguments[0]); - if (arguments[0].indexOf('foobar') === -1) { - originalConsoleWrite.apply(this, arguments); - } - }; + logger = proxyquire('../src/logger.js', { + 'log-driver': fakeLogDriver + }); }); - after(function() { - console._stdout.write = originalConsoleWrite; + it('should create a logger with the correct levels', function() { + assert.deepEqual(logger().levels, [ + 'error', + 'warn', + 'info', + 'debug', + 'silly' + ]); }); - it('should return a logger through the create function', function() { - var l = logger.create('debug', __filename); - assert.ok(l); - assert.ok(l.error); - assert.ok(typeof l.error === 'function'); + it('should use a specified level', function() { + var level = 'level'; + assert.strictEqual(logger({ level: level }).level, level); }); - it('should generate log messages successfully', function() { - var l = logger.create('silly', 'foobar'); - l.error('a'); - assert.ok(/ERROR.*: a/.test(buffer.pop())); - l.warn('b', 'c'); - assert.ok(/WARN.*: b c/.test(buffer.pop())); - l.info('d', 'e', 'f'); - assert.ok(/INFO.*: d e f/.test(buffer.pop())); - l.debug('g'); - assert.ok(/DEBUG.*: g/.test(buffer.pop())); - l.silly('h'); - assert.ok(/SILLY.*: h/.test(buffer.pop())); + it('should treat a single arguments as the level', function() { + var level = 'level'; + assert.strictEqual(logger(level).level, level); }); - it('should not log when the default level is lower', function() { - buffer = []; + it('should default level to error', function() { + assert.strictEqual(logger().level, 'error'); + }); - var l = logger.create('warn', 'foobar'); + describe('formatting', function() { + var LEVEL = 'level-name'; + var TAG = 'tag-name'; + var MESSAGES = [ + 'message-1', + 'message-2' + ]; - l.error('a'); - assert.ok(buffer.length === 1); - buffer.pop(); + it('should correctly format without a tag', function() { + var formatted = logger().format(LEVEL, MESSAGES[0], MESSAGES[1]); - l.warn('b'); - assert.ok(buffer.length === 1); - buffer.pop(); + assert.strictEqual(formatted, 'LEVEL-NAME message-1 message-2'); + }); - l.info('c'); - assert.ok(buffer.length === 0); + it('should correctly format with a tag', function() { + var formatted = logger({ + tag: TAG + }).format(LEVEL, MESSAGES[0], MESSAGES[1]); - l.debug('d'); - assert.ok(buffer.length === 0); + assert.strictEqual(formatted, 'LEVEL-NAME:tag-name: message-1 message-2'); + }); }); });