UNPKG

pinpoint-node-agent

Version:

Pinpoint APM agent for Node.js — distributed tracing, error analysis, and URI statistics

189 lines (155 loc) 6.22 kB
/** * Pinpoint Node.js Agent * Copyright 2020-present NAVER Corp. * Apache License v2.0 */ 'use strict' const logger = require('./utils/log/logger') const dataSenderFactory = require('./client/data-sender-factory') const stringMetaService = require('./context/string-meta-service') const apiMetaService = require('./context/api-meta-service') const TraceContext = require('./context/trace-context') const { ModuleHook } = require('./instrumentation/module-hook') const Scheduler = require('./utils/scheduler') const AgentStatsMonitor = require('./metric/agent-stats-monitor') const PingScheduler = require('./metric/ping-scheduler') const { ConfigBuilder } = require('./config-builder') const { SpanRecorderFactory } = require('./context/trace/span-recorder-factory') const { SqlMetadataService } = require('./instrumentation/sql/sql-metadata-service') const { IntIdParsingResultFactory } = require('./context/trace/parsing-result-factory') const SpanEventRecorderFactory = require('./context/trace/span-event-recorder-factory') const { CompositeTraceCompletionEnricher } = require('./context/trace/composite-trace-completion-enricher') class Agent { constructor(agentInfo, dataSender, config, logger, traceCompletionEnricher, spanRecorderFactory, spanEventRecorderFactory) { this.agentInfo = agentInfo this.dataSender = dataSender this.config = config this.logger = logger this.traceContext = new TraceContext(agentInfo, dataSender, config, traceCompletionEnricher, spanRecorderFactory, spanEventRecorderFactory) } start() { this.logger.warn('[Pinpoint Agent] Configuration', this.config) if (typeof this.config?.enable === 'boolean' && !this.config.enable) { this.logger.warn('[Pinpoint Agent][' + this.config.agentId + '] Disabled') return } this.dataSender.send(this.agentInfo) stringMetaService.init(this.dataSender) apiMetaService.init(this.dataSender) this.moduleHook = new ModuleHook(this) this.moduleHook.start() this.shutdownServices = this.services .map(service => service.call(this, this.dataSender)) .filter(service => service && typeof service.shutdown === 'function') this.logger.warn('[Pinpoint Agent][' + this.config.agentId + '] Initialized', this.agentInfo) } createTraceObject() { return this.traceContext.newTraceObject() } currentTraceObject() { return this.traceContext.currentTraceObject() } completeTraceObject(trace) { this.traceContext.completeTraceObject(trace) } getAgentInfo() { return this.agentInfo } getTraceContext() { return this.traceContext } shutdown() { this.mainScheduler?.stop() this.pingScheduler?.stop() this.moduleHook?.stop() this.shutdownServices?.forEach(service => service.shutdown()) } } class AgentBuilder { constructor(agentInfo) { this.agentInfo = agentInfo this.services = [] this.enableStatsMonitor = true this.enablePingScheduler = true this.enableServiceCommand = true this.enrichers = [] } setConfig(config) { this.config = config return this } setDataSender(dataSender) { this.dataSender = dataSender return this } setLogger(logger) { this.logger = logger return this } addService(service) { this.services.push(service) return this } disableStatsScheduler() { this.enableStatsMonitor = false return this } disablePingScheduler() { this.enablePingScheduler = false return this } disableServiceCommand() { this.enableServiceCommand = false return this } addEnricher(enricher) { this.enrichers.push(enricher) return this } setSpanRecorderFactory(spanRecorderFactory) { this.spanRecorderFactory = spanRecorderFactory return this } setParsingResultFactory(parsingResultFactory) { this.parsingResultFactory = parsingResultFactory return this } build() { if (!this.config) { this.config = new ConfigBuilder().build() } if (!this.dataSender) { this.dataSender = dataSenderFactory.create(this.config, this.agentInfo) } if (!this.spanRecorderFactory) { this.spanRecorderFactory = new SpanRecorderFactory(this.config) } const parsingResultFactory = this.parsingResultFactory ?? new IntIdParsingResultFactory() const sqlMetadataService = new SqlMetadataService(this.dataSender, parsingResultFactory) const exceptionSpanEventEnricher = this.enrichers.find(e => typeof e.recordException === 'function') const spanEventRecorderFactory = new SpanEventRecorderFactory(sqlMetadataService, exceptionSpanEventEnricher) const traceCompletionEnricher = CompositeTraceCompletionEnricher.make(this.enrichers) const agent = new Agent(this.agentInfo, this.dataSender, this.config, this.logger ?? logger.getLogger(), traceCompletionEnricher, this.spanRecorderFactory, spanEventRecorderFactory) if (this.enableStatsMonitor || this.config.isStatsMonitoringEnabled()) { this.addService((dataSender) => { this.mainScheduler = new Scheduler(5000) const agentStatsMonitor = new AgentStatsMonitor(dataSender, this.agentInfo.getAgentId(), this.agentInfo.getAgentStartTime()) this.mainScheduler.addJob(() => { agentStatsMonitor.run() }) this.mainScheduler.start() }) } if (this.enablePingScheduler) { this.addService((dataSender) => { this.pingScheduler = new PingScheduler(dataSender) }) } if (this.enableServiceCommand) { this.addService((dataSender) => { dataSender.sendSupportedServicesCommand() }) } agent.services = this.services return agent } } module.exports = { Agent, AgentBuilder }