whatap 0.5.26 → 1.0.0-canary.0

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 +78 -32
  2. package/agent/darwin/arm64/whatap_nodejs +0 -0
  3. package/agent/linux/amd64/whatap_nodejs +0 -0
  4. package/agent/linux/arm64/whatap_nodejs +0 -0
  5. package/build.txt +4 -0
  6. package/lib/conf/config-default.js +3 -10
  7. package/lib/conf/configure.js +349 -369
  8. package/lib/conf/license.js +1 -1
  9. package/lib/control/packagectr-helper.js +3 -34
  10. package/lib/core/agent.js +882 -176
  11. package/lib/core/interceptor.js +6 -6
  12. package/lib/core/shimmer.js +36 -82
  13. package/lib/counter/counter-manager.js +8 -79
  14. package/lib/counter/task/activetransaction.js +17 -68
  15. package/lib/io/data-inputx.js +3 -13
  16. package/lib/io/data-outputx.js +206 -268
  17. package/lib/logger.js +6 -6
  18. package/lib/net/security-master.js +20 -139
  19. package/lib/observers/apollo-server-observer.js +27 -33
  20. package/lib/observers/global-observer.js +80 -155
  21. package/lib/observers/http-observer.js +236 -666
  22. package/lib/observers/ioredis-observer.js +294 -0
  23. package/lib/observers/maria-observer.js +362 -204
  24. package/lib/observers/mongodb-observer.js +226 -169
  25. package/lib/observers/mongoose-observer.js +323 -518
  26. package/lib/observers/mssql-observer.js +418 -177
  27. package/lib/observers/mysql-observer.js +449 -342
  28. package/lib/observers/mysql2-observer.js +358 -396
  29. package/lib/observers/oracle-observer.js +384 -559
  30. package/lib/observers/pgsql-observer.js +489 -231
  31. package/lib/observers/prisma-observer.js +92 -303
  32. package/lib/observers/process-observer.js +35 -79
  33. package/lib/observers/redis-observer.js +331 -166
  34. package/lib/observers/socket.io-observer.js +187 -226
  35. package/lib/observers/websocket-observer.js +301 -175
  36. package/lib/pack/counter-pack.js +0 -3
  37. package/lib/pack/log-sink-pack.js +52 -14
  38. package/lib/pack/tagcount-pack.js +4 -4
  39. package/lib/{counter/task → system}/gc-action.js +74 -27
  40. package/lib/trace/trace-context-manager.js +25 -113
  41. package/lib/trace/trace-context.js +7 -21
  42. package/lib/trace/trace-httpc.js +11 -17
  43. package/lib/trace/trace-sql.js +21 -29
  44. package/lib/udp/async_sender.js +119 -0
  45. package/lib/udp/index.js +17 -0
  46. package/lib/udp/packet_enum.js +52 -0
  47. package/lib/udp/packet_queue.js +69 -0
  48. package/lib/udp/packet_type_enum.js +33 -0
  49. package/lib/udp/param_def.js +72 -0
  50. package/lib/udp/udp_session.js +336 -0
  51. package/lib/util/escape-literal-sql.js +5 -5
  52. package/lib/util/hashutil.js +18 -18
  53. package/lib/util/keygen.js +3 -0
  54. package/lib/util/linkedset.js +2 -1
  55. package/lib/util/nodeutil.js +1 -2
  56. package/lib/util/sql-util.js +178 -0
  57. package/lib/util/trace-helper.js +91 -0
  58. package/lib/util/transfer.js +58 -0
  59. package/lib/value/map-value.js +2 -3
  60. package/package.json +5 -10
  61. package/whatap.conf +4 -1
  62. package/lib/conf/conf-sys-mon.js +0 -101
  63. package/lib/control/cmd-config.js +0 -24
  64. package/lib/control/control-handler.js +0 -367
  65. package/lib/core/request-agent.js +0 -27
  66. package/lib/counter/meter/meter-activex.js +0 -67
  67. package/lib/counter/meter/meter-httpc.js +0 -57
  68. package/lib/counter/meter/meter-resource.js +0 -9
  69. package/lib/counter/meter/meter-service.js +0 -168
  70. package/lib/counter/meter/meter-socket.io.js +0 -51
  71. package/lib/counter/meter/meter-sql.js +0 -71
  72. package/lib/counter/meter/meter-users.js +0 -58
  73. package/lib/counter/meter.js +0 -183
  74. package/lib/counter/task/agentinfo.js +0 -107
  75. package/lib/counter/task/gcstat.js +0 -34
  76. package/lib/counter/task/heapmem.js +0 -25
  77. package/lib/counter/task/httpc.js +0 -76
  78. package/lib/counter/task/metering-info.js +0 -125
  79. package/lib/counter/task/proc-cpu.js +0 -29
  80. package/lib/counter/task/realtimeuser.js +0 -31
  81. package/lib/counter/task/res/systemECSTask.js +0 -39
  82. package/lib/counter/task/res/systemKubeTask.js +0 -53
  83. package/lib/counter/task/res/util/awsEcsClientThread.js +0 -218
  84. package/lib/counter/task/res/util/linuxProcStatUtil.js +0 -14
  85. package/lib/counter/task/res-sys-cpu.js +0 -62
  86. package/lib/counter/task/service.js +0 -202
  87. package/lib/counter/task/socketio.js +0 -30
  88. package/lib/counter/task/sql.js +0 -105
  89. package/lib/counter/task/systemperf.js +0 -43
  90. package/lib/data/datapack-sender.js +0 -289
  91. package/lib/data/dataprofile-agent.js +0 -162
  92. package/lib/data/datatext-agent.js +0 -135
  93. package/lib/data/event-level.js +0 -15
  94. package/lib/data/test.js +0 -49
  95. package/lib/data/zipprofile.js +0 -197
  96. package/lib/env/constants.js +0 -21
  97. package/lib/error/error-handler.js +0 -437
  98. package/lib/kube/kube-client.js +0 -144
  99. package/lib/lang/text-types.js +0 -58
  100. package/lib/logsink/line-log-util.js +0 -87
  101. package/lib/logsink/line-log.js +0 -12
  102. package/lib/logsink/log-sender.js +0 -78
  103. package/lib/logsink/log-tracer.js +0 -40
  104. package/lib/logsink/sender-util.js +0 -56
  105. package/lib/logsink/zip/zip-send.js +0 -177
  106. package/lib/net/netflag.js +0 -55
  107. package/lib/net/receiver.js +0 -66
  108. package/lib/net/sender.js +0 -141
  109. package/lib/net/tcp-return.js +0 -18
  110. package/lib/net/tcp-session.js +0 -286
  111. package/lib/net/tcpreq-client-proxy.js +0 -70
  112. package/lib/net/tcprequest-mgr.js +0 -58
  113. package/lib/observers/cluster-observer.js +0 -22
  114. package/lib/observers/express-observer.js +0 -215
  115. package/lib/observers/file-observer.js +0 -184
  116. package/lib/observers/grpc-observer.js +0 -336
  117. package/lib/observers/memcached-observer.js +0 -56
  118. package/lib/observers/mongo-observer.js +0 -317
  119. package/lib/observers/net-observer.js +0 -77
  120. package/lib/observers/promise-observer.js +0 -31
  121. package/lib/observers/schedule-observer.js +0 -67
  122. package/lib/observers/stream-observer.js +0 -19
  123. package/lib/observers/thrift-observer.js +0 -197
  124. package/lib/pack/activestack-pack.js +0 -55
  125. package/lib/pack/apenum.js +0 -8
  126. package/lib/pack/errorsnap-pack.js +0 -69
  127. package/lib/pack/event-pack.js +0 -54
  128. package/lib/pack/hitmap-pack.js +0 -63
  129. package/lib/pack/hitmap-pack1.js +0 -152
  130. package/lib/pack/netstat.js +0 -15
  131. package/lib/pack/otype.js +0 -7
  132. package/lib/pack/profile-pack.js +0 -49
  133. package/lib/pack/realtimeuser-pack.js +0 -41
  134. package/lib/pack/stat-general-pack.js +0 -96
  135. package/lib/pack/staterror-pack.js +0 -120
  136. package/lib/pack/stathttpc-pack.js +0 -66
  137. package/lib/pack/stathttpc-rec.js +0 -78
  138. package/lib/pack/statremote-pack.js +0 -46
  139. package/lib/pack/statservice-pack.js +0 -63
  140. package/lib/pack/statservice-pack1.js +0 -88
  141. package/lib/pack/statservice-rec.js +0 -292
  142. package/lib/pack/statservice-rec_dep.js +0 -151
  143. package/lib/pack/statsql-pack.js +0 -69
  144. package/lib/pack/statsql-rec.js +0 -100
  145. package/lib/pack/statuseragent-pack.js +0 -44
  146. package/lib/pack/tagctr.js +0 -15
  147. package/lib/pack/text-pack.js +0 -50
  148. package/lib/pack/time-count.js +0 -25
  149. package/lib/pack/websocket.js +0 -15
  150. package/lib/pack/zip-pack.js +0 -70
  151. package/lib/pii/pii-item.js +0 -31
  152. package/lib/pii/pii-mask.js +0 -174
  153. package/lib/plugin/plugin-loadermanager.js +0 -57
  154. package/lib/plugin/plugin.js +0 -75
  155. package/lib/service/tx-record.js +0 -332
  156. package/lib/stat/stat-error.js +0 -116
  157. package/lib/stat/stat-httpc.js +0 -98
  158. package/lib/stat/stat-remote-ip.js +0 -46
  159. package/lib/stat/stat-remote-ipurl.js +0 -88
  160. package/lib/stat/stat-sql.js +0 -113
  161. package/lib/stat/stat-tranx.js +0 -58
  162. package/lib/stat/stat-tx-caller.js +0 -160
  163. package/lib/stat/stat-tx-domain.js +0 -111
  164. package/lib/stat/stat-tx-referer.js +0 -112
  165. package/lib/stat/stat-useragent.js +0 -48
  166. package/lib/stat/timingsender.js +0 -76
  167. package/lib/step/activestack-step.js +0 -38
  168. package/lib/step/dbc-step.js +0 -36
  169. package/lib/step/http-stepx.js +0 -67
  170. package/lib/step/message-step.js +0 -40
  171. package/lib/step/method-stepx.js +0 -45
  172. package/lib/step/resultset-step.js +0 -40
  173. package/lib/step/securemsg-step.js +0 -44
  174. package/lib/step/socket-step.js +0 -46
  175. package/lib/step/sql-stepx.js +0 -68
  176. package/lib/step/sqlxtype.js +0 -16
  177. package/lib/step/step.js +0 -66
  178. package/lib/step/stepenum.js +0 -54
  179. package/lib/topology/link.js +0 -63
  180. package/lib/topology/nodeinfo.js +0 -123
  181. package/lib/topology/status-detector.js +0 -111
  182. package/lib/util/anylist.js +0 -103
  183. package/lib/util/cardinality/hyperloglog.js +0 -106
  184. package/lib/util/cardinality/murmurhash.js +0 -31
  185. package/lib/util/cardinality/registerset.js +0 -75
  186. package/lib/util/errordata.js +0 -21
  187. package/lib/util/iputil_x.js +0 -527
  188. package/lib/util/kube-util.js +0 -73
  189. package/lib/util/paramsecurity.js +0 -80
  190. package/lib/util/pre-process.js +0 -13
  191. package/lib/util/process-seq.js +0 -166
  192. package/lib/util/property-util.js +0 -36
  193. package/lib/util/request-queue.js +0 -70
  194. package/lib/util/requestdouble-queue.js +0 -72
  195. package/lib/util/resourceprofile.js +0 -157
  196. package/lib/util/stop-watch.js +0 -30
  197. package/lib/util/system-util.js +0 -10
  198. package/lib/util/userid-util.js +0 -57
