From 5ac09c0258acc268c4301fc049a051fb2d941bb1 Mon Sep 17 00:00:00 2001 From: popomore Date: Tue, 1 Nov 2016 19:23:51 +0800 Subject: [PATCH] feat: add getLogger to app and ctx it can be override with custom logical Closes eggjs/egg#36 --- app/extend/context.js | 49 ++++++++++++------- lib/egg.js | 18 +++++-- test/app/extend/application.test.js | 13 +++++ test/app/extend/context.test.js | 24 +++++++++ test/fixtures/apps/get-logger/app/router.js | 12 +++++ .../fixtures/apps/get-logger/config/config.js | 13 +++++ test/fixtures/apps/get-logger/package.json | 3 ++ 7 files changed, 108 insertions(+), 24 deletions(-) create mode 100644 test/fixtures/apps/get-logger/app/router.js create mode 100644 test/fixtures/apps/get-logger/config/config.js create mode 100644 test/fixtures/apps/get-logger/package.json diff --git a/app/extend/context.js b/app/extend/context.js index d779e0b27a..51d41756ce 100644 --- a/app/extend/context.js +++ b/app/extend/context.js @@ -7,13 +7,12 @@ const Cookies = require('egg-cookies'); const co = require('co'); const util = require('../../lib/core/util'); -const LOGGER = Symbol('LOGGER'); -const CORE_LOGGER = Symbol('CORE_LOGGER'); const HELPER = Symbol('Context#helper'); const VIEW = Symbol('Context#view'); const LOCALS = Symbol('Context#locals'); const LOCALS_LIST = Symbol('Context#localsList'); const COOKIES = Symbol('Context#cookies'); +const CONTEXT_LOGGERS = Symbol('Context#logger'); const proto = module.exports = { get cookies() { @@ -183,10 +182,31 @@ const proto = module.exports = { }, /** - * 应用 Web 相关日志,用于记录 Web 行为相关的日志, - * 最终日志文件输出到 `{log.dir}/{app.name}-web.log` 中。 - * 每行日志会自动记录上当前请求的一些基本信息, - * 如 `[$logonId/$userId/$ip/$timestamp_ms/$sofaTraceId $use_ms $method $url]` + * Wrap app.loggers with context infomation, + * if a custom logger is defined by naming aLogger, then you can `ctx.getLogger('aLogger')` + * @param {String} name - logger name + * @return {Logger} logger + */ + getLogger(name) { + let cache = this[CONTEXT_LOGGERS]; + if (!cache) { + cache = this[CONTEXT_LOGGERS] = {}; + } + + // read from cache + if (cache[name]) return cache[name]; + + // get no exist logger + const appLogger = this.app.getLogger(name); + if (!appLogger) return null; + + // write to cache + cache[name] = new ContextLogger(this, appLogger); + return cache[name]; + }, + + /** + * Logger for Application, wrapping app.coreLogger with context infomation * @member {ContextLogger} Context#logger * @since 1.0.0 * @example @@ -194,28 +214,19 @@ const proto = module.exports = { * this.logger.info('some request data: %j', this.request.body); * this.logger.warn('WARNING!!!!'); * ``` - * 错误日志记录,直接会将错误日志完整堆栈信息记录下来,并且输出到 `{log.dir}/common-error.log` - * ``` - * this.logger.error(err); - * ``` */ get logger() { - if (!this[LOGGER]) { - this[LOGGER] = new ContextLogger(this, this.app.logger); - } - return this[LOGGER]; + return this.getLogger('logger'); }, /** - * app context 级别的 core logger,适合 core 对当前请求记录日志使用 + * Logger for frameworks and plugins, + * wrapping app.coreLogger with context infomation * @member {ContextLogger} Context#coreLogger * @since 1.0.0 */ get coreLogger() { - if (!this[CORE_LOGGER]) { - this[CORE_LOGGER] = new ContextLogger(this, this.app.coreLogger); - } - return this[CORE_LOGGER]; + return this.getLogger('coreLogger'); }, /** diff --git a/lib/egg.js b/lib/egg.js index e8a43b5e12..b5e717ac7f 100644 --- a/lib/egg.js +++ b/lib/egg.js @@ -154,9 +154,7 @@ class EggApplication extends EggCore { } /** - * logger 集合,包含两个: - * - 应用使用:loggers.logger - * - 框架使用:loggers.coreLogger + * All loggers contain logger, coreLogger and customLogger * @member {Object} * @since 1.0.0 */ @@ -167,13 +165,23 @@ class EggApplication extends EggCore { return this[LOGGERS]; } + /** + * Get logger by name, it's equal to app.loggers['name'], + * but you can extend it with your own logical. + * @param {String} name - logger name + * @return {Logger} logger + */ + getLogger(name) { + return this.loggers[name] || null; + } + /** * 同 {@link Agent#coreLogger} 相同 * @member {Logger} * @since 1.0.0 */ get logger() { - return this.loggers.logger; + return this.getLogger('logger'); } /** @@ -182,7 +190,7 @@ class EggApplication extends EggCore { * @since 1.0.0 */ get coreLogger() { - return this.loggers.coreLogger; + return this.getLogger('coreLogger'); } _unhandledRejectionHandler(err) { diff --git a/test/app/extend/application.test.js b/test/app/extend/application.test.js index 6e09eadb3f..90e5964591 100644 --- a/test/app/extend/application.test.js +++ b/test/app/extend/application.test.js @@ -5,6 +5,7 @@ const mm = require('egg-mock'); const utils = require('../../utils'); describe('test/app/extend/application.test.js', () => { + describe('app.logger', () => { let app; before(() => { @@ -16,6 +17,18 @@ describe('test/app/extend/application.test.js', () => { it('should alias app.logger => app.loggers.logger', () => { app.logger.should.equal(app.loggers.logger); }); + + it('should alias app.coreLooger => app.loggers.coreLooger', () => { + app.coreLogger.should.equal(app.loggers.coreLogger); + }); + + it('should alias app.getLogger(\'coreLogger\') => app.loggers.coreLooger', () => { + app.getLogger('coreLogger').should.equal(app.loggers.coreLogger); + }); + + it('should alias app.getLogger(\'noexist\') => null', () => { + (app.getLogger('noexist') === null).should.be.true(); + }); }); describe('app.inspect()', () => { diff --git a/test/app/extend/context.test.js b/test/app/extend/context.test.js index 6223718f3e..0ede75ab3f 100644 --- a/test/app/extend/context.test.js +++ b/test/app/extend/context.test.js @@ -100,6 +100,30 @@ describe('test/app/extend/context.test.js', () => { }); }); + describe('ctx.getLogger', () => { + let app; + before(() => { + app = utils.app('apps/get-logger'); + return app.ready(); + }); + after(() => app.close()); + + it('should return null when logger is not found', () => { + return request(app.callback()) + .get('/noExistLogger') + .expect('null'); + }); + + it('should log with padding message', function* () { + yield request(app.callback()) + .get('/logger') + .expect(200); + + const logPath = utils.getFilepath('apps/get-logger/logs/get-logger/a.log'); + fs.readFileSync(logPath, 'utf8').should.match(/\[-\/127.0.0.1\/-\/\d+ms GET \/logger\] aaa/); + }); + }); + describe('properties', () => { let app; before(() => { diff --git a/test/fixtures/apps/get-logger/app/router.js b/test/fixtures/apps/get-logger/app/router.js new file mode 100644 index 0000000000..1903c0ec42 --- /dev/null +++ b/test/fixtures/apps/get-logger/app/router.js @@ -0,0 +1,12 @@ +'use strict'; + +module.exports = function(app) { + app.get('/logger', function* () { + this.getLogger('aLogger').info('aaa'); + this.body = 'done'; + }); + + app.get('/noExistLogger', function* () { + this.body = this.app.getLogger('noexist') + ''; + }); +}; diff --git a/test/fixtures/apps/get-logger/config/config.js b/test/fixtures/apps/get-logger/config/config.js new file mode 100644 index 0000000000..53fba40f48 --- /dev/null +++ b/test/fixtures/apps/get-logger/config/config.js @@ -0,0 +1,13 @@ +'use strict'; + +const path = require('path'); + +module.exports = appInfo => { + return { + customLogger: { + aLogger: { + file: path.join(appInfo.baseDir, 'logs', appInfo.name, 'a.log'), + }, + }, + }; +}; diff --git a/test/fixtures/apps/get-logger/package.json b/test/fixtures/apps/get-logger/package.json new file mode 100644 index 0000000000..38918ab476 --- /dev/null +++ b/test/fixtures/apps/get-logger/package.json @@ -0,0 +1,3 @@ +{ + "name": "get-logger" +}