diff --git a/agent.js b/agent.js new file mode 100644 index 0000000..3069b99 --- /dev/null +++ b/agent.js @@ -0,0 +1,3 @@ +'use strict'; + +module.exports = require('./index'); diff --git a/app.js b/app.js new file mode 100644 index 0000000..3069b99 --- /dev/null +++ b/app.js @@ -0,0 +1,3 @@ +'use strict'; + +module.exports = require('./index'); diff --git a/app/extend/agent.js b/app/extend/agent.js new file mode 100644 index 0000000..a6ac241 --- /dev/null +++ b/app/extend/agent.js @@ -0,0 +1,3 @@ +'use strict'; + +module.exports = require('../../lib/index.js'); diff --git a/app/extend/application.js b/app/extend/application.js new file mode 100644 index 0000000..a6ac241 --- /dev/null +++ b/app/extend/application.js @@ -0,0 +1,3 @@ +'use strict'; + +module.exports = require('../../lib/index.js'); diff --git a/appveyor.yml b/appveyor.yml index ec7400e..0ef97fa 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,7 +1,7 @@ environment: matrix: - nodejs_version: '6' - - nodejs_version: '7' + - nodejs_version: '8' install: - ps: Install-Product node $env:nodejs_version diff --git a/index.js b/index.js new file mode 100644 index 0000000..bfed49c --- /dev/null +++ b/index.js @@ -0,0 +1,10 @@ +'use strict'; + +const isReady = Symbol.for('egg_tracer_is_ready'); + +module.exports = app => { + app.ready(() => { + app[isReady] = true; + }); +}; + diff --git a/lib/index.js b/lib/index.js new file mode 100644 index 0000000..7e448e8 --- /dev/null +++ b/lib/index.js @@ -0,0 +1,22 @@ +'use strict'; + +const cacheTracer = Symbol('before_ready_tracer'); +const isReady = Symbol.for('egg_tracer_is_ready'); + +module.exports = { + get tracer() { + if (this[isReady]) { + return new this.config.tracer.Class({ + app: this, + }); + } + + if (!this[cacheTracer]) { + this[cacheTracer] = new this.config.tracer.Class({ + app: this, + }); + } + + return this[cacheTracer]; + }, +}; diff --git a/package.json b/package.json index 743ef44..f81cf4d 100644 --- a/package.json +++ b/package.json @@ -7,9 +7,12 @@ }, "main": "lib/tracer.js", "files": [ + "lib", "app", "config", - "lib" + "agent.js", + "index.js", + "app.js" ], "keywords": [ "egg", @@ -28,7 +31,7 @@ "egg": "^0.10.0", "egg-bin": "^2.0.2", "egg-ci": "^1.1.0", - "egg-mock": "^2.3.1", + "egg-mock": "^3.8.0", "eslint": "^3.14.1", "eslint-config-egg": "^3.2.0", "supertest": "^3.0.0" @@ -42,7 +45,8 @@ "test-local": "egg-bin test", "cov": "egg-bin cov", "lint": "eslint .", - "ci": "npm run lint && npm run cov" + "pkgfiles": "egg-bin pkgfiles", + "ci": "egg-bin pkgfiles --check && npm run lint && npm run cov" }, "ci": { "version": "6, 7" diff --git a/test/error.tracer.test.js b/test/error.tracer.test.js new file mode 100644 index 0000000..0a522c0 --- /dev/null +++ b/test/error.tracer.test.js @@ -0,0 +1,34 @@ +'use strict'; + +const mm = require('egg-mock'); +const assert = require('assert'); + +describe('test/error.tracer.test.js', () => { + let app; + before(() => { + app = mm.app({ + baseDir: 'apps/error-tracer-test', + }); + return app.ready(); + }); + + after(() => app.close()); + + afterEach(mm.restore); + + it('should get app, agent tracer is null', function* () { + assert(app.appBeforeReadyTracers.length === 0); + assert(app.agent.agentBeforeReadyTracers.length === 0); + + assert(app.appAfterReadyTracers.length === 0); + assert(app.agent.agentAfterReadyTracers.length === 0); + }); + + it('should GET /', () => { + return app.httpRequest() + .get('/') + .expect('x-trace-id', /\w{13}/) + .expect('hi, egg') + .expect(200); + }); +}); diff --git a/test/fixtures/apps/error-tracer-test/agent.js b/test/fixtures/apps/error-tracer-test/agent.js new file mode 100644 index 0000000..3ba49e8 --- /dev/null +++ b/test/fixtures/apps/error-tracer-test/agent.js @@ -0,0 +1,29 @@ +'use strict'; + + +module.exports = agent => { + const agentBeforeReadyTracers = []; + const agentAfterReadyTracers = []; + + agent.agentBeforeReadyTracers = agentBeforeReadyTracers; + agent.agentAfterReadyTracers = agentAfterReadyTracers; + + try { + agentBeforeReadyTracers.push(agent.tracer); + agentBeforeReadyTracers.push(agent.tracer); + agentBeforeReadyTracers.push(agent.tracer); + + } catch (e) { + agent.coreLogger.warn(e); + } + + agent.ready(() => { + try { + agentAfterReadyTracers.push(agent.tracer); + agentAfterReadyTracers.push(agent.tracer); + agentAfterReadyTracers.push(agent.tracer); + } catch (e) { + agent.coreLogger.warn(e); + } + }); +}; diff --git a/test/fixtures/apps/error-tracer-test/app.js b/test/fixtures/apps/error-tracer-test/app.js new file mode 100644 index 0000000..475546e --- /dev/null +++ b/test/fixtures/apps/error-tracer-test/app.js @@ -0,0 +1,29 @@ +'use strict'; + + +module.exports = app => { + const appBeforeReadyTracers = []; + const appAfterReadyTracers = []; + + app.appBeforeReadyTracers = appBeforeReadyTracers; + app.appAfterReadyTracers = appAfterReadyTracers; + + try { + appBeforeReadyTracers.push(app.tracer); + appBeforeReadyTracers.push(app.tracer); + appBeforeReadyTracers.push(app.tracer); + + } catch (e) { + app.coreLogger.warn(e); + } + + app.ready(() => { + try { + appAfterReadyTracers.push(app.tracer); + appAfterReadyTracers.push(app.tracer); + appAfterReadyTracers.push(app.tracer); + } catch (e) { + app.coreLogger.warn(e); + } + }); +}; diff --git a/test/fixtures/apps/error-tracer-test/app/router.js b/test/fixtures/apps/error-tracer-test/app/router.js new file mode 100644 index 0000000..d57a9ff --- /dev/null +++ b/test/fixtures/apps/error-tracer-test/app/router.js @@ -0,0 +1,11 @@ +'use strict'; + +const assert = require('assert'); + +module.exports = app => { + app.get('/', function* () { + assert(this.traceId === this.traceId); + this.set('x-trace-id', this.traceId); + this.body = 'hi, egg'; + }); +}; diff --git a/test/fixtures/apps/error-tracer-test/config/config.default.js b/test/fixtures/apps/error-tracer-test/config/config.default.js new file mode 100644 index 0000000..cae008a --- /dev/null +++ b/test/fixtures/apps/error-tracer-test/config/config.default.js @@ -0,0 +1,22 @@ +'use strict'; + +/** + * tracer config + * @member Config#tracer + * @property {Tracer} Class - tracer class name + */ +exports.tracer = { + Class: class Tracer { + constructor(ctx) { + this.ctx = ctx; + this.name = ctx.locals.name; + } + + get traceId() { + if (!this.TRACE_ID) { + this.TRACE_ID = Date.now(); + } + return this.TRACE_ID; + } + }, +}; diff --git a/test/fixtures/apps/error-tracer-test/package.json b/test/fixtures/apps/error-tracer-test/package.json new file mode 100644 index 0000000..c0c85f5 --- /dev/null +++ b/test/fixtures/apps/error-tracer-test/package.json @@ -0,0 +1,3 @@ +{ + "name": "error-tracer-test" +} \ No newline at end of file diff --git a/test/fixtures/apps/plugin-test/agent.js b/test/fixtures/apps/plugin-test/agent.js new file mode 100644 index 0000000..7143520 --- /dev/null +++ b/test/fixtures/apps/plugin-test/agent.js @@ -0,0 +1,20 @@ +'use strict'; + + +module.exports = agent => { + const agentBeforeReadyTracers = []; + const agentAfterReadyTracers = []; + + agentBeforeReadyTracers.push(agent.tracer); + agentBeforeReadyTracers.push(agent.tracer); + agentBeforeReadyTracers.push(agent.tracer); + + agent.agentBeforeReadyTracers = agentBeforeReadyTracers; + agent.agentAfterReadyTracers = agentAfterReadyTracers; + + agent.ready(() => { + agentAfterReadyTracers.push(agent.tracer); + agentAfterReadyTracers.push(agent.tracer); + agentAfterReadyTracers.push(agent.tracer); + }); +}; diff --git a/test/fixtures/apps/plugin-test/app.js b/test/fixtures/apps/plugin-test/app.js new file mode 100644 index 0000000..c7cd6c3 --- /dev/null +++ b/test/fixtures/apps/plugin-test/app.js @@ -0,0 +1,20 @@ +'use strict'; + + +module.exports = app => { + const appBeforeReadyTracers = []; + const appAfterReadyTracers = []; + + appBeforeReadyTracers.push(app.tracer); + appBeforeReadyTracers.push(app.tracer); + appBeforeReadyTracers.push(app.tracer); + + app.appBeforeReadyTracers = appBeforeReadyTracers; + app.appAfterReadyTracers = appAfterReadyTracers; + + app.ready(() => { + appAfterReadyTracers.push(app.tracer); + appAfterReadyTracers.push(app.tracer); + appAfterReadyTracers.push(app.tracer); + }); +}; diff --git a/test/plugin.test.js b/test/plugin.test.js index 2c0feea..ef5c2cd 100644 --- a/test/plugin.test.js +++ b/test/plugin.test.js @@ -1,6 +1,5 @@ 'use strict'; -const request = require('supertest'); const mm = require('egg-mock'); describe('test/plugin.test.js', () => { @@ -17,7 +16,7 @@ describe('test/plugin.test.js', () => { afterEach(mm.restore); it('should GET /', () => { - return request(app.callback()) + return app.httpRequest() .get('/') .expect('x-trace-id', /\w{8}-\w{4}-\w{4}-\w{4}-\w{12}/) .expect('hi, egg') diff --git a/test/tracer.test.js b/test/tracer.test.js new file mode 100644 index 0000000..7d1f1cc --- /dev/null +++ b/test/tracer.test.js @@ -0,0 +1,85 @@ +'use strict'; + +const mm = require('egg-mock'); +const assert = require('assert'); + +describe('test/tracer.test.js', () => { + let app; + before(() => { + app = mm.app({ + baseDir: 'apps/plugin-test', + }); + return app.ready(); + }); + + after(() => app.close()); + + afterEach(mm.restore); + + it('should get app, agent tracer', function* () { + assert(app[Symbol.for('egg_tracer_is_ready')]); + assert(app.agent[Symbol.for('egg_tracer_is_ready')]); + + let [ appTracer_1, appTracer_2, appTracer_3 ] = app.appBeforeReadyTracers; + let [ agentTracer_1, agentTracer_2, agentTracer_3 ] = app.agent.agentBeforeReadyTracers; + + assert(appTracer_1 === appTracer_2); + assert(appTracer_1 === appTracer_3); + + assert(appTracer_1.traceId); + assert(appTracer_2.traceId); + assert(appTracer_3.traceId); + + assert(appTracer_1 === appTracer_2); + assert(appTracer_1 === appTracer_3); + + assert(appTracer_1.traceId === appTracer_2.traceId); + assert(appTracer_1.traceId === appTracer_3.traceId); + + assert(agentTracer_1.traceId); + assert(agentTracer_2.traceId); + assert(agentTracer_3.traceId); + + assert(agentTracer_1 === agentTracer_2); + assert(agentTracer_1 === agentTracer_3); + + assert(agentTracer_1.traceId); + assert(agentTracer_2.traceId); + assert(agentTracer_3.traceId); + + assert(agentTracer_1.traceId === agentTracer_2.traceId); + assert(agentTracer_1.traceId === agentTracer_3.traceId); + + // app ready + [ appTracer_1, appTracer_2, appTracer_3 ] = app.appAfterReadyTracers; + + assert(appTracer_1 !== appTracer_2); + assert(appTracer_1 !== appTracer_3); + + assert(appTracer_1.traceId); + assert(appTracer_2.traceId); + assert(appTracer_3.traceId); + + assert(appTracer_1 !== appTracer_2); + assert(appTracer_1 !== appTracer_3); + + assert(appTracer_1.traceId !== appTracer_2.traceId); + assert(appTracer_1.traceId !== appTracer_3.traceId); + + // agent ready + [ agentTracer_1, agentTracer_2, agentTracer_3 ] = app.agent.agentAfterReadyTracers; + assert(agentTracer_1.traceId); + assert(agentTracer_2.traceId); + assert(agentTracer_3.traceId); + + assert(agentTracer_1 !== agentTracer_2); + assert(agentTracer_1 !== agentTracer_3); + + assert(agentTracer_1.traceId); + assert(agentTracer_2.traceId); + assert(agentTracer_3.traceId); + + assert(agentTracer_1.traceId !== agentTracer_2.traceId); + assert(agentTracer_1.traceId !== agentTracer_3.traceId); + }); +});