@@ -5,32 +5,21 @@
5
5
  */
6
6
 
7
7
  var TraceContextManager = require('../trace/trace-context-manager'),
8
- SocketStep = require('../step/socket-step'),
9
8
  conf = require('../conf/configure'),
10
9
  IPUtil = require('../util/iputil'),
11
10
  Logger = require('../logger');
12
11
  const {Detector: URLPatternDetector} = require("../trace/serviceurl-pattern-detector");
13
- const DataTextAgent = require("../data/datatext-agent");
14
- const ResourceProfile = require("../util/resourceprofile");
15
- const ProfilePack = require('../pack/profile-pack');
16
- const TxRecord = require('../service/tx-record');
17
- const DateUtil = require('../util/dateutil');
18
- const SecurityMaster = require('../net/security-master');
19
- const DataProfileAgent = require('../data/dataprofile-agent');
20
- const MeterUsers = require("../counter/meter/meter-users");
21
- const MeterService = require('../counter/meter/meter-service').MeterService;
22
12
  const shimmer = require('../core/shimmer');
23
- const MessageStep = require('../step/message-step');
24
- const HashUtil = require('../util/hashutil');
13
+ const AsyncSender = require('../udp/async_sender');
14
+ const PacketTypeEnum = require('../udp/packet_type_enum');
15
+ const os = require('os');
25
16
 
