forked from pinpoint-apm/pinpoint-node-agent
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathagent.js
157 lines (129 loc) · 5.25 KB
/
agent.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/**
* Pinpoint Node.js Agent
* Copyright 2020-present NAVER Corp.
* Apache License v2.0
*/
'use strict'
const ModuleHook = require('./instrumentation/module-hook')
const traceContext = require('./context/trace-context')
const log = require('./utils/logger')
const stringMetaService = require('./context/string-meta-service')
const apiMetaService = require('./context/api-meta-service')
const Scheduler = require('./utils/scheduler')
const AgentStatsMonitor = require('./metric/agent-stats-monitor')
const getConfig = require('./config').getConfig
const PinpointClient = require('./client/pinpoint-client')
const dataSenderFactory = require('./client/data-sender-factory')
const AgentInfo = require('./data/dto/agent-info')
const wrapped = Symbol('pinpoint-wrapped-function')
const PinScheduler = require('./metric/ping-scheduler')
class Agent {
constructor(initOptions) {
this.config = getConfig(initOptions)
log.warn('[Pinpoint Agent] Configuration', this.config)
if (!this.config.enable || this.config.enable.toString() !== 'true') {
global.__PINPOINT_ENABLED__ = false
log.warn('[Pinpoint Agent][' + this.config.agentId + '] Disabled')
return
}
global.__PINPOINT_ENABLED__ = true
log.warn('[Pinpoint Agent][' + this.config.agentId + '] Init Started')
const agentId = this.config.agentId
const agentStartTime = Date.now()
this.agentInfo = this.createAgentInfo(this.config, agentStartTime)
this.initializeDataSender()
this.initializePinpointClient()
this.traceContext = traceContext.init(this.agentInfo, this.dataSender, this.config)
stringMetaService.init(this.dataSender)
apiMetaService.init(this.dataSender)
this.startSchedule(agentId, agentStartTime)
this.initailizeSupportModules()
log.warn('[Pinpoint Agent][' + agentId + '] Init Completed')
}
initializeDataSender() {
this.dataSender = dataSenderFactory.create(this.config, this.agentInfo)
this.dataSender.send(this.agentInfo)
}
initailizeSupportModules() {
this.moduleHook = new ModuleHook(this)
}
initializePinpointClient() {
this.pinpointClient = new PinpointClient(this.config, this.agentInfo, this.dataSender)
}
createTraceObject(requestData) {
return this.traceContext.makeTrace(requestData)
}
currentTraceObject() {
return this.traceContext.currentTraceObject()
}
completeTraceObject(trace) {
this.traceContext.completeTraceObject(trace)
if (trace.span) {
/*
const spanEvent = []
// step1. 우선 비동기 코드 (추후 더미코드) 를 먼저 가져오도록 한다.
const dummyEventMap = trace.span.spanEventList.reduce((map, dummyEvent) => {
if (dummyEvent.serviceType === ServiceTypeCode.callback_dummy) {
map[dummyEvent.nextDummyId] = dummyEvent
}
return map
}, {})
// step2. 콜백코드로 저장된 걸 가져오도록 한다. (순서가 보장 안되기 때문에 해당 과정이 필요하다.. )
const callEvent = trace.span.spanEventList.reduce((map, callbackEvent) => {
if (callbackEvent.dummyId !== null) {
map.push(callbackEvent)
}
return map
}, [])
// step3. 비동기 코드를 순차적으로 우회하며 돌도록 한다.
callEvent.forEach((event) => {
const dummyRecoder = dummyEventMap[event.dummyId]
if (dummyRecoder) {
event.sequence = dummyRecoder.sequence
event.depth = dummyRecoder.depth
//TODO. agent view 에서 문제가 있기에 우선 임의로 넣어둔다. (paas와 논의 필요)
// event.startElapsed = dummyRecoder.startElapsed
// event.elapsedTime = dummyRecoder.elapsedTime
if (event.nextDummyId !== null) {
//TODO. event chaiing인 경우 depth 등을 조정해야한다. 순서가 보장안될 수 있으니.. 차순 변경 후 가도 될 듯
dummyEventMap[event.nextDummyId].sequence = event.sequence + 1
dummyEventMap[event.nextDummyId].depth = event.depth + 1
}
}
})
trace.span.spanEventList.forEach((event) => {
if (event.serviceType !== ServiceTypeCode.callback_dummy) {
spanEvent.push(event)
}
})
trace.span.spanEventList = spanEvent
log.debug('finally->\n', trace.span)
*/
}
}
createAgentInfo(config, agentStartTime) {
return AgentInfo.create(config, agentStartTime)
}
startSchedule(agentId, agentStartTime) {
if (this.config.enabledStatsMonitor) {
this.mainScheduler = new Scheduler(5000)
const agentStatsMonitor = new AgentStatsMonitor(this.pinpointClient.dataSender, agentId, agentStartTime)
this.mainScheduler.addJob(() => { agentStatsMonitor.run() })
this.mainScheduler.start()
}
this.pingScheduler = new PinScheduler(this.dataSender)
}
spanEndCallbackWrapper(trace, spanEventRecorder, original) {
if (typeof original !== 'function' || original.name === 'pinpointCallbackWrapper') return original
if (trace && !trace.canSampled()) {
return original
}
original[wrapped] = pinpointCallbackWrapper
return pinpointCallbackWrapper
function pinpointCallbackWrapper() {
const result = original.apply(this, arguments)
return result
}
}
}
module.exports = Agent