UNPKG

atatus-nodejs

Version:

Atatus APM agent for Node.js

248 lines (189 loc) 6.84 kB
const Transporter = require('../transporter') function Reporter(agent, aggregator) { this.agent = agent this.aggregator = aggregator this.transporter = new Transporter(agent) } Reporter.prototype.start = function start(callback) { if (!callback) throw new TypeError("callback required!") let reporter = this // For quicker data display, flush in 10 seconds after the startup setTimeout(function intitial_delayed_flush() { reporter.flush(function cb_flush(error) { reporter._startReporter(reporter.agent._conf.metricsInterval) reporter.transporter.sendHostInfo(callback) }) }, 10000) } Reporter.prototype.stop = function stop(callback) { if (!callback) throw new TypeError("callback required!") this._stopReporter() process.nextTick(callback) } Reporter.prototype.flush = function flush(callback) { if (!callback) throw new TypeError("callback required!") let reporter = this let reporterSteps = [ '_reportTransactions', '_reportTraces', '_reportErrorEvents', '_reportErrorMetrics', '_reportHostInfo', '_reportMetrics', '_reportAnalytics', ] runReporterStep(0) function runReporterStep(n) { reporter[reporterSteps[n++]](next) function next(error) { if (error || n >= reporterSteps.length) return callback(error) runReporterStep(n) } } } Reporter.prototype._restartReporter = function _restartReporter(flushSeconds) { this._stopReporter() this._startReporter(flushSeconds) } Reporter.prototype._stopReporter = function _stopReporter() { if (this.lifeCycleThread) clearInterval(this.lifeCycleThread) this.lifeCycleThread = undefined } Reporter.prototype._startReporter = function _startReporter(flushSeconds) { let reporter = this function onError(error) { if (error) { reporter.agent.logger.info(error && error.message, "Unable to send data to Atatus server.") } } function flush() { reporter.flush(onError) } this.lifeCycleThread = setInterval(flush, flushSeconds * 1000) if (this.lifeCycleThread.unref) this.lifeCycleThread.unref() } Reporter.prototype._reportTransactions = function _reportTransactions(callback) { if (this.aggregator.isTransactionsEmpty()) { this.agent.logger.debug("No transactions to send.") return process.nextTick(callback) } let reporter = this let payload = this.aggregator.getAndResetTransactionsPayload(); this.transporter.send('transactions', payload, function cb_transactions(error) { if (error) reporter.aggregator.mergeTransactions(payload) callback(error) }) } Reporter.prototype._reportAnalytics = function _reportAnalytics(callback) { // Here we don't need to verify backend config analytics // Because if host info set backend config analytics to false, // then analytics payload queue will be there forever. // Once backend config analytic set to false, then we will drop in aggregator. if (!this.agent._conf.analytics) { this.agent.logger.debug("Analytics is not enabled.") this.aggregator.resetAnalyticsEvents() return process.nextTick(callback) } if (this.aggregator.isAnalyticsEmpty()) { this.agent.logger.debug("No analytic events to send.") return process.nextTick(callback) } let reporter = this let payload = this.aggregator.getAndResetAnalyticsPayload(); let analyticsSanitizedData = [] let analyticsPayloadLen = 0 let requests = payload.requests if (payload.size > 6 * 1024 * 1024) { for (let i = 0; i < requests.length; i++) { analyticsSanitizedData.push(requests[i]) analyticsPayloadLen += (requests[i].bodyLength || 0) if (analyticsPayloadLen > 6 * 1024 * 1024) { payload.requests = analyticsSanitizedData this.transporter.send('analytics', payload, function cb_analytics(error) { if (error) reporter.aggregator.mergeAnalyticsEvents(payload) }) analyticsSanitizedData = [] analyticsPayloadLen = 0 } } } else { analyticsSanitizedData = requests; } if (analyticsSanitizedData.length > 0) { payload.requests = analyticsSanitizedData this.transporter.send('analytics', payload, function cb_analytics(error) { if (error) reporter.aggregator.mergeAnalyticsEvents(payload) callback(error) }) analyticsSanitizedData = [] analyticsPayloadLen = 0 } else { callback(null) } } Reporter.prototype._reportTraces = function _reportTraces(callback) { if (this.aggregator.isTracesEmpty()) { this.agent.logger.debug("No traces to send.") return process.nextTick(callback) } let reporter = this let payload = this.aggregator.getAndResetTracesPayload(); this.transporter.send('traces', payload, function cb_traces(error) { if (error) reporter.aggregator.mergeTraces(payload) callback(error) }) } Reporter.prototype._reportErrorEvents = function _reportErrorEvents(callback) { if (this.agent._conf.captureExceptions) { if (this.aggregator.isErrorEventsEmpty()) { this.agent.logger.debug("No error events to send.") return process.nextTick(callback) } let reporter = this let payload = this.aggregator.getAndResetErrorEventsPayload() this.transporter.send('errorEvents', payload, function cb_errorEvents(error) { if (error) reporter.aggregator.mergeErrorEventsPayload(payload) callback(error) }) } else { this.aggregator.resetErrorEvents() process.nextTick(callback) } } Reporter.prototype._reportErrorMetrics = function _reportErrorMetrics(callback) { if (this.aggregator.isErrorMetricsEmpty()) { this.agent.logger.debug("No error metrics to send.") return process.nextTick(callback) } let reporter = this let payload = this.aggregator.getAndResetErrorMetricsPayload() this.transporter.send('errorMetrics', payload, function cb_errorMetrics(error) { if (error) reporter.aggregator.mergeErrorMetrics(payload) callback(error) }) } Reporter.prototype._reportHostInfo = function _reportHostInfo(callback) { let currentMinute = new Date().getMinutes() if (currentMinute === 0 || currentMinute === 30) { // Only send host info for every 30 minutes this.transporter.sendHostInfo(function cb_hostInfo(error) { callback(error) }) } else { return process.nextTick(callback) } } Reporter.prototype._reportMetrics = function _reportMetrics(callback) { if (this.aggregator.isMetricsEmpty()) { this.agent.logger.debug("No system metrics to send.") return process.nextTick(callback) } let reporter = this let payload = this.aggregator.getAndResetMetrics(); this.transporter.send('metrics', payload, function cb_metrics(error) { if (error) reporter.aggregator.mergeMetrics(payload) callback(error) }) } module.exports = Reporter