26
17
  // 설정을 객체로 통합하여 관리 (참조 성능 향상)
27
18
  var config = {
28
19
  trace_background_socket_enabled: conf.getProperty('trace_background_socket_enabled', true),
29
20
  trace_sampling_enabled: conf.getProperty('trace_sampling_enabled', true),
30
21
  trace_sampling_tps: conf.getProperty('trace_sampling_tps', 1000),
31
- resource_sampling_rate: 0.1, // 리소스 프로파일링을 10%만 수행
32
- profile_batch_size: 20, // 프로파일 배치 처리 크기
33
- flush_interval: 500 // 프로파일 플러시 간격 (ms)
22
+ resource_sampling_rate: 0.1 // 리소스 프로파일링을 10%만 수행
34
23
  };
35
24
 
36
25
  // 설정 변경 감지를 단일 리스너로 통합
@@ -68,48 +57,10 @@ var SocketIOObserver = function(agent){
68
57
  }
69
58
  };
70
59
 
71
- // 프로파일 데이터 버퍼링 (배치 처리)
72
- this.profileBuffer = [];
73
-
74
- // 주기적 플러시 설정
75
- setInterval(() => this.flushProfileBuffer(), config.flush_interval);
76
-
77
60
  // IP 주소 캐싱 (성능 최적화)
