Compare commits

...
27 Commits
Author SHA1 Message Date
DuansgandTomsun28 1b51c19c97 [fix]fixed sql formatting error (#4008)
Co-authored-by: Tomsun28 <tomsun28@outlook.com>
2026-01-30 00:00:31 +08:00
LunaRain_079 a83cb0f50f [docs] Fix HTTP Service Discovery API response format (#4005) 2026-01-29 22:10:15 +08:00
Tomsun28 d6022cb587 docs: update doc add contributors and pnpm lock (#4002)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2026-01-25 20:34:49 +08:00
LogicandTomsun28 67f525a603 [fix] update table name generation to include application context (#4001)
Co-authored-by: Tomsun28 <tomsun28@outlook.com>
2026-01-24 23:26:08 +08:00
LunaRain_079andDuansg 634006aa7e [refactor] Dynamically concatenate app parameter on the front end to accommodate Prometheus apps (#4000)
Co-authored-by: Duansg <siguoduan@gmail.com>
2026-01-24 23:06:25 +08:00
3eb3f926f5 [fix] Update query parameter encoding and error time parser in VictoriaMetricsClusterDataStorage (#3989)
Co-authored-by: Yang Chen <1597081640@qq.com>
Co-authored-by: aias00 <liuhongyu@apache.org>
Co-authored-by: Duansg <siguoduan@gmail.com>
2026-01-24 20:37:08 +08:00
47caa5bdf8 feat: support otlp http binary protobuf format log data and update doc (#3986)
Signed-off-by: Yang Chen <1597081640@qq.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2026-01-23 18:34:36 +08:00
Logic 67c3727362 [Refactor] tighten resource constraints for XML/XPath collector (#3999) 2026-01-22 18:51:01 +08:00
b510d6e5ea [feature] add datasource status retrieval and update alert settings UI (#3985)
Signed-off-by: Logic <zqr10159@126.com>
Signed-off-by: Duansg <siguoduan@gmail.com>
Co-authored-by: aias00 <liuhongyu@apache.org>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Duansg <siguoduan@gmail.com>
2026-01-20 22:43:47 +08:00
1ab27bd556 [doc]: update to Docusaurus v3.9.2 (#3984)
Co-authored-by: Tomsun28 <tomsun28@outlook.com>
Co-authored-by: Duansg <siguoduan@gmail.com>
Co-authored-by: aias00 <liuhongyu@apache.org>
2026-01-20 22:04:27 +08:00
Duansg 9600a5e56f [improve] upgrade script merge (#3987) 2026-01-19 23:47:32 +08:00
6c0d5c0db4 [fix]Fix issues such as index failure (#3953)
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: Yang Chen <1597081640@qq.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2026-01-18 23:07:42 +08:00
4b010e6523 [monitoring-template] feat(mysql): add database account expiry metrics (#3969)
Co-authored-by: Logic <zqr10159@dromara.org>
Co-authored-by: Duansg <siguoduan@gmail.com>
2026-01-18 22:29:03 +08:00
8962253dd2 [manager] bugfix: fix incorrect status page date calculation (#3962)
Signed-off-by: Tomsun28 <tomsun28@outlook.com>
Co-authored-by: Duansg <siguoduan@gmail.com>
Co-authored-by: Tomsun28 <tomsun28@outlook.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-17 20:08:12 +08:00
Logic afd89e4309 Fix htaccess (#3980)
Signed-off-by: Logic <zqr10159@dromara.org>
2026-01-16 22:16:15 +08:00
Logic 43332f49db [fix]: update Content Security Policy in .htaccess to include new domains (#3979) 2026-01-16 20:53:11 +08:00
Duansg cc90de5541 [fix] fixed cache parsing issues (#3977) 2026-01-16 15:47:09 +08:00
Tomsun28 5e1460bf29 docs: update invitation email template (#3975) 2026-01-16 09:10:51 +08:00
LogicandYang Chen 7dbdca849a [doc]: add monitoring documentation for various service discovery methods (#3965)
Co-authored-by: Yang Chen <1597081640@qq.com>
2026-01-15 21:27:42 +08:00
Yang ChenandDuansg df525d2d32 fix: add GreptimeDB docker-compose assembly configuration (#3960)
Co-authored-by: Duansg <siguoduan@gmail.com>
2026-01-14 20:51:24 +08:00
LunaRain_079 dc96f1766b [Fix]: fix TAG type mismatch by introducing schema version for TDengine (#3963) 2026-01-13 21:29:27 +08:00
Tomsun28andDuansg 70da7d5dce docs: update docs link (#3958)
Co-authored-by: Duansg <siguoduan@gmail.com>
2026-01-11 18:46:13 +08:00
Prakash Kumar 0f1169ce36 [Fix] Fixed alignment of header social links on mobile (#3959) 2026-01-11 09:57:39 +08:00
KOYR 1c38d01abb style: widen table column to prevent label truncation (#3957) 2026-01-10 22:10:53 +08:00
f82b5add11 [feature] Update CSP permissions to include Kapa.ai services (#3948)
Signed-off-by: Duansg <siguoduan@gmail.com>
Co-authored-by: Duansg <siguoduan@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-08 09:49:48 +08:00
KOYR 8e2c1f3b07 style: adjust grid layout width of form labels (#3950) 2026-01-07 15:06:45 +08:00
Logic 8ef92d70d2 [fix] Update overflow properties and enhance swiper container styles (#3947) 2026-01-07 08:10:37 +08:00
1095 changed files with 60378 additions and 7731 deletions
+47 -1
View File
@@ -2545,7 +2545,8 @@
"avatar_url": "https://avatars.githubusercontent.com/u/176664901?v=4",
"profile": "https://github.com/Saramanda9988",
"contributions": [
"doc"
"doc",
"code"
]
},
{
@@ -2667,6 +2668,51 @@
"contributions": [
"code"
]
},
{
"login": "KOYR",
"name": "KOYR",
"avatar_url": "https://avatars.githubusercontent.com/u/53216619?v=4",
"profile": "https://github.com/KOYR",
"contributions": [
"code"
]
},
{
"login": "Lathika226",
"name": "LathikaBaddam",
"avatar_url": "https://avatars.githubusercontent.com/u/178710568?v=4",
"profile": "https://github.com/Lathika226",
"contributions": [
"doc"
]
},
{
"login": "Sahil-Shadwal",
"name": "Sahil Shadwal",
"avatar_url": "https://avatars.githubusercontent.com/u/119167601?v=4",
"profile": "https://shadwal.space/",
"contributions": [
"code"
]
},
{
"login": "BhanuNidumolu",
"name": "N.Bhanu Prasad",
"avatar_url": "https://avatars.githubusercontent.com/u/180380413?v=4",
"profile": "https://github.com/BhanuNidumolu",
"contributions": [
"code"
]
},
{
"login": "Prakash1185",
"name": "Prakash Kumar",
"avatar_url": "https://avatars.githubusercontent.com/u/183058331?v=4",
"profile": "https://prakashh-portfolio.vercel.app/",
"contributions": [
"code"
]
}
],
"contributorsPerLine": 7,
+8 -1
View File
@@ -525,7 +525,7 @@ Thanks to these wonderful people, welcome to join us:
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lx1229"><img src="https://avatars.githubusercontent.com/u/44620005?v=4?s=100" width="100px;" alt="Liuxin"/><br /><sub><b>Liuxin</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=lx1229" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yy549159265"><img src="https://avatars.githubusercontent.com/u/40821310?v=4?s=100" width="100px;" alt="yy549159265"/><br /><sub><b>yy549159265</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=yy549159265" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=yy549159265" title="Tests">⚠️</a> <a href="#design-yy549159265" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/cto-huhang"><img src="https://avatars.githubusercontent.com/u/53338629?v=4?s=100" width="100px;" alt="cto-huhang"/><br /><sub><b>cto-huhang</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=cto-huhang" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Saramanda9988"><img src="https://avatars.githubusercontent.com/u/176664901?v=4?s=100" width="100px;" alt="LunaRain_079"/><br /><sub><b>LunaRain_079</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Saramanda9988" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Saramanda9988"><img src="https://avatars.githubusercontent.com/u/176664901?v=4?s=100" width="100px;" alt="LunaRain_079"/><br /><sub><b>LunaRain_079</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Saramanda9988" title="Documentation">📖</a> <a href="https://github.com/apache/hertzbeat/commits?author=Saramanda9988" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/delei"><img src="https://avatars.githubusercontent.com/u/17263766?v=4?s=100" width="100px;" alt="DeleiGuo"/><br /><sub><b>DeleiGuo</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=delei" title="Documentation">📖</a> <a href="https://github.com/apache/hertzbeat/commits?author=delei" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=delei" title="Tests">⚠️</a> <a href="https://github.com/apache/hertzbeat/issues?q=author%3Adelei" title="Bug reports">🐛</a></td>
</tr>
<tr>
@@ -543,6 +543,13 @@ Thanks to these wonderful people, welcome to join us:
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Jetiaime"><img src="https://avatars.githubusercontent.com/u/93769000?v=4?s=100" width="100px;" alt="TeAmo"/><br /><sub><b>TeAmo</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Jetiaime" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/pentium100"><img src="https://avatars.githubusercontent.com/u/27917?v=4?s=100" width="100px;" alt="pentium100"/><br /><sub><b>pentium100</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=pentium100" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/dedyks"><img src="https://avatars.githubusercontent.com/u/23741665?v=4?s=100" width="100px;" alt="Dedy Kurniawan Santoso"/><br /><sub><b>Dedy Kurniawan Santoso</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=dedyks" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/KOYR"><img src="https://avatars.githubusercontent.com/u/53216619?v=4?s=100" width="100px;" alt="KOYR"/><br /><sub><b>KOYR</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=KOYR" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Lathika226"><img src="https://avatars.githubusercontent.com/u/178710568?v=4?s=100" width="100px;" alt="LathikaBaddam"/><br /><sub><b>LathikaBaddam</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Lathika226" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://shadwal.space/"><img src="https://avatars.githubusercontent.com/u/119167601?v=4?s=100" width="100px;" alt="Sahil Shadwal"/><br /><sub><b>Sahil Shadwal</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Sahil-Shadwal" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/BhanuNidumolu"><img src="https://avatars.githubusercontent.com/u/180380413?v=4?s=100" width="100px;" alt="N.Bhanu Prasad"/><br /><sub><b>N.Bhanu Prasad</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=BhanuNidumolu" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://prakashh-portfolio.vercel.app/"><img src="https://avatars.githubusercontent.com/u/183058331?v=4?s=100" width="100px;" alt="Prakash Kumar"/><br /><sub><b>Prakash Kumar</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Prakash1185" title="Code">💻</a></td>
</tr>
</tbody>
</table>
+8 -1
View File
@@ -522,7 +522,7 @@ Thanks these wonderful people, welcome to join us:
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lx1229"><img src="https://avatars.githubusercontent.com/u/44620005?v=4?s=100" width="100px;" alt="Liuxin"/><br /><sub><b>Liuxin</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=lx1229" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yy549159265"><img src="https://avatars.githubusercontent.com/u/40821310?v=4?s=100" width="100px;" alt="yy549159265"/><br /><sub><b>yy549159265</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=yy549159265" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=yy549159265" title="Tests">⚠️</a> <a href="#design-yy549159265" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/cto-huhang"><img src="https://avatars.githubusercontent.com/u/53338629?v=4?s=100" width="100px;" alt="cto-huhang"/><br /><sub><b>cto-huhang</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=cto-huhang" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Saramanda9988"><img src="https://avatars.githubusercontent.com/u/176664901?v=4?s=100" width="100px;" alt="LunaRain_079"/><br /><sub><b>LunaRain_079</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Saramanda9988" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Saramanda9988"><img src="https://avatars.githubusercontent.com/u/176664901?v=4?s=100" width="100px;" alt="LunaRain_079"/><br /><sub><b>LunaRain_079</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Saramanda9988" title="Documentation">📖</a> <a href="https://github.com/apache/hertzbeat/commits?author=Saramanda9988" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/delei"><img src="https://avatars.githubusercontent.com/u/17263766?v=4?s=100" width="100px;" alt="DeleiGuo"/><br /><sub><b>DeleiGuo</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=delei" title="Documentation">📖</a> <a href="https://github.com/apache/hertzbeat/commits?author=delei" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=delei" title="Tests">⚠️</a> <a href="https://github.com/apache/hertzbeat/issues?q=author%3Adelei" title="Bug reports">🐛</a></td>
</tr>
<tr>
@@ -540,6 +540,13 @@ Thanks these wonderful people, welcome to join us:
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Jetiaime"><img src="https://avatars.githubusercontent.com/u/93769000?v=4?s=100" width="100px;" alt="TeAmo"/><br /><sub><b>TeAmo</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Jetiaime" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/pentium100"><img src="https://avatars.githubusercontent.com/u/27917?v=4?s=100" width="100px;" alt="pentium100"/><br /><sub><b>pentium100</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=pentium100" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/dedyks"><img src="https://avatars.githubusercontent.com/u/23741665?v=4?s=100" width="100px;" alt="Dedy Kurniawan Santoso"/><br /><sub><b>Dedy Kurniawan Santoso</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=dedyks" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/KOYR"><img src="https://avatars.githubusercontent.com/u/53216619?v=4?s=100" width="100px;" alt="KOYR"/><br /><sub><b>KOYR</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=KOYR" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Lathika226"><img src="https://avatars.githubusercontent.com/u/178710568?v=4?s=100" width="100px;" alt="LathikaBaddam"/><br /><sub><b>LathikaBaddam</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Lathika226" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://shadwal.space/"><img src="https://avatars.githubusercontent.com/u/119167601?v=4?s=100" width="100px;" alt="Sahil Shadwal"/><br /><sub><b>Sahil Shadwal</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Sahil-Shadwal" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/BhanuNidumolu"><img src="https://avatars.githubusercontent.com/u/180380413?v=4?s=100" width="100px;" alt="N.Bhanu Prasad"/><br /><sub><b>N.Bhanu Prasad</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=BhanuNidumolu" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://prakashh-portfolio.vercel.app/"><img src="https://avatars.githubusercontent.com/u/183058331?v=4?s=100" width="100px;" alt="Prakash Kumar"/><br /><sub><b>Prakash Kumar</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Prakash1185" title="Code">💻</a></td>
</tr>
</tbody>
</table>
+8 -1
View File
@@ -525,7 +525,7 @@ Thanks these wonderful people, welcome to join us:
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lx1229"><img src="https://avatars.githubusercontent.com/u/44620005?v=4?s=100" width="100px;" alt="Liuxin"/><br /><sub><b>Liuxin</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=lx1229" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yy549159265"><img src="https://avatars.githubusercontent.com/u/40821310?v=4?s=100" width="100px;" alt="yy549159265"/><br /><sub><b>yy549159265</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=yy549159265" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=yy549159265" title="Tests">⚠️</a> <a href="#design-yy549159265" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/cto-huhang"><img src="https://avatars.githubusercontent.com/u/53338629?v=4?s=100" width="100px;" alt="cto-huhang"/><br /><sub><b>cto-huhang</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=cto-huhang" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Saramanda9988"><img src="https://avatars.githubusercontent.com/u/176664901?v=4?s=100" width="100px;" alt="LunaRain_079"/><br /><sub><b>LunaRain_079</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Saramanda9988" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Saramanda9988"><img src="https://avatars.githubusercontent.com/u/176664901?v=4?s=100" width="100px;" alt="LunaRain_079"/><br /><sub><b>LunaRain_079</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Saramanda9988" title="Documentation">📖</a> <a href="https://github.com/apache/hertzbeat/commits?author=Saramanda9988" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/delei"><img src="https://avatars.githubusercontent.com/u/17263766?v=4?s=100" width="100px;" alt="DeleiGuo"/><br /><sub><b>DeleiGuo</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=delei" title="Documentation">📖</a> <a href="https://github.com/apache/hertzbeat/commits?author=delei" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=delei" title="Tests">⚠️</a> <a href="https://github.com/apache/hertzbeat/issues?q=author%3Adelei" title="Bug reports">🐛</a></td>
</tr>
<tr>
@@ -543,6 +543,13 @@ Thanks these wonderful people, welcome to join us:
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Jetiaime"><img src="https://avatars.githubusercontent.com/u/93769000?v=4?s=100" width="100px;" alt="TeAmo"/><br /><sub><b>TeAmo</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Jetiaime" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/pentium100"><img src="https://avatars.githubusercontent.com/u/27917?v=4?s=100" width="100px;" alt="pentium100"/><br /><sub><b>pentium100</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=pentium100" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/dedyks"><img src="https://avatars.githubusercontent.com/u/23741665?v=4?s=100" width="100px;" alt="Dedy Kurniawan Santoso"/><br /><sub><b>Dedy Kurniawan Santoso</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=dedyks" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/KOYR"><img src="https://avatars.githubusercontent.com/u/53216619?v=4?s=100" width="100px;" alt="KOYR"/><br /><sub><b>KOYR</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=KOYR" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Lathika226"><img src="https://avatars.githubusercontent.com/u/178710568?v=4?s=100" width="100px;" alt="LathikaBaddam"/><br /><sub><b>LathikaBaddam</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Lathika226" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://shadwal.space/"><img src="https://avatars.githubusercontent.com/u/119167601?v=4?s=100" width="100px;" alt="Sahil Shadwal"/><br /><sub><b>Sahil Shadwal</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Sahil-Shadwal" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/BhanuNidumolu"><img src="https://avatars.githubusercontent.com/u/180380413?v=4?s=100" width="100px;" alt="N.Bhanu Prasad"/><br /><sub><b>N.Bhanu Prasad</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=BhanuNidumolu" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://prakashh-portfolio.vercel.app/"><img src="https://avatars.githubusercontent.com/u/183058331?v=4?s=100" width="100px;" alt="Prakash Kumar"/><br /><sub><b>Prakash Kumar</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Prakash1185" title="Code">💻</a></td>
</tr>
</tbody>
</table>
@@ -22,6 +22,7 @@ import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.apache.hertzbeat.alert.service.AlertDefineService;
import org.apache.hertzbeat.alert.service.DataSourceService;
import org.apache.hertzbeat.common.entity.alerter.AlertDefine;
import org.apache.hertzbeat.common.entity.dto.Message;
import org.apache.hertzbeat.common.support.exception.AlertExpressionException;
@@ -57,6 +58,9 @@ public class AlertDefineController {
@Autowired
private AlertDefineService alertDefineService;
@Autowired
private DataSourceService dataSourceService;
@PostMapping
@Operation(summary = "New Alarm Definition", description = "Added an alarm definition")
public ResponseEntity<Message<Void>> addNewAlertDefine(@Valid @RequestBody AlertDefine alertDefine) {
@@ -112,4 +116,12 @@ public class AlertDefineController {
}
}
@GetMapping(path = "/datasource/status")
@Operation(summary = "Get available datasource executors status",
description = "Get status of available datasource executors for periodic alerts")
public ResponseEntity<Message<Map<String, Object>>> getDatasourceStatus() {
Map<String, Object> status = dataSourceService.getAvailableExecutors();
return ResponseEntity.ok(Message.successWithData(status));
}
}
@@ -40,4 +40,10 @@ public interface DataSourceService {
* @return result
*/
List<Map<String, Object>> query(String datasource, String expr);
/**
* Get available datasource executors status
* @return map containing available executors by type (promql, sql)
*/
Map<String, Object> getAvailableExecutors();
}
@@ -72,13 +72,6 @@ public class DataSourceServiceImpl implements DataSourceService {
.recordStats()
.build();
@Getter
private final Cache<String, CommonTokenStream> tokenStreamCache = Caffeine.newBuilder()
.maximumSize(512)
.expireAfterWrite(30, TimeUnit.MINUTES)
.recordStats()
.build();
public DataSourceServiceImpl(@Autowired(required = false) List<QueryExecutor> executors) {
this.executors = executors != null ? executors : Collections.emptyList();
this.sqlSecurityValidator = new SqlSecurityValidator(DEFAULT_ALLOWED_TABLES);
@@ -159,10 +152,12 @@ public class DataSourceServiceImpl implements DataSourceService {
}
private List<Map<String, Object>> evaluate(String expr, QueryExecutor executor) {
CommonTokenStream tokens = tokenStreamCache.get(expr, this::createTokenStream);
CommonTokenStream tokens = createTokenStream(expr);
AlertExpressionParser parser = new AlertExpressionParser(tokens);
ParseTree tree = expressionCache.get(expr, e -> parser.expr());
if (null != tokens && tokens.LA(1) != Token.EOF) {
// Validate EOF only during the first parsing (when tokens.index > 0)
// Skip EOF check when cache hit, as it has already been validated on the first pass.
if (tokens.index() > 0 && tokens.LA(1) != Token.EOF) {
throw new AlertExpressionException(bundle.getString("alerter.calculate.parse.error"));
}
AlertExpressionEvalVisitor visitor = new AlertExpressionEvalVisitor(executor, tokens);
@@ -173,4 +168,34 @@ public class DataSourceServiceImpl implements DataSourceService {
AlertExpressionLexer lexer = new AlertExpressionLexer(CharStreams.fromString(expr));
return new CommonTokenStream(lexer);
}
@Override
public Map<String, Object> getAvailableExecutors() {
boolean hasPromqlExecutor = false;
boolean hasSqlExecutor = false;
java.util.Set<String> availableExecutors = new java.util.HashSet<>();
if (executors != null) {
for (QueryExecutor executor : executors) {
String datasource = executor.getDatasource();
availableExecutors.add(datasource);
// Check if executor supports promql
if (executor.support(WarehouseConstants.PROMQL)) {
hasPromqlExecutor = true;
}
// Check if executor supports sql
if (executor.support(WarehouseConstants.SQL)) {
hasSqlExecutor = true;
}
}
}
Map<String, Object> result = new java.util.HashMap<>(8);
result.put("hasPromqlExecutor", hasPromqlExecutor);
result.put("hasSqlExecutor", hasSqlExecutor);
result.put("availableExecutors", availableExecutors);
return result;
}
}
@@ -18,7 +18,6 @@
package org.apache.hertzbeat.alert.service;
import com.github.benmanes.caffeine.cache.Cache;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
import org.apache.hertzbeat.alert.service.impl.DataSourceServiceImpl;
import org.apache.hertzbeat.common.support.exception.AlertExpressionException;
@@ -557,13 +556,11 @@ class DataSourceServiceTest {
dataSourceService.setExecutors(List.of(mockExecutor));
String expr = "node_cpu_seconds_total > 50";
Cache<String, ParseTree> expressionCache = dataSourceService.getExpressionCache();
Cache<String, CommonTokenStream> tokenStreamCache = dataSourceService.getTokenStreamCache();
expressionCache.invalidateAll();
tokenStreamCache.invalidateAll();
long beforeHits = tokenStreamCache.stats().hitCount();
long beforeHits = expressionCache.stats().hitCount();
dataSourceService.calculate("promql", expr);
dataSourceService.calculate("promql", expr);
long actualHits = tokenStreamCache.stats().hitCount() - beforeHits;
long actualHits = expressionCache.stats().hitCount() - beforeHits;
assertEquals(1, actualHits, "expression cache should hit but miss");
}
@@ -578,9 +575,7 @@ class DataSourceServiceTest {
dataSourceService.setExecutors(List.of(mockExecutor));
dataSourceService.calculate("promql", "node_cpu_seconds_total > 50");
Cache<String, ParseTree> expressionCache = dataSourceService.getExpressionCache();
Cache<String, CommonTokenStream> tokenStreamCache = dataSourceService.getTokenStreamCache();
expressionCache.invalidateAll();
tokenStreamCache.invalidateAll();
String expr1 = "node_cpu_seconds_total > 30";
String expr2 = "node_cpu_seconds_total > 50";
long beforeHits = expressionCache.stats().hitCount();
@@ -601,15 +596,13 @@ class DataSourceServiceTest {
dataSourceService.setExecutors(List.of(mockExecutor));
dataSourceService.calculate("promql", "node_cpu_seconds_total > 50");
Cache<String, ParseTree> expressionCache = dataSourceService.getExpressionCache();
Cache<String, CommonTokenStream> tokenStreamCache = dataSourceService.getTokenStreamCache();
expressionCache.invalidateAll();
tokenStreamCache.invalidateAll();
String expr1 = "node_cpu_seconds_total > 30";
String expr2 = "node_cpu_seconds_total > 50";
long beforeHits = tokenStreamCache.stats().hitCount();
long beforeHits = expressionCache.stats().hitCount();
dataSourceService.calculate("promql", expr1);
dataSourceService.calculate("promql", expr2);
long actualHits = tokenStreamCache.stats().hitCount() - beforeHits;
long actualHits = expressionCache.stats().hitCount() - beforeHits;
assertEquals(0, actualHits, "expression cache should miss but hit");
}
@@ -39,6 +39,7 @@ import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import javax.net.ssl.SSLException;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
@@ -106,6 +107,22 @@ import java.util.Collections;
*/
@Slf4j
public class HttpCollectImpl extends AbstractCollect {
/**
* Pre-compiled regex patterns for dangerous Xpath detection.
* Compiled once at class load for performance.
*/
private static final List<Pattern> DANGEROUS_XPATH_PATTERNS;
static {
List<Pattern> patterns = new ArrayList<>();
for (String pattern : CollectorConstants.DANGEROUS_XPATH_PATTERNS) {
// Use CASE_INSENSITIVE to prevent bypass via case variations (e.g., //TEXT() vs //text())
patterns.add(Pattern.compile(pattern, Pattern.CASE_INSENSITIVE | Pattern.DOTALL));
}
DANGEROUS_XPATH_PATTERNS = Collections.unmodifiableList(patterns);
}
private final Set<Integer> defaultSuccessStatusCodes = Set.of(
HttpStatus.SC_OK,
HttpStatus.SC_CREATED,
@@ -357,21 +374,83 @@ public class HttpCollectImpl extends AbstractCollect {
}
}
/**
* Validates the Xpath expression to prevent DoS attacks.
* Checks for dangerous patterns that could traverse the entire XML document.
* Uses pre-compiled patterns for performance and case-insensitive matching for security.
*
* @param xpathExpression the Xpath expression to validate
* @throws IllegalArgumentException if the expression contains dangerous patterns
*/
private void validateXpathExpression(String xpathExpression) throws IllegalArgumentException {
if (!StringUtils.hasText(xpathExpression)) {
return;
}
// Check against dangerous patterns using pre-compiled regex
for (Pattern pattern : DANGEROUS_XPATH_PATTERNS) {
Matcher matcher = pattern.matcher(xpathExpression);
if (matcher.find()) {
throw new IllegalArgumentException(
"Xpath expression contains dangerous pattern that may cause DoS: " + pattern.pattern()
);
}
}
// Check for excessive wildcard usage (more than 3 // or * operators)
long descendantAxisCount = xpathExpression.chars().filter(ch -> ch == '/').count();
long wildcardCount = xpathExpression.chars().filter(ch -> ch == '*').count();
if (descendantAxisCount > 10 || wildcardCount > 5) {
throw new IllegalArgumentException(
"Xpath expression contains too many wildcards or descendant axes, potential DoS risk"
);
}
log.debug("Xpath expression validation passed: {}", xpathExpression);
}
private void parseResponseByXmlPath(String resp, Metrics metrics,
CollectRep.MetricsData.Builder builder, Long responseTime) {
HttpProtocol http = metrics.getHttp();
List<String> aliasFields = metrics.getAliasFields();
String xpathExpression = http.getParseScript();
// Layer 1: Validate Xpath expression is not empty
if (!StringUtils.hasText(xpathExpression)) {
log.warn("Http collect parse type is xmlPath, but the xpath expression is empty.");
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg("XPath expression is empty");
builder.setMsg("Xpath expression is empty");
return;
}
// Layer 2: Check XML response size to prevent memory exhaustion
if (resp != null && resp.length() > CollectorConstants.MAX_XML_RESPONSE_SIZE) {
log.warn("XML response size {} bytes exceeds maximum allowed size {} bytes",
resp.length(), CollectorConstants.MAX_XML_RESPONSE_SIZE);
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg("XML response exceeds maximum allowed size of "
+ (CollectorConstants.MAX_XML_RESPONSE_SIZE / 1024 / 1024) + "MB");
return;
}
// Layer 3: Validate Xpath expression for dangerous patterns
try {
validateXpathExpression(xpathExpression);
} catch (IllegalArgumentException e) {
log.warn("Xpath expression validation failed: {}", e.getMessage());
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg(e.getMessage());
return;
}
int keywordNum = CollectUtil.countMatchKeyword(resp, http.getKeyword());
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// Layer 4: Enable XML secure processing and XXE protection
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
@@ -387,7 +466,7 @@ public class HttpCollectImpl extends AbstractCollect {
NodeList nodeList = (NodeList) xpath.evaluate(xpathExpression, document, XPathConstants.NODESET);
if (nodeList == null || nodeList.getLength() == 0) {
log.debug("XPath expression '{}' returned no nodes.", xpathExpression);
log.debug("Xpath expression '{}' returned no nodes.", xpathExpression);
boolean requestedSummaryFields = aliasFields.stream()
.anyMatch(alias -> NetworkConstants.RESPONSE_TIME.equalsIgnoreCase(alias)
|| CollectorConstants.KEYWORD.equalsIgnoreCase(alias));
@@ -408,7 +487,16 @@ public class HttpCollectImpl extends AbstractCollect {
return;
}
for (int i = 0; i < nodeList.getLength(); i++) {
// Layer 5: Limit the number of results to prevent excessive resource consumption
int resultSize = nodeList.getLength();
int maxResults = CollectorConstants.MAX_XPATH_RESULT_NODES;
if (resultSize > maxResults) {
log.warn("Xpath expression returned {} nodes, exceeding limit of {}. Processing first {} nodes only.",
resultSize, maxResults, maxResults);
resultSize = maxResults;
}
for (int i = 0; i < resultSize; i++) {
Node node = nodeList.item(i);
CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder();
@@ -422,7 +510,7 @@ public class HttpCollectImpl extends AbstractCollect {
String value = (String) xpath.evaluate(alias, node, XPathConstants.STRING);
valueRowBuilder.addColumn(StringUtils.hasText(value) ? value : CommonConstants.NULL_VALUE);
} catch (XPathExpressionException e) {
log.warn("Failed to evaluate XPath '{}' for node [{}]: {}", alias, node.getNodeName(), e.getMessage());
log.warn("Failed to evaluate Xpath '{}' for node [{}]: {}", alias, node.getNodeName(), e.getMessage());
valueRowBuilder.addColumn(CommonConstants.NULL_VALUE);
}
}
@@ -431,7 +519,7 @@ public class HttpCollectImpl extends AbstractCollect {
}
} catch (Exception e) {
log.warn("Failed to parse XML response with XPath '{}': {}", xpathExpression, e.getMessage(), e);
log.warn("Failed to parse XML response with Xpath '{}': {}", xpathExpression, e.getMessage(), e);
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg("Failed to parse XML response: " + e.getMessage());
}
@@ -882,4 +970,4 @@ public class HttpCollectImpl extends AbstractCollect {
}
return successCodeSet.contains(statusCode);
}
}
}
@@ -49,4 +49,28 @@ public interface CollectorConstants extends NetworkConstants {
String STATUS_CODE = "statusCode";
/**
* Maximum XML response size in bytes (10MB) to prevent DoS attacks
*/
int MAX_XML_RESPONSE_SIZE = 10 * 1024 * 1024;
/**
* Maximum number of nodes returned by Xpath query to prevent excessive resource consumption
*/
int MAX_XPATH_RESULT_NODES = 1000;
/**
* Dangerous Xpath expression patterns that could cause DoS attacks
* These patterns match expressions that traverse the entire XML document
*/
String[] DANGEROUS_XPATH_PATTERNS = {
"//\\*\\s*\\|\\s*//@\\*\\s*\\|\\s*//text\\(\\)", // //* | //@* | //text()
"//\\*\\s*\\|", // //* | ...
"//@\\*\\s*\\|", // //@* | ...
"//node\\(\\)\\s*\\|", // //node() | ...
"descendant-or-self::node\\(\\)\\s*\\|", // descendant-or-self::node() | ...
"/descendant-or-self::node\\(\\)", // /descendant-or-self::node()
"//\\*[\\s\\S]*//\\*" // //** with multiple wildcards
};
}
@@ -48,8 +48,8 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener;
*/
@Entity
@Table(name = "hzb_alert_define_monitor_bind", indexes = {
@Index(name = "index_alert_define_monitor", columnList = "alertDefineId"),
@Index(name = "index_alert_define_monitor", columnList = "monitor_id")
@Index(name = "idx_alert_define_id", columnList = "alert_define_id"),
@Index(name = "idx_monitor_id", columnList = "monitor_id")
})
@Data
@Builder
@@ -42,8 +42,8 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener;
*/
@Entity
@Table(name = "hzb_collector_monitor_bind", indexes = {
@Index(name = "index_collector_monitor", columnList = "collector"),
@Index(name = "index_collector_monitor", columnList = "monitor_id")
@Index(name = "idx_collector_monitor_collector", columnList = "collector"),
@Index(name = "idx_collector_monitor_monitor_id", columnList = "monitor_id")
})
@Data
@Builder
@@ -51,9 +51,9 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener;
*/
@Entity
@Table(name = "hzb_monitor", indexes = {
@Index(name = "monitor_query_index", columnList = "app"),
@Index(name = "monitor_query_index", columnList = "instance"),
@Index(name = "monitor_query_index", columnList = "name")
@Index(name = "idx_hzb_monitor_app", columnList = "app"),
@Index(name = "idx_hzb_monitor_instance", columnList = "instance"),
@Index(name = "idx_hzb_monitor_name", columnList = "name")
})
@Data
@Builder
@@ -62,51 +62,51 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener;
@Schema(description = "Monitor Entity")
@EntityListeners(AuditingEntityListener.class)
public class Monitor {
@Id
@Schema(title = "Monitor task ID", example = "87584674384", accessMode = READ_ONLY)
private Long id;
@Schema(title = "Collect task ID", example = "43243543543", accessMode = READ_ONLY)
private Long jobId;
@Schema(title = "task name", example = "Api-TanCloud.cn", accessMode = READ_WRITE)
@Size(max = 100)
private String name;
@Schema(title = "Type of monitoring", example = "TanCloud", accessMode = READ_WRITE)
@Size(max = 100)
private String app;
@Schema(title = "Scrape type: static | http_sd | dns_sd | zookeeper_sd", example = "static", accessMode = READ_WRITE)
@Size(max = 100)
private String scrape;
@Schema(title = "the monitor target: ip/domain+port or ip/domain", example = "192.167.25.11:8081", accessMode = READ_WRITE)
@Size(max = 100)
@HostValid
private String instance;
@Schema(title = "Monitoring of the acquisition interval time in seconds", example = "600", accessMode = READ_WRITE)
@Min(10)
private Integer intervals;
@Schema(title = "Schedule type: interval | cron", example = "interval", accessMode = READ_WRITE)
@Size(max = 20)
private String scheduleType;
@Schema(title = "Cron expression when scheduleType is cron", example = "0/5 * * * * ?", accessMode = READ_WRITE)
@Size(max = 100)
private String cronExpression;
@Schema(title = "Task status 0: Paused, 1: Up, 2: Down", accessMode = READ_WRITE)
@Min(0)
@Max(4)
private byte status;
@Schema(title = "Task type 0: Normal, 1: push auto create, 2: discovery auto create")
private byte type;
@Schema(title = "task label", example = "{env:test}", accessMode = READ_WRITE)
@Convert(converter = JsonMapAttributeConverter.class)
@Column(length = 4096)
@@ -116,23 +116,23 @@ public class Monitor {
@Convert(converter = JsonMapAttributeConverter.class)
@Column(length = 4096)
private Map<String, String> annotations;
@Schema(title = "Monitor note description", example = "Availability monitoring of the SAAS website TanCloud", accessMode = READ_WRITE)
@Size(max = 255)
private String description;
@Schema(title = "The creator of this record", example = "tom", accessMode = READ_ONLY)
@CreatedBy
private String creator;
@Schema(title = "The modifier of this record", example = "tom", accessMode = READ_ONLY)
@LastModifiedBy
private String modifier;
@Schema(title = "Record create time", example = "2024-07-02T20:09:34.903217", accessMode = READ_ONLY)
@CreatedDate
private LocalDateTime gmtCreate;
@Schema(title = "Record modify time", example = "2024-07-02T20:09:34.903217", accessMode = READ_ONLY)
@LastModifiedDate
private LocalDateTime gmtUpdate;
@@ -42,7 +42,7 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener;
*/
@Entity
@Table(name = "hzb_monitor_bind", indexes = {
@Index(name = "index_monitor_bind", columnList = "bizId"),
@Index(name = "index_monitor_bind", columnList = "biz_id"),
@Index(name = "index_monitor_bin", columnList = "monitor_id")
})
@Data
@@ -59,7 +59,7 @@ public class MonitorBind {
@Schema(title = "key string: ip:port")
private String keyStr;
@Schema(title = "connect bind id", example = "87432674384")
private Long bizId;
@@ -46,8 +46,11 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener;
* Monitor parameter values
*/
@Entity
@Table(name = "hzb_param", indexes = { @Index(columnList = "monitorId") },
uniqueConstraints = @UniqueConstraint(columnNames = {"monitorId", "field"}))
@Table(
name = "hzb_param",
indexes = {@Index(name = "idx_hzb_param_monitor_id", columnList = "monitor_id")},
uniqueConstraints = {@UniqueConstraint(name = "uk_hzb_param_monitor_field", columnNames = {"monitor_id", "field"})}
)
@Data
@Builder
@AllArgsConstructor
@@ -68,6 +71,7 @@ public class Param {
* Monitor ID
*/
@Schema(title = "Monitor task ID", example = "875846754543", accessMode = READ_WRITE)
@Column(name = "monitor_id")
private Long monitorId;
/**
@@ -75,6 +79,7 @@ public class Param {
*/
@Schema(title = "Parameter identifier field", example = "port", accessMode = READ_WRITE)
@Size(max = 100)
@Column(name = "field")
@NotBlank(message = "field can not null")
private String field;
@@ -41,7 +41,6 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener;
@Entity
@Table(name = "hzb_status_page_incident_component_bind", indexes = {
@Index(name = "index_incident_component", columnList = "incident_id"),
@Index(name = "index_incident_component", columnList = "component_id")
})
@Data
@Builder
@@ -59,7 +58,7 @@ public class StatusPageIncidentComponentBind {
@Schema(title = "Incident ID", example = "87432674384")
@Column(name = "incident_id")
private Long incidentId;
@Schema(title = "Component ID", example = "87432674336")
@Column(name = "component_id")
private Long componentId;
@@ -71,5 +70,5 @@ public class StatusPageIncidentComponentBind {
@Schema(title = "Record modify time", example = "1612198444000")
@LastModifiedDate
private LocalDateTime gmtUpdate;
}
@@ -35,8 +35,8 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener;
*/
@Entity
@Table(name = "hzb_push_metrics", indexes = {
@Index(name = "push_query_index", columnList = "monitorId"),
@Index(name = "push_query_index", columnList = "time")
@Index(name = "idx_push_metrics_monitor_id", columnList = "monitor_id"),
@Index(name = "idx_push_metrics_time", columnList = "time")
})
@Data
@Builder
@@ -37,10 +37,10 @@ import lombok.NoArgsConstructor;
*/
@Entity
@Table(name = "hzb_history", indexes = {
@Index(name = "history_query_index", columnList = "instance"),
@Index(name = "history_query_index", columnList = "app"),
@Index(name = "history_query_index", columnList = "metrics"),
@Index(name = "history_query_index", columnList = "metric")
@Index(name = "idx_hzb_history_instance", columnList = "instance"),
@Index(name = "idx_hzb_history_app", columnList = "app"),
@Index(name = "idx_hzb_history_metrics", columnList = "metrics"),
@Index(name = "idx_hzb_history_metric", columnList = "metric")
})
@Data
@Builder
@@ -65,7 +65,7 @@ public class History {
@Schema(title = "Monitoring Metric usage speed count")
private String metric;
@Column(length = 5000)
private String metricLabels;
@@ -159,4 +159,8 @@ public class StrBuffer {
}
return Double.parseDouble(s);
}
public static String escapeForFormat(String value) {
return value.replace("%", "%%");
}
}
@@ -161,6 +161,6 @@ public class GreptimeLogStorageE2eTest {
long startTime = endTime - Duration.ofMinutes(5).toMillis(); // Look back 5 minutes
return greptimeDbDataStorage.queryLogsByMultipleConditions(
startTime, endTime, null, null, null, null);
startTime, endTime, null, null, null, null, null);
}
}
@@ -17,6 +17,7 @@
package org.apache.hertzbeat.log.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
@@ -25,8 +26,8 @@ import org.apache.hertzbeat.common.constants.CommonConstants;
import org.apache.hertzbeat.common.entity.dto.Message;
import org.apache.hertzbeat.log.service.LogProtocolAdapter;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@@ -34,15 +35,16 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Log Ingestion Controller
* Generic Log Ingestion Controller
* Provides a fallback endpoint for log protocols that don't have dedicated controllers.
* For OTLP protocol, use OtlpLogController instead.
*/
@Tag(name = "Log Ingestion Controller")
@RestController
@RequestMapping(path = "/api/logs", produces = "application/json")
@RequestMapping(path = "/api/logs", produces = MediaType.APPLICATION_JSON_VALUE)
@Slf4j
public class LogIngestionController {
private static final String DEFAULT_PROTOCOL = "otlp";
private final List<LogProtocolAdapter> protocolAdapters;
public LogIngestionController(List<LogProtocolAdapter> protocolAdapters) {
@@ -51,26 +53,23 @@ public class LogIngestionController {
/**
* Receive log payload pushed from external system specifying the log protocol.
* Examples:
* - POST /api/logs/ingest/otlp (content body is OTLP JSON)
*
* @param protocol log protocol identifier
* @param content raw request body
* @param protocol log protocol identifier (e.g., "vector", "loki")
* @param content raw request body
*/
@PostMapping("/ingest/{protocol}")
public ResponseEntity<Message<Void>> ingestExternLog(@PathVariable("protocol") String protocol,
@RequestBody String content) {
log.debug("Receive extern log from protocol: {}, content length: {}", protocol, content == null ? 0 : content.length());
if (!StringUtils.hasText(protocol)) {
protocol = DEFAULT_PROTOCOL; // Default to OTLP if no protocol specified
}
@Operation(summary = "Ingest logs by protocol name")
@PostMapping(value = "/ingest/{protocol}", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Message<Void>> ingestLog(@PathVariable("protocol") String protocol,
@RequestBody String content) {
log.debug("Receive log from protocol: {}, content length: {}", protocol, content == null ? 0 : content.length());
for (LogProtocolAdapter adapter : protocolAdapters) {
if (adapter.supportProtocol().equalsIgnoreCase(protocol)) {
try {
adapter.ingest(content);
return ResponseEntity.ok(Message.success("Add extern log success"));
} catch (Exception e) {
log.error("Add extern log failed: {}", e.getMessage(), e);
log.error("Add log failed: {}", e.getMessage(), e);
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(Message.fail(CommonConstants.FAIL_CODE, "Add extern log failed: " + e.getMessage()));
}
@@ -80,30 +79,4 @@ public class LogIngestionController {
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(Message.fail(CommonConstants.FAIL_CODE, "Not support the " + protocol + " protocol log"));
}
/**
* Receive default log payload (when protocol is not specified).
* It will look for a service whose supportProtocol() returns "otlp".
*/
@PostMapping("/ingest")
public ResponseEntity<Message<Void>> ingestDefaultExternLog(@RequestBody String content) {
log.info("Receive default extern log content, length: {}", content == null ? 0 : content.length());
LogProtocolAdapter adapter = protocolAdapters.stream()
.filter(item -> DEFAULT_PROTOCOL.equalsIgnoreCase(item.supportProtocol()))
.findFirst()
.orElse(null);
if (adapter != null) {
try {
adapter.ingest(content);
return ResponseEntity.ok(Message.success("Add extern log success"));
} catch (Exception e) {
log.error("Add extern log failed: {}", e.getMessage(), e);
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(Message.fail(CommonConstants.FAIL_CODE, "Add extern log failed: " + e.getMessage()));
}
}
log.error("Not support default extern log protocol");
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(Message.fail(CommonConstants.FAIL_CODE, "Not support the default protocol log"));
}
}
@@ -61,50 +61,54 @@ public class LogQueryController {
}
@GetMapping("/list")
@Operation(summary = "Query logs by time range with optional filters",
description = "Query logs by [start,end] in ms and optional filters with pagination. Returns paginated log entries sorted by timestamp in descending order.")
@Operation(summary = "Query logs by time range with optional filters",
description = "Query logs by [start,end] in ms and optional filters with pagination. Returns paginated log entries sorted by timestamp in descending order.")
public ResponseEntity<Message<Page<LogEntry>>> list(
@Parameter(description = "Start timestamp in milliseconds (Unix timestamp)", example = "1640995200000")
@Parameter(description = "Start timestamp in milliseconds (Unix timestamp)", example = "1640995200000")
@RequestParam(value = "start", required = false) Long start,
@Parameter(description = "End timestamp in milliseconds (Unix timestamp)", example = "1641081600000")
@Parameter(description = "End timestamp in milliseconds (Unix timestamp)", example = "1641081600000")
@RequestParam(value = "end", required = false) Long end,
@Parameter(description = "Trace ID for distributed tracing", example = "1234567890abcdef")
@Parameter(description = "Trace ID for distributed tracing", example = "1234567890abcdef")
@RequestParam(value = "traceId", required = false) String traceId,
@Parameter(description = "Span ID for distributed tracing", example = "abcdef1234567890")
@Parameter(description = "Span ID for distributed tracing", example = "abcdef1234567890")
@RequestParam(value = "spanId", required = false) String spanId,
@Parameter(description = "Log severity number (1-24 according to OpenTelemetry standard)", example = "9")
@Parameter(description = "Log severity number (1-24 according to OpenTelemetry standard)", example = "9")
@RequestParam(value = "severityNumber", required = false) Integer severityNumber,
@Parameter(description = "Log severity text (TRACE, DEBUG, INFO, WARN, ERROR, FATAL)", example = "INFO")
@Parameter(description = "Log severity text (TRACE, DEBUG, INFO, WARN, ERROR, FATAL)", example = "INFO")
@RequestParam(value = "severityText", required = false) String severityText,
@Parameter(description = "Page index starting from 0", example = "0")
@Parameter(description = "Log content search keyword", example = "error")
@RequestParam(value = "search", required = false) String search,
@Parameter(description = "Page index starting from 0", example = "0")
@RequestParam(value = "pageIndex", required = false, defaultValue = "0") Integer pageIndex,
@Parameter(description = "Number of items per page", example = "20")
@Parameter(description = "Number of items per page", example = "20")
@RequestParam(value = "pageSize", required = false, defaultValue = "20") Integer pageSize) {
Page<LogEntry> result = getPagedLogs(start, end, traceId, spanId, severityNumber, severityText, pageIndex, pageSize);
Page<LogEntry> result = getPagedLogs(start, end, traceId, spanId, severityNumber, severityText, search, pageIndex, pageSize);
return ResponseEntity.ok(Message.success(result));
}
@GetMapping("/stats/overview")
@Operation(summary = "Log overview statistics",
description = "Overall counts and basic statistics with filters. Provides counts by severity levels according to OpenTelemetry standard.")
@Operation(summary = "Log overview statistics",
description = "Overall counts and basic statistics with filters. Provides counts by severity levels according to OpenTelemetry standard.")
public ResponseEntity<Message<Map<String, Object>>> overviewStats(
@Parameter(description = "Start timestamp in milliseconds (Unix timestamp)", example = "1640995200000")
@Parameter(description = "Start timestamp in milliseconds (Unix timestamp)", example = "1640995200000")
@RequestParam(value = "start", required = false) Long start,
@Parameter(description = "End timestamp in milliseconds (Unix timestamp)", example = "1641081600000")
@Parameter(description = "End timestamp in milliseconds (Unix timestamp)", example = "1641081600000")
@RequestParam(value = "end", required = false) Long end,
@Parameter(description = "Trace ID for distributed tracing", example = "1234567890abcdef")
@Parameter(description = "Trace ID for distributed tracing", example = "1234567890abcdef")
@RequestParam(value = "traceId", required = false) String traceId,
@Parameter(description = "Span ID for distributed tracing", example = "abcdef1234567890")
@Parameter(description = "Span ID for distributed tracing", example = "abcdef1234567890")
@RequestParam(value = "spanId", required = false) String spanId,
@Parameter(description = "Log severity number (1-24 according to OpenTelemetry standard)", example = "9")
@Parameter(description = "Log severity number (1-24 according to OpenTelemetry standard)", example = "9")
@RequestParam(value = "severityNumber", required = false) Integer severityNumber,
@Parameter(description = "Log severity text (TRACE, DEBUG, INFO, WARN, ERROR, FATAL)", example = "INFO")
@RequestParam(value = "severityText", required = false) String severityText) {
List<LogEntry> logs = getFilteredLogs(start, end, traceId, spanId, severityNumber, severityText);
@Parameter(description = "Log severity text (TRACE, DEBUG, INFO, WARN, ERROR, FATAL)", example = "INFO")
@RequestParam(value = "severityText", required = false) String severityText,
@Parameter(description = "Log content search keyword", example = "error")
@RequestParam(value = "search", required = false) String search) {
List<LogEntry> logs = getFilteredLogs(start, end, traceId, spanId, severityNumber, severityText, search);
Map<String, Object> overview = new HashMap<>();
overview.put("totalCount", logs.size());
// Count by severity levels according to OpenTelemetry standard
// TRACE: 1-4, DEBUG: 5-8, INFO: 9-12, WARN: 13-16, ERROR: 17-20, FATAL: 21-24
long fatalCount = logs.stream().filter(log -> log.getSeverityNumber() != null && log.getSeverityNumber() >= 21 && log.getSeverityNumber() <= 24).count();
@@ -113,114 +117,117 @@ public class LogQueryController {
long infoCount = logs.stream().filter(log -> log.getSeverityNumber() != null && log.getSeverityNumber() >= 9 && log.getSeverityNumber() <= 12).count();
long debugCount = logs.stream().filter(log -> log.getSeverityNumber() != null && log.getSeverityNumber() >= 5 && log.getSeverityNumber() <= 8).count();
long traceCount = logs.stream().filter(log -> log.getSeverityNumber() != null && log.getSeverityNumber() >= 1 && log.getSeverityNumber() <= 4).count();
overview.put("fatalCount", fatalCount);
overview.put("errorCount", errorCount);
overview.put("warnCount", warnCount);
overview.put("infoCount", infoCount);
overview.put("debugCount", debugCount);
overview.put("traceCount", traceCount);
return ResponseEntity.ok(Message.success(overview));
}
@GetMapping("/stats/trace-coverage")
@Operation(summary = "Trace coverage statistics",
description = "Statistics about trace information availability. Shows how many logs have trace IDs, span IDs, or both for distributed tracing analysis.")
@Operation(summary = "Trace coverage statistics",
description = "Statistics about trace information availability. Shows how many logs have trace IDs, span IDs, or both for distributed tracing analysis.")
public ResponseEntity<Message<Map<String, Object>>> traceCoverageStats(
@Parameter(description = "Start timestamp in milliseconds (Unix timestamp)", example = "1640995200000")
@Parameter(description = "Start timestamp in milliseconds (Unix timestamp)", example = "1640995200000")
@RequestParam(value = "start", required = false) Long start,
@Parameter(description = "End timestamp in milliseconds (Unix timestamp)", example = "1641081600000")
@Parameter(description = "End timestamp in milliseconds (Unix timestamp)", example = "1641081600000")
@RequestParam(value = "end", required = false) Long end,
@Parameter(description = "Trace ID for distributed tracing", example = "1234567890abcdef")
@Parameter(description = "Trace ID for distributed tracing", example = "1234567890abcdef")
@RequestParam(value = "traceId", required = false) String traceId,
@Parameter(description = "Span ID for distributed tracing", example = "abcdef1234567890")
@Parameter(description = "Span ID for distributed tracing", example = "abcdef1234567890")
@RequestParam(value = "spanId", required = false) String spanId,
@Parameter(description = "Log severity number (1-24 according to OpenTelemetry standard)", example = "9")
@Parameter(description = "Log severity number (1-24 according to OpenTelemetry standard)", example = "9")
@RequestParam(value = "severityNumber", required = false) Integer severityNumber,
@Parameter(description = "Log severity text (TRACE, DEBUG, INFO, WARN, ERROR, FATAL)", example = "INFO")
@RequestParam(value = "severityText", required = false) String severityText) {
List<LogEntry> logs = getFilteredLogs(start, end, traceId, spanId, severityNumber, severityText);
@Parameter(description = "Log severity text (TRACE, DEBUG, INFO, WARN, ERROR, FATAL)", example = "INFO")
@RequestParam(value = "severityText", required = false) String severityText,
@Parameter(description = "Log content search keyword", example = "error")
@RequestParam(value = "search", required = false) String search) {
List<LogEntry> logs = getFilteredLogs(start, end, traceId, spanId, severityNumber, severityText, search);
Map<String, Object> result = new HashMap<>();
// Trace coverage statistics
long withTraceId = logs.stream().filter(log -> log.getTraceId() != null && !log.getTraceId().isEmpty()).count();
long withSpanId = logs.stream().filter(log -> log.getSpanId() != null && !log.getSpanId().isEmpty()).count();
long withBothTraceAndSpan = logs.stream().filter(log ->
log.getTraceId() != null && !log.getTraceId().isEmpty()
&& log.getSpanId() != null && !log.getSpanId().isEmpty()).count();
long withBothTraceAndSpan = logs.stream().filter(log ->
log.getTraceId() != null && !log.getTraceId().isEmpty()
&& log.getSpanId() != null && !log.getSpanId().isEmpty()).count();
long withoutTrace = logs.size() - withTraceId;
Map<String, Long> traceCoverage = new HashMap<>();
traceCoverage.put("withTrace", withTraceId);
traceCoverage.put("withoutTrace", withoutTrace);
traceCoverage.put("withSpan", withSpanId);
traceCoverage.put("withBothTraceAndSpan", withBothTraceAndSpan);
result.put("traceCoverage", traceCoverage);
return ResponseEntity.ok(Message.success(result));
}
@GetMapping("/stats/trend")
@Operation(summary = "Log trend over time",
description = "Count logs by hour intervals with filters. Groups logs by hour and provides time-series data for trend analysis.")
@Operation(summary = "Log trend over time",
description = "Count logs by hour intervals with filters. Groups logs by hour and provides time-series data for trend analysis.")
public ResponseEntity<Message<Map<String, Object>>> trendStats(
@Parameter(description = "Start timestamp in milliseconds (Unix timestamp)", example = "1640995200000")
@Parameter(description = "Start timestamp in milliseconds (Unix timestamp)", example = "1640995200000")
@RequestParam(value = "start", required = false) Long start,
@Parameter(description = "End timestamp in milliseconds (Unix timestamp)", example = "1641081600000")
@Parameter(description = "End timestamp in milliseconds (Unix timestamp)", example = "1641081600000")
@RequestParam(value = "end", required = false) Long end,
@Parameter(description = "Trace ID for distributed tracing", example = "1234567890abcdef")
@Parameter(description = "Trace ID for distributed tracing", example = "1234567890abcdef")
@RequestParam(value = "traceId", required = false) String traceId,
@Parameter(description = "Span ID for distributed tracing", example = "abcdef1234567890")
@Parameter(description = "Span ID for distributed tracing", example = "abcdef1234567890")
@RequestParam(value = "spanId", required = false) String spanId,
@Parameter(description = "Log severity number (1-24 according to OpenTelemetry standard)", example = "9")
@Parameter(description = "Log severity number (1-24 according to OpenTelemetry standard)", example = "9")
@RequestParam(value = "severityNumber", required = false) Integer severityNumber,
@Parameter(description = "Log severity text (TRACE, DEBUG, INFO, WARN, ERROR, FATAL)", example = "INFO")
@RequestParam(value = "severityText", required = false) String severityText) {
List<LogEntry> logs = getFilteredLogs(start, end, traceId, spanId, severityNumber, severityText);
@Parameter(description = "Log severity text (TRACE, DEBUG, INFO, WARN, ERROR, FATAL)", example = "INFO")
@RequestParam(value = "severityText", required = false) String severityText,
@Parameter(description = "Log content search keyword", example = "error")
@RequestParam(value = "search", required = false) String search) {
List<LogEntry> logs = getFilteredLogs(start, end, traceId, spanId, severityNumber, severityText, search);
// Group by hour
Map<String, Long> hourlyStats = logs.stream()
.filter(log -> log.getTimeUnixNano() != null)
.collect(Collectors.groupingBy(
log -> {
long timestampMs = log.getTimeUnixNano() / 1_000_000L;
LocalDateTime dateTime = LocalDateTime.ofInstant(
Instant.ofEpochMilli(timestampMs),
ZoneId.systemDefault());
return dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:00"));
},
Collectors.counting()));
.filter(log -> log.getTimeUnixNano() != null)
.collect(Collectors.groupingBy(
log -> {
long timestampMs = log.getTimeUnixNano() / 1_000_000L;
LocalDateTime dateTime = LocalDateTime.ofInstant(
Instant.ofEpochMilli(timestampMs),
ZoneId.systemDefault());
return dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:00"));
},
Collectors.counting()));
Map<String, Object> result = new HashMap<>();
result.put("hourlyStats", hourlyStats);
return ResponseEntity.ok(Message.success(result));
}
private List<LogEntry> getFilteredLogs(Long start, Long end, String traceId, String spanId,
Integer severityNumber, String severityText) {
private List<LogEntry> getFilteredLogs(Long start, Long end, String traceId, String spanId,
Integer severityNumber, String severityText, String search) {
// Use the new multi-condition query method
return historyDataReader.queryLogsByMultipleConditions(start, end, traceId, spanId, severityNumber, severityText);
return historyDataReader.queryLogsByMultipleConditions(start, end, traceId, spanId, severityNumber, severityText, search);
}
private Page<LogEntry> getPagedLogs(Long start, Long end, String traceId, String spanId,
Integer severityNumber, String severityText, Integer pageIndex, Integer pageSize) {
private Page<LogEntry> getPagedLogs(Long start, Long end, String traceId, String spanId,
Integer severityNumber, String severityText, String search,
Integer pageIndex, Integer pageSize) {
// Calculate pagination parameters
int offset = pageIndex * pageSize;
// Get total count and paginated data
long totalElements = historyDataReader.countLogsByMultipleConditions(start, end, traceId, spanId, severityNumber, severityText);
long totalElements = historyDataReader.countLogsByMultipleConditions(start, end, traceId, spanId, severityNumber, severityText, search);
List<LogEntry> pagedLogs = historyDataReader.queryLogsByMultipleConditionsWithPagination(
start, end, traceId, spanId, severityNumber, severityText, offset, pageSize);
start, end, traceId, spanId, severityNumber, severityText, search, offset, pageSize);
// Create PageRequest (sorted by timestamp descending)
Sort sort = Sort.by(Sort.Direction.DESC, "timeUnixNano");
PageRequest pageRequest = PageRequest.of(pageIndex, pageSize, sort);
// Return Spring Data Page object
return new PageImpl<>(pagedLogs, pageRequest, totalElements);
}
}
}
@@ -0,0 +1,160 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hertzbeat.log.controller;
import com.fasterxml.jackson.core.io.JsonStringEncoder;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.util.JsonFormat;
import com.google.rpc.Status;
import io.opentelemetry.proto.collector.logs.v1.ExportLogsServiceResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.hertzbeat.log.service.impl.OtlpLogProtocolAdapter;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* OTLP Log Ingestion Controller
* Implements OTLP/HTTP specification for log ingestion.
* Supports both binary-encoded Protobuf (application/x-protobuf) and JSON-encoded Protobuf (application/json).
*
* @see <a href="https://opentelemetry.io/docs/specs/otlp/#otlphttp">OTLP/HTTP Specification</a>
*/
@Tag(name = "OTLP Log Controller")
@RestController
@RequestMapping(path = "/api/logs/otlp")
@Slf4j
public class OtlpLogController {
private static final String CONTENT_TYPE_PROTOBUF = "application/x-protobuf";
private static final ExportLogsServiceResponse EMPTY_RESPONSE = ExportLogsServiceResponse.newBuilder().build();
private final OtlpLogProtocolAdapter otlpLogProtocolAdapter;
public OtlpLogController(OtlpLogProtocolAdapter otlpLogProtocolAdapter) {
this.otlpLogProtocolAdapter = otlpLogProtocolAdapter;
}
/**
* OTLP/HTTP standard endpoint for logs with JSON-encoded Protobuf payload.
* Content-Type: application/json
*
* Response follows OTLP specification:
* - Success: HTTP 200 with ExportLogsServiceResponse (JSON encoded)
* - Failure: HTTP 400 with google.rpc.Status (JSON encoded)
*
* @param content JSON-encoded ExportLogsServiceRequest
* @return ExportLogsServiceResponse on success, Status on failure
*/
@Operation(summary = "Ingest OTLP logs (JSON format)")
@PostMapping(value = "/v1/logs", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<String> ingestJsonLogs(@RequestBody String content) {
log.debug("Receive OTLP JSON logs, content length: {}", content == null ? 0 : content.length());
try {
otlpLogProtocolAdapter.ingest(content);
return ResponseEntity.ok(toJsonResponse(EMPTY_RESPONSE));
} catch (IllegalArgumentException e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(toJsonErrorResponse(e.getMessage()));
} catch (Exception e) {
// Server-side errors - unexpected failure
log.error("Unexpected error ingesting OTLP JSON logs: {}", e.getMessage(), e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(toJsonErrorResponse(e.getMessage()));
}
}
/**
* OTLP/HTTP standard endpoint for logs with binary-encoded Protobuf payload.
* Content-Type: application/x-protobuf
*
* Response follows OTLP specification:
* - Success: HTTP 200 with ExportLogsServiceResponse (binary encoded)
* - Failure: HTTP 400 with google.rpc.Status (binary encoded)
*
* @param content binary-encoded ExportLogsServiceRequest
* @return ExportLogsServiceResponse on success, Status on failure
*/
@Operation(summary = "Ingest OTLP logs (binary Protobuf format)")
@PostMapping(value = "/v1/logs", consumes = CONTENT_TYPE_PROTOBUF, produces = CONTENT_TYPE_PROTOBUF)
public ResponseEntity<byte[]> ingestBinaryLogs(@RequestBody byte[] content) {
log.debug("Receive OTLP binary logs, content length: {}", content == null ? 0 : content.length);
try {
otlpLogProtocolAdapter.ingestBinary(content);
return ResponseEntity.ok(EMPTY_RESPONSE.toByteArray());
} catch (IllegalArgumentException e) {
// Client-side validation errors - malformed request
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(createBinaryErrorResponse(e.getMessage()));
} catch (Exception e) {
// Server-side errors - unexpected failure
log.error("Unexpected error ingesting OTLP binary logs: {}", e.getMessage(), e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(createBinaryErrorResponse(e.getMessage()));
}
}
private String toJsonResponse(ExportLogsServiceResponse response) {
try {
return JsonFormat.printer().print(response);
} catch (InvalidProtocolBufferException e) {
log.error("Failed to convert ExportLogsServiceResponse to JSON: {}", e.getMessage(), e);
return "{}";
}
}
private String toJsonErrorResponse(String message) {
Status status = Status.newBuilder()
.setMessage(message != null ? message : "Unknown error")
.build();
try {
return JsonFormat.printer().print(status);
} catch (InvalidProtocolBufferException e) {
return "{\"message\":\"" + escapeJson(message) + "\"}";
}
}
/**
* Escapes a string value for safe inclusion in JSON.
*
* @param message the string to escape
* @return the escaped string, or empty string if message is null
*/
private String escapeJson(String message) {
if (message == null) {
return "";
}
char[] escaped = JsonStringEncoder.getInstance().quoteAsString(message);
return new String(escaped);
}
private byte[] createBinaryErrorResponse(String message) {
return Status.newBuilder()
.setMessage(message != null ? message : "Unknown error")
.build()
.toByteArray();
}
}
@@ -49,7 +49,13 @@ public class LogSseFilterCriteria {
*/
@Schema(description = "The severity text (also known as log level).", example = "INFO", accessMode = READ_WRITE)
private String severityText;
/**
* Log content text filtering (case-insensitive contains match).
*/
@Schema(description = "Log content text filtering", example = "error occurred", accessMode = READ_WRITE)
private String logContent;
/**
* A unique identifier for a trace.
* All spans from the same trace share the same trace_id.
@@ -77,18 +83,30 @@ public class LogSseFilterCriteria {
if (StringUtils.hasText(severityText) && !severityText.equalsIgnoreCase(log.getSeverityText())) {
return false;
}
// Check severity number match (if both are present)
if (severityNumber != null && log.getSeverityNumber() != null
&& !severityNumber.equals(log.getSeverityNumber())) {
return false;
}
// Check log content match
if (StringUtils.hasText(logContent)) {
Object body = log.getBody();
if (body == null) {
return false;
}
String bodyStr = body.toString();
if (!StringUtils.hasText(bodyStr) || !bodyStr.toLowerCase().contains(logContent.toLowerCase())) {
return false;
}
}
// Check trace ID match
if (StringUtils.hasText(traceId) && !traceId.equalsIgnoreCase(log.getTraceId())) {
return false;
}
// Check span ID match
if (StringUtils.hasText(spanId) && !spanId.equalsIgnoreCase(log.getSpanId())) {
return false;
@@ -28,7 +28,7 @@ package org.apache.hertzbeat.log.service;
public interface LogProtocolAdapter {
/**
* Ingest raw log payload pushed from external system.
* Ingest log payload pushed from external system.
*
* @param content raw request body string
*/
@@ -39,7 +39,10 @@ import java.util.List;
import java.util.Map;
/**
* Adapter for OpenTelemetry OTLP/HTTP JSON log ingestion.
* Adapter for OpenTelemetry OTLP/HTTP log ingestion.
* Supports both JSON-encoded and binary-encoded Protobuf formats.
*
* @see <a href="https://opentelemetry.io/docs/specs/otlp/#otlphttp">OTLP/HTTP Specification</a>
*/
@Slf4j
@Service
@@ -58,26 +61,47 @@ public class OtlpLogProtocolAdapter implements LogProtocolAdapter {
@Override
public void ingest(String content) {
if (content == null || content.isEmpty()) {
log.warn("Received empty OTLP log payload - skip processing.");
log.warn("Received empty OTLP JSON log payload - skip processing.");
return;
}
ExportLogsServiceRequest.Builder builder = ExportLogsServiceRequest.newBuilder();
try {
JsonFormat.parser().ignoringUnknownFields().merge(content, builder);
ExportLogsServiceRequest request = builder.build();
// Extract LogEntry instances from the request
List<LogEntry> logEntries = extractLogEntries(request);
log.debug("Successfully extracted {} log entries from OTLP payload {}", logEntries.size(), content);
commonDataQueue.sendLogEntryToStorageBatch(logEntries);
commonDataQueue.sendLogEntryToAlertBatch(logEntries);
logEntries.forEach(logSseManager::broadcast);
processLogsRequest(request, "JSON");
} catch (InvalidProtocolBufferException e) {
log.error("Failed to parse OTLP log payload: {}", e.getMessage());
throw new IllegalArgumentException("Invalid OTLP log content", e);
log.error("Failed to parse OTLP JSON log payload: {}", e.getMessage());
throw new IllegalArgumentException("Invalid OTLP JSON log content", e);
}
}
/**
* Ingest binary-encoded Protobuf log payload (OTLP-specific).
*
* @param content binary-encoded ExportLogsServiceRequest
*/
public void ingestBinary(byte[] content) {
if (content == null || content.length == 0) {
log.warn("Received empty OTLP binary log payload - skip processing.");
return;
}
try {
ExportLogsServiceRequest request = ExportLogsServiceRequest.parseFrom(content);
processLogsRequest(request, "binary");
} catch (InvalidProtocolBufferException e) {
log.error("Failed to parse OTLP binary log payload: {}", e.getMessage());
throw new IllegalArgumentException("Invalid OTLP binary log content", e);
}
}
private void processLogsRequest(ExportLogsServiceRequest request, String format) {
List<LogEntry> logEntries = extractLogEntries(request);
log.debug("Successfully extracted {} log entries from OTLP {} payload", logEntries.size(), format);
commonDataQueue.sendLogEntryToStorageBatch(logEntries);
commonDataQueue.sendLogEntryToAlertBatch(logEntries);
logEntries.forEach(logSseManager::broadcast);
}
/**
* Extract LogEntry instances from ExportLogsServiceRequest.
*
@@ -18,24 +18,22 @@
package org.apache.hertzbeat.log.controller;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import org.apache.hertzbeat.common.constants.CommonConstants;
import org.apache.hertzbeat.common.entity.log.LogEntry;
import org.apache.hertzbeat.common.util.JsonUtil;
import org.apache.hertzbeat.log.service.LogProtocolAdapter;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
@@ -51,34 +49,29 @@ class LogIngestionControllerTest {
private MockMvc mockMvc;
@Mock
private LogProtocolAdapter otlpAdapter;
private LogProtocolAdapter vectorAdapter;
private LogIngestionController logIngestionController;
@BeforeEach
void setUp() {
List<LogProtocolAdapter> adapters = Arrays.asList(otlpAdapter);
List<LogProtocolAdapter> adapters = Arrays.asList(vectorAdapter);
this.logIngestionController = new LogIngestionController(adapters);
this.mockMvc = MockMvcBuilders.standaloneSetup(logIngestionController).build();
}
@Test
void testIngestExternLogWithOtlpProtocol() throws Exception {
LogEntry logEntry = LogEntry.builder()
.timeUnixNano(1734005477630L)
.severityNumber(1)
.severityText("INFO")
.body("Test log message")
.attributes(new HashMap<>())
.build();
void testIngestLogWithKnownProtocol() throws Exception {
String logContent = "{\"message\":\"Test log message\"}";
when(otlpAdapter.supportProtocol()).thenReturn("otlp");
when(vectorAdapter.supportProtocol()).thenReturn("vector");
doNothing().when(vectorAdapter).ingest(anyString());
mockMvc.perform(
MockMvcRequestBuilders
.post("/api/logs/ingest/otlp")
.post("/api/logs/ingest/vector")
.contentType(MediaType.APPLICATION_JSON)
.content(JsonUtil.toJson(logEntry))
.content(logContent)
)
.andDo(print())
.andExpect(status().isOk())
@@ -88,16 +81,16 @@ class LogIngestionControllerTest {
}
@Test
void testIngestExternLogWithUnsupportedProtocol() throws Exception {
String unsupportedLogContent = "{\"message\":\"Unsupported protocol log\"}";
void testIngestLogWithUnsupportedProtocol() throws Exception {
String logContent = "{\"message\":\"Unsupported protocol log\"}";
when(otlpAdapter.supportProtocol()).thenReturn("otlp");
when(vectorAdapter.supportProtocol()).thenReturn("vector");
mockMvc.perform(
MockMvcRequestBuilders
.post("/api/logs/ingest/unsupported")
.contentType(MediaType.APPLICATION_JSON)
.content(unsupportedLogContent)
.content(logContent)
)
.andExpect(status().isBadRequest())
.andExpect(jsonPath("$.code").value((int) CommonConstants.FAIL_CODE))
@@ -105,38 +98,15 @@ class LogIngestionControllerTest {
}
@Test
void testIngestDefaultExternLog() throws Exception {
LogEntry logEntry = LogEntry.builder()
.timeUnixNano(1734005477630L)
.severityNumber(2)
.severityText("WARN")
.body("Default protocol log message")
.attributes(new HashMap<>())
.build();
void testIngestLogWithAdapterException() throws Exception {
String logContent = "{\"message\":\"Log message that will cause exception\"}";
when(otlpAdapter.supportProtocol()).thenReturn("otlp");
when(vectorAdapter.supportProtocol()).thenReturn("vector");
doThrow(new IllegalArgumentException("Invalid log format")).when(vectorAdapter).ingest(anyString());
mockMvc.perform(
MockMvcRequestBuilders
.post("/api/logs/ingest")
.contentType(MediaType.APPLICATION_JSON)
.content(JsonUtil.toJson(logEntry))
)
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE))
.andExpect(jsonPath("$.msg").value("Add extern log success"));
}
@Test
void testIngestDefaultExternLogWithAdapterException() throws Exception {
String logContent = "{\"message\":\"Default log message that will cause exception\"}";
when(otlpAdapter.supportProtocol()).thenReturn("otlp");
Mockito.doThrow(new IllegalArgumentException("Invalid log format")).when(otlpAdapter).ingest(anyString());
mockMvc.perform(
MockMvcRequestBuilders
.post("/api/logs/ingest")
.post("/api/logs/ingest/vector")
.contentType(MediaType.APPLICATION_JSON)
.content(logContent)
)
@@ -17,11 +17,10 @@
package org.apache.hertzbeat.log.controller;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@@ -87,10 +86,10 @@ class LogQueryControllerTest {
List<LogEntry> mockLogs = Arrays.asList(logEntry1, logEntry2);
when(historyDataReader.countLogsByMultipleConditions(anyLong(), anyLong(), anyString(),
anyString(), anyInt(), anyString())).thenReturn(2L);
when(historyDataReader.queryLogsByMultipleConditionsWithPagination(anyLong(), anyLong(),
anyString(), anyString(), anyInt(), anyString(), anyInt(), anyInt()))
when(historyDataReader.countLogsByMultipleConditions(anyLong(), anyLong(), any(),
any(), any(), any(), any())).thenReturn(2L);
when(historyDataReader.queryLogsByMultipleConditionsWithPagination(anyLong(), anyLong(),
any(), any(), any(), any(), any(), anyInt(), anyInt()))
.thenReturn(mockLogs);
mockMvc.perform(
@@ -127,10 +126,10 @@ class LogQueryControllerTest {
.build()
);
when(historyDataReader.countLogsByMultipleConditions(isNull(), isNull(), isNull(),
isNull(), isNull(), isNull())).thenReturn(1L);
when(historyDataReader.queryLogsByMultipleConditionsWithPagination(isNull(), isNull(),
isNull(), isNull(), isNull(), isNull(), eq(0), eq(20)))
when(historyDataReader.countLogsByMultipleConditions(any(), any(), any(),
any(), any(), any(), any())).thenReturn(1L);
when(historyDataReader.queryLogsByMultipleConditionsWithPagination(any(), any(),
any(), any(), any(), any(), any(), eq(0), eq(20)))
.thenReturn(mockLogs);
mockMvc.perform(
@@ -163,8 +162,8 @@ class LogQueryControllerTest {
LogEntry.builder().severityNumber(21).build()
);
when(historyDataReader.queryLogsByMultipleConditions(isNull(), isNull(), isNull(),
isNull(), isNull(), isNull())).thenReturn(mockLogs);
when(historyDataReader.queryLogsByMultipleConditions(any(), any(), any(),
any(), any(), any(), any())).thenReturn(mockLogs);
mockMvc.perform(
MockMvcRequestBuilders
@@ -188,8 +187,8 @@ class LogQueryControllerTest {
LogEntry.builder().severityNumber(17).build()
);
when(historyDataReader.queryLogsByMultipleConditions(eq(1734005477000L), eq(1734005478000L),
isNull(), isNull(), isNull(), isNull())).thenReturn(mockLogs);
when(historyDataReader.queryLogsByMultipleConditions(eq(1734005477000L), eq(1734005478000L),
any(), any(), any(), any(), any())).thenReturn(mockLogs);
mockMvc.perform(
MockMvcRequestBuilders
@@ -217,8 +216,8 @@ class LogQueryControllerTest {
LogEntry.builder().build() // null values
);
when(historyDataReader.queryLogsByMultipleConditions(isNull(), isNull(), isNull(),
isNull(), isNull(), isNull())).thenReturn(mockLogs);
when(historyDataReader.queryLogsByMultipleConditions(any(), any(), any(),
any(), any(), any(), any())).thenReturn(mockLogs);
mockMvc.perform(
MockMvcRequestBuilders
@@ -244,8 +243,8 @@ class LogQueryControllerTest {
LogEntry.builder().timeUnixNano(1734009077630000000L).build()
);
when(historyDataReader.queryLogsByMultipleConditions(isNull(), isNull(), isNull(),
isNull(), isNull(), isNull())).thenReturn(mockLogs);
when(historyDataReader.queryLogsByMultipleConditions(any(), any(), any(),
any(), any(), any(), any())).thenReturn(mockLogs);
mockMvc.perform(
MockMvcRequestBuilders
@@ -263,8 +262,8 @@ class LogQueryControllerTest {
LogEntry.builder().timeUnixNano(null).build() // This should be filtered out
);
when(historyDataReader.queryLogsByMultipleConditions(isNull(), isNull(), isNull(),
isNull(), isNull(), isNull())).thenReturn(mockLogs);
when(historyDataReader.queryLogsByMultipleConditions(any(), any(), any(),
any(), any(), any(), any())).thenReturn(mockLogs);
mockMvc.perform(
MockMvcRequestBuilders
@@ -0,0 +1,131 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hertzbeat.log.controller;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doThrow;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import org.apache.hertzbeat.log.service.impl.OtlpLogProtocolAdapter;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
/**
* Unit test for {@link OtlpLogController}
*/
@ExtendWith(MockitoExtension.class)
class OtlpLogControllerTest {
private static final String CONTENT_TYPE_PROTOBUF = "application/x-protobuf";
private MockMvc mockMvc;
@Mock
private OtlpLogProtocolAdapter otlpLogProtocolAdapter;
private OtlpLogController otlpLogController;
@BeforeEach
void setUp() {
this.otlpLogController = new OtlpLogController(otlpLogProtocolAdapter);
this.mockMvc = MockMvcBuilders.standaloneSetup(otlpLogController).build();
}
@Test
void testIngestJsonLogsSuccess() throws Exception {
String jsonContent = "{\"resourceLogs\":[]}";
doNothing().when(otlpLogProtocolAdapter).ingest(anyString());
mockMvc.perform(
MockMvcRequestBuilders
.post("/api/logs/otlp/v1/logs")
.contentType(MediaType.APPLICATION_JSON)
.content(jsonContent)
)
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andReturn();
}
@Test
void testIngestJsonLogsFailure() throws Exception {
String jsonContent = "{\"invalid\":\"content\"}";
doThrow(new IllegalArgumentException("Invalid OTLP JSON log content"))
.when(otlpLogProtocolAdapter).ingest(anyString());
mockMvc.perform(
MockMvcRequestBuilders
.post("/api/logs/otlp/v1/logs")
.contentType(MediaType.APPLICATION_JSON)
.content(jsonContent)
)
.andExpect(status().isBadRequest())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andReturn();
}
@Test
void testIngestBinaryLogsSuccess() throws Exception {
byte[] binaryContent = new byte[]{0x0a, 0x0b, 0x0c};
doNothing().when(otlpLogProtocolAdapter).ingestBinary(any(byte[].class));
mockMvc.perform(
MockMvcRequestBuilders
.post("/api/logs/otlp/v1/logs")
.contentType(CONTENT_TYPE_PROTOBUF)
.content(binaryContent)
)
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().contentType(CONTENT_TYPE_PROTOBUF))
.andReturn();
}
@Test
void testIngestBinaryLogsFailure() throws Exception {
byte[] binaryContent = new byte[]{0x0a, 0x0b, 0x0c};
doThrow(new IllegalArgumentException("Invalid OTLP binary log content"))
.when(otlpLogProtocolAdapter).ingestBinary(any(byte[].class));
mockMvc.perform(
MockMvcRequestBuilders
.post("/api/logs/otlp/v1/logs")
.contentType(CONTENT_TYPE_PROTOBUF)
.content(binaryContent)
)
.andExpect(status().isBadRequest())
.andExpect(content().contentType(CONTENT_TYPE_PROTOBUF))
.andReturn();
}
}
@@ -105,16 +105,44 @@ class LogSseFilterCriteriaTest {
// Test Span ID filter - match
filterCriteria.setSpanId("1234567890abcdef");
assertTrue(filterCriteria.matches(testLogEntry));
// Test Span ID filter - no match
filterCriteria.setSpanId("abcdef1234567890");
assertFalse(filterCriteria.matches(testLogEntry));
// Test Span ID filter - case insensitive
filterCriteria.setSpanId("1234567890ABCDEF");
assertTrue(filterCriteria.matches(testLogEntry));
}
@Test
void testMatchesWithLogContentFilter() {
// Test log content filter - match
filterCriteria.setLogContent("Test log");
assertTrue(filterCriteria.matches(testLogEntry));
// Test log content filter - no match
filterCriteria.setLogContent("Error message");
assertFalse(filterCriteria.matches(testLogEntry));
// Test log content filter - case insensitive
filterCriteria.setLogContent("test log");
assertTrue(filterCriteria.matches(testLogEntry));
// Test log content filter - partial match
filterCriteria.setLogContent("message");
assertTrue(filterCriteria.matches(testLogEntry));
// Test log content filter with null body
LogEntry nullBodyLog = LogEntry.builder()
.severityNumber(9)
.severityText("INFO")
.body(null)
.build();
filterCriteria.setLogContent("test");
assertFalse(filterCriteria.matches(nullBodyLog));
}
@Test
void testMatchesWithMultipleFilters() {
// Test multiple filter combinations - all match
@@ -163,14 +191,15 @@ class LogSseFilterCriteriaTest {
void testConstructorWithAllParameters() {
// Test constructor with all parameters
LogSseFilterCriteria criteria = new LogSseFilterCriteria(
9, "INFO", "1234567890abcdef1234567890abcdef", "1234567890abcdef"
9, "INFO", null, "1234567890abcdef1234567890abcdef", "1234567890abcdef"
);
assertEquals(9, criteria.getSeverityNumber());
assertEquals("INFO", criteria.getSeverityText());
assertEquals(null, criteria.getLogContent());
assertEquals("1234567890abcdef1234567890abcdef", criteria.getTraceId());
assertEquals("1234567890abcdef", criteria.getSpanId());
// Test matching
assertTrue(criteria.matches(testLogEntry));
}
@@ -179,17 +208,19 @@ class LogSseFilterCriteriaTest {
void testNoArgsConstructorAndSetters() {
// Test no-args constructor and setter methods
LogSseFilterCriteria criteria = new LogSseFilterCriteria();
criteria.setSeverityNumber(9);
criteria.setSeverityText("INFO");
criteria.setLogContent("Test log");
criteria.setTraceId("1234567890abcdef1234567890abcdef");
criteria.setSpanId("1234567890abcdef");
assertEquals(9, criteria.getSeverityNumber());
assertEquals("INFO", criteria.getSeverityText());
assertEquals("Test log", criteria.getLogContent());
assertEquals("1234567890abcdef1234567890abcdef", criteria.getTraceId());
assertEquals("1234567890abcdef", criteria.getSpanId());
// Test matching
assertTrue(criteria.matches(testLogEntry));
}
@@ -80,6 +80,47 @@ class OtlpLogProtocolAdapterTest {
verifyNoInteractions(commonDataQueue, logSseManager);
}
@Test
void testIngestBinaryWithNullContent() {
adapter.ingestBinary(null);
verifyNoInteractions(commonDataQueue, logSseManager);
}
@Test
void testIngestBinaryWithEmptyContent() {
adapter.ingestBinary(new byte[0]);
verifyNoInteractions(commonDataQueue, logSseManager);
}
@Test
void testIngestBinaryWithValidOtlpLogData() throws Exception {
byte[] binaryPayload = createValidOtlpLogBinaryPayload();
adapter.ingestBinary(binaryPayload);
ArgumentCaptor<List<LogEntry>> listCaptor = ArgumentCaptor.forClass(List.class);
verify(commonDataQueue, times(1)).sendLogEntryToStorageBatch(listCaptor.capture());
verify(commonDataQueue, times(1)).sendLogEntryToAlertBatch(anyList());
verify(logSseManager, times(1)).broadcast(any(LogEntry.class));
List<LogEntry> capturedList = listCaptor.getValue();
assertNotNull(capturedList);
assertEquals(1, capturedList.size());
LogEntry capturedEntry = capturedList.get(0);
assertEquals("binary-test-service", capturedEntry.getResource().get("service_name"));
assertEquals("binary log message", capturedEntry.getBody());
assertEquals("INFO", capturedEntry.getSeverityText());
}
@Test
void testIngestBinaryWithInvalidContent() {
byte[] invalidBinary = "not a valid protobuf".getBytes();
assertThrows(IllegalArgumentException.class, () -> adapter.ingestBinary(invalidBinary));
verifyNoInteractions(commonDataQueue, logSseManager);
}
@Test
void testIngestWithValidOtlpLogData() throws Exception {
String otlpPayload = createValidOtlpLogPayload();
@@ -315,4 +356,32 @@ class OtlpLogProtocolAdapterTest {
ExportLogsServiceRequest request = ExportLogsServiceRequest.newBuilder().build();
return JsonFormat.printer().print(request);
}
private byte[] createValidOtlpLogBinaryPayload() {
ExportLogsServiceRequest request = ExportLogsServiceRequest.newBuilder()
.addResourceLogs(ResourceLogs.newBuilder()
.setResource(Resource.newBuilder()
.addAttributes(KeyValue.newBuilder()
.setKey("service.name")
.setValue(AnyValue.newBuilder().setStringValue("binary-test-service").build())
.build())
.build())
.addScopeLogs(ScopeLogs.newBuilder()
.setScope(InstrumentationScope.newBuilder()
.setName("binary-test-scope")
.setVersion("1.0.0")
.build())
.addLogRecords(LogRecord.newBuilder()
.setTimeUnixNano(System.currentTimeMillis() * 1_000_000)
.setObservedTimeUnixNano(System.currentTimeMillis() * 1_000_000)
.setSeverityNumberValue(9)
.setSeverityText("INFO")
.setBody(AnyValue.newBuilder().setStringValue("binary log message").build())
.build())
.build())
.build())
.build();
return request.toByteArray();
}
}
@@ -45,8 +45,11 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener;
* PluginParam
*/
@Entity
@Table(name = "hzb_plugin_param", indexes = { @Index(columnList = "pluginMetadataId") },
uniqueConstraints = @UniqueConstraint(columnNames = {"pluginMetadataId", "field"}))
@Table(
name = "hzb_plugin_param",
indexes = {@Index(name = "idx_hzb_plugin_param_plugin_metadata_id", columnList = "plugin_metadata_id")},
uniqueConstraints = @UniqueConstraint(name = "uk_hzb_plugin_param_metadata_field", columnNames = {"plugin_metadata_id", "field"})
)
@Data
@Builder
@AllArgsConstructor
@@ -65,8 +68,9 @@ public class PluginParam {
/**
* Monitor ID
*/
@Schema(title = "Plugin task ID", example = "875846754543", accessMode = READ_WRITE)
@NotNull
@Column(name = "plugin_metadata_id")
@Schema(title = "Plugin task ID", example = "875846754543", accessMode = READ_WRITE)
private Long pluginMetadataId;
/**
@@ -75,6 +79,7 @@ public class PluginParam {
@Schema(title = "Parameter identifier field", example = "port", accessMode = READ_WRITE)
@Size(max = 100)
@NotNull
@Column(name = "field")
private String field;
/**
@@ -18,9 +18,8 @@
package org.apache.hertzbeat.manager.service.impl;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
@@ -131,45 +130,70 @@ public class StatusPageServiceImpl implements StatusPageService {
componentStatus.setInfo(component);
List<StatusPageHistory> histories = new LinkedList<>();
// query today status
LocalDateTime nowTime = LocalDateTime.now();
LocalDateTime todayStartTime = nowTime.withHour(0).withMinute(0).withSecond(0).withNano(0);
ZoneOffset zoneOffset = ZoneId.systemDefault().getRules().getOffset(Instant.now());
long nowTimestamp = nowTime.toInstant(zoneOffset).toEpochMilli();
long todayStartTimestamp = todayStartTime.toInstant(zoneOffset).toEpochMilli();
ZoneId zoneId = ZoneId.systemDefault();
Instant now = Instant.now();
long nowTimestamp = now.toEpochMilli();
long todayStartTimestamp = now
.atZone(zoneId)
.toLocalDate()
.atStartOfDay(zoneId)
.toInstant()
.toEpochMilli();
List<StatusPageHistory> todayStatusPageHistoryList = statusPageHistoryDao
.findStatusPageHistoriesByComponentIdAndTimestampBetween(component.getId(), todayStartTimestamp, nowTimestamp);
StatusPageHistory todayStatus = combineOneDayStatusPageHistory(todayStatusPageHistoryList, component, nowTimestamp);
histories.add(todayStatus);
// query 30d component status history
LocalDateTime preTime = todayStartTime.minusDays(HISTORY_SPAN_DAYS);
long preTimestamp = preTime.toInstant(zoneOffset).toEpochMilli();
long preTimestamp = now
.atZone(zoneId)
.toLocalDate()
.minusDays(HISTORY_SPAN_DAYS)
.atStartOfDay(zoneId)
.toInstant()
.toEpochMilli();
List<StatusPageHistory> history = statusPageHistoryDao
.findStatusPageHistoriesByComponentIdAndTimestampBetween(component.getId(), preTimestamp, todayStartTimestamp);
LinkedList<StatusPageHistory> historyList = new LinkedList<>(history);
historyList.sort((o1, o2) -> (int) (o1.getTimestamp() - o2.getTimestamp()));
LocalDateTime endTime = todayStartTime.minusSeconds(1);
LocalDateTime startTime = endTime.withHour(0).withMinute(0).withSecond(0).withNano(0);
for (int index = 0; index < HISTORY_SPAN_DAYS; index++) {
long startTimestamp = startTime.toInstant(zoneOffset).toEpochMilli();
long endTimestamp = endTime.toInstant(zoneOffset).toEpochMilli();
List<StatusPageHistory> thisDayHistory = historyList.stream().filter(item ->
item.getTimestamp() >= startTimestamp && item.getTimestamp() <= endTimestamp)
.collect(Collectors.toList());
historyList.sort((o1, o2) -> Long.compare(o1.getTimestamp(), o2.getTimestamp()));
ZonedDateTime end = Instant.ofEpochMilli(todayStartTimestamp)
.atZone(zoneId)
.minusSeconds(1); // yesterday 23:59:59 local time
for (int i = 0; i < HISTORY_SPAN_DAYS; i++) {
long endTimestamp = end.toInstant().toEpochMilli();
long startTimestamp = end.toLocalDate()
.atStartOfDay(zoneId)
.toInstant()
.toEpochMilli();
List<StatusPageHistory> thisDayHistory = historyList.stream()
.filter(h -> h.getTimestamp() >= startTimestamp && h.getTimestamp() <= endTimestamp)
.collect(Collectors.toList());
if (thisDayHistory.isEmpty()) {
StatusPageHistory statusPageHistory = StatusPageHistory.builder().timestamp(endTimestamp)
.componentId(component.getId()).state(CommonConstants.STATUS_PAGE_COMPONENT_STATE_UNKNOWN).build();
histories.add(statusPageHistory);
histories.add(StatusPageHistory.builder()
.timestamp(endTimestamp)
.componentId(component.getId())
.state(CommonConstants.STATUS_PAGE_COMPONENT_STATE_UNKNOWN)
.build());
} else if (thisDayHistory.size() == 1) {
histories.add(thisDayHistory.get(0));
} else {
StatusPageHistory statusPageHistory = combineOneDayStatusPageHistory(thisDayHistory, component, endTimestamp);
histories.add(statusPageHistory);
StatusPageHistory merged =
combineOneDayStatusPageHistory(thisDayHistory, component, endTimestamp);
histories.add(merged);
statusPageHistoryDao.deleteAll(thisDayHistory);
statusPageHistoryDao.save(statusPageHistory);
statusPageHistoryDao.save(merged);
}
startTime = startTime.minusDays(1);
endTime = endTime.minusDays(1);
end = end.minusDays(1);
}
componentStatus.setHistory(histories);
componentStatusList.add(componentStatus);
}
@@ -215,50 +239,86 @@ public class StatusPageServiceImpl implements StatusPageService {
@Override
public ComponentStatus queryComponentStatus(long id) {
StatusPageComponent component = statusPageComponentDao.findById(id).orElseThrow(() -> new IllegalArgumentException("component not found"));
StatusPageComponent component = statusPageComponentDao.findById(id)
.orElseThrow(() -> new IllegalArgumentException("component not found"));
ComponentStatus componentStatus = new ComponentStatus();
componentStatus.setInfo(component);
List<StatusPageHistory> histories = new LinkedList<>();
// query today status
LocalDateTime nowTime = LocalDateTime.now();
LocalDateTime todayStartTime = nowTime.withHour(0).withMinute(0).withSecond(0).withNano(0);
ZoneOffset zoneOffset = ZoneId.systemDefault().getRules().getOffset(Instant.now());
long nowTimestamp = nowTime.toInstant(zoneOffset).toEpochMilli();
long todayStartTimestamp = todayStartTime.toInstant(zoneOffset).toEpochMilli();
List<StatusPageHistory> todayStatusPageHistoryList = statusPageHistoryDao
.findStatusPageHistoriesByComponentIdAndTimestampBetween(component.getId(), todayStartTimestamp, nowTimestamp);
StatusPageHistory todayStatus = combineOneDayStatusPageHistory(todayStatusPageHistoryList, component, nowTimestamp);
ZoneId zoneId = ZoneId.systemDefault();
Instant now = Instant.now();
long nowTimestamp = now.toEpochMilli();
long todayStartTimestamp = now
.atZone(zoneId)
.toLocalDate()
.atStartOfDay(zoneId)
.toInstant()
.toEpochMilli();
// Today
List<StatusPageHistory> todayStatusPageHistoryList =
statusPageHistoryDao.findStatusPageHistoriesByComponentIdAndTimestampBetween(
component.getId(), todayStartTimestamp, nowTimestamp);
StatusPageHistory todayStatus =
combineOneDayStatusPageHistory(todayStatusPageHistoryList, component, nowTimestamp);
histories.add(todayStatus);
// query 30d component status history
LocalDateTime preTime = todayStartTime.minusDays(HISTORY_SPAN_DAYS);
long preTimestamp = preTime.toInstant(zoneOffset).toEpochMilli();
List<StatusPageHistory> history = statusPageHistoryDao
.findStatusPageHistoriesByComponentIdAndTimestampBetween(component.getId(), preTimestamp, todayStartTimestamp);
// Previous HISTORY_SPAN_DAYS days (excluding today)
long preTimestamp = now
.atZone(zoneId)
.toLocalDate()
.minusDays(HISTORY_SPAN_DAYS)
.atStartOfDay(zoneId)
.toInstant()
.toEpochMilli();
List<StatusPageHistory> history =
statusPageHistoryDao.findStatusPageHistoriesByComponentIdAndTimestampBetween(
component.getId(), preTimestamp, todayStartTimestamp);
LinkedList<StatusPageHistory> historyList = new LinkedList<>(history);
historyList.sort((o1, o2) -> (int) (o1.getTimestamp() - o2.getTimestamp()));
LocalDateTime endTime = todayStartTime.minusSeconds(1);
LocalDateTime startTime = endTime.withHour(0).withMinute(0).withSecond(0).withNano(0);
for (int index = 0; index < HISTORY_SPAN_DAYS; index++) {
long startTimestamp = startTime.toInstant(zoneOffset).toEpochMilli();
long endTimestamp = endTime.toInstant(zoneOffset).toEpochMilli();
List<StatusPageHistory> thisDayHistory = historyList.stream().filter(item ->
item.getTimestamp() >= startTimestamp && item.getTimestamp() <= endTimestamp)
.collect(Collectors.toList());
historyList.sort((o1, o2) -> Long.compare(o1.getTimestamp(), o2.getTimestamp()));
ZonedDateTime end = Instant.ofEpochMilli(todayStartTimestamp)
.atZone(zoneId)
.minusSeconds(1); // yesterday 23:59:59 local time
for (int i = 0; i < HISTORY_SPAN_DAYS; i++) {
long endTimestamp = end.toInstant().toEpochMilli();
long startTimestamp = end.toLocalDate()
.atStartOfDay(zoneId)
.toInstant()
.toEpochMilli();
List<StatusPageHistory> thisDayHistory = historyList.stream()
.filter(h -> h.getTimestamp() >= startTimestamp && h.getTimestamp() <= endTimestamp)
.collect(Collectors.toList());
if (thisDayHistory.isEmpty()) {
StatusPageHistory statusPageHistory = StatusPageHistory.builder().timestamp(endTimestamp)
.componentId(component.getId()).state(CommonConstants.STATUS_PAGE_COMPONENT_STATE_UNKNOWN).build();
histories.add(statusPageHistory);
histories.add(StatusPageHistory.builder()
.timestamp(endTimestamp)
.componentId(component.getId())
.state(CommonConstants.STATUS_PAGE_COMPONENT_STATE_UNKNOWN)
.build());
} else if (thisDayHistory.size() == 1) {
histories.add(thisDayHistory.get(0));
} else {
StatusPageHistory statusPageHistory = combineOneDayStatusPageHistory(thisDayHistory, component, endTimestamp);
histories.add(statusPageHistory);
StatusPageHistory merged =
combineOneDayStatusPageHistory(thisDayHistory, component, endTimestamp);
histories.add(merged);
statusPageHistoryDao.deleteAll(thisDayHistory);
statusPageHistoryDao.save(statusPageHistory);
statusPageHistoryDao.save(merged);
}
startTime = startTime.minusDays(1);
endTime = endTime.minusDays(1);
end = end.minusDays(1);
}
componentStatus.setHistory(histories);
return componentStatus;
}
@@ -1178,3 +1178,69 @@ metrics:
privateKey: ^_^sshPrivateKey^_^
privateKeyPassphrase: ^_^sshPrivateKeyPassphrase^_^
shareConnection: ^_^sshShareConnection^_^
- name: account_expiry
priority: 100
i18n:
zh-CN: 数据库账号有效期
en-US: Account Expiry
ja-JP: アカウント有効期限
fields:
- field: user
type: 1
label: true
i18n:
zh-CN: 用户
en-US: User
ja-JP: ユーザー
- field: host
type: 1
label: true
i18n:
zh-CN: 主机
en-US: Host
ja-JP: ホスト
- field: days_left
type: 0
i18n:
zh-CN: 剩余天数
en-US: Days Left
ja-JP: 残り日数
- field: password_expired
type: 1
i18n:
zh-CN: 是否已过期
en-US: Password Expired
ja-JP: 期限切れ
protocol: jdbc
jdbc:
host: ^_^host^_^
port: ^_^port^_^
platform: mysql
username: ^_^username^_^
password: ^_^password^_^
database: mysql
timeout: ^_^timeout^_^
queryType: multiRow
sql: |
SELECT
user,
host,
IF(password_lifetime IS NULL,
NULL,
password_lifetime - DATEDIFF(NOW(), password_last_changed)
) AS days_left,
password_expired
FROM mysql.user;
url: ^_^url^_^
sshTunnel:
enable: ^_^enableSshTunnel^_^
host: ^_^sshHost^_^
port: ^_^sshPort^_^
timeout: ^_^sshTimeout^_^
username: ^_^sshUsername^_^
password: ^_^sshPassword^_^
privateKey: ^_^sshPrivateKey^_^
privateKeyPassphrase: ^_^sshPrivateKeyPassphrase^_^
shareConnection: ^_^sshShareConnection^_^
@@ -0,0 +1,142 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hertzbeat.manager.service.impl;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.when;
import java.lang.reflect.Field;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.List;
import org.apache.hertzbeat.common.constants.CommonConstants;
import org.apache.hertzbeat.common.entity.manager.StatusPageComponent;
import org.apache.hertzbeat.common.entity.manager.StatusPageHistory;
import org.apache.hertzbeat.manager.component.status.CalculateStatus;
import org.apache.hertzbeat.manager.dao.StatusPageComponentDao;
import org.apache.hertzbeat.manager.dao.StatusPageHistoryDao;
import org.apache.hertzbeat.manager.dao.StatusPageIncidentComponentBindDao;
import org.apache.hertzbeat.manager.dao.StatusPageIncidentDao;
import org.apache.hertzbeat.manager.dao.StatusPageOrgDao;
import org.apache.hertzbeat.manager.pojo.dto.ComponentStatus;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
class StatusPageServiceImplTimeTest {
@Mock private StatusPageHistoryDao historyDao;
@Mock private StatusPageComponentDao componentDao;
@Mock private StatusPageOrgDao orgDao;
@Mock private StatusPageIncidentDao incidentDao;
@Mock private StatusPageIncidentComponentBindDao bindDao;
@Mock private CalculateStatus calculateStatus;
private StatusPageServiceImpl service;
private StatusPageComponent component;
@BeforeEach
void setup() throws Exception {
MockitoAnnotations.openMocks(this);
// Create service using its real constructor
service = new StatusPageServiceImpl(bindDao);
// Inject all @Autowired fields manually
inject("statusPageHistoryDao", historyDao);
inject("statusPageComponentDao", componentDao);
inject("statusPageOrgDao", orgDao);
inject("statusPageIncidentDao", incidentDao);
inject("calculateStatus", calculateStatus);
component = new StatusPageComponent();
component.setId(1L);
component.setState((byte) CommonConstants.STATUS_PAGE_COMPONENT_STATE_NORMAL);
when(componentDao.findAll()).thenReturn(List.of(component));
when(calculateStatus.getCalculateStatusIntervals()).thenReturn(300);
when(bindDao.countByComponentId(anyLong())).thenReturn(0L);
}
private void inject(String field, Object value) throws Exception {
Field f = StatusPageServiceImpl.class.getDeclaredField(field);
f.setAccessible(true);
f.set(service, value);
}
@Test
void testMidnightBoundary() {
Instant midnight = LocalDate.of(2026, 1, 14)
.atStartOfDay(ZoneId.of("UTC"))
.toInstant();
StatusPageHistory before = history(midnight.minusSeconds(1),
CommonConstants.STATUS_PAGE_COMPONENT_STATE_ABNORMAL);
StatusPageHistory after = history(midnight.plusSeconds(1),
CommonConstants.STATUS_PAGE_COMPONENT_STATE_NORMAL);
when(historyDao.findStatusPageHistoriesByComponentIdAndTimestampBetween(anyLong(), anyLong(), anyLong()))
.thenReturn(List.of(before, after));
List<ComponentStatus> result = service.queryComponentsStatus();
assertEquals(30, result.get(0).getHistory().size());
}
@Test
void testDstDay() {
ZoneId zone = ZoneId.of("America/New_York");
Instant dstDay = ZonedDateTime.of(2026, 3, 8, 12, 0, 0, 0, zone).toInstant();
StatusPageHistory history = history(dstDay,
CommonConstants.STATUS_PAGE_COMPONENT_STATE_ABNORMAL);
when(historyDao.findStatusPageHistoriesByComponentIdAndTimestampBetween(anyLong(), anyLong(), anyLong()))
.thenReturn(List.of(history));
List<ComponentStatus> result = service.queryComponentsStatus();
assertEquals(30, result.get(0).getHistory().size());
}
@Test
void testHistoryWindowSize() {
Instant tenDaysAgo = Instant.now().minus(Duration.ofDays(10));
StatusPageHistory history = history(tenDaysAgo,
CommonConstants.STATUS_PAGE_COMPONENT_STATE_NORMAL);
when(historyDao.findStatusPageHistoriesByComponentIdAndTimestampBetween(anyLong(), anyLong(), anyLong()))
.thenReturn(List.of(history));
List<ComponentStatus> result = service.queryComponentsStatus();
assertEquals(30, result.get(0).getHistory().size());
}
private StatusPageHistory history(Instant time, int state) {
return StatusPageHistory.builder()
.timestamp(time.toEpochMilli())
.state((byte) state)
.componentId(1L)
.build();
}
}
@@ -72,7 +72,7 @@ void migrateHistoryTable(java.sql.Connection conn) throws java.sql.SQLException
try (java.sql.ResultSet rs = conn.getMetaData().getColumns(null, null, "HZB_HISTORY", "METRIC_LABELS")) {
if (rs.next()) metricLabelsExists = true;
}
if (monitorIdExists) {
try (java.sql.Statement stmt = conn.createStatement()) {
if (!metricLabelsExists) {
@@ -92,3 +92,518 @@ void migrateHistoryTable(java.sql.Connection conn) throws java.sql.SQLException
$$;
CALL MIGRATE_HISTORY_TABLE();
DROP ALIAS MIGRATE_HISTORY_TABLE;
-- ========================================
-- hzb_alert_define_monitor_bind table
-- ========================================
CREATE ALIAS UPDATE_ALERT_DEFINE_MONITOR_BIND_INDEXES AS $$
void updateAlertDefineMonitorBindIndexes(java.sql.Connection conn) throws java.sql.SQLException {
boolean tableExists = false;
try (java.sql.ResultSet rs = conn.getMetaData().getTables(null, null, "HZB_ALERT_DEFINE_MONITOR_BIND", null)) {
if (rs.next()) tableExists = true;
}
if (tableExists) {
try (java.sql.Statement stmt = conn.createStatement()) {
// Drop old index if exists
try (java.sql.ResultSet rs = conn.getMetaData().getIndexInfo(null, null, "HZB_ALERT_DEFINE_MONITOR_BIND", false, false)) {
while (rs.next()) {
String indexName = rs.getString("INDEX_NAME");
if ("INDEX_ALERT_DEFINE_MONITOR".equalsIgnoreCase(indexName)) {
stmt.execute("DROP INDEX INDEX_ALERT_DEFINE_MONITOR");
break;
}
}
} catch (Exception e) {
// Index may not exist, continue
}
// Create new indexes if not exist
boolean alertDefineIdIndexExists = false;
boolean monitorIdIndexExists = false;
try (java.sql.ResultSet rs = conn.getMetaData().getIndexInfo(null, null, "HZB_ALERT_DEFINE_MONITOR_BIND", false, false)) {
while (rs.next()) {
String indexName = rs.getString("INDEX_NAME");
if ("IDX_ALERT_DEFINE_ID".equalsIgnoreCase(indexName)) {
alertDefineIdIndexExists = true;
}
if ("IDX_MONITOR_ID".equalsIgnoreCase(indexName)) {
monitorIdIndexExists = true;
}
}
}
if (!alertDefineIdIndexExists) {
stmt.execute("CREATE INDEX IDX_ALERT_DEFINE_ID ON HZB_ALERT_DEFINE_MONITOR_BIND(ALERT_DEFINE_ID)");
}
if (!monitorIdIndexExists) {
stmt.execute("CREATE INDEX IDX_MONITOR_ID ON HZB_ALERT_DEFINE_MONITOR_BIND(MONITOR_ID)");
}
}
}
}
$$;
CALL UPDATE_ALERT_DEFINE_MONITOR_BIND_INDEXES();
DROP ALIAS UPDATE_ALERT_DEFINE_MONITOR_BIND_INDEXES;
-- ========================================
-- hzb_collector_monitor_bind table
-- ========================================
CREATE ALIAS UPDATE_COLLECTOR_MONITOR_BIND_INDEXES AS $$
void updateCollectorMonitorBindIndexes(java.sql.Connection conn) throws java.sql.SQLException {
boolean tableExists = false;
try (java.sql.ResultSet rs = conn.getMetaData().getTables(null, null, "HZB_COLLECTOR_MONITOR_BIND", null)) {
if (rs.next()) tableExists = true;
}
if (tableExists) {
try (java.sql.Statement stmt = conn.createStatement()) {
// Drop old index if exists
try (java.sql.ResultSet rs = conn.getMetaData().getIndexInfo(null, null, "HZB_COLLECTOR_MONITOR_BIND", false, false)) {
while (rs.next()) {
String indexName = rs.getString("INDEX_NAME");
if ("INDEX_COLLECTOR_MONITOR".equalsIgnoreCase(indexName)) {
stmt.execute("DROP INDEX INDEX_COLLECTOR_MONITOR");
break;
}
}
} catch (Exception e) {
// Index may not exist, continue
}
// Create new indexes if not exist
boolean collectorIndexExists = false;
boolean monitorIdIndexExists = false;
try (java.sql.ResultSet rs = conn.getMetaData().getIndexInfo(null, null, "HZB_COLLECTOR_MONITOR_BIND", false, false)) {
while (rs.next()) {
String indexName = rs.getString("INDEX_NAME");
if ("IDX_COLLECTOR_MONITOR_COLLECTOR".equalsIgnoreCase(indexName)) {
collectorIndexExists = true;
}
if ("IDX_COLLECTOR_MONITOR_MONITOR_ID".equalsIgnoreCase(indexName)) {
monitorIdIndexExists = true;
}
}
}
if (!collectorIndexExists) {
stmt.execute("CREATE INDEX IDX_COLLECTOR_MONITOR_COLLECTOR ON HZB_COLLECTOR_MONITOR_BIND(COLLECTOR)");
}
if (!monitorIdIndexExists) {
stmt.execute("CREATE INDEX IDX_COLLECTOR_MONITOR_MONITOR_ID ON HZB_COLLECTOR_MONITOR_BIND(MONITOR_ID)");
}
}
}
}
$$;
CALL UPDATE_COLLECTOR_MONITOR_BIND_INDEXES();
DROP ALIAS UPDATE_COLLECTOR_MONITOR_BIND_INDEXES;
-- ========================================
-- hzb_monitor table
-- ========================================
CREATE ALIAS UPDATE_MONITOR_INDEXES AS $$
void updateMonitorIndexes(java.sql.Connection conn) throws java.sql.SQLException {
boolean tableExists = false;
try (java.sql.ResultSet rs = conn.getMetaData().getTables(null, null, "HZB_MONITOR", null)) {
if (rs.next()) tableExists = true;
}
if (tableExists) {
try (java.sql.Statement stmt = conn.createStatement()) {
// Drop old index if exists
try (java.sql.ResultSet rs = conn.getMetaData().getIndexInfo(null, null, "HZB_MONITOR", false, false)) {
while (rs.next()) {
String indexName = rs.getString("INDEX_NAME");
if ("MONITOR_QUERY_INDEX".equalsIgnoreCase(indexName)) {
stmt.execute("DROP INDEX MONITOR_QUERY_INDEX");
break;
}
}
} catch (Exception e) {
// Index may not exist, continue
}
// Create new indexes if not exist
boolean appIndexExists = false;
boolean instanceIndexExists = false;
boolean nameIndexExists = false;
try (java.sql.ResultSet rs = conn.getMetaData().getIndexInfo(null, null, "HZB_MONITOR", false, false)) {
while (rs.next()) {
String indexName = rs.getString("INDEX_NAME");
if ("IDX_HZB_MONITOR_APP".equalsIgnoreCase(indexName)) {
appIndexExists = true;
}
if ("IDX_HZB_MONITOR_INSTANCE".equalsIgnoreCase(indexName)) {
instanceIndexExists = true;
}
if ("IDX_HZB_MONITOR_NAME".equalsIgnoreCase(indexName)) {
nameIndexExists = true;
}
}
}
if (!appIndexExists) {
stmt.execute("CREATE INDEX IDX_HZB_MONITOR_APP ON HZB_MONITOR(APP)");
}
if (!instanceIndexExists) {
stmt.execute("CREATE INDEX IDX_HZB_MONITOR_INSTANCE ON HZB_MONITOR(INSTANCE)");
}
if (!nameIndexExists) {
stmt.execute("CREATE INDEX IDX_HZB_MONITOR_NAME ON HZB_MONITOR(NAME)");
}
}
}
}
$$;
CALL UPDATE_MONITOR_INDEXES();
DROP ALIAS UPDATE_MONITOR_INDEXES;
-- ========================================
-- hzb_monitor_bind table
-- ========================================
CREATE ALIAS UPDATE_MONITOR_BIND_INDEXES AS $$
void updateMonitorBindIndexes(java.sql.Connection conn) throws java.sql.SQLException {
boolean tableExists = false;
try (java.sql.ResultSet rs = conn.getMetaData().getTables(null, null, "HZB_MONITOR_BIND", null)) {
if (rs.next()) tableExists = true;
}
if (tableExists) {
try (java.sql.Statement stmt = conn.createStatement()) {
// Create new index if not exist
boolean bindIndexExists = false;
try (java.sql.ResultSet rs = conn.getMetaData().getIndexInfo(null, null, "HZB_MONITOR_BIND", false, false)) {
while (rs.next()) {
String indexName = rs.getString("INDEX_NAME");
if ("INDEX_MONITOR_BIND".equalsIgnoreCase(indexName)) {
bindIndexExists = true;
}
}
}
if (!bindIndexExists) {
stmt.execute("CREATE INDEX INDEX_MONITOR_BIND ON HZB_MONITOR_BIND(BIZ_ID)");
}
}
}
}
$$;
CALL UPDATE_MONITOR_BIND_INDEXES();
DROP ALIAS UPDATE_MONITOR_BIND_INDEXES;
-- ========================================
-- hzb_status_page_incident_component_bind table
-- Special handling: component_id might have auto-created index from FK
-- ========================================
CREATE ALIAS UPDATE_STATUS_PAGE_INCIDENT_COMPONENT_BIND_INDEXES AS $$
void updateStatusPageIncidentComponentBindIndexes(java.sql.Connection conn) throws java.sql.SQLException {
boolean tableExists = false;
try (java.sql.ResultSet rs = conn.getMetaData().getTables(null, null, "HZB_STATUS_PAGE_INCIDENT_COMPONENT_BIND", null)) {
if (rs.next()) tableExists = true;
}
if (tableExists) {
try (java.sql.Statement stmt = conn.createStatement()) {
// Check if component_id column already has any index
boolean hasComponentIdIndex = false;
try (java.sql.ResultSet rs = conn.getMetaData().getIndexInfo(null, null, "HZB_STATUS_PAGE_INCIDENT_COMPONENT_BIND", false, false)) {
while (rs.next()) {
String columnName = rs.getString("COLUMN_NAME");
if (columnName != null && "COMPONENT_ID".equalsIgnoreCase(columnName)) {
hasComponentIdIndex = true;
break;
}
}
}
// Create index on component_id only if no index exists on this column
if (!hasComponentIdIndex) {
stmt.execute("CREATE INDEX IDX_INCIDENT_COMPONENT_COMPONENT_ID ON HZB_STATUS_PAGE_INCIDENT_COMPONENT_BIND(COMPONENT_ID)");
}
}
}
}
$$;
CALL UPDATE_STATUS_PAGE_INCIDENT_COMPONENT_BIND_INDEXES();
DROP ALIAS UPDATE_STATUS_PAGE_INCIDENT_COMPONENT_BIND_INDEXES;
-- ========================================
-- hzb_push_metrics table
-- ========================================
CREATE ALIAS UPDATE_PUSH_METRICS_INDEXES AS $$
void updatePushMetricsIndexes(java.sql.Connection conn) throws java.sql.SQLException {
boolean tableExists = false;
try (java.sql.ResultSet rs = conn.getMetaData().getTables(null, null, "HZB_PUSH_METRICS", null)) {
if (rs.next()) tableExists = true;
}
if (tableExists) {
try (java.sql.Statement stmt = conn.createStatement()) {
// Drop old index if exists
try (java.sql.ResultSet rs = conn.getMetaData().getIndexInfo(null, null, "HZB_PUSH_METRICS", false, false)) {
while (rs.next()) {
String indexName = rs.getString("INDEX_NAME");
if ("PUSH_QUERY_INDEX".equalsIgnoreCase(indexName)) {
stmt.execute("DROP INDEX PUSH_QUERY_INDEX");
break;
}
}
} catch (Exception e) {
// Index may not exist, continue
}
// Create new indexes if not exist
boolean monitorIdIndexExists = false;
boolean timeIndexExists = false;
try (java.sql.ResultSet rs = conn.getMetaData().getIndexInfo(null, null, "HZB_PUSH_METRICS", false, false)) {
while (rs.next()) {
String indexName = rs.getString("INDEX_NAME");
if ("IDX_PUSH_METRICS_MONITOR_ID".equalsIgnoreCase(indexName)) {
monitorIdIndexExists = true;
}
if ("IDX_PUSH_METRICS_TIME".equalsIgnoreCase(indexName)) {
timeIndexExists = true;
}
}
}
if (!monitorIdIndexExists) {
stmt.execute("CREATE INDEX IDX_PUSH_METRICS_MONITOR_ID ON HZB_PUSH_METRICS(MONITOR_ID)");
}
if (!timeIndexExists) {
stmt.execute("CREATE INDEX IDX_PUSH_METRICS_TIME ON HZB_PUSH_METRICS(TIME)");
}
}
}
}
$$;
CALL UPDATE_PUSH_METRICS_INDEXES();
DROP ALIAS UPDATE_PUSH_METRICS_INDEXES;
-- ========================================
-- hzb_history table
-- ========================================
CREATE ALIAS UPDATE_HISTORY_INDEXES AS $$
void updateHistoryIndexes(java.sql.Connection conn) throws java.sql.SQLException {
boolean tableExists = false;
try (java.sql.ResultSet rs = conn.getMetaData().getTables(null, null, "HZB_HISTORY", null)) {
if (rs.next()) tableExists = true;
}
if (tableExists) {
try (java.sql.Statement stmt = conn.createStatement()) {
// Drop old index if exists
try (java.sql.ResultSet rs = conn.getMetaData().getIndexInfo(null, null, "HZB_HISTORY", false, false)) {
while (rs.next()) {
String indexName = rs.getString("INDEX_NAME");
if ("HISTORY_QUERY_INDEX".equalsIgnoreCase(indexName)) {
stmt.execute("DROP INDEX HISTORY_QUERY_INDEX");
break;
}
}
} catch (Exception e) {
// Index may not exist, continue
}
// Create new indexes if not exist
boolean instanceIndexExists = false;
boolean appIndexExists = false;
boolean metricsIndexExists = false;
boolean metricIndexExists = false;
try (java.sql.ResultSet rs = conn.getMetaData().getIndexInfo(null, null, "HZB_HISTORY", false, false)) {
while (rs.next()) {
String indexName = rs.getString("INDEX_NAME");
if ("IDX_HZB_HISTORY_INSTANCE".equalsIgnoreCase(indexName)) {
instanceIndexExists = true;
}
if ("IDX_HZB_HISTORY_APP".equalsIgnoreCase(indexName)) {
appIndexExists = true;
}
if ("IDX_HZB_HISTORY_METRICS".equalsIgnoreCase(indexName)) {
metricsIndexExists = true;
}
if ("IDX_HZB_HISTORY_METRIC".equalsIgnoreCase(indexName)) {
metricIndexExists = true;
}
}
}
if (!instanceIndexExists) {
stmt.execute("CREATE INDEX IDX_HZB_HISTORY_INSTANCE ON HZB_HISTORY(INSTANCE)");
}
if (!appIndexExists) {
stmt.execute("CREATE INDEX IDX_HZB_HISTORY_APP ON HZB_HISTORY(APP)");
}
if (!metricsIndexExists) {
stmt.execute("CREATE INDEX IDX_HZB_HISTORY_METRICS ON HZB_HISTORY(METRICS)");
}
if (!metricIndexExists) {
stmt.execute("CREATE INDEX IDX_HZB_HISTORY_METRIC ON HZB_HISTORY(METRIC)");
}
}
}
}
$$;
CALL UPDATE_HISTORY_INDEXES();
DROP ALIAS UPDATE_HISTORY_INDEXES;
-- ========================================
-- hzb_param table
-- ========================================
CREATE ALIAS UPDATE_PARAM_TABLE_INDEXES AS $$
void updateParamTableIndexes(java.sql.Connection conn) throws java.sql.SQLException {
boolean tableExists = false;
try (java.sql.ResultSet rs = conn.getMetaData().getTables(null, null, "HZB_PARAM", null)) {
if (rs.next()) tableExists = true;
}
if (tableExists) {
try (java.sql.Statement stmt = conn.createStatement()) {
// Drop old index if exists
try (java.sql.ResultSet rs = conn.getMetaData().getIndexInfo(null, null, "HZB_PARAM", false, false)) {
while (rs.next()) {
String indexName = rs.getString("INDEX_NAME");
if ("IDX_HZB_PARAM_MONITOR_ID".equalsIgnoreCase(indexName)) {
stmt.execute("DROP INDEX IDX_HZB_PARAM_MONITOR_ID");
break;
}
}
} catch (Exception e) {
// Index may not exist, continue
}
// Create new index if not exist
boolean indexExists = false;
try (java.sql.ResultSet rs = conn.getMetaData().getIndexInfo(null, null, "HZB_PARAM", false, false)) {
while (rs.next()) {
if ("IDX_HZB_PARAM_MONITOR_ID".equalsIgnoreCase(rs.getString("INDEX_NAME"))) {
indexExists = true;
break;
}
}
}
if (!indexExists) {
stmt.execute("CREATE INDEX IDX_HZB_PARAM_MONITOR_ID ON HZB_PARAM(MONITOR_ID)");
}
// Drop old unique constraint if exists
try (java.sql.ResultSet rs = conn.getMetaData().getIndexInfo(null, null, "HZB_PARAM", true, false)) {
while (rs.next()) {
String indexName = rs.getString("INDEX_NAME");
if (indexName != null && indexName.equalsIgnoreCase("UK_HZB_PARAM_MONITOR_FIELD")) {
stmt.execute("DROP INDEX UK_HZB_PARAM_MONITOR_FIELD");
break;
}
}
} catch (Exception e) {
// Constraint may not exist, continue
}
// Create new unique constraint if not exist
boolean constraintExists = false;
try (java.sql.ResultSet rs = conn.getMetaData().getIndexInfo(null, null, "HZB_PARAM", true, false)) {
while (rs.next()) {
String indexName = rs.getString("INDEX_NAME");
if (indexName != null && indexName.equalsIgnoreCase("UK_HZB_PARAM_MONITOR_FIELD")) {
constraintExists = true;
break;
}
}
}
if (!constraintExists) {
stmt.execute("CREATE UNIQUE INDEX UK_HZB_PARAM_MONITOR_FIELD ON HZB_PARAM(MONITOR_ID, FIELD)");
}
}
}
}
$$;
CALL UPDATE_PARAM_TABLE_INDEXES();
DROP ALIAS UPDATE_PARAM_TABLE_INDEXES;
-- ========================================
-- hzb_plugin_param table
-- ========================================
CREATE ALIAS UPDATE_PLUGIN_PARAM_TABLE_INDEXES AS $$
void updatePluginParamTableIndexes(java.sql.Connection conn) throws java.sql.SQLException {
boolean tableExists = false;
try (java.sql.ResultSet rs = conn.getMetaData().getTables(null, null, "HZB_PLUGIN_PARAM", null)) {
if (rs.next()) tableExists = true;
}
if (tableExists) {
try (java.sql.Statement stmt = conn.createStatement()) {
// Drop old index if exists
try (java.sql.ResultSet rs = conn.getMetaData().getIndexInfo(null, null, "HZB_PLUGIN_PARAM", false, false)) {
while (rs.next()) {
String indexName = rs.getString("INDEX_NAME");
if ("IDX_HZB_PLUGIN_PARAM_PLUGIN_METADATA_ID".equalsIgnoreCase(indexName)) {
stmt.execute("DROP INDEX IDX_HZB_PLUGIN_PARAM_PLUGIN_METADATA_ID");
break;
}
}
} catch (Exception e) {
// Index may not exist, continue
}
// Create new index if not exist
boolean indexExists = false;
try (java.sql.ResultSet rs = conn.getMetaData().getIndexInfo(null, null, "HZB_PLUGIN_PARAM", false, false)) {
while (rs.next()) {
if ("IDX_HZB_PLUGIN_PARAM_PLUGIN_METADATA_ID".equalsIgnoreCase(rs.getString("INDEX_NAME"))) {
indexExists = true;
break;
}
}
}
if (!indexExists) {
stmt.execute("CREATE INDEX IDX_HZB_PLUGIN_PARAM_PLUGIN_METADATA_ID ON HZB_PLUGIN_PARAM(PLUGIN_METADATA_ID)");
}
// Drop old unique constraint if exists
try (java.sql.ResultSet rs = conn.getMetaData().getIndexInfo(null, null, "HZB_PLUGIN_PARAM", true, false)) {
while (rs.next()) {
String indexName = rs.getString("INDEX_NAME");
if (indexName != null && indexName.equalsIgnoreCase("UK_HZB_PLUGIN_PARAM_METADATA_FIELD")) {
stmt.execute("DROP INDEX UK_HZB_PLUGIN_PARAM_METADATA_FIELD");
break;
}
}
} catch (Exception e) {
// Constraint may not exist, continue
}
// Create new unique constraint if not exist
boolean constraintExists = false;
try (java.sql.ResultSet rs = conn.getMetaData().getIndexInfo(null, null, "HZB_PLUGIN_PARAM", true, false)) {
while (rs.next()) {
String indexName = rs.getString("INDEX_NAME");
if (indexName != null && indexName.equalsIgnoreCase("UK_HZB_PLUGIN_PARAM_METADATA_FIELD")) {
constraintExists = true;
break;
}
}
}
if (!constraintExists) {
stmt.execute("CREATE UNIQUE INDEX UK_HZB_PLUGIN_PARAM_METADATA_FIELD ON HZB_PLUGIN_PARAM(PLUGIN_METADATA_ID, FIELD)");
}
}
}
}
$$;
CALL UPDATE_PLUGIN_PARAM_TABLE_INDEXES();
DROP ALIAS UPDATE_PLUGIN_PARAM_TABLE_INDEXES;
@@ -91,7 +91,7 @@ BEGIN
SELECT COUNT(*) INTO monitor_id_exists FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'hzb_history' AND COLUMN_NAME = 'monitor_id';
SELECT COUNT(*) INTO metric_labels_exists FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'hzb_history' AND COLUMN_NAME = 'metric_labels';
IF monitor_id_exists > 0 THEN
IF metric_labels_exists = 0 THEN
SET @sql_rename = 'ALTER TABLE hzb_history CHANGE instance metric_labels VARCHAR(5000)';
@@ -111,9 +111,9 @@ BEGIN
EXECUTE stmt_resize;
DEALLOCATE PREPARE stmt_resize;
END IF;
UPDATE hzb_history h JOIN hzb_monitor m ON h.monitor_id = m.id SET h.instance = m.instance;
SET @sql_drop = 'ALTER TABLE hzb_history DROP COLUMN monitor_id';
PREPARE stmt_drop FROM @sql_drop;
EXECUTE stmt_drop;
@@ -124,4 +124,433 @@ DELIMITER ;
CALL MigrateHistoryTable();
DROP PROCEDURE IF EXISTS MigrateHistoryTable;
-- ========================================
-- hzb_alert_define_monitor_bind table
-- ========================================
DELIMITER //
CREATE PROCEDURE UpdateAlertDefineMonitorBindIndexes()
BEGIN
DECLARE table_exists INT;
SELECT COUNT(*) INTO table_exists
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'hzb_alert_define_monitor_bind';
IF table_exists = 1 THEN
-- Drop old index if exists
IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'hzb_alert_define_monitor_bind'
AND INDEX_NAME = 'index_alert_define_monitor') THEN
SET @drop_sql = 'DROP INDEX index_alert_define_monitor ON hzb_alert_define_monitor_bind';
PREPARE stmt FROM @drop_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END IF;
-- Create new indexes if not exist
IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'hzb_alert_define_monitor_bind'
AND INDEX_NAME = 'idx_alert_define_id') THEN
CREATE INDEX idx_alert_define_id ON hzb_alert_define_monitor_bind(alert_define_id);
END IF;
IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'hzb_alert_define_monitor_bind'
AND INDEX_NAME = 'idx_monitor_id') THEN
CREATE INDEX idx_monitor_id ON hzb_alert_define_monitor_bind(monitor_id);
END IF;
END IF;
END //
DELIMITER ;
CALL UpdateAlertDefineMonitorBindIndexes();
DROP PROCEDURE IF EXISTS UpdateAlertDefineMonitorBindIndexes;
-- ========================================
-- hzb_collector_monitor_bind table
-- ========================================
DELIMITER //
CREATE PROCEDURE UpdateCollectorMonitorBindIndexes()
BEGIN
DECLARE table_exists INT;
SELECT COUNT(*) INTO table_exists
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'hzb_collector_monitor_bind';
IF table_exists = 1 THEN
-- Drop old index if exists
IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'hzb_collector_monitor_bind'
AND INDEX_NAME = 'index_collector_monitor') THEN
SET @drop_sql = 'DROP INDEX index_collector_monitor ON hzb_collector_monitor_bind';
PREPARE stmt FROM @drop_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END IF;
-- Create new indexes if not exist
IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'hzb_collector_monitor_bind'
AND INDEX_NAME = 'idx_collector_monitor_collector') THEN
CREATE INDEX idx_collector_monitor_collector ON hzb_collector_monitor_bind(collector);
END IF;
IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'hzb_collector_monitor_bind'
AND INDEX_NAME = 'idx_collector_monitor_monitor_id') THEN
CREATE INDEX idx_collector_monitor_monitor_id ON hzb_collector_monitor_bind(monitor_id);
END IF;
END IF;
END //
DELIMITER ;
CALL UpdateCollectorMonitorBindIndexes();
DROP PROCEDURE IF EXISTS UpdateCollectorMonitorBindIndexes;
-- ========================================
-- hzb_monitor table
-- ========================================
DELIMITER //
CREATE PROCEDURE UpdateMonitorIndexes()
BEGIN
DECLARE table_exists INT;
SELECT COUNT(*) INTO table_exists
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'hzb_monitor';
IF table_exists = 1 THEN
-- Drop old index if exists
IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'hzb_monitor'
AND INDEX_NAME = 'monitor_query_index') THEN
SET @drop_sql = 'DROP INDEX monitor_query_index ON hzb_monitor';
PREPARE stmt FROM @drop_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END IF;
-- Create new indexes if not exist
IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'hzb_monitor'
AND INDEX_NAME = 'idx_hzb_monitor_app') THEN
CREATE INDEX idx_hzb_monitor_app ON hzb_monitor(app);
END IF;
IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'hzb_monitor'
AND INDEX_NAME = 'idx_hzb_monitor_instance') THEN
CREATE INDEX idx_hzb_monitor_instance ON hzb_monitor(instance);
END IF;
IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'hzb_monitor'
AND INDEX_NAME = 'idx_hzb_monitor_name') THEN
CREATE INDEX idx_hzb_monitor_name ON hzb_monitor(name);
END IF;
END IF;
END //
DELIMITER ;
CALL UpdateMonitorIndexes();
DROP PROCEDURE IF EXISTS UpdateMonitorIndexes;
-- ========================================
-- hzb_monitor_bind table
-- ========================================
DELIMITER //
CREATE PROCEDURE UpdateMonitorBindIndexes()
BEGIN
DECLARE table_exists INT;
SELECT COUNT(*) INTO table_exists
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'hzb_monitor_bind';
IF table_exists = 1 THEN
-- Create new index if not exist
IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'hzb_monitor_bind'
AND INDEX_NAME = 'index_monitor_bind') THEN
CREATE INDEX index_monitor_bind ON hzb_monitor_bind(biz_id);
END IF;
END IF;
END //
DELIMITER ;
CALL UpdateMonitorBindIndexes();
DROP PROCEDURE IF EXISTS UpdateMonitorBindIndexes;
-- ========================================
-- hzb_status_page_incident_component_bind table
-- Special handling: component_id might have auto-created index from FK
-- ========================================
DELIMITER //
CREATE PROCEDURE UpdateStatusPageIncidentComponentBindIndexes()
BEGIN
DECLARE table_exists INT;
DECLARE component_id_has_index INT;
SELECT COUNT(*) INTO table_exists
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'hzb_status_page_incident_component_bind';
IF table_exists = 1 THEN
-- Check if component_id column already has any index (including auto-created by FK)
SELECT COUNT(*) INTO component_id_has_index
FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'hzb_status_page_incident_component_bind'
AND COLUMN_NAME = 'component_id'
AND INDEX_NAME != 'PRIMARY';
-- Create index on component_id only if no index exists on this column
IF component_id_has_index = 0 THEN
CREATE INDEX idx_incident_component_component_id ON hzb_status_page_incident_component_bind(component_id);
END IF;
END IF;
END //
DELIMITER ;
CALL UpdateStatusPageIncidentComponentBindIndexes();
DROP PROCEDURE IF EXISTS UpdateStatusPageIncidentComponentBindIndexes;
-- ========================================
-- hzb_push_metrics table
-- ========================================
DELIMITER //
CREATE PROCEDURE UpdatePushMetricsIndexes()
BEGIN
DECLARE table_exists INT;
SELECT COUNT(*) INTO table_exists
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'hzb_push_metrics';
IF table_exists = 1 THEN
-- Drop old index if exists
IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'hzb_push_metrics'
AND INDEX_NAME = 'push_query_index') THEN
SET @drop_sql = 'DROP INDEX push_query_index ON hzb_push_metrics';
PREPARE stmt FROM @drop_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END IF;
-- Create new indexes if not exist
IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'hzb_push_metrics'
AND INDEX_NAME = 'idx_push_metrics_monitor_id') THEN
CREATE INDEX idx_push_metrics_monitor_id ON hzb_push_metrics(monitor_id);
END IF;
IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'hzb_push_metrics'
AND INDEX_NAME = 'idx_push_metrics_time') THEN
CREATE INDEX idx_push_metrics_time ON hzb_push_metrics(time);
END IF;
END IF;
END //
DELIMITER ;
CALL UpdatePushMetricsIndexes();
DROP PROCEDURE IF EXISTS UpdatePushMetricsIndexes;
-- ========================================
-- hzb_history table
-- ========================================
DELIMITER //
CREATE PROCEDURE UpdateHistoryIndexes()
BEGIN
DECLARE table_exists INT;
SELECT COUNT(*) INTO table_exists
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'hzb_history';
IF table_exists = 1 THEN
-- Drop old index if exists
IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'hzb_history'
AND INDEX_NAME = 'history_query_index') THEN
SET @drop_sql = 'DROP INDEX history_query_index ON hzb_history';
PREPARE stmt FROM @drop_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END IF;
-- Create new indexes if not exist
IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'hzb_history'
AND INDEX_NAME = 'idx_hzb_history_instance') THEN
CREATE INDEX idx_hzb_history_instance ON hzb_history(instance);
END IF;
IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'hzb_history'
AND INDEX_NAME = 'idx_hzb_history_app') THEN
CREATE INDEX idx_hzb_history_app ON hzb_history(app);
END IF;
IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'hzb_history'
AND INDEX_NAME = 'idx_hzb_history_metrics') THEN
CREATE INDEX idx_hzb_history_metrics ON hzb_history(metrics);
END IF;
IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'hzb_history'
AND INDEX_NAME = 'idx_hzb_history_metric') THEN
CREATE INDEX idx_hzb_history_metric ON hzb_history(metric);
END IF;
END IF;
END //
DELIMITER ;
CALL UpdateHistoryIndexes();
DROP PROCEDURE IF EXISTS UpdateHistoryIndexes;
-- ========================================
-- hzb_param table
-- ========================================
DELIMITER //
CREATE PROCEDURE UpdateParamTableIndexes()
BEGIN
DECLARE table_exists INT;
SELECT COUNT(*) INTO table_exists
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'hzb_param';
IF table_exists = 1 THEN
-- Drop old index if exists
IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'hzb_param'
AND INDEX_NAME = 'idx_hzb_param_monitor_id') THEN
SET @drop_sql = 'DROP INDEX idx_hzb_param_monitor_id ON hzb_param';
PREPARE stmt FROM @drop_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END IF;
-- Create new index if not exist
IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'hzb_param'
AND INDEX_NAME = 'idx_hzb_param_monitor_id') THEN
CREATE INDEX idx_hzb_param_monitor_id ON hzb_param(monitor_id);
END IF;
-- Drop old unique constraint if exists
IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'hzb_param'
AND CONSTRAINT_TYPE = 'UNIQUE'
AND CONSTRAINT_NAME = 'uk_hzb_param_monitor_field') THEN
SET @drop_sql = 'ALTER TABLE hzb_param DROP INDEX uk_hzb_param_monitor_field';
PREPARE stmt FROM @drop_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END IF;
-- Create new unique constraint if not exist
IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'hzb_param'
AND CONSTRAINT_TYPE = 'UNIQUE'
AND CONSTRAINT_NAME = 'uk_hzb_param_monitor_field') THEN
ALTER TABLE hzb_param
ADD CONSTRAINT uk_hzb_param_monitor_field
UNIQUE (monitor_id, field);
END IF;
END IF;
END //
DELIMITER ;
CALL UpdateParamTableIndexes();
DROP PROCEDURE IF EXISTS UpdateParamTableIndexes;
-- ========================================
-- hzb_plugin_param table
-- ========================================
DELIMITER //
CREATE PROCEDURE UpdatePluginParamTableIndexes()
BEGIN
DECLARE table_exists INT;
SELECT COUNT(*) INTO table_exists
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'hzb_plugin_param';
IF table_exists = 1 THEN
-- Drop old index if exists
IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'hzb_plugin_param'
AND INDEX_NAME = 'idx_hzb_plugin_param_plugin_metadata_id') THEN
SET @drop_sql = 'DROP INDEX idx_hzb_plugin_param_plugin_metadata_id ON hzb_plugin_param';
PREPARE stmt FROM @drop_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END IF;
-- Create new index if not exist
IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'hzb_plugin_param'
AND INDEX_NAME = 'idx_hzb_plugin_param_plugin_metadata_id') THEN
CREATE INDEX idx_hzb_plugin_param_plugin_metadata_id ON hzb_plugin_param(plugin_metadata_id);
END IF;
-- Drop old unique constraint if exists
IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'hzb_plugin_param'
AND CONSTRAINT_TYPE = 'UNIQUE'
AND CONSTRAINT_NAME = 'uk_hzb_plugin_param_metadata_field') THEN
SET @drop_sql = 'ALTER TABLE hzb_plugin_param DROP INDEX uk_hzb_plugin_param_metadata_field';
PREPARE stmt FROM @drop_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END IF;
-- Create new unique constraint if not exist
IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'hzb_plugin_param'
AND CONSTRAINT_TYPE = 'UNIQUE'
AND CONSTRAINT_NAME = 'uk_hzb_plugin_param_metadata_field') THEN
ALTER TABLE hzb_plugin_param
ADD CONSTRAINT uk_hzb_plugin_param_metadata_field
UNIQUE (plugin_metadata_id, field);
END IF;
END IF;
END //
DELIMITER ;
CALL UpdatePluginParamTableIndexes();
DROP PROCEDURE IF EXISTS UpdatePluginParamTableIndexes;
COMMIT;
@@ -62,14 +62,240 @@ BEGIN
UPDATE hzb_history SET instance = NULL;
ALTER TABLE hzb_history ALTER COLUMN instance TYPE VARCHAR(255);
END IF;
UPDATE hzb_history h
SET instance = m.instance
FROM hzb_monitor m
WHERE h.monitor_id = m.id;
ALTER TABLE hzb_history DROP COLUMN monitor_id;
END IF;
END $$;
commit;
-- ========================================
-- hzb_alert_define_monitor_bind table
-- ========================================
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'hzb_alert_define_monitor_bind') THEN
-- Drop old index if exists
IF EXISTS (SELECT 1 FROM pg_indexes WHERE tablename = 'hzb_alert_define_monitor_bind' AND indexname = 'index_alert_define_monitor') THEN
DROP INDEX IF EXISTS index_alert_define_monitor;
END IF;
-- Create new indexes if not exist
IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE tablename = 'hzb_alert_define_monitor_bind' AND indexname = 'idx_alert_define_id') THEN
CREATE INDEX idx_alert_define_id ON hzb_alert_define_monitor_bind(alert_define_id);
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE tablename = 'hzb_alert_define_monitor_bind' AND indexname = 'idx_monitor_id') THEN
CREATE INDEX idx_monitor_id ON hzb_alert_define_monitor_bind(monitor_id);
END IF;
END IF;
END $$;
-- ========================================
-- hzb_collector_monitor_bind table
-- ========================================
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'hzb_collector_monitor_bind') THEN
-- Drop old index if exists
IF EXISTS (SELECT 1 FROM pg_indexes WHERE tablename = 'hzb_collector_monitor_bind' AND indexname = 'index_collector_monitor') THEN
DROP INDEX IF EXISTS index_collector_monitor;
END IF;
-- Create new indexes if not exist
IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE tablename = 'hzb_collector_monitor_bind' AND indexname = 'idx_collector_monitor_collector') THEN
CREATE INDEX idx_collector_monitor_collector ON hzb_collector_monitor_bind(collector);
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE tablename = 'hzb_collector_monitor_bind' AND indexname = 'idx_collector_monitor_monitor_id') THEN
CREATE INDEX idx_collector_monitor_monitor_id ON hzb_collector_monitor_bind(monitor_id);
END IF;
END IF;
END $$;
-- ========================================
-- hzb_monitor table
-- ========================================
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'hzb_monitor') THEN
-- Drop old index if exists
IF EXISTS (SELECT 1 FROM pg_indexes WHERE tablename = 'hzb_monitor' AND indexname = 'monitor_query_index') THEN
DROP INDEX IF EXISTS monitor_query_index;
END IF;
-- Create new indexes if not exist
IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE tablename = 'hzb_monitor' AND indexname = 'idx_hzb_monitor_app') THEN
CREATE INDEX idx_hzb_monitor_app ON hzb_monitor(app);
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE tablename = 'hzb_monitor' AND indexname = 'idx_hzb_monitor_instance') THEN
CREATE INDEX idx_hzb_monitor_instance ON hzb_monitor(instance);
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE tablename = 'hzb_monitor' AND indexname = 'idx_hzb_monitor_name') THEN
CREATE INDEX idx_hzb_monitor_name ON hzb_monitor(name);
END IF;
END IF;
END $$;
-- ========================================
-- hzb_monitor_bind table
-- ========================================
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'hzb_monitor_bind') THEN
-- Create new index if not exist
IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE tablename = 'hzb_monitor_bind' AND indexname = 'index_monitor_bind') THEN
CREATE INDEX index_monitor_bind ON hzb_monitor_bind(biz_id);
END IF;
END IF;
END $$;
-- ========================================
-- hzb_status_page_incident_component_bind table
-- Special handling: component_id might have auto-created index from FK
-- ========================================
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'hzb_status_page_incident_component_bind') THEN
-- Check if component_id column already has any index, create if not
IF NOT EXISTS (
SELECT 1 FROM pg_indexes
WHERE tablename = 'hzb_status_page_incident_component_bind'
AND indexdef LIKE '%component_id%'
AND indexname NOT LIKE '%_pkey'
) THEN
CREATE INDEX idx_incident_component_component_id ON hzb_status_page_incident_component_bind(component_id);
END IF;
END IF;
END $$;
-- ========================================
-- hzb_push_metrics table
-- ========================================
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'hzb_push_metrics') THEN
-- Drop old index if exists
IF EXISTS (SELECT 1 FROM pg_indexes WHERE tablename = 'hzb_push_metrics' AND indexname = 'push_query_index') THEN
DROP INDEX IF EXISTS push_query_index;
END IF;
-- Create new indexes if not exist
IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE tablename = 'hzb_push_metrics' AND indexname = 'idx_push_metrics_monitor_id') THEN
CREATE INDEX idx_push_metrics_monitor_id ON hzb_push_metrics(monitor_id);
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE tablename = 'hzb_push_metrics' AND indexname = 'idx_push_metrics_time') THEN
CREATE INDEX idx_push_metrics_time ON hzb_push_metrics(time);
END IF;
END IF;
END $$;
-- ========================================
-- hzb_history table
-- ========================================
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'hzb_history') THEN
-- Drop old index if exists
IF EXISTS (SELECT 1 FROM pg_indexes WHERE tablename = 'hzb_history' AND indexname = 'history_query_index') THEN
DROP INDEX IF EXISTS history_query_index;
END IF;
-- Create new indexes if not exist
IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE tablename = 'hzb_history' AND indexname = 'idx_hzb_history_instance') THEN
CREATE INDEX idx_hzb_history_instance ON hzb_history(instance);
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE tablename = 'hzb_history' AND indexname = 'idx_hzb_history_app') THEN
CREATE INDEX idx_hzb_history_app ON hzb_history(app);
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE tablename = 'hzb_history' AND indexname = 'idx_hzb_history_metrics') THEN
CREATE INDEX idx_hzb_history_metrics ON hzb_history(metrics);
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE tablename = 'hzb_history' AND indexname = 'idx_hzb_history_metric') THEN
CREATE INDEX idx_hzb_history_metric ON hzb_history(metric);
END IF;
END IF;
END $$;
-- ========================================
-- hzb_param table
-- ========================================
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'hzb_param') THEN
-- Drop old index if exists
IF EXISTS (SELECT 1 FROM pg_indexes WHERE tablename = 'hzb_param' AND indexname = 'idx_hzb_param_monitor_id') THEN
DROP INDEX IF EXISTS idx_hzb_param_monitor_id;
END IF;
-- Create new index if not exist
IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE tablename = 'hzb_param' AND indexname = 'idx_hzb_param_monitor_id') THEN
CREATE INDEX idx_hzb_param_monitor_id ON hzb_param(monitor_id);
END IF;
-- Drop old unique constraint if exists
IF EXISTS (SELECT 1 FROM information_schema.table_constraints
WHERE table_name = 'hzb_param'
AND constraint_type = 'UNIQUE'
AND constraint_name = 'uk_hzb_param_monitor_field') THEN
ALTER TABLE hzb_param DROP CONSTRAINT IF EXISTS uk_hzb_param_monitor_field;
END IF;
-- Create new unique constraint if not exist
IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints
WHERE table_name = 'hzb_param'
AND constraint_type = 'UNIQUE'
AND constraint_name = 'uk_hzb_param_monitor_field') THEN
ALTER TABLE hzb_param
ADD CONSTRAINT uk_hzb_param_monitor_field
UNIQUE (monitor_id, field);
END IF;
END IF;
END $$;
-- ========================================
-- hzb_plugin_param table
-- ========================================
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'hzb_plugin_param') THEN
-- Drop old index if exists
IF EXISTS (SELECT 1 FROM pg_indexes WHERE tablename = 'hzb_plugin_param' AND indexname = 'idx_hzb_plugin_param_plugin_metadata_id') THEN
DROP INDEX IF EXISTS idx_hzb_plugin_param_plugin_metadata_id;
END IF;
-- Create new index if not exist
IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE tablename = 'hzb_plugin_param' AND indexname = 'idx_hzb_plugin_param_plugin_metadata_id') THEN
CREATE INDEX idx_hzb_plugin_param_plugin_metadata_id ON hzb_plugin_param(plugin_metadata_id);
END IF;
-- Drop old unique constraint if exists
IF EXISTS (SELECT 1 FROM information_schema.table_constraints
WHERE table_name = 'hzb_plugin_param'
AND constraint_type = 'UNIQUE'
AND constraint_name = 'uk_hzb_plugin_param_metadata_field') THEN
ALTER TABLE hzb_plugin_param DROP CONSTRAINT IF EXISTS uk_hzb_plugin_param_metadata_field;
END IF;
-- Create new unique constraint if not exist
IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints
WHERE table_name = 'hzb_plugin_param'
AND constraint_type = 'UNIQUE'
AND constraint_name = 'uk_hzb_plugin_param_metadata_field') THEN
ALTER TABLE hzb_plugin_param
ADD CONSTRAINT uk_hzb_plugin_param_metadata_field
UNIQUE (plugin_metadata_id, field);
END IF;
END IF;
END $$;
COMMIT;
@@ -0,0 +1,185 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hertzbeat.startup;
import jakarta.persistence.Index;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
import lombok.extern.slf4j.Slf4j;
import org.apache.hertzbeat.common.entity.alerter.AlertDefineMonitorBind;
import org.apache.hertzbeat.common.entity.manager.CollectorMonitorBind;
import org.apache.hertzbeat.common.entity.manager.Monitor;
import org.apache.hertzbeat.common.entity.manager.MonitorBind;
import org.apache.hertzbeat.common.entity.manager.Param;
import org.apache.hertzbeat.common.entity.manager.StatusPageIncidentComponentBind;
import org.apache.hertzbeat.common.entity.push.PushMetrics;
import org.apache.hertzbeat.common.entity.warehouse.History;
import org.apache.hertzbeat.manager.pojo.dto.PluginParam;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.WebProperties;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.TestPropertySource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* Integration test for validating that entity indexes are actually created in the database.
* This test uses H2 in-memory database to verify DDL generation and index creation.
*/
@Slf4j
@SpringBootTest(classes = HertzBeatApplication.class, webEnvironment = SpringBootTest.WebEnvironment.NONE)
@ActiveProfiles("test")
@TestPropertySource(properties = {
"spring.jpa.hibernate.ddl-auto=create-drop",
"spring.datasource.url=jdbc:h2:mem:testdb;MODE=MySQL;DB_CLOSE_DELAY=-1",
"spring.datasource.driver-class-name=org.h2.Driver",
"spring.jpa.show-sql=false"
})
@DisplayName("Entity Index Creation Integration Test")
class EntityIndexIntegrationTest {
@Autowired
private DataSource dataSource;
public List<Class<?>> entities = List.of(
AlertDefineMonitorBind.class,
CollectorMonitorBind.class,
Monitor.class,
MonitorBind.class,
Param.class,
StatusPageIncidentComponentBind.class,
PushMetrics.class,
History.class,
PluginParam.class
);
@Test
@DisplayName("All entity indexes should be created in database")
public void testAllEntityIndexes() throws SQLException {
for (Class<?> entity : entities) {
List<ExpectedIndex> expectedIndexes = parseExpectedIndexes(entity);
if (expectedIndexes.isEmpty()) {
continue;
}
Map<String, IndexMeta> actual = getIndexes(expectedIndexes.get(0).tableName());
for (ExpectedIndex expected : expectedIndexes) {
assertIndexExists(expected, actual);
}
}
}
private List<ExpectedIndex> parseExpectedIndexes(Class<?> entityClass) {
Table table = entityClass.getAnnotation(Table.class);
if (table == null) {
return List.of();
}
String tableName = table.name().toUpperCase();
List<ExpectedIndex> result = new ArrayList<>();
for (Index idx : table.indexes()) {
Set<String> columns = Arrays.stream(idx.columnList().split(","))
.map(String::trim)
.map(String::toUpperCase)
.collect(Collectors.toSet());
result.add(new ExpectedIndex(tableName, columns, false));
}
for (UniqueConstraint uc : table.uniqueConstraints()) {
Set<String> columns = Arrays.stream(uc.columnNames())
.map(String::toUpperCase).collect(Collectors.toSet());
result.add(new ExpectedIndex(tableName, columns, true));
}
return result;
}
private void assertIndexExists(ExpectedIndex expected, Map<String, IndexMeta> actualIndexes) {
boolean found = actualIndexes.values().stream().filter(idx -> !expected.unique || idx.unique).anyMatch(idx -> idx.columns.containsAll(expected.columns));
assertTrue(found, "Expected index not found. Table=" + expected.tableName + ", columns=" + expected.columns + ", unique=" + expected.unique + ", actual=" + actualIndexes);
}
private Map<String, IndexMeta> getIndexes(String tableName) throws SQLException {
Map<String, IndexMeta> indexes = new HashMap<>();
String sql = """
SELECT
INDEX_NAME,
COLUMN_NAME,
IS_UNIQUE
FROM INFORMATION_SCHEMA.INDEX_COLUMNS
WHERE TABLE_NAME = ?
""";
try (Connection conn = dataSource.getConnection(); var ps = conn.prepareStatement(sql)) {
ps.setString(1, tableName.toUpperCase());
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
String indexName = rs.getString("INDEX_NAME");
String column = rs.getString("COLUMN_NAME");
boolean unique = rs.getBoolean("IS_UNIQUE");
if ("PRIMARY".equalsIgnoreCase(indexName)) {
continue;
}
indexes.computeIfAbsent(indexName, k -> new IndexMeta(unique)).columns.add(column.toUpperCase());
}
}
}
return indexes;
}
static class IndexMeta {
final boolean unique;
final Set<String> columns = new HashSet<>();
IndexMeta(boolean unique) {
this.unique = unique;
}
}
record ExpectedIndex(String tableName, Set<String> columns, boolean unique) {
}
@TestConfiguration
static class TestConfig {
@Bean
public WebProperties webProperties() {
return new WebProperties();
}
}
}
@@ -65,45 +65,67 @@ public interface HistoryDataReader {
* @param spanId span ID filter
* @param severityNumber severity number filter
* @param severityText severity text filter
* @param searchContent search content in log body
* @return filtered log entries
*/
default List<LogEntry> queryLogsByMultipleConditions(Long startTime, Long endTime, String traceId,
String spanId, Integer severityNumber,
String severityText) {
String severityText, String searchContent) {
throw new UnsupportedOperationException("query logs by multiple conditions is not supported");
}
/**
* Query logs with multiple filter conditions and pagination
* Query logs with multiple filter conditions and pagination (Legacy)
*/
default List<LogEntry> queryLogsByMultipleConditionsWithPagination(Long startTime, Long endTime, String traceId,
String spanId, Integer severityNumber,
String severityText, Integer offset, Integer limit) {
return queryLogsByMultipleConditionsWithPagination(startTime, endTime, traceId, spanId, severityNumber, severityText, null, offset, limit);
}
/**
* Query logs with multiple filter conditions and pagination including search content
* @param startTime start time in milliseconds
* @param endTime end time in milliseconds
* @param traceId trace ID filter
* @param spanId span ID filter
* @param severityNumber severity number filter
* @param severityText severity text filter
* @param searchContent search content in log body
* @param offset pagination offset
* @param limit pagination limit
* @return filtered log entries with pagination
*/
default List<LogEntry> queryLogsByMultipleConditionsWithPagination(Long startTime, Long endTime, String traceId,
String spanId, Integer severityNumber,
String severityText, Integer offset, Integer limit) {
String severityText, String searchContent,
Integer offset, Integer limit) {
throw new UnsupportedOperationException("query logs by multiple conditions with pagination is not supported");
}
/**
* Count logs with multiple filter conditions
* Count logs with multiple filter conditions (Legacy)
*/
default long countLogsByMultipleConditions(Long startTime, Long endTime, String traceId,
String spanId, Integer severityNumber,
String severityText) {
return countLogsByMultipleConditions(startTime, endTime, traceId, spanId, severityNumber, severityText, null);
}
/**
* Count logs with multiple filter conditions including search content
* @param startTime start time in milliseconds
* @param endTime end time in milliseconds
* @param traceId trace ID filter
* @param spanId span ID filter
* @param severityNumber severity number filter
* @param severityText severity text filter
* @param searchContent search content in log body
* @return count of matching log entries
*/
default long countLogsByMultipleConditions(Long startTime, Long endTime, String traceId,
String spanId, Integer severityNumber,
String severityText) {
String severityText, String searchContent) {
throw new UnsupportedOperationException("count logs by multiple conditions is not supported");
}
}
}
@@ -43,6 +43,7 @@ import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
@@ -143,7 +144,8 @@ public class GreptimeDbDataStorage extends AbstractHistoryDataStorage {
return;
}
String instance = metricsData.getInstance();
String tableName = getTableName(metricsData.getMetrics());
String app = metricsData.getApp();
String tableName = getTableName(app, metricsData.getMetrics());
TableSchema.Builder tableSchemaBuilder = TableSchema.newBuilder(tableName);
tableSchemaBuilder.addTag("instance", DataType.String)
@@ -220,8 +222,8 @@ public class GreptimeDbDataStorage extends AbstractHistoryDataStorage {
return getHistoryData(start, end, step, instance, app, metrics, metric);
}
private String getTableName(String metrics) {
return metrics;
private String getTableName(String app, String metrics) {
return app + "_" + metrics;
}
@Override
@@ -246,7 +248,7 @@ public class GreptimeDbDataStorage extends AbstractHistoryDataStorage {
long effectiveStart = values.get(0).getTime() / 1000;
long effectiveEnd = values.get(values.size() - 1).getTime() / 1000 + Duration.ofHours(4).getSeconds();
String name = getTableName(metrics);
String name = getTableName(app, metrics);
String timeSeriesSelector = name + "{" + LABEL_KEY_INSTANCE + "=\"" + instance + "\"";
if (!CommonConstants.PROMETHEUS.equals(app)) {
timeSeriesSelector = timeSeriesSelector + "," + LABEL_KEY_FIELD + "=\"" + metric + "\"";
@@ -330,7 +332,7 @@ public class GreptimeDbDataStorage extends AbstractHistoryDataStorage {
* @return history metric data
*/
private Map<String, List<Value>> getHistoryData(long start, long end, String step, String instance, String app, String metrics, String metric) {
String name = getTableName(metrics);
String name = getTableName(app, metrics);
String timeSeriesSelector = LABEL_KEY_NAME + "=\"" + name + "\""
+ "," + LABEL_KEY_INSTANCE + "=\"" + instance + "\"";
if (!CommonConstants.PROMETHEUS.equals(app)) {
@@ -541,10 +543,10 @@ public class GreptimeDbDataStorage extends AbstractHistoryDataStorage {
@Override
public List<LogEntry> queryLogsByMultipleConditions(Long startTime, Long endTime, String traceId,
String spanId, Integer severityNumber,
String severityText) {
String severityText, String searchContent) {
try {
StringBuilder sql = new StringBuilder("SELECT * FROM ").append(LOG_TABLE_NAME);
buildWhereConditions(sql, startTime, endTime, traceId, spanId, severityNumber, severityText);
buildWhereConditions(sql, startTime, endTime, traceId, spanId, severityNumber, severityText, searchContent);
sql.append(" ORDER BY time_unix_nano DESC");
List<Map<String, Object>> rows = greptimeSqlQueryExecutor.execute(sql.toString());
@@ -558,10 +560,11 @@ public class GreptimeDbDataStorage extends AbstractHistoryDataStorage {
@Override
public List<LogEntry> queryLogsByMultipleConditionsWithPagination(Long startTime, Long endTime, String traceId,
String spanId, Integer severityNumber,
String severityText, Integer offset, Integer limit) {
String severityText, String searchContent,
Integer offset, Integer limit) {
try {
StringBuilder sql = new StringBuilder("SELECT * FROM ").append(LOG_TABLE_NAME);
buildWhereConditions(sql, startTime, endTime, traceId, spanId, severityNumber, severityText);
buildWhereConditions(sql, startTime, endTime, traceId, spanId, severityNumber, severityText, searchContent);
sql.append(" ORDER BY time_unix_nano DESC");
// Add pagination
@@ -583,10 +586,10 @@ public class GreptimeDbDataStorage extends AbstractHistoryDataStorage {
@Override
public long countLogsByMultipleConditions(Long startTime, Long endTime, String traceId,
String spanId, Integer severityNumber,
String severityText) {
String severityText, String searchContent) {
try {
StringBuilder sql = new StringBuilder("SELECT COUNT(*) as count FROM ").append(LOG_TABLE_NAME);
buildWhereConditions(sql, startTime, endTime, traceId, spanId, severityNumber, severityText);
buildWhereConditions(sql, startTime, endTime, traceId, spanId, severityNumber, severityText, searchContent);
List<Map<String, Object>> rows = greptimeSqlQueryExecutor.execute(sql.toString());
if (rows != null && !rows.isEmpty()) {
@@ -623,7 +626,7 @@ public class GreptimeDbDataStorage extends AbstractHistoryDataStorage {
* @param severityNumber severity number
*/
private void buildWhereConditions(StringBuilder sql, Long startTime, Long endTime, String traceId,
String spanId, Integer severityNumber, String severityText) {
String spanId, Integer severityNumber, String severityText, String searchContent) {
List<String> conditions = new ArrayList<>();
// Time range condition
@@ -651,6 +654,11 @@ public class GreptimeDbDataStorage extends AbstractHistoryDataStorage {
conditions.add("severity_text = '" + safeString(severityText) + "'");
}
// Search content condition - search in body field
if (StringUtils.hasText(searchContent)) {
conditions.add("body LIKE '%" + safeString(searchContent) + "%'");
}
// Add WHERE clause if there are conditions
if (!conditions.isEmpty()) {
sql.append(" WHERE ").append(String.join(" AND ", conditions));
@@ -758,7 +766,7 @@ public class GreptimeDbDataStorage extends AbstractHistoryDataStorage {
try {
StringBuilder sql = new StringBuilder("DELETE FROM ").append(LOG_TABLE_NAME).append(" WHERE time_unix_nano IN (");
sql.append(timeUnixNanos.stream()
.filter(time -> time != null)
.filter(Objects::nonNull)
.map(String::valueOf)
.collect(Collectors.joining(", ")));
sql.append(")");
@@ -47,6 +47,7 @@ import org.apache.hertzbeat.common.entity.arrow.RowWrapper;
import org.apache.hertzbeat.common.entity.dto.Value;
import org.apache.hertzbeat.common.entity.message.CollectRep;
import org.apache.hertzbeat.common.util.JsonUtil;
import org.apache.hertzbeat.common.util.StrBuffer;
import org.apache.hertzbeat.warehouse.store.history.tsdb.AbstractHistoryDataStorage;
import org.jetbrains.annotations.NotNull;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -68,8 +69,14 @@ public class TdEngineDataStorage extends AbstractHistoryDataStorage {
private static final String INSTANCE_NULL = "''";
private static final String CONSTANTS_CREATE_DATABASE = "CREATE DATABASE IF NOT EXISTS %s";
private static final String INSERT_TABLE_DATA_SQL = "INSERT INTO `%s` USING `%s` TAGS (%s) VALUES %s";
private static final String CREATE_SUPER_TABLE_SQL = "CREATE STABLE IF NOT EXISTS `%s` %s TAGS (monitor BIGINT)";
private static final String CREATE_SUPER_TABLE_SQL = "CREATE STABLE IF NOT EXISTS `%s` %s TAGS (instance NCHAR(128))";
private static final String NO_SUPER_TABLE_ERROR = "Table does not exist";
/**
* schema version suffix - increment when TAG definition changes.
* v1: instance BIGINT (original monitorId like 123456789)
* v2: instance NCHAR(128) (supports string instance values like 127.0.0.1:8080)
*/
private static final String SUPER_TABLE_VERSION = "_v2";
private static final String QUERY_HISTORY_WITH_INSTANCE_SQL =
"SELECT ts, metric_labels, `%s` FROM `%s` WHERE metric_labels = '%s' AND ts >= now - %s order by ts desc";
@@ -185,7 +192,7 @@ public class TdEngineDataStorage extends AbstractHistoryDataStorage {
String instance = metricsData.getInstance();
String app = metricsData.getApp();
String metrics = metricsData.getMetrics();
String superTable = getTable(app, metrics, "_super");
String superTable = getSuperTable(app, metrics);
String table = getTable(app, metrics, instance);
StringBuilder sqlBuffer = new StringBuilder();
int i = 0;
@@ -215,7 +222,12 @@ public class TdEngineDataStorage extends AbstractHistoryDataStorage {
} else {
try {
double number = Double.parseDouble(value);
sqlRowBuffer.append(number);
// TDengine doesn't support NaN or Infinity literals, convert to NULL
if (Double.isNaN(number) || Double.isInfinite(number)) {
sqlRowBuffer.append("NULL");
} else {
sqlRowBuffer.append(number);
}
} catch (Exception e) {
if (log.isWarnEnabled()) {
@@ -230,7 +242,7 @@ public class TdEngineDataStorage extends AbstractHistoryDataStorage {
if (CommonConstants.NULL_VALUE.equals(value)) {
sqlRowBuffer.append("NULL");
} else {
sqlRowBuffer.append("'").append(formatStringValue(value)).append("'");
sqlRowBuffer.append("'").append(StrBuffer.escapeForFormat(formatStringValue(value))).append("'");
}
}
@@ -246,7 +258,7 @@ public class TdEngineDataStorage extends AbstractHistoryDataStorage {
sqlBuffer.append(" ").append(String.format(sqlRowBuffer.toString(), formatStringValue(JsonUtil.toJson(labels))));
}
String insertDataSql = String.format(INSERT_TABLE_DATA_SQL, table, superTable, instance, sqlBuffer);
String insertDataSql = String.format(INSERT_TABLE_DATA_SQL, table, superTable, "'" + formatStringValue(instance) + "'", sqlBuffer);
if (log.isDebugEnabled()) {
log.debug(insertDataSql);
@@ -325,7 +337,12 @@ public class TdEngineDataStorage extends AbstractHistoryDataStorage {
.replace("[", "_")
.replace("]", "_");
}
return app + "_" + metrics + "_" + instance;
return app + "_" + metrics + "_" + instance + SUPER_TABLE_VERSION;
}
@NotNull
private static String getSuperTable(String app, String metrics) {
return app + "_" + metrics + "_super" + SUPER_TABLE_VERSION;
}
private String formatStringValue(String value) {
@@ -6,7 +6,7 @@
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -22,10 +22,7 @@ import com.fasterxml.jackson.databind.JsonNode;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.Instant;
import java.time.ZonedDateTime;
import java.time.temporal.TemporalAmount;
import java.util.ArrayList;
@@ -150,17 +147,17 @@ public class VictoriaMetricsClusterDataStorage extends AbstractHistoryDataStorag
String selectNodeStatusUrl = vmClusterProps.select().url() + VM_SELECT_BASE_PATH.formatted(vmClusterProps.accountID(), STATUS_PATH);
HttpHeaders headers = new HttpHeaders();
if (StringUtils.hasText(vmInsertProps.username())
&& StringUtils.hasText(vmInsertProps.password())) {
&& StringUtils.hasText(vmInsertProps.password())) {
String authStr = vmInsertProps.username() + ":" + vmInsertProps.password();
String encodedAuth = Base64Util.encode(authStr);
headers.add(HttpHeaders.AUTHORIZATION, NetworkConstants.BASIC + SignConstants.BLANK + encodedAuth);
}
HttpEntity<Void> requestEntity = new HttpEntity<>(headers);
ResponseEntity<String> responseEntity = restTemplate.exchange(
selectNodeStatusUrl,
HttpMethod.GET,
requestEntity,
String.class
selectNodeStatusUrl,
HttpMethod.GET,
requestEntity,
String.class
);
String result = responseEntity.getBody();
@@ -186,7 +183,7 @@ public class VictoriaMetricsClusterDataStorage extends AbstractHistoryDataStorag
}
if (metricsData.getValues().isEmpty()) {
log.info("[warehouse victoria-metrics] flush metrics data {} {} {} is null, ignore.",
metricsData.getId(), metricsData.getApp(), metricsData.getMetrics());
metricsData.getId(), metricsData.getApp(), metricsData.getMetrics());
return;
}
Map<String, String> defaultLabels = Maps.newHashMapWithExpectedSize(8);
@@ -196,7 +193,7 @@ public class VictoriaMetricsClusterDataStorage extends AbstractHistoryDataStorag
isPrometheusAuto = true;
defaultLabels.remove(MONITOR_METRICS_KEY);
defaultLabels.put(LABEL_KEY_JOB, metricsData.getApp()
.substring(CommonConstants.PROMETHEUS_APP_PREFIX.length()));
.substring(CommonConstants.PROMETHEUS_APP_PREFIX.length()));
} else {
isPrometheusAuto = false;
defaultLabels.put(LABEL_KEY_JOB, metricsData.getApp());
@@ -239,7 +236,7 @@ public class VictoriaMetricsClusterDataStorage extends AbstractHistoryDataStorag
try {
labels.putAll(defaultLabels);
String labelName = isPrometheusAuto ? metricsData.getMetrics()
: metricsData.getMetrics() + SPILT + entry.getKey();
: metricsData.getMetrics() + SPILT + entry.getKey();
labels.put(LABEL_KEY_NAME, labelName);
if (!isPrometheusAuto) {
labels.put(MONITOR_METRIC_KEY, entry.getKey());
@@ -251,10 +248,10 @@ public class VictoriaMetricsClusterDataStorage extends AbstractHistoryDataStorag
labels.putAll(customizedLabels);
}
VictoriaMetricsDataStorage.VictoriaMetricsContent content = VictoriaMetricsDataStorage.VictoriaMetricsContent.builder()
.metric(new HashMap<>(labels))
.values(new Double[]{entry.getValue()})
.timestamps(timestamp)
.build();
.metric(new HashMap<>(labels))
.values(new Double[]{entry.getValue()})
.timestamps(timestamp)
.build();
contentList.add(content);
} catch (Exception e) {
log.error("combine metrics data error: {}.", e.getMessage(), e);
@@ -290,13 +287,13 @@ public class VictoriaMetricsClusterDataStorage extends AbstractHistoryDataStorag
public Map<String, List<Value>> getHistoryMetricData(String instance, String app, String metrics, String metric,
String history) {
String labelName = metrics + SPILT + metric;
if (CommonConstants.PROMETHEUS.equals(app)) {
if (app.startsWith(CommonConstants.PROMETHEUS_APP_PREFIX)) {
labelName = metrics;
}
String timeSeriesSelector = Stream.of(
LABEL_KEY_NAME + "=\"" + labelName + "\"",
LABEL_KEY_INSTANCE + "=\"" + instance + "\"",
CommonConstants.PROMETHEUS.equals(app) ? null : MONITOR_METRIC_KEY + "=\"" + metric + "\""
app.startsWith(CommonConstants.PROMETHEUS_APP_PREFIX) ? null : MONITOR_METRIC_KEY + "=\"" + metric + "\""
).filter(Objects::nonNull).collect(Collectors.joining(","));
Map<String, List<Value>> instanceValuesMap = new HashMap<>(8);
try {
@@ -307,26 +304,25 @@ public class VictoriaMetricsClusterDataStorage extends AbstractHistoryDataStorag
String authStr = vmSelectProps.username() + ":" + vmSelectProps.password();
String encodedAuth = Base64Util.encode(authStr);
headers.add(HttpHeaders.AUTHORIZATION, NetworkConstants.BASIC
+ SignConstants.BLANK + encodedAuth);
+ SignConstants.BLANK + encodedAuth);
}
HttpEntity<Void> httpEntity = new HttpEntity<>(headers);
Instant end = Instant.now();
Duration duration = Duration.ofHours(Long.parseLong(history.replace("h", "")));
Instant start = end.minus(duration);
String exportUrl = vmClusterProps.select().url() + VM_SELECT_BASE_PATH.formatted(vmClusterProps.accountID(), EXPORT_PATH);
String exportUrl = vmClusterProps.select().url() + VM_SELECT_BASE_PATH.formatted(vmClusterProps.accountID(), EXPORT_PATH);
URI uri = UriComponentsBuilder.fromUriString(exportUrl)
.queryParam("match", URLEncoder.encode("{" + timeSeriesSelector + "}", StandardCharsets.UTF_8))
.queryParam("start", String.valueOf(start.getEpochSecond()))
.queryParam("end", String.valueOf(end.getEpochSecond()))
.build(true).toUri();
.queryParam("match[]", "{" + timeSeriesSelector + "}")
.queryParam("start", "now-" + history)
.queryParam("end", "now")
.build()
.encode()
.toUri();
ResponseEntity<String> responseEntity = restTemplate.exchange(uri, HttpMethod.GET, httpEntity,
String.class);
String.class);
if (responseEntity.getStatusCode().is2xxSuccessful()) {
log.debug("query metrics data from victoria-metrics success. {}", uri);
if (StringUtils.hasText(responseEntity.getBody())) {
String[] contentJsonArr = responseEntity.getBody().split("\n");
List<VictoriaMetricsContent> contents = Arrays.stream(contentJsonArr)
.map(item -> JsonUtil.fromJson(item, VictoriaMetricsContent.class)).toList();
.map(item -> JsonUtil.fromJson(item, VictoriaMetricsContent.class)).toList();
for (VictoriaMetricsContent content : contents) {
Map<String, String> labels = content.getMetric();
labels.remove(LABEL_KEY_NAME);
@@ -338,7 +334,7 @@ public class VictoriaMetricsClusterDataStorage extends AbstractHistoryDataStorag
String labelStr = JsonUtil.toJson(labels);
if (content.getValues() != null && content.getTimestamps() != null) {
List<Value> valueList = instanceValuesMap.computeIfAbsent(labelStr,
k -> new LinkedList<>());
k -> new LinkedList<>());
if (content.getValues().length != content.getTimestamps().length) {
log.error("content.getValues().length != content.getTimestamps().length");
continue;
@@ -347,7 +343,7 @@ public class VictoriaMetricsClusterDataStorage extends AbstractHistoryDataStorag
Long[] timestamps = content.getTimestamps();
for (int index = 0; index < content.getValues().length; index++) {
String strValue = BigDecimal.valueOf(values[index]).setScale(4, RoundingMode.HALF_UP)
.stripTrailingZeros().toPlainString();
.stripTrailingZeros().toPlainString();
// read timestamp here is ms unit
valueList.add(new Value(strValue, timestamps[index]));
}
@@ -368,7 +364,7 @@ public class VictoriaMetricsClusterDataStorage extends AbstractHistoryDataStorag
String metric, String history) {
if (!serverAvailable) {
log.error("""
\t---------------VictoriaMetrics Init Failed---------------
\t--------------Please Config VictoriaMetrics--------------
\t----------Can Not Use Metric History Now----------
@@ -392,13 +388,13 @@ public class VictoriaMetricsClusterDataStorage extends AbstractHistoryDataStorag
startTime = dateTime.toEpochSecond();
}
String labelName = metrics + SPILT + metric;
if (CommonConstants.PROMETHEUS.equals(app)) {
if (app.startsWith(CommonConstants.PROMETHEUS_APP_PREFIX)) {
labelName = metrics;
}
String timeSeriesSelector = Stream.of(
LABEL_KEY_NAME + "=\"" + labelName + "\"",
LABEL_KEY_INSTANCE + "=\"" + instance + "\"",
CommonConstants.PROMETHEUS.equals(app) ? null : MONITOR_METRIC_KEY + "=\"" + metric + "\""
app.startsWith(CommonConstants.PROMETHEUS_APP_PREFIX) ? null : MONITOR_METRIC_KEY + "=\"" + metric + "\""
).filter(Objects::nonNull).collect(Collectors.joining(","));
Map<String, List<Value>> instanceValuesMap = new HashMap<>(8);
try {
@@ -409,25 +405,26 @@ public class VictoriaMetricsClusterDataStorage extends AbstractHistoryDataStorag
String authStr = vmSelectProps.username() + ":" + vmSelectProps.password();
String encodedAuth = Base64Util.encode(authStr);
headers.add(HttpHeaders.AUTHORIZATION, NetworkConstants.BASIC
+ SignConstants.BLANK + encodedAuth);
+ SignConstants.BLANK + encodedAuth);
}
HttpEntity<Void> httpEntity = new HttpEntity<>(headers);
String rangeUrl = VM_SELECT_BASE_PATH.formatted(vmClusterProps.accountID(), QUERY_RANGE_PATH);
String rangeUrl = vmClusterProps.select().url() + VM_SELECT_BASE_PATH.formatted(vmClusterProps.accountID(), QUERY_RANGE_PATH);
URI uri = UriComponentsBuilder.fromUriString(rangeUrl)
.queryParam("query", URLEncoder.encode("{" + timeSeriesSelector + "}", StandardCharsets.UTF_8))
.queryParam("step", "4h")
.queryParam("start", startTime)
.queryParam("end", endTime)
.build(true)
.toUri();
.queryParam("query", "{" + timeSeriesSelector + "}")
.queryParam("step", "4h")
.queryParam("start", startTime)
.queryParam("end", endTime)
.build()
.encode()
.toUri();
ResponseEntity<PromQlQueryContent> responseEntity = restTemplate.exchange(uri, HttpMethod.GET,
httpEntity, PromQlQueryContent.class);
httpEntity, PromQlQueryContent.class);
if (responseEntity.getStatusCode().is2xxSuccessful()) {
log.debug("query metrics data from victoria-metrics success. {}", uri);
if (responseEntity.getBody() != null && responseEntity.getBody().getData() != null
&& responseEntity.getBody().getData().getResult() != null) {
&& responseEntity.getBody().getData().getResult() != null) {
List<PromQlQueryContent.ContentData.Content> contents = responseEntity.getBody().getData()
.getResult();
.getResult();
for (PromQlQueryContent.ContentData.Content content : contents) {
Map<String, String> labels = content.getMetric();
labels.remove(LABEL_KEY_NAME);
@@ -439,11 +436,11 @@ public class VictoriaMetricsClusterDataStorage extends AbstractHistoryDataStorag
String labelStr = JsonUtil.toJson(labels);
if (content.getValues() != null && !content.getValues().isEmpty()) {
List<Value> valueList = instanceValuesMap.computeIfAbsent(labelStr,
k -> new LinkedList<>());
k -> new LinkedList<>());
for (Object[] valueArr : content.getValues()) {
long timestamp = Long.parseLong(String.valueOf(valueArr[0]));
String value = new BigDecimal(String.valueOf(valueArr[1])).setScale(4,
RoundingMode.HALF_UP).stripTrailingZeros().toPlainString();
RoundingMode.HALF_UP).stripTrailingZeros().toPlainString();
// read timestamp here is s unit
valueList.add(new Value(value, timestamp * 1000));
}
@@ -455,18 +452,19 @@ public class VictoriaMetricsClusterDataStorage extends AbstractHistoryDataStorag
}
// max
uri = UriComponentsBuilder.fromUriString(rangeUrl)
.queryParam("query", URLEncoder.encode("max_over_time({" + timeSeriesSelector + "})", StandardCharsets.UTF_8))
.queryParam("step", "4h")
.queryParam("start", startTime)
.queryParam("end", endTime)
.build(true)
.toUri();
.queryParam("query", "max_over_time({" + timeSeriesSelector + "})")
.queryParam("step", "4h")
.queryParam("start", startTime)
.queryParam("end", endTime)
.build()
.encode()
.toUri();
responseEntity = restTemplate.exchange(uri, HttpMethod.GET, httpEntity, PromQlQueryContent.class);
if (responseEntity.getStatusCode().is2xxSuccessful()) {
if (responseEntity.getBody() != null && responseEntity.getBody().getData() != null
&& responseEntity.getBody().getData().getResult() != null) {
&& responseEntity.getBody().getData().getResult() != null) {
List<PromQlQueryContent.ContentData.Content> contents = responseEntity.getBody().getData()
.getResult();
.getResult();
for (PromQlQueryContent.ContentData.Content content : contents) {
Map<String, String> labels = content.getMetric();
labels.remove(LABEL_KEY_NAME);
@@ -478,13 +476,13 @@ public class VictoriaMetricsClusterDataStorage extends AbstractHistoryDataStorag
String labelStr = JsonUtil.toJson(labels);
if (content.getValues() != null && !content.getValues().isEmpty()) {
List<Value> valueList = instanceValuesMap.computeIfAbsent(labelStr,
k -> new LinkedList<>());
k -> new LinkedList<>());
if (valueList.size() == content.getValues().size()) {
for (int timestampIndex = 0; timestampIndex < valueList.size(); timestampIndex++) {
Value value = valueList.get(timestampIndex);
Object[] valueArr = content.getValues().get(timestampIndex);
String maxValue = new BigDecimal(String.valueOf(valueArr[1])).setScale(4,
RoundingMode.HALF_UP).stripTrailingZeros().toPlainString();
RoundingMode.HALF_UP).stripTrailingZeros().toPlainString();
value.setMax(maxValue);
}
}
@@ -494,18 +492,19 @@ public class VictoriaMetricsClusterDataStorage extends AbstractHistoryDataStorag
}
// min
uri = UriComponentsBuilder.fromUriString(rangeUrl)
.queryParam("query", URLEncoder.encode("min_over_time({" + timeSeriesSelector + "})", StandardCharsets.UTF_8))
.queryParam("step", "4h")
.queryParam("start", startTime)
.queryParam("end", endTime)
.build(true)
.toUri();
.queryParam("query", "min_over_time({" + timeSeriesSelector + "})")
.queryParam("step", "4h")
.queryParam("start", startTime)
.queryParam("end", endTime)
.build()
.encode()
.toUri();
responseEntity = restTemplate.exchange(uri, HttpMethod.GET, httpEntity, PromQlQueryContent.class);
if (responseEntity.getStatusCode().is2xxSuccessful()) {
if (responseEntity.getBody() != null && responseEntity.getBody().getData() != null
&& responseEntity.getBody().getData().getResult() != null) {
&& responseEntity.getBody().getData().getResult() != null) {
List<PromQlQueryContent.ContentData.Content> contents = responseEntity.getBody().getData()
.getResult();
.getResult();
for (PromQlQueryContent.ContentData.Content content : contents) {
Map<String, String> labels = content.getMetric();
labels.remove(LABEL_KEY_NAME);
@@ -517,13 +516,13 @@ public class VictoriaMetricsClusterDataStorage extends AbstractHistoryDataStorag
String labelStr = JsonUtil.toJson(labels);
if (content.getValues() != null && !content.getValues().isEmpty()) {
List<Value> valueList = instanceValuesMap.computeIfAbsent(labelStr,
k -> new LinkedList<>());
k -> new LinkedList<>());
if (valueList.size() == content.getValues().size()) {
for (int timestampIndex = 0; timestampIndex < valueList.size(); timestampIndex++) {
Value value = valueList.get(timestampIndex);
Object[] valueArr = content.getValues().get(timestampIndex);
String minValue = new BigDecimal(String.valueOf(valueArr[1])).setScale(4,
RoundingMode.HALF_UP).stripTrailingZeros().toPlainString();
RoundingMode.HALF_UP).stripTrailingZeros().toPlainString();
value.setMin(minValue);
}
}
@@ -533,18 +532,19 @@ public class VictoriaMetricsClusterDataStorage extends AbstractHistoryDataStorag
}
// avg
uri = UriComponentsBuilder.fromUriString(rangeUrl)
.queryParam("query", URLEncoder.encode("avg_over_time({" + timeSeriesSelector + "})", StandardCharsets.UTF_8))
.queryParam("step", "4h")
.queryParam("start", startTime)
.queryParam("end", endTime)
.build(true)
.toUri();
.queryParam("query", "avg_over_time({" + timeSeriesSelector + "})")
.queryParam("step", "4h")
.queryParam("start", startTime)
.queryParam("end", endTime)
.build()
.encode()
.toUri();
responseEntity = restTemplate.exchange(uri, HttpMethod.GET, httpEntity, PromQlQueryContent.class);
if (responseEntity.getStatusCode().is2xxSuccessful()) {
if (responseEntity.getBody() != null && responseEntity.getBody().getData() != null
&& responseEntity.getBody().getData().getResult() != null) {
&& responseEntity.getBody().getData().getResult() != null) {
List<PromQlQueryContent.ContentData.Content> contents = responseEntity.getBody().getData()
.getResult();
.getResult();
for (PromQlQueryContent.ContentData.Content content : contents) {
Map<String, String> labels = content.getMetric();
labels.remove(LABEL_KEY_NAME);
@@ -556,13 +556,13 @@ public class VictoriaMetricsClusterDataStorage extends AbstractHistoryDataStorag
String labelStr = JsonUtil.toJson(labels);
if (content.getValues() != null && !content.getValues().isEmpty()) {
List<Value> valueList = instanceValuesMap.computeIfAbsent(labelStr,
k -> new LinkedList<>());
k -> new LinkedList<>());
if (valueList.size() == content.getValues().size()) {
for (int timestampIndex = 0; timestampIndex < valueList.size(); timestampIndex++) {
Value value = valueList.get(timestampIndex);
Object[] valueArr = content.getValues().get(timestampIndex);
String avgValue = new BigDecimal(String.valueOf(valueArr[1])).setScale(4,
RoundingMode.HALF_UP).stripTrailingZeros().toPlainString();
RoundingMode.HALF_UP).stripTrailingZeros().toPlainString();
value.setMean(avgValue);
}
}
@@ -584,7 +584,7 @@ public class VictoriaMetricsClusterDataStorage extends AbstractHistoryDataStorag
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
if (StringUtils.hasText(vmInsertProps.username())
&& StringUtils.hasText(vmInsertProps.password())) {
&& StringUtils.hasText(vmInsertProps.password())) {
String authStr = vmInsertProps.username() + ":" + vmInsertProps.password();
String encodedAuth = Base64Util.encode(authStr);
headers.add(HttpHeaders.AUTHORIZATION, NetworkConstants.BASIC + SignConstants.BLANK + encodedAuth);
@@ -596,7 +596,7 @@ public class VictoriaMetricsClusterDataStorage extends AbstractHistoryDataStorag
HttpEntity<String> httpEntity = new HttpEntity<>(stringBuilder.toString(), headers);
String importUrl = vmClusterProps.insert().url() + VM_INSERT_BASE_PATH.formatted(vmClusterProps.accountID(), IMPORT_PATH);
ResponseEntity<String> responseEntity = restTemplate.postForEntity(importUrl,
httpEntity, String.class);
httpEntity, String.class);
if (responseEntity.getStatusCode().is2xxSuccessful()) {
log.debug("insert metrics data to victoria-metrics success.");
} else {
@@ -6,7 +6,7 @@
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -21,7 +21,6 @@ import java.io.ByteArrayOutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.ZonedDateTime;
@@ -86,7 +85,7 @@ public class VictoriaMetricsDataStorage extends AbstractHistoryDataStorage {
private static final String IMPORT_PATH = "/api/v1/import";
/**
* <a href="https://docs.victoriametrics.com/Single-server-VictoriaMetrics.html#how-to-export-data-in-json-line-format">
* https://docs.victoriametrics.com/Single-server-VictoriaMetrics.html#how-to-export-data-in-json-line-format
* https://docs.victoriametrics.com/Single-server-VictoriaMetrics.html#how-to-export-data-in-json-line-format
* </a>
*/
private static final String EXPORT_PATH = "/api/v1/export";
@@ -105,7 +104,7 @@ public class VictoriaMetricsDataStorage extends AbstractHistoryDataStorage {
private final VictoriaMetricsProperties victoriaMetricsProp;
private final RestTemplate restTemplate;
private final BlockingQueue<VictoriaMetricsDataStorage.VictoriaMetricsContent> metricsBufferQueue;
private HashedWheelTimer metricsFlushTimer = null;
private final VictoriaMetricsProperties.InsertConfig insertConfig;
private final AtomicBoolean draining = new AtomicBoolean(false);
@@ -119,7 +118,7 @@ public class VictoriaMetricsDataStorage extends AbstractHistoryDataStorage {
victoriaMetricsProp = victoriaMetricsProperties;
serverAvailable = checkVictoriaMetricsDatasourceAvailable();
insertConfig = victoriaMetricsProperties.insert() == null ? new VictoriaMetricsProperties.InsertConfig(100, 3,
new VictoriaMetricsProperties.Compression(false)) : victoriaMetricsProperties.insert();
new VictoriaMetricsProperties.Compression(false)) : victoriaMetricsProperties.insert();
metricsBufferQueue = new LinkedBlockingQueue<>(insertConfig.bufferSize());
initializeFlushTimer();
}
@@ -139,14 +138,14 @@ public class VictoriaMetricsDataStorage extends AbstractHistoryDataStorage {
try {
HttpHeaders headers = new HttpHeaders();
if (StringUtils.hasText(victoriaMetricsProp.username())
&& StringUtils.hasText(victoriaMetricsProp.password())) {
&& StringUtils.hasText(victoriaMetricsProp.password())) {
String authStr = victoriaMetricsProp.username() + SignConstants.DOUBLE_MARK + victoriaMetricsProp.password();
String encodedAuth = Base64Util.encode(authStr);
headers.add(HttpHeaders.AUTHORIZATION, NetworkConstants.BASIC + " " + encodedAuth);
}
HttpEntity<Void> httpEntity = new HttpEntity<>(headers);
ResponseEntity<String> responseEntity = restTemplate.exchange(victoriaMetricsProp.url() + STATUS_PATH,
HttpMethod.GET, httpEntity, String.class);
HttpMethod.GET, httpEntity, String.class);
if (responseEntity.getStatusCode().is2xxSuccessful()) {
log.info("check victoria metrics server status success.");
return true;
@@ -168,7 +167,7 @@ public class VictoriaMetricsDataStorage extends AbstractHistoryDataStorage {
}
if (metricsData.getValues().isEmpty()) {
log.info("[warehouse victoria-metrics] flush metrics data {} {} {} is null, ignore.",
metricsData.getId(), metricsData.getApp(), metricsData.getMetrics());
metricsData.getId(), metricsData.getApp(), metricsData.getMetrics());
return;
}
Map<String, String> defaultLabels = Maps.newHashMapWithExpectedSize(8);
@@ -178,7 +177,7 @@ public class VictoriaMetricsDataStorage extends AbstractHistoryDataStorage {
isPrometheusAuto = true;
defaultLabels.remove(MONITOR_METRICS_KEY);
defaultLabels.put(LABEL_KEY_JOB, metricsData.getApp()
.substring(CommonConstants.PROMETHEUS_APP_PREFIX.length()));
.substring(CommonConstants.PROMETHEUS_APP_PREFIX.length()));
} else {
defaultLabels.put(LABEL_KEY_JOB, metricsData.getApp());
}
@@ -220,7 +219,7 @@ public class VictoriaMetricsDataStorage extends AbstractHistoryDataStorage {
try {
labels.putAll(defaultLabels);
String labelName = isPrometheusAuto ? metricsData.getMetrics()
: metricsData.getMetrics() + SPILT + entry.getKey();
: metricsData.getMetrics() + SPILT + entry.getKey();
labels.put(LABEL_KEY_NAME, labelName);
if (!isPrometheusAuto) {
labels.put(MONITOR_METRIC_KEY, entry.getKey());
@@ -232,10 +231,10 @@ public class VictoriaMetricsDataStorage extends AbstractHistoryDataStorage {
labels.putAll(customizedLabels);
}
VictoriaMetricsContent content = VictoriaMetricsContent.builder()
.metric(new HashMap<>(labels))
.values(new Double[]{entry.getValue()})
.timestamps(timestamp)
.build();
.metric(new HashMap<>(labels))
.values(new Double[]{entry.getValue()})
.timestamps(timestamp)
.build();
contentList.add(content);
} catch (Exception e) {
log.error("combine metrics data error: {}.", e.getMessage(), e);
@@ -266,37 +265,39 @@ public class VictoriaMetricsDataStorage extends AbstractHistoryDataStorage {
@Override
public Map<String, List<Value>> getHistoryMetricData(String instance, String app, String metrics, String metric, String history) {
String labelName = metrics + SPILT + metric;
if (CommonConstants.PROMETHEUS.equals(app)) {
if (app.startsWith(CommonConstants.PROMETHEUS_APP_PREFIX)) {
labelName = metrics;
}
String timeSeriesSelector = LABEL_KEY_NAME + "=\"" + labelName + "\""
+ "," + LABEL_KEY_INSTANCE + "=\"" + instance + "\""
+ (CommonConstants.PROMETHEUS.equals(app) ? "" : "," + MONITOR_METRIC_KEY + "=\"" + metric + "\"");
+ (app.startsWith(CommonConstants.PROMETHEUS_APP_PREFIX) ? "" : "," + MONITOR_METRIC_KEY + "=\"" + metric + "\"");
Map<String, List<Value>> instanceValuesMap = new HashMap<>(8);
try {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(List.of(MediaType.APPLICATION_JSON));
if (StringUtils.hasText(victoriaMetricsProp.username())
&& StringUtils.hasText(victoriaMetricsProp.password())) {
&& StringUtils.hasText(victoriaMetricsProp.password())) {
String authStr = victoriaMetricsProp.username() + ":" + victoriaMetricsProp.password();
String encodedAuth = Base64Util.encode(authStr);
headers.add(HttpHeaders.AUTHORIZATION, NetworkConstants.BASIC + SignConstants.BLANK + encodedAuth);
}
HttpEntity<Void> httpEntity = new HttpEntity<>(headers);
URI uri = UriComponentsBuilder.fromUriString(victoriaMetricsProp.url() + EXPORT_PATH)
.queryParam(URLEncoder.encode("match[]", StandardCharsets.UTF_8), URLEncoder.encode("{" + timeSeriesSelector + "}", StandardCharsets.UTF_8))
.queryParam("start", URLEncoder.encode("now-" + history, StandardCharsets.UTF_8))
.queryParam("end", "now")
.build(true).toUri();
.queryParam("match[]", "{" + timeSeriesSelector + "}")
.queryParam("start", "now-" + history)
.queryParam("end", "now")
.build()
.encode()
.toUri();
ResponseEntity<String> responseEntity = restTemplate.exchange(uri,
HttpMethod.GET, httpEntity, String.class);
HttpMethod.GET, httpEntity, String.class);
if (responseEntity.getStatusCode().is2xxSuccessful()) {
log.debug("query metrics data from victoria-metrics success. {}", uri);
if (StringUtils.hasText(responseEntity.getBody())) {
String[] contentJsonArr = responseEntity.getBody().split("\n");
List<VictoriaMetricsContent> contents = Arrays.stream(contentJsonArr).map(
item -> JsonUtil.fromJson(item, VictoriaMetricsContent.class)
item -> JsonUtil.fromJson(item, VictoriaMetricsContent.class)
).toList();
for (VictoriaMetricsContent content : contents) {
Map<String, String> labels = content.getMetric();
@@ -337,7 +338,7 @@ public class VictoriaMetricsDataStorage extends AbstractHistoryDataStorage {
String metric, String history) {
if (!serverAvailable) {
log.error("""
\t---------------VictoriaMetrics Init Failed---------------
\t--------------Please Config VictoriaMetrics--------------
\t----------Can Not Use Metric History Now----------
@@ -361,37 +362,39 @@ public class VictoriaMetricsDataStorage extends AbstractHistoryDataStorage {
startTime = dateTime.toEpochSecond();
}
String labelName = metrics + SPILT + metric;
if (CommonConstants.PROMETHEUS.equals(app)) {
if (app.startsWith(CommonConstants.PROMETHEUS_APP_PREFIX)) {
labelName = metrics;
}
String timeSeriesSelector = LABEL_KEY_NAME + "=\"" + labelName + "\""
+ "," + LABEL_KEY_INSTANCE + "=\"" + instance + "\""
+ (CommonConstants.PROMETHEUS.equals(app) ? "" : "," + MONITOR_METRIC_KEY + "=\"" + metric + "\"");
+ (app.startsWith(CommonConstants.PROMETHEUS_APP_PREFIX) ? "" : "," + MONITOR_METRIC_KEY + "=\"" + metric + "\"");
Map<String, List<Value>> instanceValuesMap = new HashMap<>(8);
try {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(List.of(MediaType.APPLICATION_JSON));
if (StringUtils.hasText(victoriaMetricsProp.username())
&& StringUtils.hasText(victoriaMetricsProp.password())) {
&& StringUtils.hasText(victoriaMetricsProp.password())) {
String authStr = victoriaMetricsProp.username() + ":" + victoriaMetricsProp.password();
String encodedAuth = Base64Util.encode(authStr);
headers.add(HttpHeaders.AUTHORIZATION, NetworkConstants.BASIC
+ SignConstants.BLANK + encodedAuth);
+ SignConstants.BLANK + encodedAuth);
}
HttpEntity<Void> httpEntity = new HttpEntity<>(headers);
URI uri = UriComponentsBuilder.fromUriString(victoriaMetricsProp.url() + QUERY_RANGE_PATH)
.queryParam(URLEncoder.encode("query", StandardCharsets.UTF_8), URLEncoder.encode("{" + timeSeriesSelector + "}", StandardCharsets.UTF_8))
.queryParam("step", "4h")
.queryParam("start", startTime)
.queryParam("end", endTime)
.build(true).toUri();
.queryParam("query", "{" + timeSeriesSelector + "}")
.queryParam("step", "4h")
.queryParam("start", startTime)
.queryParam("end", endTime)
.build()
.encode()
.toUri();
ResponseEntity<PromQlQueryContent> responseEntity = restTemplate.exchange(uri,
HttpMethod.GET, httpEntity, PromQlQueryContent.class);
HttpMethod.GET, httpEntity, PromQlQueryContent.class);
if (responseEntity.getStatusCode().is2xxSuccessful()) {
log.debug("query metrics data from victoria-metrics success. {}", uri);
if (responseEntity.getBody() != null && responseEntity.getBody().getData() != null
&& responseEntity.getBody().getData().getResult() != null) {
&& responseEntity.getBody().getData().getResult() != null) {
List<PromQlQueryContent.ContentData.Content> contents = responseEntity.getBody().getData().getResult();
for (PromQlQueryContent.ContentData.Content content : contents) {
Map<String, String> labels = content.getMetric();
@@ -418,16 +421,18 @@ public class VictoriaMetricsDataStorage extends AbstractHistoryDataStorage {
}
// max
uri = UriComponentsBuilder.fromUriString(victoriaMetricsProp.url() + QUERY_RANGE_PATH)
.queryParam(URLEncoder.encode("query", StandardCharsets.UTF_8), URLEncoder.encode("max_over_time({" + timeSeriesSelector + "})", StandardCharsets.UTF_8))
.queryParam("step", "4h")
.queryParam("start", startTime)
.queryParam("end", endTime)
.build(true).toUri();
.queryParam("query", "max_over_time({" + timeSeriesSelector + "})")
.queryParam("step", "4h")
.queryParam("start", startTime)
.queryParam("end", endTime)
.build()
.encode()
.toUri();
responseEntity = restTemplate.exchange(uri,
HttpMethod.GET, httpEntity, PromQlQueryContent.class);
HttpMethod.GET, httpEntity, PromQlQueryContent.class);
if (responseEntity.getStatusCode().is2xxSuccessful()) {
if (responseEntity.getBody() != null && responseEntity.getBody().getData() != null
&& responseEntity.getBody().getData().getResult() != null) {
&& responseEntity.getBody().getData().getResult() != null) {
List<PromQlQueryContent.ContentData.Content> contents = responseEntity.getBody().getData().getResult();
for (PromQlQueryContent.ContentData.Content content : contents) {
Map<String, String> labels = content.getMetric();
@@ -454,16 +459,18 @@ public class VictoriaMetricsDataStorage extends AbstractHistoryDataStorage {
}
// min
uri = UriComponentsBuilder.fromUriString(victoriaMetricsProp.url() + QUERY_RANGE_PATH)
.queryParam(URLEncoder.encode("query", StandardCharsets.UTF_8), URLEncoder.encode("min_over_time({" + timeSeriesSelector + "})", StandardCharsets.UTF_8))
.queryParam("step", "4h")
.queryParam("start", startTime)
.queryParam("end", endTime)
.build(true).toUri();
.queryParam("query", "min_over_time({" + timeSeriesSelector + "})")
.queryParam("step", "4h")
.queryParam("start", startTime)
.queryParam("end", endTime)
.build()
.encode()
.toUri();
responseEntity = restTemplate.exchange(uri,
HttpMethod.GET, httpEntity, PromQlQueryContent.class);
HttpMethod.GET, httpEntity, PromQlQueryContent.class);
if (responseEntity.getStatusCode().is2xxSuccessful()) {
if (responseEntity.getBody() != null && responseEntity.getBody().getData() != null
&& responseEntity.getBody().getData().getResult() != null) {
&& responseEntity.getBody().getData().getResult() != null) {
List<PromQlQueryContent.ContentData.Content> contents = responseEntity.getBody().getData().getResult();
for (PromQlQueryContent.ContentData.Content content : contents) {
Map<String, String> labels = content.getMetric();
@@ -490,16 +497,18 @@ public class VictoriaMetricsDataStorage extends AbstractHistoryDataStorage {
}
// avg
uri = UriComponentsBuilder.fromUriString(victoriaMetricsProp.url() + QUERY_RANGE_PATH)
.queryParam(URLEncoder.encode("query", StandardCharsets.UTF_8), URLEncoder.encode("avg_over_time({" + timeSeriesSelector + "})", StandardCharsets.UTF_8))
.queryParam("step", "4h")
.queryParam("start", startTime)
.queryParam("end", endTime)
.build(true).toUri();
.queryParam("query", "avg_over_time({" + timeSeriesSelector + "})")
.queryParam("step", "4h")
.queryParam("start", startTime)
.queryParam("end", endTime)
.build()
.encode()
.toUri();
responseEntity = restTemplate.exchange(uri,
HttpMethod.GET, httpEntity, PromQlQueryContent.class);
HttpMethod.GET, httpEntity, PromQlQueryContent.class);
if (responseEntity.getStatusCode().is2xxSuccessful()) {
if (responseEntity.getBody() != null && responseEntity.getBody().getData() != null
&& responseEntity.getBody().getData().getResult() != null) {
&& responseEntity.getBody().getData().getResult() != null) {
List<PromQlQueryContent.ContentData.Content> contents = responseEntity.getBody().getData().getResult();
for (PromQlQueryContent.ContentData.Content content : contents) {
Map<String, String> labels = content.getMetric();
@@ -598,7 +607,7 @@ public class VictoriaMetricsDataStorage extends AbstractHistoryDataStorage {
}
// Refresh in advance to avoid waiting
if (metricsBufferQueue.size() >= insertConfig.bufferSize() * 0.8
&& draining.compareAndSet(false, true)) {
&& draining.compareAndSet(false, true)) {
triggerImmediateFlush();
}
}
@@ -664,7 +673,7 @@ public class VictoriaMetricsDataStorage extends AbstractHistoryDataStorage {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
if (StringUtils.hasText(victoriaMetricsProp.username())
&& StringUtils.hasText(victoriaMetricsProp.password())) {
&& StringUtils.hasText(victoriaMetricsProp.password())) {
String authStr = victoriaMetricsProp.username() + ":" + victoriaMetricsProp.password();
String encodedAuth = Base64Util.encode(authStr);
headers.add(HttpHeaders.AUTHORIZATION, NetworkConstants.BASIC + SignConstants.BLANK + encodedAuth);
@@ -693,7 +702,7 @@ public class VictoriaMetricsDataStorage extends AbstractHistoryDataStorage {
}
ResponseEntity<String> responseEntity = restTemplate.postForEntity(victoriaMetricsProp.url() + IMPORT_PATH,
httpEntity, String.class);
httpEntity, String.class);
if (responseEntity.getStatusCode().is2xxSuccessful()) {
log.debug("insert metrics data to victoria-metrics success.");
} else {
@@ -17,17 +17,67 @@
package org.apache.hertzbeat.warehouse.store;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.arrow.vector.types.pojo.ArrowType;
import org.apache.arrow.vector.types.pojo.Field;
import org.apache.arrow.vector.types.pojo.FieldType;
import org.apache.hertzbeat.common.constants.CommonConstants;
import org.apache.hertzbeat.common.constants.MetricDataConstants;
import org.apache.hertzbeat.common.entity.arrow.ArrowCell;
import org.apache.hertzbeat.common.entity.arrow.RowWrapper;
import org.apache.hertzbeat.common.entity.message.CollectRep;
import org.apache.hertzbeat.warehouse.store.history.tsdb.tdengine.TdEngineDataStorage;
import org.apache.hertzbeat.warehouse.store.history.tsdb.tdengine.TdEngineProperties;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
import java.sql.Connection;
import java.sql.Statement;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* Test case for {@link TdEngineDataStorage}
*/
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
class TdEngineDataStorageTest {
@Mock
private TdEngineProperties tdEngineProperties;
@Mock
private HikariDataSource mockHikariDataSource;
@Mock
private Connection mockConnection;
@Mock
private Statement mockStatement;
private TdEngineDataStorage tdEngineDataStorage;
@BeforeEach
void setUp() {
void setUp() throws Exception {
when(tdEngineProperties.enabled()).thenReturn(true);
when(tdEngineProperties.url()).thenReturn("jdbc:TAOS-RS://localhost:6041/demo");
when(tdEngineProperties.username()).thenReturn("root");
when(tdEngineProperties.password()).thenReturn("root");
when(tdEngineProperties.tableStrColumnDefineMaxLength()).thenReturn(200);
when(mockHikariDataSource.getConnection()).thenReturn(mockConnection);
when(mockConnection.createStatement()).thenReturn(mockStatement);
}
@Test
@@ -35,7 +85,34 @@ class TdEngineDataStorageTest {
}
@Test
void saveData() {
void testSaveData() throws Exception {
tdEngineDataStorage = new TdEngineDataStorage(tdEngineProperties);
setPrivateField(tdEngineDataStorage, "hikariDataSource", mockHikariDataSource);
setParentPrivateField(tdEngineDataStorage, "serverAvailable", true);
CollectRep.MetricsData metricsData = generateMockedMetricsData();
tdEngineDataStorage.saveData(metricsData);
ArgumentCaptor<String> sqlCaptor = ArgumentCaptor.forClass(String.class);
verify(mockStatement, atLeastOnce()).execute(sqlCaptor.capture());
String executedSql = sqlCaptor.getValue();
// Verify SQL structure
assertNotNull(executedSql);
assertTrue(executedSql.startsWith("INSERT INTO"), "SQL should start with INSERT INTO");
assertTrue(executedSql.contains("USING"), "SQL should contain USING clause");
assertTrue(executedSql.contains("TAGS"), "SQL should contain TAGS clause");
assertTrue(executedSql.contains("VALUES"), "SQL should contain VALUES clause");
// Verify table name format: app_metrics_instance_v2
assertTrue(executedSql.contains("app_cpu_test-%server-01_v2"), "Should contain correct table name");
// Verify super table name format: app_metrics_super_v2
assertTrue(executedSql.contains("app_cpu_super_v2"), "Should contain correct super table name");
// Verify tags format: test-%server-01
assertTrue(executedSql.contains("TAGS ('test-%server-01')"), "Should contain correct super table name");
// Verify VALUES clause structure (timestamp + data values)
assertTrue(executedSql.matches(".*VALUES\\s+\\(\\d+.*68\\.7\\)"), "Should contain timestamp and value 68.7");
}
@Test
@@ -49,4 +126,81 @@ class TdEngineDataStorageTest {
@Test
void getHistoryIntervalMetricData() {
}
/**
* Helper method to set private field using reflection
*/
private void setPrivateField(Object target, String fieldName, Object value) throws Exception {
java.lang.reflect.Field field = target.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(target, value);
}
/**
* Helper method to set private field from parent class using reflection
*/
private void setParentPrivateField(Object target, String fieldName, Object value) throws Exception {
java.lang.reflect.Field field = target.getClass().getSuperclass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(target, value);
}
public static CollectRep.MetricsData generateMockedMetricsData() {
CollectRep.MetricsData mockMetricsData = Mockito.mock(CollectRep.MetricsData.class);
when(mockMetricsData.getId()).thenReturn(0L);
when(mockMetricsData.getMetrics()).thenReturn("cpu");
when(mockMetricsData.getTime()).thenReturn(System.currentTimeMillis());
when(mockMetricsData.getCode()).thenReturn(CollectRep.Code.SUCCESS);
when(mockMetricsData.getApp()).thenReturn("app");
when(mockMetricsData.getInstance()).thenReturn("test-%server-01");
CollectRep.ValueRow mockValueRow = Mockito.mock(CollectRep.ValueRow.class);
List<String> columnValues = List.of("test-%server-01", "68.7");
when(mockValueRow.getColumnsList()).thenReturn(columnValues);
when(mockValueRow.getColumns(0)).thenReturn("test-%server-01");
when(mockValueRow.getColumns(1)).thenReturn("68.7");
List<CollectRep.ValueRow> mockValueRowsList = List.of(mockValueRow);
when(mockMetricsData.getValues()).thenReturn(mockValueRowsList);
CollectRep.Field instanceField = Mockito.mock(CollectRep.Field.class);
when(instanceField.getName()).thenReturn("instance");
CollectRep.Field usageField = Mockito.mock(CollectRep.Field.class);
when(usageField.getName()).thenReturn("usage");
CollectRep.Field systemField = Mockito.mock(CollectRep.Field.class);
when(systemField.getName()).thenReturn("system");
List<CollectRep.Field> mockFields = List.of(instanceField, usageField, systemField);
when(mockMetricsData.getFields()).thenReturn(mockFields);
ArrowType instanceArrowType = new ArrowType.Utf8();
FieldType instanceFieldType = new FieldType(true, instanceArrowType, null, null);
Field instanceArrowField = new Field("instance", instanceFieldType, null);
ArrowCell instanceCell = Mockito.mock(ArrowCell.class);
when(instanceCell.getField()).thenReturn(instanceArrowField);
when(instanceCell.getValue()).thenReturn("test-%server-01");
when(instanceCell.getMetadataAsBoolean(MetricDataConstants.LABEL)).thenReturn(true);
when(instanceCell.getMetadataAsByte(MetricDataConstants.TYPE)).thenReturn(CommonConstants.TYPE_STRING);
ArrowType usageArrowType = new ArrowType.Utf8();
FieldType usageFieldType = new FieldType(true, usageArrowType, null, null);
Field usageArrowField = new Field("usage", usageFieldType, null);
ArrowCell usageCell = Mockito.mock(ArrowCell.class);
when(usageCell.getField()).thenReturn(usageArrowField);
when(usageCell.getValue()).thenReturn("68.7");
when(usageCell.getMetadataAsBoolean(MetricDataConstants.LABEL)).thenReturn(false);
when(usageCell.getMetadataAsByte(MetricDataConstants.TYPE)).thenReturn(CommonConstants.TYPE_NUMBER);
List<ArrowCell> mockCells = List.of(instanceCell, usageCell);
// Create Arrow Field list for RowWrapper
List<org.apache.arrow.vector.types.pojo.Field> arrowFields = List.of(instanceArrowField, usageArrowField);
RowWrapper mockRowWrapper = Mockito.mock(RowWrapper.class);
when(mockRowWrapper.hasNextRow()).thenReturn(true).thenReturn(false);
when(mockRowWrapper.nextRow()).thenReturn(mockRowWrapper);
when(mockRowWrapper.cellStream()).thenAnswer(invocation -> mockCells.stream());
when(mockRowWrapper.getFieldList()).thenReturn(arrowFields);
when(mockMetricsData.readRow()).thenReturn(mockRowWrapper);
return mockMetricsData;
}
}
@@ -82,7 +82,7 @@ class GreptimeDbDataStorageTest {
@Mock
private GreptimeDB greptimeDb;
private GreptimeDbDataStorage greptimeDbDataStorage;
@BeforeEach
@@ -120,14 +120,14 @@ class GreptimeDbDataStorageTest {
void testSaveData() {
try (MockedStatic<GreptimeDB> mockedStatic = mockStatic(GreptimeDB.class)) {
mockedStatic.when(() -> GreptimeDB.create(any())).thenReturn(greptimeDb);
// Mock the write result
@SuppressWarnings("unchecked")
Result<WriteOk, Err> mockResult = mock(Result.class);
when(mockResult.isOk()).thenReturn(true);
CompletableFuture<Result<WriteOk, Err>> mockFuture = CompletableFuture.completedFuture(mockResult);
when(greptimeDb.write(any(Table.class))).thenReturn(mockFuture);
greptimeDbDataStorage = new GreptimeDbDataStorage(greptimeProperties, restTemplate, greptimeSqlQueryExecutor);
// Test with valid metrics data
@@ -153,7 +153,7 @@ class GreptimeDbDataStorageTest {
@Test
void testGetHistoryMetricData() {
greptimeDbDataStorage = new GreptimeDbDataStorage(greptimeProperties, restTemplate, greptimeSqlQueryExecutor);
PromQlQueryContent content = createMockPromQlQueryContent();
ResponseEntity<PromQlQueryContent> responseEntity = new ResponseEntity<>(content, HttpStatus.OK);
@@ -172,14 +172,14 @@ class GreptimeDbDataStorageTest {
void testSaveLogData() {
try (MockedStatic<GreptimeDB> mockedStatic = mockStatic(GreptimeDB.class)) {
mockedStatic.when(() -> GreptimeDB.create(any())).thenReturn(greptimeDb);
// Mock the write result
@SuppressWarnings("unchecked")
Result<WriteOk, Err> mockResult = mock(Result.class);
when(mockResult.isOk()).thenReturn(true);
CompletableFuture<Result<WriteOk, Err>> mockFuture = CompletableFuture.completedFuture(mockResult);
when(greptimeDb.write(any(Table.class))).thenReturn(mockFuture);
greptimeDbDataStorage = new GreptimeDbDataStorage(greptimeProperties, restTemplate, greptimeSqlQueryExecutor);
LogEntry logEntry = createMockLogEntry();
@@ -196,10 +196,10 @@ class GreptimeDbDataStorageTest {
greptimeDbDataStorage = new GreptimeDbDataStorage(greptimeProperties, restTemplate, greptimeSqlQueryExecutor);
List<Map<String, Object>> mockLogRows = createMockLogRows();
when(greptimeSqlQueryExecutor.execute(anyString())).thenReturn(mockLogRows);
// Test basic query
List<LogEntry> result = greptimeDbDataStorage.queryLogsByMultipleConditions(
System.currentTimeMillis() - 3600000, System.currentTimeMillis(), "trace123", "span456", 1, "INFO"
System.currentTimeMillis() - 3600000, System.currentTimeMillis(), "trace123", "span456", 1, "INFO", "content"
);
assertNotNull(result);
assertEquals(1, result.size());
@@ -209,34 +209,34 @@ class GreptimeDbDataStorageTest {
List<Map<String, Object>> mockCountResult = List.of(Map.of("count", 5L));
when(greptimeSqlQueryExecutor.execute(anyString())).thenReturn(mockCountResult);
long count = greptimeDbDataStorage.countLogsByMultipleConditions(
System.currentTimeMillis() - 3600000, System.currentTimeMillis(), null, null, null, null
System.currentTimeMillis() - 3600000, System.currentTimeMillis(), null, null, null, null, null
);
assertEquals(5L, count);
// Test count query with executor error
when(greptimeSqlQueryExecutor.execute(anyString())).thenThrow(new RuntimeException("Database error"));
long errorCount = greptimeDbDataStorage.countLogsByMultipleConditions(System.currentTimeMillis() - 3600000, System.currentTimeMillis(), null, null, null, null);
long errorCount = greptimeDbDataStorage.countLogsByMultipleConditions(System.currentTimeMillis() - 3600000, System.currentTimeMillis(), null, null, null, null, null);
assertEquals(0L, errorCount);
}
}
@Test
void testQueryLogsWithPagination() {
try (MockedStatic<GreptimeDB> mockedStatic = mockStatic(GreptimeDB.class)) {
mockedStatic.when(() -> GreptimeDB.create(any())).thenReturn(greptimeDb);
greptimeDbDataStorage = new GreptimeDbDataStorage(greptimeProperties, restTemplate, greptimeSqlQueryExecutor);
when(greptimeSqlQueryExecutor.execute(anyString())).thenReturn(createMockLogRows());
ArgumentCaptor<String> sqlCaptor = ArgumentCaptor.forClass(String.class);
greptimeDbDataStorage.queryLogsByMultipleConditionsWithPagination(
System.currentTimeMillis() - 3600000, System.currentTimeMillis(),
null, null, null, null, 1, 10
null, null, null, null, null, 1, 10
);
verify(greptimeSqlQueryExecutor).execute(sqlCaptor.capture());
String capturedSql = sqlCaptor.getValue();
assertTrue(capturedSql.toLowerCase().contains("limit 10"));
assertTrue(capturedSql.toLowerCase().contains("offset 1"));
}
@@ -299,7 +299,7 @@ class GreptimeDbDataStorageTest {
lenient().when(mockMetricsData.getCode()).thenReturn(CollectRep.Code.SUCCESS);
lenient().when(mockMetricsData.getMetrics()).thenReturn("cpu");
lenient().when(mockMetricsData.getId()).thenReturn(1L);
if (!hasValues) {
lenient().when(mockMetricsData.getValues()).thenReturn(Collections.emptyList());
return mockMetricsData;
@@ -311,36 +311,36 @@ class GreptimeDbDataStorageTest {
lenient().when(mockField1.getName()).thenReturn("usage");
lenient().when(mockField1.getLabel()).thenReturn(false);
lenient().when(mockField1.getType()).thenReturn((int) CommonConstants.TYPE_NUMBER);
CollectRep.Field mockField2 = mock(CollectRep.Field.class);
lenient().when(mockField2.getName()).thenReturn("instance");
lenient().when(mockField2.getLabel()).thenReturn(true);
lenient().when(mockField2.getType()).thenReturn((int) CommonConstants.TYPE_STRING);
lenient().when(mockMetricsData.getFields()).thenReturn(List.of(mockField1, mockField2));
// Create ValueRow mock
CollectRep.ValueRow mockValueRow = mock(CollectRep.ValueRow.class);
lenient().when(mockValueRow.getColumnsList()).thenReturn(List.of("server1", "85.5"));
lenient().when(mockMetricsData.getValues()).thenReturn(List.of(mockValueRow));
// Mock RowWrapper for readRow()
RowWrapper mockRowWrapper = mock(RowWrapper.class);
lenient().when(mockRowWrapper.hasNextRow()).thenReturn(true, false);
lenient().when(mockRowWrapper.nextRow()).thenReturn(mockRowWrapper);
// Mock cell stream
ArrowCell mockCell1 = mock(ArrowCell.class);
lenient().when(mockCell1.getValue()).thenReturn("85.5");
lenient().when(mockCell1.getMetadataAsBoolean(any())).thenReturn(false);
lenient().when(mockCell1.getMetadataAsByte(any())).thenReturn(CommonConstants.TYPE_NUMBER);
ArrowCell mockCell2 = mock(ArrowCell.class);
lenient().when(mockCell2.getValue()).thenReturn("server1");
lenient().when(mockCell2.getMetadataAsBoolean(any())).thenReturn(true);
lenient().when(mockCell2.getMetadataAsByte(any())).thenReturn(CommonConstants.TYPE_STRING);
lenient().when(mockRowWrapper.cellStream()).thenReturn(java.util.stream.Stream.of(mockCell1, mockCell2));
lenient().when(mockMetricsData.readRow()).thenReturn(mockRowWrapper);
@@ -384,7 +384,7 @@ class GreptimeDbDataStorageTest {
row.put("body", "\"Test log message\"");
row.put("trace_id", "trace123");
row.put("span_id", "span456");
return List.of(row);
}
}
}
+1
View File
@@ -0,0 +1 @@
enable-pre-post-scripts=true
+20 -20
View File
@@ -1,12 +1,12 @@
---
title: Cloud Monitoring System HertzBeat v1.0 Officially Released
author: tom
author_title: tom
author_url: https://github.com/tomsun28
title: Cloud Monitoring System HertzBeat v1.0 Officially Released
author: tom
author_title: tom
author_url: https://github.com/tomsun28
tags: [opensource]
---
HertzBeat, incubated by Dromara and open-sourced by TanCloud, is an open-source monitoring and alerting project that supports a variety of monitoring types including websites, APIs, PING, ports, databases, full-site, operating systems, middleware, etc.
HertzBeat, incubated by Dromara and open-sourced by TanCloud, is an open-source monitoring and alerting project that supports a variety of monitoring types including websites, APIs, PING, ports, databases, full-site, operating systems, middleware, etc.
It supports threshold alarms and notification alerts (email, webhook, DingTalk, WeCom, Feishu robots) and has an easy-to-use, friendly visual operation interface.
Official Website: hertzbeat.com | tancloud.cn
@@ -17,20 +17,20 @@ We would like to thank the HertzBeat Contributors for their contributions since
<table>
<tr>
<td align="center"><a href="https://github.com/tomsun28"><img src="https://avatars.githubusercontent.com/u/24788200?v=4?s=100" width="100px;" alt=""/><br /><sub><b>tomsun28</b></sub></a><br /><a href="https://github.com/tomsun28/hertzbeat/commits?author=tomsun28" title="Code">💻</a> <a href="https://github.com/tomsun28/hertzbeat/commits?author=tomsun28" title="Documentation">📖</a> <a href="#design-tomsun28" title="Design">🎨</a></td>
<td align="center"><a href="https://github.com/wang1027-wqh"><img src="https://avatars.githubusercontent.com/u/71161318?v=4?s=100" width="100px;" alt=""/><br /><sub><b>会编程的王学长</b></sub></a><br /><a href="https://github.com/tomsun28/hertzbeat/commits?author=wang1027-wqh" title="Code">💻</a> <a href="https://github.com/tomsun28/hertzbeat/commits?author=wang1027-wqh" title="Documentation">📖</a> <a href="#design-wang1027-wqh" title="Design">🎨</a></td>
<td align="center"><a href="https://www.maxkey.top/"><img src="https://avatars.githubusercontent.com/u/1563377?v=4?s=100" width="100px;" alt=""/><br /><sub><b>MaxKey</b></sub></a><br /><a href="https://github.com/tomsun28/hertzbeat/commits?author=shimingxy" title="Code">💻</a> <a href="#design-shimingxy" title="Design">🎨</a> <a href="#ideas-shimingxy" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center"><a href="https://blog.gcdd.top/"><img src="https://avatars.githubusercontent.com/u/26523525?v=4?s=100" width="100px;" alt=""/><br /><sub><b>观沧海</b></sub></a><br /><a href="https://github.com/tomsun28/hertzbeat/commits?author=gcdd1993" title="Code">💻</a> <a href="#design-gcdd1993" title="Design">🎨</a> <a href="https://github.com/tomsun28/hertzbeat/issues?q=author%3Agcdd1993" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://github.com/a25017012"><img src="https://avatars.githubusercontent.com/u/32265356?v=4?s=100" width="100px;" alt=""/><br /><sub><b>yuye</b></sub></a><br /><a href="https://github.com/tomsun28/hertzbeat/commits?author=a25017012" title="Code">💻</a> <a href="https://github.com/tomsun28/hertzbeat/commits?author=a25017012" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/jx10086"><img src="https://avatars.githubusercontent.com/u/5323228?v=4?s=100" width="100px;" alt=""/><br /><sub><b>jx10086</b></sub></a><br /><a href="https://github.com/tomsun28/hertzbeat/commits?author=jx10086" title="Code">💻</a> <a href="https://github.com/tomsun28/hertzbeat/issues?q=author%3Ajx10086" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://github.com/winnerTimer"><img src="https://avatars.githubusercontent.com/u/76024658?v=4?s=100" width="100px;" alt=""/><br /><sub><b>winnerTimer</b></sub></a><br /><a href="https://github.com/tomsun28/hertzbeat/commits?author=winnerTimer" title="Code">💻</a> <a href="https://github.com/tomsun28/hertzbeat/issues?q=author%3AwinnerTimer" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://github.com/tomsun28"><img src="https://avatars.githubusercontent.com/u/24788200?v=4?s=100" width="100px;" alt="" /><br /><sub><b>tomsun28</b></sub></a><br /><a href="https://github.com/tomsun28/hertzbeat/commits?author=tomsun28" title="Code">💻</a> <a href="https://github.com/tomsun28/hertzbeat/commits?author=tomsun28" title="Documentation">📖</a> <a href="#design-tomsun28" title="Design">🎨</a></td>
<td align="center"><a href="https://github.com/wang1027-wqh"><img src="https://avatars.githubusercontent.com/u/71161318?v=4?s=100" width="100px;" alt="" /><br /><sub><b>会编程的王学长</b></sub></a><br /><a href="https://github.com/tomsun28/hertzbeat/commits?author=wang1027-wqh" title="Code">💻</a> <a href="https://github.com/tomsun28/hertzbeat/commits?author=wang1027-wqh" title="Documentation">📖</a> <a href="#design-wang1027-wqh" title="Design">🎨</a></td>
<td align="center"><a href="https://www.maxkey.top/"><img src="https://avatars.githubusercontent.com/u/1563377?v=4?s=100" width="100px;" alt="" /><br /><sub><b>MaxKey</b></sub></a><br /><a href="https://github.com/tomsun28/hertzbeat/commits?author=shimingxy" title="Code">💻</a> <a href="#design-shimingxy" title="Design">🎨</a> <a href="#ideas-shimingxy" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center"><a href="https://blog.gcdd.top/"><img src="https://avatars.githubusercontent.com/u/26523525?v=4?s=100" width="100px;" alt="" /><br /><sub><b>观沧海</b></sub></a><br /><a href="https://github.com/tomsun28/hertzbeat/commits?author=gcdd1993" title="Code">💻</a> <a href="#design-gcdd1993" title="Design">🎨</a> <a href="https://github.com/tomsun28/hertzbeat/issues?q=author%3Agcdd1993" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://github.com/a25017012"><img src="https://avatars.githubusercontent.com/u/32265356?v=4?s=100" width="100px;" alt="" /><br /><sub><b>yuye</b></sub></a><br /><a href="https://github.com/tomsun28/hertzbeat/commits?author=a25017012" title="Code">💻</a> <a href="https://github.com/tomsun28/hertzbeat/commits?author=a25017012" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/jx10086"><img src="https://avatars.githubusercontent.com/u/5323228?v=4?s=100" width="100px;" alt="" /><br /><sub><b>jx10086</b></sub></a><br /><a href="https://github.com/tomsun28/hertzbeat/commits?author=jx10086" title="Code">💻</a> <a href="https://github.com/tomsun28/hertzbeat/issues?q=author%3Ajx10086" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://github.com/winnerTimer"><img src="https://avatars.githubusercontent.com/u/76024658?v=4?s=100" width="100px;" alt="" /><br /><sub><b>winnerTimer</b></sub></a><br /><a href="https://github.com/tomsun28/hertzbeat/commits?author=winnerTimer" title="Code">💻</a> <a href="https://github.com/tomsun28/hertzbeat/issues?q=author%3AwinnerTimer" title="Bug reports">🐛</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/goo-kits"><img src="https://avatars.githubusercontent.com/u/13163673?v=4?s=100" width="100px;" alt=""/><br /><sub><b>goo-kits</b></sub></a><br /><a href="https://github.com/tomsun28/hertzbeat/commits?author=goo-kits" title="Code">💻</a> <a href="https://github.com/tomsun28/hertzbeat/issues?q=author%3Agoo-kits" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://github.com/brave4Time"><img src="https://avatars.githubusercontent.com/u/105094014?v=4?s=100" width="100px;" alt=""/><br /><sub><b>brave4Time</b></sub></a><br /><a href="https://github.com/tomsun28/hertzbeat/commits?author=brave4Time" title="Code">💻</a> <a href="https://github.com/tomsun28/hertzbeat/issues?q=author%3Abrave4Time" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://github.com/walkerlee-lab"><img src="https://avatars.githubusercontent.com/u/8426753?v=4?s=100" width="100px;" alt=""/><br /><sub><b>WalkerLee</b></sub></a><br /><a href="https://github.com/tomsun28/hertzbeat/commits?author=walkerlee-lab" title="Code">💻</a> <a href="https://github.com/tomsun28/hertzbeat/issues?q=author%3Awalkerlee-lab" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://github.com/fullofjoy"><img src="https://avatars.githubusercontent.com/u/30247571?v=4?s=100" width="100px;" alt=""/><br /><sub><b>jianghang</b></sub></a><br /><a href="https://github.com/tomsun28/hertzbeat/commits?author=fullofjoy" title="Code">💻</a> <a href="https://github.com/tomsun28/hertzbeat/issues?q=author%3Afullofjoy" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://github.com/ChineseTony"><img src="https://avatars.githubusercontent.com/u/24618786?v=4?s=100" width="100px;" alt=""/><br /><sub><b>ChineseTony</b></sub></a><br /><a href="https://github.com/tomsun28/hertzbeat/commits?author=ChineseTony" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/goo-kits"><img src="https://avatars.githubusercontent.com/u/13163673?v=4?s=100" width="100px;" alt="" /><br /><sub><b>goo-kits</b></sub></a><br /><a href="https://github.com/tomsun28/hertzbeat/commits?author=goo-kits" title="Code">💻</a> <a href="https://github.com/tomsun28/hertzbeat/issues?q=author%3Agoo-kits" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://github.com/brave4Time"><img src="https://avatars.githubusercontent.com/u/105094014?v=4?s=100" width="100px;" alt="" /><br /><sub><b>brave4Time</b></sub></a><br /><a href="https://github.com/tomsun28/hertzbeat/commits?author=brave4Time" title="Code">💻</a> <a href="https://github.com/tomsun28/hertzbeat/issues?q=author%3Abrave4Time" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://github.com/walkerlee-lab"><img src="https://avatars.githubusercontent.com/u/8426753?v=4?s=100" width="100px;" alt="" /><br /><sub><b>WalkerLee</b></sub></a><br /><a href="https://github.com/tomsun28/hertzbeat/commits?author=walkerlee-lab" title="Code">💻</a> <a href="https://github.com/tomsun28/hertzbeat/issues?q=author%3Awalkerlee-lab" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://github.com/fullofjoy"><img src="https://avatars.githubusercontent.com/u/30247571?v=4?s=100" width="100px;" alt="" /><br /><sub><b>jianghang</b></sub></a><br /><a href="https://github.com/tomsun28/hertzbeat/commits?author=fullofjoy" title="Code">💻</a> <a href="https://github.com/tomsun28/hertzbeat/issues?q=author%3Afullofjoy" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://github.com/ChineseTony"><img src="https://avatars.githubusercontent.com/u/24618786?v=4?s=100" width="100px;" alt="" /><br /><sub><b>ChineseTony</b></sub></a><br /><a href="https://github.com/tomsun28/hertzbeat/commits?author=ChineseTony" title="Code">💻</a></td>
</tr>
</table>
@@ -52,7 +52,7 @@ Bug fix.
5. [[collector]bugfix: fix warehouse data queue consume error #153](https://github.com/apache/hertzbeat/pull/153). issue by @daqianxiaoyao
6. [[web-app]bugfix:fix input blocking when input error in dark theme #157](https://github.com/apache/hertzbeat/pull/157). issue by @ConradWen
Online <https://console.tancloud.cn>.
Online: [tancloud](https://console.tancloud.cn)
-----------------------
@@ -69,5 +69,5 @@ Online <https://console.tancloud.cn>.
**Repository url**
[Github](https://github.com/apache/hertzbeat) <https://github.com/apache/hertzbeat>
[Gitee](https://gitee.com/hertzbeat/hertzbeat) <https://gitee.com/hertzbeat/hertzbeat>
[Github](https://github.com/apache/hertzbeat) [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)
[Gitee](https://gitee.com/hertzbeat/hertzbeat) [https://gitee.com/hertzbeat/hertzbeat](https://gitee.com/hertzbeat/hertzbeat)
+3 -3
View File
@@ -32,7 +32,7 @@ Bugfixes:
3. [[monitor] bugfix: Fix for Elasticsearch monitoring failure under basic authentication #174](https://github.com/apache/hertzbeat/pull/174) Contributed by @weifuqing
4. [Fix for monitoring failure due to ambiguous Oracle monitoring parameter "database name" #182](https://github.com/apache/hertzbeat/pull/182) @zklmcookle
Online at <https://console.tancloud.cn>.
Online at [https://console.tancloud.cn](https://console.tancloud.cn).
---
@@ -68,5 +68,5 @@ Have Fun!
**Repository Addresses**
[Github](https://github.com/apache/hertzbeat) <https://github.com/apache/hertzbeat>
[Gitee](https://gitee.com/hertzbeat/hertzbeat) <https://gitee.com/hertzbeat/hertzbeat>
[Github](https://github.com/apache/hertzbeat) [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)
[Gitee](https://gitee.com/hertzbeat/hertzbeat) [https://gitee.com/hertzbeat/hertzbeat](https://gitee.com/hertzbeat/hertzbeat)
+2 -2
View File
@@ -67,5 +67,5 @@ Have Fun!
**Repository Addresses**
[Github](https://github.com/apache/hertzbeat) <https://github.com/apache/hertzbeat>
[Gitee](https://gitee.com/hertzbeat/hertzbeat) <https://gitee.com/hertzbeat/hertzbeat>
[Github](https://github.com/apache/hertzbeat) [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)
[Gitee](https://gitee.com/hertzbeat/hertzbeat) [https://gitee.com/hertzbeat/hertzbeat](https://gitee.com/hertzbeat/hertzbeat)
+3 -3
View File
@@ -39,7 +39,7 @@ Bugfix.
8. [[manager] 修改监控页面取消监控功能再启动监控导致多生成jobId,原有监控项目并没有真实取消 #215](https://github.com/apache/hertzbeat/pull/215) contribute by @yangshihui
9. [[warehouse] bugfix exception when tdengine create table SQL contain special char #220](https://github.com/apache/hertzbeat/pull/220)
Online <https://console.tancloud.cn>.
Online [https://console.tancloud.cn](https://console.tancloud.cn).
Have Fun!
@@ -57,5 +57,5 @@ Have Fun!
**If you like HertzBeat, star us on GitHub**
[Github](https://github.com/apache/hertzbeat) <https://github.com/apache/hertzbeat>
[Gitee](https://gitee.com/hertzbeat/hertzbeat) <https://gitee.com/hertzbeat/hertzbeat>
[Github](https://github.com/apache/hertzbeat) [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)
[Gitee](https://gitee.com/hertzbeat/hertzbeat) [https://gitee.com/hertzbeat/hertzbeat](https://gitee.com/hertzbeat/hertzbeat)
+3 -3
View File
@@ -32,9 +32,9 @@ Bugfix.
1. [[docs] fix extend-http-jsonpath.md parseScript error #262](https://github.com/apache/hertzbeat/pull/262) contribute by @woshiniusange .
2. [[monitor] update help docs, refactor redis metrics name #264](https://github.com/apache/hertzbeat/pull/264)
3. [[manager] bugfix alert tags is null when tags map key normal value null. #270](https://github.com/apache/hertzbeat/pull/270) issue by <https://gitee.com/hello_brother_niu>
4. [[alert] bugfix: the alert global preset config do not take effect #275](https://github.com/apache/hertzbeat/pull/275) issue by <https://gitee.com/hello_brother_niu>
3. [[manager] bugfix alert tags is null when tags map key normal value null. #270](https://github.com/apache/hertzbeat/pull/270) issue by [https://gitee.com/hello_brother_niu](https://gitee.com/hello_brother_niu)
4. [[alert] bugfix: the alert global preset config do not take effect #275](https://github.com/apache/hertzbeat/pull/275) issue by [https://gitee.com/hello_brother_niu](https://gitee.com/hello_brother_niu)
Online <https://console.tancloud.cn>.
Online [https://console.tancloud.cn](https://console.tancloud.cn).
## Have Fun
+7 -7
View File
@@ -16,10 +16,10 @@ Today's article describes how to use hertzbeat monitoring system to detect the v
HertzBeat is a real-time monitoring tool with powerful customizable monitoring capabilities without the need for an agent. Website monitoring, PING connectivity, port availability, database, OS, middleware, API monitoring, threshold alerts, alert notifications (email weChat pinning flybook).
**Official website: <https://hertzbeat.apache.org> | <https://tancloud.cn>**
**Official website: [https://hertzbeat.apache.org](https://hertzbeat.apache.org) | [https://tancloud.cn](https://tancloud.cn)**
github: <https://github.com/apache/hertzbeat>
gitee: <https://gitee.com/hertzbeat/hertzbeat>
github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)
gitee: [https://gitee.com/hertzbeat/hertzbeat](https://gitee.com/hertzbeat/hertzbeat)
#### Install HertzBeat
@@ -86,8 +86,8 @@ gitee: <https://gitee.com/hertzbeat/hertzbeat>
You can refer to the help file for the token configuration of Nail WeChat Flying Book, etc.
<https://hertzbeat.apache.org/docs/help/alert_dingtalk>
<https://tancloud.cn/docs/help/alert_dingtalk>
[https://hertzbeat.apache.org/docs/help/alert_dingtalk](https://hertzbeat.apache.org/docs/help/alert_dingtalk)
[https://tancloud.cn/docs/help/alert_dingtalk](https://tancloud.cn/docs/help/alert_dingtalk)
> Alert Notification -> Add new alert notification policy -> Enable notification for the recipients you just configured
@@ -101,6 +101,6 @@ gitee: <https://gitee.com/hertzbeat/hertzbeat>
The practice of monitoring SSL certificates here, of course, for hertzbeat this function is just the tip of the iceberg, if you think hertzbeat this open source project is good if you welcome to give us in the GitHub Gitee star oh, thank you very much. Thank you for your support. The author!
**github: <https://github.com/apache/hertzbeat>**
**github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)**
**gitee: <https://gitee.com/hertzbeat/hertzbeat>**
**gitee: [https://gitee.com/hertzbeat/hertzbeat](https://gitee.com/hertzbeat/hertzbeat)**
+2 -2
View File
@@ -44,13 +44,13 @@ Bugfixes.
2. [[web-app] fix redirect when monitors app is null #286](https://github.com/apache/hertzbeat/pull/286)
3. [[alerter] bugfix aviator expression match npe #297](https://github.com/apache/hertzbeat/pull/297)
4. [[doc] fix project name error #294](https://github.com/apache/hertzbeat/pull/294) contributed by @CharlieXCL
5. [[common]feature:use "apache.http.conn.util" replace "sun.net.util" for upgrading java version #299](<https://github.com/dromara/> hertzbeat/pull/299) contributed by @Privauto
5. [[common]feature:use "apache.http.conn.util" replace "sun.net.util" for upgrading java version #299]([https://github.com/dromara/](https://github.com/dromara/) hertzbeat/pull/299) contributed by @Privauto
6. [Update docker-deploy.md #304](https://github.com/apache/hertzbeat/pull/304) contributed by @emrys-he
7. [fix(sec): upgrade snakeyaml to 1.31 #313](https://github.com/apache/hertzbeat/pull/313) contributed by @SxLiuYu
8. [[script] add startup log and optimize port service judgment #321](https://github.com/apache/hertzbeat/pull/321)
9. [[web-app] fix echarts y-axis value tip overflow #325](https://github.com/apache/hertzbeat/pull/325)
10. [[webapp] fix interceptor http resp common error-msg when error #329](https://github.com/apache/hertzbeat/pull/329)
Online <https://console.tancloud.cn>.
Online [https://console.tancloud.cn](https://console.tancloud.cn).
Have Fun!
+1 -1
View File
@@ -50,6 +50,6 @@ Bugfix.
6. [[manager] bugfix the gmtUpdate not change when update monitor param #459](https://github.com/apache/hertzbeat/pull/459)
7. [[home] fix typo in springboot2.md #464](https://github.com/apache/hertzbeat/pull/464) @eltociear
Online <https://console.tancloud.cn>.
Online [https://console.tancloud.cn](https://console.tancloud.cn).
Have Fun!
+1 -1
View File
@@ -56,7 +56,7 @@ github[wang1027-wqh](https://github.com/wang1027-wqh)
现从事:某互联网公司Java开发工程师
email<1758619238@qq.com>
email[1758619238@qq.com](mailto:1758619238@qq.com)
Hertzbeat Committer
+1 -1
View File
@@ -48,6 +48,6 @@ Bugfix.
7. [监控k8s问题issue描述与解决方案 #511](https://github.com/apache/hertzbeat/pull/511) @MrAndyMing
8. [[manager] springboot2 monitor support base path config #515](https://github.com/apache/hertzbeat/pull/515)
Online <https://console.tancloud.cn>.
Online [https://console.tancloud.cn](https://console.tancloud.cn).
Have Fun!
+5 -5
View File
@@ -40,7 +40,7 @@ tags: [opensource, practice]
- PROMETHEUS
```
2. Restart IoTDB, open a browser or use curl to access <http://ip:9091/metrics>, and you can see the metric data.
2. Restart IoTDB, open a browser or use curl to access [http://ip:9091/metrics](http://ip:9091/metrics), and you can see the metric data.
#### 2. Add IoTDB monitoring on the HertzBeat monitoring page
@@ -53,7 +53,7 @@ tags: [opensource, practice]
2. Configure the parameters required for monitoring IoTDB
Fill in the IoTDB **service IP** and **monitoring port** (default 9091) on the monitoring page, and finally click OK to add.
For other parameters such as **collection interval**, **timeout period**, etc., please refer to [Help Documentation](https://hertzbeat.apache.org/docs/help/iotdb/) <https://hertzbeat.apache.org/docs/help> /iotdb/
For other parameters such as **collection interval**, **timeout period**, etc., please refer to [Help Documentation](https://hertzbeat.apache.org/docs/help/iotdb/) [https://hertzbeat.apache.org/docs/help](https://hertzbeat.apache.org/docs/help) /iotdb/
![HertzBeat](/img/blog/monitor-iotdb-2.png)
@@ -95,7 +95,7 @@ tags: [opensource, practice]
Message notification methods support **email, DingTalk, WeChat Work, Feishu, WebHook, SMS**, etc. Here we take the commonly used DingTalk as an example.
- Refer to this [Help Documentation](https://hertzbeat.apache.org/docs/help/alert_dingtalk) <https://hertzbeat.apache.org/docs/help/alert_dingtalk> to configure the robot on DingTalk and set the security custom keyword `HertzBeat`, get the corresponding `access_token` value.
- Refer to this [Help Documentation](https://hertzbeat.apache.org/docs/help/alert_dingtalk) [https://hertzbeat.apache.org/docs/help/alert_dingtalk](https://hertzbeat.apache.org/docs/help/alert_dingtalk) to configure the robot on DingTalk and set the security custom keyword `HertzBeat`, get the corresponding `access_token` value.
- Configure the receiver parameters in HertzBeat as follows.
【Alarm Notification】->【New Recipient】->【Select DingTalk Robot Notification Method】->【Set DingTalk Robot ACCESS_TOKEN】->【OK】
@@ -122,8 +122,8 @@ Content details: The status of IOTDB node 127.0.0.1 is monitored as OFFLINE, ple
This practical article took us to experience that if HertzBeat is used to monitor the IoTDB database metric data, we can find that HertzBeat, which integrates monitoring-alarm-notification, is more convenient in operation and use, and IoTDB can be included in the monitoring with a simple click on the page, it is no longer necessary to deploy multiple components and write multiple YML configuration files with thresholds.
IoTDB Github: <https://github.com/apache/iotdb>
HertzBeat Github: <https://github.com/apache/hertzbeat>
IoTDB Github: [https://github.com/apache/iotdb](https://github.com/apache/iotdb)
HertzBeat Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)
**Welcome to learn about using Star Support!**
+9 -9
View File
@@ -42,11 +42,11 @@ tags: [opensource, practice]
1. Add the `metrics plugin` dependency to the `pom.xml` file of the gateway.
```xml
<dependency>
<groupId>org.apache.shenyu</groupId>
<artifactId>shenyu-spring-boot-starter-plugin-metrics</artifactId>
<version>${project.version}</version>
</dependency>
`<dependency>`
`<groupId>`org.apache.shenyu`</groupId>`
`<artifactId>`shenyu-spring-boot-starter-plugin-metrics`</artifactId>`
`<version>`${project.version}`</version>`
`</dependency>`
```
2. `metric` plugin Capture is turned off by default, edit the following in the gateway's configuration `yaml` file:
@@ -76,7 +76,7 @@ tags: [opensource, practice]
2. Configure the parameters required for monitoring ShenYu
On the monitor page, fill in ShenYu **service IP**, **monitor port** (default 8090), and click OK to add.
For other parameters such as **collection interval**, **timeout**, etc., you can refer to the [help file](https://hertzbeat.apache.org/docs/help/shenyu/) <https://hertzbeat.apache.org/docs/help/shenyu/>
For other parameters such as **collection interval**, **timeout**, etc., you can refer to the [help file](https://hertzbeat.apache.org/docs/help/shenyu/) [https://hertzbeat.apache.org/docs/help/shenyu/](https://hertzbeat.apache.org/docs/help/shenyu/)
![HertzBeat](/img/blog/monitor-shenyu-1.png)
@@ -125,7 +125,7 @@ Of course, just looking at it is not perfect, monitoring is often accompanied by
Message notification methods support **Email, Nail, WeChat, Flybook, WebHook, SMS**, etc. Here we take the commonly used Nail as an example.
- Refer to this [help document](https://hertzbeat.apache.org/docs/help/alert_dingtalk) <https://hertzbeat.apache.org/docs/help/alert_dingtalk> Configure the bot on the pinning side, set the security customization keyword `HertzBeat`, get the corresponding `access_token` value.
- Refer to this [help document](https://hertzbeat.apache.org/docs/help/alert_dingtalk) [https://hertzbeat.apache.org/docs/help/alert_dingtalk](https://hertzbeat.apache.org/docs/help/alert_dingtalk) Configure the bot on the pinning side, set the security customization keyword `HertzBeat`, get the corresponding `access_token` value.
- Configure the recipient parameters in HertzBeat as follows.
[Alert Notification] -> [Add Recipient] -> [Select Nailed Bot Notification Method] -> [Set Nailed Bot ACCESS_TOKEN] -> [OK]
@@ -156,8 +156,8 @@ Details : Please note that the number of file descriptors opened by ⚠️ ShenY
This hands-on article takes us through how to use HertzBeat to monitor Apache ShenYu metrics data, and we can find that HertzBeat, which combines ``Monitoring-Alert-Notification``, is much more convenient to operate and use, and you can include ShenYu in the monitoring by simply clicking on a page. There is no need to deploy multiple components and write multiple YML configuration files.
:::
Apache ShenYu Github: <https://github.com/apache/shenyu>
HertzBeat Github: <https://github.com/apache/hertzbeat>
Apache ShenYu Github: [https://github.com/apache/shenyu](https://github.com/apache/shenyu)
HertzBeat Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)
**Welcome to learn about using Star Support Oh!**
+4 -4
View File
@@ -88,7 +88,7 @@ tags: [opensource, practice]
2. Configure the parameters required for monitoring DynamicTp.
On the monitor page, fill in DynamicTp **service IP**, **monitoring port** (default 8080), and finally click OK to add it.
For other parameters such as **collection interval**, **timeout**, etc., you can refer to [help](https://hertzbeat.apache.org/docs/help/dynamic_tp/) <https://hertzbeat.apache.org/docs/help/dynamic_tp/>
For other parameters such as **collection interval**, **timeout**, etc., you can refer to [help](https://hertzbeat.apache.org/docs/help/dynamic_tp/) [https://hertzbeat.apache.org/docs/help/dynamic_tp/](https://hertzbeat.apache.org/docs/help/dynamic_tp/)
![HertzBeat](/img/blog/monitor-dynamic-tp-2.png)
@@ -137,7 +137,7 @@ Of course, just watching is not perfect, monitoring is often accompanied by alar
Message notification methods support **Email, Dingtalk, WeChat, Flybook, WebHook, SMS**, etc. We take the commonly used Dingtalk as an example.
- Refer to this [help document](https://hertzbeat.apache.org/docs/help/alert_dingtalk) <https://hertzbeat.apache.org/docs/help/alert_dingtalk> Configure the bot on Dingtalk side, set the security customization keyword `HertzBeat`, get the corresponding `access_token` value.
- Refer to this [help document](https://hertzbeat.apache.org/docs/help/alert_dingtalk) [https://hertzbeat.apache.org/docs/help/alert_dingtalk](https://hertzbeat.apache.org/docs/help/alert_dingtalk) Configure the bot on Dingtalk side, set the security customization keyword `HertzBeat`, get the corresponding `access_token` value.
- Configure the recipient parameters in HertzBeat as follows.
[Alert Notification] -> [Add Recipient] -> [Choose Dingtalk bot notification method] -> [Set Dingtalk bot ACCESS_TOKEN] -> [OK]
@@ -168,8 +168,8 @@ Details : DynamicTp has run timeout thread, count is 2
This practical article takes us to experience how to use HertzBeat to monitor DynamicTp thread pool metrics data, and we can find that HertzBeat with ``monitoring-alerting-notification`` is much more convenient to operate and use, and you only need to point and click on a page to include DynamicTp thread pool into the monitoring and alert notification, and you don't need to deploy multiple components to write YML configuration files anymore. There is no need to deploy multiple components and write YML configuration files.
:::
DynamicTp Github: <https://github.com/dromara/dynamic-tp>
HertzBeat Github: <https://github.com/apache/hertzbeat>
DynamicTp Github: [https://github.com/dromara/dynamic-tp](https://github.com/dromara/dynamic-tp)
HertzBeat Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)
**Welcome to learn how to use Star Support!**
+2 -2
View File
@@ -112,8 +112,8 @@ First of all, I am also a newcomer to Novice Village, but I can share some of my
>
> The powerful customization of `HertzBeat`, multi-type support, easy expansion, and low coupling, hope to help developers and small and medium-sized teams quickly build their own monitoring tools.
**Github: <https://github.com/apache/hertzbeat>**
**Gitee: <https://gitee.com/hertzbeat/hertzbeat>**
**Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)**
**Gitee: [https://gitee.com/hertzbeat/hertzbeat](https://gitee.com/hertzbeat/hertzbeat)**
## ⛄ Supported
+4 -4
View File
@@ -39,7 +39,7 @@ Keywords: [Open source monitoring tool, open source database monitoring, Mysql d
2. Configure the parameters required for the new monitoring Mysql database
On the monitoring page, fill in Mysql **service IP**, **monitoring port** (default 3306), **account password, etc.**, and finally click OK to add.
For other parameters such as **collection interval**, **timeout period**, etc., please refer to [Help Documentation](https://hertzbeat.apache.org/docs/help/mysql/) <https://hertzbeat.apache.org/docs/help> /mysql/
For other parameters such as **collection interval**, **timeout period**, etc., please refer to [Help Documentation](https://hertzbeat.apache.org/docs/help/mysql/) [https://hertzbeat.apache.org/docs/help](https://hertzbeat.apache.org/docs/help) /mysql/
![HertzBeat](/img/blog/monitor-mysql-2.png)
@@ -87,7 +87,7 @@ Of course, just looking at it is definitely not perfect. Monitoring is often acc
Message notification methods support **email, DingTalk, WeChat Work, Feishu, WebHook, SMS**, etc. Here we take the commonly used DingTalk as an example.
- Refer to this [Help Documentation](https://hertzbeat.apache.org/docs/help/alert_dingtalk) <https://hertzbeat.apache.org/docs/help/alert_dingtalk> to configure the robot on DingTalk and set the security custom keyword `HertzBeat`, get the corresponding `access_token` value.
- Refer to this [Help Documentation](https://hertzbeat.apache.org/docs/help/alert_dingtalk) [https://hertzbeat.apache.org/docs/help/alert_dingtalk](https://hertzbeat.apache.org/docs/help/alert_dingtalk) to configure the robot on DingTalk and set the security custom keyword `HertzBeat`, get the corresponding `access_token` value.
- Configure the receiver parameters in HertzBeat as follows.
【Alarm Notification】->【New Recipient】->【Select DingTalk Robot Notification Method】->【Set DingTalk Robot ACCESS_TOKEN】->【OK】
@@ -118,8 +118,8 @@ Content details: mysql db query_cache_hit_rate is too low, now is 20.
This practical article took us to experience how to use the open source real-time monitoring tool HertzBeat to monitor Mysql database metric data. We can find that HertzBeat, which integrates `monitoring-alarm-notification`, is more convenient in operation and use, just click on the page The Mysql database can be included in the monitoring and alarm notification, and the tedious operations of deploying multiple components and writing configuration files are no longer needed.
:::
Mysql Github: <https://github.com/mysql/mysql-server>
HertzBeat Github: <https://github.com/apache/hertzbeat>
Mysql Github: [https://github.com/mysql/mysql-server](https://github.com/mysql/mysql-server)
HertzBeat Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)
**Welcome to learn, use and star!**
+5 -5
View File
@@ -17,7 +17,7 @@ keywords: [Open source monitoring tool, operating system monitoring, Linux monit
- It configurable protocol specifications such as Http, Jmx, Ssh, Snmp, Jdbc, Prometheus, etc. You only need to configure YML to use these protocols to customize and collect any metrics you want to collect. Do you believe that you can immediately adapt to a new monitoring type such as K8s or Docker just by configuring YML?
- HertzBeat's powerful customization, multi-type support, easy expansion, and low coupling, hope to help developers and small and medium teams quickly build their own monitoring tools.
Github: <https://github.com/apache/hertzbeat>
Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)
### Get Linux Monitoring Done in HertzBeat in 5 Minutes
@@ -36,7 +36,7 @@ Github: <https://github.com/apache/hertzbeat>
2. Configure the parameters required for new monitoring Linux
Fill in the Linux **peer IP**, **SSH port** (default 22), **account password, etc.** on the monitoring page, and finally click OK to add.
For other parameters such as **collection interval**, **timeout period**, etc., please refer to the help document <https://hertzbeat.apache.org/docs/help/mysql/>
For other parameters such as **collection interval**, **timeout period**, etc., please refer to the help document [https://hertzbeat.apache.org/docs/help/mysql/](https://hertzbeat.apache.org/docs/help/mysql/)
![HertzBeat](/img/blog/monitor-linux-2.png)
@@ -88,7 +88,7 @@ Of course, just looking at it is definitely not perfect. Monitoring is often acc
Message notification methods support **email, DingTalk, WeChat Work, Feishu, WebHook, SMS**, etc. Here we take the commonly used DingTalk as an example.
- Refer to this [Help Documentation](https://hertzbeat.apache.org/docs/help/alert_dingtalk) <https://hertzbeat.apache.org/docs/help/alert_dingtalk> to configure the robot on DingTalk and set the security custom keyword `HertzBeat`, get the corresponding `access_token` value.
- Refer to this [Help Documentation](https://hertzbeat.apache.org/docs/help/alert_dingtalk) [https://hertzbeat.apache.org/docs/help/alert_dingtalk](https://hertzbeat.apache.org/docs/help/alert_dingtalk) to configure the robot on DingTalk and set the security custom keyword `HertzBeat`, get the corresponding `access_token` value.
- Configure the receiver parameters in HertzBeat as follows.
【Alarm Notification】->【New Recipient】->【Select DingTalk Robot Notification Method】->【Set DingTalk Robot ACCESS_TOKEN】->【OK】
@@ -132,8 +132,8 @@ This practical article took us to experience how to use the open source real-tim
>
> The powerful customization of `HertzBeat`, multi-type support, easy expansion, and low coupling, hope to help developers and small and medium-sized teams quickly build their own monitoring tools.
**Github: <https://github.com/apache/hertzbeat>**
**Gitee: <https://gitee.com/hertzbeat/hertzbeat>**
**Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)**
**Gitee: [https://gitee.com/hertzbeat/hertzbeat](https://gitee.com/hertzbeat/hertzbeat)**
## ⛄ Supported
+4 -4
View File
@@ -21,9 +21,9 @@ Website: hertzbeat.com | tancloud.cn
>
> Do you believe that you can immediately adapt a new monitoring type such as K8s or Docker just by defining YML?
**Github: <https://github.com/apache/hertzbeat>**
**Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)**
**Gitee: <https://gitee.com/hertzbeat/hertzbeat>**
**Gitee: [https://gitee.com/hertzbeat/hertzbeat](https://gitee.com/hertzbeat/hertzbeat)**
### v1.3.0 release is here
@@ -86,5 +86,5 @@ COMMIT;
---
**Github: <https://github.com/apache/hertzbeat>**
**Gitee: <https://gitee.com/hertzbeat/hertzbeat>**
**Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)**
**Gitee: [https://gitee.com/hertzbeat/hertzbeat](https://gitee.com/hertzbeat/hertzbeat)**
+5 -5
View File
@@ -21,7 +21,7 @@ keywords: [opensource monitoring, SpringBoot monitoring, alert]
>
> `HertzBeat`'s powerful custom-define, multi-type support, easy expansion, low coupling, hope to help developers and micro teams to quickly build their own monitoring system.
Github: <https://github.com/apache/hertzbeat>
Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)
### Monitoring SpringBoot2 Metrics with HertzBeat in 5 minutes
@@ -93,7 +93,7 @@ Github: <https://github.com/apache/hertzbeat>
2. Configure the parameters required for new monitoring SpringBoot2
Fill in the SpringBoot2 application **peer IP**, **service port** (default 8080), **account password, etc.** on the monitoring page, and finally click OK to add.
For other parameters such as **collection interval**, **timeout period**, etc., please refer to the help document <https://hertzbeat.apache.org/docs/help/>
For other parameters such as **collection interval**, **timeout period**, etc., please refer to the help document [https://hertzbeat.apache.org/docs/help/](https://hertzbeat.apache.org/docs/help/)
![HertzBeat](/img/blog/monitor-springboot2-2.png)
@@ -141,7 +141,7 @@ Of course, it is impossible to manually check the metrics in real time. Monitori
Message notification methods support **email, DingTalk, WeChat Work, Feishu, WebHook, SMS**, etc. Here we take the commonly used DingTalk as an example.
- Refer to this [Help Documentation](https://hertzbeat.apache.org/docs/help/alert_dingtalk) <https://hertzbeat.apache.org/docs/help/alert_dingtalk> to configure the robot on DingTalk and set the security custom keyword `HertzBeat`, get the corresponding `access_token` value.
- Refer to this [Help Documentation](https://hertzbeat.apache.org/docs/help/alert_dingtalk) [https://hertzbeat.apache.org/docs/help/alert_dingtalk](https://hertzbeat.apache.org/docs/help/alert_dingtalk) to configure the robot on DingTalk and set the security custom keyword `HertzBeat`, get the corresponding `access_token` value.
- Configure the receiver parameters in HertzBeat as follows.
【Alarm Notification】->【New Recipient】->【Select DingTalk Robot Notification Method】->【Set DingTalk Robot ACCESS_TOKEN】->【OK】
@@ -208,5 +208,5 @@ This practical article took us to experience how to use the open source real-tim
----
**Github: <https://github.com/apache/hertzbeat>**
**Gitee: <https://gitee.com/hertzbeat/hertzbeat>**
**Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)**
**Gitee: [https://gitee.com/hertzbeat/hertzbeat](https://gitee.com/hertzbeat/hertzbeat)**
+4 -4
View File
@@ -24,9 +24,9 @@ Website: hertzbeat.com | tancloud.cn
> `HertzBeat`'s powerful custom-define, multi-type support, easy expansion, low coupling, hope to help developers and micro teams to quickly build their own monitoring system.
> We also provide **[Monitoring SaaS Cloud](https://console.tancloud.cn)**, users no longer need to deploy a cumbersome monitoring system in order to monitor resources. **[Get started for free](https://console.tancloud.cn)**.
**Github: <https://github.com/apache/hertzbeat>**
**Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)**
**Gitee: <https://gitee.com/hertzbeat/hertzbeat>**
**Gitee: [https://gitee.com/hertzbeat/hertzbeat](https://gitee.com/hertzbeat/hertzbeat)**
### v1.3.1 release is here
@@ -66,5 +66,5 @@ COMMIT;
---
**Github: <https://github.com/apache/hertzbeat>**
**Gitee: <https://gitee.com/hertzbeat/hertzbeat>**
**Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)**
**Gitee: [https://gitee.com/hertzbeat/hertzbeat](https://gitee.com/hertzbeat/hertzbeat)**
+5 -5
View File
@@ -75,9 +75,9 @@ See the [official documentation](https://hertzbeat.apache.org/zh-cn/docs/start/d
- `-v /opt/application.yml:/opt/hertzbeat/config/application.yml` : Mount customized local configuration files to the container, i.e. use local configuration files to overwrite the container configuration files.
Note that the ⚠️ local mount configuration file `application.yml` needs to exist in advance, and the full contents of the file can be found in the project repository [/script/application.yml](<https://github.com/apache/hertzbeat/raw/master/script/> application.yml)
Note that the ⚠️ local mount configuration file `application.yml` needs to exist in advance, and the full contents of the file can be found in the project repository [/script/application.yml]([https://github.com/apache/hertzbeat/raw/master/script/](https://github.com/apache/hertzbeat/raw/master/script/) application.yml)
2. Go to <http://ip:1157/> with the default account and password admin/hertzbeat to see if HertzBeat starts successfully.
2. Go to [http://ip:1157/](http://ip:1157/) with the default account and password admin/hertzbeat to see if HertzBeat starts successfully.
#### Configure to use GreptimeDB to store HertzBeat monitoring metrics metrics data
@@ -105,7 +105,7 @@ See the [official documentation](https://hertzbeat.apache.org/zh-cn/docs/start/d
#### Observe the authentication effect
1. visit HertzBeat in your browser <http://ip:1157/> default account password admin/hertzbeat
1. visit HertzBeat in your browser [http://ip:1157/](http://ip:1157/) default account password admin/hertzbeat
2. Use HertzBeat to add application monitors, such as website monitors, Linux monitors, Mysql monitors, and so on.
3. After monitoring and collecting several cycles, check whether GreptimeDB database stores the metrics data and whether HertzBeat metrics data graph data is displayed normally.
@@ -122,8 +122,8 @@ Here's the picture: !
This article took us to experience how to use the open source time-series database GreptimeDB to store the metrics data of the open source real-time monitoring HertzBeat, in general, the two open source products is very simple to get started, the key is that if it is too much trouble do not want to deploy both of them still have cloud services 😂 let you toss.
As one of the developers of the feature [HertzBeat supports GreptimeDB](https://github.com/apache/hertzbeat/pull/834), in the actual adaptation process, GreptimeDB's silky-smooth native SDK and relational database-like SQL, let us from other GreptimeDB native SDK and relational database-like SQL make it very easy to switch from other time-series databases like `TDengine, IotDB, InfluxDB` to GreptimeDB, and the experience is very smooth.
GreptimeDB Github: <https://github.com/GreptimeTeam/greptimedb>
HertzBeat Github: <https://github.com/apache/hertzbeat>
GreptimeDB Github: [https://github.com/GreptimeTeam/greptimedb](https://github.com/GreptimeTeam/greptimedb)
HertzBeat Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)
**Finally, you are welcome to be more understanding, more use, more comments, more ISSUE, more PR, more Star support these two did not come out for a long time hope to get care of open source cattle are not afraid of difficulties a small star oh! Do open source, we are sincere, love 💗**
+4 -4
View File
@@ -24,9 +24,9 @@ Website: hertzbeat.com | tancloud.cn
> `HertzBeat`'s powerful custom-define, multi-type support, easy expansion, low coupling, hope to help developers and micro teams to quickly build their own monitoring system.
> We also provide **[Monitoring SaaS Cloud](https://console.tancloud.cn)**, users no longer need to deploy a cumbersome monitoring system in order to monitor resources. **[Get started for free](https://console.tancloud.cn)**.
**Github: <https://github.com/apache/hertzbeat>**
**Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)**
**Gitee: <https://gitee.com/hertzbeat/hertzbeat>**
**Gitee: [https://gitee.com/hertzbeat/hertzbeat](https://gitee.com/hertzbeat/hertzbeat)**
### v1.3.2
@@ -92,5 +92,5 @@ spring:
---
**Github: <https://github.com/apache/hertzbeat>**
**Gitee: <https://gitee.com/hertzbeat/hertzbeat>**
**Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)**
**Gitee: [https://gitee.com/hertzbeat/hertzbeat](https://gitee.com/hertzbeat/hertzbeat)**
+51 -51
View File
@@ -25,9 +25,9 @@ keywords: [open source monitoring system, alerting system, Linux monitoring]
![HertzBeat](/img/docs/hertzbeat-arch.png)
**Github: <https://github.com/apache/hertzbeat>**
**Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)**
**Gitee: <https://gitee.com/hertzbeat/hertzbeat>**
**Gitee: [https://gitee.com/hertzbeat/hertzbeat](https://gitee.com/hertzbeat/hertzbeat)**
### The cluster version is coming
@@ -100,53 +100,53 @@ Detailed config refer to [Install HertzBeat via Docker](https://hertzbeat.apache
> Welcome to explore more new version updates, thanks to the hard work of the community partners, love 💗!
* [doc] add v1.3.2 publish doc by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1075>
* remove elasticsearch unused param index by @Ceilzcx in <https://github.com/apache/hertzbeat/pull/1080>
* feature support monitoring apache airflow by @luoxuanzao in <https://github.com/apache/hertzbeat/pull/1081>
* add luoxuanzao as a contributor for code by @allcontributors in <https://github.com/apache/hertzbeat/pull/1083>
* [collector] bugfix sshd cannot use private key to connect by @gcdd1993 in <https://github.com/apache/hertzbeat/pull/1084>
* bugfix update dashboard alerts cards height not consist by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1087>
* Feature#serverchan by @zqr10159 in <https://github.com/apache/hertzbeat/pull/1092>
* bugfix dm database monitoring connect error by @lisongning in <https://github.com/apache/hertzbeat/pull/1094>
* add lisongning as a contributor for code by @allcontributors in <https://github.com/apache/hertzbeat/pull/1096>
* update alert rule operator display "<=" to ">=" by @Ceilzcx in <https://github.com/apache/hertzbeat/pull/1097>
* [doc] add custom monitoring relate document by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1098>
* add YutingNie as a contributor for code by @allcontributors in <https://github.com/apache/hertzbeat/pull/1103>
* Remove unreachable status by @YutingNie in <https://github.com/apache/hertzbeat/pull/1102>
* 139 auto update alert status by @l646505418 in <https://github.com/apache/hertzbeat/pull/1104>
* feat: aviator fn for str contains, exists & matches by @mikezzb in <https://github.com/apache/hertzbeat/pull/1106>
* add mikezzb as a contributor for code by @allcontributors in <https://github.com/apache/hertzbeat/pull/1107>
* bugfix common alarm do not need monitorId tag existed by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1108>
* bugfix extern alert do not have labels mapping inner monitor by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1111>
* feature: support apache spark metrics monitoring by @a-little-fool in <https://github.com/apache/hertzbeat/pull/1114>
* add a-little-fool as a contributor for code by @allcontributors in <https://github.com/apache/hertzbeat/pull/1116>
* [Feature]Add third report of TenCloud by @zqr10159 in <https://github.com/apache/hertzbeat/pull/1113>
* [Feature]Add third report of TenCloud (#1113) by @zqr10159 in <https://github.com/apache/hertzbeat/pull/1119>
* [manager] fix: can query by tags when tagValue is null by @l646505418 in <https://github.com/apache/hertzbeat/pull/1118>
* bugfix the notification template environment variable display error by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1120>
* add littlezhongzer as a contributor for code by @allcontributors in <https://github.com/apache/hertzbeat/pull/1127>
* feature:monitor brearer token api, ignore letter case to comparison by @littlezhongzer in <https://github.com/apache/hertzbeat/pull/1122>
* docs: enhance README by @mikezzb in <https://github.com/apache/hertzbeat/pull/1128>
* Update app-oracle.yml by @ChenXiangxxxxx in <https://github.com/apache/hertzbeat/pull/1129>
* add ChenXiangxxxxx as a contributor for code by @allcontributors in <https://github.com/apache/hertzbeat/pull/1130>
* fix alarm silence strategy setting failed by @Ceilzcx in <https://github.com/apache/hertzbeat/pull/1131>
* support run sql script file in jdbc protocol config by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1117>
* bugfix return old cache json file when upgrade version by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1137>
* support ssh protocol config choose if reuse connection by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1136>
* feat(web): alert threshold UI support matches & contains by @mikezzb in <https://github.com/apache/hertzbeat/pull/1138>
* support hertzbeat metrics collector cluster by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1101>
* add collector card in dashboard by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1147>
* bugfix: linux collect warning: bad syntax, perhaps a bogus '-' by @Mr-zhou315 in <https://github.com/apache/hertzbeat/pull/1151>
* add Mr-zhou315 as a contributor for code by @allcontributors in <https://github.com/apache/hertzbeat/pull/1157>
* support config timezone locale language region on web ui by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1154>
* bugfix monitoring template app name already exists by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1152>
* bugfix can not startup when error monitoring template yml file by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1153>
* tags also deleted when the monitor is deleted by @Ceilzcx in <https://github.com/apache/hertzbeat/pull/1159>
* monitoring param host with http head will not be error reported by @littlezhongzer in <https://github.com/apache/hertzbeat/pull/1155>
* [script] feature update build.sh and Dockerfile: detect app version a… by @XimfengYao in <https://github.com/apache/hertzbeat/pull/1162>
* add XimfengYao as a contributor for code by @allcontributors in <https://github.com/apache/hertzbeat/pull/1163>
* [doc] add collector clusters document by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1161>
* [hertzbeat] release hertzbeat version v1.4.0 by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1168>
* [doc] add v1.3.2 publish doc by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1075](https://github.com/apache/hertzbeat/pull/1075)
* remove elasticsearch unused param index by @Ceilzcx in [https://github.com/apache/hertzbeat/pull/1080](https://github.com/apache/hertzbeat/pull/1080)
* feature support monitoring apache airflow by @luoxuanzao in [https://github.com/apache/hertzbeat/pull/1081](https://github.com/apache/hertzbeat/pull/1081)
* add luoxuanzao as a contributor for code by @allcontributors in [https://github.com/apache/hertzbeat/pull/1083](https://github.com/apache/hertzbeat/pull/1083)
* [collector] bugfix sshd cannot use private key to connect by @gcdd1993 in [https://github.com/apache/hertzbeat/pull/1084](https://github.com/apache/hertzbeat/pull/1084)
* bugfix update dashboard alerts cards height not consist by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1087](https://github.com/apache/hertzbeat/pull/1087)
* Feature#serverchan by @zqr10159 in [https://github.com/apache/hertzbeat/pull/1092](https://github.com/apache/hertzbeat/pull/1092)
* bugfix dm database monitoring connect error by @lisongning in [https://github.com/apache/hertzbeat/pull/1094](https://github.com/apache/hertzbeat/pull/1094)
* add lisongning as a contributor for code by @allcontributors in [https://github.com/apache/hertzbeat/pull/1096](https://github.com/apache/hertzbeat/pull/1096)
* update alert rule operator display "\<=" to "\>=" by @Ceilzcx in [https://github.com/apache/hertzbeat/pull/1097](https://github.com/apache/hertzbeat/pull/1097)
* [doc] add custom monitoring relate document by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1098](https://github.com/apache/hertzbeat/pull/1098)
* add YutingNie as a contributor for code by @allcontributors in [https://github.com/apache/hertzbeat/pull/1103](https://github.com/apache/hertzbeat/pull/1103)
* Remove unreachable status by @YutingNie in [https://github.com/apache/hertzbeat/pull/1102](https://github.com/apache/hertzbeat/pull/1102)
* 139 auto update alert status by @l646505418 in [https://github.com/apache/hertzbeat/pull/1104](https://github.com/apache/hertzbeat/pull/1104)
* feat: aviator fn for str contains, exists & matches by @mikezzb in [https://github.com/apache/hertzbeat/pull/1106](https://github.com/apache/hertzbeat/pull/1106)
* add mikezzb as a contributor for code by @allcontributors in [https://github.com/apache/hertzbeat/pull/1107](https://github.com/apache/hertzbeat/pull/1107)
* bugfix common alarm do not need monitorId tag existed by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1108](https://github.com/apache/hertzbeat/pull/1108)
* bugfix extern alert do not have labels mapping inner monitor by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1111](https://github.com/apache/hertzbeat/pull/1111)
* feature: support apache spark metrics monitoring by @a-little-fool in [https://github.com/apache/hertzbeat/pull/1114](https://github.com/apache/hertzbeat/pull/1114)
* add a-little-fool as a contributor for code by @allcontributors in [https://github.com/apache/hertzbeat/pull/1116](https://github.com/apache/hertzbeat/pull/1116)
* [Feature]Add third report of TenCloud by @zqr10159 in [https://github.com/apache/hertzbeat/pull/1113](https://github.com/apache/hertzbeat/pull/1113)
* [Feature]Add third report of TenCloud (#1113) by @zqr10159 in [https://github.com/apache/hertzbeat/pull/1119](https://github.com/apache/hertzbeat/pull/1119)
* [manager] fix: can query by tags when tagValue is null by @l646505418 in [https://github.com/apache/hertzbeat/pull/1118](https://github.com/apache/hertzbeat/pull/1118)
* bugfix the notification template environment variable display error by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1120](https://github.com/apache/hertzbeat/pull/1120)
* add littlezhongzer as a contributor for code by @allcontributors in [https://github.com/apache/hertzbeat/pull/1127](https://github.com/apache/hertzbeat/pull/1127)
* feature:monitor brearer token api, ignore letter case to comparison by @littlezhongzer in [https://github.com/apache/hertzbeat/pull/1122](https://github.com/apache/hertzbeat/pull/1122)
* docs: enhance README by @mikezzb in [https://github.com/apache/hertzbeat/pull/1128](https://github.com/apache/hertzbeat/pull/1128)
* Update app-oracle.yml by @ChenXiangxxxxx in [https://github.com/apache/hertzbeat/pull/1129](https://github.com/apache/hertzbeat/pull/1129)
* add ChenXiangxxxxx as a contributor for code by @allcontributors in [https://github.com/apache/hertzbeat/pull/1130](https://github.com/apache/hertzbeat/pull/1130)
* fix alarm silence strategy setting failed by @Ceilzcx in [https://github.com/apache/hertzbeat/pull/1131](https://github.com/apache/hertzbeat/pull/1131)
* support run sql script file in jdbc protocol config by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1117](https://github.com/apache/hertzbeat/pull/1117)
* bugfix return old cache json file when upgrade version by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1137](https://github.com/apache/hertzbeat/pull/1137)
* support ssh protocol config choose if reuse connection by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1136](https://github.com/apache/hertzbeat/pull/1136)
* feat(web): alert threshold UI support matches & contains by @mikezzb in [https://github.com/apache/hertzbeat/pull/1138](https://github.com/apache/hertzbeat/pull/1138)
* support hertzbeat metrics collector cluster by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1101](https://github.com/apache/hertzbeat/pull/1101)
* add collector card in dashboard by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1147](https://github.com/apache/hertzbeat/pull/1147)
* bugfix: linux collect warning: bad syntax, perhaps a bogus '-' by @Mr-zhou315 in [https://github.com/apache/hertzbeat/pull/1151](https://github.com/apache/hertzbeat/pull/1151)
* add Mr-zhou315 as a contributor for code by @allcontributors in [https://github.com/apache/hertzbeat/pull/1157](https://github.com/apache/hertzbeat/pull/1157)
* support config timezone locale language region on web ui by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1154](https://github.com/apache/hertzbeat/pull/1154)
* bugfix monitoring template app name already exists by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1152](https://github.com/apache/hertzbeat/pull/1152)
* bugfix can not startup when error monitoring template yml file by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1153](https://github.com/apache/hertzbeat/pull/1153)
* tags also deleted when the monitor is deleted by @Ceilzcx in [https://github.com/apache/hertzbeat/pull/1159](https://github.com/apache/hertzbeat/pull/1159)
* monitoring param host with http head will not be error reported by @littlezhongzer in [https://github.com/apache/hertzbeat/pull/1155](https://github.com/apache/hertzbeat/pull/1155)
* [script] feature update build.sh and Dockerfile: detect app version a… by @XimfengYao in [https://github.com/apache/hertzbeat/pull/1162](https://github.com/apache/hertzbeat/pull/1162)
* add XimfengYao as a contributor for code by @allcontributors in [https://github.com/apache/hertzbeat/pull/1163](https://github.com/apache/hertzbeat/pull/1163)
* [doc] add collector clusters document by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1161](https://github.com/apache/hertzbeat/pull/1161)
* [hertzbeat] release hertzbeat version v1.4.0 by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1168](https://github.com/apache/hertzbeat/pull/1168)
---
@@ -163,5 +163,5 @@ Detailed config refer to [Install HertzBeat via Docker](https://hertzbeat.apache
---
**Github: <https://github.com/apache/hertzbeat>**
**Gitee: <https://gitee.com/hertzbeat/hertzbeat>**
**Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)**
**Gitee: [https://gitee.com/hertzbeat/hertzbeat](https://gitee.com/hertzbeat/hertzbeat)**
+1 -1
View File
@@ -84,6 +84,6 @@ HertzBeat HertzBeat is an open source real-time monitoring and alerting system w
> `HertzBeat`'s powerful customization, multi-type support, high performance, easy to extend, low-coupling, and hopefully can help developers and teams to quickly build their own monitoring system.
Github: <https://github.com/apache/hertzbeat>
Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)
More users are welcome to participate in `HertzBeat` open source collaboration, no matter a typo or punctuation we are very welcome.
+56 -56
View File
@@ -25,9 +25,9 @@ keywords: [open source monitoring system, alerting system, Linux monitoring]
![HertzBeat](/img/docs/hertzbeat-arch.png)
**Github: <https://github.com/apache/hertzbeat>**
**Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)**
**Gitee: <https://gitee.com/hertzbeat/hertzbeat>**
**Gitee: [https://gitee.com/hertzbeat/hertzbeat](https://gitee.com/hertzbeat/hertzbeat)**
### HertzBeat's 1.4.1 version is coming
@@ -83,58 +83,58 @@ Detailed config refer to [Install HertzBeat via Docker](https://hertzbeat.apache
> Welcome to explore more new version updates, thanks to the hard work of the community partners, love 💗!
* bugfix npe when get undefined name monitor template yml by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1173>
* [bug fixed]When importing and exporting monitoring, support export collectors, configure collectors when importing by @zqr10159 in <https://github.com/apache/hertzbeat/pull/1178>
* support alert threshold rule config system value row count by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1180>
* Update README.md by @zqr10159 in <https://github.com/apache/hertzbeat/pull/1182>
* support config alert threshold tags bind by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1181>
* the back-end of help component has been built by @YutingNie in <https://github.com/apache/hertzbeat/pull/1160>
* support enable alert threshold auto resolved notice by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1185>
* Delete tag of the dashboard's homepage on the top four pages by @Ceilzcx in <https://github.com/apache/hertzbeat/pull/1189>
* replace obsolete `registry.npm.taobao.org` to`registry.npmmirror.com` by @zqr10159 in <https://github.com/apache/hertzbeat/pull/1192>
* refactor MonitorServiceImpl by @Carpe-Wang in <https://github.com/apache/hertzbeat/pull/1190>
* config default system timezone and fix monitor status auto recover by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1187>
* update-doc-doris by @zqr10159 in <https://github.com/apache/hertzbeat/pull/1193>
* [manager] support tidb database monitoring by @luxx-lq in <https://github.com/apache/hertzbeat/pull/733>
* refactor fix potential npe by @Carpe-Wang in <https://github.com/apache/hertzbeat/pull/1197>
* [ospp] support ui help massage component by @YutingNie in <https://github.com/apache/hertzbeat/pull/1199>
* support monitor metrics name i18n by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1198>
* support google analytics by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1202>
* refactor code and fix some npe by @Carpe-Wang in <https://github.com/apache/hertzbeat/pull/1201>
* bugfix fix found 2 dataQueue bean when not config common.queue param by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1205>
* Help component update by @YutingNie in <https://github.com/apache/hertzbeat/pull/1207>
* bugfix enterprise wechat push display content is too cumbersome by @l646505418 in <https://github.com/apache/hertzbeat/pull/1149>
* bugfix WeChatAppAlertNotifyHandlerImpl by @LINGLUOJUN in <https://github.com/apache/hertzbeat/pull/1208>
* add LINGLUOJUN as a contributor for code by @allcontributors in <https://github.com/apache/hertzbeat/pull/1209>
* fix jmx jndi inject vulnerability by @luelueking in <https://github.com/apache/hertzbeat/pull/1215>
* add luelueking as a contributor for code by @allcontributors in <https://github.com/apache/hertzbeat/pull/1217>
* bugfix monitoring param number limit range by @qyaaaa in <https://github.com/apache/hertzbeat/pull/1216>
* add qyaaaa as a contributor for code by @allcontributors in <https://github.com/apache/hertzbeat/pull/1218>
* add app-ping i18n by @qyaaaa in <https://github.com/apache/hertzbeat/pull/1220>
* some codes opt by @LINGLUOJUN in <https://github.com/apache/hertzbeat/pull/1214>
* support deploy hertzbeat by kubernetes helm charts by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1221>
* bugfix threshold setting template variables has repeated parameters by @qyaaaa in <https://github.com/apache/hertzbeat/pull/1223>
* support display metrics i18n label when threshold setting by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1225>
* bugfix user role display not correctly on webui by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1227>
* add hertzbeat about msg card by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1229>
* add app-api i18n by @novohit in <https://github.com/apache/hertzbeat/pull/1236>
* add novohit as a contributor for code by @allcontributors in <https://github.com/apache/hertzbeat/pull/1238>
* [feature]Add `getAlertDefinesByName`. by @zqr10159 in <https://github.com/apache/hertzbeat/pull/1237>
* thread pool executor support shutdown gracefully by @LINGLUOJUN in <https://github.com/apache/hertzbeat/pull/1240>
* fix: expression injection RCE by @mikezzb in <https://github.com/apache/hertzbeat/pull/1241>
* [bugfix]Replace schema "{key1:value1}" to "{\"key1\":\"value1\"}" by @zqr10159 in <https://github.com/apache/hertzbeat/pull/1245>
* [Refactor] Use static methods instead of constructors for Message.java by @gcdd1993 in <https://github.com/apache/hertzbeat/pull/1247>
* bugfix snake yaml decode rce by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1239>
* bugfix jackson deserialize localDatetime error by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1249>
* netty as an independent module, add new feature about collector list by @Ceilzcx in <https://github.com/apache/hertzbeat/pull/1244>
* support show deploy collector script in web by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1251>
* bugfix mongodb collect extra metrics npe by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1257>
* bugfix fix collector run cyclic when connect auth failed by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1256>
* update webapp login ui by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1260>
* bugfix collector can not auto reconnect when channel idle by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1259>
* update alarm notice wework app send content ui by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1258>
* [hertzbeat] release hertzbeat version v1.4.1 by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1261>
* auto split webhook token when user input hook url by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1262>
* bugfix npe when get undefined name monitor template yml by @tomsun28 in [#1173](https://github.com/apache/hertzbeat/pull/1173)
* [bug fixed]When importing and exporting monitoring, support export collectors, configure collectors when importing by @zqr10159 in [#1178](https://github.com/apache/hertzbeat/pull/1178)
* support alert threshold rule config system value row count by @tomsun28 in [#1180](https://github.com/apache/hertzbeat/pull/1180)
* Update README.md by @zqr10159 in [#1182](https://github.com/apache/hertzbeat/pull/1182)
* support config alert threshold tags bind by @tomsun28 in [#1181](https://github.com/apache/hertzbeat/pull/1181)
* the back-end of help component has been built by @YutingNie in [#1160](https://github.com/apache/hertzbeat/pull/1160)
* support enable alert threshold auto resolved notice by @tomsun28 in [#1185](https://github.com/apache/hertzbeat/pull/1185)
* Delete tag of the dashboard's homepage on the top four pages by @Ceilzcx in [#1189](https://github.com/apache/hertzbeat/pull/1189)
* replace obsolete `registry.npm.taobao.org` to`registry.npmmirror.com` by @zqr10159 in [#1192](https://github.com/apache/hertzbeat/pull/1192)
* refactor MonitorServiceImpl by @Carpe-Wang in [#1190](https://github.com/apache/hertzbeat/pull/1190)
* config default system timezone and fix monitor status auto recover by @tomsun28 in [#1187](https://github.com/apache/hertzbeat/pull/1187)
* update-doc-doris by @zqr10159 in [#1193](https://github.com/apache/hertzbeat/pull/1193)
* [manager] support tidb database monitoring by @luxx-lq in [#733](https://github.com/apache/hertzbeat/pull/733)
* refactor fix potential npe by @Carpe-Wang in [#1197](https://github.com/apache/hertzbeat/pull/1197)
* [ospp] support ui help massage component by @YutingNie in [#1199](https://github.com/apache/hertzbeat/pull/1199)
* support monitor metrics name i18n by @tomsun28 in [#1198](https://github.com/apache/hertzbeat/pull/1198)
* support google analytics by @tomsun28 in [#1202](https://github.com/apache/hertzbeat/pull/1202)
* refactor code and fix some npe by @Carpe-Wang in [#1201](https://github.com/apache/hertzbeat/pull/1201)
* bugfix fix found 2 dataQueue bean when not config common.queue param by @tomsun28 in [#1205](https://github.com/apache/hertzbeat/pull/1205)
* Help component update by @YutingNie in [#1207](https://github.com/apache/hertzbeat/pull/1207)
* bugfix enterprise wechat push display content is too cumbersome by @l646505418 in [#1149](https://github.com/apache/hertzbeat/pull/1149)
* bugfix WeChatAppAlertNotifyHandlerImpl by @LINGLUOJUN in [#1208](https://github.com/apache/hertzbeat/pull/1208)
* add LINGLUOJUN as a contributor for code by @allcontributors in [#1209](https://github.com/apache/hertzbeat/pull/1209)
* fix jmx jndi inject vulnerability by @luelueking in [#1215](https://github.com/apache/hertzbeat/pull/1215)
* add luelueking as a contributor for code by @allcontributors in [#1217](https://github.com/apache/hertzbeat/pull/1217)
* bugfix monitoring param number limit range by @qyaaaa in [#1216](https://github.com/apache/hertzbeat/pull/1216)
* add qyaaaa as a contributor for code by @allcontributors in [#1218](https://github.com/apache/hertzbeat/pull/1218)
* add app-ping i18n by @qyaaaa in [#1220](https://github.com/apache/hertzbeat/pull/1220)
* some codes opt by @LINGLUOJUN in [#1214](https://github.com/apache/hertzbeat/pull/1214)
* support deploy hertzbeat by kubernetes helm charts by @tomsun28 in [#1221](https://github.com/apache/hertzbeat/pull/1221)
* bugfix threshold setting template variables has repeated parameters by @qyaaaa in [#1223](https://github.com/apache/hertzbeat/pull/1223)
* support display metrics i18n label when threshold setting by @tomsun28 in [#1225](https://github.com/apache/hertzbeat/pull/1225)
* bugfix user role display not correctly on webui by @tomsun28 in [#1227](https://github.com/apache/hertzbeat/pull/1227)
* add hertzbeat about msg card by @tomsun28 in [#1229](https://github.com/apache/hertzbeat/pull/1229)
* add app-api i18n by @novohit in [#1236](https://github.com/apache/hertzbeat/pull/1236)
* add novohit as a contributor for code by @allcontributors in [#1238](https://github.com/apache/hertzbeat/pull/1238)
* [feature]Add `getAlertDefinesByName`. by @zqr10159 in [#1237](https://github.com/apache/hertzbeat/pull/1237)
* thread pool executor support shutdown gracefully by @LINGLUOJUN in [#1240](https://github.com/apache/hertzbeat/pull/1240)
* fix: expression injection RCE by @mikezzb in [#1241](https://github.com/apache/hertzbeat/pull/1241)
* [bugfix]Replace schema `"{key1:value1}"` to `"{\"key1\":\"value1\"}"` by @zqr10159 in [#1245](https://github.com/apache/hertzbeat/pull/1245)
* [Refactor] Use static methods instead of constructors for Message.java by @gcdd1993 in [#1247](https://github.com/apache/hertzbeat/pull/1247)
* bugfix snake yaml decode rce by @tomsun28 in [#1239](https://github.com/apache/hertzbeat/pull/1239)
* bugfix jackson deserialize localDatetime error by @tomsun28 in [#1249](https://github.com/apache/hertzbeat/pull/1249)
* netty as an independent module, add new feature about collector list by @Ceilzcx in [#1244](https://github.com/apache/hertzbeat/pull/1244)
* support show deploy collector script in web by @tomsun28 in [#1251](https://github.com/apache/hertzbeat/pull/1251)
* bugfix mongodb collect extra metrics npe by @tomsun28 in [#1257](https://github.com/apache/hertzbeat/pull/1257)
* bugfix fix collector run cyclic when connect auth failed by @tomsun28 in [#1256](https://github.com/apache/hertzbeat/pull/1256)
* update webapp login ui by @tomsun28 in [#1260](https://github.com/apache/hertzbeat/pull/1260)
* bugfix collector can not auto reconnect when channel idle by @tomsun28 in [#1259](https://github.com/apache/hertzbeat/pull/1259)
* update alarm notice wework app send content ui by @tomsun28 in [#1258](https://github.com/apache/hertzbeat/pull/1258)
* [hertzbeat] release hertzbeat version v1.4.1 by @tomsun28 in [#1261](https://github.com/apache/hertzbeat/pull/1261)
* auto split webhook token when user input hook url by @tomsun28 in [#1262](https://github.com/apache/hertzbeat/pull/1262)
---
@@ -151,5 +151,5 @@ Detailed config refer to [Install HertzBeat via Docker](https://hertzbeat.apache
---
**Github: <https://github.com/apache/hertzbeat>**
**Gitee: <https://gitee.com/hertzbeat/hertzbeat>**
**Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)**
**Gitee: [https://gitee.com/hertzbeat/hertzbeat](https://gitee.com/hertzbeat/hertzbeat)**
+50 -50
View File
@@ -23,9 +23,9 @@ keywords: [open source monitoring system, alerting system, Linux monitoring]
![HertzBeat](/img/docs/hertzbeat-arch.png)
**Github: <https://github.com/apache/hertzbeat>**
**Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)**
**Gitee: <https://gitee.com/hertzbeat/hertzbeat>**
**Gitee: [https://gitee.com/hertzbeat/hertzbeat](https://gitee.com/hertzbeat/hertzbeat)**
### HertzBeat's 1.4.2 version release
@@ -65,55 +65,55 @@ Detailed config refer to [Install HertzBeat via Docker](https://hertzbeat.apache
> Welcome to explore more new version updates, thanks to the hard work of the community partners, love 💗!
* bugfix counting wrong tasks num of collector by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1265>
* [ospp] add push style collector by @vinci-897 in <https://github.com/apache/hertzbeat/pull/1222>
* add 1.4.1 version doc by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1263>
* support using Huawei Cloud OBS to store custom define yml file by @gcdd1993 in <https://github.com/apache/hertzbeat/pull/1266>
* [doc] add more contact channel by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1272>
* bugfix app-tomcat memory_pool unit mb by @rbsrcy in <https://github.com/apache/hertzbeat/pull/1268>
* add rbsrcy as a contributor for code by @allcontributors in <https://github.com/apache/hertzbeat/pull/1271>
* [doc] update docker.md by @ruanliang-hualun in <https://github.com/apache/hertzbeat/pull/1270>
* add ruanliang-hualun as a contributor for doc by @allcontributors in <https://github.com/apache/hertzbeat/pull/1274>
* bugfix jmx memory_pool unit and time unit error by @rbsrcy in <https://github.com/apache/hertzbeat/pull/1273>
* bugfix old version monitor alert has no monitor name by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1278>
* support edit monitor in monitor detail page by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1282>
* reset alert converge reduce cache when restored alert trigger by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1281>
* [ospp] add push style collector doc by @vinci-897 in <https://github.com/apache/hertzbeat/pull/1267>
* bugfix threshold availability automatically carries threshold parameters by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1285>
* [ospp] support custom notice template by @Eden4701 in <https://github.com/apache/hertzbeat/pull/1233>
* add Eden4701 as a contributor for code by @allcontributors in <https://github.com/apache/hertzbeat/pull/1287>
* bugfix AvailableAlertDefineInit - query did not return a unique result by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1288>
* upgrade to version angular 15 by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1291>
* support push style for multiple messages by @vinci-897 in <https://github.com/apache/hertzbeat/pull/1292>
* update hertzbeat upgrade help doc by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1294>
* feat alert converge, define, silence support search query by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1300>
* feature:support monitoring udp port availability by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1295>
* support emqx monitor by @vinci-897 in <https://github.com/apache/hertzbeat/pull/1302>
* add an explicit tag filter by @vinci-897 in <https://github.com/apache/hertzbeat/pull/1303>
* add hertzbeat icon by @zqr10159 in <https://github.com/apache/hertzbeat/pull/1305>
* [doc] update kafka help doc by @XiaTian688 in <https://github.com/apache/hertzbeat/pull/1308>
* add XiaTian688 as a contributor for doc by @allcontributors in <https://github.com/apache/hertzbeat/pull/1309>
* support webhook custom template by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1306>
* set ssh param connect reused default false by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1310>
* upgrade greptimedb to v0.4 by @liyin in <https://github.com/apache/hertzbeat/pull/1311>
* add liyin as a contributor for code by @allcontributors in <https://github.com/apache/hertzbeat/pull/1313>
* add some emqx monitoring metrics by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1312>
* feature: app-mysql.yml by @a-little-fool in <https://github.com/apache/hertzbeat/pull/1316>
* modify default IoTDB version config to V_1_0 by @Ceilzcx in <https://github.com/apache/hertzbeat/pull/1315>
* bugfix timestamp is null by @qyaaaa in <https://github.com/apache/hertzbeat/pull/1246>
* [hertzbeat] release hertzbeat version v1.4.2 by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1317>
* bugfix alarm time span match in silence and notice by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1318>
* update available alert threshold trigger times default 2 by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1324>
* bugfix rabbitmq contains duplicated metric by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1322>
* [alerter] optimize the encoding of how to add Extern Alarm Manage API(#1320) by @SurryChen in <https://github.com/apache/hertzbeat/pull/1325>
* bugfix webhook post body error and alarm recover exception by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1327>
* build hertzbeat package with jdk runtime by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1328>
* bugfix counting wrong tasks num of collector by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1265](https://github.com/apache/hertzbeat/pull/1265)
* [ospp] add push style collector by @vinci-897 in [https://github.com/apache/hertzbeat/pull/1222](https://github.com/apache/hertzbeat/pull/1222)
* add 1.4.1 version doc by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1263](https://github.com/apache/hertzbeat/pull/1263)
* support using Huawei Cloud OBS to store custom define yml file by @gcdd1993 in [https://github.com/apache/hertzbeat/pull/1266](https://github.com/apache/hertzbeat/pull/1266)
* [doc] add more contact channel by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1272](https://github.com/apache/hertzbeat/pull/1272)
* bugfix app-tomcat memory_pool unit mb by @rbsrcy in [https://github.com/apache/hertzbeat/pull/1268](https://github.com/apache/hertzbeat/pull/1268)
* add rbsrcy as a contributor for code by @allcontributors in [https://github.com/apache/hertzbeat/pull/1271](https://github.com/apache/hertzbeat/pull/1271)
* [doc] update docker.md by @ruanliang-hualun in [https://github.com/apache/hertzbeat/pull/1270](https://github.com/apache/hertzbeat/pull/1270)
* add ruanliang-hualun as a contributor for doc by @allcontributors in [https://github.com/apache/hertzbeat/pull/1274](https://github.com/apache/hertzbeat/pull/1274)
* bugfix jmx memory_pool unit and time unit error by @rbsrcy in [https://github.com/apache/hertzbeat/pull/1273](https://github.com/apache/hertzbeat/pull/1273)
* bugfix old version monitor alert has no monitor name by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1278](https://github.com/apache/hertzbeat/pull/1278)
* support edit monitor in monitor detail page by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1282](https://github.com/apache/hertzbeat/pull/1282)
* reset alert converge reduce cache when restored alert trigger by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1281](https://github.com/apache/hertzbeat/pull/1281)
* [ospp] add push style collector doc by @vinci-897 in [https://github.com/apache/hertzbeat/pull/1267](https://github.com/apache/hertzbeat/pull/1267)
* bugfix threshold availability automatically carries threshold parameters by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1285](https://github.com/apache/hertzbeat/pull/1285)
* [ospp] support custom notice template by @Eden4701 in [https://github.com/apache/hertzbeat/pull/1233](https://github.com/apache/hertzbeat/pull/1233)
* add Eden4701 as a contributor for code by @allcontributors in [https://github.com/apache/hertzbeat/pull/1287](https://github.com/apache/hertzbeat/pull/1287)
* bugfix AvailableAlertDefineInit - query did not return a unique result by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1288](https://github.com/apache/hertzbeat/pull/1288)
* upgrade to version angular 15 by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1291](https://github.com/apache/hertzbeat/pull/1291)
* support push style for multiple messages by @vinci-897 in [https://github.com/apache/hertzbeat/pull/1292](https://github.com/apache/hertzbeat/pull/1292)
* update hertzbeat upgrade help doc by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1294](https://github.com/apache/hertzbeat/pull/1294)
* feat alert converge, define, silence support search query by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1300](https://github.com/apache/hertzbeat/pull/1300)
* feature:support monitoring udp port availability by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1295](https://github.com/apache/hertzbeat/pull/1295)
* support emqx monitor by @vinci-897 in [https://github.com/apache/hertzbeat/pull/1302](https://github.com/apache/hertzbeat/pull/1302)
* add an explicit tag filter by @vinci-897 in [https://github.com/apache/hertzbeat/pull/1303](https://github.com/apache/hertzbeat/pull/1303)
* add hertzbeat icon by @zqr10159 in [https://github.com/apache/hertzbeat/pull/1305](https://github.com/apache/hertzbeat/pull/1305)
* [doc] update kafka help doc by @XiaTian688 in [https://github.com/apache/hertzbeat/pull/1308](https://github.com/apache/hertzbeat/pull/1308)
* add XiaTian688 as a contributor for doc by @allcontributors in [https://github.com/apache/hertzbeat/pull/1309](https://github.com/apache/hertzbeat/pull/1309)
* support webhook custom template by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1306](https://github.com/apache/hertzbeat/pull/1306)
* set ssh param connect reused default false by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1310](https://github.com/apache/hertzbeat/pull/1310)
* upgrade greptimedb to v0.4 by @liyin in [https://github.com/apache/hertzbeat/pull/1311](https://github.com/apache/hertzbeat/pull/1311)
* add liyin as a contributor for code by @allcontributors in [https://github.com/apache/hertzbeat/pull/1313](https://github.com/apache/hertzbeat/pull/1313)
* add some emqx monitoring metrics by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1312](https://github.com/apache/hertzbeat/pull/1312)
* feature: app-mysql.yml by @a-little-fool in [https://github.com/apache/hertzbeat/pull/1316](https://github.com/apache/hertzbeat/pull/1316)
* modify default IoTDB version config to V_1_0 by @Ceilzcx in [https://github.com/apache/hertzbeat/pull/1315](https://github.com/apache/hertzbeat/pull/1315)
* bugfix timestamp is null by @qyaaaa in [https://github.com/apache/hertzbeat/pull/1246](https://github.com/apache/hertzbeat/pull/1246)
* [hertzbeat] release hertzbeat version v1.4.2 by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1317](https://github.com/apache/hertzbeat/pull/1317)
* bugfix alarm time span match in silence and notice by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1318](https://github.com/apache/hertzbeat/pull/1318)
* update available alert threshold trigger times default 2 by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1324](https://github.com/apache/hertzbeat/pull/1324)
* bugfix rabbitmq contains duplicated metric by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1322](https://github.com/apache/hertzbeat/pull/1322)
* [alerter] optimize the encoding of how to add Extern Alarm Manage API(#1320) by @SurryChen in [https://github.com/apache/hertzbeat/pull/1325](https://github.com/apache/hertzbeat/pull/1325)
* bugfix webhook post body error and alarm recover exception by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1327](https://github.com/apache/hertzbeat/pull/1327)
* build hertzbeat package with jdk runtime by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1328](https://github.com/apache/hertzbeat/pull/1328)
## New Contributors
* @rbsrcy made their first contribution in <https://github.com/apache/hertzbeat/pull/1268>
* @XiaTian688 made their first contribution in <https://github.com/apache/hertzbeat/pull/1308>
* @liyin made their first contribution in <https://github.com/apache/hertzbeat/pull/1311>
* @rbsrcy made their first contribution in [https://github.com/apache/hertzbeat/pull/1268](https://github.com/apache/hertzbeat/pull/1268)
* @XiaTian688 made their first contribution in [https://github.com/apache/hertzbeat/pull/1308](https://github.com/apache/hertzbeat/pull/1308)
* @liyin made their first contribution in [https://github.com/apache/hertzbeat/pull/1311](https://github.com/apache/hertzbeat/pull/1311)
---
@@ -130,5 +130,5 @@ Detailed config refer to [Install HertzBeat via Docker](https://hertzbeat.apache
---
**Github: <https://github.com/apache/hertzbeat>**
**Gitee: <https://gitee.com/hertzbeat/hertzbeat>**
**Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)**
**Gitee: [https://gitee.com/hertzbeat/hertzbeat](https://gitee.com/hertzbeat/hertzbeat)**
+58 -58
View File
@@ -24,9 +24,9 @@ keywords: [open source monitoring system, alerting system]
![HertzBeat](/img/docs/hertzbeat-arch.png)
**Github: <https://github.com/apache/hertzbeat>**
**Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)**
**Gitee: <https://gitee.com/hertzbeat/hertzbeat>**
**Gitee: [https://gitee.com/hertzbeat/hertzbeat](https://gitee.com/hertzbeat/hertzbeat)**
### HertzBeat's 1.4.3 Version Release
@@ -71,63 +71,63 @@ Detailed config refer to [Install HertzBeat via Docker](https://hertzbeat.apache
> Welcome to explore more new version updates, thanks to the hard work of the community partners, love 💗!
* update package deploy doc by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1330>
* bugfix duplicate collect job when update monitor templates by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1332>
* bugfix number variable in freemarker template display error by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1334>
* [alerter] Enhanced reporting of external general alert API by @SurryChen in <https://github.com/apache/hertzbeat/pull/1326>
* [doc] update hertzbeat-mysql-tdengine readme by @jiashu1024 in <https://github.com/apache/hertzbeat/pull/1335>
* add jiashu1024 as a contributor for doc by @allcontributors in <https://github.com/apache/hertzbeat/pull/1336>
* app-mysql.yml: Adjust slow query translation by @1036664317 in <https://github.com/apache/hertzbeat/pull/1337>
* add 1036664317 as a contributor for doc by @allcontributors in <https://github.com/apache/hertzbeat/pull/1338>
* Bump com.google.guava:guava from 31.0.1-jre to 32.0.0-jre by @dependabot in <https://github.com/apache/hertzbeat/pull/1339>
* [feature] support auto collect metrics by prometheus task by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1342>
* [doc] add vinci as new committer by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1341>
* [feature] add tag word cloud in dashboard by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1345>
* support custom prometheus endpoint path by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1346>
* bugfix tdengine query interval history metrics data with instance error by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1348>
* unlimit Alert.java content field length by @xiaoguolong in <https://github.com/apache/hertzbeat/pull/1351>
* add xiaoguolong as a contributor for code by @allcontributors in <https://github.com/apache/hertzbeat/pull/1353>
* update monitor detail table ui layout by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1352>
* [doc]add star history by @zqr10159 in <https://github.com/apache/hertzbeat/pull/1356>
* feature: app-mongodb.yml by @a-little-fool in <https://github.com/apache/hertzbeat/pull/1359>
* alarm threshold support prometheus task metrics by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1354>
* support victoriametrics as metrics data storage by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1361>
* Add time type to support query_time of mysql and mariadb by @Clownsw in <https://github.com/apache/hertzbeat/pull/1364>
* add Clownsw as a contributor for code by @allcontributors in <https://github.com/apache/hertzbeat/pull/1365>
* Error occured when I followed running steps to start Front-web by @Calvin979 in <https://github.com/apache/hertzbeat/pull/1366>
* add Calvin979 as a contributor for doc by @allcontributors in <https://github.com/apache/hertzbeat/pull/1367>
* enriches the cncf landscape by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1368>
* Fix flaky test in CollectUtilTest by @bbelide2 in <https://github.com/apache/hertzbeat/pull/1371>
* add bbelide2 as a contributor for code by @allcontributors in <https://github.com/apache/hertzbeat/pull/1372>
* Fix flaky test replaceSmilingPlaceholder by @bbelide2 in <https://github.com/apache/hertzbeat/pull/1373>
* add docker-compose script hertzbeat+mysql+victoria-metrics all in one by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1370>
* Feature: app-jvm.yml support for international name aliases by @Calvin979 in <https://github.com/apache/hertzbeat/pull/1376>
* add Calvin979 as a contributor for code by @allcontributors in <https://github.com/apache/hertzbeat/pull/1377>
* feature: support monitoring spring gateway metrics by @a-little-fool in <https://github.com/apache/hertzbeat/pull/1374>
* update code comment and doc, bugfix concurrent exception by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1378>
* update windows define and accept snmp leaf by @jinyaoMa in <https://github.com/apache/hertzbeat/pull/1379>
* add jinyaoMa as a contributor for code by @allcontributors in <https://github.com/apache/hertzbeat/pull/1380>
* fix exception when sending email has special chars by @Carpe-Wang in <https://github.com/apache/hertzbeat/pull/1383>
* test: add e2e testing for some basic APIs by @LinuxSuRen in <https://github.com/apache/hertzbeat/pull/1387>
* add LinuxSuRen as a contributor for code, and test by @allcontributors in <https://github.com/apache/hertzbeat/pull/1389>
* bugfix auto generate monitor name error when add monitor by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1384>
* bugfix CalculateAlarm execAlertExpression NPE by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1388>
* Feature: app-redis.yml support for international name aliases by @Calvin979 in <https://github.com/apache/hertzbeat/pull/1390>
* test: add more monitor related e2e testing case by @LinuxSuRen in <https://github.com/apache/hertzbeat/pull/1391>
* chore: update the pr template about the e2e testing by @LinuxSuRen in <https://github.com/apache/hertzbeat/pull/1392>
* add help header ui when update or add monitors by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1399>
* [hertzbeat] release hertzbeat version v1.4.3 by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1400>
* update package deploy doc by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1330](https://github.com/apache/hertzbeat/pull/1330)
* bugfix duplicate collect job when update monitor templates by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1332](https://github.com/apache/hertzbeat/pull/1332)
* bugfix number variable in freemarker template display error by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1334](https://github.com/apache/hertzbeat/pull/1334)
* [alerter] Enhanced reporting of external general alert API by @SurryChen in [https://github.com/apache/hertzbeat/pull/1326](https://github.com/apache/hertzbeat/pull/1326)
* [doc] update hertzbeat-mysql-tdengine readme by @jiashu1024 in [https://github.com/apache/hertzbeat/pull/1335](https://github.com/apache/hertzbeat/pull/1335)
* add jiashu1024 as a contributor for doc by @allcontributors in [https://github.com/apache/hertzbeat/pull/1336](https://github.com/apache/hertzbeat/pull/1336)
* app-mysql.yml: Adjust slow query translation by @1036664317 in [https://github.com/apache/hertzbeat/pull/1337](https://github.com/apache/hertzbeat/pull/1337)
* add 1036664317 as a contributor for doc by @allcontributors in [https://github.com/apache/hertzbeat/pull/1338](https://github.com/apache/hertzbeat/pull/1338)
* Bump com.google.guava:guava from 31.0.1-jre to 32.0.0-jre by @dependabot in [https://github.com/apache/hertzbeat/pull/1339](https://github.com/apache/hertzbeat/pull/1339)
* [feature] support auto collect metrics by prometheus task by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1342](https://github.com/apache/hertzbeat/pull/1342)
* [doc] add vinci as new committer by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1341](https://github.com/apache/hertzbeat/pull/1341)
* [feature] add tag word cloud in dashboard by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1345](https://github.com/apache/hertzbeat/pull/1345)
* support custom prometheus endpoint path by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1346](https://github.com/apache/hertzbeat/pull/1346)
* bugfix tdengine query interval history metrics data with instance error by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1348](https://github.com/apache/hertzbeat/pull/1348)
* unlimit Alert.java content field length by @xiaoguolong in [https://github.com/apache/hertzbeat/pull/1351](https://github.com/apache/hertzbeat/pull/1351)
* add xiaoguolong as a contributor for code by @allcontributors in [https://github.com/apache/hertzbeat/pull/1353](https://github.com/apache/hertzbeat/pull/1353)
* update monitor detail table ui layout by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1352](https://github.com/apache/hertzbeat/pull/1352)
* [doc]add star history by @zqr10159 in [https://github.com/apache/hertzbeat/pull/1356](https://github.com/apache/hertzbeat/pull/1356)
* feature: app-mongodb.yml by @a-little-fool in [https://github.com/apache/hertzbeat/pull/1359](https://github.com/apache/hertzbeat/pull/1359)
* alarm threshold support prometheus task metrics by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1354](https://github.com/apache/hertzbeat/pull/1354)
* support victoriametrics as metrics data storage by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1361](https://github.com/apache/hertzbeat/pull/1361)
* Add time type to support query_time of mysql and mariadb by @Clownsw in [https://github.com/apache/hertzbeat/pull/1364](https://github.com/apache/hertzbeat/pull/1364)
* add Clownsw as a contributor for code by @allcontributors in [https://github.com/apache/hertzbeat/pull/1365](https://github.com/apache/hertzbeat/pull/1365)
* Error occured when I followed running steps to start Front-web by @Calvin979 in [https://github.com/apache/hertzbeat/pull/1366](https://github.com/apache/hertzbeat/pull/1366)
* add Calvin979 as a contributor for doc by @allcontributors in [https://github.com/apache/hertzbeat/pull/1367](https://github.com/apache/hertzbeat/pull/1367)
* enriches the cncf landscape by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1368](https://github.com/apache/hertzbeat/pull/1368)
* Fix flaky test in CollectUtilTest by @bbelide2 in [https://github.com/apache/hertzbeat/pull/1371](https://github.com/apache/hertzbeat/pull/1371)
* add bbelide2 as a contributor for code by @allcontributors in [https://github.com/apache/hertzbeat/pull/1372](https://github.com/apache/hertzbeat/pull/1372)
* Fix flaky test replaceSmilingPlaceholder by @bbelide2 in [https://github.com/apache/hertzbeat/pull/1373](https://github.com/apache/hertzbeat/pull/1373)
* add docker-compose script hertzbeat+mysql+victoria-metrics all in one by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1370](https://github.com/apache/hertzbeat/pull/1370)
* Feature: app-jvm.yml support for international name aliases by @Calvin979 in [https://github.com/apache/hertzbeat/pull/1376](https://github.com/apache/hertzbeat/pull/1376)
* add Calvin979 as a contributor for code by @allcontributors in [https://github.com/apache/hertzbeat/pull/1377](https://github.com/apache/hertzbeat/pull/1377)
* feature: support monitoring spring gateway metrics by @a-little-fool in [https://github.com/apache/hertzbeat/pull/1374](https://github.com/apache/hertzbeat/pull/1374)
* update code comment and doc, bugfix concurrent exception by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1378](https://github.com/apache/hertzbeat/pull/1378)
* update windows define and accept snmp leaf by @jinyaoMa in [https://github.com/apache/hertzbeat/pull/1379](https://github.com/apache/hertzbeat/pull/1379)
* add jinyaoMa as a contributor for code by @allcontributors in [https://github.com/apache/hertzbeat/pull/1380](https://github.com/apache/hertzbeat/pull/1380)
* fix exception when sending email has special chars by @Carpe-Wang in [https://github.com/apache/hertzbeat/pull/1383](https://github.com/apache/hertzbeat/pull/1383)
* test: add e2e testing for some basic APIs by @LinuxSuRen in [https://github.com/apache/hertzbeat/pull/1387](https://github.com/apache/hertzbeat/pull/1387)
* add LinuxSuRen as a contributor for code, and test by @allcontributors in [https://github.com/apache/hertzbeat/pull/1389](https://github.com/apache/hertzbeat/pull/1389)
* bugfix auto generate monitor name error when add monitor by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1384](https://github.com/apache/hertzbeat/pull/1384)
* bugfix CalculateAlarm execAlertExpression NPE by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1388](https://github.com/apache/hertzbeat/pull/1388)
* Feature: app-redis.yml support for international name aliases by @Calvin979 in [https://github.com/apache/hertzbeat/pull/1390](https://github.com/apache/hertzbeat/pull/1390)
* test: add more monitor related e2e testing case by @LinuxSuRen in [https://github.com/apache/hertzbeat/pull/1391](https://github.com/apache/hertzbeat/pull/1391)
* chore: update the pr template about the e2e testing by @LinuxSuRen in [https://github.com/apache/hertzbeat/pull/1392](https://github.com/apache/hertzbeat/pull/1392)
* add help header ui when update or add monitors by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1399](https://github.com/apache/hertzbeat/pull/1399)
* [hertzbeat] release hertzbeat version v1.4.3 by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1400](https://github.com/apache/hertzbeat/pull/1400)
## New Contributors
* @1036664317 made their first contribution in <https://github.com/apache/hertzbeat/pull/1337>
* @dependabot made their first contribution in <https://github.com/apache/hertzbeat/pull/1339>
* @xiaoguolong made their first contribution in <https://github.com/apache/hertzbeat/pull/1351>
* @Clownsw made their first contribution in <https://github.com/apache/hertzbeat/pull/1364>
* @Calvin979 made their first contribution in <https://github.com/apache/hertzbeat/pull/1366>
* @bbelide2 made their first contribution in <https://github.com/apache/hertzbeat/pull/1371>
* @jinyaoMa made their first contribution in <https://github.com/apache/hertzbeat/pull/1379>
* @LinuxSuRen made their first contribution in <https://github.com/apache/hertzbeat/pull/1387>
* @1036664317 made their first contribution in [https://github.com/apache/hertzbeat/pull/1337](https://github.com/apache/hertzbeat/pull/1337)
* @dependabot made their first contribution in [https://github.com/apache/hertzbeat/pull/1339](https://github.com/apache/hertzbeat/pull/1339)
* @xiaoguolong made their first contribution in [https://github.com/apache/hertzbeat/pull/1351](https://github.com/apache/hertzbeat/pull/1351)
* @Clownsw made their first contribution in [https://github.com/apache/hertzbeat/pull/1364](https://github.com/apache/hertzbeat/pull/1364)
* @Calvin979 made their first contribution in [https://github.com/apache/hertzbeat/pull/1366](https://github.com/apache/hertzbeat/pull/1366)
* @bbelide2 made their first contribution in [https://github.com/apache/hertzbeat/pull/1371](https://github.com/apache/hertzbeat/pull/1371)
* @jinyaoMa made their first contribution in [https://github.com/apache/hertzbeat/pull/1379](https://github.com/apache/hertzbeat/pull/1379)
* @LinuxSuRen made their first contribution in [https://github.com/apache/hertzbeat/pull/1387](https://github.com/apache/hertzbeat/pull/1387)
---
@@ -144,5 +144,5 @@ Detailed config refer to [Install HertzBeat via Docker](https://hertzbeat.apache
---
**Github: <https://github.com/apache/hertzbeat>**
**Gitee: <https://gitee.com/hertzbeat/hertzbeat>**
**Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)**
**Gitee: [https://gitee.com/hertzbeat/hertzbeat](https://gitee.com/hertzbeat/hertzbeat)**
+2 -2
View File
@@ -128,8 +128,8 @@ Thanks to the authors of hertzbeat for the documentation and help. Thanks to my
> ``HertzBeat``s powerful customization, multi-type support, high performance, easy to extend, low coupling, hope to help developers and teams quickly build their own monitoring system.
**Github: <https://github.com/apache/hertzbeat>**
**Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)**
**Gitee: <https://gitee.com/hertzbeat/hertzbeat>**
**Gitee: [https://gitee.com/hertzbeat/hertzbeat](https://gitee.com/hertzbeat/hertzbeat)**
Welcome more partners to participate in HertzBeat's open source collaboration, no matter a typo or punctuation we are very welcome, we learn together to make progress, the goal is to do a world-class open source software.
+68 -68
View File
@@ -24,9 +24,9 @@ keywords: [open source monitoring system, alerting system]
![HertzBeat](/img/docs/hertzbeat-arch.png)
**Github: <https://github.com/apache/hertzbeat>**
**Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)**
**Gitee: <https://gitee.com/hertzbeat/hertzbeat>**
**Gitee: [https://gitee.com/hertzbeat/hertzbeat](https://gitee.com/hertzbeat/hertzbeat)**
### HertzBeat's 1.4.4 Version Release
@@ -72,76 +72,76 @@ Detailed config refer to [Install HertzBeat via Docker](https://hertzbeat.apache
> Welcome to explore more new version updates, thanks to the hard work of the community partners, love 💗!
* bugfix metrics tags value store jpa data-storage error by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1403>
* add smtp protocol and support smtp monitoring by @ZY945 in <https://github.com/apache/hertzbeat/pull/1407>
* add ZY945 as a contributor for code by @allcontributors in <https://github.com/apache/hertzbeat/pull/1409>
* support new parse type 'log' in ssh collect protocol by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1410>
* add ntp protocol and support ntp monitoring by @ZY945 in <https://github.com/apache/hertzbeat/pull/1411>
* monitoring the availability of websockets through handshake. by @ZY945 in <https://github.com/apache/hertzbeat/pull/1413>
* [Task-1386] When adding tags in tag management, random colors are given by default. by @prolevel1 in <https://github.com/apache/hertzbeat/pull/1412>
* add prolevel1 as a contributor for code by @allcontributors in <https://github.com/apache/hertzbeat/pull/1415>
* bugfix metrics tags value store jpa data-storage error by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1403](https://github.com/apache/hertzbeat/pull/1403)
* add smtp protocol and support smtp monitoring by @ZY945 in [https://github.com/apache/hertzbeat/pull/1407](https://github.com/apache/hertzbeat/pull/1407)
* add ZY945 as a contributor for code by @allcontributors in [https://github.com/apache/hertzbeat/pull/1409](https://github.com/apache/hertzbeat/pull/1409)
* support new parse type 'log' in ssh collect protocol by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1410](https://github.com/apache/hertzbeat/pull/1410)
* add ntp protocol and support ntp monitoring by @ZY945 in [https://github.com/apache/hertzbeat/pull/1411](https://github.com/apache/hertzbeat/pull/1411)
* monitoring the availability of websockets through handshake. by @ZY945 in [https://github.com/apache/hertzbeat/pull/1413](https://github.com/apache/hertzbeat/pull/1413)
* [Task-1386] When adding tags in tag management, random colors are given by default. by @prolevel1 in [https://github.com/apache/hertzbeat/pull/1412](https://github.com/apache/hertzbeat/pull/1412)
* add prolevel1 as a contributor for code by @allcontributors in [https://github.com/apache/hertzbeat/pull/1415](https://github.com/apache/hertzbeat/pull/1415)
*
## 1397 feature: support for dns monitoring by @Calvin979 in <https://github.com/apache/hertzbeat/pull/1416>
## 1397 feature: support for dns monitoring by @Calvin979 in [https://github.com/apache/hertzbeat/pull/1416](https://github.com/apache/hertzbeat/pull/1416)
* Support monitoring hive metrics by @a-little-fool in <https://github.com/apache/hertzbeat/pull/1417>
* support legend pageable in history data charts by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1414>
* update component tip and help tip doc by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1418>
* feature: support monitoring nginx metrics and add a help doc by @a-little-fool in <https://github.com/apache/hertzbeat/pull/1420>
* update parser to parse from prometheus txt metrics data by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1421>
* support monitoring memcached metrics and add a help doc by @ZY945 in <https://github.com/apache/hertzbeat/pull/1423>
* support all ssh connect key exchange by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1424>
* [doc] add code of conduct by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1425>
* update label structure store in victoria metrics, make it prometheus like by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1426>
* feature: support monitoring pop3 metrics and add help doc by @a-little-fool in <https://github.com/apache/hertzbeat/pull/1427>
* Update sidebars.json by @a-little-fool in <https://github.com/apache/hertzbeat/pull/1428>
* Add zh-cn help doc by @a-little-fool in <https://github.com/apache/hertzbeat/pull/1429>
* update monitoring state un-manage to unmonitored, update pic by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1430>
* Add jpa to date type storage by @Clownsw in <https://github.com/apache/hertzbeat/pull/1431>
* bugfix ^o^ token error, protect metrics api auth by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1434>
* Add relevant documents for SMTP and NTP by @ZY945 in <https://github.com/apache/hertzbeat/pull/1437>
* bugfix threshold init error in mysql env by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1435>
* app-rabbitmq.yml support for international name aliases by @ZY945 in <https://github.com/apache/hertzbeat/pull/1439>
* fix(*): error create lru-cache-timeout-cleaner thread by @Clownsw in <https://github.com/apache/hertzbeat/pull/1438>
* app-rabbitmq.yml Modifying Error Fields. by @ZY945 in <https://github.com/apache/hertzbeat/pull/1440>
* support monitoring NebulaGraph metrics and add help doc by @ZY945 in <https://github.com/apache/hertzbeat/pull/1441>
* Fix Nginx Collect validateParams function NPE by @Clownsw in <https://github.com/apache/hertzbeat/pull/1442>
* feature: add metrics i18n for app-springboot3.yml by @liyin in <https://github.com/apache/hertzbeat/pull/1445>
* feat: add metrics i18n for app-docker.yml by @liyin in <https://github.com/apache/hertzbeat/pull/1446>
* update docker-compose script and fix version by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1447>
* bugfix java.lang.IllegalArgumentException: Illegal character in query… by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1443>
* bugfix delete monitor error after monitor canceled by @ZhangZixuan1994 in <https://github.com/apache/hertzbeat/pull/1451>
* add ZhangZixuan1994 as a contributor for code by @allcontributors in <https://github.com/apache/hertzbeat/pull/1454>
* remove sleep, probably busy-waiting by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1456>
* [doc] add new committer ZY945 by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1453>
* Update app-zookeeper.yml by @hurenjie1 in <https://github.com/apache/hertzbeat/pull/1458>
* add hurenjie1 as a contributor for code by @allcontributors in <https://github.com/apache/hertzbeat/pull/1459>
* update dashboard ui, remove ssh custom SignatureFactories, update app name by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1460>
* [Task] Monitoring Template Yml Metrics I18n | 监控模板指标国际化任务认领 #1212 by @tslj1024 in <https://github.com/apache/hertzbeat/pull/1461>
* add tslj1024 as a contributor for code by @allcontributors in <https://github.com/apache/hertzbeat/pull/1462>
* Add alarm trigger time for alarm restore by @Calvin979 in <https://github.com/apache/hertzbeat/pull/1464>
* bugfix history range query not work when victoria-metrics store by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1463>
* bugfix springboot3 translation by @liyin in <https://github.com/apache/hertzbeat/pull/1467>
* bugfix telegram-notice can not input bot-token by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1465>
* feat: support hostname target by @ldysdu in <https://github.com/apache/hertzbeat/pull/1455>
* add ldysdu as a contributor for code by @allcontributors in <https://github.com/apache/hertzbeat/pull/1471>
* [feature] support snmp v3 monitoring protocol by @TJxiaobao in <https://github.com/apache/hertzbeat/pull/1469>
* bugfix alarm trigger-times not work when alarm and recovered trigger cyclically by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1468>
* update switch monitoring metrics i18n by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1472>
* fixed: snmpv3 contextName bug by @TJxiaobao in <https://github.com/apache/hertzbeat/pull/1473>
* Fix npt of webhook notify by @Calvin979 in <https://github.com/apache/hertzbeat/pull/1474>
* [hertzbeat] release hertzbeat version v1.4.4 by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1475>
* bugfix nginx collect http deadlock error by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1476>
* alarm calculate ignore metrics collect code - TIMEOUT by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1478>
* Support monitoring hive metrics by @a-little-fool in [https://github.com/apache/hertzbeat/pull/1417](https://github.com/apache/hertzbeat/pull/1417)
* support legend pageable in history data charts by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1414](https://github.com/apache/hertzbeat/pull/1414)
* update component tip and help tip doc by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1418](https://github.com/apache/hertzbeat/pull/1418)
* feature: support monitoring nginx metrics and add a help doc by @a-little-fool in [https://github.com/apache/hertzbeat/pull/1420](https://github.com/apache/hertzbeat/pull/1420)
* update parser to parse from prometheus txt metrics data by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1421](https://github.com/apache/hertzbeat/pull/1421)
* support monitoring memcached metrics and add a help doc by @ZY945 in [https://github.com/apache/hertzbeat/pull/1423](https://github.com/apache/hertzbeat/pull/1423)
* support all ssh connect key exchange by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1424](https://github.com/apache/hertzbeat/pull/1424)
* [doc] add code of conduct by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1425](https://github.com/apache/hertzbeat/pull/1425)
* update label structure store in victoria metrics, make it prometheus like by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1426](https://github.com/apache/hertzbeat/pull/1426)
* feature: support monitoring pop3 metrics and add help doc by @a-little-fool in [https://github.com/apache/hertzbeat/pull/1427](https://github.com/apache/hertzbeat/pull/1427)
* Update sidebars.json by @a-little-fool in [https://github.com/apache/hertzbeat/pull/1428](https://github.com/apache/hertzbeat/pull/1428)
* Add zh-cn help doc by @a-little-fool in [https://github.com/apache/hertzbeat/pull/1429](https://github.com/apache/hertzbeat/pull/1429)
* update monitoring state un-manage to unmonitored, update pic by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1430](https://github.com/apache/hertzbeat/pull/1430)
* Add jpa to date type storage by @Clownsw in [https://github.com/apache/hertzbeat/pull/1431](https://github.com/apache/hertzbeat/pull/1431)
* bugfix ^o^ token error, protect metrics api auth by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1434](https://github.com/apache/hertzbeat/pull/1434)
* Add relevant documents for SMTP and NTP by @ZY945 in [https://github.com/apache/hertzbeat/pull/1437](https://github.com/apache/hertzbeat/pull/1437)
* bugfix threshold init error in mysql env by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1435](https://github.com/apache/hertzbeat/pull/1435)
* app-rabbitmq.yml support for international name aliases by @ZY945 in [https://github.com/apache/hertzbeat/pull/1439](https://github.com/apache/hertzbeat/pull/1439)
* fix(*): error create lru-cache-timeout-cleaner thread by @Clownsw in [https://github.com/apache/hertzbeat/pull/1438](https://github.com/apache/hertzbeat/pull/1438)
* app-rabbitmq.yml Modifying Error Fields. by @ZY945 in [https://github.com/apache/hertzbeat/pull/1440](https://github.com/apache/hertzbeat/pull/1440)
* support monitoring NebulaGraph metrics and add help doc by @ZY945 in [https://github.com/apache/hertzbeat/pull/1441](https://github.com/apache/hertzbeat/pull/1441)
* Fix Nginx Collect validateParams function NPE by @Clownsw in [https://github.com/apache/hertzbeat/pull/1442](https://github.com/apache/hertzbeat/pull/1442)
* feature: add metrics i18n for app-springboot3.yml by @liyin in [https://github.com/apache/hertzbeat/pull/1445](https://github.com/apache/hertzbeat/pull/1445)
* feat: add metrics i18n for app-docker.yml by @liyin in [https://github.com/apache/hertzbeat/pull/1446](https://github.com/apache/hertzbeat/pull/1446)
* update docker-compose script and fix version by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1447](https://github.com/apache/hertzbeat/pull/1447)
* bugfix java.lang.IllegalArgumentException: Illegal character in query… by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1443](https://github.com/apache/hertzbeat/pull/1443)
* bugfix delete monitor error after monitor canceled by @ZhangZixuan1994 in [https://github.com/apache/hertzbeat/pull/1451](https://github.com/apache/hertzbeat/pull/1451)
* add ZhangZixuan1994 as a contributor for code by @allcontributors in [https://github.com/apache/hertzbeat/pull/1454](https://github.com/apache/hertzbeat/pull/1454)
* remove sleep, probably busy-waiting by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1456](https://github.com/apache/hertzbeat/pull/1456)
* [doc] add new committer ZY945 by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1453](https://github.com/apache/hertzbeat/pull/1453)
* Update app-zookeeper.yml by @hurenjie1 in [https://github.com/apache/hertzbeat/pull/1458](https://github.com/apache/hertzbeat/pull/1458)
* add hurenjie1 as a contributor for code by @allcontributors in [https://github.com/apache/hertzbeat/pull/1459](https://github.com/apache/hertzbeat/pull/1459)
* update dashboard ui, remove ssh custom SignatureFactories, update app name by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1460](https://github.com/apache/hertzbeat/pull/1460)
* [Task] Monitoring Template Yml Metrics I18n | 监控模板指标国际化任务认领 #1212 by @tslj1024 in [https://github.com/apache/hertzbeat/pull/1461](https://github.com/apache/hertzbeat/pull/1461)
* add tslj1024 as a contributor for code by @allcontributors in [https://github.com/apache/hertzbeat/pull/1462](https://github.com/apache/hertzbeat/pull/1462)
* Add alarm trigger time for alarm restore by @Calvin979 in [https://github.com/apache/hertzbeat/pull/1464](https://github.com/apache/hertzbeat/pull/1464)
* bugfix history range query not work when victoria-metrics store by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1463](https://github.com/apache/hertzbeat/pull/1463)
* bugfix springboot3 translation by @liyin in [https://github.com/apache/hertzbeat/pull/1467](https://github.com/apache/hertzbeat/pull/1467)
* bugfix telegram-notice can not input bot-token by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1465](https://github.com/apache/hertzbeat/pull/1465)
* feat: support hostname target by @ldysdu in [https://github.com/apache/hertzbeat/pull/1455](https://github.com/apache/hertzbeat/pull/1455)
* add ldysdu as a contributor for code by @allcontributors in [https://github.com/apache/hertzbeat/pull/1471](https://github.com/apache/hertzbeat/pull/1471)
* [feature] support snmp v3 monitoring protocol by @TJxiaobao in [https://github.com/apache/hertzbeat/pull/1469](https://github.com/apache/hertzbeat/pull/1469)
* bugfix alarm trigger-times not work when alarm and recovered trigger cyclically by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1468](https://github.com/apache/hertzbeat/pull/1468)
* update switch monitoring metrics i18n by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1472](https://github.com/apache/hertzbeat/pull/1472)
* fixed: snmpv3 contextName bug by @TJxiaobao in [https://github.com/apache/hertzbeat/pull/1473](https://github.com/apache/hertzbeat/pull/1473)
* Fix npt of webhook notify by @Calvin979 in [https://github.com/apache/hertzbeat/pull/1474](https://github.com/apache/hertzbeat/pull/1474)
* [hertzbeat] release hertzbeat version v1.4.4 by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1475](https://github.com/apache/hertzbeat/pull/1475)
* bugfix nginx collect http deadlock error by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1476](https://github.com/apache/hertzbeat/pull/1476)
* alarm calculate ignore metrics collect code - TIMEOUT by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1478](https://github.com/apache/hertzbeat/pull/1478)
## New Contributors
* @ZY945 made their first contribution in <https://github.com/apache/hertzbeat/pull/1407>
* @prolevel1 made their first contribution in <https://github.com/apache/hertzbeat/pull/1412>
* @ZhangZixuan1994 made their first contribution in <https://github.com/apache/hertzbeat/pull/1451>
* @hurenjie1 made their first contribution in <https://github.com/apache/hertzbeat/pull/1458>
* @tslj1024 made their first contribution in <https://github.com/apache/hertzbeat/pull/1461>
* @ldysdu made their first contribution in <https://github.com/apache/hertzbeat/pull/1455>
* @ZY945 made their first contribution in [https://github.com/apache/hertzbeat/pull/1407](https://github.com/apache/hertzbeat/pull/1407)
* @prolevel1 made their first contribution in [https://github.com/apache/hertzbeat/pull/1412](https://github.com/apache/hertzbeat/pull/1412)
* @ZhangZixuan1994 made their first contribution in [https://github.com/apache/hertzbeat/pull/1451](https://github.com/apache/hertzbeat/pull/1451)
* @hurenjie1 made their first contribution in [https://github.com/apache/hertzbeat/pull/1458](https://github.com/apache/hertzbeat/pull/1458)
* @tslj1024 made their first contribution in [https://github.com/apache/hertzbeat/pull/1461](https://github.com/apache/hertzbeat/pull/1461)
* @ldysdu made their first contribution in [https://github.com/apache/hertzbeat/pull/1455](https://github.com/apache/hertzbeat/pull/1455)
---
@@ -158,5 +158,5 @@ Detailed config refer to [Install HertzBeat via Docker](https://hertzbeat.apache
---
**Github: <https://github.com/apache/hertzbeat>**
**Gitee: <https://gitee.com/hertzbeat/hertzbeat>**
**Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)**
**Gitee: [https://gitee.com/hertzbeat/hertzbeat](https://gitee.com/hertzbeat/hertzbeat)**
+3 -3
View File
@@ -304,14 +304,14 @@ Special thanks to the Champions and Mentors who have kindly offered guidance to
**Repo Url**
**<https://github.com/apache/hertzbeat>**
**[https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)**
Welcome to star us🐶🐶🐶
**Home Url**
**<https://hertzbeat.apache.org/>**
**[https://hertzbeat.apache.org/](https://hertzbeat.apache.org/)**
**Email List**
**<dev@hertzbeat.apache.org>**
**[dev@hertzbeat.apache.org](mailto:dev@hertzbeat.apache.org)**
@@ -13,9 +13,9 @@ HertzBeat is a powerful custom monitoring capabilities, high-performance cluster
- High-performance, supports horizontal expansion of multiple collector clusters, supports multi-isolated network monitoring, and cloud edge collaboration.
- Free alarm threshold rules, `mail,` `Discord,` `Slack,` `Telegram,` `Dingding,` `wechat,` `Feibook,` `SMS,` `Webhook,` `Server sauce,` and other ways to send messages in a timely manner.
**Github: <https://github.com/apache/hertzbeat>**
**Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)**
**Gitee: <https://gitee.com/hertzbeat/hertzbeat>**
**Gitee: [https://gitee.com/hertzbeat/hertzbeat](https://gitee.com/hertzbeat/hertzbeat)**
## What is Open Source Summer?
+290 -290
View File
@@ -16,9 +16,9 @@ At the same time, some bugs were fixed and some functions were optimized, and mo
**Of course, the most important thing is to give the best thanks to the contributors in the community!**
Download Page: <https://hertzbeat.apache.org/docs/download/>
Download Page: [https://hertzbeat.apache.org/docs/download/](https://hertzbeat.apache.org/docs/download/)
Upgrade Guide: <https://hertzbeat.apache.org/blog/2024/06/11/hertzbeat-v1.6.0-update/>
Upgrade Guide: [https://hertzbeat.apache.org/blog/2024/06/11/hertzbeat-v1.6.0-update/](https://hertzbeat.apache.org/blog/2024/06/11/hertzbeat-v1.6.0-update/)
## What is HertzBeat?
@@ -38,7 +38,7 @@ Upgrade Guide: <https://hertzbeat.apache.org/blog/2024/06/11/hertzbeat-v1.6.0-up
![HertzBeat](/img/docs/hertzbeat-arch.png)
**Github: <https://github.com/apache/hertzbeat>**
**Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)**
## HertzBeat's 1.6.0 Version Release
@@ -78,292 +78,292 @@ Upgrade Guide: <https://hertzbeat.apache.org/blog/2024/06/11/hertzbeat-v1.6.0-up
## What's Changed
* bugfix collector can not startup alone by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1633>
* translate some hertzbeat blog by @TJxiaobao in <https://github.com/apache/hertzbeat/pull/1635>
* Check class description by @ZY945 in <https://github.com/apache/hertzbeat/pull/1638>
* translate class description to english by @TJxiaobao in <https://github.com/apache/hertzbeat/pull/1641>
* support monitor metrics name i18n: ClickHouse by @ZY945 in <https://github.com/apache/hertzbeat/pull/1642>
* translate blog 20220601 to English by @vinci-897 in <https://github.com/apache/hertzbeat/pull/1646>
* add a online prometheus parser and a prometheus-like push style. by @vinci-897 in <https://github.com/apache/hertzbeat/pull/1644>
* translate blog 20220320 to English by @vinci-897 in <https://github.com/apache/hertzbeat/pull/1647>
* support monitor metrics name i18n: DynamicTp by @ZY945 in <https://github.com/apache/hertzbeat/pull/1649>
* translate blog 20220228 to English by @vinci-897 in <https://github.com/apache/hertzbeat/pull/1648>
* translate blog 20220310 to English by @vinci-897 in <https://github.com/apache/hertzbeat/pull/1651>
* translate blog 20220904 to English by @vinci-897 in <https://github.com/apache/hertzbeat/pull/1652>
* support monitor metrics name i18n: Airflow by @ZY945 in <https://github.com/apache/hertzbeat/pull/1654>
* support monitor metrics name i18n: IoTDB by @ZY945 in <https://github.com/apache/hertzbeat/pull/1659>
* Translate 2022-02-11-hertzbeat document by @wang1027-wqh in <https://github.com/apache/hertzbeat/pull/1660>
* bugfix The annotation @Transactional specifies rollbackFor. by @handy-git in <https://github.com/apache/hertzbeat/pull/1643>
* add handy-git as a contributor for code by @allcontributors in <https://github.com/apache/hertzbeat/pull/1661>
* feature:Translate 2022-02-17-hertzbeat Document by @wang1027-wqh in <https://github.com/apache/hertzbeat/pull/1662>
* support monitor metrics name i18n: rocketmq by @ZY945 in <https://github.com/apache/hertzbeat/pull/1663>
* [doc] update relate doc and readme by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1667>
* bugfix monitoring mongodb not work in springboot3 by @ZY945 in <https://github.com/apache/hertzbeat/pull/1668>
* [feature] add storm monitor by @starmilkxin in <https://github.com/apache/hertzbeat/pull/1673>
* [bugfix] fixed the issue in http_sd where services were incorrectly reported as available when they were actually unavailable by @starmilkxin in <https://github.com/apache/hertzbeat/pull/1678>
* remove mysql-oracle dependency jar from release package lib by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1680>
* System config theme by @TJxiaobao in <https://github.com/apache/hertzbeat/pull/1636>
* update webapp menu layout and doc by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1682>
* bugfix can not find mysql dependency when startup by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1686>
* support config common aes secret by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1683>
* [bugfix]fix the issue of add redis cluster node test error report(#1601) by @LiuTianyou in <https://github.com/apache/hertzbeat/pull/1684>
* add LiuTianyou as a contributor for code by @allcontributors in <https://github.com/apache/hertzbeat/pull/1687>
* mongodb monitoring support custom connection timeout param by @ZY945 in <https://github.com/apache/hertzbeat/pull/1697>
* bugfix old data decode error when use new common-secret by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1696>
* [bugfix] fix bug where reopening pop-up window still retained previously edited data after closing. by @starmilkxin in <https://github.com/apache/hertzbeat/pull/1698>
* monitor center add search type modal by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1699>
* fix status page logo overflow by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1700>
* bugfix npe monitor jobid may be null by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1701>
* support custom main menus in monitor template by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1703>
* update home website doc by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1712>
* [Improve] change package group to org Apache HertzBeat™ by @vinci-897 in <https://github.com/apache/hertzbeat/pull/1724>
* [improve] initial license clean up by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1725>
* update manager and collector logback config(#1704) by @handy-git in <https://github.com/apache/hertzbeat/pull/1723>
* fix(sec): upgrade com.h2database:h2 to by @WinterKi1ler in <https://github.com/apache/hertzbeat/pull/1718>
* add WinterKi1ler as a contributor for code by @allcontributors in <https://github.com/apache/hertzbeat/pull/1736>
* update asf branch protected check by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1738>
* [doc]Update star chart by @zqr10159 in <https://github.com/apache/hertzbeat/pull/1737>
* [fixed] fixed click collector online offline button error by @miki-hmt in <https://github.com/apache/hertzbeat/pull/1734>
* [improve] initial doc clean up by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1741>
* [Improvement]Support multiple receivers. by @zqr10159 in <https://github.com/apache/hertzbeat/pull/1731>
* [improvement]Add lisence. by @zqr10159 in <https://github.com/apache/hertzbeat/pull/1746>
* Backend LICENSE Initialize by @wang1027-wqh in <https://github.com/apache/hertzbeat/pull/1744>
* Back-end dependency upgrade by @TJxiaobao in <https://github.com/apache/hertzbeat/pull/1743>
* [Improve] run hertzbeat in docker compose support dependen service condition by @gjjjj0101 in <https://github.com/apache/hertzbeat/pull/1748>
* [bugfix] fix statuspage index exception by @makechoicenow in <https://github.com/apache/hertzbeat/pull/1747>
* remove unlicensed dependency 'wolfy87 eventemitter' by @alpha951 in <https://github.com/apache/hertzbeat/pull/1745>
* [improve] auto label when pr, update asf config by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1749>
* [improve] update asf config set required status checks context by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1751>
* [improve] home add apache info by @a-little-fool in <https://github.com/apache/hertzbeat/pull/1740>
* [doc] Change e2e path by @crossoverJie in <https://github.com/apache/hertzbeat/pull/1758>
* fix : ingress tls inoperative by @PeixyJ in <https://github.com/apache/hertzbeat/pull/1760>
* [refactor] method improvement rationale by @dukbong in <https://github.com/apache/hertzbeat/pull/1757>
* [improve] create disclaimer file, add incubating in describe by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1764>
* [improve] update new hertzbeat brand logo, update doc by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1761>
* Complete the code comment translation of the common module by @Hi-Mr-Wind in <https://github.com/apache/hertzbeat/pull/1766>
* Remove unnecessary if-else statement. by @dukbong in <https://github.com/apache/hertzbeat/pull/1770>
* [doc] remove and translate chinese to english in warehous by @xuziyang in <https://github.com/apache/hertzbeat/pull/1773>
* Replace deprecated methods with builder pattern for RedisURI construction by @dukbong in <https://github.com/apache/hertzbeat/pull/1772>
* remove and translate chinese to english in collector,script,push,remoting and manager module by @MananPoojara in <https://github.com/apache/hertzbeat/pull/1774>
* Added the function of sending SMS messages through Alibaba Cloud. by @lwqzz in <https://github.com/apache/hertzbeat/pull/1768>
* [improve]Add frontend license. by @zqr10159 in <https://github.com/apache/hertzbeat/pull/1776>
* [test] Add RedisSingleCollectImplTest by @crossoverJie in <https://github.com/apache/hertzbeat/pull/1784>
* [refactor] add override annotation by @handy-git in <https://github.com/apache/hertzbeat/pull/1782>
* '[docs]bugfix: display syntax error of ipmi protocol' by @tomorrowshipyltm in <https://github.com/apache/hertzbeat/pull/1793>
* [doc] translate alerter moudle code chinese to english by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1765>
* [refactor] database-related properties class, type changed to record by @xuziyang in <https://github.com/apache/hertzbeat/pull/1786>
* Fix snmp template unit conversion problem by @TJxiaobao in <https://github.com/apache/hertzbeat/pull/1796>
* [doc] Add help documentation for clickhouse monitoring by @LiuTianyou in <https://github.com/apache/hertzbeat/pull/1798>
* [feature:update-checkstyle] Limit the java file header by @YxYL6125 in <https://github.com/apache/hertzbeat/pull/1799>
* [improve]Add external lib folder to store mysql and oracle driver. by @zqr10159 in <https://github.com/apache/hertzbeat/pull/1783>
* [Improve]When multiple lines are returned, each alarm is triggered instead of only the first alarm by @15613060203 in <https://github.com/apache/hertzbeat/pull/1797>
* [doc] add team page in website by @alpha951 in <https://github.com/apache/hertzbeat/pull/1800>
* [feature] Improve the import checkstyle by @crossoverJie in <https://github.com/apache/hertzbeat/pull/1802>
* [doc] Add help document for dns monitoring by @LiuTianyou in <https://github.com/apache/hertzbeat/pull/1804>
* [improve] preventing NPE by @dukbong in <https://github.com/apache/hertzbeat/pull/1808>
* [refactor] change the warehouse properties the type to record by @xuziyang in <https://github.com/apache/hertzbeat/pull/1806>
* Refactor: upgrade syntax to jdk17(instanceof & switch) by @Calvin979 in <https://github.com/apache/hertzbeat/pull/1807>
* [test] Add NginxCollect test by @crossoverJie in <https://github.com/apache/hertzbeat/pull/1809>
* [website] update team page by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1803>
* [test] Add RedisClusterCollectImplTest by @crossoverJie in <https://github.com/apache/hertzbeat/pull/1789>
* [improve] Fix typo ReqStatusResponse by @crossoverJie in <https://github.com/apache/hertzbeat/pull/1811>
* Comparing N objects for null with Assert.noNullElements(). by @dukbong in <https://github.com/apache/hertzbeat/pull/1814>
* [doc] Add help document for elasticsearch monitoring and ftp monitoring by @LiuTianyou in <https://github.com/apache/hertzbeat/pull/1815>
* [doc] add help documentation for huawei switch monitoring by @Alanxtl in <https://github.com/apache/hertzbeat/pull/1813>
* chore: upgrade the api-testing (e2e) to v0.0.16 by @LinuxSuRen in <https://github.com/apache/hertzbeat/pull/1817>
* [Remove]\[Improve\]Mail config by @zqr10159 in <https://github.com/apache/hertzbeat/pull/1819>
* Remove and translate chinese to english in code by @dukbong in <https://github.com/apache/hertzbeat/pull/1816>
* [feature]Add monitoring for Hbase Master by @zhangshenghang in <https://github.com/apache/hertzbeat/pull/1820>
* [doc] resolve code conflicts and coverage caused by pr(#1813) merge by @LiuTianyou in <https://github.com/apache/hertzbeat/pull/1821>
* [doc] Add help document for tidb and nacos monitoring by @Alanxtl in <https://github.com/apache/hertzbeat/pull/1823>
* [improve] use eclipselink orm replace of hibernate orm by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1801>
* [improve] Add whitespace checkstyle by @crossoverJie in <https://github.com/apache/hertzbeat/pull/1824>
* [bugfix] dns monitoring template add query class parameter by @LiuTianyou in <https://github.com/apache/hertzbeat/pull/1825>
* [Refactor] Preventing Unnecessary Object Creation and Using Utility Methods by @dukbong in <https://github.com/apache/hertzbeat/pull/1818>
* [doc]Add and modify Doris FE Chinese and English documentation by @zhangshenghang in <https://github.com/apache/hertzbeat/pull/1828>
* [docs] Optimize: add help docs for UDP port & Springboot3 help doc by @zuobiao-zhou in <https://github.com/apache/hertzbeat/pull/1832>
* Code Simplification, Structure Changes, and Translation Work, Along with a Question by @dukbong in <https://github.com/apache/hertzbeat/pull/1827>
* [doc] add help document for mongodb monitoring by @LiuTianyou in <https://github.com/apache/hertzbeat/pull/1834>
* [collector] fix: inverts the compareTo sort of MetricsCollect run queue by @Pzz-2021 in <https://github.com/apache/hertzbeat/pull/1837>
* [doc]Doc add debian system by @zhangshenghang in <https://github.com/apache/hertzbeat/pull/1842>
* [feature] Add Apache Hbase RegionServer monitoring by @zhangshenghang in <https://github.com/apache/hertzbeat/pull/1833>
* [improve] Optimize websocket monitor by @LiuTianyou in <https://github.com/apache/hertzbeat/pull/1838>
* [refactor] Split the WarehouseProperties class by @xuziyang in <https://github.com/apache/hertzbeat/pull/1830>
* [test] Add test for HttpsdImpl by @crossoverJie in <https://github.com/apache/hertzbeat/pull/1840>
* [fix] Fix the wrong comment by @xuziyang in <https://github.com/apache/hertzbeat/pull/1843>
* [refactor] trans and use assert by @dukbong in <https://github.com/apache/hertzbeat/pull/1841>
* [bugfix] modify the command in the mongodb monitoring template by @LiuTianyou in <https://github.com/apache/hertzbeat/pull/1844>
* [bigfix]Fix Debian system Top10 monitoring bug by @zhangshenghang in <https://github.com/apache/hertzbeat/pull/1846>
* [cleanup]Delete the corresponding Chinese comments by @hudongdong129 in <https://github.com/apache/hertzbeat/pull/1847>
* [doc] translates chinese comment to english. by @dukbong in <https://github.com/apache/hertzbeat/pull/1853>
* [doc] fix error and add help document for prometheus task by @LiuTianyou in <https://github.com/apache/hertzbeat/pull/1852>
* [feature] Add Linux process monitoring by @zhangshenghang in <https://github.com/apache/hertzbeat/pull/1857>
* [test] Add test for FtpCollectImpl by @crossoverJie in <https://github.com/apache/hertzbeat/pull/1856>
* [improve] use apache jexl replace of aviator by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1859>
* [bugfix] jpa data save logic repair by @zhangshenghang in <https://github.com/apache/hertzbeat/pull/1863>
* [feature] add influxdb metrics monitoring by @TJxiaobao in <https://github.com/apache/hertzbeat/pull/1730>
* [doc] add help document for rocketmq by @LiuTianyou in <https://github.com/apache/hertzbeat/pull/1874>
* [improve] Imporve checkstyle of test code. by @crossoverJie in <https://github.com/apache/hertzbeat/pull/1864>
* [feature] Support Redfish protocol to monitoring server by @gjjjj0101 in <https://github.com/apache/hertzbeat/pull/1867>
* Fix debian monitoring template issue about process monitoring by @LLP2333 in <https://github.com/apache/hertzbeat/pull/1868>
* [bugfix] centos Top10 shows missing one by @zhangshenghang in <https://github.com/apache/hertzbeat/pull/1870>
* [improve] add website apache incubator footer by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1860>
* [doc] update help document by @LiuTianyou in <https://github.com/apache/hertzbeat/pull/1861>
* [featurn] support flyway database migration by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1875>
* [improve] Delete the timestamp field in the class MetricFamily.Metric by @xuziyang in <https://github.com/apache/hertzbeat/pull/1878>
* [improve] Use java.lang.AutoCloseable instead of CacheCloseable by @crossoverJie in <https://github.com/apache/hertzbeat/pull/1879>
* [bugfix]Fix top10 process command. by @zqr10159 in <https://github.com/apache/hertzbeat/pull/1876>
* [feature] support the VictoriaMetrics cluster by @xuziyang in <https://github.com/apache/hertzbeat/pull/1880>
* [improve] Refactor common cache code by @crossoverJie in <https://github.com/apache/hertzbeat/pull/1881>
* Eliminate Unnecessary Unboxing and Generics by @handy-git in <https://github.com/apache/hertzbeat/pull/1882>
* [bugfix]\[doc\]Add kafka sidebar. by @zqr10159 in <https://github.com/apache/hertzbeat/pull/1883>
* [doc] I18n for monitoring template yml metrics by @zuobiao-zhou in <https://github.com/apache/hertzbeat/pull/1888>
* [refactor] StoreProperties is no longer useful, delete it by @xuziyang in <https://github.com/apache/hertzbeat/pull/1887>
* bugfix statistical metrics data matching fails by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1884>
* [doc] add help doc for flink monitoring by @HeartLinked in <https://github.com/apache/hertzbeat/pull/1893>
* [doc] add almalinux documentation by @zhangshenghang in <https://github.com/apache/hertzbeat/pull/1892>
* [improve] Missing a generic by @crossoverJie in <https://github.com/apache/hertzbeat/pull/1889>
* [bugfix] Fixed some metrics of Jexlespression not matching in Elasticsearch by @zhangshenghang in <https://github.com/apache/hertzbeat/pull/1894>
* feat(*): Support Time Type to Tengine Data Storage by @Clownsw in <https://github.com/apache/hertzbeat/pull/1890>
* [feature] support random jwt secret when not custom by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1897>
* [doc] add opensuse doc by @zhangshenghang in <https://github.com/apache/hertzbeat/pull/1902>
* fix when manager restart, collect register error by @Ceilzcx in <https://github.com/apache/hertzbeat/pull/1896>
* [bugfix] fix can not use empty collection as query params in eclipselink by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1900>
* [doc] update doc add download page and pic by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1904>
* [test] Add test for UdpCollectImpl by @crossoverJie in <https://github.com/apache/hertzbeat/pull/1906>
* fix license by @yqxxgh in <https://github.com/apache/hertzbeat/pull/1907>
* [improve] refactor code by @Ceilzcx in <https://github.com/apache/hertzbeat/pull/1901>
* [type:bugfix] fix customized menu invalid bug #1898 by @Aias00 in <https://github.com/apache/hertzbeat/pull/1908>
* [type:bugfix] fix HTTP API bug #1895 by @Aias00 in <https://github.com/apache/hertzbeat/pull/1909>
* [test] Add test for WebsocketCollectImpl by @crossoverJie in <https://github.com/apache/hertzbeat/pull/1912>
* [doc] translates chinese comment to english. by @westboy in <https://github.com/apache/hertzbeat/pull/1914>
* [doc] Add HIP document and template by @crossoverJie in <https://github.com/apache/hertzbeat/pull/1913>
* [improve] clean up home webapp unused code by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1915>
* [feature] support use ngql query metrics from nebulaGraph by @LiuTianyou in <https://github.com/apache/hertzbeat/pull/1917>
* [doc] Improve the Contribution Documentation. by @crossoverJie in <https://github.com/apache/hertzbeat/pull/1918>
* [featrue]add apache hdfs monitor by @zhangshenghang in <https://github.com/apache/hertzbeat/pull/1920>
* [doc] update hbase documentation description by @zhangshenghang in <https://github.com/apache/hertzbeat/pull/1921>
* [doc] Add documentation for nebulaGraph cluster monitoring and custom monitoring using NGQL, and clean up useless parameters by @LiuTianyou in <https://github.com/apache/hertzbeat/pull/1923>
* [test] Add test for TelnetCollectImplTest by @crossoverJie in <https://github.com/apache/hertzbeat/pull/1924>
* fix(*): fix TdEngine Init not found Database by @Clownsw in <https://github.com/apache/hertzbeat/pull/1891>
* [doc] update contribution and add run-build guide by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1919>
* bugfix collector startup error can not find JdbcClient by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1925>
* [doc] add help document for freebsd monitoring by @LiuTianyou in <https://github.com/apache/hertzbeat/pull/1928>
* [refactoring] Split AbstractHistoryDataStorage class by @xuziyang in <https://github.com/apache/hertzbeat/pull/1926>
* [fix] fixed name error in monitoring template and improve NGQL protocol by @LiuTianyou in <https://github.com/apache/hertzbeat/pull/1931>
* [refactoring] Split AbstractRealTimeDataStorage class by @xuziyang in <https://github.com/apache/hertzbeat/pull/1935>
* [bugfix] fix ssl-cert days_remaining and npe by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1934>
* [feature] add apache yarn monitor by @zhangshenghang in <https://github.com/apache/hertzbeat/pull/1937>
* [doc] add help document for redhat monitoring and rocky linux monitoring by @LiuTianyou in <https://github.com/apache/hertzbeat/pull/1939>
* [test] Add test for NtpCollectImpl by @crossoverJie in <https://github.com/apache/hertzbeat/pull/1940>
* [bugfix] fix alarm center tags display error by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1938>
* [improve] prepare for release hertzbeat v1.6.0 by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1929>
* add:Updated the Open Source Summer Project blog. by @TJxiaobao in <https://github.com/apache/hertzbeat/pull/1943>
* [feature] Support monitoring of OpenAI accounts by @zuobiao-zhou in <https://github.com/apache/hertzbeat/pull/1947>
* [refactoring] Inject a single instance of the data store by @xuziyang in <https://github.com/apache/hertzbeat/pull/1944>
* [refactoring] AbstractHistoryDataStorage implement the DisposableBean by @xuziyang in <https://github.com/apache/hertzbeat/pull/1946>
* [doc] update iotdb init document by @zhangshenghang in <https://github.com/apache/hertzbeat/pull/1948>
* [improve] update build script by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1949>
* [test] add test for NgqlCollectImpl by @LiuTianyou in <https://github.com/apache/hertzbeat/pull/1953>
* [bugfix]Replace monitors to alert. by @zqr10159 in <https://github.com/apache/hertzbeat/pull/1954>
* [improve] add llm, server menu and update doc by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1955>
* [improve]\[HIP\] HIP-01: Refactoring AbstractCollect by @crossoverJie in <https://github.com/apache/hertzbeat/pull/1930>
* [bugfix] fix ConnectionCommonCache possible npe by @crossoverJie in <https://github.com/apache/hertzbeat/pull/1959>
* [doc] add help document for eulerOS monitoring by @LiuTianyou in <https://github.com/apache/hertzbeat/pull/1960>
* [fixbug] Fix the problem of no data for springboot3 monitoring by @zhangshenghang in <https://github.com/apache/hertzbeat/pull/1961>
* commitfix the front-end popup cannot exit by @Yanshuming1 in <https://github.com/apache/hertzbeat/pull/1957>
* [fixbug] expression rule adaptation by @zhangshenghang in <https://github.com/apache/hertzbeat/pull/1963>
* [doc] add help doc for influxdb-promql and kafka-promql monitoring by @LiuTianyou in <https://github.com/apache/hertzbeat/pull/1965>
* [doc]: update readme-cn docs by @yuluo-yx in <https://github.com/apache/hertzbeat/pull/1964>
* [improve]\[HIP\] HIP-01: Implement refactoring AbstractCollect by @crossoverJie in <https://github.com/apache/hertzbeat/pull/1966>
* [chore] update .gitignore to save .idea/icon.png by @yuluo-yx in <https://github.com/apache/hertzbeat/pull/1971>
* [improve]\[bugfix\]: fix AlertTemplateUtilTest test exception and update code style by @yuluo-yx in <https://github.com/apache/hertzbeat/pull/1969>
* [feature] add apache hugegraph monitor by @zhangshenghang in <https://github.com/apache/hertzbeat/pull/1972>
* [improve] Implement cascading parameter list for SNMP protocol by @zuobiao-zhou in <https://github.com/apache/hertzbeat/pull/1976>
* [improve] optimize DateUtil and add test case by @yuluo-yx in <https://github.com/apache/hertzbeat/pull/1974>
* [feature]Hertzbeat custom plugin. by @zqr10159 in <https://github.com/apache/hertzbeat/pull/1973>
* update login page and status page color by @lwjxy in <https://github.com/apache/hertzbeat/pull/1977>
* [chore] update code style and add some comment by @yuluo-yx in <https://github.com/apache/hertzbeat/pull/1975>
* [doc]Hertzbeat plugin doc. by @zqr10159 in <https://github.com/apache/hertzbeat/pull/1980>
* [doc] update contributors and update status page style by @tomsun28 in <https://github.com/apache/hertzbeat/pull/1981>
* [feature] Implement cascading parameter list by @zuobiao-zhou in <https://github.com/apache/hertzbeat/pull/1978>
* [doc]update threshold alarm doc by @zhangshenghang in <https://github.com/apache/hertzbeat/pull/1983>
* [chore] optimize code style by @yuluo-yx in <https://github.com/apache/hertzbeat/pull/1984>
* [fix] Compatible with MongoDB versions earlier than 3.6 by @gjjjj0101 in <https://github.com/apache/hertzbeat/pull/1988>
* [chore] optimize manager code style by @yuluo-yx in <https://github.com/apache/hertzbeat/pull/1993>
* [doc] Translate part of documentation development.md under `zh-cn` directory from `en` to `zh-cn` by @Thespica in <https://github.com/apache/hertzbeat/pull/1995>
* [improve] http protocol prometheus parsing optimization by @zhangshenghang in <https://github.com/apache/hertzbeat/pull/1996>
* [feature] add at function for wechat by @Yanshuming1 in <https://github.com/apache/hertzbeat/pull/1994>
* [improve] add common util test by @yuluo-yx in <https://github.com/apache/hertzbeat/pull/2001>
* [improve] update release license notice and package by @tomsun28 in <https://github.com/apache/hertzbeat/pull/2003>
* [bugfix] fix collector startup error classpath by @tomsun28 in <https://github.com/apache/hertzbeat/pull/2004>
* [chore] optimize code style by @yuluo-yx in <https://github.com/apache/hertzbeat/pull/2000>
* [improve] Bump up `eslint-plugin-jsdoc` to 48.2.5 to support node 20+ by @Thespica in <https://github.com/apache/hertzbeat/pull/2005>
* [doc] fix doc highlighting by @boatrainlsz in <https://github.com/apache/hertzbeat/pull/2006>
* [web-app]feature: case insensitive search by @JavaProgrammerLB in <https://github.com/apache/hertzbeat/pull/2007>
* [feature] Support time calculation expressions. by @LiuTianyou in <https://github.com/apache/hertzbeat/pull/2009>
* [doc] add document for time expression by @LiuTianyou in <https://github.com/apache/hertzbeat/pull/2012>
* [feature] Add Apache Pulsar monitor by @zhangshenghang in <https://github.com/apache/hertzbeat/pull/2013>
* [doc] home verify release doc update by @tomsun28 in <https://github.com/apache/hertzbeat/pull/2014>
* [Improve] Improve clickhouse monitor And Improve Pulsar monitor by @zhangshenghang in <https://github.com/apache/hertzbeat/pull/2015>
* [doc] translate help document for memcached monitoring by @LiuTianyou in <https://github.com/apache/hertzbeat/pull/2019>
* [improve] optimize collector httpsd discovery by @yuluo-yx in <https://github.com/apache/hertzbeat/pull/1991>
* [optimize] optimize code style and logic, add unit test by @yuluo-yx in <https://github.com/apache/hertzbeat/pull/2010>
* [fix] Fix possible potential thread safe bugs by @gjjjj0101 in <https://github.com/apache/hertzbeat/pull/2021>
* [improve] add ci for home by @LiuTianyou in <https://github.com/apache/hertzbeat/pull/2024>
* [bugfix]Tag with empty value Shouldn't transform to Tag: by @JavaProgrammerLB in <https://github.com/apache/hertzbeat/pull/2025>
* [bugfix] modify popup confirm to clear cache and cancel popup save by @Yanshuming1 in <https://github.com/apache/hertzbeat/pull/2026>
* [improve] update monitor state desc by @tomsun28 in <https://github.com/apache/hertzbeat/pull/2028>
* bugfix: fix overflow of integers by @Calvin979 in <https://github.com/apache/hertzbeat/pull/2029>
* [improve] tips need update initial default password by @tomsun28 in <https://github.com/apache/hertzbeat/pull/2030>
* [improve] deprecate support iotdb 0.* version by @Ceilzcx in <https://github.com/apache/hertzbeat/pull/2032>
* [fixbug] required field check by @zhangshenghang in <https://github.com/apache/hertzbeat/pull/2022>
* [improve] add IcmpCollectImplTest by @zuobiao-zhou in <https://github.com/apache/hertzbeat/pull/2033>
* [improve] fix code style by @zuobiao-zhou in <https://github.com/apache/hertzbeat/pull/2034>
* [improve] increase the length limit of the username field by @zuobiao-zhou in <https://github.com/apache/hertzbeat/pull/2035>
* [improve] Checkstyle include testSource by @crossoverJie in <https://github.com/apache/hertzbeat/pull/2036>
* [bugfix] fix collector and frontend dependent license error by @tomsun28 in <https://github.com/apache/hertzbeat/pull/2037>
* [improve] Add test for MemcachedCollectImpl by @zuobiao-zhou in <https://github.com/apache/hertzbeat/pull/2044>
* [imprve] Remove duplicate indices by @zuobiao-zhou in <https://github.com/apache/hertzbeat/pull/2045>
* [docs]: fix several typos in docs by @lw-yang in <https://github.com/apache/hertzbeat/pull/2047>
* Add the missing parts of docs, fix layout, sync the English version with the Chinese version by @xfl12345 in <https://github.com/apache/hertzbeat/pull/2048>
* [improve] add filename check in home ci by @LiuTianyou in <https://github.com/apache/hertzbeat/pull/2049>
* [improve] update dependency licenses and remove the aliyun sms depend by @tomsun28 in <https://github.com/apache/hertzbeat/pull/2058>
* bugfix collector can not startup alone by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1633](https://github.com/apache/hertzbeat/pull/1633)
* translate some hertzbeat blog by @TJxiaobao in [https://github.com/apache/hertzbeat/pull/1635](https://github.com/apache/hertzbeat/pull/1635)
* Check class description by @ZY945 in [https://github.com/apache/hertzbeat/pull/1638](https://github.com/apache/hertzbeat/pull/1638)
* translate class description to english by @TJxiaobao in [https://github.com/apache/hertzbeat/pull/1641](https://github.com/apache/hertzbeat/pull/1641)
* support monitor metrics name i18n: ClickHouse by @ZY945 in [https://github.com/apache/hertzbeat/pull/1642](https://github.com/apache/hertzbeat/pull/1642)
* translate blog 20220601 to English by @vinci-897 in [https://github.com/apache/hertzbeat/pull/1646](https://github.com/apache/hertzbeat/pull/1646)
* add a online prometheus parser and a prometheus-like push style. by @vinci-897 in [https://github.com/apache/hertzbeat/pull/1644](https://github.com/apache/hertzbeat/pull/1644)
* translate blog 20220320 to English by @vinci-897 in [https://github.com/apache/hertzbeat/pull/1647](https://github.com/apache/hertzbeat/pull/1647)
* support monitor metrics name i18n: DynamicTp by @ZY945 in [https://github.com/apache/hertzbeat/pull/1649](https://github.com/apache/hertzbeat/pull/1649)
* translate blog 20220228 to English by @vinci-897 in [https://github.com/apache/hertzbeat/pull/1648](https://github.com/apache/hertzbeat/pull/1648)
* translate blog 20220310 to English by @vinci-897 in [https://github.com/apache/hertzbeat/pull/1651](https://github.com/apache/hertzbeat/pull/1651)
* translate blog 20220904 to English by @vinci-897 in [https://github.com/apache/hertzbeat/pull/1652](https://github.com/apache/hertzbeat/pull/1652)
* support monitor metrics name i18n: Airflow by @ZY945 in [https://github.com/apache/hertzbeat/pull/1654](https://github.com/apache/hertzbeat/pull/1654)
* support monitor metrics name i18n: IoTDB by @ZY945 in [https://github.com/apache/hertzbeat/pull/1659](https://github.com/apache/hertzbeat/pull/1659)
* Translate 2022-02-11-hertzbeat document by @wang1027-wqh in [https://github.com/apache/hertzbeat/pull/1660](https://github.com/apache/hertzbeat/pull/1660)
* bugfix The annotation @Transactional specifies rollbackFor. by @handy-git in [https://github.com/apache/hertzbeat/pull/1643](https://github.com/apache/hertzbeat/pull/1643)
* add handy-git as a contributor for code by @allcontributors in [https://github.com/apache/hertzbeat/pull/1661](https://github.com/apache/hertzbeat/pull/1661)
* feature:Translate 2022-02-17-hertzbeat Document by @wang1027-wqh in [https://github.com/apache/hertzbeat/pull/1662](https://github.com/apache/hertzbeat/pull/1662)
* support monitor metrics name i18n: rocketmq by @ZY945 in [https://github.com/apache/hertzbeat/pull/1663](https://github.com/apache/hertzbeat/pull/1663)
* [doc] update relate doc and readme by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1667](https://github.com/apache/hertzbeat/pull/1667)
* bugfix monitoring mongodb not work in springboot3 by @ZY945 in [https://github.com/apache/hertzbeat/pull/1668](https://github.com/apache/hertzbeat/pull/1668)
* [feature] add storm monitor by @starmilkxin in [https://github.com/apache/hertzbeat/pull/1673](https://github.com/apache/hertzbeat/pull/1673)
* [bugfix] fixed the issue in http_sd where services were incorrectly reported as available when they were actually unavailable by @starmilkxin in [https://github.com/apache/hertzbeat/pull/1678](https://github.com/apache/hertzbeat/pull/1678)
* remove mysql-oracle dependency jar from release package lib by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1680](https://github.com/apache/hertzbeat/pull/1680)
* System config theme by @TJxiaobao in [https://github.com/apache/hertzbeat/pull/1636](https://github.com/apache/hertzbeat/pull/1636)
* update webapp menu layout and doc by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1682](https://github.com/apache/hertzbeat/pull/1682)
* bugfix can not find mysql dependency when startup by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1686](https://github.com/apache/hertzbeat/pull/1686)
* support config common aes secret by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1683](https://github.com/apache/hertzbeat/pull/1683)
* [bugfix]fix the issue of add redis cluster node test error report(#1601) by @LiuTianyou in [https://github.com/apache/hertzbeat/pull/1684](https://github.com/apache/hertzbeat/pull/1684)
* add LiuTianyou as a contributor for code by @allcontributors in [https://github.com/apache/hertzbeat/pull/1687](https://github.com/apache/hertzbeat/pull/1687)
* mongodb monitoring support custom connection timeout param by @ZY945 in [https://github.com/apache/hertzbeat/pull/1697](https://github.com/apache/hertzbeat/pull/1697)
* bugfix old data decode error when use new common-secret by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1696](https://github.com/apache/hertzbeat/pull/1696)
* [bugfix] fix bug where reopening pop-up window still retained previously edited data after closing. by @starmilkxin in [https://github.com/apache/hertzbeat/pull/1698](https://github.com/apache/hertzbeat/pull/1698)
* monitor center add search type modal by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1699](https://github.com/apache/hertzbeat/pull/1699)
* fix status page logo overflow by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1700](https://github.com/apache/hertzbeat/pull/1700)
* bugfix npe monitor jobid may be null by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1701](https://github.com/apache/hertzbeat/pull/1701)
* support custom main menus in monitor template by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1703](https://github.com/apache/hertzbeat/pull/1703)
* update home website doc by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1712](https://github.com/apache/hertzbeat/pull/1712)
* [Improve] change package group to org Apache HertzBeat™ by @vinci-897 in [https://github.com/apache/hertzbeat/pull/1724](https://github.com/apache/hertzbeat/pull/1724)
* [improve] initial license clean up by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1725](https://github.com/apache/hertzbeat/pull/1725)
* update manager and collector logback config(#1704) by @handy-git in [https://github.com/apache/hertzbeat/pull/1723](https://github.com/apache/hertzbeat/pull/1723)
* fix(sec): upgrade com.h2database:h2 to by @WinterKi1ler in [https://github.com/apache/hertzbeat/pull/1718](https://github.com/apache/hertzbeat/pull/1718)
* add WinterKi1ler as a contributor for code by @allcontributors in [https://github.com/apache/hertzbeat/pull/1736](https://github.com/apache/hertzbeat/pull/1736)
* update asf branch protected check by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1738](https://github.com/apache/hertzbeat/pull/1738)
* [doc]Update star chart by @zqr10159 in [https://github.com/apache/hertzbeat/pull/1737](https://github.com/apache/hertzbeat/pull/1737)
* [fixed] fixed click collector online offline button error by @miki-hmt in [https://github.com/apache/hertzbeat/pull/1734](https://github.com/apache/hertzbeat/pull/1734)
* [improve] initial doc clean up by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1741](https://github.com/apache/hertzbeat/pull/1741)
* [Improvement]Support multiple receivers. by @zqr10159 in [https://github.com/apache/hertzbeat/pull/1731](https://github.com/apache/hertzbeat/pull/1731)
* [improvement]Add lisence. by @zqr10159 in [https://github.com/apache/hertzbeat/pull/1746](https://github.com/apache/hertzbeat/pull/1746)
* Backend LICENSE Initialize by @wang1027-wqh in [https://github.com/apache/hertzbeat/pull/1744](https://github.com/apache/hertzbeat/pull/1744)
* Back-end dependency upgrade by @TJxiaobao in [https://github.com/apache/hertzbeat/pull/1743](https://github.com/apache/hertzbeat/pull/1743)
* [Improve] run hertzbeat in docker compose support dependen service condition by @gjjjj0101 in [https://github.com/apache/hertzbeat/pull/1748](https://github.com/apache/hertzbeat/pull/1748)
* [bugfix] fix statuspage index exception by @makechoicenow in [https://github.com/apache/hertzbeat/pull/1747](https://github.com/apache/hertzbeat/pull/1747)
* remove unlicensed dependency 'wolfy87 eventemitter' by @alpha951 in [https://github.com/apache/hertzbeat/pull/1745](https://github.com/apache/hertzbeat/pull/1745)
* [improve] auto label when pr, update asf config by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1749](https://github.com/apache/hertzbeat/pull/1749)
* [improve] update asf config set required status checks context by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1751](https://github.com/apache/hertzbeat/pull/1751)
* [improve] home add apache info by @a-little-fool in [https://github.com/apache/hertzbeat/pull/1740](https://github.com/apache/hertzbeat/pull/1740)
* [doc] Change e2e path by @crossoverJie in [https://github.com/apache/hertzbeat/pull/1758](https://github.com/apache/hertzbeat/pull/1758)
* fix : ingress tls inoperative by @PeixyJ in [https://github.com/apache/hertzbeat/pull/1760](https://github.com/apache/hertzbeat/pull/1760)
* [refactor] method improvement rationale by @dukbong in [https://github.com/apache/hertzbeat/pull/1757](https://github.com/apache/hertzbeat/pull/1757)
* [improve] create disclaimer file, add incubating in describe by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1764](https://github.com/apache/hertzbeat/pull/1764)
* [improve] update new hertzbeat brand logo, update doc by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1761](https://github.com/apache/hertzbeat/pull/1761)
* Complete the code comment translation of the common module by @Hi-Mr-Wind in [https://github.com/apache/hertzbeat/pull/1766](https://github.com/apache/hertzbeat/pull/1766)
* Remove unnecessary if-else statement. by @dukbong in [https://github.com/apache/hertzbeat/pull/1770](https://github.com/apache/hertzbeat/pull/1770)
* [doc] remove and translate chinese to english in warehous by @xuziyang in [https://github.com/apache/hertzbeat/pull/1773](https://github.com/apache/hertzbeat/pull/1773)
* Replace deprecated methods with builder pattern for RedisURI construction by @dukbong in [https://github.com/apache/hertzbeat/pull/1772](https://github.com/apache/hertzbeat/pull/1772)
* remove and translate chinese to english in collector,script,push,remoting and manager module by @MananPoojara in [https://github.com/apache/hertzbeat/pull/1774](https://github.com/apache/hertzbeat/pull/1774)
* Added the function of sending SMS messages through Alibaba Cloud. by @lwqzz in [https://github.com/apache/hertzbeat/pull/1768](https://github.com/apache/hertzbeat/pull/1768)
* [improve]Add frontend license. by @zqr10159 in [https://github.com/apache/hertzbeat/pull/1776](https://github.com/apache/hertzbeat/pull/1776)
* [test] Add RedisSingleCollectImplTest by @crossoverJie in [https://github.com/apache/hertzbeat/pull/1784](https://github.com/apache/hertzbeat/pull/1784)
* [refactor] add override annotation by @handy-git in [https://github.com/apache/hertzbeat/pull/1782](https://github.com/apache/hertzbeat/pull/1782)
* '[docs]bugfix: display syntax error of ipmi protocol' by @tomorrowshipyltm in [https://github.com/apache/hertzbeat/pull/1793](https://github.com/apache/hertzbeat/pull/1793)
* [doc] translate alerter moudle code chinese to english by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1765](https://github.com/apache/hertzbeat/pull/1765)
* [refactor] database-related properties class, type changed to record by @xuziyang in [https://github.com/apache/hertzbeat/pull/1786](https://github.com/apache/hertzbeat/pull/1786)
* Fix snmp template unit conversion problem by @TJxiaobao in [https://github.com/apache/hertzbeat/pull/1796](https://github.com/apache/hertzbeat/pull/1796)
* [doc] Add help documentation for clickhouse monitoring by @LiuTianyou in [https://github.com/apache/hertzbeat/pull/1798](https://github.com/apache/hertzbeat/pull/1798)
* [feature:update-checkstyle] Limit the java file header by @YxYL6125 in [https://github.com/apache/hertzbeat/pull/1799](https://github.com/apache/hertzbeat/pull/1799)
* [improve]Add external lib folder to store mysql and oracle driver. by @zqr10159 in [https://github.com/apache/hertzbeat/pull/1783](https://github.com/apache/hertzbeat/pull/1783)
* [Improve]When multiple lines are returned, each alarm is triggered instead of only the first alarm by @15613060203 in [https://github.com/apache/hertzbeat/pull/1797](https://github.com/apache/hertzbeat/pull/1797)
* [doc] add team page in website by @alpha951 in [https://github.com/apache/hertzbeat/pull/1800](https://github.com/apache/hertzbeat/pull/1800)
* [feature] Improve the import checkstyle by @crossoverJie in [https://github.com/apache/hertzbeat/pull/1802](https://github.com/apache/hertzbeat/pull/1802)
* [doc] Add help document for dns monitoring by @LiuTianyou in [https://github.com/apache/hertzbeat/pull/1804](https://github.com/apache/hertzbeat/pull/1804)
* [improve] preventing NPE by @dukbong in [https://github.com/apache/hertzbeat/pull/1808](https://github.com/apache/hertzbeat/pull/1808)
* [refactor] change the warehouse properties the type to record by @xuziyang in [https://github.com/apache/hertzbeat/pull/1806](https://github.com/apache/hertzbeat/pull/1806)
* Refactor: upgrade syntax to jdk17(instanceof & switch) by @Calvin979 in [https://github.com/apache/hertzbeat/pull/1807](https://github.com/apache/hertzbeat/pull/1807)
* [test] Add NginxCollect test by @crossoverJie in [https://github.com/apache/hertzbeat/pull/1809](https://github.com/apache/hertzbeat/pull/1809)
* [website] update team page by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1803](https://github.com/apache/hertzbeat/pull/1803)
* [test] Add RedisClusterCollectImplTest by @crossoverJie in [https://github.com/apache/hertzbeat/pull/1789](https://github.com/apache/hertzbeat/pull/1789)
* [improve] Fix typo ReqStatusResponse by @crossoverJie in [https://github.com/apache/hertzbeat/pull/1811](https://github.com/apache/hertzbeat/pull/1811)
* Comparing N objects for null with Assert.noNullElements(). by @dukbong in [https://github.com/apache/hertzbeat/pull/1814](https://github.com/apache/hertzbeat/pull/1814)
* [doc] Add help document for elasticsearch monitoring and ftp monitoring by @LiuTianyou in [https://github.com/apache/hertzbeat/pull/1815](https://github.com/apache/hertzbeat/pull/1815)
* [doc] add help documentation for huawei switch monitoring by @Alanxtl in [https://github.com/apache/hertzbeat/pull/1813](https://github.com/apache/hertzbeat/pull/1813)
* chore: upgrade the api-testing (e2e) to v0.0.16 by @LinuxSuRen in [https://github.com/apache/hertzbeat/pull/1817](https://github.com/apache/hertzbeat/pull/1817)
* [Remove]\[Improve\]Mail config by @zqr10159 in [https://github.com/apache/hertzbeat/pull/1819](https://github.com/apache/hertzbeat/pull/1819)
* Remove and translate chinese to english in code by @dukbong in [https://github.com/apache/hertzbeat/pull/1816](https://github.com/apache/hertzbeat/pull/1816)
* [feature]Add monitoring for Hbase Master by @zhangshenghang in [https://github.com/apache/hertzbeat/pull/1820](https://github.com/apache/hertzbeat/pull/1820)
* [doc] resolve code conflicts and coverage caused by pr(#1813) merge by @LiuTianyou in [https://github.com/apache/hertzbeat/pull/1821](https://github.com/apache/hertzbeat/pull/1821)
* [doc] Add help document for tidb and nacos monitoring by @Alanxtl in [https://github.com/apache/hertzbeat/pull/1823](https://github.com/apache/hertzbeat/pull/1823)
* [improve] use eclipselink orm replace of hibernate orm by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1801](https://github.com/apache/hertzbeat/pull/1801)
* [improve] Add whitespace checkstyle by @crossoverJie in [https://github.com/apache/hertzbeat/pull/1824](https://github.com/apache/hertzbeat/pull/1824)
* [bugfix] dns monitoring template add query class parameter by @LiuTianyou in [https://github.com/apache/hertzbeat/pull/1825](https://github.com/apache/hertzbeat/pull/1825)
* [Refactor] Preventing Unnecessary Object Creation and Using Utility Methods by @dukbong in [https://github.com/apache/hertzbeat/pull/1818](https://github.com/apache/hertzbeat/pull/1818)
* [doc]Add and modify Doris FE Chinese and English documentation by @zhangshenghang in [https://github.com/apache/hertzbeat/pull/1828](https://github.com/apache/hertzbeat/pull/1828)
* [docs] Optimize: add help docs for UDP port & Springboot3 help doc by @zuobiao-zhou in [https://github.com/apache/hertzbeat/pull/1832](https://github.com/apache/hertzbeat/pull/1832)
* Code Simplification, Structure Changes, and Translation Work, Along with a Question by @dukbong in [https://github.com/apache/hertzbeat/pull/1827](https://github.com/apache/hertzbeat/pull/1827)
* [doc] add help document for mongodb monitoring by @LiuTianyou in [https://github.com/apache/hertzbeat/pull/1834](https://github.com/apache/hertzbeat/pull/1834)
* [collector] fix: inverts the compareTo sort of MetricsCollect run queue by @Pzz-2021 in [https://github.com/apache/hertzbeat/pull/1837](https://github.com/apache/hertzbeat/pull/1837)
* [doc]Doc add debian system by @zhangshenghang in [https://github.com/apache/hertzbeat/pull/1842](https://github.com/apache/hertzbeat/pull/1842)
* [feature] Add Apache Hbase RegionServer monitoring by @zhangshenghang in [https://github.com/apache/hertzbeat/pull/1833](https://github.com/apache/hertzbeat/pull/1833)
* [improve] Optimize websocket monitor by @LiuTianyou in [https://github.com/apache/hertzbeat/pull/1838](https://github.com/apache/hertzbeat/pull/1838)
* [refactor] Split the WarehouseProperties class by @xuziyang in [https://github.com/apache/hertzbeat/pull/1830](https://github.com/apache/hertzbeat/pull/1830)
* [test] Add test for HttpsdImpl by @crossoverJie in [https://github.com/apache/hertzbeat/pull/1840](https://github.com/apache/hertzbeat/pull/1840)
* [fix] Fix the wrong comment by @xuziyang in [https://github.com/apache/hertzbeat/pull/1843](https://github.com/apache/hertzbeat/pull/1843)
* [refactor] trans and use assert by @dukbong in [https://github.com/apache/hertzbeat/pull/1841](https://github.com/apache/hertzbeat/pull/1841)
* [bugfix] modify the command in the mongodb monitoring template by @LiuTianyou in [https://github.com/apache/hertzbeat/pull/1844](https://github.com/apache/hertzbeat/pull/1844)
* [bigfix]Fix Debian system Top10 monitoring bug by @zhangshenghang in [https://github.com/apache/hertzbeat/pull/1846](https://github.com/apache/hertzbeat/pull/1846)
* [cleanup]Delete the corresponding Chinese comments by @hudongdong129 in [https://github.com/apache/hertzbeat/pull/1847](https://github.com/apache/hertzbeat/pull/1847)
* [doc] translates chinese comment to english. by @dukbong in [https://github.com/apache/hertzbeat/pull/1853](https://github.com/apache/hertzbeat/pull/1853)
* [doc] fix error and add help document for prometheus task by @LiuTianyou in [https://github.com/apache/hertzbeat/pull/1852](https://github.com/apache/hertzbeat/pull/1852)
* [feature] Add Linux process monitoring by @zhangshenghang in [https://github.com/apache/hertzbeat/pull/1857](https://github.com/apache/hertzbeat/pull/1857)
* [test] Add test for FtpCollectImpl by @crossoverJie in [https://github.com/apache/hertzbeat/pull/1856](https://github.com/apache/hertzbeat/pull/1856)
* [improve] use apache jexl replace of aviator by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1859](https://github.com/apache/hertzbeat/pull/1859)
* [bugfix] jpa data save logic repair by @zhangshenghang in [https://github.com/apache/hertzbeat/pull/1863](https://github.com/apache/hertzbeat/pull/1863)
* [feature] add influxdb metrics monitoring by @TJxiaobao in [https://github.com/apache/hertzbeat/pull/1730](https://github.com/apache/hertzbeat/pull/1730)
* [doc] add help document for rocketmq by @LiuTianyou in [https://github.com/apache/hertzbeat/pull/1874](https://github.com/apache/hertzbeat/pull/1874)
* [improve] Imporve checkstyle of test code. by @crossoverJie in [https://github.com/apache/hertzbeat/pull/1864](https://github.com/apache/hertzbeat/pull/1864)
* [feature] Support Redfish protocol to monitoring server by @gjjjj0101 in [https://github.com/apache/hertzbeat/pull/1867](https://github.com/apache/hertzbeat/pull/1867)
* Fix debian monitoring template issue about process monitoring by @LLP2333 in [https://github.com/apache/hertzbeat/pull/1868](https://github.com/apache/hertzbeat/pull/1868)
* [bugfix] centos Top10 shows missing one by @zhangshenghang in [https://github.com/apache/hertzbeat/pull/1870](https://github.com/apache/hertzbeat/pull/1870)
* [improve] add website apache incubator footer by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1860](https://github.com/apache/hertzbeat/pull/1860)
* [doc] update help document by @LiuTianyou in [https://github.com/apache/hertzbeat/pull/1861](https://github.com/apache/hertzbeat/pull/1861)
* [featurn] support flyway database migration by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1875](https://github.com/apache/hertzbeat/pull/1875)
* [improve] Delete the timestamp field in the class MetricFamily.Metric by @xuziyang in [https://github.com/apache/hertzbeat/pull/1878](https://github.com/apache/hertzbeat/pull/1878)
* [improve] Use java.lang.AutoCloseable instead of CacheCloseable by @crossoverJie in [https://github.com/apache/hertzbeat/pull/1879](https://github.com/apache/hertzbeat/pull/1879)
* [bugfix]Fix top10 process command. by @zqr10159 in [https://github.com/apache/hertzbeat/pull/1876](https://github.com/apache/hertzbeat/pull/1876)
* [feature] support the VictoriaMetrics cluster by @xuziyang in [https://github.com/apache/hertzbeat/pull/1880](https://github.com/apache/hertzbeat/pull/1880)
* [improve] Refactor common cache code by @crossoverJie in [https://github.com/apache/hertzbeat/pull/1881](https://github.com/apache/hertzbeat/pull/1881)
* Eliminate Unnecessary Unboxing and Generics by @handy-git in [https://github.com/apache/hertzbeat/pull/1882](https://github.com/apache/hertzbeat/pull/1882)
* [bugfix]\[doc\]Add kafka sidebar. by @zqr10159 in [https://github.com/apache/hertzbeat/pull/1883](https://github.com/apache/hertzbeat/pull/1883)
* [doc] I18n for monitoring template yml metrics by @zuobiao-zhou in [https://github.com/apache/hertzbeat/pull/1888](https://github.com/apache/hertzbeat/pull/1888)
* [refactor] StoreProperties is no longer useful, delete it by @xuziyang in [https://github.com/apache/hertzbeat/pull/1887](https://github.com/apache/hertzbeat/pull/1887)
* bugfix statistical metrics data matching fails by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1884](https://github.com/apache/hertzbeat/pull/1884)
* [doc] add help doc for flink monitoring by @HeartLinked in [https://github.com/apache/hertzbeat/pull/1893](https://github.com/apache/hertzbeat/pull/1893)
* [doc] add almalinux documentation by @zhangshenghang in [https://github.com/apache/hertzbeat/pull/1892](https://github.com/apache/hertzbeat/pull/1892)
* [improve] Missing a generic by @crossoverJie in [https://github.com/apache/hertzbeat/pull/1889](https://github.com/apache/hertzbeat/pull/1889)
* [bugfix] Fixed some metrics of Jexlespression not matching in Elasticsearch by @zhangshenghang in [https://github.com/apache/hertzbeat/pull/1894](https://github.com/apache/hertzbeat/pull/1894)
* feat(*): Support Time Type to Tengine Data Storage by @Clownsw in [https://github.com/apache/hertzbeat/pull/1890](https://github.com/apache/hertzbeat/pull/1890)
* [feature] support random jwt secret when not custom by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1897](https://github.com/apache/hertzbeat/pull/1897)
* [doc] add opensuse doc by @zhangshenghang in [https://github.com/apache/hertzbeat/pull/1902](https://github.com/apache/hertzbeat/pull/1902)
* fix when manager restart, collect register error by @Ceilzcx in [https://github.com/apache/hertzbeat/pull/1896](https://github.com/apache/hertzbeat/pull/1896)
* [bugfix] fix can not use empty collection as query params in eclipselink by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1900](https://github.com/apache/hertzbeat/pull/1900)
* [doc] update doc add download page and pic by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1904](https://github.com/apache/hertzbeat/pull/1904)
* [test] Add test for UdpCollectImpl by @crossoverJie in [https://github.com/apache/hertzbeat/pull/1906](https://github.com/apache/hertzbeat/pull/1906)
* fix license by @yqxxgh in [https://github.com/apache/hertzbeat/pull/1907](https://github.com/apache/hertzbeat/pull/1907)
* [improve] refactor code by @Ceilzcx in [https://github.com/apache/hertzbeat/pull/1901](https://github.com/apache/hertzbeat/pull/1901)
* [type:bugfix] fix customized menu invalid bug #1898 by @Aias00 in [https://github.com/apache/hertzbeat/pull/1908](https://github.com/apache/hertzbeat/pull/1908)
* [type:bugfix] fix HTTP API bug #1895 by @Aias00 in [https://github.com/apache/hertzbeat/pull/1909](https://github.com/apache/hertzbeat/pull/1909)
* [test] Add test for WebsocketCollectImpl by @crossoverJie in [https://github.com/apache/hertzbeat/pull/1912](https://github.com/apache/hertzbeat/pull/1912)
* [doc] translates chinese comment to english. by @westboy in [https://github.com/apache/hertzbeat/pull/1914](https://github.com/apache/hertzbeat/pull/1914)
* [doc] Add HIP document and template by @crossoverJie in [https://github.com/apache/hertzbeat/pull/1913](https://github.com/apache/hertzbeat/pull/1913)
* [improve] clean up home webapp unused code by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1915](https://github.com/apache/hertzbeat/pull/1915)
* [feature] support use ngql query metrics from nebulaGraph by @LiuTianyou in [https://github.com/apache/hertzbeat/pull/1917](https://github.com/apache/hertzbeat/pull/1917)
* [doc] Improve the Contribution Documentation. by @crossoverJie in [https://github.com/apache/hertzbeat/pull/1918](https://github.com/apache/hertzbeat/pull/1918)
* [featrue]add apache hdfs monitor by @zhangshenghang in [https://github.com/apache/hertzbeat/pull/1920](https://github.com/apache/hertzbeat/pull/1920)
* [doc] update hbase documentation description by @zhangshenghang in [https://github.com/apache/hertzbeat/pull/1921](https://github.com/apache/hertzbeat/pull/1921)
* [doc] Add documentation for nebulaGraph cluster monitoring and custom monitoring using NGQL, and clean up useless parameters by @LiuTianyou in [https://github.com/apache/hertzbeat/pull/1923](https://github.com/apache/hertzbeat/pull/1923)
* [test] Add test for TelnetCollectImplTest by @crossoverJie in [https://github.com/apache/hertzbeat/pull/1924](https://github.com/apache/hertzbeat/pull/1924)
* fix(*): fix TdEngine Init not found Database by @Clownsw in [https://github.com/apache/hertzbeat/pull/1891](https://github.com/apache/hertzbeat/pull/1891)
* [doc] update contribution and add run-build guide by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1919](https://github.com/apache/hertzbeat/pull/1919)
* bugfix collector startup error can not find JdbcClient by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1925](https://github.com/apache/hertzbeat/pull/1925)
* [doc] add help document for freebsd monitoring by @LiuTianyou in [https://github.com/apache/hertzbeat/pull/1928](https://github.com/apache/hertzbeat/pull/1928)
* [refactoring] Split AbstractHistoryDataStorage class by @xuziyang in [https://github.com/apache/hertzbeat/pull/1926](https://github.com/apache/hertzbeat/pull/1926)
* [fix] fixed name error in monitoring template and improve NGQL protocol by @LiuTianyou in [https://github.com/apache/hertzbeat/pull/1931](https://github.com/apache/hertzbeat/pull/1931)
* [refactoring] Split AbstractRealTimeDataStorage class by @xuziyang in [https://github.com/apache/hertzbeat/pull/1935](https://github.com/apache/hertzbeat/pull/1935)
* [bugfix] fix ssl-cert days_remaining and npe by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1934](https://github.com/apache/hertzbeat/pull/1934)
* [feature] add apache yarn monitor by @zhangshenghang in [https://github.com/apache/hertzbeat/pull/1937](https://github.com/apache/hertzbeat/pull/1937)
* [doc] add help document for redhat monitoring and rocky linux monitoring by @LiuTianyou in [https://github.com/apache/hertzbeat/pull/1939](https://github.com/apache/hertzbeat/pull/1939)
* [test] Add test for NtpCollectImpl by @crossoverJie in [https://github.com/apache/hertzbeat/pull/1940](https://github.com/apache/hertzbeat/pull/1940)
* [bugfix] fix alarm center tags display error by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1938](https://github.com/apache/hertzbeat/pull/1938)
* [improve] prepare for release hertzbeat v1.6.0 by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1929](https://github.com/apache/hertzbeat/pull/1929)
* add:Updated the Open Source Summer Project blog. by @TJxiaobao in [https://github.com/apache/hertzbeat/pull/1943](https://github.com/apache/hertzbeat/pull/1943)
* [feature] Support monitoring of OpenAI accounts by @zuobiao-zhou in [https://github.com/apache/hertzbeat/pull/1947](https://github.com/apache/hertzbeat/pull/1947)
* [refactoring] Inject a single instance of the data store by @xuziyang in [https://github.com/apache/hertzbeat/pull/1944](https://github.com/apache/hertzbeat/pull/1944)
* [refactoring] AbstractHistoryDataStorage implement the DisposableBean by @xuziyang in [https://github.com/apache/hertzbeat/pull/1946](https://github.com/apache/hertzbeat/pull/1946)
* [doc] update iotdb init document by @zhangshenghang in [https://github.com/apache/hertzbeat/pull/1948](https://github.com/apache/hertzbeat/pull/1948)
* [improve] update build script by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1949](https://github.com/apache/hertzbeat/pull/1949)
* [test] add test for NgqlCollectImpl by @LiuTianyou in [https://github.com/apache/hertzbeat/pull/1953](https://github.com/apache/hertzbeat/pull/1953)
* [bugfix]Replace monitors to alert. by @zqr10159 in [https://github.com/apache/hertzbeat/pull/1954](https://github.com/apache/hertzbeat/pull/1954)
* [improve] add llm, server menu and update doc by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1955](https://github.com/apache/hertzbeat/pull/1955)
* [improve]\[HIP\] HIP-01: Refactoring AbstractCollect by @crossoverJie in [https://github.com/apache/hertzbeat/pull/1930](https://github.com/apache/hertzbeat/pull/1930)
* [bugfix] fix ConnectionCommonCache possible npe by @crossoverJie in [https://github.com/apache/hertzbeat/pull/1959](https://github.com/apache/hertzbeat/pull/1959)
* [doc] add help document for eulerOS monitoring by @LiuTianyou in [https://github.com/apache/hertzbeat/pull/1960](https://github.com/apache/hertzbeat/pull/1960)
* [fixbug] Fix the problem of no data for springboot3 monitoring by @zhangshenghang in [https://github.com/apache/hertzbeat/pull/1961](https://github.com/apache/hertzbeat/pull/1961)
* commitfix the front-end popup cannot exit by @Yanshuming1 in [https://github.com/apache/hertzbeat/pull/1957](https://github.com/apache/hertzbeat/pull/1957)
* [fixbug] expression rule adaptation by @zhangshenghang in [https://github.com/apache/hertzbeat/pull/1963](https://github.com/apache/hertzbeat/pull/1963)
* [doc] add help doc for influxdb-promql and kafka-promql monitoring by @LiuTianyou in [https://github.com/apache/hertzbeat/pull/1965](https://github.com/apache/hertzbeat/pull/1965)
* [doc]: update readme-cn docs by @yuluo-yx in [https://github.com/apache/hertzbeat/pull/1964](https://github.com/apache/hertzbeat/pull/1964)
* [improve]\[HIP\] HIP-01: Implement refactoring AbstractCollect by @crossoverJie in [https://github.com/apache/hertzbeat/pull/1966](https://github.com/apache/hertzbeat/pull/1966)
* [chore] update .gitignore to save .idea/icon.png by @yuluo-yx in [https://github.com/apache/hertzbeat/pull/1971](https://github.com/apache/hertzbeat/pull/1971)
* [improve]\[bugfix\]: fix AlertTemplateUtilTest test exception and update code style by @yuluo-yx in [https://github.com/apache/hertzbeat/pull/1969](https://github.com/apache/hertzbeat/pull/1969)
* [feature] add apache hugegraph monitor by @zhangshenghang in [https://github.com/apache/hertzbeat/pull/1972](https://github.com/apache/hertzbeat/pull/1972)
* [improve] Implement cascading parameter list for SNMP protocol by @zuobiao-zhou in [https://github.com/apache/hertzbeat/pull/1976](https://github.com/apache/hertzbeat/pull/1976)
* [improve] optimize DateUtil and add test case by @yuluo-yx in [https://github.com/apache/hertzbeat/pull/1974](https://github.com/apache/hertzbeat/pull/1974)
* [feature]Hertzbeat custom plugin. by @zqr10159 in [https://github.com/apache/hertzbeat/pull/1973](https://github.com/apache/hertzbeat/pull/1973)
* update login page and status page color by @lwjxy in [https://github.com/apache/hertzbeat/pull/1977](https://github.com/apache/hertzbeat/pull/1977)
* [chore] update code style and add some comment by @yuluo-yx in [https://github.com/apache/hertzbeat/pull/1975](https://github.com/apache/hertzbeat/pull/1975)
* [doc]Hertzbeat plugin doc. by @zqr10159 in [https://github.com/apache/hertzbeat/pull/1980](https://github.com/apache/hertzbeat/pull/1980)
* [doc] update contributors and update status page style by @tomsun28 in [https://github.com/apache/hertzbeat/pull/1981](https://github.com/apache/hertzbeat/pull/1981)
* [feature] Implement cascading parameter list by @zuobiao-zhou in [https://github.com/apache/hertzbeat/pull/1978](https://github.com/apache/hertzbeat/pull/1978)
* [doc]update threshold alarm doc by @zhangshenghang in [https://github.com/apache/hertzbeat/pull/1983](https://github.com/apache/hertzbeat/pull/1983)
* [chore] optimize code style by @yuluo-yx in [https://github.com/apache/hertzbeat/pull/1984](https://github.com/apache/hertzbeat/pull/1984)
* [fix] Compatible with MongoDB versions earlier than 3.6 by @gjjjj0101 in [https://github.com/apache/hertzbeat/pull/1988](https://github.com/apache/hertzbeat/pull/1988)
* [chore] optimize manager code style by @yuluo-yx in [https://github.com/apache/hertzbeat/pull/1993](https://github.com/apache/hertzbeat/pull/1993)
* [doc] Translate part of documentation development.md under `zh-cn` directory from `en` to `zh-cn` by @Thespica in [https://github.com/apache/hertzbeat/pull/1995](https://github.com/apache/hertzbeat/pull/1995)
* [improve] http protocol prometheus parsing optimization by @zhangshenghang in [https://github.com/apache/hertzbeat/pull/1996](https://github.com/apache/hertzbeat/pull/1996)
* [feature] add at function for wechat by @Yanshuming1 in [https://github.com/apache/hertzbeat/pull/1994](https://github.com/apache/hertzbeat/pull/1994)
* [improve] add common util test by @yuluo-yx in [https://github.com/apache/hertzbeat/pull/2001](https://github.com/apache/hertzbeat/pull/2001)
* [improve] update release license notice and package by @tomsun28 in [https://github.com/apache/hertzbeat/pull/2003](https://github.com/apache/hertzbeat/pull/2003)
* [bugfix] fix collector startup error classpath by @tomsun28 in [https://github.com/apache/hertzbeat/pull/2004](https://github.com/apache/hertzbeat/pull/2004)
* [chore] optimize code style by @yuluo-yx in [https://github.com/apache/hertzbeat/pull/2000](https://github.com/apache/hertzbeat/pull/2000)
* [improve] Bump up `eslint-plugin-jsdoc` to 48.2.5 to support node 20+ by @Thespica in [https://github.com/apache/hertzbeat/pull/2005](https://github.com/apache/hertzbeat/pull/2005)
* [doc] fix doc highlighting by @boatrainlsz in [https://github.com/apache/hertzbeat/pull/2006](https://github.com/apache/hertzbeat/pull/2006)
* [web-app]feature: case insensitive search by @JavaProgrammerLB in [https://github.com/apache/hertzbeat/pull/2007](https://github.com/apache/hertzbeat/pull/2007)
* [feature] Support time calculation expressions. by @LiuTianyou in [https://github.com/apache/hertzbeat/pull/2009](https://github.com/apache/hertzbeat/pull/2009)
* [doc] add document for time expression by @LiuTianyou in [https://github.com/apache/hertzbeat/pull/2012](https://github.com/apache/hertzbeat/pull/2012)
* [feature] Add Apache Pulsar monitor by @zhangshenghang in [https://github.com/apache/hertzbeat/pull/2013](https://github.com/apache/hertzbeat/pull/2013)
* [doc] home verify release doc update by @tomsun28 in [https://github.com/apache/hertzbeat/pull/2014](https://github.com/apache/hertzbeat/pull/2014)
* [Improve] Improve clickhouse monitor And Improve Pulsar monitor by @zhangshenghang in [https://github.com/apache/hertzbeat/pull/2015](https://github.com/apache/hertzbeat/pull/2015)
* [doc] translate help document for memcached monitoring by @LiuTianyou in [https://github.com/apache/hertzbeat/pull/2019](https://github.com/apache/hertzbeat/pull/2019)
* [improve] optimize collector httpsd discovery by @yuluo-yx in [https://github.com/apache/hertzbeat/pull/1991](https://github.com/apache/hertzbeat/pull/1991)
* [optimize] optimize code style and logic, add unit test by @yuluo-yx in [https://github.com/apache/hertzbeat/pull/2010](https://github.com/apache/hertzbeat/pull/2010)
* [fix] Fix possible potential thread safe bugs by @gjjjj0101 in [https://github.com/apache/hertzbeat/pull/2021](https://github.com/apache/hertzbeat/pull/2021)
* [improve] add ci for home by @LiuTianyou in [https://github.com/apache/hertzbeat/pull/2024](https://github.com/apache/hertzbeat/pull/2024)
* [bugfix]Tag with empty value Shouldn't transform to Tag: by @JavaProgrammerLB in [https://github.com/apache/hertzbeat/pull/2025](https://github.com/apache/hertzbeat/pull/2025)
* [bugfix] modify popup confirm to clear cache and cancel popup save by @Yanshuming1 in [https://github.com/apache/hertzbeat/pull/2026](https://github.com/apache/hertzbeat/pull/2026)
* [improve] update monitor state desc by @tomsun28 in [https://github.com/apache/hertzbeat/pull/2028](https://github.com/apache/hertzbeat/pull/2028)
* bugfix: fix overflow of integers by @Calvin979 in [https://github.com/apache/hertzbeat/pull/2029](https://github.com/apache/hertzbeat/pull/2029)
* [improve] tips need update initial default password by @tomsun28 in [https://github.com/apache/hertzbeat/pull/2030](https://github.com/apache/hertzbeat/pull/2030)
* [improve] deprecate support iotdb 0.* version by @Ceilzcx in [https://github.com/apache/hertzbeat/pull/2032](https://github.com/apache/hertzbeat/pull/2032)
* [fixbug] required field check by @zhangshenghang in [https://github.com/apache/hertzbeat/pull/2022](https://github.com/apache/hertzbeat/pull/2022)
* [improve] add IcmpCollectImplTest by @zuobiao-zhou in [https://github.com/apache/hertzbeat/pull/2033](https://github.com/apache/hertzbeat/pull/2033)
* [improve] fix code style by @zuobiao-zhou in [https://github.com/apache/hertzbeat/pull/2034](https://github.com/apache/hertzbeat/pull/2034)
* [improve] increase the length limit of the username field by @zuobiao-zhou in [https://github.com/apache/hertzbeat/pull/2035](https://github.com/apache/hertzbeat/pull/2035)
* [improve] Checkstyle include testSource by @crossoverJie in [https://github.com/apache/hertzbeat/pull/2036](https://github.com/apache/hertzbeat/pull/2036)
* [bugfix] fix collector and frontend dependent license error by @tomsun28 in [https://github.com/apache/hertzbeat/pull/2037](https://github.com/apache/hertzbeat/pull/2037)
* [improve] Add test for MemcachedCollectImpl by @zuobiao-zhou in [https://github.com/apache/hertzbeat/pull/2044](https://github.com/apache/hertzbeat/pull/2044)
* [imprve] Remove duplicate indices by @zuobiao-zhou in [https://github.com/apache/hertzbeat/pull/2045](https://github.com/apache/hertzbeat/pull/2045)
* [docs]: fix several typos in docs by @lw-yang in [https://github.com/apache/hertzbeat/pull/2047](https://github.com/apache/hertzbeat/pull/2047)
* Add the missing parts of docs, fix layout, sync the English version with the Chinese version by @xfl12345 in [https://github.com/apache/hertzbeat/pull/2048](https://github.com/apache/hertzbeat/pull/2048)
* [improve] add filename check in home ci by @LiuTianyou in [https://github.com/apache/hertzbeat/pull/2049](https://github.com/apache/hertzbeat/pull/2049)
* [improve] update dependency licenses and remove the aliyun sms depend by @tomsun28 in [https://github.com/apache/hertzbeat/pull/2058](https://github.com/apache/hertzbeat/pull/2058)
## New Contributors
* @handy-git made their first contribution in <https://github.com/apache/hertzbeat/pull/1643>
* @LiuTianyou made their first contribution in <https://github.com/apache/hertzbeat/pull/1684>
* @WinterKi1ler made their first contribution in <https://github.com/apache/hertzbeat/pull/1718>
* @miki-hmt made their first contribution in <https://github.com/apache/hertzbeat/pull/1734>
* @gjjjj0101 made their first contribution in <https://github.com/apache/hertzbeat/pull/1748>
* @makechoicenow made their first contribution in <https://github.com/apache/hertzbeat/pull/1747>
* @alpha951 made their first contribution in <https://github.com/apache/hertzbeat/pull/1745>
* @crossoverJie made their first contribution in <https://github.com/apache/hertzbeat/pull/1758>
* @PeixyJ made their first contribution in <https://github.com/apache/hertzbeat/pull/1760>
* @dukbong made their first contribution in <https://github.com/apache/hertzbeat/pull/1757>
* @xuziyang made their first contribution in <https://github.com/apache/hertzbeat/pull/1773>
* @MananPoojara made their first contribution in <https://github.com/apache/hertzbeat/pull/1774>
* @lwqzz made their first contribution in <https://github.com/apache/hertzbeat/pull/1768>
* @tomorrowshipyltm made their first contribution in <https://github.com/apache/hertzbeat/pull/1793>
* @YxYL6125 made their first contribution in <https://github.com/apache/hertzbeat/pull/1799>
* @15613060203 made their first contribution in <https://github.com/apache/hertzbeat/pull/1797>
* @Alanxtl made their first contribution in <https://github.com/apache/hertzbeat/pull/1813>
* @zhangshenghang made their first contribution in <https://github.com/apache/hertzbeat/pull/1820>
* @zuobiao-zhou made their first contribution in <https://github.com/apache/hertzbeat/pull/1832>
* @Pzz-2021 made their first contribution in <https://github.com/apache/hertzbeat/pull/1837>
* @LLP2333 made their first contribution in <https://github.com/apache/hertzbeat/pull/1868>
* @HeartLinked made their first contribution in <https://github.com/apache/hertzbeat/pull/1893>
* @Aias00 made their first contribution in <https://github.com/apache/hertzbeat/pull/1908>
* @westboy made their first contribution in <https://github.com/apache/hertzbeat/pull/1914>
* @Yanshuming1 made their first contribution in <https://github.com/apache/hertzbeat/pull/1957>
* @yuluo-yx made their first contribution in <https://github.com/apache/hertzbeat/pull/1964>
* @lwjxy made their first contribution in <https://github.com/apache/hertzbeat/pull/1977>
* @Thespica made their first contribution in <https://github.com/apache/hertzbeat/pull/1995>
* @boatrainlsz made their first contribution in <https://github.com/apache/hertzbeat/pull/2006>
* @JavaProgrammerLB made their first contribution in <https://github.com/apache/hertzbeat/pull/2007>
* @lw-yang made their first contribution in <https://github.com/apache/hertzbeat/pull/2047>
* @xfl12345 made their first contribution in <https://github.com/apache/hertzbeat/pull/2048>
* @handy-git made their first contribution in [https://github.com/apache/hertzbeat/pull/1643](https://github.com/apache/hertzbeat/pull/1643)
* @LiuTianyou made their first contribution in [https://github.com/apache/hertzbeat/pull/1684](https://github.com/apache/hertzbeat/pull/1684)
* @WinterKi1ler made their first contribution in [https://github.com/apache/hertzbeat/pull/1718](https://github.com/apache/hertzbeat/pull/1718)
* @miki-hmt made their first contribution in [https://github.com/apache/hertzbeat/pull/1734](https://github.com/apache/hertzbeat/pull/1734)
* @gjjjj0101 made their first contribution in [https://github.com/apache/hertzbeat/pull/1748](https://github.com/apache/hertzbeat/pull/1748)
* @makechoicenow made their first contribution in [https://github.com/apache/hertzbeat/pull/1747](https://github.com/apache/hertzbeat/pull/1747)
* @alpha951 made their first contribution in [https://github.com/apache/hertzbeat/pull/1745](https://github.com/apache/hertzbeat/pull/1745)
* @crossoverJie made their first contribution in [https://github.com/apache/hertzbeat/pull/1758](https://github.com/apache/hertzbeat/pull/1758)
* @PeixyJ made their first contribution in [https://github.com/apache/hertzbeat/pull/1760](https://github.com/apache/hertzbeat/pull/1760)
* @dukbong made their first contribution in [https://github.com/apache/hertzbeat/pull/1757](https://github.com/apache/hertzbeat/pull/1757)
* @xuziyang made their first contribution in [https://github.com/apache/hertzbeat/pull/1773](https://github.com/apache/hertzbeat/pull/1773)
* @MananPoojara made their first contribution in [https://github.com/apache/hertzbeat/pull/1774](https://github.com/apache/hertzbeat/pull/1774)
* @lwqzz made their first contribution in [https://github.com/apache/hertzbeat/pull/1768](https://github.com/apache/hertzbeat/pull/1768)
* @tomorrowshipyltm made their first contribution in [https://github.com/apache/hertzbeat/pull/1793](https://github.com/apache/hertzbeat/pull/1793)
* @YxYL6125 made their first contribution in [https://github.com/apache/hertzbeat/pull/1799](https://github.com/apache/hertzbeat/pull/1799)
* @15613060203 made their first contribution in [https://github.com/apache/hertzbeat/pull/1797](https://github.com/apache/hertzbeat/pull/1797)
* @Alanxtl made their first contribution in [https://github.com/apache/hertzbeat/pull/1813](https://github.com/apache/hertzbeat/pull/1813)
* @zhangshenghang made their first contribution in [https://github.com/apache/hertzbeat/pull/1820](https://github.com/apache/hertzbeat/pull/1820)
* @zuobiao-zhou made their first contribution in [https://github.com/apache/hertzbeat/pull/1832](https://github.com/apache/hertzbeat/pull/1832)
* @Pzz-2021 made their first contribution in [https://github.com/apache/hertzbeat/pull/1837](https://github.com/apache/hertzbeat/pull/1837)
* @LLP2333 made their first contribution in [https://github.com/apache/hertzbeat/pull/1868](https://github.com/apache/hertzbeat/pull/1868)
* @HeartLinked made their first contribution in [https://github.com/apache/hertzbeat/pull/1893](https://github.com/apache/hertzbeat/pull/1893)
* @Aias00 made their first contribution in [https://github.com/apache/hertzbeat/pull/1908](https://github.com/apache/hertzbeat/pull/1908)
* @westboy made their first contribution in [https://github.com/apache/hertzbeat/pull/1914](https://github.com/apache/hertzbeat/pull/1914)
* @Yanshuming1 made their first contribution in [https://github.com/apache/hertzbeat/pull/1957](https://github.com/apache/hertzbeat/pull/1957)
* @yuluo-yx made their first contribution in [https://github.com/apache/hertzbeat/pull/1964](https://github.com/apache/hertzbeat/pull/1964)
* @lwjxy made their first contribution in [https://github.com/apache/hertzbeat/pull/1977](https://github.com/apache/hertzbeat/pull/1977)
* @Thespica made their first contribution in [https://github.com/apache/hertzbeat/pull/1995](https://github.com/apache/hertzbeat/pull/1995)
* @boatrainlsz made their first contribution in [https://github.com/apache/hertzbeat/pull/2006](https://github.com/apache/hertzbeat/pull/2006)
* @JavaProgrammerLB made their first contribution in [https://github.com/apache/hertzbeat/pull/2007](https://github.com/apache/hertzbeat/pull/2007)
* @lw-yang made their first contribution in [https://github.com/apache/hertzbeat/pull/2047](https://github.com/apache/hertzbeat/pull/2047)
* @xfl12345 made their first contribution in [https://github.com/apache/hertzbeat/pull/2048](https://github.com/apache/hertzbeat/pull/2048)
## Just one command to get started
@@ -373,14 +373,14 @@ Upgrade Guide: <https://hertzbeat.apache.org/blog/2024/06/11/hertzbeat-v1.6.0-up
```docker run -d -p 1157:1157 -p 1158:1158 --name hertzbeat quay.io/tancloud/hertzbeat```
Detailed refer to HertzBeat Document <https://hertzbeat.apache.org/docs>
Detailed refer to HertzBeat Document [https://hertzbeat.apache.org/docs](https://hertzbeat.apache.org/docs)
---
**Github: <https://github.com/apache/hertzbeat>**
**Github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)**
Download Page: <https://hertzbeat.apache.org/docs/download/>
Download Page: [https://hertzbeat.apache.org/docs/download/](https://hertzbeat.apache.org/docs/download/)
Upgrade Guide: <https://hertzbeat.apache.org/blog/2024/06/11/hertzbeat-v1.6.0-update/>
Upgrade Guide: [https://hertzbeat.apache.org/blog/2024/06/11/hertzbeat-v1.6.0-update/](https://hertzbeat.apache.org/blog/2024/06/11/hertzbeat-v1.6.0-update/)
Have Fun!
+6 -6
View File
@@ -19,8 +19,8 @@ From my junior year to the present, I still maintain my passion for open source
## Participate in the Apache Community
[Apache Software Foundation (ASF)](https://community.apache.org/) is an American non-profit organization that aims to support various open source software projects. ASF was originally formed by a group of developers of Apache HTTP Server and was officially established on March 25, 1999. As of 2021, its total membership is approximately 1,000. The name comes from a local Indian tribe in North America.
This tribe is famous for its superb military literacy and superhuman endurance. In the second half of the 19th century, it resisted the invaders who invaded their territory. In order to show respect for this Indian tribe, the name of the tribe (Apache) is used as the server name.
[Apache Software Foundation (ASF)](https://community.apache.org/) is an American non-profit organization that aims to support various open source software projects. ASF was originally formed by a group of developers of Apache HTTP Server and was officially established on March 25, 1999. As of 2021, its total membership is approximately 1,000. The name comes from a local Indian tribe in North America.
This tribe is famous for its superb military literacy and superhuman endurance. In the second half of the 19th century, it resisted the invaders who invaded their territory. In order to show respect for this Indian tribe, the name of the tribe (Apache) is used as the server name.
But when it comes to this naming, there is an interesting story circulating here. Because this server is based on the NCSA HTTPd server and is the product of continuous revision and patching through the efforts of everyone, it is nicknamed "A Patchy Server" (a patch server). Here, because "A Patchy" and "Apache" are homophones, it was finally officially named "Apache Server".
The above is an introduction to the Apache Software Foundation from Wikipedia.
@@ -35,7 +35,7 @@ The first contribution in the Apache community should be to delete a `{@link}` c
### Get nominated and become a Committer
This nomination was recommended by PPMC Member [Logic](https://github.com/zqr10159) of Apache HertzbeatP(Incubating). Thanks to the Apache HertzBeat™ Team. I was successfully nominated to become a Hertzbeat Committer and got my own Apache mailbox.
This nomination was recommended by PPMC Member [Logic](https://github.com/zqr10159) of Apache Hertzbeat. Thanks to the Apache HertzBeat™ Team. I was successfully nominated to become a Hertzbeat Committer and got my own Apache mailbox.
![Apache ID Email](/img/blog/committer/yuluo-yx/3.jpg)
@@ -47,14 +47,14 @@ As the saying goes, the greater the ability, the greater the task. Becoming a pr
## How to participate in open source
Anyone who wants to do something needs an opportunity and a guide. Among the many Apache projects, there are many people who pay attention to the project's Issue List. The one time that remains fresh in my memory is: one night after writing the unit test of a tool class, I discovered a small bug. What I thought at the time was that there was too much contextual information and it was not good to write it in a PR, so I opened an Issue to record the context.
Anyone who wants to do something needs an opportunity and a guide. Among the many Apache projects, there are many people who pay attention to the project's Issue List. The one time that remains fresh in my memory is: one night after writing the unit test of a tool class, I discovered a small bug. What I thought at the time was that there was too much contextual information and it was not good to write it in a PR, so I opened an Issue to record the context.
How small is this bug? It was so small that I just created the Issue. After submitting the unit test and the code to fix the bug together, I refreshed the PR List again and saw a PR Title to fix the bug.
In fact, there is no shortage of people paying attention to the project, but more of an opportunity! Opportunities to participate in projects.
### The Apache Way
[The Apache Way](https://www.apache.org/theapacheway/) pursued by the Apache Community. The community is greater than the code. A good community is often more important than excellent code. The components of the community include developers, users, etc. Users are the first users of the project code. A healthy community status is when users discover problems, then report problems, and finally solve problems during use.
[The Apache Way](https://www.apache.org/theapacheway/) pursued by the Apache Community. The community is greater than the code. A good community is often more important than excellent code. The components of the community include developers, users, etc. Users are the first users of the project code. A healthy community status is when users discover problems, then report problems, and finally solve problems during use.
A more likely scenario is that a user reports a problem, switches from being a user to a developer, and solves the problem. And continue to participate in the maintenance of community projects.
### Paths to participate in open source
@@ -63,7 +63,7 @@ Open source is often pure, and the Apache Foundation exists to protect projects
#### Apache Community Identity
Before contributing to the community, it is important to understand the community's definition of identity, where a project's Committers are located, and how to become a Committer. The Apache community has a clear definition of [Contributor Identity](<https://community.apache.org/contributor-ladder>. html): [Contributor Identity](<https://community.apache.org/contributor-ladder>. html). The Apache community has a very clear definition of [contributor status](. html):
Before contributing to the community, it is important to understand the community's definition of identity, where a project's Committers are located, and how to become a Committer. The Apache community has a clear definition of [Contributor Identity]([https://community.apache.org/contributor-ladder](https://community.apache.org/contributor-ladder). html): [Contributor Identity]([https://community.apache.org/contributor-ladder](https://community.apache.org/contributor-ladder). html). The Apache community has a very clear definition of [contributor status](. html):
! [Apache contributor label](/img/blog/committer/yuluo-yx/6.jpg)
+1 -1
View File
@@ -17,7 +17,7 @@ Besides work, I am also passionate about the open-source community. Participatin
## Participating in the Apache Community
The first Apache project I participated in was Apache ShenYu (<https://github.com/apache/shenyu>). As an API gateway project, ShenYu provided me with an opportunity to gain a deep understanding of microservice architecture and gateway technology. Through my involvement in ShenYu's development, I not only enhanced my technical skills but also learned about the collaboration methods and open-source spirit of the Apache community.
The first Apache project I participated in was Apache ShenYu ([https://github.com/apache/shenyu](https://github.com/apache/shenyu)). As an API gateway project, ShenYu provided me with an opportunity to gain a deep understanding of microservice architecture and gateway technology. Through my involvement in ShenYu's development, I not only enhanced my technical skills but also learned about the collaboration methods and open-source spirit of the Apache community.
This experience gave me a deeper understanding of the Apache community and laid the foundation for my later participation in other Apache projects, such as HertzBeat. From ShenYu to HertzBeat, I gradually deepened my understanding and contribution to Apache projects, eventually becoming a Committer for HertzBeat.
+8 -8
View File
@@ -13,8 +13,8 @@ We are thrilled to announce the official release of Apache HertzBeat™ version
## Downloads and Documentation
- **Apache HertzBeat™ 1.6.1 Download Link**: <https://hertzbeat.apache.org/zh-cn/docs/download>
- **Apache HertzBeat™ Documentation**: <https://hertzbeat.apache.org/zh-cn/docs/>
- **Apache HertzBeat™ 1.6.1 Download Link**: [https://hertzbeat.apache.org/zh-cn/docs/download](https://hertzbeat.apache.org/zh-cn/docs/download)
- **Apache HertzBeat™ Documentation**: [https://hertzbeat.apache.org/zh-cn/docs/](https://hertzbeat.apache.org/zh-cn/docs/)
## Major Updates
@@ -68,23 +68,23 @@ Special thanks to **@zqr10159** for supporting this release and to the following
**Repository URL:**
<https://github.com/apache/hertzbeat>
[https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)
**Official Website:**
<https://hertzbeat.apache.org/>
[https://hertzbeat.apache.org/](https://hertzbeat.apache.org/)
**Apache HertzBeat™ Download Link:**
<https://hertzbeat.apache.org/zh-cn/docs/download>
[https://hertzbeat.apache.org/zh-cn/docs/download](https://hertzbeat.apache.org/zh-cn/docs/download)
**Apache HertzBeat™ Docker Images:**
Apache HertzBeat™ provides Docker images for each release, available on Docker Hub:
- HertzBeat: <https://hub.docker.com/r/apache/hertzbeat>
- HertzBeat Collector: <https://hub.docker.com/r/apache/hertzbeat-collector>
- HertzBeat: [https://hub.docker.com/r/apache/hertzbeat](https://hub.docker.com/r/apache/hertzbeat)
- HertzBeat Collector: [https://hub.docker.com/r/apache/hertzbeat-collector](https://hub.docker.com/r/apache/hertzbeat-collector)
**How to Contribute to the Apache HertzBeat™ Open Source Community?**
<https://hertzbeat.apache.org/zh-cn/docs/community/contribution>
[https://hertzbeat.apache.org/zh-cn/docs/community/contribution](https://hertzbeat.apache.org/zh-cn/docs/community/contribution)
+44 -44
View File
@@ -22,10 +22,10 @@ The overall structure of the Collector module can be divided into four main part
- **collector-xxx**: This is the extension Collector module for different services or protocols. For example, monitoring for specific services like MongoDB or RocketMQ often requires introducing their proprietary dependencies and developing within their respective modules. Below is an example of MongoDB's dependency:
```xml
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
</dependency>
`<dependency>`
`<groupId>`org.mongodb`</groupId>`
`<artifactId>`mongodb-driver-sync`</artifactId>`
`</dependency>`
```
Through this modular design, the Collector can easily be extended to adapt to various monitoring scenarios.
@@ -46,35 +46,35 @@ First, we need to create a new module in the project for Kafka monitoring, named
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.hertzbeat</groupId>
<artifactId>hertzbeat-collector</artifactId>
<version>2.0-SNAPSHOT</version>
</parent>
`<modelVersion>`4.0.0`</modelVersion>`
`<parent>`
`<groupId>`org.apache.hertzbeat`</groupId>`
`<artifactId>`hertzbeat-collector`</artifactId>`
`<version>`2.0-SNAPSHOT`</version>`
`</parent>`
<artifactId>hertzbeat-collector-kafka</artifactId>
<name>${project.artifactId}</name>
`<artifactId>`hertzbeat-collector-kafka`</artifactId>`
`<name>`${project.artifactId}`</name>`
<properties>
`<properties>`
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
`</properties>`
<dependencies>
<dependency>
<groupId>org.apache.hertzbeat</groupId>
<artifactId>hertzbeat-collector-common</artifactId>
<scope>provided</scope>
</dependency>
`<dependencies>`
`<dependency>`
`<groupId>`org.apache.hertzbeat`</groupId>`
`<artifactId>`hertzbeat-collector-common`</artifactId>`
`<scope>`provided`</scope>`
`</dependency>`
<!-- kafka -->
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
</dependency>
</dependencies>
</project>
`<dependency>`
`<groupId>`org.apache.kafka`</groupId>`
`<artifactId>`kafka-clients`</artifactId>`
`</dependency>`
`</dependencies>`
`</project>`
```
Points to note:
@@ -152,7 +152,7 @@ import org.apache.kafka.clients.admin.KafkaAdminClient;
import java.util.Properties;
public class KafkaConnect extends AbstractConnection<AdminClient> {
public class KafkaConnect extends AbstractConnection`<AdminClient>` {
private static AdminClient adminClient;
@@ -292,7 +292,7 @@ public class KafkaCollectImpl extends AbstractCollect {
*/
private void collectTopicOffset(CollectRep.MetricsData.Builder builder, AdminClient adminClient) throws InterruptedException, ExecutionException {
ListTopicsResult listTopicsResult = adminClient.listTopics(new ListTopicsOptions().listInternal(true));
Set<String> names = listTopicsResult.names().get();
Set`<String>` names = listTopicsResult.names().get();
names.forEach(name -> {
try {
Map<String, TopicDescription> map = adminClient.describeTopics(Collections.singleton(name)).all().get(3L, TimeUnit.SECONDS);
@@ -361,7 +361,7 @@ public class KafkaCollectImpl extends AbstractCollect {
*/
private static void collectTopicList(CollectRep.MetricsData.Builder builder, AdminClient adminClient) throws InterruptedException, ExecutionException {
ListTopicsOptions options = new ListTopicsOptions().listInternal(true);
Set<String> names = adminClient.listTopics(options).names().get();
Set`<String>` names = adminClient.listTopics(options).names().get();
names.forEach(name -> {
CollectRep.ValueRow valueRow = CollectRep.ValueRow.newBuilder().addColumns(name).build();
builder.addValues(valueRow);
@@ -378,11 +378,11 @@ public class KafkaCollectImpl extends AbstractCollect {
ListTopicsOptions options = new ListTopicsOptions();
options.listInternal(true);
ListTopicsResult listTopicsResult = adminClient.listTopics(options);
Set<String> names = listTopicsResult.names().get();
Set`<String>` names = listTopicsResult.names().get();
DescribeTopicsResult describeTopicsResult = adminClient.describeTopics(names);
Map<String, TopicDescription> map = describeTopicsResult.all().get();
map.forEach((key, value) -> {
List<TopicPartitionInfo> listp = value.partitions();
List`<TopicPartitionInfo>` listp = value.partitions();
listp.forEach(info -> {
CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder();
valueRowBuilder.addColumns(value.name());
@@ -418,11 +418,11 @@ org.apache.hertzbeat.collector.collect.kafka.KafkaCollectImpl
The final step is to add the `kafka-collector` module dependency in `collector/collector/pom.xml`:
```xml
<dependency>
<groupId>org.apache.hertzbeat</groupId>
<artifactId>hertzbeat-collector-kafka</artifactId>
<version>${hertzbeat.version}</version>
</dependency>
`<dependency>`
`<groupId>`org.apache.hertzbeat`</groupId>`
`<artifactId>`hertzbeat-collector-kafka`</artifactId>`
`<version>`${hertzbeat.version}`</version>`
`</dependency>`
```
By following the above steps, we have completed the development of a Kafka Collector, from protocol definition to the final SPI configuration and dependency management, fully extending a Kafka monitoring module.
@@ -456,9 +456,9 @@ name:
zh-TW: Kafka消息系統(客戶端)
# The description and help of this monitoring type
help:
zh-CN: HertzBeat 使用 <a href="https://hertzbeat.apache.org/docs/advanced/extend-jmx">Kafka Admin Client</a> 对 Kafka 的通用指标进行采集监控。</span>
en-US: HertzBeat uses <a href='https://hertzbeat.apache.org/docs/advanced/extend-jmx'>Kafka Admin Client</a> to monitor Kafka general metrics. </span>
zh-TW: HertzBeat 使用 <a href="https://hertzbeat.apache.org/docs/advanced/extend-jmx">Kafka Admin Client</a> 對 Kafka 的通用指標進行采集監控。</span>
zh-CN: HertzBeat 使用 <a href="https://hertzbeat.apache.org/docs/advanced/extend-jmx">Kafka Admin Client`</a>` 对 Kafka 的通用指标进行采集监控。`</span>`
en-US: HertzBeat uses <a href='https://hertzbeat.apache.org/docs/advanced/extend-jmx'>Kafka Admin Client`</a>` to monitor Kafka general metrics. `</span>`
zh-TW: HertzBeat 使用 <a href="https://hertzbeat.apache.org/docs/advanced/extend-jmx">Kafka Admin Client`</a>` 對 Kafka 的通用指標進行采集監控。`</span>`
helpLink:
zh-CN: https://hertzbeat.apache.org/zh-cn/docs/help/kafka_client
en-US: https://hertzbeat.apache.org/docs/help/kafka_client
@@ -610,9 +610,9 @@ When starting the `manager` module locally, if the added monitoring cannot find
```xml
<!-- collector-kafka -->
<dependency>
<groupId>org.apache.hertzbeat</groupId>
<artifactId>hertzbeat-collector-kafka</artifactId>
<version>${hertzbeat.version}</version>
</dependency>
`<dependency>`
`<groupId>`org.apache.hertzbeat`</groupId>`
`<artifactId>`hertzbeat-collector-kafka`</artifactId>`
`<version>`${hertzbeat.version}`</version>`
`</dependency>`
```
+8 -8
View File
@@ -13,8 +13,8 @@ We are thrilled to announce the official release of Apache HertzBeat™ version
## Downloads and Documentation
- **Apache HertzBeat™ 1.7.0 Download Link**: <https://hertzbeat.apache.org/docs/download>
- **Apache HertzBeat™ Documentation**: <https://hertzbeat.apache.org/docs/>
- **Apache HertzBeat™ 1.7.0 Download Link**: [https://hertzbeat.apache.org/docs/download](https://hertzbeat.apache.org/docs/download)
- **Apache HertzBeat™ Documentation**: [https://hertzbeat.apache.org/docs/](https://hertzbeat.apache.org/docs/)
## Major Updates
@@ -293,23 +293,23 @@ Special thanks to the following community members for their collaborative effort
**Repository URL:**
<https://github.com/apache/hertzbeat>
[https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)
**Official Website:**
<https://hertzbeat.apache.org/>
[https://hertzbeat.apache.org/](https://hertzbeat.apache.org/)
**Apache HertzBeat™ Download Link:**
<https://hertzbeat.apache.org/docs/download>
[https://hertzbeat.apache.org/docs/download](https://hertzbeat.apache.org/docs/download)
**Apache HertzBeat™ Docker Images:**
Apache HertzBeat™ provides Docker images for each release, available on Docker Hub:
- HertzBeat: <https://hub.docker.com/r/apache/hertzbeat>
- HertzBeat Collector: <https://hub.docker.com/r/apache/hertzbeat-collector>
- HertzBeat: [https://hub.docker.com/r/apache/hertzbeat](https://hub.docker.com/r/apache/hertzbeat)
- HertzBeat Collector: [https://hub.docker.com/r/apache/hertzbeat-collector](https://hub.docker.com/r/apache/hertzbeat-collector)
**How to Contribute to the Apache HertzBeat™ Open Source Community?**
<https://hertzbeat.apache.org/docs/community/contribution>
[https://hertzbeat.apache.org/docs/community/contribution](https://hertzbeat.apache.org/docs/community/contribution)
@@ -7,8 +7,8 @@
- **Back up the database**: Manually back up MySQL data as needed.
```bash
mysqldump -h<HOST-IP> -P<PORT> -uroot -p"PASSWORD" <DB_NAME> > hertzbeat_backup-`date +%Y-%m-%d`.sql # Single database
mysqldump -h<HOST-IP> -P<PORT> -uroot -p"PASSWORD" --all-databases > hertzbeat_backup-`date +%Y-%m-%d`.sql # Full database
mysqldump -h<HOST-IP> -P`<PORT>` -uroot -p"PASSWORD" `<DB_NAME>` > hertzbeat_backup-`date +%Y-%m-%d`.sql # Single database
mysqldump -h<HOST-IP> -P`<PORT>` -uroot -p"PASSWORD" --all-databases > hertzbeat_backup-`date +%Y-%m-%d`.sql # Full database
```
- **Back up configuration files and data directory**:
+8 -8
View File
@@ -13,8 +13,8 @@ We are thrilled to announce the official release of Apache HertzBeat™ version
## Downloads and Documentation
- **Apache HertzBeat™ 1.7.1 Download Link**: <https://hertzbeat.apache.org/docs/download>
- **Apache HertzBeat™ Documentation**: <https://hertzbeat.apache.org/docs/>
- **Apache HertzBeat™ 1.7.1 Download Link**: [https://hertzbeat.apache.org/docs/download](https://hertzbeat.apache.org/docs/download)
- **Apache HertzBeat™ Documentation**: [https://hertzbeat.apache.org/docs/](https://hertzbeat.apache.org/docs/)
## Major Updates
@@ -203,23 +203,23 @@ Special thanks to the following community members for their collaborative effort
**Repository URL:**
<https://github.com/apache/hertzbeat>
[https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)
**Official Website:**
<https://hertzbeat.apache.org/>
[https://hertzbeat.apache.org/](https://hertzbeat.apache.org/)
**Apache HertzBeat™ Download Link:**
<https://hertzbeat.apache.org/docs/download>
[https://hertzbeat.apache.org/docs/download](https://hertzbeat.apache.org/docs/download)
**Apache HertzBeat™ Docker Images:**
Apache HertzBeat™ provides Docker images for each release, available on Docker Hub:
- HertzBeat: <https://hub.docker.com/r/apache/hertzbeat>
- HertzBeat Collector: <https://hub.docker.com/r/apache/hertzbeat-collector>
- HertzBeat: [https://hub.docker.com/r/apache/hertzbeat](https://hub.docker.com/r/apache/hertzbeat)
- HertzBeat Collector: [https://hub.docker.com/r/apache/hertzbeat-collector](https://hub.docker.com/r/apache/hertzbeat-collector)
**How to Contribute to the Apache HertzBeat™ Open Source Community?**
<https://hertzbeat.apache.org/docs/community/contribution>
[https://hertzbeat.apache.org/docs/community/contribution](https://hertzbeat.apache.org/docs/community/contribution)
+11 -11
View File
@@ -13,8 +13,8 @@ We are thrilled to announce the official release of Apache HertzBeat™ version
## Downloads and Documentation
- **Apache HertzBeat™ 1.7.2 Download Link**: <https://hertzbeat.apache.org/docs/download>
- **Apache HertzBeat™ Documentation**: <https://hertzbeat.apache.org/docs/>
- **Apache HertzBeat™ 1.7.2 Download Link**: [https://hertzbeat.apache.org/docs/download](https://hertzbeat.apache.org/docs/download)
- **Apache HertzBeat™ Documentation**: [https://hertzbeat.apache.org/docs/](https://hertzbeat.apache.org/docs/)
## Major Updates
@@ -167,31 +167,31 @@ Special thanks to the following community members for their collaborative effort
## New Contributors
- @Duansg made their first contribution in <https://github.com/apache/hertzbeat/pull/3380>
- @lx1229 made their first contribution in <https://github.com/apache/hertzbeat/pull/3431>
- @RainBondsongyg made their first contribution in <https://github.com/apache/hertzbeat/pull/3440>
- @Duansg made their first contribution in [https://github.com/apache/hertzbeat/pull/3380](https://github.com/apache/hertzbeat/pull/3380)
- @lx1229 made their first contribution in [https://github.com/apache/hertzbeat/pull/3431](https://github.com/apache/hertzbeat/pull/3431)
- @RainBondsongyg made their first contribution in [https://github.com/apache/hertzbeat/pull/3440](https://github.com/apache/hertzbeat/pull/3440)
## Apache Hertzbeat
**Repository URL:**
<https://github.com/apache/hertzbeat>
[https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)
**Official Website:**
<https://hertzbeat.apache.org/>
[https://hertzbeat.apache.org/](https://hertzbeat.apache.org/)
**Apache HertzBeat™ Download Link:**
<https://hertzbeat.apache.org/docs/download>
[https://hertzbeat.apache.org/docs/download](https://hertzbeat.apache.org/docs/download)
**Apache HertzBeat™ Docker Images:**
Apache HertzBeat™ provides Docker images for each release, available on Docker Hub:
- HertzBeat: <https://hub.docker.com/r/apache/hertzbeat>
- HertzBeat Collector: <https://hub.docker.com/r/apache/hertzbeat-collector>
- HertzBeat: [https://hub.docker.com/r/apache/hertzbeat](https://hub.docker.com/r/apache/hertzbeat)
- HertzBeat Collector: [https://hub.docker.com/r/apache/hertzbeat-collector](https://hub.docker.com/r/apache/hertzbeat-collector)
**How to Contribute to the Apache HertzBeat™ Open Source Community?**
<https://hertzbeat.apache.org/docs/community/contribution>
[https://hertzbeat.apache.org/docs/community/contribution](https://hertzbeat.apache.org/docs/community/contribution)
+16 -16
View File
@@ -13,8 +13,8 @@ We are thrilled to announce the official release of Apache HertzBeat™ 1.7.3. T
## Downloads and Documentation
- **Apache HertzBeat™ 1.7.3 Download Link**: <https://hertzbeat.apache.org/zh-cn/docs/download>
- **Apache HertzBeat™ Documentation**: <https://hertzbeat.apache.org/zh-cn/docs/>
- **Apache HertzBeat™ 1.7.3 Download Link**: [https://hertzbeat.apache.org/zh-cn/docs/download](https://hertzbeat.apache.org/zh-cn/docs/download)
- **Apache HertzBeat™ Documentation**: [https://hertzbeat.apache.org/zh-cn/docs/](https://hertzbeat.apache.org/zh-cn/docs/)
## Major Updates
@@ -218,36 +218,36 @@ Special thanks to the following community members for their collaborative effort
## New Contributors
- @yy549159265 made their first contribution in <https://github.com/apache/hertzbeat/pull/3474>
- @cto-huhang made their first contribution in <https://github.com/apache/hertzbeat/pull/3594>
- @Saramanda9988 made their first contribution in <https://github.com/apache/hertzbeat/pull/3598>
- @delei made their first contribution in <https://github.com/apache/hertzbeat/pull/3608>
- @chingjustwe made their first contribution in <https://github.com/apache/hertzbeat/pull/3622>
- @rowankid made their first contribution in <https://github.com/apache/hertzbeat/pull/3690>
- @tuzuy made their first contribution in <https://github.com/apache/hertzbeat/pull/3668>
- @carlpinto25 made their first contribution in <https://github.com/apache/hertzbeat/pull/3726>
- @yy549159265 made their first contribution in [https://github.com/apache/hertzbeat/pull/3474](https://github.com/apache/hertzbeat/pull/3474)
- @cto-huhang made their first contribution in [https://github.com/apache/hertzbeat/pull/3594](https://github.com/apache/hertzbeat/pull/3594)
- @Saramanda9988 made their first contribution in [https://github.com/apache/hertzbeat/pull/3598](https://github.com/apache/hertzbeat/pull/3598)
- @delei made their first contribution in [https://github.com/apache/hertzbeat/pull/3608](https://github.com/apache/hertzbeat/pull/3608)
- @chingjustwe made their first contribution in [https://github.com/apache/hertzbeat/pull/3622](https://github.com/apache/hertzbeat/pull/3622)
- @rowankid made their first contribution in [https://github.com/apache/hertzbeat/pull/3690](https://github.com/apache/hertzbeat/pull/3690)
- @tuzuy made their first contribution in [https://github.com/apache/hertzbeat/pull/3668](https://github.com/apache/hertzbeat/pull/3668)
- @carlpinto25 made their first contribution in [https://github.com/apache/hertzbeat/pull/3726](https://github.com/apache/hertzbeat/pull/3726)
## Apache Hertzbeat
**Repository URL:**
<https://github.com/apache/hertzbeat>
[https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)
**Official Website:**
<https://hertzbeat.apache.org/>
[https://hertzbeat.apache.org/](https://hertzbeat.apache.org/)
**Apache HertzBeat™ Download Link:**
<https://hertzbeat.apache.org/docs/download>
[https://hertzbeat.apache.org/docs/download](https://hertzbeat.apache.org/docs/download)
**Apache HertzBeat™ Docker Images:**
Apache HertzBeat™ provides Docker images for each release, available on Docker Hub:
- HertzBeat: <https://hub.docker.com/r/apache/hertzbeat>
- HertzBeat Collector: <https://hub.docker.com/r/apache/hertzbeat-collector>
- HertzBeat: [https://hub.docker.com/r/apache/hertzbeat](https://hub.docker.com/r/apache/hertzbeat)
- HertzBeat Collector: [https://hub.docker.com/r/apache/hertzbeat-collector](https://hub.docker.com/r/apache/hertzbeat-collector)
**How to Contribute to the Apache HertzBeat™ Open Source Community?**
<https://hertzbeat.apache.org/docs/community/contribution>
[https://hertzbeat.apache.org/docs/community/contribution](https://hertzbeat.apache.org/docs/community/contribution)
+5 -5
View File
@@ -40,12 +40,12 @@ Apache HertzBeat™ is an open source real-time monitoring system emphasizing ea
### How to Contribute?
We welcome contributions of code, documentation, and ideas. My open source journey taught me that the hardest parts are starting and persisting. If interested, visit our contribution guide:
<https://hertzbeat.apache.org/zh-cn/docs/community/contribution>
Feel free to email me at <liutianyou@apache.org> - I'm happy to help you take your first open source steps!
[https://hertzbeat.apache.org/zh-cn/docs/community/contribution](https://hertzbeat.apache.org/zh-cn/docs/community/contribution)
Feel free to email me at [liutianyou@apache.org](mailto:liutianyou@apache.org) - I'm happy to help you take your first open source steps!
- Official Site: <https://hertzbeat.apache.org>
- GitHub: <https://github.com/apache/hertzbeat>
- Mailing List: <dev@hertzbeat.apache.org>
- Official Site: [https://hertzbeat.apache.org](https://hertzbeat.apache.org)
- GitHub: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)
- Mailing List: [dev@hertzbeat.apache.org](mailto:dev@hertzbeat.apache.org)
### Acknowledgments
+3 -3
View File
@@ -96,9 +96,9 @@ name:
en-US: EXAMPLE APP
# The description and help of this monitoring type
help:
zh-CN: HertzBeat 支持自定义监控,您只需配置监控模板 YML 就能适配一款自定义的监控类型。<br>定义流程如下:HertzBeat 页面 -> 监控模板菜单 -> 新增监控类型 -> 配置自定义监控模板YML -> 点击保存应用 -> 使用新监控类型添加监控。
en-US: "HertzBeat supports custom monitoring, and you only need to configure the monitoring template YML to adapt to a custom monitoring type. <br>Definition process as follow: HertzBeat Pages -> Main Menu -> Monitor Template -> edit and save -> apply this template."
zh-TW: HertzBeat支持自定義監控,您只需配寘監控模板YML就能適配一款自定義的監控類型。<br>定義流程如下:HertzBeat頁面->監控模板選單->新增監控類型->配寘自定義監控模板YML ->點擊保存應用->使用新監控類型添加監控。
zh-CN: HertzBeat 支持自定义监控,您只需配置监控模板 YML 就能适配一款自定义的监控类型。`<br>`定义流程如下:HertzBeat 页面 -> 监控模板菜单 -> 新增监控类型 -> 配置自定义监控模板YML -> 点击保存应用 -> 使用新监控类型添加监控。
en-US: "HertzBeat supports custom monitoring, and you only need to configure the monitoring template YML to adapt to a custom monitoring type. `<br>`Definition process as follow: HertzBeat Pages -> Main Menu -> Monitor Template -> edit and save -> apply this template."
zh-TW: HertzBeat支持自定義監控,您只需配寘監控模板YML就能適配一款自定義的監控類型。`<br>`定義流程如下:HertzBeat頁面->監控模板選單->新增監控類型->配寘自定義監控模板YML ->點擊保存應用->使用新監控類型添加監控。
helpLink:
zh-CN: https://hertzbeat.apache.org/zh-cn/docs/advanced/extend-point/
en-US: https://hertzbeat.apache.org/docs/advanced/extend-point/
@@ -78,9 +78,9 @@ name:
en-US: HertzBeat
# The description and help of this monitoring type
help:
zh-CN: Hertzbeat 对 Hertzbeat 监控系统的通用指标进行测量监控。<br>您可以点击 “<i>新建 HertzBeat监控系统</i>” 并进行配置,或者选择“<i>更多操作</i>”,导入已有配置。
en-US: Hertzbeat monitors HertzBeat Monitor through general performance metric. You could click the "<i>New HertzBeat Monitor</i>" button and proceed with the configuration or import an existing setup through the "<i>More Actions</i>" menu.
zh-TW: Hertzbeat對Hertzbeat監控系統的通用名額進行量測監控。<br>您可以點擊“<i>新建HertzBeat監控系統</i>”並進行配寘,或者選擇“<i>更多操作</i>”,導入已有配寘。
zh-CN: Hertzbeat 对 Hertzbeat 监控系统的通用指标进行测量监控。`<br>`您可以点击 “`<i>`新建 HertzBeat监控系统`</i>`” 并进行配置,或者选择“`<i>`更多操作`</i>`”,导入已有配置。
en-US: Hertzbeat monitors HertzBeat Monitor through general performance metric. You could click the "`<i>`New HertzBeat Monitor`</i>`" button and proceed with the configuration or import an existing setup through the "`<i>`More Actions`</i>`" menu.
zh-TW: Hertzbeat對Hertzbeat監控系統的通用名額進行量測監控。`<br>`您可以點擊“`<i>`新建HertzBeat監控系統`</i>`”並進行配寘,或者選擇“`<i>`更多操作`</i>`”,導入已有配寘。
helpLink:
zh-CN: https://hertzbeat.apache.org/zh-cn/docs/help/hertzbeat
en-US: https://hertzbeat.apache.org/docs/help/hertzbeat
@@ -217,4 +217,4 @@ This is the end of the practice of custom monitoring of the HTTP protocol. The H
If you think hertzbeat is a good open source project, please star us on GitHub Gitee, thank you very much.
**github: <https://github.com/apache/hertzbeat>**
**github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)**
+10 -10
View File
@@ -60,9 +60,9 @@ name:
en-US: HertzBeat(Token)
# The description and help of this monitoring type
help:
zh-CN: Hertzbeat 对 HertzBeat监控(Token)进行测量监控。<br>您可以点击 “<i>新建 HertzBeat监控(Token)</i>” 并进行配置,或者选择“<i>更多操作</i>”,导入已有配置。
en-US: Hertzbeat monitors HertzBeat Monitor(Token). You could click the "<i>New HertzBeat Monitor(Token)</i>" button and proceed with the configuration or import an existing setup through the "<i>More Actions</i>" menu.
zh-TW: Hertzbeat對HertzBeat監控(Token)進行量測監控。<br>您可以點擊“<i>新建HertzBeat監控(Token</i>”並進行配寘,或者選擇“<i>更多操作</i>”,導入已有配寘。
zh-CN: Hertzbeat 对 HertzBeat监控(Token)进行测量监控。`<br>`您可以点击 “`<i>`新建 HertzBeat监控(Token)`</i>`” 并进行配置,或者选择“`<i>`更多操作`</i>`”,导入已有配置。
en-US: Hertzbeat monitors HertzBeat Monitor(Token). You could click the "`<i>`New HertzBeat Monitor(Token)`</i>`" button and proceed with the configuration or import an existing setup through the "`<i>`More Actions`</i>`" menu.
zh-TW: Hertzbeat對HertzBeat監控(Token)進行量測監控。`<br>`您可以點擊“`<i>`新建HertzBeat監控(Token`</i>`”並進行配寘,或者選擇“`<i>`更多操作`</i>`”,導入已有配寘。
helpLink:
zh-CN: https://hertzbeat.apache.org/zh-cn/docs/help/hertzbeat_token
en-US: https://hertzbeat.apache.org/docs/help/hertzbeat_token
@@ -128,9 +128,9 @@ name:
en-US: HertzBeat(Token)
# The description and help of this monitoring type
help:
zh-CN: Hertzbeat 对 HertzBeat监控(Token)进行测量监控。<br>您可以点击 “<i>新建 HertzBeat监控(Token)</i>” 并进行配置,或者选择“<i>更多操作</i>”,导入已有配置。
en-US: Hertzbeat monitors HertzBeat Monitor(Token). You could click the "<i>New HertzBeat Monitor(Token)</i>" button and proceed with the configuration or import an existing setup through the "<i>More Actions</i>" menu.
zh-TW: Hertzbeat對HertzBeat監控(Token)進行量測監控。<br>您可以點擊“<i>新建HertzBeat監控(Token</i>”並進行配寘,或者選擇“<i>更多操作</i>”,導入已有配寘。
zh-CN: Hertzbeat 对 HertzBeat监控(Token)进行测量监控。`<br>`您可以点击 “`<i>`新建 HertzBeat监控(Token)`</i>`” 并进行配置,或者选择“`<i>`更多操作`</i>`”,导入已有配置。
en-US: Hertzbeat monitors HertzBeat Monitor(Token). You could click the "`<i>`New HertzBeat Monitor(Token)`</i>`" button and proceed with the configuration or import an existing setup through the "`<i>`More Actions`</i>`" menu.
zh-TW: Hertzbeat對HertzBeat監控(Token)進行量測監控。`<br>`您可以點擊“`<i>`新建HertzBeat監控(Token`</i>`”並進行配寘,或者選擇“`<i>`更多操作`</i>`”,導入已有配寘。
helpLink:
zh-CN: https://hertzbeat.apache.org/zh-cn/docs/help/hertzbeat_token
en-US: https://hertzbeat.apache.org/docs/help/hertzbeat_token
@@ -267,9 +267,9 @@ name:
en-US: HertzBeat(Token)
# The description and help of this monitoring type
help:
zh-CN: Hertzbeat 对 HertzBeat监控(Token)进行测量监控。<br>您可以点击 “<i>新建 HertzBeat监控(Token)</i>” 并进行配置,或者选择“<i>更多操作</i>”,导入已有配置。
en-US: Hertzbeat monitors HertzBeat Monitor(Token). You could click the "<i>New HertzBeat Monitor(Token)</i>" button and proceed with the configuration or import an existing setup through the "<i>More Actions</i>" menu.
zh-TW: Hertzbeat對HertzBeat監控(Token)進行量測監控。<br>您可以點擊“<i>新建HertzBeat監控(Token</i>”並進行配寘,或者選擇“<i>更多操作</i>”,導入已有配寘。
zh-CN: Hertzbeat 对 HertzBeat监控(Token)进行测量监控。`<br>`您可以点击 “`<i>`新建 HertzBeat监控(Token)`</i>`” 并进行配置,或者选择“`<i>`更多操作`</i>`”,导入已有配置。
en-US: Hertzbeat monitors HertzBeat Monitor(Token). You could click the "`<i>`New HertzBeat Monitor(Token)`</i>`" button and proceed with the configuration or import an existing setup through the "`<i>`More Actions`</i>`" menu.
zh-TW: Hertzbeat對HertzBeat監控(Token)進行量測監控。`<br>`您可以點擊“`<i>`新建HertzBeat監控(Token`</i>`”並進行配寘,或者選擇“`<i>`更多操作`</i>`”,導入已有配寘。
helpLink:
zh-CN: https://hertzbeat.apache.org/zh-cn/docs/help/hertzbeat_token
en-US: https://hertzbeat.apache.org/docs/help/hertzbeat_token
@@ -405,4 +405,4 @@ This is the end of the practice of custom monitoring of the HTTP protocol. The H
If you think hertzbeat is a good open source project, please star us on GitHub Gitee, thank you very much.
**github: <https://github.com/apache/hertzbeat>**
**github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)**
+8 -8
View File
@@ -34,25 +34,25 @@ Assume the HTTP API returns the following XML data:
<CPUList>
<CPU>
<cpuUtilization>36.400002</cpuUtilization>
</CPU>
</CPUList>
<CPU>
<CPUList>
<MemoryList>
<Memory>
<memoryUsage>399640</memoryUsage>
<memoryAvailable>98792</memoryAvailable>
<cacheSize>228492</cacheSize>
</Memory>
</MemoryList>
<Memory>
<MemoryList>
<NetPortStatusList>
<NetPortStatus>
<id>1</id>
<workSpeed>1000</workSpeed>
</NetPortStatus>
<NetPortStatus>
<NetPortStatus>
<id>2</id>
<workSpeed>0</workSpeed>
</NetPortStatus>
</NetPortStatusList>
<NetPortStatus>
<NetPortStatusList>
<bootTime>2025-01-06 10:27:48</bootTime>
<deviceUpTime>87天0时55分59秒</deviceUpTime>
<lastCalibrationTime>2025-04-03 11:09:18</lastCalibrationTime>
@@ -64,7 +64,7 @@ Assume the HTTP API returns the following XML data:
</uploadTimeConsumingList>
<lastCalibrationTimeMode>NTP</lastCalibrationTimeMode>
<lastCalibrationTimeAddress>34.191.45.101</lastCalibrationTimeAddress>
</DeviceStatus>
<DeviceStatus>
```
We want to monitor the device status and extract various metrics.
+3 -3
View File
@@ -45,9 +45,9 @@ name:
en-US: EXAMPLE APP
# The description and help of this monitoring type
help:
zh-CN: HertzBeat 支持自定义监控,您只需配置监控模板 YML 就能适配一款自定义的监控类型。<br>定义流程如下:HertzBeat 页面 -> 监控模板菜单 -> 新增监控类型 -> 配置自定义监控模板YML -> 点击保存应用 -> 使用新监控类型添加监控。
en-US: "HertzBeat supports custom monitoring, and you only need to configure the monitoring template YML to adapt to a custom monitoring type. <br>Definition process as follow: HertzBeat Pages -> Main Menu -> Monitor Template -> edit and save -> apply this template."
zh-TW: HertzBeat支持自定義監控,您只需配寘監控模板YML就能適配一款自定義的監控類型。<br>定義流程如下:HertzBeat頁面->監控模板選單->新增監控類型->配寘自定義監控模板YML ->點擊保存應用->使用新監控類型添加監控。
zh-CN: HertzBeat 支持自定义监控,您只需配置监控模板 YML 就能适配一款自定义的监控类型。`<br>`定义流程如下:HertzBeat 页面 -> 监控模板菜单 -> 新增监控类型 -> 配置自定义监控模板YML -> 点击保存应用 -> 使用新监控类型添加监控。
en-US: "HertzBeat supports custom monitoring, and you only need to configure the monitoring template YML to adapt to a custom monitoring type. `<br>`Definition process as follow: HertzBeat Pages -> Main Menu -> Monitor Template -> edit and save -> apply this template."
zh-TW: HertzBeat支持自定義監控,您只需配寘監控模板YML就能適配一款自定義的監控類型。`<br>`定義流程如下:HertzBeat頁面->監控模板選單->新增監控類型->配寘自定義監控模板YML ->點擊保存應用->使用新監控類型添加監控。
helpLink:
zh-CN: https://hertzbeat.apache.org/zh-cn/docs/advanced/extend-point/
en-US: https://hertzbeat.apache.org/docs/advanced/extend-point/
+3 -3
View File
@@ -40,9 +40,9 @@ name:
en-US: EXAMPLE WEBSITE
# The description and help of this monitoring type
help:
zh-CN: HertzBeat 支持自定义监控,您只需配置监控模板 YML 就能适配一款自定义的监控类型。<br>定义流程如下:HertzBeat 页面 -> 监控模板菜单 -> 新增监控类型 -> 配置自定义监控模板YML -> 点击保存应用 -> 使用新监控类型添加监控。
en-US: "HertzBeat supports custom monitoring, and you only need to configure the monitoring template YML to adapt to a custom monitoring type. <br>Definition process as follow: HertzBeat Pages -> Main Menu -> Monitor Template -> edit and save -> apply this template."
zh-TW: HertzBeat支持自定義監控,您只需配寘監控模板YML就能適配一款自定義的監控類型。<br>定義流程如下:HertzBeat頁面->監控模板選單->新增監控類型->配寘自定義監控模板YML ->點擊保存應用->使用新監控類型添加監控。
zh-CN: HertzBeat 支持自定义监控,您只需配置监控模板 YML 就能适配一款自定义的监控类型。`<br>`定义流程如下:HertzBeat 页面 -> 监控模板菜单 -> 新增监控类型 -> 配置自定义监控模板YML -> 点击保存应用 -> 使用新监控类型添加监控。
en-US: "HertzBeat supports custom monitoring, and you only need to configure the monitoring template YML to adapt to a custom monitoring type. `<br>`Definition process as follow: HertzBeat Pages -> Main Menu -> Monitor Template -> edit and save -> apply this template."
zh-TW: HertzBeat支持自定義監控,您只需配寘監控模板YML就能適配一款自定義的監控類型。`<br>`定義流程如下:HertzBeat頁面->監控模板選單->新增監控類型->配寘自定義監控模板YML ->點擊保存應用->使用新監控類型添加監控。
helpLink:
zh-CN: https://hertzbeat.apache.org/zh-cn/docs/advanced/extend-point/
en-US: https://hertzbeat.apache.org/docs/advanced/extend-point/
+4 -4
View File
@@ -80,9 +80,9 @@ name:
en-US: HertzBeat Monitor
# The description and help of this monitoring type
help:
zh-CN: Hertzbeat 对 Hertzbeat 监控系统的通用指标进行测量监控。<br>您可以点击 “<i>新建 HertzBeat监控系统</i>” 并进行配置,或者选择“<i>更多操作</i>”,导入已有配置。
en-US: Hertzbeat monitors HertzBeat Monitor through general performance metric. You could click the "<i>New HertzBeat Monitor</i>" button and proceed with the configuration or import an existing setup through the "<i>More Actions</i>" menu.
zh-TW: Hertzbeat對Hertzbeat監控系統的通用名額進行量測監控。<br>您可以點擊“<i>新建HertzBeat監控系統</i>”並進行配寘,或者選擇“<i>更多操作</i>”,導入已有配寘。
zh-CN: Hertzbeat 对 Hertzbeat 监控系统的通用指标进行测量监控。`<br>`您可以点击 “`<i>`新建 HertzBeat监控系统`</i>`” 并进行配置,或者选择“`<i>`更多操作`</i>`”,导入已有配置。
en-US: Hertzbeat monitors HertzBeat Monitor through general performance metric. You could click the "`<i>`New HertzBeat Monitor`</i>`" button and proceed with the configuration or import an existing setup through the "`<i>`More Actions`</i>`" menu.
zh-TW: Hertzbeat對Hertzbeat監控系統的通用名額進行量測監控。`<br>`您可以點擊“`<i>`新建HertzBeat監控系統`</i>`”並進行配寘,或者選擇“`<i>`更多操作`</i>`”,導入已有配寘。
helpLink:
zh-CN: https://hertzbeat.apache.org/zh-cn/docs/help/hertzbeat
en-US: https://hertzbeat.apache.org/docs/help/hertzbeat
@@ -229,4 +229,4 @@ This is the end of the practice of custom monitoring of the HTTP protocol. The H
If you think hertzbeat is a good open source project, please star us on GitHub Gitee, thank you very much. Thanks for the old iron support. Refill!
**github: <https://github.com/apache/hertzbeat>**
**github: [https://github.com/apache/hertzbeat](https://github.com/apache/hertzbeat)**
@@ -129,7 +129,7 @@ Error code description:
1. Prioritize selecting nouns for variable naming, it's easier to distinguish between `variables` or `methods`.
```java
Cache<String> publicKeyCache;
Cache`<String>` publicKeyCache;
```
2. Pinyin abbreviations are prohibited for variables (excluding nouns such as place names), such as chengdu.
@@ -210,7 +210,7 @@ Error code description:
- The referenced `package` or `resource` name doesn't need to be extracted as constant.
3. Variables that have not been reassigned must also be declared as <mark> final </mark> types.
3. Variables that have not been reassigned must also be declared as `<mark>` final `</mark>` types.
4. About the arrangement order of `constant/variable` lines
@@ -229,7 +229,7 @@ Error code description:
For example, if the parameter cannot be null, it is best to add a `@Nonnull` annotation. If the returned value can be null, the `@Nullable` annotation should be added first.
<mark> Note: that the package name is <b>javax.validation.requirements</b> </mark>
`<mark>` Note: that the package name is `<b>`javax.validation.requirements`</b>` `</mark>`
3. If there are too many lines of code in the method, please have a try on using multiple sub methods at appropriate points to segment the method body.
@@ -245,9 +245,9 @@ Error code description:
### 3.4 Collection Rule
1. For `collection` returned values, unless there are special `concurrent` (such as thread safety), always return the `interface`, such as:
- returns <mark> List </mark> if use `ArrayList`
- returns <mark> Map </mark> if use `HashMap`
- returns <mark> Set </mark> if use `HashSet`
- returns `<mark>` List `</mark>` if use `ArrayList`
- returns `<mark>` Map `</mark>` if use `HashMap`
- returns `<mark>` Set `</mark>` if use `HashSet`
2. If there are multiple threads, the following declaration or returned types can be used:
```java
@@ -276,7 +276,7 @@ Error code description:
1. The `thread pool` needs to be managed, using a unified entry point to obtain the `thread pool`.
<mark> Note: During the evolution process, we will provide additional examples for developers to have a clearer reference and understanding. </mark>
`<mark>` Note: During the evolution process, we will provide additional examples for developers to have a clearer reference and understanding. `</mark>`
2. `Thread pool` needs to be resource constrained to prevent resource leakage caused by improper handling
@@ -618,7 +618,7 @@ public void process(String input) {
```java
// ignored declaration lines.
List<User> userList = getUsersByBatch(1000);
List`<User>` userList = getUsersByBatch(1000);
LOG.debug("All users: {}", getAllUserIds(userList));
```
@@ -628,7 +628,7 @@ public void process(String input) {
```java
// ignored declaration lines.
List<User> userList = getUsersByBatch(1000);
List`<User>` userList = getUsersByBatch(1000);
if (LOG.isDebugEnabled()) {
LOG.debug("All ids of users: {}", getAllIDsOfUsers(userList));
}
@@ -642,8 +642,8 @@ public void process(String input) {
## References
- <https://site.mockito.org/>
- <https://alibaba.github.io/p3c/>
- <https://rules.sonarsource.com/java/>
- <https://junit.org/junit5/>
- <https://streampark.apache.org/>
- [https://site.mockito.org/](https://site.mockito.org/)
- [https://alibaba.github.io/p3c/](https://alibaba.github.io/p3c/)
- [https://rules.sonarsource.com/java/](https://rules.sonarsource.com/java/)
- [https://junit.org/junit5/](https://junit.org/junit5/)
- [https://streampark.apache.org/](https://streampark.apache.org/)
+1 -1
View File
@@ -85,7 +85,7 @@ Of course, if you have a good idea, you can also propose it directly on GitHub D
2. Then download the code locally with git command:
```shell
git clone git@github.com:${YOUR_USERNAME}/hertzbeat.git #Recommended
git clone git@github.com:`YOUR_USERNAME`/hertzbeat.git #Recommended
```
3. After the download is complete, please refer to the getting started guide or README file of the target repository to initialize the project.
+2 -2
View File
@@ -40,8 +40,8 @@ This website is compiled using node, using Docusaurus framework components
1. Download and install nodejs (version 18.8.0)
2. Clone the code to the local `git clone git@github.com:apache/hertzbeat.git`
3. In `home` directory run `npm install` to install the required dependent libraries.
4. In `home` directory run `npm run start`, you can visit <http://localhost:3000> to view the English mode preview of the site
5. In `home` directory run `npm run start-zh-cn`, you can visit <http://localhost:3000> to view the Chinese mode preview of the site
4. In `home` directory run `npm run start`, you can visit [http://localhost:3000](http://localhost:3000) to view the English mode preview of the site
5. In `home` directory run `npm run start-zh-cn`, you can visit [http://localhost:3000](http://localhost:3000) to view the Chinese mode preview of the site
6. To generate static website resource files, run `npm run build`. The static resources of the build are in the build directory.
## Document Format Inspection
+40 -40
View File
@@ -49,10 +49,10 @@ What keysize do you want? (3072) 4096 # Please enter 4096 here
Requested keysize is 4096 bits
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
`<n>` = key expires in n days
`<n>`w = key expires in n weeks
`<n>`m = key expires in n months
`<n>`y = key expires in n years
Key is valid for? (0) 0 # Please enter 0
Key does not expire at all
Is this correct? (y/N) y # Please enter y here
@@ -63,7 +63,7 @@ Real name: muchunjin # Please enter 'gpg real name'
Email address: muchunjin@apache.org # Please enter your apache email address here
Comment: apache key # Please enter some comments here
You selected this USER-ID:
"muchunjin (apache key) <muchunjin@apache.org>"
"muchunjin (apache key) [muchunjin@apache.org](mailto:muchunjin@apache.org)"
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O # Please enter O here
We need to generate a lot of random bytes. It is a good idea to perform
@@ -71,7 +71,7 @@ some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
# At this time, a dialog box will pop up, asking you to enter the key for this gpg.
# At this time, a dialog box will pop up, asking you to enter the key for this gpg.
# you need to remember that it will be used in subsequent steps.
┌─────────────────────────────────────────────────────┐
│ Please enter this passphrase to │
@@ -79,7 +79,7 @@ generator a better chance to gain enough entropy.
│ │
│ Passphrase: _______________________________________
│ │
│ <OK> <Cancel> │
`<OK>` `<Cancel>`
└─────────────────────────────────────────────────────┘
# Here you need to re-enter the password in the previous step.
@@ -88,7 +88,7 @@ generator a better chance to gain enough entropy.
│ │
│ Passphrase: _______________________________________
│ │
│ <OK> <Cancel> │
`<OK>` `<Cancel>`
└─────────────────────────────────────────────────────┘
gpg: key ACFB69E705016886 marked as ultimately trusted
gpg: revocation certificate stored as '/root/.gnupg/openpgp-revocs.d/DC12398CCC33A5349EB9663DF9D970AB18C9EDF6.rev'
@@ -96,7 +96,7 @@ public and secret key created and signed.
pub rsa4096 2023-05-01 [SC]
85778A4CE4DD04B7E07813ABACFB69E705016886
uid muchunjin (apache key) <muchunjin@apache.org>
uid muchunjin (apache key) [muchunjin@apache.org](mailto:muchunjin@apache.org)
sub rsa4096 2023-05-01 [E]
```
@@ -110,7 +110,7 @@ $ gpg --keyid-format SHORT --list-keys
------------------------
pub rsa4096/05016886 2023-05-01 [SC]
85778A4CE4DD04B7E07813ABACFB69E705016886
uid [ultimate] muchunjin (apache key) <muchunjin@apache.org>
uid [ultimate] muchunjin (apache key) [muchunjin@apache.org](mailto:muchunjin@apache.org)
sub rsa4096/0C5A4E1C 2023-05-01 [E]
# Send public key to keyserver via key id
@@ -124,17 +124,17 @@ Verify whether it is synchronized to the public network, it will take about a mi
```shell
$ gpg --keyserver keyserver.ubuntu.com --recv-keys 05016886 # If the following content appears, it means success
gpg: key ACFB69E705016886: "muchunjin (apache key) <muchunjin@apache.org>" not changed
gpg: key ACFB69E705016886: "muchunjin (apache key) [muchunjin@apache.org](mailto:muchunjin@apache.org)" not changed
gpg: Total number processed: 1
gpg: unchanged: 1
```
Or enter <https://keyserver.ubuntu.com/> address in the browser, enter the name of the key and click 'Search key' to search if existed.
Or enter [https://keyserver.ubuntu.com/](https://keyserver.ubuntu.com/) address in the browser, enter the name of the key and click 'Search key' to search if existed.
#### 2.4 Add the gpg public key to the KEYS file of the Apache SVN project repo
- Apache HertzBeat™ Branch Dev <https://dist.apache.org/repos/dist/dev/hertzbeat>
- Apache HertzBeat™ Branch Release <https://dist.apache.org/repos/dist/release/hertzbeat>
- Apache HertzBeat™ Branch Dev [https://dist.apache.org/repos/dist/dev/hertzbeat](https://dist.apache.org/repos/dist/dev/hertzbeat)
- Apache HertzBeat™ Branch Release [https://dist.apache.org/repos/dist/release/hertzbeat](https://dist.apache.org/repos/dist/release/hertzbeat)
##### 2.4.1 Add public key to KEYS in dev branch
@@ -146,7 +146,7 @@ $ svn co https://dist.apache.org/repos/dist/dev/hertzbeat
$ cd svn/dev/hertzbeat
# Append the KEY you generated to the file KEYS, and check if it is added correctly
$ (gpg --list-sigs muchunjin@apache.org && gpg --export --armor muchunjin@apache.org) >> KEYS
$ (gpg --list-sigs muchunjin@apache.org && gpg --export --armor muchunjin@apache.org) >> KEYS
$ svn ci -m "add gpg key for muchunjin"
```
@@ -161,7 +161,7 @@ $ svn co https://dist.apache.org/repos/dist/release/hertzbeat
$ cd svn/release/hertzbeat
# Append the KEY you generated to the file KEYS, and check if it is added correctly
$ (gpg --list-sigs muchunjin@apache.org && gpg --export --armor muchunjin@apache.org) >> KEYS
$ (gpg --list-sigs muchunjin@apache.org && gpg --export --armor muchunjin@apache.org) >> KEYS
$ svn ci -m "add gpg key for muchunjin"
```
@@ -170,7 +170,7 @@ $ svn ci -m "add gpg key for muchunjin"
### Build Package
#### 3.1 Based on the master branch, create a release-${release_version}-rcx branch, such as release-1.7.3-rc1, And create a tag named v1.7.3-rc1 based on the release-1.7.3-rc1 branch, and set this tag as pre-release
#### 3.1 Based on the master branch, create a release-`release_version`-rcx branch, such as release-1.7.3-rc1, And create a tag named v1.7.3-rc1 based on the release-1.7.3-rc1 branch, and set this tag as pre-release
```shell
git checkout master
@@ -277,19 +277,19 @@ $ for i in *.tar.gz; do echo $i; gpg --verify $i.asc $i ; done
apache-hertzbeat-1.7.3-bin.tar.gz
gpg: Signature made Tue May 2 12:16:35 2023 CST
gpg: using RSA key 85778A4CE4DD04B7E07813ABACFB69E705016886
gpg: Good signature from "muchunjin (apache key) <muchunjin@apache.org>" [ultimate]
gpg: Good signature from "muchunjin (apache key) [muchunjin@apache.org](mailto:muchunjin@apache.org)" [ultimate]
apache-hertzbeat-1.7.3-docker-compose.tar.gz
gpg: Signature made Tue May 2 12:16:36 2023 CST
gpg: using RSA key 85778A4CE4DD04B7E07813ABACFB69E705016886
gpg: Good signature from "muchunjin (apache key) <muchunjin@apache.org>" [ultimate]
gpg: Good signature from "muchunjin (apache key) [muchunjin@apache.org](mailto:muchunjin@apache.org)" [ultimate]
apache-hertzbeat-1.7.3-src.tar.gz
gpg: Signature made Tue May 2 12:16:37 2023 CST
gpg: using RSA key 85778A4CE4DD04B7E07813ABACFB69E705016886
gpg: Good signature from "muchunjin (apache key) <muchunjin@apache.org>" [ultimate]
gpg: Good signature from "muchunjin (apache key) [muchunjin@apache.org](mailto:muchunjin@apache.org)" [ultimate]
apache-hertzbeat-collector-1.7.3-bin.tar.gz
gpg: Signature made Tue May 2 12:16:37 2023 CST
gpg: using RSA key 85778A4CE4DD04B7E07813ABACFB69E705016886
gpg: Good signature from "muchunjin (apache key) <muchunjin@apache.org>" [ultimate]
gpg: Good signature from "muchunjin (apache key) [muchunjin@apache.org](mailto:muchunjin@apache.org)" [ultimate]
# Verify SHA512
$ for i in *.tar.gz; do echo $i; sha512sum --check $i.sha512; done
@@ -310,15 +310,15 @@ apache-hertzbeat-collector-1.7.3-bin.tar.gz: OK
```shell
# Check out the dev directory of the Apache SVN to the svn/dev directory under dist in the root directory of the Apache HertzBeat™ project
svn co https://dist.apache.org/repos/dist/dev/incubator/hertzbeat svn/dev
svn co https://dist.apache.org/repos/dist/dev/hertzbeat svn/dev
svn co --depth empty https://dist.apache.org/repos/dist/dev/incubator/hertzbeat
svn co --depth empty https://dist.apache.org/repos/dist/dev/hertzbeat
```
- Copy the material package to the dev directory
Create a version number directory and name it in the form of ${release_version}-${RC_version}. RC_version starts from 1, that is, the candidate version starts from RC1. During the release process, there is a problem that causes the vote to fail.
If it needs to be corrected, it needs to iterate the RC version , the RC version number needs to be +1. For example: Vote for version 1.7.3-RC1. If the vote passes without any problems, the RC1 version material will be released as the final version material.
Create a version number directory and name it in the form of `release_version`-`RC_version`. RC_version starts from 1, that is, the candidate version starts from RC1. During the release process, there is a problem that causes the vote to fail.
If it needs to be corrected, it needs to iterate the RC version , the RC version number needs to be +1. For example: Vote for version 1.7.3-RC1. If the vote passes without any problems, the RC1 version material will be released as the final version material.
If there is a problem (when the hertzbeat/incubator community votes, the voters will strictly check various release requirements and compliance issues) and need to be corrected, then re-initiate the vote after the correction, and the candidate version for the next vote is 1.7.3- RC2.
```shell
@@ -345,7 +345,7 @@ svn commit -m "release for HertzBeat 1.7.3"
- Check Apache SVN Commit Results
> Visit the address <https://dist.apache.org/repos/dist/dev/hertzbeat/> in the browser, check if existed the new material package
> Visit the address [https://dist.apache.org/repos/dist/dev/hertzbeat/](https://dist.apache.org/repos/dist/dev/hertzbeat/) in the browser, check if existed the new material package
## 4. Enter the community voting stage
@@ -353,7 +353,7 @@ svn commit -m "release for HertzBeat 1.7.3"
Send a voting email in the community requires at least three `+1` and no `-1`.
> `Send to`: <dev@hertzbeat.apache.org> <br />
> `Send to`: [dev@hertzbeat.apache.org](mailto:dev@hertzbeat.apache.org) <br />
> `Title`: [VOTE] Release Apache HertzBeat™ 1.7.3 rc1 <br />
> `Body`:
@@ -368,13 +368,13 @@ Release notes:
https://github.com/apache/hertzbeat/releases/tag/v1.7.3-rc1
The release candidates:
https://dist.apache.org/repos/dist/dev/incubator/hertzbeat/1.7.3-RC1/
https://dist.apache.org/repos/dist/dev/hertzbeat/1.7.3-RC1/
Git tag for the release:
https://github.com/apache/hertzbeat/releases/tag/v1.7.3-rc1
The artifacts signed with PGP key [33545C76], corresponding to [muchunjin@apache.org], that can be found in keys file:
https://downloads.apache.org/incubator/hertzbeat/KEYS
https://downloads.apache.org/hertzbeat/KEYS
The vote will be open for at least 72 hours or until the necessary number of votes are reached.
@@ -406,7 +406,7 @@ Thanks!
After 72 hours, the voting results will be counted, and the voting result email will be sent, as follows.
> `Send to`: <dev@hertzbeat.apache.org> <br />
> `Send to`: [dev@hertzbeat.apache.org](mailto:dev@hertzbeat.apache.org) <br />
> `Title`: [RESULT]\[VOTE\] Release Apache HertzBeat™ 1.7.3-rc1 <br />
> `Body`:
@@ -435,7 +435,7 @@ Best,
ChunJin Mu
```
One item of the email content is `Vote thread`, and the link is obtained here: <https://lists.apache.org/list.html?dev@hertzbeat.apache.org>
One item of the email content is `Vote thread`, and the link is obtained here: [https://lists.apache.org/list.html?dev@hertzbeat.apache.org](https://lists.apache.org/list.html?dev@hertzbeat.apache.org)
## 4. Complete the final publishing steps
@@ -447,10 +447,10 @@ svn mv https://dist.apache.org/repos/dist/dev/hertzbeat/1.7.3-RC1 https://dist.a
#### 4.2 Add the new version download address to the official website
<https://github.com/apache/hertzbeat/blob/master/home/docs/download.md>
<https://github.com/apache/hertzbeat/blob/master/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/download.md>
[https://github.com/apache/hertzbeat/blob/master/home/docs/download.md](https://github.com/apache/hertzbeat/blob/master/home/docs/download.md)
[https://github.com/apache/hertzbeat/blob/master/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/download.md](https://github.com/apache/hertzbeat/blob/master/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/download.md)
Open the official website address <https://hertzbeat.apache.org/docs/download/> to see if there is a new version of the download
Open the official website address [https://hertzbeat.apache.org/docs/download/](https://hertzbeat.apache.org/docs/download/) to see if there is a new version of the download
> It should be noted that the download link may take effect after an hour, so please pay attention to it.
@@ -483,8 +483,8 @@ The rename the release-1.7.3-rc1 branch to release-1.7.3.
#### 4.5 Send new version announcement email
> `Send to`: <announce@apache.org> <br />
> `cc`: <dev@hertzbeat.apache.org> <br />
> `Send to`: [announce@apache.org](mailto:announce@apache.org) <br />
> `cc`: [dev@hertzbeat.apache.org](mailto:dev@hertzbeat.apache.org) <br />
> `Title`: [ANNOUNCE] Apache HertzBeat™ 1.7.3 released <br />
> `Body`:
@@ -492,17 +492,17 @@ The rename the release-1.7.3-rc1 branch to release-1.7.3.
Hi Community,
We are glad to announce the release of Apache HertzBeat™ 1.7.3.
Thanks again for your help.
Thanks again for your help.
Apache HertzBeat™ (https://hertzbeat.apache.org/) - A real-time observability system with agentless, performance cluster, prometheus-compatible, custom monitoring and status page building capabilities.
Download Link:
Download Link:
https://hertzbeat.apache.org/docs/download/
Release Note:
Release Note:
https://github.com/apache/hertzbeat/releases/tag/v1.7.3
Website:
Website:
https://hertzbeat.apache.org/
HertzBeat Resources:
+7 -7
View File
@@ -8,7 +8,7 @@ sidebar_position: 4
For detailed check list, please refer to the official [check list](https://cwiki.apache.org/confluence/display/INCUBATOR/Incubator+Release+Checklist)
Version content accessible in browser <https://dist.apache.org/repos/dist/dev/hertzbeat/>
Version content accessible in browser [https://dist.apache.org/repos/dist/dev/hertzbeat/](https://dist.apache.org/repos/dist/dev/hertzbeat/)
### 1. Download the candidate version
@@ -22,9 +22,9 @@ If the network is poor, downloading may be time-consuming. The download is compl
```shell
#If there is svn locally, you can clone to the local
$ svn co https://dist.apache.org/repos/dist/dev/incubator/hertzbeat/${release_version}-${rc_version}/
$ svn co https://dist.apache.org/repos/dist/dev/hertzbeat/`release_version`-`rc_version`/
#or download the material file directly
$ wget https://dist.apache.org/repos/dist/dev/incubator/hertzbeat/${release_version}-${rc_version}/xxx.xxx
$ wget https://dist.apache.org/repos/dist/dev/hertzbeat/`release_version`-`rc_version`/xxx.xxx
```
### 2. Verify that the uploaded version is compliant
@@ -47,7 +47,7 @@ First import the publisher's public key. Import KEYS from the svn repository to
##### 2.2.1 Import public key
```shell
curl https://downloads.apache.org/incubator/hertzbeat/KEYS > KEYS # Download KEYS
-curl https://downloads.apache.org/hertzbeat/KEYS > KEYS # Download KEYS
gpg --import KEYS # Import KEYS to local
```
@@ -125,10 +125,10 @@ check as follows:
> If the binary/web-binary package is uploaded, check the binary package.
Unzip `apache-hertzbeat-${release_version}-src.tar.gz`
Unzip `apache-hertzbeat-`release_version`-src.tar.gz`
```shell
cd apache-hertzbeat-${release_version}-src
cd apache-hertzbeat-`release_version`-src
```
compile the source code: [Build HertzBeat Binary Package](https://hertzbeat.apache.org/docs/community/development/#build-hertzbeat-binary-package)
@@ -153,7 +153,7 @@ If you initiate a posting vote, you can refer to this response example to reply
:::caution Attention
When replying to the email, you must bring the information that you have checked by yourself. Simply replying to `+1 approve` is invalid.
When new PMC votes in the <dev@hertzbeat.apache.org> hertzbeat community, Please bring the binding suffix to indicate that it has a binding vote for the vote in the hertzbeat community, and it is convenient to count the voting results.
When new PMC votes in the [dev@hertzbeat.apache.org](mailto:dev@hertzbeat.apache.org) hertzbeat community, Please bring the binding suffix to indicate that it has a binding vote for the vote in the hertzbeat community, and it is convenient to count the voting results.
:::
Non-PMC member:

Some files were not shown because too many files have changed in this diff Show More