diff --git a/CHANGELOG.md b/CHANGELOG.md index ee74b54..869534a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,52 @@ +# [1.1.0](https://github.com/serverless-tencent/tencent-component-monitor/compare/v1.0.6...v1.1.0) (2020-05-28) + + +### Features + +* support no report flag ([982b418](https://github.com/serverless-tencent/tencent-component-monitor/commit/982b4182e513255f0d093c53aaf3136e0576cdd7)) + +## [1.0.6](https://github.com/serverless-tencent/tencent-component-monitor/compare/v1.0.5...v1.0.6) (2020-05-25) + + +### Bug Fixes + +* 上报增加100ms超时 ([a3f75dd](https://github.com/serverless-tencent/tencent-component-monitor/commit/a3f75dd05469e35204da38e3401b449539f685c0)) + +## [1.0.5](https://github.com/serverless-tencent/tencent-component-monitor/compare/v1.0.4...v1.0.5) (2020-05-20) + + +### Bug Fixes + +* remove monitor log ([62afa5b](https://github.com/serverless-tencent/tencent-component-monitor/commit/62afa5ba57e15af53382290d95b23ef32c30b68f)) + +## [1.0.4](https://github.com/serverless-tencent/tencent-component-monitor/compare/v1.0.3...v1.0.4) (2020-05-13) + + +### Bug Fixes + +* remove context decode ([286fe4b](https://github.com/serverless-tencent/tencent-component-monitor/commit/286fe4bb38e946cabeae61aa88cf40a4f05c0089)) + +## [1.0.3](https://github.com/serverless-tencent/tencent-component-monitor/compare/v1.0.2...v1.0.3) (2020-05-13) + + +### Bug Fixes + +* 获取context方式修改 ([d9e4dc6](https://github.com/serverless-tencent/tencent-component-monitor/commit/d9e4dc6ddccc3c8b84c0ce0152efb4bf3799a236)) + +## [1.0.2](https://github.com/serverless-tencent/tencent-component-monitor/compare/v1.0.1...v1.0.2) (2020-05-09) + + +### Bug Fixes + +* add report error log ([3305b52](https://github.com/serverless-tencent/tencent-component-monitor/commit/3305b52c47fbbe36f25ba96762427ec1324fd71b)) + +## [1.0.1](https://github.com/serverless-tencent/tencent-component-monitor/compare/v1.0.0...v1.0.1) (2020-05-08) + + +### Bug Fixes + +* 保证finalhandler时执行正常 ([47c33cf](https://github.com/serverless-tencent/tencent-component-monitor/commit/47c33cfed4865b74b173453ee088cb3a6265364e)) + # 1.0.0 (2020-05-06) diff --git a/package.json b/package.json index 0ddd6a9..50bb92f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tencent-component-monitor", - "version": "1.0.0", + "version": "1.1.0", "description": "Tencent component monitor", "main": "src/index.js", "scripts": { @@ -69,6 +69,6 @@ "semantic-release": "^17.0.4" }, "dependencies": { - "@tencent-sdk/capi": "0.2.15" + "@tencent-sdk/capi": "^0.2.16" } } diff --git a/src/agent.js b/src/agent.js index 6da88d9..f5b02f2 100644 --- a/src/agent.js +++ b/src/agent.js @@ -1,5 +1,15 @@ const { EventEmitter } = require('events') -class Agent extends EventEmitter {} +const Transaction = require('./transaction') + +class Agent extends EventEmitter { + constructor() { + super() + this._transaction = new Transaction() + } + get transaction() { + return this._transaction + } +} module.exports = Agent diff --git a/src/constants.js b/src/constants.js index 4470abf..7724b92 100644 --- a/src/constants.js +++ b/src/constants.js @@ -8,7 +8,8 @@ const MODULE_TYPE = { /** Web server framework module, such as Express or Koa. */ WEB_FRAMEWORK: 'web-framework', - PROXY: 'proxy' + PROXY: 'proxy', + TRANSACTION: 'transaction' } exports.MODULE_TYPE = MODULE_TYPE diff --git a/src/instrumentation/core/http.js b/src/instrumentation/core/http.js new file mode 100644 index 0000000..dfb3fbd --- /dev/null +++ b/src/instrumentation/core/http.js @@ -0,0 +1,54 @@ +const utils = require('../../utils') + +function wrapEmitWithTransaction(agent, emit) { + const { transaction } = agent + + return function wrappedHandler(evnt, request, response) { + transaction.init() + + function instrumentedFinish() { + response.removeListener('finish', instrumentedFinish) + request.removeListener('aborted', instrumentedFinish) + + // 状态码 + if (response.statusCode != null) { + const statusCode = String(response.statusCode) + const path = transaction.path || request.path + if (/^\d+$/.test(statusCode)) { + const context = request.__SLS_CONTEXT__ + const latency = Date.now() - transaction.start + const data = { + latency, + path, + method: request.method, + statusCode + } + agent.emit('responseFinish', context, data, request.__SLS_NO_REPORT__) + } + } + transaction.end() + } + // response结束时上报状态码和耗时 + response.once('finish', instrumentedFinish) + request.once('aborted', instrumentedFinish) + + return emit.apply(this, arguments) + } +} + +module.exports = function initialize(agent, http) { + if (!http) { + return false + } + + utils.wrapMethod(http.Server && http.Server.prototype, 'emit', function wrapEmit(emit) { + var txStarter = wrapEmitWithTransaction(agent, emit) + return function wrappedEmit(evnt) { + // 针对request事件做特殊逻辑 + if (evnt === 'request') { + return txStarter.apply(this, arguments) + } + return emit.apply(this, arguments) + } + }) +} diff --git a/src/instrumentation/express.js b/src/instrumentation/express.js index 0ff29d2..2cf3e92 100644 --- a/src/instrumentation/express.js +++ b/src/instrumentation/express.js @@ -38,27 +38,9 @@ module.exports = function initialize(agent, express) { utils.wrapMethod(layer, 'handle', function(func) { const { route } = layer const { path } = route - return function(request, response) { - function finish() { - response.removeListener('finish', finish) - request.removeListener('aborted', finish) - // 状态码 - if (response.statusCode != null) { - const responseCode = String(response.statusCode) - if (/^\d+$/.test(responseCode)) { - const context = request.headers['x-apigateway-context'] - agent.emit('responseFinish', context, request.method, path, responseCode) - } - } - } - - // response结束时上报状态码和耗时 - response.once('finish', finish) - request.once('aborted', finish) - - const handle = func.apply(this, arguments) - return handle - } + const { transaction } = agent + transaction.path = path + return func }) } return sourceRoute diff --git a/src/instrumentation/tencent-serverless-http.js b/src/instrumentation/tencent-serverless-http.js index 36bceb2..7b64ef8 100644 --- a/src/instrumentation/tencent-serverless-http.js +++ b/src/instrumentation/tencent-serverless-http.js @@ -1,17 +1,22 @@ const utils = require('../utils') -const { REUQEST_START_KEY } = require('../constants') const report = require('../report') module.exports = function initialize(agent, httpProxy) { utils.wrapMethod(httpProxy, 'proxy', function wrapRoute(fn) { - return function(server, event, context) { - context[REUQEST_START_KEY] = Date.now() + return function() { + const { transaction } = agent + transaction.init() const proxy = fn.apply(this, arguments) return new Promise(function(resolve) { - agent.once('responseFinish', function(ctx, method, path, responseCode) { - if (ctx) { - report.reportHttp(ctx, method, path, responseCode).then( - function() { + agent.once('responseFinish', function(ctx, data, noReport) { + if (ctx && noReport !== true) { + report.reportHttp(ctx, data).then( + function(/* _data*/) { + // const { Response } = _data || {} + // const { Error: error } = Response || {} + // if (error && error.Message) { + // console.warn('Report monitor data error: ' + error.Message) + // } resolve(proxy) }, function() { diff --git a/src/report.js b/src/report.js index 8996db9..976363d 100644 --- a/src/report.js +++ b/src/report.js @@ -1,6 +1,5 @@ const { Capi } = require('@tencent-sdk/capi') -const logger = require('./logger') -const { REUQEST_START_KEY } = require('./constants') +// const logger = require('./logger') // 字符串转16进制 function str2hex(str) { @@ -14,9 +13,8 @@ function str2hex(str) { return arr.join('') } -exports.reportHttp = async function(context, method, path, statusCode) { +exports.reportHttp = async function(context, { latency, method, path, statusCode }) { try { - context = JSON.parse(decodeURIComponent(context)) // 自定级监控上报的指标名只支持【a-zA-Z0-9_-】,所以把path进行转义上报 path = str2hex(path) const ServiceType = 'monitor' @@ -36,7 +34,7 @@ exports.reportHttp = async function(context, method, path, statusCode) { } = environment const Region = tencentcloud_region || envTencentRegion || envRegion || 'ap-guangzhou' if (!SecretId || !SecretKey) { - logger.warn('No SecretId or SecretKey in environment parameters.') + // logger.warn('Report monitor data error: No SecretId or SecretKey in environment parameters.') return } const client = new Capi({ @@ -52,10 +50,10 @@ exports.reportHttp = async function(context, method, path, statusCode) { } const debugOptions = { debug: false, - host: 'monitor.tencentcloudapi.com' + host: 'monitor.tencentcloudapi.com', + timeout: 100 } - const latency = Date.now() - context[REUQEST_START_KEY] const keyPrefix = `${method}_${path}` const Metrics = [ { MetricName: 'request', Value: 1 }, diff --git a/src/shimmer.js b/src/shimmer.js index af7c60a..2c48104 100644 --- a/src/shimmer.js +++ b/src/shimmer.js @@ -3,12 +3,25 @@ const fs = require('fs') const utils = require('./utils') const INSTRUMENTATIONS = require('./instrumentations')() -function _firstPartyInstrumentation(agent, fileName, nodule) { +const { MODULE_TYPE } = require('./constants') + +const CORE_INSTRUMENTATION = { + http: { + type: MODULE_TYPE.TRANSACTION, + file: 'http.js' + }, + https: { + type: MODULE_TYPE.TRANSACTION, + file: 'http.js' + } +} + +function _firstPartyInstrumentation(agent, fileName, nodule, moduleName) { if (!fs.existsSync(fileName)) { return } try { - return require(fileName)(agent, nodule) + return require(fileName)(agent, nodule, moduleName) } catch (error) { agent.emit('responseFinish') } @@ -73,6 +86,19 @@ const shimmer = { }, bootstrapInstrumentation: function bootstrapInstrumentation(agent) { + // Instrument each of the core modules. + Object.keys(CORE_INSTRUMENTATION).forEach(function forEachCore(mojule) { + const core = CORE_INSTRUMENTATION[mojule] + const filePath = path.join(__dirname, 'instrumentation', 'core', core.file) + let uninstrumented = null + + try { + uninstrumented = require(mojule) + } catch (err) {} + + _firstPartyInstrumentation(agent, filePath, uninstrumented) + }) + // 注册所有注入模块 Object.keys(INSTRUMENTATIONS).forEach(function forEachInstrumentation(moduleName) { const instrInfo = INSTRUMENTATIONS[moduleName] diff --git a/src/transaction/index.js b/src/transaction/index.js new file mode 100644 index 0000000..6ff162f --- /dev/null +++ b/src/transaction/index.js @@ -0,0 +1,19 @@ +class Transaction { + get start() { + return this._start + } + set Path(path) { + this._path = path + } + get path() { + return this._path + } + init() { + this._start = Date.now() + } + end() { + this._start = null + this._path = null + } +} +module.exports = Transaction