78
61
  this.ipCache = new Map();
79
62
  };
80
63
 
81
- SocketIOObserver.prototype.flushProfileBuffer = function() {
82
- if (this.profileBuffer.length === 0) return;
83
-
84
- const now = Date.now();
85
- // 100ms 이상 지난 항목만 처리
86
- const bufferToFlush = this.profileBuffer.filter(item => (now - item.timestamp) >= 100);
87
- if (bufferToFlush.length === 0) return;
88
-
89
- // 최대 batch_size까지만 처리
90
- let batchToProcess;
91
- if(bufferToFlush.length > config.profile_batch_size)
92
- batchToProcess = bufferToFlush.slice(0, config.profile_batch_size);
93
- else
94
- batchToProcess = bufferToFlush;
95
-
96
- // 버퍼에서 처리할 항목 제거
97
- this.profileBuffer = this.profileBuffer.filter(item =>
98
- !batchToProcess.some(batch => batch.ctx._id === item.ctx._id)
99
- );
100
-
101
- // 배치 처리
102
- batchToProcess.forEach(item => {
103
- try {
104
- DataProfileAgent.sendProfile(item.ctx, item.profile, false);
105
- // 컨텍스트 정리 (메모리 누수 방지)
106
- item.ctx = null;
107
- } catch (e) {
108
- Logger.printError('WHATAP-615', 'Socket.io buffer flush error', e, false);
109
- }
110
- });
111
- };
112
-
113
64
  // IP 주소 처리 최적화 함수
