whatap 2.0.5 → 2.0.6-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.
- package/.claude/settings.local.json +15 -1
- package/lib/core/agent.js +63 -45
- package/package.json +2 -2
|
@@ -38,7 +38,21 @@
|
|
|
38
38
|
"Bash(git add *)",
|
|
39
39
|
"Bash(git commit *)",
|
|
40
40
|
"Bash(git fetch *)",
|
|
41
|
-
"Bash(git push *)"
|
|
41
|
+
"Bash(git push *)",
|
|
42
|
+
"Bash(node --check /Users/seunghunlee/agent_workspace/nodejs_agent/lib/core/agent.js)",
|
|
43
|
+
"Bash(git -C /Users/seunghunlee/agent_workspace/nodejs_agent branch -a)",
|
|
44
|
+
"Bash(git -C /Users/seunghunlee/agent_workspace/nodejs_agent log --all --oneline -- test)",
|
|
45
|
+
"Bash(node *)",
|
|
46
|
+
"Bash(git *)",
|
|
47
|
+
"Read(//Users/seunghunlee/workspace/go_sample/node_modules/whatap/lib/core/**)",
|
|
48
|
+
"Read(//Users/seunghunlee/workspace/go_sample/**)",
|
|
49
|
+
"Bash(rm -f agent-cfd56737.pid agent-cfd56737.lock whatap_nodejs.pid)",
|
|
50
|
+
"Bash(pkill -f whatap_nodejs)",
|
|
51
|
+
"Bash(xargs kill -9)",
|
|
52
|
+
"Bash(kill 34859)",
|
|
53
|
+
"Bash(cp node_modules/whatap/lib/core/agent.js node_modules/whatap/lib/core/agent.js.2.0.5.bak)",
|
|
54
|
+
"Bash(cp /Users/seunghunlee/agent_workspace/nodejs_agent/lib/core/agent.js node_modules/whatap/lib/core/agent.js)",
|
|
55
|
+
"Bash(ls -la agent-*)"
|
|
42
56
|
]
|
|
43
57
|
}
|
|
44
58
|
}
|
package/lib/core/agent.js
CHANGED
|
@@ -936,6 +936,52 @@ NodeAgent.prototype.restartGoAgent = function(opts = {}) {
|
|
|
936
936
|
return true;
|
|
937
937
|
};
|
|
938
938
|
|
|
939
|
+
// 기동용 lock 파일이 stale인지 판정
|
|
940
|
+
// lock은 spawn 중 몇 초만 존재해야 정상이므로, 소유 프로세스가 죽었거나
|
|
941
|
+
// 생성 후 60초가 지났으면 stale로 간주한다 (pid 재사용 대비 mtime 안전망)
|
|
942
|
+
NodeAgent.prototype.isStaleLockFile = function(lockFile) {
|
|
943
|
+
let lockPid = null;
|
|
944
|
+
try {
|
|
945
|
+
const stat = fs.statSync(lockFile);
|
|
946
|
+
if (Date.now() - stat.mtime.getTime() > 60000) return true;
|
|
947
|
+
lockPid = parseInt(fs.readFileSync(lockFile, 'utf8').trim(), 10);
|
|
948
|
+
} catch (e) {
|
|
949
|
+
return true;
|
|
950
|
+
}
|
|
951
|
+
// 내용이 비어있거나 파싱 불가: 다른 프로세스가 wx로 생성 직후 pid를 쓰기 전 순간일 수 있음
|
|
952
|
+
// (PM2 cluster 동시 부팅에서 발생 가능) → mtime이 신선한 동안은 기동 중으로 간주,
|
|
953
|
+
// 진짜 깨진 파일이면 60초 후 위의 mtime 규칙으로 stale 처리됨
|
|
954
|
+
if (!lockPid) return false;
|
|
955
|
+
try {
|
|
956
|
+
process.kill(lockPid, 0);
|
|
957
|
+
return false;
|
|
958
|
+
} catch (e) {
|
|
959
|
+
// EPERM: 프로세스는 살아있으나 권한 없음 -> stale 아님
|
|
960
|
+
return e.code !== 'EPERM';
|
|
961
|
+
}
|
|
962
|
+
};
|
|
963
|
+
|
|
964
|
+
// 기동용 lock 획득 (O_EXCL로 원자적 생성, stale lock은 제거 후 1회 재시도)
|
|
965
|
+
NodeAgent.prototype.acquireStartLock = function(lockFile) {
|
|
966
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
967
|
+
try {
|
|
968
|
+
fs.writeFileSync(lockFile, process.pid.toString(), { flag: 'wx' });
|
|
969
|
+
return true;
|
|
970
|
+
} catch (e) {
|
|
971
|
+
if (e.code !== 'EEXIST') {
|
|
972
|
+
Logger.printError("WHATAP-033", "Error acquiring lock", e, false);
|
|
973
|
+
return false;
|
|
974
|
+
}
|
|
975
|
+
if (!this.isStaleLockFile(lockFile)) {
|
|
976
|
+
return false;
|
|
977
|
+
}
|
|
978
|
+
Logger.print("WHATAP-225", `Stale lock file detected (${lockFile}), removing and retrying...`, false);
|
|
979
|
+
try { fs.unlinkSync(lockFile); } catch (unlinkErr) {}
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
return false;
|
|
983
|
+
};
|
|
984
|
+
|
|
939
985
|
// startGoAgent with improved PID handling
|
|
940
986
|
NodeAgent.prototype.startGoAgent = function(opts = {}) {
|
|
941
987
|
const self = this;
|
|
@@ -976,48 +1022,23 @@ NodeAgent.prototype.startGoAgent = function(opts = {}) {
|
|
|
976
1022
|
Logger.printError("WHATAP-029", "Error checking shared lock file", e, false);
|
|
977
1023
|
}
|
|
978
1024
|
|
|
979
|
-
// 3.
|
|
980
|
-
if (
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
Logger.print("WHATAP-030",
|
|
988
|
-
`PM2 cluster mode: Instance ${process.env.pm_id} will start shared agent`,
|
|
989
|
-
false);
|
|
990
|
-
} else {
|
|
991
|
-
// 다른 인스턴스가 이미 에이전트를 시작하는 중
|
|
992
|
-
Logger.print("WHATAP-031",
|
|
993
|
-
`PM2 cluster mode: Instance ${process.env.pm_id} detected another instance starting the agent, will use shared agent`,
|
|
994
|
-
false);
|
|
995
|
-
return;
|
|
996
|
-
}
|
|
997
|
-
} catch (e) {
|
|
998
|
-
Logger.printError("WHATAP-032", "Error acquiring lock in PM2 cluster mode", e, false);
|
|
999
|
-
return;
|
|
1000
|
-
}
|
|
1001
|
-
|
|
1002
|
-
if (!lockAcquired) {
|
|
1003
|
-
return;
|
|
1004
|
-
}
|
|
1005
|
-
} else {
|
|
1006
|
-
// 일반 모드에서는 기존 로직 사용
|
|
1007
|
-
let lockAcquired = false;
|
|
1008
|
-
try {
|
|
1009
|
-
if (!fs.existsSync(sharedLockFile)) {
|
|
1010
|
-
fs.writeFileSync(sharedLockFile, process.pid.toString());
|
|
1011
|
-
lockAcquired = true;
|
|
1012
|
-
}
|
|
1013
|
-
} catch (e) {
|
|
1014
|
-
Logger.printError("WHATAP-033", "Error acquiring lock", e, false);
|
|
1015
|
-
}
|
|
1016
|
-
|
|
1017
|
-
if (!lockAcquired) {
|
|
1025
|
+
// 3. 잠금 파일로 동시 실행 방지 (stale lock은 자동 제거 후 재시도)
|
|
1026
|
+
if (!this.acquireStartLock(sharedLockFile)) {
|
|
1027
|
+
if (isPM2Cluster) {
|
|
1028
|
+
// 다른 인스턴스가 이미 에이전트를 시작하는 중
|
|
1029
|
+
Logger.print("WHATAP-031",
|
|
1030
|
+
`PM2 cluster mode: Instance ${process.env.pm_id} detected another instance starting the agent, will use shared agent`,
|
|
1031
|
+
false);
|
|
1032
|
+
} else {
|
|
1018
1033
|
Logger.print("WHATAP-034", "Another process is starting the agent, waiting...", false);
|
|
1019
|
-
return;
|
|
1020
1034
|
}
|
|
1035
|
+
return;
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
if (isPM2Cluster) {
|
|
1039
|
+
Logger.print("WHATAP-030",
|
|
1040
|
+
`PM2 cluster mode: Instance ${process.env.pm_id} will start shared agent`,
|
|
1041
|
+
false);
|
|
1021
1042
|
}
|
|
1022
1043
|
|
|
1023
1044
|
// 기존 whatap_nodejs.pid 파일 처리 (호환성 유지)
|
|
@@ -1206,8 +1227,8 @@ NodeAgent.prototype.startGoAgent = function(opts = {}) {
|
|
|
1206
1227
|
Logger.print("WHATAP-040", `PID ${actualPid} written to PID files`, false);
|
|
1207
1228
|
|
|
1208
1229
|
// Lock 파일 해제 (spawn 완료 후 안전하게 삭제)
|
|
1230
|
+
// 이 lock은 proper-lockfile이 아닌 writeFileSync로 생성한 파일이므로 unlink만 수행
|
|
1209
1231
|
try {
|
|
1210
|
-
properLock.unlockSync(sharedLockFile);
|
|
1211
1232
|
fs.unlinkSync(sharedLockFile);
|
|
1212
1233
|
Logger.print("WHATAP-041", "Lock file released after spawn", false);
|
|
1213
1234
|
} catch (e) {}
|
|
@@ -1278,10 +1299,7 @@ NodeAgent.prototype.startGoAgent = function(opts = {}) {
|
|
|
1278
1299
|
} catch (e) {
|
|
1279
1300
|
Logger.printError("WHATAP-048", "Error starting agent", e, false);
|
|
1280
1301
|
// 에러 발생 시 파일 정리
|
|
1281
|
-
try {
|
|
1282
|
-
properLock.unlockSync(sharedLockFile);
|
|
1283
|
-
fs.unlinkSync(sharedLockFile);
|
|
1284
|
-
} catch (unlockErr) {}
|
|
1302
|
+
try { fs.unlinkSync(sharedLockFile); } catch (unlockErr) {}
|
|
1285
1303
|
try { fs.unlinkSync(sharedPidFile); } catch (pidErr) {}
|
|
1286
1304
|
}
|
|
1287
1305
|
};
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "whatap",
|
|
3
3
|
"homepage": "http://www.whatap.io",
|
|
4
|
-
"version": "2.0.
|
|
5
|
-
"releaseDate": "
|
|
4
|
+
"version": "2.0.6-canary.0",
|
|
5
|
+
"releaseDate": "20260713",
|
|
6
6
|
"description": "Monitoring and Profiling Service",
|
|
7
7
|
"main": "index.js",
|
|
8
8
|
"scripts": {},
|