whatap 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (198) hide show
  1. package/README.md +32 -78
  2. package/lib/conf/conf-sys-mon.js +101 -0
  3. package/lib/conf/config-default.js +10 -3
  4. package/lib/conf/configure.js +369 -349
  5. package/lib/conf/license.js +1 -1
  6. package/lib/control/cmd-config.js +24 -0
  7. package/lib/control/control-handler.js +367 -0
  8. package/lib/control/packagectr-helper.js +34 -3
  9. package/lib/core/agent.js +176 -882
  10. package/lib/core/interceptor.js +6 -6
  11. package/lib/core/request-agent.js +27 -0
  12. package/lib/core/shimmer.js +82 -36
  13. package/lib/counter/counter-manager.js +79 -8
  14. package/lib/counter/meter/meter-activex.js +67 -0
  15. package/lib/counter/meter/meter-httpc.js +57 -0
  16. package/lib/counter/meter/meter-resource.js +9 -0
  17. package/lib/counter/meter/meter-service.js +168 -0
  18. package/lib/counter/meter/meter-socket.io.js +51 -0
  19. package/lib/counter/meter/meter-sql.js +71 -0
  20. package/lib/counter/meter/meter-users.js +58 -0
  21. package/lib/counter/meter.js +183 -0
  22. package/lib/counter/task/activetransaction.js +68 -17
  23. package/lib/counter/task/agentinfo.js +107 -0
  24. package/lib/{system → counter/task}/gc-action.js +27 -74
  25. package/lib/counter/task/gcstat.js +34 -0
  26. package/lib/counter/task/heapmem.js +25 -0
  27. package/lib/counter/task/httpc.js +76 -0
  28. package/lib/counter/task/metering-info.js +125 -0
  29. package/lib/counter/task/proc-cpu.js +29 -0
  30. package/lib/counter/task/realtimeuser.js +31 -0
  31. package/lib/counter/task/res/systemECSTask.js +39 -0
  32. package/lib/counter/task/res/systemKubeTask.js +53 -0
  33. package/lib/counter/task/res/util/awsEcsClientThread.js +218 -0
  34. package/lib/counter/task/res/util/linuxProcStatUtil.js +14 -0
  35. package/lib/counter/task/res-sys-cpu.js +62 -0
  36. package/lib/counter/task/service.js +202 -0
  37. package/lib/counter/task/socketio.js +30 -0
  38. package/lib/counter/task/sql.js +105 -0
  39. package/lib/counter/task/systemperf.js +43 -0
  40. package/lib/data/datapack-sender.js +289 -0
  41. package/lib/data/dataprofile-agent.js +162 -0
  42. package/lib/data/datatext-agent.js +135 -0
  43. package/lib/data/event-level.js +15 -0
  44. package/lib/data/test.js +49 -0
  45. package/lib/data/zipprofile.js +197 -0
  46. package/lib/env/constants.js +21 -0
  47. package/lib/error/error-handler.js +437 -0
  48. package/lib/io/data-inputx.js +13 -3
  49. package/lib/io/data-outputx.js +268 -206
  50. package/lib/kube/kube-client.js +144 -0
  51. package/lib/lang/text-types.js +58 -0
  52. package/lib/logger.js +6 -6
  53. package/lib/logsink/line-log-util.js +87 -0
  54. package/lib/logsink/line-log.js +12 -0
  55. package/lib/logsink/log-sender.js +78 -0
  56. package/lib/logsink/log-tracer.js +40 -0
  57. package/lib/logsink/sender-util.js +56 -0
  58. package/lib/logsink/zip/zip-send.js +177 -0
  59. package/lib/net/netflag.js +55 -0
  60. package/lib/net/receiver.js +66 -0
  61. package/lib/net/security-master.js +139 -20
  62. package/lib/net/sender.js +141 -0
  63. package/lib/net/tcp-return.js +18 -0
  64. package/lib/net/tcp-session.js +286 -0
  65. package/lib/net/tcpreq-client-proxy.js +70 -0
  66. package/lib/net/tcprequest-mgr.js +58 -0
  67. package/lib/observers/apollo-server-observer.js +33 -27
  68. package/lib/observers/cluster-observer.js +22 -0
  69. package/lib/observers/express-observer.js +215 -0
  70. package/lib/observers/file-observer.js +184 -0
  71. package/lib/observers/global-observer.js +155 -80
  72. package/lib/observers/grpc-observer.js +336 -0
  73. package/lib/observers/http-observer.js +666 -236
  74. package/lib/observers/maria-observer.js +204 -362
  75. package/lib/observers/memcached-observer.js +56 -0
  76. package/lib/observers/mongo-observer.js +317 -0
  77. package/lib/observers/mongodb-observer.js +169 -226
  78. package/lib/observers/mongoose-observer.js +518 -323
  79. package/lib/observers/mssql-observer.js +177 -418
  80. package/lib/observers/mysql-observer.js +342 -449
  81. package/lib/observers/mysql2-observer.js +396 -358
  82. package/lib/observers/net-observer.js +77 -0
  83. package/lib/observers/oracle-observer.js +559 -384
  84. package/lib/observers/pgsql-observer.js +231 -489
  85. package/lib/observers/prisma-observer.js +303 -92
  86. package/lib/observers/process-observer.js +79 -35
  87. package/lib/observers/promise-observer.js +31 -0
  88. package/lib/observers/redis-observer.js +166 -331
  89. package/lib/observers/schedule-observer.js +67 -0
  90. package/lib/observers/socket.io-observer.js +226 -187
  91. package/lib/observers/stream-observer.js +19 -0
  92. package/lib/observers/thrift-observer.js +197 -0
  93. package/lib/observers/websocket-observer.js +175 -301
  94. package/lib/pack/activestack-pack.js +55 -0
  95. package/lib/pack/apenum.js +8 -0
  96. package/lib/pack/counter-pack.js +3 -0
  97. package/lib/pack/errorsnap-pack.js +69 -0
  98. package/lib/pack/event-pack.js +54 -0
  99. package/lib/pack/hitmap-pack.js +63 -0
  100. package/lib/pack/hitmap-pack1.js +152 -0
  101. package/lib/pack/log-sink-pack.js +14 -52
  102. package/lib/pack/netstat.js +15 -0
  103. package/lib/pack/otype.js +7 -0
  104. package/lib/pack/profile-pack.js +49 -0
  105. package/lib/pack/realtimeuser-pack.js +41 -0
  106. package/lib/pack/stat-general-pack.js +96 -0
  107. package/lib/pack/staterror-pack.js +120 -0
  108. package/lib/pack/stathttpc-pack.js +66 -0
  109. package/lib/pack/stathttpc-rec.js +78 -0
  110. package/lib/pack/statremote-pack.js +46 -0
  111. package/lib/pack/statservice-pack.js +63 -0
  112. package/lib/pack/statservice-pack1.js +88 -0
  113. package/lib/pack/statservice-rec.js +292 -0
  114. package/lib/pack/statservice-rec_dep.js +151 -0
  115. package/lib/pack/statsql-pack.js +69 -0
  116. package/lib/pack/statsql-rec.js +100 -0
  117. package/lib/pack/statuseragent-pack.js +44 -0
  118. package/lib/pack/tagcount-pack.js +4 -4
  119. package/lib/pack/tagctr.js +15 -0
  120. package/lib/pack/text-pack.js +50 -0
  121. package/lib/pack/time-count.js +25 -0
  122. package/lib/pack/websocket.js +15 -0
  123. package/lib/pack/zip-pack.js +70 -0
  124. package/lib/pii/pii-item.js +31 -0
  125. package/lib/pii/pii-mask.js +174 -0
  126. package/lib/plugin/plugin-loadermanager.js +57 -0
  127. package/lib/plugin/plugin.js +75 -0
  128. package/lib/service/tx-record.js +332 -0
  129. package/lib/stat/stat-error.js +116 -0
  130. package/lib/stat/stat-httpc.js +98 -0
  131. package/lib/stat/stat-remote-ip.js +46 -0
  132. package/lib/stat/stat-remote-ipurl.js +88 -0
  133. package/lib/stat/stat-sql.js +113 -0
  134. package/lib/stat/stat-tranx.js +58 -0
  135. package/lib/stat/stat-tx-caller.js +160 -0
  136. package/lib/stat/stat-tx-domain.js +111 -0
  137. package/lib/stat/stat-tx-referer.js +112 -0
  138. package/lib/stat/stat-useragent.js +48 -0
  139. package/lib/stat/timingsender.js +76 -0
  140. package/lib/step/activestack-step.js +38 -0
  141. package/lib/step/dbc-step.js +36 -0
  142. package/lib/step/http-stepx.js +67 -0
  143. package/lib/step/message-step.js +40 -0
  144. package/lib/step/method-stepx.js +45 -0
  145. package/lib/step/resultset-step.js +40 -0
  146. package/lib/step/securemsg-step.js +44 -0
  147. package/lib/step/socket-step.js +46 -0
  148. package/lib/step/sql-stepx.js +68 -0
  149. package/lib/step/sqlxtype.js +16 -0
  150. package/lib/step/step.js +66 -0
  151. package/lib/step/stepenum.js +54 -0
  152. package/lib/topology/link.js +63 -0
  153. package/lib/topology/nodeinfo.js +123 -0
  154. package/lib/topology/status-detector.js +111 -0
  155. package/lib/trace/trace-context-manager.js +113 -25
  156. package/lib/trace/trace-context.js +21 -7
  157. package/lib/trace/trace-httpc.js +17 -11
  158. package/lib/trace/trace-sql.js +29 -21
  159. package/lib/util/anylist.js +103 -0
  160. package/lib/util/cardinality/hyperloglog.js +106 -0
  161. package/lib/util/cardinality/murmurhash.js +31 -0
  162. package/lib/util/cardinality/registerset.js +75 -0
  163. package/lib/util/errordata.js +21 -0
  164. package/lib/util/escape-literal-sql.js +5 -5
  165. package/lib/util/hashutil.js +18 -18
  166. package/lib/util/iputil_x.js +527 -0
  167. package/lib/util/keygen.js +0 -3
  168. package/lib/util/kube-util.js +73 -0
  169. package/lib/util/linkedset.js +1 -2
  170. package/lib/util/nodeutil.js +2 -1
  171. package/lib/util/paramsecurity.js +80 -0
  172. package/lib/util/pre-process.js +13 -0
  173. package/lib/util/process-seq.js +166 -0
  174. package/lib/util/property-util.js +36 -0
  175. package/lib/util/request-queue.js +70 -0
  176. package/lib/util/requestdouble-queue.js +72 -0
  177. package/lib/util/resourceprofile.js +157 -0
  178. package/lib/util/stop-watch.js +30 -0
  179. package/lib/util/system-util.js +10 -0
  180. package/lib/util/userid-util.js +57 -0
  181. package/lib/value/map-value.js +3 -2
  182. package/package.json +9 -4
  183. package/whatap.conf +1 -4
  184. package/agent/darwin/arm64/whatap_nodejs +0 -0
  185. package/agent/linux/amd64/whatap_nodejs +0 -0
  186. package/agent/linux/arm64/whatap_nodejs +0 -0
  187. package/build.txt +0 -4
  188. package/lib/observers/ioredis-observer.js +0 -294
  189. package/lib/udp/async_sender.js +0 -119
  190. package/lib/udp/index.js +0 -17
  191. package/lib/udp/packet_enum.js +0 -52
  192. package/lib/udp/packet_queue.js +0 -69
  193. package/lib/udp/packet_type_enum.js +0 -33
  194. package/lib/udp/param_def.js +0 -72
  195. package/lib/udp/udp_session.js +0 -336
  196. package/lib/util/sql-util.js +0 -178
  197. package/lib/util/trace-helper.js +0 -91
  198. package/lib/util/transfer.js +0 -58