114
65
  SocketIOObserver.prototype.getProcessedIp = function(address) {
115
66
  if (!address) return null;
@@ -140,41 +91,64 @@ SocketIOObserver.prototype.getProcessedIp = function(address) {
140
91
  return result;
141
92
  };
142
93
 
143
- SocketIOObserver.prototype.inject = function (mod, moduleName) {
144
- if (mod.__whatap_observe__) {
145
- return;
146
- }
147
- mod.__whatap_observe__ = true;
148
- Logger.initPrint("SocketIOObserver");
94
+ // 에러 처리 함수
95
+ function handleSocketError(ctx, err) {
96
+ if (!err) return null;
149
97
 
150
- var self = this;
98
+ try {
99
+ var errorClass = err.code || err.name || err.constructor?.name || 'SocketIOError';
100
+ var errorMessage = err.message || 'socket.io error';
101
+ var errorStack = '';
102
+
103
+ if (conf.trace_sql_error_stack && conf.trace_sql_error_depth && err.stack) {
104
+ var traceDepth = conf.trace_sql_error_depth;
105
+ var stackLines = err.stack.split("\n");
106
+ if (stackLines.length > traceDepth) {
107
+ stackLines = stackLines.slice(0, traceDepth + 1);
108
+ }
109
+ errorStack = stackLines.join("\n");
110
+ }
151
111
 
152
- // 공통 emit 래핑 함수
153
- const wrapEmitFunction = function(target, emitType, getContextInfo) {
154
- if (!target || typeof target.emit !== 'function' || target.emit.__wrapped__) {
155
- return false;
112
+ var shouldAddError = false;
113
+ if (conf._is_trace_ignore_err_cls_contains === true && errorClass &&
114
+ errorClass.indexOf(conf.trace_ignore_err_cls_contains) < 0) {
115
+ shouldAddError = true;
116
+ } else if (conf._is_trace_ignore_err_msg_contains === true && errorMessage &&
117
+ errorMessage.indexOf(conf.trace_ignore_err_msg_contains) < 0) {
118
+ shouldAddError = true;
119
+ } else if (conf._is_trace_ignore_err_cls_contains === false &&
120
+ conf._is_trace_ignore_err_msg_contains === false) {
121
+ shouldAddError = true;
156
122
  }
157
123
 
158
- const originalEmit = target.emit;
159
- target.emit = function(event, ...args) {
160
- if (!config.trace_background_socket_enabled) {
161
- return originalEmit.apply(this, [event, ...args]);
124
+ if (shouldAddError) {
125
+ if (!ctx.error) ctx.error = 1;
126
+ ctx.status = 500;
127
+ var errors = [errorClass];
128
+ if (errorMessage) {
129
+ errors.push(errorMessage);
130
+ }
131
+ if (errorStack || err.stack) {
132
+ errors.push(errorStack || err.stack);
162
133
  }
163
134
 
164
- const contextInfo = getContextInfo ? getContextInfo.call(this) : {};
165
- self.__handleSocketEmitEvent(this, event, args, emitType, contextInfo);
166
- return originalEmit.apply(this, [event, ...args]);
167
- };
135
+ AsyncSender.send_packet(PacketTypeEnum.TX_ERROR, ctx, errors);
136
+ return errorClass; // 에러 정보 반환
137
+ }
138
+ } catch (e) {
139
+ Logger.printError('WHATAP-227', 'Error handling Socket.IO error', e, false);
140
+ }
141
+ return null;
142
+ }
168
143
 
169
- // 원본 함수 속성 보존
170
- Object.defineProperties(target.emit, {
171
- length: { value: originalEmit.length },
172
- name: { value: originalEmit.name },
173
- __wrapped__: { value: true }
174
- });
144
+ SocketIOObserver.prototype.inject = function (mod, moduleName) {
145
+ if (mod.__whatap_observe__) {
146
+ return;
147
+ }
148
+ mod.__whatap_observe__ = true;
149
+ Logger.initPrint("SocketIOObserver");
175
150
 
176
- return true;
177
- };
151
+ var self = this;
178
152
 
179
153
  const wrapSocketIOEvents = function(target) {
180
154
  if (!target || typeof target.on !== 'function') {
@@ -388,141 +362,164 @@ SocketIOObserver.prototype.inject = function (mod, moduleName) {
388
362
  if (mod.Server && mod.Server.prototype) {
389
363
  wrapSocketIOEvents(mod.Server.prototype);
390
364
  }
391
-
392
- // 3. 직접 모듈 래핑 (일부 버전에서 필요할 수 있음)
393
- // if (typeof mod.on === 'function') {
394
- // wrapSocketIOEvents(mod);
395
- // }
396
365
  };
397
366
 
398
- // 소켓 이벤트 처리 최적화 (CPU 및 메모리 사용 감소) - broadcast 지원 추가
399
367
  SocketIOObserver.prototype.__handleSocketEmitEvent = function(socket, event, args, emitType, contextInfo) {
400
- // 빠른 샘플링 체크 (조기 반환으로 성능 향상)
401
368
  if (config.trace_sampling_enabled && !this.socketCounter.checkSampling()) {
402
- MeterService.add(0, 1, 0, SecurityMaster.PCODE, SecurityMaster.OKIND, SecurityMaster.OID);
403
369
  return;
404
370
  }
405
371
 
406
- // 리소스 프로파일링 샘플링 (전체 이벤트의 일부만 측정)
407
- const shouldProfileResource = Math.random() < config.resource_sampling_rate;
372
+ TraceContextManager._asyncLocalStorage.run(this.__initCtx(socket, args, emitType, contextInfo), () => {
373
+ var ctx = TraceContextManager._asyncLocalStorage.getStore();
374
+ if (!ctx) {
375
+ return;
376
+ }
408
377
 
409
- // 컨텍스트 생성 및 실행
410
- TraceContextManager._asyncLocalStorage.run(this.__initCtx(socket, args, shouldProfileResource, emitType, contextInfo), () => {
411
378
  try {
412
- var ctx = TraceContextManager._asyncLocalStorage.getStore();
413
- if (!ctx) return;
414
-
415
- // IP 주소 처리 최적화
416
- var host = null;
417
- var remoteAddress = contextInfo.remoteAddress || (socket && socket.conn && socket.conn.remoteAddress);
418
-
419
- if (remoteAddress) {
420
- const ipInfo = this.getProcessedIp(remoteAddress);
421
- if (ipInfo) {
422
- host = ipInfo.host;
423
- // 이미 처리된 IP 바이트 사용
424
- var step = new SocketStep();
425
- step.start_time = ctx.getElapsedTime();
426
- step.ipaddr = ipInfo.ipBytes;
427
- step.elapsed = 0; // 즉시 종료 (측정 최소화)
428
-
429
- // 브로드캐스트 타입 정보 추가
430
- if (emitType !== 'socket') {
431
- step.broadcast_type = emitType;
432
- step.broadcast_info = contextInfo;
433
- }
434
-
435
- ctx.profile.push(step);
436
- }
437
- } else {
438
- const ipBytes = Buffer.from(IPUtil.stringToBytes("0.0.0.0"));
439
- var step = new SocketStep();
440
- step.start_time = ctx.getElapsedTime();
441
- step.ipaddr = ipBytes;
442
- step.elapsed = 0;
443
-
444
- ctx.profile.push(step);
445
- }
446
-
447
- // 트랜잭션 종료 및 데이터 전송
379
+ ctx.service_name = "/socket.io";
380
+ let hostname = '';
381
+
382
+ let datas = [
383
+ hostname,
384
+ ctx.service_name,
385
+ ctx.remoteIp || 0,
386
+ ctx.userAgentString || '',
387
+ ctx.referer || '',
388
+ String(ctx.userid || 0),
389
+ String(false), // isStaticContents
390
+ ''
391
+ ];
392
+
393
+ AsyncSender.send_packet(PacketTypeEnum.TX_START, ctx, datas);
394
+
395
+ this.__sendSocketMessage(ctx, emitType, contextInfo);
396
+ this.__sendSocketEvent(ctx, socket, event, args, emitType, contextInfo);
448
397
  this.__endTransaction(null, ctx);
449
-
450
398
  } catch (e) {
451
- Logger.printError('WHATAP-616', 'socket.io emit transaction error', e, false);
399
+ Logger.printError('WHATAP-228', 'socket.io emit transaction error', e, false);
452
400
 
453
- // 에러 컨텍스트 정리 (메모리 누수 방지)
454
- var ctx = TraceContextManager._asyncLocalStorage.getStore();
455
- if (ctx) {
456
- TraceContextManager.end(ctx._id);
457
- }
401
+ var errorInfo = handleSocketError(ctx, e);
402
+ this.__endTransaction(errorInfo, ctx);
458
403
  }
459
404
  });
460
405
  };
461
406
 
462
- // 트랜잭션 종료 최적화 (배치 처리 메모리 사용 감소)
463
- SocketIOObserver.prototype.__endTransaction = function(error, ctx) {
407
+ SocketIOObserver.prototype.__sendSocketMessage = function(ctx, emitType, contextInfo) {
464
408
  try {
465
- // 기본 성능 데이터 수집
466
- var profile = new ProfilePack();
467
- var wtx = new TxRecord();
468
- wtx.endTime = DateUtil.currentTime();
469
- profile.time = wtx.endTime;
470
- wtx.elapsed = ctx.getElapsedTime();
471
-
472
- // 서비스 이름에 브로드캐스트 타입 정보 추가
473
- let serviceName = ctx.service_name;
474
- DataTextAgent.SERVICE.add(ctx.service_hash, serviceName);
475
-
476
- wtx.seq = ctx.txid;
477
- wtx.service = ctx.service_hash;
478
-
479
- // 리소스 프로파일링은 샘플링된 경우에만 수행
480
- if (ctx.shouldProfileResource) {
481
- wtx.cpuTime = ResourceProfile.getCPUTime() - ctx.start_cpu;
482
- wtx.malloc = ResourceProfile.getUsedHeapSize() - ctx.start_malloc;
483
- if(wtx.malloc < 0) { wtx.malloc = 0; }
484
- } else {
485
- wtx.cpuTime = 0;
486
- wtx.malloc = 0;
409
+ var title, message;
410
+
411
+ switch (emitType) {
412
+ case 'broadcast':
413
+ title = "Broadcast";
414
+ message = "Broadcast to all clients except sender";
415
+ break;
416
+ case 'room_broadcast':
417
+ title = "Room Broadcast";
418
+ message = `Broadcast to room: ${contextInfo.room || 'unknown'}`;
419
+ break;
420
+ case 'global_broadcast':
421
+ title = "Global Broadcast";
422
+ message = `Total clients: ${contextInfo.connectedSockets || 0}`;
423
+ break;
424
+ case 'server_room_broadcast':
425
+ title = "Server Room Broadcast";
426
+ message = `Room: ${contextInfo.room || 'unknown'}, Total clients: ${contextInfo.connectedSockets || 0}`;
427
+ break;
428
+ default:
429
+ title = "Socket";
430
+ message = "Direct socket message";
487
431
  }
488
432
 
489
- wtx.status = 2;
490
- wtx.ipaddr = ctx.remoteIp;
491
-
492
- // 기본 측정 데이터 기록
493
- MeterService.add(0, wtx.elapsed, 0, SecurityMaster.PCODE, SecurityMaster.OKIND, SecurityMaster.OID);
433
+ AsyncSender.send_packet(PacketTypeEnum.TX_MSG, ctx, [title, '', message]);
434
+ } catch (e) {
435
+ Logger.printError('WHATAP-229', 'Socket.io send message error', e, false);
436
+ throw e;
437
+ }
438
+ };
494
439
 
495
- profile.oid = SecurityMaster.OID;
496
- profile.service = wtx;
440
+ SocketIOObserver.prototype.__sendSocketEvent = function(ctx, socket, event, args, emitType, contextInfo) {
441
+ try {
442
+ var start_time = Date.now();
443
+ ctx.start_time = start_time;
444
+ ctx.elapsed = 0;
445
+ ctx.error = 0;
446
+
447
+ // IP 주소 및 포트 처리
448
+ var ipString = "0.0.0.0";
449
+ var port = 0;
450
+ var remoteAddress = contextInfo.remoteAddress || (socket && socket.conn && socket.conn.remoteAddress);
451
+
452
+ if (remoteAddress) {
453
+ const ipInfo = this.getProcessedIp(remoteAddress);
454
+ if (ipInfo) {
455
+ ipString = ipInfo.host;
456
+ ctx.remoteIp = ipInfo.ipInt;
457
+
458
+ if (socket && socket.conn && socket.conn.remotePort) {
459
+ port = Number(socket.conn.remotePort);
460
+ } else if (remoteAddress.includes(':')) {
461
+ // remoteAddress에서 포트 추출 시도
462
+ const parts = remoteAddress.split(':');
463
+ if (parts.length > 1) {
464
+ const portStr = parts[parts.length - 1];
465
+ const parsedPort = parseInt(portStr, 10);
466
+ if (!isNaN(parsedPort)) {
467
+ port = parsedPort;
468
+ }
469
+ }
470
+ }
471
+ }
472
+ }
497
473
 
498
- // 컨텍스트 ID 보존 후 컨텍스트 종료 (메모리 누수 방지)
499
- const ctxId = ctx._id;
500
- TraceContextManager.end(ctxId);
474
+ var elapsed = Date.now() - start_time;
475
+ ctx.elapsed = elapsed;
501
476
 
502
- // 프로파일 데이터 버퍼에 추가 (비동기 처리 최적화)
503
- this.profileBuffer.push({
504
- ctx: ctx,
505
- profile: profile,
506
- timestamp: Date.now()
507
- });
477
+ var datas = [ipString, port, elapsed, 0];
478
+ AsyncSender.send_packet(PacketTypeEnum.TX_WEB_SOCKET, ctx, datas);
479
+ } catch (e) {
480
+ Logger.printError('WHATAP-230', 'Socket.io send event error', e, false);
481
+ throw e;
482
+ }
483
+ };
508
484
 
509
- if (this.profileBuffer.length > 1000) {
510
- // 가장 오래된 항목부터 제거
511
- this.profileBuffer = this.profileBuffer.slice(-500);
485
+ SocketIOObserver.prototype.__endTransaction = function(error, ctx) {
486
+ try {
487
+ if (error) {
488
+ TraceContextManager.end(ctx != null ? ctx.id : null);
489
+ ctx = null;
490
+ return;
512
491
  }
513
492
 
493
+ if (ctx == null || TraceContextManager.isExist(ctx.id) === false)
494
+ return;
495
+
496
+ ctx.start_time = Date.now();
497
+ let datas = [
498
+ os.hostname(), // hostname
499
+ ctx.service_name,
500
+ 0, // mtid
501
+ 0, // mdepth
502
+ 0, // mcaller_txid
503
+ 0, // mcaller_pcode
504
+ '', // mcaller_spec
505
+ String(0), // mcaller_url_hash
506
+ 200
507
+ ];
508
+ ctx.elapsed = Date.now() - ctx.start_time;
509
+ AsyncSender.send_packet(PacketTypeEnum.TX_END, ctx, datas);
510
+
511
+ TraceContextManager.end(ctx.id);
512
+
514
513
  } catch (e) {
515
- Logger.printError('WHATAP-615', 'Socket.io end transaction error', e, false);
516
- // 에러 시에도 컨텍스트 정리
517
- TraceContextManager.end(ctx._id);
514
+ Logger.printError('WHATAP-231', 'Socket.io end transaction error', e, false);
515
+ TraceContextManager.end(ctx.id);
518
516
  ctx = null;
519
517
  }
520
518
  };
521
519
 
522
- // 컨텍스트 초기화 최적화 - broadcast 정보 추가
523
- SocketIOObserver.prototype.__initCtx = function(socket, args, shouldProfileResource, emitType, contextInfo) {
520
+ SocketIOObserver.prototype.__initCtx = function(socket, args, emitType, contextInfo) {
524
521
  const ctx = TraceContextManager.start();
525
- if (!ctx) {return;}
522
+ if (!ctx) return null;
526
523
 
527
524
  var remote_addr;
528
525
  var remoteAddress = contextInfo.remoteAddress || (socket && socket.conn && socket.conn.remoteAddress);
@@ -534,54 +531,18 @@ SocketIOObserver.prototype.__initCtx = function(socket, args, shouldProfileResou
534
531
  }
535
532
 
536
533
  ctx.service_name = "/socket.io";
537
- ctx.service_hash = HashUtil.hashFromString(ctx.service_name);
538
-
539
- // MessageStep 생성 - 브로드캐스트 타입별 정보
540
- var step = new MessageStep();
541
- var title, message;
542
-
543
- switch (emitType) {
544
- case 'broadcast':
545
- title = "Broadcast";
546
- message = "Broadcast to all clients except sender";
547
- break;
548
- case 'room_broadcast':
549
- title = "Room Broadcast";
550
- message = `Broadcast to room: ${contextInfo.room || 'unknown'}`;
551
- break;
552
- case 'global_broadcast':
553
- title = "Global Broadcast";
554
- message = `Total clients: ${contextInfo.connectedSockets || 0}`;
555
- break;
556
- case 'server_room_broadcast':
557
- title = "Server Room Broadcast";
558
- message = `Room: ${contextInfo.room || 'unknown'}, Total clients: ${contextInfo.connectedSockets || 0}`;
559
- break;
560
- default:
561
- title = "Socket";
562
- message = "Direct socket message";
563
- }
564
-
565
- step.hash = HashUtil.hashFromString(title);
566
- step.start_time = ctx.getElapsedTime();
567
- step.desc = message;
568
- DataTextAgent.MESSAGE.add(step.hash, title);
569
- ctx.profile.push(step);
570
-
571
- // 리소스 측정은 샘플링된 경우에만 수행
572
- ctx.shouldProfileResource = shouldProfileResource;
573
- if (shouldProfileResource) {
574
- ctx.start_malloc = ResourceProfile.getUsedHeapSize();
575
- ctx.start_cpu = ResourceProfile.getCPUTime();
576
- }
577
534
 
578
535
  if (remote_addr) {
579
536
  remote_addr = IPUtil.checkIp4(remote_addr);
580
537
  ctx.remoteIp = IPUtil.stringToInt(remote_addr);
581
- ctx.userid = Long.fromNumber(ctx.remoteIp);
582
- MeterUsers.add(ctx.userid);
538
+ ctx.userid = ctx.remoteIp;
583
539
  }
584
540
 
541
+ // 기본값 설정
542
+ ctx.userAgentString = '';
543
+ ctx.referer = '';
544
+ ctx.status = 200;
545
+
585
546
  return ctx;
586
547
  };
587
548