add prod docker

This commit is contained in:
王性驊 2026-06-25 17:52:17 +08:00
parent e820bc0368
commit a9482fa646
14 changed files with 479 additions and 81 deletions

View File

@ -1,7 +1,7 @@
.run .run
.git .git
web/node_modules web/node_modules
web/dist # web/dist 保留給 deploy/Dockerfile.web.static本機 make web-build 後 COPY
worker/node_modules worker/node_modules
**/*_test.go **/*_test.go
**/.DS_Store **/.DS_Store

View File

@ -1662,3 +1662,153 @@ Starting backend backend at 0.0.0.0:8890...
{"@timestamp":"2026-06-25T17:49:05.203+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2069.1ms","level":"info","span":"0a4994cf697b29d0","trace":"0f685fd382d5680b7209970ee4808dc6"} {"@timestamp":"2026-06-25T17:49:05.203+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2069.1ms","level":"info","span":"0a4994cf697b29d0","trace":"0f685fd382d5680b7209970ee4808dc6"}
{"@timestamp":"2026-06-25T17:49:06.224+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58275 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"8.2ms","level":"info","span":"8447e57ea152313d","trace":"3f8a9dcf4e4550c04faa79e9c620b2d2"} {"@timestamp":"2026-06-25T17:49:06.224+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58275 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"8.2ms","level":"info","span":"8447e57ea152313d","trace":"3f8a9dcf4e4550c04faa79e9c620b2d2"}
{"@timestamp":"2026-06-25T17:49:08.218+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58279 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"4.9ms","level":"info","span":"24c6ce2604e43c9b","trace":"1b8bd5b533a55488943f9e04478f9f4b"} {"@timestamp":"2026-06-25T17:49:08.218+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58279 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"4.9ms","level":"info","span":"24c6ce2604e43c9b","trace":"1b8bd5b533a55488943f9e04478f9f4b"}
{"@timestamp":"2026-06-25T17:49:10.213+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2006.2ms)","duration":"2006.2ms","level":"slow","span":"0045ecc2abcb4687","trace":"4e079a0a132652cda9b6dfc4714bf8ff"}
{"@timestamp":"2026-06-25T17:49:10.213+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2006.2ms","level":"info","span":"0045ecc2abcb4687","trace":"4e079a0a132652cda9b6dfc4714bf8ff"}
{"@timestamp":"2026-06-25T17:49:10.215+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58283 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"3.1ms","level":"info","span":"61e6a20f0e72d0a1","trace":"653e05b0b32a7c53302a3c8f6bf3f7d5"}
{"@timestamp":"2026-06-25T17:49:12.217+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58290 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"4.1ms","level":"info","span":"856376c3d56dd339","trace":"6d06ff846806c3c1b325b387f5105b17"}
{"@timestamp":"2026-06-25T17:49:14.214+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58294 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"2.3ms","level":"info","span":"afefaa7f35fe4ae1","trace":"4c7dee2269d572b553dcf0813eb66ae4"}
{"@timestamp":"2026-06-25T17:49:15.260+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2044.9ms)","duration":"2044.9ms","level":"slow","span":"0cd9fcc1ba61775b","trace":"d367869a0d4e34078f356bc0919b4b85"}
{"@timestamp":"2026-06-25T17:49:15.261+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2044.9ms","level":"info","span":"0cd9fcc1ba61775b","trace":"d367869a0d4e34078f356bc0919b4b85"}
{"@timestamp":"2026-06-25T17:49:16.220+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58300 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"5.7ms","level":"info","span":"2f2ffddd4aef493b","trace":"08e55751814ae17098daafa6807d213a"}
{"@timestamp":"2026-06-25T17:49:18.220+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58306 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"5.9ms","level":"info","span":"241b0c35f7d72642","trace":"de395eb037a65622449c455f028881e3"}
{"@timestamp":"2026-06-25T17:49:20.220+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58311 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"5.1ms","level":"info","span":"ebb12748e813216b","trace":"a8b767ba9b34af74a649d931d69905d0"}
{"@timestamp":"2026-06-25T17:49:20.296+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2032.2ms)","duration":"2032.2ms","level":"slow","span":"39a3c2d3133995f3","trace":"1049728af2c76a9639d1424bd4a6d2be"}
{"@timestamp":"2026-06-25T17:49:20.296+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2032.2ms","level":"info","span":"39a3c2d3133995f3","trace":"1049728af2c76a9639d1424bd4a6d2be"}
{"@timestamp":"2026-06-25T17:49:22.219+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58315 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"5.1ms","level":"info","span":"fed5fc50b94a7bbb","trace":"ccadda96bdaca92b176b579c3547ed71"}
{"@timestamp":"2026-06-25T17:49:24.219+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58320 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"6.0ms","level":"info","span":"ff68e44165a71845","trace":"6e083c659a37ba59631b7c26610ae15a"}
{"@timestamp":"2026-06-25T17:49:25.311+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2014.0ms)","duration":"2014.0ms","level":"slow","span":"0052f4348fe91396","trace":"ebca1cb8758082a9b75e25ba23860e1b"}
{"@timestamp":"2026-06-25T17:49:25.312+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2014.0ms","level":"info","span":"0052f4348fe91396","trace":"ebca1cb8758082a9b75e25ba23860e1b"}
{"@timestamp":"2026-06-25T17:49:26.214+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58324 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"2.4ms","level":"info","span":"e5efbc87e657d0c1","trace":"26ae069f11f440369bfae45758c7156b"}
{"@timestamp":"2026-06-25T17:49:28.218+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58329 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"4.9ms","level":"info","span":"ca11a97305d9421c","trace":"a189bffaf538f2aa5bc4a7622e31624f"}
{"@timestamp":"2026-06-25T17:49:30.260+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58333 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"46.2ms","level":"info","span":"26c03d93588a5fc2","trace":"e81504443fdc0abdede4f7abc1126e97"}
{"@timestamp":"2026-06-25T17:49:30.327+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2013.0ms)","duration":"2013.0ms","level":"slow","span":"6407e1bae63cbee8","trace":"b0568fca29c0ecf72408c51fa611f261"}
{"@timestamp":"2026-06-25T17:49:30.327+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2013.0ms","level":"info","span":"6407e1bae63cbee8","trace":"b0568fca29c0ecf72408c51fa611f261"}
{"@timestamp":"2026-06-25T17:49:32.221+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58340 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"5.9ms","level":"info","span":"4160ad0c252c15cc","trace":"e2a51c91b1fb9cae462c63e07cd8c8df"}
{"@timestamp":"2026-06-25T17:49:34.221+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58344 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"4.8ms","level":"info","span":"e6c255aa2c58d067","trace":"847d9b6b85e5dfdb38dbe101f3044858"}
{"@timestamp":"2026-06-25T17:49:35.340+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2009.3ms)","duration":"2009.3ms","level":"slow","span":"14d2351d66936498","trace":"465672fb8ffaa6c11e1b22336df434ec"}
{"@timestamp":"2026-06-25T17:49:35.340+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2009.3ms","level":"info","span":"14d2351d66936498","trace":"465672fb8ffaa6c11e1b22336df434ec"}
{"@timestamp":"2026-06-25T17:49:36.215+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58349 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"3.4ms","level":"info","span":"14ea1676fe9c7e75","trace":"5e206497dfe0476c1fb31009bb491ccd"}
{"@timestamp":"2026-06-25T17:49:38.218+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58354 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"4.5ms","level":"info","span":"d77c5109885d4969","trace":"ccf04a26b821ce088995288234c9b959"}
{"@timestamp":"2026-06-25T17:49:40.217+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58358 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"2.1ms","level":"info","span":"b5264f792418d59d","trace":"9583e73d114e0d6d73b4caf28839cc07"}
{"@timestamp":"2026-06-25T17:49:40.387+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2044.5ms)","duration":"2044.5ms","level":"slow","span":"18ec04d4275ba4f0","trace":"afa6f275f2232eb7e1128d0fcf50a9fb"}
{"@timestamp":"2026-06-25T17:49:40.387+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2044.5ms","level":"info","span":"18ec04d4275ba4f0","trace":"afa6f275f2232eb7e1128d0fcf50a9fb"}
{"@timestamp":"2026-06-25T17:49:42.219+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58363 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"4.7ms","level":"info","span":"efbcb6fb22f8d67f","trace":"1883cfcd153290035b23eb1c78a8a358"}
{"@timestamp":"2026-06-25T17:49:42.566+08:00","caller":"stat/usage.go:82","content":"CPU: 0m, MEMORY: Alloc=4.5Mi, TotalAlloc=300.4Mi, Sys=27.3Mi, NumGC=117","level":"stat"}
{"@timestamp":"2026-06-25T17:49:42.598+08:00","caller":"load/sheddingstat.go:61","content":"(api) shedding_stat [1m], cpu: 0, total: 42, pass: 42, drop: 0","level":"stat"}
{"@timestamp":"2026-06-25T17:49:42.979+08:00","caller":"stat/metrics.go:210","content":"(haixun-backend) - qps: 0.7/s, drops: 0, avg time: 585.5ms, med: 5.3ms, 90th: 2044.4ms, 99th: 2069.1ms, 99.9th: 2069.1ms","level":"stat"}
{"@timestamp":"2026-06-25T17:49:44.218+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58367 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"4.9ms","level":"info","span":"f9243a2bfdf7d222","trace":"ca91e2df498357b759f89ee062687956"}
{"@timestamp":"2026-06-25T17:49:45.418+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2027.3ms)","duration":"2027.3ms","level":"slow","span":"fad6af145d59ae77","trace":"d47baec2e8a473f7836659b92e198d6a"}
{"@timestamp":"2026-06-25T17:49:45.418+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2027.3ms","level":"info","span":"fad6af145d59ae77","trace":"d47baec2e8a473f7836659b92e198d6a"}
{"@timestamp":"2026-06-25T17:49:46.218+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58371 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"1.9ms","level":"info","span":"ad2ec7244f658598","trace":"9bc5c42cb10c6b08926d0d77338192f9"}
{"@timestamp":"2026-06-25T17:49:50.451+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2031.9ms)","duration":"2031.9ms","level":"slow","span":"7fbd631630cd7543","trace":"e1fb9b12f329f8eebefc10a0105d154c"}
{"@timestamp":"2026-06-25T17:49:50.452+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2031.9ms","level":"info","span":"7fbd631630cd7543","trace":"e1fb9b12f329f8eebefc10a0105d154c"}
{"@timestamp":"2026-06-25T17:49:55.466+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2010.5ms)","duration":"2010.5ms","level":"slow","span":"96202158bcaa10ff","trace":"cf8227d43ba9bde0b181e9bff9b1ff9b"}
{"@timestamp":"2026-06-25T17:49:55.466+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2010.5ms","level":"info","span":"96202158bcaa10ff","trace":"cf8227d43ba9bde0b181e9bff9b1ff9b"}
{"@timestamp":"2026-06-25T17:50:00.490+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2020.7ms)","duration":"2020.7ms","level":"slow","span":"f2ea252d156aa0f3","trace":"543d7b96373b59d9400ef3cc0bd68cc9"}
{"@timestamp":"2026-06-25T17:50:00.491+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2020.7ms","level":"info","span":"f2ea252d156aa0f3","trace":"543d7b96373b59d9400ef3cc0bd68cc9"}
{"@timestamp":"2026-06-25T17:50:05.526+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2031.7ms)","duration":"2031.7ms","level":"slow","span":"27ba86e6454af95e","trace":"a889c2e713d333d87d7649223d85207e"}
{"@timestamp":"2026-06-25T17:50:05.526+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2031.7ms","level":"info","span":"27ba86e6454af95e","trace":"a889c2e713d333d87d7649223d85207e"}
{"@timestamp":"2026-06-25T17:50:06.225+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58406 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"7.0ms","level":"info","span":"d1d1a4a5ee2a9e13","trace":"b646c843fb2ff47322c9b57ac1b01b7f"}
{"@timestamp":"2026-06-25T17:50:10.572+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2042.2ms)","duration":"2042.2ms","level":"slow","span":"5906925838b1dbb4","trace":"b7182c489e58db90a25dfa2fe31f0a58"}
{"@timestamp":"2026-06-25T17:50:10.572+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2042.2ms","level":"info","span":"5906925838b1dbb4","trace":"b7182c489e58db90a25dfa2fe31f0a58"}
{"@timestamp":"2026-06-25T17:50:15.617+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2040.7ms)","duration":"2040.7ms","level":"slow","span":"9120342af7f9fc2c","trace":"6759f558e00a93625fd1afa2c2381863"}
{"@timestamp":"2026-06-25T17:50:15.617+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2040.7ms","level":"info","span":"9120342af7f9fc2c","trace":"6759f558e00a93625fd1afa2c2381863"}
{"@timestamp":"2026-06-25T17:50:20.651+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2030.5ms)","duration":"2030.5ms","level":"slow","span":"18079375ce1b1185","trace":"5624020102cb94d8281d013c54479320"}
{"@timestamp":"2026-06-25T17:50:20.652+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2030.5ms","level":"info","span":"18079375ce1b1185","trace":"5624020102cb94d8281d013c54479320"}
{"@timestamp":"2026-06-25T17:50:25.684+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2028.0ms)","duration":"2028.0ms","level":"slow","span":"df7a34bb8a85bd63","trace":"0390db05e76182bd28b0a5797531a1e7"}
{"@timestamp":"2026-06-25T17:50:25.684+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2028.0ms","level":"info","span":"df7a34bb8a85bd63","trace":"0390db05e76182bd28b0a5797531a1e7"}
{"@timestamp":"2026-06-25T17:50:30.727+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2038.3ms)","duration":"2038.3ms","level":"slow","span":"f36ec7af7253e31b","trace":"015ab49a486fad0f9127295be668fba8"}
{"@timestamp":"2026-06-25T17:50:30.727+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2038.3ms","level":"info","span":"f36ec7af7253e31b","trace":"015ab49a486fad0f9127295be668fba8"}
{"@timestamp":"2026-06-25T17:50:35.763+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2032.6ms)","duration":"2032.6ms","level":"slow","span":"2aa9dfdc5dc8a85e","trace":"b8de737d8ab04873a78f84a404437987"}
{"@timestamp":"2026-06-25T17:50:35.763+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2032.6ms","level":"info","span":"2aa9dfdc5dc8a85e","trace":"b8de737d8ab04873a78f84a404437987"}
{"@timestamp":"2026-06-25T17:50:39.226+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58419 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"3.4ms","level":"info","span":"f63faa48c6bb1197","trace":"5dde53bc0b074cd28ee44ea91f513f33"}
{"@timestamp":"2026-06-25T17:50:39.700+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58421 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"10.3ms","level":"info","span":"c3e561d21852b694","trace":"32eb6fcc5bb3e5aa87b5bbdc4b6b48f8"}
{"@timestamp":"2026-06-25T17:50:40.794+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2028.7ms)","duration":"2028.7ms","level":"slow","span":"2edd3c9c57d63b85","trace":"e5d6ae91768e94027179ac546ffe7bf3"}
{"@timestamp":"2026-06-25T17:50:40.794+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2028.7ms","level":"info","span":"2edd3c9c57d63b85","trace":"e5d6ae91768e94027179ac546ffe7bf3"}
{"@timestamp":"2026-06-25T17:50:41.693+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58424 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"5.0ms","level":"info","span":"5dbf83f4424ef014","trace":"8ea6587d087f51d7924e69207c4208d3"}
{"@timestamp":"2026-06-25T17:50:42.566+08:00","caller":"stat/usage.go:82","content":"CPU: 0m, MEMORY: Alloc=3.9Mi, TotalAlloc=302.4Mi, Sys=27.3Mi, NumGC=118","level":"stat"}
{"@timestamp":"2026-06-25T17:50:42.598+08:00","caller":"load/sheddingstat.go:61","content":"(api) shedding_stat [1m], cpu: 0, total: 18, pass: 18, drop: 0","level":"stat"}
{"@timestamp":"2026-06-25T17:50:42.979+08:00","caller":"stat/metrics.go:210","content":"(haixun-backend) - qps: 0.3/s, drops: 0, avg time: 1355.2ms, med: 2027.9ms, 90th: 2042.2ms, 99th: 2042.2ms, 99.9th: 2042.2ms","level":"stat"}
{"@timestamp":"2026-06-25T17:50:43.692+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58426 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"5.3ms","level":"info","span":"5295b3d06737e601","trace":"ce7e94c80bcbb0bf56a8562d79b6e29b"}
{"@timestamp":"2026-06-25T17:50:45.188+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/personas/51f4d954-b152-4127-bfb9-e47bde06d1f8 - 127.0.0.1:58432 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"5.9ms","level":"info","span":"d00916bfb349cc40","trace":"ac2541ca5ed3e9a20badcf6df59f2d88"}
{"@timestamp":"2026-06-25T17:50:45.188+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/personas - 127.0.0.1:58430 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"6.9ms","level":"info","span":"ef1f8cfe58e03264","trace":"9f582b67aff50e79ec32e0b36df21042"}
{"@timestamp":"2026-06-25T17:50:45.191+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/personas/51f4d954-b152-4127-bfb9-e47bde06d1f8/copy-missions - 127.0.0.1:58431 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"9.0ms","level":"info","span":"367437d8bc78db0d","trace":"6e5d56c577d43c0f206162b38099ad7d"}
{"@timestamp":"2026-06-25T17:50:45.194+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/personas/51f4d954-b152-4127-bfb9-e47bde06d1f8 - 127.0.0.1:58435 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"2.6ms","level":"info","span":"3e1dabad1de57351","trace":"61a5afea13f332a8f61dfa7630cb643a"}
{"@timestamp":"2026-06-25T17:50:45.195+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/personas - 127.0.0.1:58436 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"2.5ms","level":"info","span":"e551bcd1cf2f0b3a","trace":"29c57709c7a7ecd220f80e0efff76a80"}
{"@timestamp":"2026-06-25T17:50:45.200+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/personas - 127.0.0.1:58440 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"2.6ms","level":"info","span":"98cff0faaf497ecb","trace":"adaf628de399aeff7f168e440b470fc3"}
{"@timestamp":"2026-06-25T17:50:45.202+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/personas/51f4d954-b152-4127-bfb9-e47bde06d1f8/copy-missions - 127.0.0.1:58439 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"4.4ms","level":"info","span":"a152fe1fe7e27989","trace":"f792504bf7db0c16f60fed1351c4c20e"}
{"@timestamp":"2026-06-25T17:50:45.208+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/threads-accounts/bf9e27eb-d529-4ef5-be11-20870194a4b8/connection - 127.0.0.1:58442 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"4.5ms","level":"info","span":"ba8c14203dd96ab0","trace":"0c814962fdbf66c6f40276246deecb03"}
{"@timestamp":"2026-06-25T17:50:45.691+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58444 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"3.3ms","level":"info","span":"b0711dd4d554a1e8","trace":"7755c0a1f40b24efbca864661701cfae"}
{"@timestamp":"2026-06-25T17:50:45.824+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2025.2ms)","duration":"2025.2ms","level":"slow","span":"199c25f04bbefc86","trace":"ba3fbca99a84dfdc904c968b4d00e39a"}
{"@timestamp":"2026-06-25T17:50:45.824+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2025.2ms","level":"info","span":"199c25f04bbefc86","trace":"ba3fbca99a84dfdc904c968b4d00e39a"}
{"@timestamp":"2026-06-25T17:50:47.692+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58447 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"4.8ms","level":"info","span":"dd8cd5bc8c1247da","trace":"b1c3722f03618bfc96b3b71236b8d64e"}
{"@timestamp":"2026-06-25T17:50:49.693+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58450 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"5.1ms","level":"info","span":"41a8707a4910eb6f","trace":"27e8f55827230ca837821f0e8920adc6"}
{"@timestamp":"2026-06-25T17:50:50.857+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2029.9ms)","duration":"2029.9ms","level":"slow","span":"1fcf049d1b1bd648","trace":"4476dc380df5731883950db3a6ae79cc"}
{"@timestamp":"2026-06-25T17:50:50.857+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2029.9ms","level":"info","span":"1fcf049d1b1bd648","trace":"4476dc380df5731883950db3a6ae79cc"}
{"@timestamp":"2026-06-25T17:50:51.692+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58452 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"4.5ms","level":"info","span":"b8ecb07eaa5680a3","trace":"d52a86282e0bca9d2e0b30e11f28ce3d"}
{"@timestamp":"2026-06-25T17:50:54.225+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58454 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"10.7ms","level":"info","span":"0c3e262e5475ca06","trace":"9a8abe779a8654a48434b1370edd7a30"}
{"@timestamp":"2026-06-25T17:50:55.875+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2016.3ms)","duration":"2016.3ms","level":"slow","span":"f51bda9751613512","trace":"33b5a9419f30665fcd79eef1c31fa3d7"}
{"@timestamp":"2026-06-25T17:50:55.875+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2016.3ms","level":"info","span":"f51bda9751613512","trace":"33b5a9419f30665fcd79eef1c31fa3d7"}
{"@timestamp":"2026-06-25T17:50:56.220+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58457 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"5.2ms","level":"info","span":"c49c02a13e39069a","trace":"b465d0c3a72bcfb62030ca84623052d2"}
{"@timestamp":"2026-06-25T17:50:58.221+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58459 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"5.7ms","level":"info","span":"0e6441e87a99303c","trace":"5b398f0ca6e742eb914c135d22f8b244"}
{"@timestamp":"2026-06-25T17:51:00.235+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58461 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"19.0ms","level":"info","span":"f2487ec5ee595dd8","trace":"53c1c19f4db9f8109e9f4ab07878695d"}
{"@timestamp":"2026-06-25T17:51:00.927+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2049.2ms)","duration":"2049.2ms","level":"slow","span":"6eb401c7ab06d74a","trace":"64f7e4c2f1d77ca0bf2c659e0c8a7fde"}
{"@timestamp":"2026-06-25T17:51:00.927+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2049.2ms","level":"info","span":"6eb401c7ab06d74a","trace":"64f7e4c2f1d77ca0bf2c659e0c8a7fde"}
{"@timestamp":"2026-06-25T17:51:02.221+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58463 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"5.8ms","level":"info","span":"3f5caad1374ce1f3","trace":"5b06b7d99dcadf5602ec5d4c8d8150b9"}
{"@timestamp":"2026-06-25T17:51:04.215+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58465 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"1.6ms","level":"info","span":"dd0afe2b69cdb27a","trace":"798294bae1ca5c1c46fde67cf1e9a8b9"}
{"@timestamp":"2026-06-25T17:51:05.967+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2037.7ms)","duration":"2037.7ms","level":"slow","span":"7c2f4832ee5aabd1","trace":"48cce458c4a3c84f4f6a4102fa6c39bd"}
{"@timestamp":"2026-06-25T17:51:05.967+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2037.7ms","level":"info","span":"7c2f4832ee5aabd1","trace":"48cce458c4a3c84f4f6a4102fa6c39bd"}
{"@timestamp":"2026-06-25T17:51:06.224+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58467 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"6.6ms","level":"info","span":"edd18ada52671c29","trace":"3312c1a5f56301d016b0afa98c781931"}
{"@timestamp":"2026-06-25T17:51:08.220+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58469 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"5.2ms","level":"info","span":"34b02bb405bd1b90","trace":"c8ec011edca4590bfd58fe0e83ca1b5e"}
{"@timestamp":"2026-06-25T17:51:10.219+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58472 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"5.2ms","level":"info","span":"4474a888892f8ff6","trace":"23fe7854bc517996597e29643aa2987d"}
{"@timestamp":"2026-06-25T17:51:10.999+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2029.1ms)","duration":"2029.1ms","level":"slow","span":"996ced2da175458b","trace":"c4d00a9719a9143cbe3c4bfe8af5e991"}
{"@timestamp":"2026-06-25T17:51:10.999+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2029.1ms","level":"info","span":"996ced2da175458b","trace":"c4d00a9719a9143cbe3c4bfe8af5e991"}
{"@timestamp":"2026-06-25T17:51:12.220+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58474 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"5.6ms","level":"info","span":"8db9340523f3a251","trace":"095616c09e7f8629e3e326fc18f173b7"}
{"@timestamp":"2026-06-25T17:51:14.216+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58478 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"3.2ms","level":"info","span":"0e39fc9c845980dd","trace":"65286215c4f12101a42710bbca78597b"}
{"@timestamp":"2026-06-25T17:51:16.019+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2017.3ms)","duration":"2017.3ms","level":"slow","span":"d950a2dcc230c049","trace":"3871c0ea220c07da7fe07288e71a2594"}
{"@timestamp":"2026-06-25T17:51:16.019+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2017.3ms","level":"info","span":"d950a2dcc230c049","trace":"3871c0ea220c07da7fe07288e71a2594"}
{"@timestamp":"2026-06-25T17:51:16.215+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58485 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"2.4ms","level":"info","span":"d03742ac346b532f","trace":"b2555159fb9070dd85a1f032c88b352e"}
{"@timestamp":"2026-06-25T17:51:18.215+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58488 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"2.7ms","level":"info","span":"01f9298b948bf166","trace":"c1752a135acb880783ad5831c4efa5d9"}
{"@timestamp":"2026-06-25T17:51:20.223+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58494 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"7.0ms","level":"info","span":"49e4e8b4b8cec944","trace":"eea5fb85e331cd7d33193ed71fc48539"}
{"@timestamp":"2026-06-25T17:51:21.075+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2053.6ms)","duration":"2053.6ms","level":"slow","span":"3bc0d76f7d3db4ca","trace":"c5288ede8dfb7e778df0557038c7edef"}
{"@timestamp":"2026-06-25T17:51:21.076+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2053.6ms","level":"info","span":"3bc0d76f7d3db4ca","trace":"c5288ede8dfb7e778df0557038c7edef"}
{"@timestamp":"2026-06-25T17:51:22.222+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58496 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"6.1ms","level":"info","span":"1422529e6457549a","trace":"5797f1318d59cae164576333eb2a5516"}
{"@timestamp":"2026-06-25T17:51:24.213+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58498 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"1.4ms","level":"info","span":"16810873c3a150d7","trace":"284933b494e48ddbb84152c908e2b2ed"}
{"@timestamp":"2026-06-25T17:51:26.109+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2031.2ms)","duration":"2031.2ms","level":"slow","span":"6f3a53767a69f02e","trace":"d014df4a55b42d3527a1300b7430e5a2"}
{"@timestamp":"2026-06-25T17:51:26.109+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2031.2ms","level":"info","span":"6f3a53767a69f02e","trace":"d014df4a55b42d3527a1300b7430e5a2"}
{"@timestamp":"2026-06-25T17:51:26.218+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58502 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"4.2ms","level":"info","span":"454cb458c55f3450","trace":"2ef7f10af5595f3f206df38fe2e487ef"}
{"@timestamp":"2026-06-25T17:51:28.215+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58504 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"2.4ms","level":"info","span":"92ab12dde6eb8e25","trace":"13bdff2fef9d291414d75774d7d5850f"}
{"@timestamp":"2026-06-25T17:51:30.215+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58507 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"1.8ms","level":"info","span":"a2b66cf42b9d80d7","trace":"859c1c2f93df26557715339904f5e4a0"}
{"@timestamp":"2026-06-25T17:51:31.138+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2027.4ms)","duration":"2027.4ms","level":"slow","span":"222d672b8af171ef","trace":"7774b5a322a0f272f8e433e73efbadad"}
{"@timestamp":"2026-06-25T17:51:31.138+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2027.4ms","level":"info","span":"222d672b8af171ef","trace":"7774b5a322a0f272f8e433e73efbadad"}
{"@timestamp":"2026-06-25T17:51:32.219+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58509 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"4.9ms","level":"info","span":"4d453174257f763b","trace":"dac800d8040a7734a4c39f0759135d9d"}
{"@timestamp":"2026-06-25T17:51:34.219+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58512 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"3.1ms","level":"info","span":"9690bcff62330f3f","trace":"3c6ee4e927b8a3f3f9bbb2902695fc3a"}
{"@timestamp":"2026-06-25T17:51:36.152+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2012.1ms)","duration":"2012.1ms","level":"slow","span":"eb094bd8e3ff788c","trace":"e7bb841e096a837a00e2c83f626a4882"}
{"@timestamp":"2026-06-25T17:51:36.153+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2012.1ms","level":"info","span":"eb094bd8e3ff788c","trace":"e7bb841e096a837a00e2c83f626a4882"}
{"@timestamp":"2026-06-25T17:51:36.213+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58520 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"1.4ms","level":"info","span":"de12cdc824373804","trace":"02bd9ca2a817f644c8a70c7e59e75236"}
{"@timestamp":"2026-06-25T17:51:38.226+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58522 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"12.9ms","level":"info","span":"c7c9ba2bee527bf6","trace":"9d907e9a44f5c1286fb45d65c0195498"}
{"@timestamp":"2026-06-25T17:51:40.215+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58526 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"2.6ms","level":"info","span":"3410340cb0412ae1","trace":"fb9caf1acee3bb2248d75e2419cdd60f"}
{"@timestamp":"2026-06-25T17:51:41.179+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2023.9ms)","duration":"2023.9ms","level":"slow","span":"0a8b251823ce2178","trace":"8d1c6cf3173221aea935a06b0f7944f3"}
{"@timestamp":"2026-06-25T17:51:41.179+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2023.9ms","level":"info","span":"0a8b251823ce2178","trace":"8d1c6cf3173221aea935a06b0f7944f3"}
{"@timestamp":"2026-06-25T17:51:42.217+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58528 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"2.2ms","level":"info","span":"91508369a2aee1e5","trace":"4ab53fc6f3d90c86bdf2505acffbeb86"}
{"@timestamp":"2026-06-25T17:51:42.567+08:00","caller":"stat/usage.go:82","content":"CPU: 0m, MEMORY: Alloc=5.1Mi, TotalAlloc=308.5Mi, Sys=27.3Mi, NumGC=120","level":"stat"}
{"@timestamp":"2026-06-25T17:51:42.599+08:00","caller":"load/sheddingstat.go:61","content":"(api) shedding_stat [1m], cpu: 0, total: 50, pass: 50, drop: 0","level":"stat"}
{"@timestamp":"2026-06-25T17:51:42.979+08:00","caller":"stat/metrics.go:210","content":"(haixun-backend) - qps: 0.8/s, drops: 0, avg time: 490.7ms, med: 5.2ms, 90th: 2029.9ms, 99th: 2053.5ms, 99.9th: 2053.5ms","level":"stat"}
{"@timestamp":"2026-06-25T17:51:44.221+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58530 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"3.7ms","level":"info","span":"f4063584c58f806f","trace":"5c70fc3b9a5cc5df38e3f964087576fb"}
{"@timestamp":"2026-06-25T17:51:46.204+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2019.2ms)","duration":"2019.2ms","level":"slow","span":"fae02e25cad201f7","trace":"686a1ba85f584297003cb991620fe88e"}
{"@timestamp":"2026-06-25T17:51:46.206+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2019.2ms","level":"info","span":"fae02e25cad201f7","trace":"686a1ba85f584297003cb991620fe88e"}
{"@timestamp":"2026-06-25T17:51:46.222+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58532 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"3.3ms","level":"info","span":"738d6627b067d5f1","trace":"a0292fb431e29dcf8d25348a484d9b0a"}
{"@timestamp":"2026-06-25T17:51:48.225+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58537 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"7.1ms","level":"info","span":"018d4a86363d10cf","trace":"0877b0d0b36177a1d5da13707ce874a7"}
{"@timestamp":"2026-06-25T17:51:50.216+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58540 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"2.8ms","level":"info","span":"d89b8aa1faa1b169","trace":"f0adc9c21f26a4a2eafb2042cd8e0476"}
{"@timestamp":"2026-06-25T17:51:51.237+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2028.1ms)","duration":"2028.1ms","level":"slow","span":"75f14dfcfdfe228e","trace":"188cfd8052d7f630bbb85faf12503ed8"}
{"@timestamp":"2026-06-25T17:51:51.238+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2028.1ms","level":"info","span":"75f14dfcfdfe228e","trace":"188cfd8052d7f630bbb85faf12503ed8"}
{"@timestamp":"2026-06-25T17:51:52.216+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58543 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"3.3ms","level":"info","span":"3c2583d6dae63260","trace":"186b2e23203da867e75f657b15809084"}
{"@timestamp":"2026-06-25T17:51:56.266+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2025.4ms)","duration":"2025.4ms","level":"slow","span":"d897f9cf146ea347","trace":"b48506c748ff40276de0bb8be770f4fa"}
{"@timestamp":"2026-06-25T17:51:56.266+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2025.4ms","level":"info","span":"d897f9cf146ea347","trace":"b48506c748ff40276de0bb8be770f4fa"}
{"@timestamp":"2026-06-25T17:52:01.302+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2032.3ms)","duration":"2032.3ms","level":"slow","span":"528bb1ad8cd51bb4","trace":"9685192c77fbd9af1b8fcd355a646452"}
{"@timestamp":"2026-06-25T17:52:01.302+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2032.3ms","level":"info","span":"528bb1ad8cd51bb4","trace":"9685192c77fbd9af1b8fcd355a646452"}
{"@timestamp":"2026-06-25T17:52:06.238+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - GET /api/v1/jobs?page=1&pageSize=12 - 127.0.0.1:58545 - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","duration":"5.5ms","level":"info","span":"151e42783870fe7d","trace":"b9c18c085426c4116b902001ff8ebaee"}
{"@timestamp":"2026-06-25T17:52:06.339+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2031.8ms)","duration":"2031.8ms","level":"slow","span":"f737d68a7addff8e","trace":"c61cdcaa62bfd5f61a29f5aa295b15e1"}
{"@timestamp":"2026-06-25T17:52:06.339+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2031.8ms","level":"info","span":"f737d68a7addff8e","trace":"c61cdcaa62bfd5f61a29f5aa295b15e1"}
{"@timestamp":"2026-06-25T17:52:11.374+08:00","caller":"handler/loghandler.go:151","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node - slowcall(2029.7ms)","duration":"2029.7ms","level":"slow","span":"634961175c1cc5e5","trace":"91ec634ef6bf3d04b47381c204442170"}
{"@timestamp":"2026-06-25T17:52:11.374+08:00","caller":"handler/loghandler.go:167","content":"[HTTP] 200 - POST /api/v1/internal/workers/jobs/claim - 127.0.0.1:55162 - node","duration":"2029.7ms","level":"info","span":"634961175c1cc5e5","trace":"91ec634ef6bf3d04b47381c204442170"}

View File

@ -79,11 +79,20 @@ check: fmt test ## 格式化並測試
prod: ## 一鍵啟動 production DockerAPI + Web + workers分身數見 deploy/.env prod: ## 一鍵啟動 production DockerAPI + Web + workers分身數見 deploy/.env
bash scripts/prod-up.sh bash scripts/prod-up.sh
prod-down: ## 停止 production Docker stack prod-update: ## 只重建/重啟 API+Web+Workersmongo/redis 不重啟,資料留在 volume
bash scripts/prod-update.sh
prod-deps: ## 只啟動 mongo+redisnamed volume 持久化)
bash scripts/prod-deps.sh
prod-down: ## 停止 stack不刪 volumeMongo/Redis 資料保留)
bash scripts/prod-down.sh bash scripts/prod-down.sh
prod-wipe-data: ## 停止並刪除 mongo/redis volume危險需輸入 yes
bash scripts/prod-wipe-data.sh
prod-logs: ## 追蹤 production logs可傳 service 名make prod-logs ARGS=api prod-logs: ## 追蹤 production logs可傳 service 名make prod-logs ARGS=api
bash scripts/prod-logs.sh $(ARGS) bash scripts/prod-logs.sh $(ARGS)
prod-build: ## 只建置 production images不啟動 prod-build: web-build ## 建置靜態前端 + production images不啟動
cd deploy && docker compose -f docker-compose.prod.yml build cd deploy && docker compose -f docker-compose.prod.yml build

View File

@ -3,11 +3,19 @@
# ── 對外埠 ── # ── 對外埠 ──
HAIXUN_WEB_PORT=8080 HAIXUN_WEB_PORT=8080
# ── 前端打包模式 ──
# static = 本機 make web-build 後 nginx 只 COPY dist預設最快
# docker = 在 Docker 內跑 npm build需改 compose 用 Dockerfile.web
# HAIXUN_WEB_BUILD_MODE=static
# ── Worker 分身數make prod 會帶入 docker compose --scale── # ── Worker 分身數make prod 會帶入 docker compose --scale──
GO_WORKER_REPLICAS=1 GO_WORKER_REPLICAS=1
NODE_STYLE8D_WORKER_REPLICAS=1 NODE_STYLE8D_WORKER_REPLICAS=1
# ── Mongo / Redis容器內預設通常不用改── # ── Mongo / Redis容器內預設通常不用改──
# 資料存在 Docker named volumehaixun-prod_mongo_data、haixun-prod_redis_data
# prod-down 不會刪 volume重啟 container 資料仍在。
# 只改版程式make prod-update不碰 mongo/redis
HAIXUN_MONGO_URI=mongodb://mongo:27017 HAIXUN_MONGO_URI=mongodb://mongo:27017
HAIXUN_MONGO_DATABASE=haixun HAIXUN_MONGO_DATABASE=haixun
HAIXUN_REDIS_ADDR=redis:6379 HAIXUN_REDIS_ADDR=redis:6379
@ -26,5 +34,7 @@ INIT_ADMIN_PASSWORD=Admin-Pass-1!
# HAIXUN_NODE_WORKER_ID=custom-node-worker-1 # HAIXUN_NODE_WORKER_ID=custom-node-worker-1
# HAIXUN_WORKER_POLL_MS=3000 # HAIXUN_WORKER_POLL_MS=3000
# ── 略過自動 init已有資料庫時可設 1── # ── 略過自動 init ──
# 預設:若 Mongo 已有 members 會自動跳過 init。
# 強制重跑 initPROD_FORCE_INIT=1 make prod
# HAIXUN_SKIP_INIT=1 # HAIXUN_SKIP_INIT=1

View File

@ -1,4 +1,5 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
# 備用:無本機 Node 時在 Docker 內編譯。預設請用 Dockerfile.web.static + make web-build。
FROM node:22-bookworm AS web-builder FROM node:22-bookworm AS web-builder
WORKDIR /src/web WORKDIR /src/web

View File

@ -0,0 +1,7 @@
# syntax=docker/dockerfile:1
# 本機先執行 make web-build再打包純靜態檔 + nginx無 Node 編譯,建置最快)
FROM nginx:1.27-alpine
COPY deploy/nginx.conf /etc/nginx/conf.d/default.conf
COPY web/dist /usr/share/nginx/html
EXPOSE 80

View File

@ -6,6 +6,7 @@ services:
restart: unless-stopped restart: unless-stopped
environment: environment:
MONGO_INITDB_DATABASE: haixun MONGO_INITDB_DATABASE: haixun
# named volume重啟/改版不會清資料(只有 prod-wipe-data 或 docker volume rm 才會)
volumes: volumes:
- mongo_data:/data/db - mongo_data:/data/db
healthcheck: healthcheck:
@ -19,6 +20,7 @@ services:
image: redis:7-alpine image: redis:7-alpine
restart: unless-stopped restart: unless-stopped
command: ["redis-server", "--appendonly", "yes"] command: ["redis-server", "--appendonly", "yes"]
# AOF + named volume重啟後 queue/lock 狀態可從磁碟恢復
volumes: volumes:
- redis_data:/data - redis_data:/data
healthcheck: healthcheck:
@ -81,7 +83,7 @@ services:
web: web:
build: build:
context: .. context: ..
dockerfile: deploy/Dockerfile.web dockerfile: deploy/Dockerfile.web.static
restart: unless-stopped restart: unless-stopped
ports: ports:
- "${HAIXUN_WEB_PORT:-8080}:80" - "${HAIXUN_WEB_PORT:-8080}:80"

View File

@ -5,7 +5,37 @@ server {
index index.html; index index.html;
gzip on; gzip on;
gzip_types text/css application/javascript application/json image/svg+xml; gzip_comp_level 5;
gzip_min_length 256;
gzip_types
text/css
text/javascript
application/javascript
application/json
application/xml
image/svg+xml;
# Vite 產物:檔名含 hash可長期快取
location /assets/ {
add_header Cache-Control "public, max-age=31536000, immutable";
try_files $uri =404;
}
location /downloads/ {
add_header Cache-Control "public, max-age=86400";
try_files $uri =404;
}
location /illustrations/ {
add_header Cache-Control "public, max-age=86400";
try_files $uri =404;
}
# SPA 入口與路由:不快取,避免部署後仍載入舊版 shell
location = /index.html {
add_header Cache-Control "no-cache";
try_files $uri =404;
}
location /api/ { location /api/ {
proxy_pass http://api:8890; proxy_pass http://api:8890;

View File

@ -0,0 +1,178 @@
#!/usr/bin/env bash
# shellcheck disable=SC2034
# Shared helpers for production Docker scripts.
_PROD_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BACKEND_DIR="$(cd "$_PROD_SCRIPT_DIR/.." && pwd)"
DEPLOY_DIR="$BACKEND_DIR/deploy"
COMPOSE_FILE="$DEPLOY_DIR/docker-compose.prod.yml"
ENV_FILE="$DEPLOY_DIR/.env"
ENV_EXAMPLE="$DEPLOY_DIR/.env.example"
prod_common_init() {
:
}
prod_load_env() {
prod_common_init
if [[ ! -f "$ENV_FILE" ]]; then
if [[ -f "$ENV_EXAMPLE" ]]; then
cp "$ENV_EXAMPLE" "$ENV_FILE"
echo "[prod] created $ENV_FILE from .env.example — 請先修改密鑰與管理員密碼"
else
echo "[prod] missing $ENV_FILE" >&2
exit 1
fi
fi
set -a
# shellcheck disable=SC1090
source "$ENV_FILE"
set +a
GO_REPLICAS="${GO_WORKER_REPLICAS:-1}"
NODE_REPLICAS="${NODE_STYLE8D_WORKER_REPLICAS:-1}"
WEB_PORT="${HAIXUN_WEB_PORT:-8080}"
MONGO_DB="${HAIXUN_MONGO_DATABASE:-haixun}"
}
prod_require_docker() {
if ! command -v docker >/dev/null 2>&1; then
echo "[prod] docker is required" >&2
exit 1
fi
}
prod_compose() {
prod_common_init
docker compose -f "$COMPOSE_FILE" "$@"
}
prod_service_health() {
local service="$1"
prod_compose ps --format json "$service" 2>/dev/null \
| grep -o '"Health":"[^"]*"' \
| head -1 \
| cut -d'"' -f4 \
|| true
}
prod_deps_healthy() {
local mongo_ok redis_ok
mongo_ok="$(prod_service_health mongo)"
redis_ok="$(prod_service_health redis)"
[[ "$mongo_ok" == "healthy" && "$redis_ok" == "healthy" ]]
}
prod_wait_deps_healthy() {
echo "[prod] waiting for mongo/redis..."
for _ in $(seq 1 90); do
if prod_deps_healthy; then
return 0
fi
sleep 1
done
echo "[prod] mongo/redis did not become healthy in time" >&2
exit 1
}
prod_ensure_deps() {
if prod_deps_healthy; then
echo "[prod] mongo + redis already healthy — 略過重啟(資料在 named volume"
return 0
fi
echo "[prod] starting mongo + redis..."
prod_compose up -d mongo redis
prod_wait_deps_healthy
}
prod_mongo_has_members() {
prod_compose exec -T mongo mongosh --quiet "$MONGO_DB" --eval \
'db.members.countDocuments({})' 2>/dev/null \
| tr -d '\r' \
| grep -Eq '^[1-9][0-9]*$'
}
prod_should_skip_init() {
if [[ "${HAIXUN_SKIP_INIT:-0}" == "1" ]]; then
return 0
fi
if [[ "${PROD_FORCE_INIT:-0}" == "1" ]]; then
return 1
fi
if prod_mongo_has_members; then
return 0
fi
return 1
}
prod_run_init_if_needed() {
if prod_should_skip_init; then
if [[ "${HAIXUN_SKIP_INIT:-0}" == "1" ]]; then
echo "[prod] skip init (HAIXUN_SKIP_INIT=1)"
else
echo "[prod] skip init (Mongo 已有資料;若要強制重跑請設 PROD_FORCE_INIT=1)"
fi
return 0
fi
echo "[prod] running bootstrap init..."
prod_compose --profile init run --rm init
}
prod_build_web_if_static() {
prod_common_init
if [[ "${HAIXUN_WEB_BUILD_MODE:-static}" == "static" ]]; then
echo "[prod] building frontend static files (vite → web/dist)..."
(cd "$BACKEND_DIR" && make web-build)
else
echo "[prod] HAIXUN_WEB_BUILD_MODE=docker — web image will compile inside Docker"
fi
}
prod_start_app_services() {
local build_flag=()
if [[ "${PROD_SKIP_BUILD:-0}" != "1" ]]; then
build_flag=(--build)
fi
echo "[prod] starting api, web, workers (go=${GO_REPLICAS}, node-style-8d=${NODE_REPLICAS})..."
prod_compose up -d "${build_flag[@]}" \
--no-deps \
--scale "go-worker=${GO_REPLICAS}" \
--scale "node-worker-style-8d=${NODE_REPLICAS}" \
api web go-worker node-worker-style-8d
}
prod_wait_api_health() {
echo "[prod] waiting for API health..."
for _ in $(seq 1 60); do
if curl -fsS "http://127.0.0.1:${WEB_PORT}/api/v1/health" >/dev/null 2>&1; then
return 0
fi
sleep 1
done
echo "[prod] API health check timed out" >&2
exit 1
}
prod_print_volume_hint() {
echo " Data: Mongo/Redis 使用 named volume重啟 container 不會清資料)"
echo " Update app: make -C haixun-backend prod-update"
echo " Wipe data: make -C haixun-backend prod-wipe-data # 會刪除 volume"
}
prod_print_stack_summary() {
echo ""
echo "[prod] stack is up"
echo " Web: http://127.0.0.1:${WEB_PORT}"
echo " API: http://127.0.0.1:${WEB_PORT}/api/v1/health (via nginx)"
echo " Go worker: ${GO_REPLICAS} replica(s)"
echo " Node 8D: ${NODE_REPLICAS} replica(s)"
echo " Env: ${ENV_FILE}"
echo " Stop: make -C haixun-backend prod-down"
echo " Logs: make -C haixun-backend prod-logs"
prod_print_volume_hint
}

View File

@ -0,0 +1,16 @@
#!/usr/bin/env bash
set -euo pipefail
# shellcheck source=scripts/prod-common.sh
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/prod-common.sh"
prod_load_env
prod_require_docker
cd "$DEPLOY_DIR"
prod_ensure_deps
echo ""
echo "[prod] mongo + redis ready"
prod_print_volume_hint

View File

@ -1,9 +1,11 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -euo pipefail set -euo pipefail
BACKEND_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" # shellcheck source=scripts/prod-common.sh
COMPOSE_FILE="$BACKEND_DIR/deploy/docker-compose.prod.yml" source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/prod-common.sh"
cd "$BACKEND_DIR/deploy" prod_common_init
docker compose -f "$COMPOSE_FILE" down cd "$DEPLOY_DIR"
echo "[prod] stopped"
prod_compose down --remove-orphans
echo "[prod] stoppedMongo/Redis 資料仍在 named volume下次 prod / prod-deps 會沿用)"

View File

@ -1,81 +1,23 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -euo pipefail set -euo pipefail
BACKEND_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" # shellcheck source=scripts/prod-common.sh
DEPLOY_DIR="$BACKEND_DIR/deploy" source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/prod-common.sh"
COMPOSE_FILE="$DEPLOY_DIR/docker-compose.prod.yml"
ENV_FILE="$DEPLOY_DIR/.env"
ENV_EXAMPLE="$DEPLOY_DIR/.env.example"
if [[ ! -f "$ENV_FILE" ]]; then prod_load_env
if [[ -f "$ENV_EXAMPLE" ]]; then prod_require_docker
cp "$ENV_EXAMPLE" "$ENV_FILE"
echo "[prod] created $ENV_FILE from .env.example — 請先修改密鑰與管理員密碼"
else
echo "[prod] missing $ENV_FILE" >&2
exit 1
fi
fi
set -a cd "$BACKEND_DIR"
# shellcheck disable=SC1090 prod_build_web_if_static
source "$ENV_FILE"
set +a
GO_REPLICAS="${GO_WORKER_REPLICAS:-1}"
NODE_REPLICAS="${NODE_STYLE8D_WORKER_REPLICAS:-1}"
WEB_PORT="${HAIXUN_WEB_PORT:-8080}"
if ! command -v docker >/dev/null 2>&1; then
echo "[prod] docker is required" >&2
exit 1
fi
cd "$DEPLOY_DIR" cd "$DEPLOY_DIR"
echo "[prod] building images..." echo "[prod] building images..."
docker compose -f "$COMPOSE_FILE" build prod_compose build
echo "[prod] starting mongo + redis..." prod_ensure_deps
docker compose -f "$COMPOSE_FILE" up -d mongo redis prod_run_init_if_needed
echo "[prod] waiting for mongo/redis..." prod_start_app_services
for _ in $(seq 1 90); do prod_wait_api_health
mongo_ok=$(docker compose -f "$COMPOSE_FILE" ps --format json mongo 2>/dev/null | grep -o '"Health":"[^"]*"' | head -1 | cut -d'"' -f4 || true) prod_print_stack_summary
redis_ok=$(docker compose -f "$COMPOSE_FILE" ps --format json redis 2>/dev/null | grep -o '"Health":"[^"]*"' | head -1 | cut -d'"' -f4 || true)
if [[ "$mongo_ok" == "healthy" && "$redis_ok" == "healthy" ]]; then
break
fi
sleep 1
done
if [[ "${HAIXUN_SKIP_INIT:-0}" != "1" ]]; then
echo "[prod] running bootstrap init..."
docker compose -f "$COMPOSE_FILE" --profile init run --rm init
else
echo "[prod] skip init (HAIXUN_SKIP_INIT=1)"
fi
echo "[prod] starting api, web, workers (go=${GO_REPLICAS}, node-style-8d=${NODE_REPLICAS})..."
docker compose -f "$COMPOSE_FILE" up -d \
--scale "go-worker=${GO_REPLICAS}" \
--scale "node-worker-style-8d=${NODE_REPLICAS}" \
api web go-worker node-worker-style-8d
echo "[prod] waiting for API health..."
for _ in $(seq 1 60); do
if curl -fsS "http://127.0.0.1:${WEB_PORT}/api/v1/health" >/dev/null 2>&1; then
break
fi
sleep 1
done
echo ""
echo "[prod] stack is up"
echo " Web: http://127.0.0.1:${WEB_PORT}"
echo " API: http://127.0.0.1:${WEB_PORT}/api/v1/health (via nginx)"
echo " Go worker: ${GO_REPLICAS} replica(s)"
echo " Node 8D: ${NODE_REPLICAS} replica(s)"
echo " Env: ${ENV_FILE}"
echo " Stop: make -C haixun-backend prod-down"
echo " Logs: make -C haixun-backend prod-logs"

View File

@ -0,0 +1,29 @@
#!/usr/bin/env bash
set -euo pipefail
# 只重建/重啟 API、Web、Workers不碰 mongo/redis資料留在 volume
# shellcheck source=scripts/prod-common.sh
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/prod-common.sh"
prod_load_env
prod_require_docker
cd "$BACKEND_DIR"
prod_build_web_if_static
cd "$DEPLOY_DIR"
if ! prod_deps_healthy; then
echo "[prod] mongo/redis 未在運行,先啟動依賴(不會清 volume..."
prod_ensure_deps
else
echo "[prod] mongo + redis 維持運行 — 只更新應用層"
fi
echo "[prod] building app images (api, web, workers)..."
prod_compose build api web go-worker node-worker-style-8d
prod_start_app_services
prod_wait_api_health
prod_print_stack_summary

View File

@ -0,0 +1,22 @@
#!/usr/bin/env bash
set -euo pipefail
# 危險:停止 stack 並刪除 Mongo/Redis named volume。
# shellcheck source=scripts/prod-common.sh
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/prod-common.sh"
prod_load_env
prod_require_docker
cd "$DEPLOY_DIR"
echo "[prod] 這會刪除 haixun-prod_mongo_data 與 haixun-prod_redis_data 內所有資料。"
read -r -p "輸入 yes 才會繼續: " confirm
if [[ "$confirm" != "yes" ]]; then
echo "[prod] cancelled"
exit 1
fi
prod_compose down -v --remove-orphans
echo "[prod] volumes removed — 下次 make prod 會是全新資料庫"