package/lib/core/agent.js CHANGED
@@ -6,60 +6,63 @@
6
6
 
7
7
  var os = require('os'),
8
8
  fs = require('fs'),
9
- path = require('path'),
10
- child_process = require('child_process'),
11
- properLock = require('proper-lockfile'),
12
- crypto = require('crypto');
9
+ path = require('path');
13
10
 
14
11
  const RequestLog = require('../requestlog');
15
12
 
16
13
  var Interceptor = require('./interceptor').Interceptor,
17
14
  HttpObserver = require('../observers/http-observer').HttpObserver,
15
+ NetObserver = require('../observers/net-observer').NetObserver,
16
+ ClusterObserver = require('../observers/cluster-observer').ClusterObserver,
17
+ ExpressObserver = require('../observers/express-observer').ExpressObserver,
18
18
  GlobalObserver = require('../observers/global-observer').GlobalObserver,
19
19
  MysqlObserver = require('../observers/mysql-observer').MysqlObserver,
20
20
  Mysql2Observer = require('../observers/mysql2-observer').Mysql2Observer,
21
21
  MariaObserver = require('../observers/maria-observer').MariaObserver,
22
22
  SocketioObserver = require('../observers/socket.io-observer').SocketIOObserver,
23
23
  WebsocketObserver = require('../observers/websocket-observer').WebsocketObserver,
24
- // WsObserver = require('../observers/websocket-observer').WsObserver,
25
24
  ProcessObserver = require('../observers/process-observer').ProcessObserver,
26
- MongoObserver = require('../observers/mongodb-observer').MongoObserver,
27
- // MongooseObserver = require('../observers/mongoose-observer').MongooseObserver,
25
+ FileObserver = require('../observers/file-observer').FileObserver,
26
+ MongoObserver = require('../observers/mongo-observer').MongoObserver,
27
+ MongooseObserver = require('../observers/mongoose-observer').MongooseObserver,
28
28
  RedisObserver = require('../observers/redis-observer').RedisObserver,
29
- IORedisObserver = require('../observers/ioredis-observer').IORedisObserver,
30
29
  MssqlObserver = require('../observers/mssql-observer').MssqlObserver,
30
+ ThriftObserver = require('../observers/thrift-observer').ThriftObserver,
31
+ PromiseObserver = require('../observers/promise-observer').PromiseObserver,
31
32
  PgSqlObserver = require('../observers/pgsql-observer').PgSqlObserver,
33
+ ScheduleObserver = require('../observers/schedule-observer').ScheduleObserver,
32
34
  // GRpcObserver = require('../observers/grpc-observer').GRpcObserver,
33
35
  ApolloObserver = require('../observers/apollo-server-observer').ApolloServerObserver,
34
36
  PrismaObserver = require('../observers/prisma-observer').PrismaObserver,
35
37
  OracleObserver = require('../observers/oracle-observer').OracleObserver;
36
38
 
37
39
 
40
+
38
41
  var Configuration = require('./../conf/configure'),
39
42
  SecurityMaster = require('./../net/security-master'),
43
+ TcpSession = require('./../net/tcp-session'),
44
+ PackageCtrHelper = require('./../control/packagectr-helper'),
45
+ DataPackSender = require('../data/datapack-sender'),
40
46
  CounterManager = require('./../counter/counter-manager'),
41
47
  NodeUtil = require('./../util/nodeutil'),
42
48
  DateUtil = require('./../util/dateutil'),
43
49
  WhatapUtil = require('./../util'),
50
+ ParamPack = require('../pack/param-pack').ParamPack,
51
+ PluginLoaderManager = require('../plugin/plugin-loadermanager'),
44
52
  TraceContextManager = require('../trace/trace-context-manager'),
53
+ DataTextAgent = require('../data/datatext-agent').agent,
54
+ TextTypes = require('../lang/text-types'),
45
55
  HashUtil = require('../util/hashutil'),
56
+ MessageStep = require('../step/message-step'),
46
57
  Logger = require('../logger');
47
58
 
48
- // Import UDP module
49
- const UdpModule = require('../udp');
50
- const UdpSession = UdpModule.UdpSession;
51
- const AsyncSender = UdpModule.AsyncSender;
52
- const PacketTypeEnum = UdpModule.PacketTypeEnum;
53
-
54
- const ARCH = {
55
- 'x64': 'amd64',
56
- 'ia32': '386',
57
- 'arm': 'arm',
58
- 'arm64': 'arm64'
59
- };
60
-
61
- // Agent binary name
62
- const AGENT_NAME = 'whatap_nodejs';
59
+ require('../stat/stat-tranx');
60
+ require('../stat/stat-sql');
61
+ require('../stat/stat-httpc');
62
+ require('../stat/stat-remote-ip');
63
+ require('../stat/stat-remote-ipurl');
64
+ require('../stat/stat-useragent');
65
+ require('../stat/timingsender');
63
66
 
64
67
  var NodeAgent = function(opt) {
65
68
  this._userOpt = opt;
@@ -67,6 +70,7 @@ var NodeAgent = function(opt) {
67
70
  this.aop = new Interceptor(this);
68
71
  this._conf = Configuration;
69
72
  this._securityMaster = SecurityMaster;
73
+ this._tcpsession = null;
70
74
  this._counterManager = null;
71
75
  this.setLoopTime = 5000;
72
76
  this.connectCount = 0;
@@ -103,837 +107,179 @@ NodeAgent.prototype.findRoot = function () {
103
107
  root = path.join(root, '..');
104
108
  }
105
109
  };
106
-
107
- // Cross-platform function to check if a process is running and is whatap_nodejs
108
- NodeAgent.prototype.isNodejsAgentProcess = function(pid) {
109
- try {
110
- pid = parseInt(pid);
111
- const platform = process.platform;
112
- let processCommand = '';
113
-
114
- if (platform === 'linux') {
115
- // On Linux, use /proc filesystem - same approach as Python
116
- try {
117
- const cmdlineFile = path.join('/proc', pid.toString(), 'cmdline');
118
- if (fs.existsSync(cmdlineFile)) {
119
- processCommand = fs.readFileSync(cmdlineFile, 'utf8');
120
- // Log for debugging
121
- Logger.print("WHATAP-PROCESS", `Process ${pid} command line: ${processCommand}`, false);
122
- }
123
- } catch (e) {
124
- Logger.printError("WHATAP-101", "Error reading Linux process info", e, false);
125
- return false;
126
- }
127
- } else if (platform === 'darwin') {
128
- // On macOS, use ps command
129
- try {
130
- processCommand = child_process.execSync(`ps -p ${pid} -o command=`, { encoding: 'utf8' }).trim();
131
- Logger.print("WHATAP-PROCESS", `Process ${pid} command line: ${processCommand}`, false);
132
- } catch (e) {
133
- Logger.printError("WHATAP-102", "Error reading MacOS process info", e, false);
134
- return false;
135
- }
136
- } else if (platform === 'win32') {
137
- // On Windows, use tasklist command
138
- try {
139
- const output = child_process.execSync(`tasklist /FI "PID eq ${pid}" /FO CSV /NH`, { encoding: 'utf8' });
140
- // Windows output has quotes, e.g.: "whatap_nodejs.exe","1234","Console","1","12,345 K"
141
- const match = output.match(/"([^"]+)"/);
142
- if (match && match[1]) {
143
- processCommand = match[1];
144
- Logger.print("WHATAP-PROCESS", `Process ${pid} command line: ${processCommand}`, false);
145
- }
146
- } catch (e) {
147
- Logger.printError("WHATAP-103", "Error reading Windows process info", e, false);
148
- return false;
149
- }
150
- } else {
151
- // On other platforms, try generic ps command
152
- try {
153
- processCommand = child_process.execSync(`ps -p ${pid} -o command=`, { encoding: 'utf8' }).trim();
154
- Logger.print("WHATAP-PROCESS", `Process ${pid} command line: ${processCommand}`, false);
155
- } catch (e) {
156
- Logger.printError("WHATAP-104", "Error reading other os process info", e, false);
157
- return false;
158
- }
159
- }
160
-
161
- // Check if the command contains the agent name (equivalent to Python's find('whatap_python') >= 0)
162
- const isAgentProcess = processCommand.indexOf(AGENT_NAME) >= 0;
163
- Logger.print("WHATAP-PROCESS", `Process ${pid} is ${isAgentProcess ? '' : 'not '}a WhaTap agent`, false);
164
- return isAgentProcess;
165
- } catch (e) {
166
- Logger.printError("WHATAP-AGENT", "Error in isNodejsAgentProcess", e, false);
167
- return false;
168
- }
169
- };
170
-
171
- // Function to read PID from file
172
- NodeAgent.prototype.readPidFile = function(home, fileName) {
173
- try {
174
- const filePath = path.join(process.env[home], fileName);
175
- if (fs.existsSync(filePath)) {
176
- return fs.readFileSync(filePath, 'utf8').trim();
177
- }
178
- } catch (e) {
179
- Logger.printError("WHATAP-PID", "Error reading PID file", e, false);
180
- }
181
- return '';
182
- };
183
-
184
- // Function to write to file
185
- NodeAgent.prototype.writeToFile = function(home, fileName, value) {
186
- try {
187
- const filePath = path.join(process.env[home], fileName);
188
- fs.writeFileSync(filePath, value);
189
- return true;
190
- } catch (e) {
191
- Logger.printError("WHATAP-FILE", `Error writing to file ${fileName}`, e, false);
192
- Logger.print("WHATAP-FILE", `Try to execute command: \`sudo chmod -R 777 $WHATAP_HOME\``, false);
193
- return false;
194
- }
195
- };
196
-
197
- // Modified isGoAgentRunning to check PID +-1 range
198
- NodeAgent.prototype.isGoAgentRunning = function(pid) {
199
- try {
200
- if (!pid) return false;
201
-
202
- // 원래 PID와 +1, -1된 PID 모두 확인
203
- const pidsToCheck = [
204
- parseInt(pid),
205
- parseInt(pid) + 1,
206
- parseInt(pid) - 1
207
- ];
208
-
209
- Logger.print("WHATAP-AGENT", `Checking PIDs: ${pidsToCheck.join(', ')} (original: ${pid})`, false);
210
-
211
- for (const pidToCheck of pidsToCheck) {
212
- try {
213
- // 프로세스 존재 여부 확인
214
- process.kill(pidToCheck, 0);
215
-
216
- // whatap_nodejs 프로세스인지 확인
217
- if (this.isNodejsAgentProcess(pidToCheck)) {
218
- Logger.print("WHATAP-AGENT",
219
- `Found agent process at PID ${pidToCheck} (original PID in file: ${pid})`,
220
- false);
221
- return true;
222
- }
223
- } catch (e) {
224
- // ESRCH error means process doesn't exist
225
- if (e.code !== 'ESRCH') {
226
- throw e;
227
- }
228
- }
229
- }
230
-
231
- Logger.print("WHATAP-AGENT", `No agent process found for PID ${pid} or adjacent PIDs`, false);
232
- return false;
233
- } catch (e) {
234
- Logger.printError("WHATAP-AGENT", "Error checking if agent is running", e, false);
235
- return false;
110
+ NodeAgent.prototype.init = function(cb) {
111
+ var self = this;
112
+ if(self._initialized) {
113
+ return;
236
114
  }
237
- };
115
+ self._initialized = true;
116
+ self.starttime = Date.now();
238
117
 
239
- /**
240
- * Read content from a file - similar to Python's read_file
241
- * @param {string} home - Environment variable name for home directory
242
- * @param {string} fileName - Name of the file to read
243
- * @returns {string} - Content of the file, or empty string on error
244
- */
245
- NodeAgent.prototype.readFile = function(home, fileName) {
246
- try {
247
- const filePath = path.join(process.env[home], fileName);
248
- if (fs.existsSync(filePath)) {
249
- return fs.readFileSync(filePath, 'utf8').toString().trim();
250
- }
251
- } catch (e) {
252
- Logger.printError("WHATAP-FILE", `Error reading file ${fileName}`, e, false);
253
- }
254
- return '';
255
- };
118
+ self.findRoot();
256
119
 
257
- /**
258
- * Write content to a file - similar to Python's write_file
259
- * @param {string} home - Environment variable name for home directory
260
- * @param {string} fileName - Name of the file to write
261
- * @param {string} value - Content to write to the file
262
- * @returns {boolean} - True if successful, false otherwise
263
- */
264
- NodeAgent.prototype.writeFile = function(home, fileName, value) {
265
- try {
266
- const filePath = path.join(process.env[home], fileName);
267
- fs.writeFileSync(filePath, value);
268
- return true;
269
- } catch (e) {
270
- Logger.printError("WHATAP-FILE", `Error writing to file ${fileName}`, e, false);
271
- Logger.print("WHATAP-FILE", `Try to execute command: \`sudo chmod -R 777 $WHATAP_HOME\``, false);
272
- return false;
273
- }
274
- };
120
+ Logger.initializer.process();
275
121
 
276
- /**
277
- * Find whatap.conf file by searching directories - similar to Python's find_whatap_conf
278
- * @returns {string|null} - Path to whatap.conf or null if not found
279
- */
280
- NodeAgent.prototype.findWhatapConf = function() {
281
- // 1. Check current directory
282
- const scriptDir = path.dirname(__filename);
283
- const parentDir = path.dirname(scriptDir);
284
- let confPath = path.join(parentDir, 'whatap.conf');
122
+ // 최초 1회 실행 후 1시간마다 실행
123
+ const ONE_HOUR = 60 * 60 * 1000;
124
+ Logger.clearOldLog();
125
+ setInterval(Logger.clearOldLog, ONE_HOUR);
285
126
 
286
- if (fs.existsSync(confPath)) {
287
- process.env.WHATAP_HOME = parentDir;
288
- return confPath;
289
- }
127
+ Logger.print('WHATAP-001', 'Start initialize WhaTap Agent... Root[' + self._conf['app.root'] + ']', true);
290
128
 
291
- // 2. Check parent directories
292
- let current = parentDir;
293
- while (current !== '/' && current !== path.parse(current).root) {
294
- confPath = path.join(current, 'whatap.conf');
295
- if (fs.existsSync(confPath)) {
296
- process.env.WHATAP_HOME = current;
297
- return confPath;
298
- }
299
- current = path.dirname(current);
129
+ if(self._conf['app.root'] == null || self._conf['app.root'].length == 0) {
130
+ return Logger.print("WHATAP-001", "Can not find application root directory", true);
300
131
  }
301
132
 
302
- return null;
303
- };
304
-
305
- /**
306
- * Open and lock the port file - similar to Python's openPortFile
307
- * @param {string} filepath - Path to the lock file
308
- * @returns {object|null} - File descriptor or null if failed
309
- */
310
- NodeAgent.prototype.openPortFile = function(filepath) {
311
- filepath = filepath || process.env.WHATAP_LOCK_FILE || '/tmp/whatap-nodejs.lock';
312
-
313
- let fileHandle = null;
314
- let attempts = 0;
315
-
316
- // Try to open the file, similar to Python's while loop
317
- while (!fileHandle && attempts < 100) {
318
- try {
319
- // Try to open file for reading and writing
320
- if (fs.existsSync(filepath)) {
321
- fileHandle = fs.openSync(filepath, 'r+');
322
- } else {
323
- // If file doesn't exist, create the directory if needed
324
- const dirPath = path.dirname(filepath);
325
- if (!fs.existsSync(dirPath)) {
326
- fs.mkdirSync(dirPath, { recursive: true });
327
- }
328
- // Create the file
329
- fileHandle = fs.openSync(filepath, 'w+');
330
- }
331
- } catch (e) {
332
- Logger.printError("WHATAP-PORT", `Error opening port file (attempt ${attempts})`, e, false);
333
- }
334
-
335
- // Similar to Python, add a delay after 50 attempts
336
- if (attempts > 50) {
337
- setTimeout(() => {}, 100); // 0.1 second delay
338
- }
339
-
340
- attempts++;
341
- }
133
+ NodeUtil.getPackageJson();
134
+ PackageCtrHelper.dynamicHook();
342
135
 
343
- if (fileHandle) {
344
- try {
345
- // Use proper-lock with the filepath instead of file descriptor
346
- properLock.lockSync(filepath);
347
- return { fileHandle, filepath };
348
- } catch (e) {
349
- Logger.printError("WHATAP-PORT", "Failed to lock port file", e, false);
350
- try {
351
- fs.closeSync(fileHandle);
352
- } catch (closeErr) {}
353
- return null;
136
+ self._conf.init(this._userOpt , function(e) {
137
+ if(e) {
138
+ Logger.printError("WHATAP-002", "Configuataion initialize error. " + e.message,
139
+ e, true);
140
+ return;
354
141
  }
355
- }
356
- return null;
357
- };
358
-
359
- /**
360
- * Get available port number for the agent - similar to Python's get_port_number
361
- * @param {number} defaultPort - Default port to start with
362
- * @param {string} home - WHATAP_HOME directory
363
- * @returns {number|null} - Allocated port number or null if failed
364
- */
365
- NodeAgent.prototype.getPortNumber = function(port, home) {
366
- port = port || 6600;
367
- home = home || process.env.WHATAP_HOME;
368
-
369
- // Return null if home is not defined
370
- if (!home) {
371
- return null;
372
- }
373
-
374
- // Open the port file
375
- const fileInfo = this.openPortFile();
376
- if (!fileInfo) {
377
- return port; // Return default port if we couldn't open the file
378
- }
379
-
380
- const { fileHandle, filepath } = fileInfo;
381
-
382
- try {
383
- // Get file size
384
- const stats = fs.fstatSync(fileHandle);
385
- let content = '';
386
-
387
- // Only read if file is not empty
388
- if (stats.size > 0) {
389
- const buffer = Buffer.alloc(stats.size);
390
- fs.readSync(fileHandle, buffer, 0, buffer.length, 0);
391
- content = buffer.toString().trim();
142
+ Logger.print('WHATAP-101', 'Finish initialize configuration... ' + Boolean(self._conf['reqlog_enabled']) , false);
143
+ if(Boolean(self._conf['reqlog_enabled']) == true ) {
144
+ Logger.print("WHATAP-REQLOG" , "ReqLog Init Start !!!! " , false);
145
+ RequestLog.initializer.process();
392
146
  }
393
147
 
394
- let lastPortFound = null;
395
-
396
- // Process each line
397
- if (content && content.length > 0) {
398
- const lines = content.split('\n');
399
- for (const line of lines) {
400
- const trimmedLine = line.trim();
401
- if (!trimmedLine) continue;
402
-
403
- try {
404
- // Parse the line "port home"
405
- const parts = trimmedLine.split(/\s+/, 2);
406
- if (parts.length < 2) continue;
407
-
408
- const portStr = parts[0];
409
- const portHome = parts[1];
410
- const currentPort = parseInt(portStr, 10);
411
-
412
- if (isNaN(currentPort)) continue;
413
-
414
- // If home matches, return the port
415
- if (home === portHome) {
416
- // Clean up before returning
417
- properLock.unlockSync(filepath);
418
- fs.closeSync(fileHandle);
419
- return currentPort;
420
- }
421
-
422
- // Track the highest port number
423
- if (!lastPortFound || lastPortFound < currentPort) {
424
- lastPortFound = currentPort;
425
- }
426
- } catch (e) {
427
- continue; // Skip lines that can't be parsed
428
- }
148
+ self._securityMaster.run( function (err) {
149
+ if(err) {
150
+ Logger.printError('WHATAP-104', 'Failed to connect to whatap server', err, false);
151
+ if(self._counterManager) self._counterManager.stop();
152
+ return;
429
153
  }
430
- }
431
-
432
- // Determine the new port number
433
- const newPort = lastPortFound ? lastPortFound + 1 : port;
434
-
435
- // Clear the file completely
436
- fs.ftruncateSync(fileHandle, 0);
437
154
 
438
- // Write the new entry directly
439
- fs.writeSync(fileHandle, `${newPort}\t${home}\n`);
440
-
441
- // Unlock and close the file
442
- properLock.unlockSync(filepath);
443
- fs.closeSync(fileHandle);
444
-
445
- return newPort;
446
- } catch (e) {
447
- Logger.printError("WHATAP-PORT", "Error processing port file", e, false);
448
-
449
- try {
450
- properLock.unlockSync(filepath);
451
- fs.closeSync(fileHandle);
452
- } catch (closeErr) {
453
- }
454
-
455
- return port;
456
- }
457
- };
458
-
459
- /**
460
- * Configure the port for the agent and update the configuration
461
- * @returns {number|null} - The configured port or null if failed
462
- */
463
- NodeAgent.prototype.configurePort = function() {
464
- const port = this.getPortNumber();
465
- if (port) {
466
- this.updateConfig('WHATAP_HOME', 'net_udp_port', port.toString());
467
- return port;
468
- }
469
- return null;
470
- };
471
-
472
- /**
473
- * Update configuration file with new option value - similar to Python's update_config
474
- * @param {string} home - Environment variable name for WhaTap home
475
- * @param {string} optKey - Option key to update
476
- * @param {string} optValue - Option value to set
477
- */
478
- NodeAgent.prototype.updateConfig = function(home, optKey, optValue) {
479
- const homePath = process.env[home];
480
- if (!homePath) {
481
- Logger.print("WHATAP-CONFIG", `${home} environment variable not set`, true);
482
- return;
483
- }
484
-
485
- const configFile = path.join(homePath, 'whatap.conf');
486
-
487
- try {
488
- let content = '';
489
- let isUpdated = false;
490
-
491
- if (fs.existsSync(configFile)) {
492
- const lines = fs.readFileSync(configFile, 'utf8').split('\n');
493
-
494
- // Look for the option key and update if found
495
- for (let line of lines) {
496
- if (line.trim()) {
497
- const parts = line.split('=');
498
- const key = parts[0].trim();
499
-
500
- if (key === optKey) {
501
- line = `${key}=${optValue}`;
502
- isUpdated = true;
503
- }
155
+ self.connect(function (err) {
156
+ if(!err) {
157
+ self.initOK(cb);
504
158
  }
505
- content += line + '\n';
506
- }
507
-
508
- // If the option wasn't found, add it
509
- if (!isUpdated) {
510
- content += `\n${optKey}=${optValue}\n`;
511
- }
512
- } else {
513
- // If config file doesn't exist, create with just this option
514
- content = `${optKey}=${optValue}\n`;
515
- }
516
-
517
- // Write updated content back to file
518
- fs.writeFileSync(configFile, content);
519
- Logger.print("WHATAP-CONFIG", `Updated configuration: ${optKey}=${optValue}`, false);
520
- } catch (e) {
521
- Logger.printError("WHATAP-CONFIG", `Error updating configuration: ${optKey}=${optValue}`, e, false);
522
- }
523
- };
524
-
525
- NodeAgent.prototype.getApplicationIdentifier = function() {
526
- // 1. 명시적 그룹 지정 (환경 변수)
527
- if (process.env.WHATAP_APP_GROUP) {
528
- return process.env.WHATAP_APP_GROUP;
529
- }
530
-
531
- // 2. 설정 파일에서 그룹 지정
532
- if (this._conf['app_group']) {
533
- return this._conf['app_group'];
534
- }
535
-
536
- // 3. 자동 생성
537
- const appRoot = this._conf['app.root'] || process.cwd();
538
- const appName = this.getApplicationName();
539
-
540
- const identifier = crypto
541
- .createHash('md5')
542
- .update(`${appRoot}:${appName}`)
543
- .digest('hex')
544
- .substr(0, 8);
545
-
546
- Logger.print("WHATAP-AGENT",
547
- `Application identifier: ${appName} at ${appRoot} => ${identifier}`,
548
- false);
549
-
550
- return identifier;
551
- };
552
-
553
- NodeAgent.prototype.getApplicationName = function() {
554
- // 1. PM2 실행 시
555
- if (process.env.PM2_APP_NAME || process.env.name) {
556
- return process.env.PM2_APP_NAME || process.env.name;
557
- }
558
-
559
- // 2. 설정 파일에서
560
- if (this._conf['app_name']) {
561
- return this._conf['app_name'];
562
- }
563
-
564
- // 3. 명령행 인수에서 --name 옵션 찾기
565
- const nameArgIndex = process.argv.indexOf('--name');
566
- if (nameArgIndex !== -1 && nameArgIndex < process.argv.length - 1) {
567
- return process.argv[nameArgIndex + 1];
568
- }
569
-
570
- // 4. 환경 변수로 직접 설정
571
- if (process.env.APP_NAME) {
572
- return process.env.APP_NAME;
573
- }
574
-
575
- // 5. 기본값: 실행 파일명
576
- return path.basename(process.argv[1], '.js');
159
+ });
160
+ });
161
+ });
162
+ self.loadObserves();
163
+ return this;
577
164
  };
578
165
 
579
- // startGoAgent with improved PID handling
580
- NodeAgent.prototype.startGoAgent = function(opts = {}) {
581
- const self = this;
582
- const home = 'WHATAP_HOME';
583
- const pidFileName = `${AGENT_NAME}.pid`;
584
- const whatapHome = process.env[home];
585
-
586
- if (!whatapHome) {
587
- Logger.printError("WHATAP-105", "WHATAP_HOME environment variable is not set", true);
588
- return;
589
- }
590
-
591
- // 1. 애플리케이션 식별자 생성 (포트 제외)
592
- const appIdentifier = this.getApplicationIdentifier();
593
- const sharedLockFile = path.join(whatapHome, `agent-${appIdentifier}.lock`);
594
- const sharedPidFile = path.join(whatapHome, `agent-${appIdentifier}.pid`);
166
+ NodeAgent.prototype.initOK = function(cb) {
167
+ var self = this;
595
168
 
596
- // 2. 공유 잠금 파일을 사용하여 중복 실행 방지
597
- try {
598
- if (fs.existsSync(sharedPidFile)) {
599
- // PID 파일에서 기존 PID 읽기
600
- const existingPid = fs.readFileSync(sharedPidFile, 'utf8').trim();
601
- if (existingPid && this.isGoAgentRunning(existingPid)) {
602
- Logger.print("WHATAP-AGENT", `Go agent already running for application ${appIdentifier} (PID: ${existingPid})`, false);
603
- return;
604
- } else {
605
- // 프로세스가 죽었다면 파일 제거
606
- Logger.print("WHATAP-AGENT", `Previous agent process ${existingPid} not found, cleaning up`, false);
607
- try { fs.unlinkSync(sharedLockFile); } catch (e) {}
608
- try { fs.unlinkSync(sharedPidFile); } catch (e) {}
609
- }
610
- }
611
- } catch (e) {
612
- Logger.printError("WHATAP-AGENT", "Error checking shared lock file", e, false);
613
- }
169
+ Logger.ONAME = self._securityMaster.ONAME;
170
+ Logger.initializer.reset();
171
+
172
+ TraceContextManager.initialized = true;
173
+ DataTextAgent.reset();
174
+
175
+ var param = new ParamPack();
176
+ param.putString("whatap.version", NodeUtil.getVersion()+' '+ NodeUtil.getReleaseDate());
177
+ param.putString("os.name", os.platform());
178
+ param.putString("os.arch", os.arch());
179
+ param.putString('os.release', os.release());
180
+ param.putString('node.version', process.version);
181
+ param.putString('node.uptime', (new Date()).toString());
182
+ param.putString('node.name', NodeUtil.getName());
183
+ param.putString('user.timezone', NodeUtil.getTimeZone());
184
+ param.putString('user.home', os.homedir());
185
+ param.putString('user.hostname', os.hostname());
186
+ // CLOUD PLATFORM INFO
187
+ param.putString('CLOUD_PLATFORM', WhatapUtil.cloudPlatformCheck());
188
+ DataPackSender.sendBoot(param);
189
+
190
+ if(self._counterManager === null) {
191
+ self._counterManager = new CounterManager(self);
192
+ self._counterManager.run();
193
+ PluginLoaderManager.start();
194
+ }
195
+
196
+ WhatapUtil.printWhatap();
197
+ self.connectCount = 0;
198
+ self.setLoopTime = 5000;
199
+ if(cb) cb();
200
+ }
614
201
 
615
- // 잠금 획득 시도
616
- let lockAcquired = false;
617
- try {
618
- if (!fs.existsSync(sharedLockFile)) {
619
- fs.writeFileSync(sharedLockFile, process.pid.toString());
620
- lockAcquired = true;
621
- }
622
- } catch (e) {
623
- Logger.printError("WHATAP-AGENT", "Error acquiring lock", e, false);
624
- }
625
202
 
626
- if (!lockAcquired) {
627
- Logger.print("WHATAP-AGENT", "Another process is starting the agent, waiting...", false);
628
- return;
629
- }
203
+ NodeAgent.prototype.context = function(cb) {
204
+ return TraceContextManager.getCurrentContext();
205
+ }
630
206
 
631
- // 기존 whatap_nodejs.pid 파일 처리 (호환성 유지)
632
- const pid = this.readPidFile(home, pidFileName);
633
- if (pid) {
634
- try {
635
- if (this.isGoAgentRunning(pid)) {
636
- Logger.print("WHATAP-106", `Found existing agent with PID ${pid}, terminating...`, false);
637
- try {
638
- process.kill(parseInt(pid), 'SIGKILL');
639
- Logger.print("WHATAP-107", `Successfully terminated existing agent with PID ${pid}`, false);
640
- } catch (killError) {
641
- Logger.printError("WHATAP-108", `Error terminating process with PID ${pid}`, killError, false);
642
- }
643
- }
644
- } catch (e) {
645
- Logger.printError("WHATAP-109", `Error checking process with PID ${pid}`, e, false);
207
+ NodeAgent.prototype.connect = function (cb) {
208
+ var self = this;
209
+ if(self.connectCount >0 && self.connectCount % 10 == 0 ) {
210
+ Logger.print("WHATAP-171",
211
+ "[WhaTap Agent] Can not find server port.\n" +
212
+ "Did you add requre('whatap') as the first line of the app's main module?\n" +
213
+ "https://service.whatap.io/project/" + self._securityMaster.PCODE + "/install",
214
+ true);
215
+ if(self.setLoopTime == 5000) {
216
+ self.setLoopTime += 25000;
217
+ Logger.print("WHATAP-150", "[WhaTap Agent] setLoopTime Up -> " + self.setLoopTime , false)
218
+ }else if(self.setLoopTime == 30000) {
219
+ self.setLoopTime += 30000;
220
+ Logger.print("WHATAP-150", "[WhaTap Agent] setLoopTime Up -> " + self.setLoopTime , false)
221
+ } else if(self.setLoopTime == 60000) {
222
+ self.setLoopTime += 300000;
223
+ Logger.print("WHATAP-150", "[WhaTap Agent] setLoopTime Up -> " + self.setLoopTime , false)
646
224
  }
647
225
  }
648
-
649
- // 포트 설정 및 에이전트 시작
650
- const port = this.configurePort();
651
- if (!port) {
652
- Logger.printError("WHATAP-AGENT", "Failed to configure UDP port for agent", null, true);
653
- try { fs.unlinkSync(sharedLockFile); } catch (e) {}
654
- return;
655
- }
656
- Logger.print("WHATAP-AGENT", `Configured agent to use UDP port: ${port}`, false);
657
-
658
- try {
659
- // 바이너리 경로 설정
660
- const agentPath = path.join(whatapHome, AGENT_NAME);
661
- const platform = process.platform;
662
- const architecture = ARCH[process.arch] || process.arch;
663
- const sourcePath = path.join(__dirname, '..', '..', 'agent', platform, architecture, AGENT_NAME);
664
-
665
- // 심볼릭 링크 생성
666
- if (!fs.existsSync(agentPath)) {
667
- try {
668
- fs.symlinkSync(sourcePath, agentPath);
669
- Logger.print("WHATAP-AGENT", `Created symbolic link for ${AGENT_NAME}`, false);
670
- } catch (e) {
671
- if (e.code !== 'EEXIST') {
672
- if (platform === 'win32') {
673
- Logger.print("WHATAP-AGENT", "Symlink failed, copying binary instead", false);
674
- fs.copyFileSync(sourcePath, agentPath);
675
- } else {
676
- throw e;
677
- }
678
- }
679
- }
680
- }
681
-
682
- // run 디렉토리 생성
683
- const sockfilePath = path.join(whatapHome, 'run');
684
- if (!fs.existsSync(sockfilePath)) {
685
- fs.mkdirSync(sockfilePath, { recursive: true });
686
- }
687
-
688
- // 환경 변수 설정
689
- const newEnv = Object.assign({}, process.env);
690
- newEnv['whatap.start'] = Date.now().toString();
691
- newEnv['node.uptime'] = new Date().toString();
692
- newEnv['node.version'] = process.version;
693
- newEnv['node.tzname'] = new Date().toLocaleString('en', {timeZoneName: 'short'}).split(' ').pop();
694
- newEnv['os.release'] = os.release();
695
- newEnv['whatap.enabled'] = 'True';
696
- newEnv['WHATAP_PID_FILE'] = sharedPidFile; // 공유 PID 파일 사용
697
- newEnv['NODEJS_PARENT_APP_PID'] = process.pid.toString();
698
- newEnv['net_udp_port'] = port.toString();
699
- newEnv['APP_IDENTIFIER'] = appIdentifier;
700
- newEnv['APP_NAME'] = this.getApplicationName();
701
-
702
- // PM2 정보 추가
703
- const isPM2 = typeof process.env.PM2_HOME !== 'undefined' ||
704
- typeof process.env.pm_id !== 'undefined' ||
705
- typeof process.env.PM2_JSON_PROCESSING !== 'undefined';
706
-
707
- if (isPM2) {
708
- newEnv['PM2_APP_NAME'] = process.env.name || '';
709
- newEnv['PM2_ID'] = process.env.pm_id || '';
710
- }
711
-
712
- Object.assign(newEnv, opts);
713
-
714
- // 에이전트 프로세스 시작
715
- const agentProcess = child_process.spawn(
716
- agentPath,
717
- ['-t', '2', '-d', '1'],
718
- {
719
- cwd: whatapHome,
720
- env: newEnv,
721
- stdio: ['pipe', 'pipe', 'pipe'],
722
- detached: true
723
- }
724
- );
725
-
726
- let stdout = '';
727
- let stderr = '';
728
-
729
- agentProcess.stdout.on('data', (data) => {
730
- stdout += data.toString();
731
- });
732
-
733
- agentProcess.stderr.on('data', (data) => {
734
- stderr += data.toString();
226
+ Logger.print("WHATAP-170", "[WhaTap Agent] now waiting for starting......", false)
227
+ self._tcpsession = TcpSession;
228
+ setTimeout(function () {
229
+ Logger.print("WHATAP-011" , "Connecton Retry....")
230
+ self.connectCount++;
231
+ self._tcpsession.open(function(err) {
232
+ if(err) {
233
+ Logger.printError("WHTAP-11", "TCP SESSION OPEN ERROR", err ,false);
234
+ return self.connect(cb);
235
+ };
236
+ if(cb) cb();
735
237
  });
736
-
737
- // PID 추적을 위한 추가 로직
738
- agentProcess.on('spawn', () => {
739
- Logger.print("WHATAP-AGENT", `Agent process spawned with PID: ${agentProcess.pid}`, false);
740
-
741
- // detached 프로세스에서 실제 PID가 다를 수 있으므로 잠시 대기 후 확인
742
- setTimeout(() => {
743
- try {
744
- // ps 명령으로 실제 PID 찾기
745
- const psCommand = process.platform === 'win32'
746
- ? `tasklist /FI "IMAGENAME eq ${AGENT_NAME}*" /FO CSV /NH`
747
- : `ps -ef | grep ${AGENT_NAME} | grep -v grep`;
748
-
749
- const psOutput = child_process.execSync(psCommand, { encoding: 'utf8' });
750
- const lines = psOutput.trim().split('\n');
751
-
752
- for (const line of lines) {
753
- let foundPid = null;
754
-
755
- if (process.platform === 'win32') {
756
- // Windows CSV format: "image","pid","session","#","mem"
757
- const match = line.match(/"[^"]+","(\d+)"/);
758
- if (match) foundPid = match[1];
759
- } else {
760
- // Unix format: uid pid ppid ...
761
- const parts = line.split(/\s+/);
762
- if (parts.length > 1) foundPid = parts[1];
763
- }
764
-
765
- if (foundPid) {
766
- const pidNum = parseInt(foundPid);
767
- // spawn된 PID와 비슷한 범위인지 확인
768
- if (Math.abs(pidNum - agentProcess.pid) <= 2) {
769
- Logger.print("WHATAP-AGENT",
770
- `Found actual agent PID: ${foundPid} (spawn returned: ${agentProcess.pid})`,
771
- false);
772
-
773
- // 실제 PID로 파일 업데이트
774
- fs.writeFileSync(sharedPidFile, foundPid);
775
- this.writeToFile(home, pidFileName, foundPid);
776
- return;
777
- }
778
- }
779
- }
780
-
781
- // 실제 PID를 찾지 못한 경우 spawn이 반환한 PID 사용
782
- Logger.print("WHATAP-AGENT",
783
- `Using spawn PID: ${agentProcess.pid} (actual PID not found)`,
784
- false);
785
-
786
- fs.writeFileSync(sharedPidFile, agentProcess.pid.toString());
787
- this.writeToFile(home, pidFileName, agentProcess.pid.toString());
788
-
789
- } catch (e) {
790
- Logger.printError("WHATAP-AGENT", "Error finding actual PID", e, false);
791
- // 에러 발생 시 spawn이 반환한 PID 사용
792
- fs.writeFileSync(sharedPidFile, agentProcess.pid.toString());
793
- this.writeToFile(home, pidFileName, agentProcess.pid.toString());
794
- }
795
- }, 1000); // 1초 대기
796
- });
797
-
798
- agentProcess.on('close', (code) => {
799
- if (code !== 0) {
800
- Logger.printError("WHATAP-AGENT", `Agent process exited with code ${code}`, null, true);
801
- Logger.print("WHATAP-AGENT", `STDOUT: ${stdout}`, false);
802
- Logger.print("WHATAP-AGENT", `STDERR: ${stderr}`, false);
803
- // 에이전트가 비정상 종료되면 파일 제거
804
- try { fs.unlinkSync(sharedLockFile); } catch (e) {}
805
- try { fs.unlinkSync(sharedPidFile); } catch (e) {}
806
- } else {
807
- Logger.print("WHATAP-AGENT", "Agent started successfully", false);
808
- }
809
- });
810
-
811
- agentProcess.unref();
812
-
813
- Logger.print("WHATAP-AGENT",
814
- `AGENT UP! (process name: ${AGENT_NAME}, using port: ${port}, app: ${appIdentifier})`,
815
- false);
816
-
817
- // 잠금 해제
818
- try { fs.unlinkSync(sharedLockFile); } catch (e) {}
819
-
820
- } catch (e) {
821
- Logger.printError("WHATAP-AGENT", "Error starting agent", e, true);
822
- // 에러 발생 시 파일 정리
823
- try { fs.unlinkSync(sharedLockFile); } catch (e) {}
824
- try { fs.unlinkSync(sharedPidFile); } catch (e) {}
825
- }
238
+ }, self.setLoopTime);
826
239
  };
827
240
 
828
- // 프로세스 종료 정리 작업 개선
829
- process.on('exit', () => {
830
- if (!process.env.WHATAP_HOME || !NodeAgent.prototype.getApplicationIdentifier) {
831
- return;
832
- }
833
-
834
- try {
835
- const appIdentifier = NodeAgent.prototype.getApplicationIdentifier.call(NodeAgent);
836
- const sharedPidFile = path.join(process.env.WHATAP_HOME, `agent-${appIdentifier}.pid`);
837
-
838
- if (fs.existsSync(sharedPidFile)) {
839
- const pid = fs.readFileSync(sharedPidFile, 'utf8').trim();
840
- // 현재 프로세스가 기록된 PID의 부모 프로세스인 경우에만 제거
841
- if (pid === process.env.NODEJS_PARENT_APP_PID) {
842
- fs.unlinkSync(sharedPidFile);
843
- }
844
- }
845
- } catch (e) {
846
- // 에러 무시
847
- }
848
- });
849
-
850
- // graceful shutdown 처리 추가
851
- ['SIGTERM', 'SIGINT'].forEach((signal) => {
852
- process.on(signal, () => {
853
- Logger.print("WHATAP-AGENT", `Received ${signal}, cleaning up...`, false);
854
- process.exit(0);
855
- });
856
- });
857
-
858
- // Updated init method to incorporate configuration setup similar to Python agent
859
- NodeAgent.prototype.init = function(cb) {
241
+ NodeAgent.prototype.connectCB = function (cb) {
860
242
  var self = this;
861
- if (self._initialized) {
862
- return self;
243
+ if(self.connectCount >0 && self.connectCount % 5 == 0 ) {
244
+ return cb(new Error());
863
245
  }
864
- self._initialized = true;
865
- self.starttime = Date.now();
866
-
867
- self.findRoot();
868
-
869
- Logger.initializer.process();
870
- Logger.print('WHATAP-110', 'Start initialize WhaTap Agent... Root[' + self._conf['app.root'] + ']', true);
871
-
872
- if (self._conf['app.root'] == null || self._conf['app.root'].length == 0) {
873
- return Logger.print("WHATAP-111", "Can not find application root directory", true);
874
- }
875
-
876
- // Initialize configuration with proper home directory
877
- if (!self.initConfig('WHATAP_HOME')) {
878
- Logger.printError("WHATAP-CONFIG", "Failed to initialize configuration", null, true);
879
- return self;
880
- }
881
-
882
- NodeUtil.getPackageJson();
883
-
884
- self._conf.init(this._userOpt, function(e) {
885
- if (e) {
886
- Logger.printError("WHATAP-112", "Configuration initialize error. " + e.message,
887
- e, true);
888
- return;
889
- }
890
- Logger.print('WHATAP-113', 'Finish initialize configuration... ' + Boolean(self._conf['reqlog_enabled']), false);
891
- if (Boolean(self._conf['reqlog_enabled']) == true) {
892
- Logger.print("WHATAP-REQLOG", "ReqLog Init Start !!!!", false);
893
- RequestLog.initializer.process();
894
- }
895
-
896
- if(!self._counterManager){
897
- self._counterManager = new CounterManager();
898
- self._counterManager.run();
899
- }
900
-
901
- // Set Oname,Oid
902
- self._securityMaster.decideAgentOnameOid();
903
246
 
904
- // Start Node.js agent with proper port configuration
905
- WhatapUtil.printWhatap();
906
- self.startGoAgent();
907
- TraceContextManager.initialized = true;
908
-
909
- self.initUdp();
910
- });
911
-
912
- self.loadObserves();
913
- return self;
247
+ Logger.print("WHATAP-970", "[WhaTap Agent] now waiting for starting......", true)
248
+ self._tcpsession = TcpSession;
249
+ setTimeout(function () {
250
+ self._tcpsession.open(function(err) {
251
+ if(err) {
252
+ Logger.printError("WHTAP-911", "TCP SESSION OPEN ERROR", err ,true);
253
+ self.connectCB(cb);
254
+ return;
255
+ };
256
+ if(cb) cb();
257
+ });
258
+ }, self.setLoopTime);
914
259
  };
915
260
 
916
- NodeAgent.prototype.context = function(cb) {
917
- return TraceContextManager.getCurrentContext();
918
- }
919
-
920
261
  NodeAgent.prototype.loadObserves = function() {
921
262
  var agent = this;
922
263
  var observes = [];
923
264
 
924
265
  observes.push(HttpObserver);
266
+ observes.push(NetObserver);
267
+ observes.push(ClusterObserver);
925
268
  observes.push(MysqlObserver);
926
269
  observes.push(Mysql2Observer);
927
270
  observes.push(MariaObserver);
928
271
  observes.push(SocketioObserver);
929
272
  observes.push(WebsocketObserver);
930
- // observes.push(WsObserver);
273
+ observes.push(ExpressObserver);
274
+ observes.push(FileObserver);
931
275
  observes.push(MongoObserver);
932
- // observes.push(MongooseObserver);
276
+ observes.push(MongooseObserver);
933
277
  observes.push(RedisObserver);
934
- observes.push(IORedisObserver);
935
278
  observes.push(MssqlObserver);
279
+ observes.push(ThriftObserver);
280
+ observes.push(PromiseObserver);
936
281
  observes.push(PgSqlObserver);
282
+ observes.push(ScheduleObserver);
937
283
  // observes.push(GRpcObserver);
938
284
  observes.push(ApolloObserver);
939
285
  observes.push(PrismaObserver);
@@ -975,83 +321,31 @@ NodeAgent.prototype.setServicePort = function (port) {
975
321
  Configuration['whatap.port'] = port || 0;
976
322
  }
977
323
 
978
- NodeAgent.prototype.initUdp = function() {
324
+ NodeAgent.prototype.profile = function(desc, value){
979
325
  var self = this;
980
- Logger.print('WHATAP-UDP', 'Initializing UDP connection...', false);
981
-
982
- // Initialize the UDP session
983
- UdpSession.udp(self._conf);
984
-
985
- // Initialize the async sender
986
- AsyncSender.startWhatapThread();
987
-
988
- Logger.print('WHATAP-UDP', 'UDP connection initialized', false);
989
- };
990
-
991
- /**
992
- * Check if WHATAP_HOME is set - similar to Python's check_whatap_home
993
- * @param {string} target - Environment variable name to check
994
- * @returns {string|null} - Value of the environment variable or null
995
- */
996
- NodeAgent.prototype.checkWhatapHome = function(target) {
997
- let whatapHome = process.env[target];
998
- if (!whatapHome) {
999
- whatapHome = this.findWhatapConf();
1000
- }
1001
- if (!whatapHome) {
1002
- Logger.print("WHATAP-HOME", `${target} is empty`, true);
1003
- }
1004
- return whatapHome;
1005
- };
1006
326
 
1007
- /**
1008
- * Initialize configuration with default values - similar to Python's init_config
1009
- * @param {string} home - Environment variable name for home directory
1010
- * @returns {boolean} - True if successful, false otherwise
1011
- */
1012
- NodeAgent.prototype.initConfig = function(home) {
1013
- let whatapHome = process.env[home];
1014
- if (!whatapHome) {
1015
- whatapHome = this.findWhatapConf();
1016
- }
1017
- if (!whatapHome) {
1018
- whatapHome = this.readFile(home, home.toLowerCase());
1019
- if (!whatapHome) {
1020
- whatapHome = process.cwd();
1021
- process.env[home] = whatapHome;
327
+ var ctx = TraceContextManager.getCurrentContext();
328
+ if(ctx == null) { return; }
1022
329
 
1023
- Logger.print("WHATAP-HOME", "WHATAP_HOME is empty", true);
1024
- Logger.print("WHATAP-HOME", "WHATAP_HOME set default CURRENT_WORKING_DIRECTORY value", true);
1025
- Logger.print("WHATAP-HOME", `CURRENT_WORKING_DIRECTORY is ${whatapHome}`, true);
1026
- }
330
+ if( self.userProfileHash === 0){
331
+ self.userProfileHash = HashUtil.hashFromString('CustomProfileStep');
1027
332
  }
1028
-
1029
- if (!this.writeFile(home, home.toLowerCase(), whatapHome)) {
1030
- return false;
333
+ DataTextAgent.add(TextTypes.MESSAGE,self.userProfileHash, 'CustomProfileStep');
334
+ var step = new MessageStep();
335
+ step.hash = self.userProfileHash;
336
+ step.start_time = ctx.getElapsedTime();
337
+ step.desc = desc;
338
+ if(value){
339
+ step.value=false;
1031
340
  }
341
+ ctx.profile.add(step);
1032
342
 
1033
- process.env[home] = whatapHome;
1034
- const configFile = path.join(process.env[home], 'whatap.conf');
1035
-
1036
- if (!fs.existsSync(configFile)) {
1037
- try {
1038
- // Copy default config from module directory
1039
- const defaultConfigPath = path.join(path.dirname(__dirname), 'whatap.conf');
1040
- if (fs.existsSync(defaultConfigPath)) {
1041
- const content = fs.readFileSync(defaultConfigPath, 'utf8');
1042
- fs.writeFileSync(configFile, content);
1043
- } else {
1044
- // Create empty config file
1045
- fs.writeFileSync(configFile, '# WhaTap Node.js Agent Configuration\n');
1046
- }
1047
- } catch (e) {
1048
- Logger.printError("WHATAP-CONFIG", "Permission error creating config file", e, true);
1049
- Logger.print("WHATAP-CONFIG", 'Try to execute command: `sudo chmod -R 777 $WHATAP_HOME`', true);
1050
- return false;
1051
- }
1052
- }
1053
-
1054
- return true;
1055
- };
1056
-
343
+ }
344
+ // var plugins={};
345
+ // NodeAgent.prototype.plugin = function(name, func){
346
+ // if(func){
347
+ // plugins[name]=func;
348
+ // }
349
+ // return plugins[name];
350
+ // }
1057
351
  exports.NodeAgent = new NodeAgent();