Compare commits

...
Author SHA1 Message Date
tomsun28 bf21538062 [improve] common metric data query design
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2025-02-28 16:36:19 +08:00
tomsun28 3688974610 [bugfix] fix alert sse illegal state exception (#3106) 2025-02-25 15:27:53 +08:00
af35043663 [feature] adding-ptBR-translation (#3098)
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-02-25 09:37:21 +08:00
Jastandshown 84c28229b2 [Feature] Add deepseek Api Monitor (#3096)
Co-authored-by: shown <yuluo08290126@gmail.com>
2025-02-24 15:39:53 +08:00
tomsun28 1a3e614209 [webapp] fix web oom crash when backend api can not access (#3100) 2025-02-23 21:22:37 +08:00
Jast 3df0e56da9 [Improve] Message notification prompt optimization (#3095) 2025-02-23 21:19:10 +08:00
Jast b5b4771e1a [Doc]Improve openai doc (#3097) 2025-02-22 10:30:25 +08:00
b8c5ae4d40 [bugfix] kafka client detect error (#3088)
Co-authored-by: Jast <shenghang@apache.org>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-02-21 22:05:12 +08:00
淞筱 207f2d958c [doc] correct home's new_committer_process (#3094) 2025-02-21 20:59:51 +08:00
Nick Guo 398a40bba4 [improve] optimize kafka collect test (#3093) 2025-02-21 17:47:46 +08:00
yunfan24andtomsun28 bb14681621 [feature] supports alibabacloud sms. (#3084)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-02-21 13:55:30 +08:00
yunfan24 d3a080fbaf [improve] Improve and unify the search. (#3085) 2025-02-20 14:58:56 +08:00
tomsun28 ce6f9feac6 [webapp] update and fix alert ui when theme dark (#3082) 2025-02-16 23:25:04 +08:00
yunfan24 7d18118bbd [feature] SMS notification supports unisms. (#3077) 2025-02-15 22:40:03 +08:00
yunfan24andaias00 d5d2b6bc71 [doc] Update the SMS configuration document. (#3073)
Co-authored-by: aias00 <rokkki@163.com>
2025-02-13 20:32:48 +08:00
Logicandtomsun28 e11a4da2ac [improve](web-app): update monitor chart configuration and springboot GreptimeDB version (#3071)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-02-13 10:19:49 +08:00
58360442ca [Bugfix] fix when the monitor is modified, the status is erroneously changed (#3067)
Co-authored-by: aias00 <rokkki@163.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-02-13 00:14:37 +08:00
yunfan24andaias00 4d76c0abf4 [improve] Refactor SMS sending and replace Tencent Cloud SDK with HTTP API. (#3063)
Co-authored-by: aias00 <rokkki@163.com>
2025-02-11 19:40:36 +08:00
Jastandtomsun28 f761e18739 [Feature]Add Chinese check (#3066)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-02-11 10:36:55 +08:00
yunfan24 6ac073a54e [improve] Complete the missing labels in the i18n file. (#3065) 2025-02-11 10:16:36 +08:00
65a8d19c5d [feature] Support SSH Tunnel (#3060)
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: aias00 <rokkki@163.com>
2025-02-10 10:20:03 +08:00
tomsun28 060b4d875d [webapp] update ui theme (#3064)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2025-02-10 10:09:31 +08:00
kangliandLogic 6c88c1ba03 [API DOC] Change Swagger description (#3061)
Co-authored-by: Logic <zqr10159@dromara.org>
2025-02-08 19:29:12 +08:00
tomsun28 8c58a35476 [bugfix] fix singleton not support remove, search id error, audio fetch 401 (#3062)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2025-02-08 18:36:42 +08:00
2ab05a5669 [feature] Add Japanese i18n (#3013)
Co-authored-by: aias00 <rokkki@163.com>
Co-authored-by: Calvin <naruse_shinji@163.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
2025-02-08 09:19:13 +08:00
f3bc7f55c5 [feature] Add Sftp config for monitor (#3038)
Co-authored-by: yinyijun <yingey2011>
Co-authored-by: yunfan24 <yunfan24@outlook.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: yinyijun <yinyijun6@mgtv.com>
2025-02-07 23:57:06 +08:00
7effbc1f0d [Feature]Add zookeeper e2e code (#3030)
Co-authored-by: Calvin <naruse_shinji@163.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
2025-02-07 23:22:10 +08:00
Logicandtomsun28 05e42182d9 [bugfix]style(alert-center): enhance 3D transformation and z-index layers (#3059)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Signed-off-by: Logic <zqr10159@dromara.org>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-02-07 20:28:15 +08:00
yunfan24andtomsun28 5e69f4dfd0 [bugfix] Fix the issue where the monitoring status is not updated. (#3056)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-02-07 16:12:47 +08:00
tomsun28 aeb0083394 [improve] update theme ui color (#3057)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2025-02-07 15:47:19 +08:00
Logic 02f635bdd3 [improve](alert-center) enhance alert card animations and interactions (#3055) 2025-02-07 10:18:52 +08:00
7dbcaaeda8 [alert] support multi query expr threshold (#3054)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Signed-off-by: Logic <zqr10159@126.com>
Co-authored-by: Logic <zqr10159@dromara.org>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-06 21:33:56 +08:00
Logicandgithub-actions[bot] 4ddf0a9f3f [alert] support sse for alert center, no need to manually refresh the page, add slide-in animation (#3051)
Signed-off-by: Logic <zqr10159@126.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-06 16:13:01 +08:00
yunfan24andtomsun28 f1b1e3f7d6 [improve] Search ignores case sensitivity. (#3042)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-02-05 15:56:31 +08:00
yunfan24 921b8e5713 [update] upgrade actions upload-artifact to v4 (#3046) 2025-02-05 11:30:42 +08:00
yunfan24andtomsun28 4009525f81 [improve] Replaced hardcoded text with internationalized string. (#3035)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-01-30 22:01:32 +08:00
yunfan24 e0c7b4e111 [bugfix] Fixed the bug in the threshold rules search box. (#3034) 2025-01-30 21:43:51 +08:00
yunfan24andaias00 5e01482caa [feature] Add pagination and name-based search functionality in notification module (#2948)
Co-authored-by: aias00 <rokkki@163.com>
2025-01-27 14:12:55 +08:00
yunfan24 028e2fbcbe [bugfix] fix and enable some unit tests. (#3031) 2025-01-27 12:58:14 +08:00
tomsun28 d00cc6dcf4 [feature] periodic alert threshold (#3024) 2025-01-26 18:37:57 +08:00
4b7fdd6985 OnlineParserTest doesn't test anything (#3010)
Co-authored-by: aias00 <rokkki@163.com>
Co-authored-by: leo <1552443053@qq.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-01-26 16:13:21 +08:00
tomsun28andJast e45ec431aa [doc] update new contributor wall (#3025)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Jast <shenghang@apache.org>
2025-01-26 15:50:05 +08:00
Jastandtomsun28 8fa52fbca1 [Feature] Add API e2e code (#3029)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-01-26 11:23:52 +08:00
Jastandtomsun28 132fd00ab1 [Improve] update english doc (#3028)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-01-26 11:12:43 +08:00
12ba2faa19 [MINOR UPDATE] Use Encode to string when possible (Base64) (#3016)
Co-authored-by: aias00 <rokkki@163.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-01-24 18:44:14 +08:00
PJ Fanningandaias00 2f3abfbad4 [issue-2998] remove invalid check in isValidLabelValue (#3015)
Co-authored-by: aias00 <rokkki@163.com>
2025-01-24 18:38:43 +08:00
myangle1120andaias00 95739d9114 [bugfix] Modify mask issue (#3018)
Co-authored-by: aias00 <rokkki@163.com>
2025-01-24 09:27:43 +08:00
Logicandtomsun28 428ae1f7d5 [bugfix]Fix page not found (#3014)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-01-23 19:49:02 +08:00
PJ Fanningandaias00 6509b8bfc6 [MINOR UPDATE] always specify the char encoding in getBytes (#3011)
Co-authored-by: aias00 <rokkki@163.com>
2025-01-23 18:40:59 +08:00
yunfan24andtomsun28 783bd8de89 [improve] Freeze the 'Operate' column on the right side of the list. (#3009)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-01-23 15:52:10 +08:00
Logicandtomsun28 d1115b44d1 [feature](alert) implement drag-and-drop functionality for alert templates (#3005)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-01-22 23:43:50 +08:00
NikhilMurugesanandaias00 68e37d613a [bugfix] fix some unit tests that failed to run (#3007)
Co-authored-by: aias00 <rokkki@163.com>
2025-01-22 23:41:08 +08:00
jonasHanhan 7db0df11ba [feature] Add alerter_zh_TW.properties configuration to adapt to mult… (#3004) 2025-01-21 16:30:48 +08:00
wanhaoandLogic e244bdc5a7 [feature] Complete multiple languages (#3002)
Co-authored-by: Logic <zqr10159@dromara.org>
2025-01-21 09:13:21 +08:00
tomsun28andLogic 0b7aa487f0 [webapp] bugfix edit monitor http query params error (#3001)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2025-01-20 13:09:27 +08:00
PJ FanningandLogic 59d8764dfb [MINOR UPDATE] refactor base64 code to simplify the conversions (#2999)
Co-authored-by: Logic <zqr10159@dromara.org>
2025-01-20 10:13:52 +08:00
yunfan24 8a38a34965 [feature] Support monitoring for StarRocks FE and StarRocks BE. (#2997) 2025-01-20 10:03:18 +08:00
tomsun28 fd7e1b0e05 [bugfix] fix wrong http user-agent content (#2996) 2025-01-20 01:16:50 +08:00
PJ Fanning 5441838888 [MINOR UPDATE] fix more instances of unclosed Http Responses (#2995) 2025-01-19 22:45:28 +08:00
PJ FanningandLogic 56b1dcb502 [MINOR UPDATE] close http response in PrometheusAutoCollectImpl (#2994)
Signed-off-by: PJ Fanning <pjfanning@users.noreply.github.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2025-01-19 17:56:16 +08:00
PJ Fanningandtomsun28 efbaf7feac [MINOR UPDATE] close HttpResponse in HttpCollectImpl (#2993)
Signed-off-by: PJ Fanning <pjfanning@users.noreply.github.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-01-19 17:48:21 +08:00
Logic 7003b8a150 [Improve]Add Copy token button (#2992) 2025-01-19 14:54:01 +08:00
wanhaoandaias00 aed524a88b [feature] Added multilingual defaults for forms (#2991)
Co-authored-by: aias00 <rokkki@163.com>
2025-01-18 20:54:57 +08:00
aias00 9b20ab8434 [type:fix] remove matomo ip (#2990) 2025-01-17 23:15:44 +08:00
5c39b98eaa [feature] Add privateKey passphrase config for linux monitor (#2982)
Co-authored-by: yinyijun <yinyijun6@mgtv.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: aias00 <rokkki@163.com>
2025-01-17 22:05:14 +08:00
aias00 43ac859939 [type:improve] fix dependencies vulnerabilites (#2989) 2025-01-17 20:31:57 +08:00
helei1030andtomsun28 b5c2eca819 [docs]added spark Chinese documents and changed the original spar… (#2987)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-01-17 10:41:19 +08:00
PJ Fanning cd57f51892 [MINOR UPDATE] improve xml parsing code (#2988)
Signed-off-by: PJ Fanning <pjfanning@users.noreply.github.com>
2025-01-17 09:17:57 +08:00
tomsun28 a33966de9f [improve] update i18n json stru and update search ui (#2986) 2025-01-16 20:46:32 +08:00
4ff9452926 [bugfix] fix hbase dashboard display anomalies and turn on HTTPS (#2980)
Co-authored-by: zhuoyuchen <>
Co-authored-by: aias00 <rokkki@163.com>
Co-authored-by: Jast <shenghang@apache.org>
2025-01-15 18:20:21 +08:00
Jast 67da9bdbba [Feature] Support copy monitoring (#2981) 2025-01-15 17:03:53 +08:00
tomsun28 8bb4493b43 [bugfix] fix alert integration extern source bug (#2979) 2025-01-14 18:22:21 +08:00
ghyandshown 92edd53f8c [webapp] key-value-input component hover effect fixed (#2972)
Signed-off-by: ghy <ghyghoo8@qq.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
2025-01-13 15:44:14 +08:00
d70ad75dcc [bugfix] Fix NullPointerException (#2849)
Signed-off-by: Ayu <127600988+ayu-v0@users.noreply.github.com>
Signed-off-by: Zhang Yuxuan <1373529784@qq.com>
Co-authored-by: Ayu <14359932+lin-Ayu0v0@user.noreply.gitee.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: aias00 <rokkki@163.com>
Co-authored-by: Zhang Yuxuan <1373529784@qq.com>
2025-01-12 22:52:37 +08:00
tomsun28andLogic 2e76c12fe1 [feature] alert integration extern source (#2978)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2025-01-12 16:13:52 +08:00
Nick Guoandtomsun28 7e158eb778 [Improve] Add more test cases for Kafka junit tests (#2976)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-01-11 17:05:04 +08:00
Logicandtomsun28 db23c94882 [bugfix](warehouse) add metrics data update logic in memory storage (#2973)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-01-10 20:10:01 +08:00
yunfan24andaias00 e905f36de2 [bugfix] Fix the search functionality issue. (#2970)
Co-authored-by: aias00 <rokkki@163.com>
2025-01-10 19:36:22 +08:00
aias00andshown 037957dbe6 [feature] replace googletagmanager to matomo (#2877)
Co-authored-by: shown <yuluo08290126@gmail.com>
2025-01-09 16:28:17 +08:00
liutianyouandtomsun28 01d18f7935 [Improve] add no popup option after next login (#2969)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-01-08 23:47:47 +08:00
88e350de1c [BUG] "Advanced Settings" is all white in dark mode (#2965)
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-01-08 23:43:27 +08:00
Nick Guoandtomsun28 07d22a8712 [Improve] Standardize Kafka metric naming (#2961)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-01-08 23:38:29 +08:00
tomsun28 7847fd78b7 [bufix] fix collector job scheduler error (#2966)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2025-01-08 21:44:42 +08:00
tomsun28 f7676ac8ca [improve] update alarm inhibit rule and alarm ui (#2957) 2025-01-08 10:04:07 +08:00
Jastandtomsun28 dd1cc700d9 [Imporve] Improve Huaweicloud (#2954)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-01-07 23:05:05 +08:00
Nick Guo d8dabe251a [Doc]Add English version of documentation for Kafka Consumer Detail (#2953) 2025-01-07 10:12:47 +08:00
Nick GuoandLogic f2e647d777 【Improve】adjust log level from INFO to WARN. (#2952)
Co-authored-by: Logic <zqr10159@dromara.org>
2025-01-06 13:50:09 +08:00
tomsun28 7bac0245a2 [improve] fix some alarm relate bug, update alarm center ui (#2951)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2025-01-06 11:25:52 +08:00
Jast d6e5399121 [Improve]Modify Chinese comments (#2950) 2025-01-06 00:36:29 +08:00
doveLinandaias00 00076fc704 [Feature] Support customized JMX monitoring through the Factory Pattern. (#2932)
Co-authored-by: aias00 <rokkki@163.com>
2025-01-05 17:59:42 +08:00
yunfan24andtomsun28 4a3d61bd9e [doc] Add Supported MySQL Versions. (#2949)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-01-05 16:53:50 +08:00
Logic af59b487e4 [bugfix](db): optimize column update. (#2947) 2025-01-05 16:48:56 +08:00
4cd3c3c97f [alarm] refactor new alarm (#2902)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Calvin <naruse_shinji@163.com>
Co-authored-by: a-little-fool <2030509072@qq.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2025-01-04 22:18:27 +08:00
69a21ffaa1 [refactor] refactoring methods replaceCryPlaceholder and replaceSmilingPlace (#2832)
Co-authored-by: Zhang Yuxuan <1373529784@qq.com>
Co-authored-by: aias00 <rokkki@163.com>
Co-authored-by: Calvin <naruse_shinji@163.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-01-04 19:54:05 +08:00
Jast 8ab71e672f [Improve]Improve e2e code (#2945) 2025-01-04 15:58:22 +08:00
7625a0b508 [home] updated navbar css #2928 (#2934)
Signed-off-by: Vedant7789 <147625492+Vedant7789@users.noreply.github.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: aias00 <rokkki@163.com>
2025-01-03 17:43:51 +08:00
dc963833e8 [improve] Refactor and Split the Message Notification Component. (#2924)
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: aias00 <rokkki@163.com>
2025-01-03 17:15:56 +08:00
Craaaaazy77andshown 87d4379efb [bugfix] Modify the doris_be.md document into an English version (#2936)
Signed-off-by: Craaaaazy77 <417989286@qq.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
2025-01-03 14:40:42 +08:00
Simon Sigréandtomsun28 bffd7c1d4f [bugfix] Corrected case 'DashBoard' is a lower case 'B' (#2935)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-01-02 20:27:24 +08:00
yunfan24 ba21ef5cdb [improve] Improve the synchronization of the mute status. (#2927) 2025-01-02 18:59:44 +08:00
Simon Sigréandtomsun28 3bf237a4eb [feature] Adding CPU Temperature Check Into Default Ubuntu Checks (#2930)
Signed-off-by: Simon Sigré <simon.sigre@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-01-02 00:57:05 +08:00
ponfeeandtomsun28 19e7f128a3 [improve] optimize website navbar css(#2928) (#2929)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-01-01 14:49:57 +08:00
Jastandtomsun28 5c409d7512 [Improve] Optimize the e2e code structure (#2926)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-01-01 14:14:26 +08:00
6bf20ba21a [bugfix] Fixed the 'java.lang.UnsupportedOperationException' exception caused by getCurrentMetricsData (#2923)
Co-authored-by: bcxc <lixiaobaivvv@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-01-01 14:00:32 +08:00
Simon Sigré 8c9b1f3f92 [doc] Update app-windows_script.yml (#2922)
Signed-off-by: Simon Sigré <simon.sigre@gmail.com>
2025-01-01 00:28:34 +08:00
yunfan24 b3eb0083df [bugfix] Bug fix for alarm voice. (#2920) 2024-12-30 23:41:48 +08:00
LogicandJast e51accb3e6 [improve](warehouse): replace empty json object key with empty string (#2919)
Co-authored-by: Jast <shenghang@apache.org>
2024-12-30 20:08:33 +08:00
Logic a9e219811a [bugfix]: fix setColumns method in CollectRep class (#2918) 2024-12-30 19:58:00 +08:00
Jastandtomsun28 51bdb56592 [Feture]Add docker e2e test (#2916)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-12-30 13:05:43 +08:00
yunfan24andtomsun28 3562e870d8 [improve] Add required field indicators and form validation prompts for convergence strategies and silent strategies in the form. (#2913)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-12-30 13:04:03 +08:00
6f9ee2f4e6 [improve] Optimize CacheService and add relevant unit test (#2912)
Co-authored-by: LLWW04 <1713673102@qq.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-12-29 23:52:36 +08:00
Jastandtomsun28 917c11f298 [bugfix] Fix docker container name unable to display problem (#2914)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-12-29 11:45:51 +08:00
bf8d5b79bb [bugfix] Fix the bug where canceling an edit on a record still updates the page values. (#2911)
Co-authored-by: aias00 <rokkki@163.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-12-29 11:38:57 +08:00
7178c444f2 [feature](web-app)Add Alarm Voice Alerts (#2906)
Signed-off-by: Logic <zqr10159@126.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: aias00 <rokkki@163.com>
2024-12-29 11:25:48 +08:00
Calvinandtomsun28 bc2dc1d567 [improve] fix import of CollectRep (#2910)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-12-28 14:04:11 +08:00
Jastandtomsun28 9714123c98 [Improve] Improve OBS (#2909)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-12-28 12:24:58 +08:00
leo 8ca2f70153 add an online parser for prometheus. (#2851) 2024-12-27 23:18:56 +08:00
doveLin 126268f7ec [feature] Add a new Singleton-pattern-based LRU local cache (#2907) 2024-12-27 14:39:00 +08:00
Logic 12d1f4990d [fix](flink): update calculate metrics definitions (#2905) 2024-12-26 23:45:02 +08:00
Jastandtomsun28 4b21df556c [Imporve] Support Kafka internal topic configuration (#2901)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-12-26 00:06:12 +08:00
Jast 893d91c4f0 [doc] update doc (#2900)
Signed-off-by: Jast <shenghang@apache.org>
2024-12-26 00:00:34 +08:00
4236c438be [feature] integrate with Apache Arrow (#2864)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Signed-off-by: shown <yuluo08290126@gmail.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: aias00 <rokkki@163.com>
2024-12-24 20:43:14 +08:00
yunfan 6a64752af0 [Improve] add notification when port number changes automatically due to HTTPS toggle.(#2779) (#2896) 2024-12-24 18:22:26 +08:00
东风 c5cce27cb4 [improve]add Plc protocol , Modbus monitor (#2850) 2024-12-23 23:52:40 +08:00
doveLin 364de609bf [collector] fix the issue of reusing the adminClient in the Kafka client. (#2895) 2024-12-23 11:44:45 +08:00
Jast 5d81c32f9d [Improve] Improve Kafka chart display (#2894) 2024-12-23 10:53:53 +08:00
doveLinandtomsun28 6aff6ed053 [collector]add monitoring metrics for consumer groups in Kafka client (#2887)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-12-20 14:20:05 +08:00
Nick Guoandtomsun28 5ba09cf5c1 [doc] add more hints when users are switching data source. (#2880)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-12-20 13:52:46 +08:00
Logic a746e35dcf [Improve]Beautify Charts (#2891) 2024-12-20 12:06:28 +08:00
liutianyou a27777adcb [improve]improve linux process (#2889) 2024-12-20 07:41:17 +08:00
Logic 4b7dfb4c8e [improve] remove stack property from line charts (#2888) 2024-12-19 22:51:42 +08:00
AyuandAyu ceda4a65f9 [chore] delete the redundant else (#2881)
Co-authored-by: Ayu <14359932+lin-Ayu0v0@user.noreply.gitee.com>
2024-12-19 16:07:57 +08:00
d4f6fc1ae8 [Fix] fix clickhouse monitor (#2874)
Co-authored-by: Calvin <naruse_shinji@163.com>
Co-authored-by: aias00 <rokkki@163.com>
2024-12-17 14:20:27 +08:00
铁甲小宝 e999360da8 modified:add a small change. (#2878) 2024-12-16 00:16:29 +08:00
Nick Guo 948fcb739a [improve]Add more helpful messages when adding a Kafka monitor (#2876) 2024-12-14 15:22:27 +08:00
cdf060e9ac [Optimize] Add a reminder about potential collection issues caused by the Docker deployment method of collector. (#2844)
Co-authored-by: Calvin <naruse_shinji@163.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: aias00 <rokkki@163.com>
2024-12-12 20:51:02 +08:00
starryCoder 1280c61af1 [doc] improve windows monitoring doc(#2869) 2024-12-12 15:10:18 +08:00
Nick Guo 86ad10ad7b [doc] Add ',' separator between monitoring types (#2865) 2024-12-10 21:08:55 +08:00
8961cf70a3 [bugfix]A bug fix (#2853)
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: aias00 <rokkki@163.com>
2024-12-08 11:48:18 +08:00
tomsun28andaias00 f31909a30d [doc] update security doc and some (#2856)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: aias00 <rokkki@163.com>
2024-12-05 08:49:18 +08:00
Jastandtomsun28 2df7e1d269 [improve] improve dependency (#2855)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-12-04 21:24:37 +08:00
tomsun28andCalvin c10ebf0b60 [doc] add security model doc and update contributors (#2846)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-12-04 13:58:16 +08:00
1fe70a60cc [bugfix]Fix wrong app name (#2845)
Co-authored-by: Calvin <naruse_shinji@163.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-11-30 16:43:09 +08:00
Jastandtomsun28 3ea4c0e7da [Feature] Add ssh e2e code (#2843)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-11-30 16:39:03 +08:00
tomsun28 8228938bd1 [fix] auto generated by protocol buffer (#2842)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2024-11-30 13:56:05 +08:00
5acaf4844a [feature] support managing tasks by using http_sd (#2830)
Co-authored-by: Zhang Yuxuan <1373529784@qq.com>
Co-authored-by: aias00 <rokkki@163.com>
2024-11-28 00:07:38 +08:00
fc8be06ad5 [improve] update victoriametrics and greptime store (#2836)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Signed-off-by: Logic <zqr10159@126.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: Logic <zqr10159@dromara.org>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Zhang Yuxuan <1373529784@qq.com>
2024-11-27 08:58:09 +08:00
tomsun28 509a9c9651 [fix] bugfix flyway location can not auto detect vendor when not h2 (#2835) 2024-11-26 19:28:39 +08:00
Logic 754b18c9ba [doc] update sidebar category label and plugin documentation (#2837) 2024-11-26 14:36:40 +08:00
8cdc92ab56 [chore] Delete redundant Spaces (#2834)
Signed-off-by: ayu-v0 <127600988+ayu-v0@users.noreply.github.com>
Co-authored-by: Ayu <14359932+lin-Ayu0v0@user.noreply.gitee.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-11-24 21:01:25 +08:00
tomsun28andLogic f0cb2af031 [improve] update and fix template yml priority (#2829)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-11-24 15:38:21 +08:00
Jastandtomsun28 bd937bf7b8 [doc] Added custom development collector documentation (#2833)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-11-24 14:10:33 +08:00
starryCoder 8852713e4d [fix]fix windows chinese encoding (#2831) 2024-11-24 11:39:50 +08:00
CalvinandZhang Yuxuan 12f4ecce01 [refactor] change name from http_sd to registry (#2827)
Co-authored-by: Zhang Yuxuan <1373529784@qq.com>
2024-11-22 19:34:42 +08:00
Kerwin Bryant ca9934ec81 Fixed the omissions in #2805 (#2826)
Signed-off-by: Kerwin Bryant <kerwin612@qq.com>
2024-11-22 08:51:00 +08:00
tomsun28andshown eaaf589083 [improve] update grafana auth method and add expose url (#2818)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
2024-11-18 23:19:57 +08:00
tomsun28 be84a0abae [improve] update windows metrics yml (#2816)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2024-11-18 21:57:50 +08:00
Jast 9a00f5a776 [improve] modify e2e test (#2814) 2024-11-14 23:38:43 +08:00
fb4626dd07 [feature] add e2e code (#2811)
Co-authored-by: aias00 <rokkki@163.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-11-14 11:24:49 +08:00
Jast f28996255a [Improve] improve kafka monitor (#2813) 2024-11-13 21:35:04 +08:00
Jast 0b79222bd0 [Doc] Add blog (#2812) 2024-11-11 23:19:15 +08:00
liutianyouandZhang Yuxuan 120f3a12fe [fix] fix the Linux process monitoring process exits abnormally without warning (#2810)
Co-authored-by: Zhang Yuxuan <1373529784@qq.com>
2024-11-11 14:09:30 +08:00
b8b1885657 [improve] Fix error links caused by module name changes. (#2807)
Co-authored-by: aias00 <rokkki@163.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-11-09 22:17:51 +08:00
caf13c09bd [feature] Support custom refresh intervals for each group of metrics (#2718)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: aias00 <rokkki@163.com>
Co-authored-by: crossoverJie <crossoverJie@gmail.com>
2024-11-09 13:41:31 +08:00
dca3e351ed [improve] code according to code specifications (#2809)
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: aias00 <rokkki@163.com>
2024-11-08 19:16:19 +08:00
Jast 6298e7ae90 [Improve] Improve module name (#2805) 2024-11-08 09:25:28 +08:00
tomsun28 4b2c3756b1 [doc] update new contributors (#2802)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2024-11-04 11:12:16 +08:00
shinestare d32ec249b4 [fix]Remove the duplicate declaration of commons-net (#2801) 2024-11-03 11:03:01 +08:00
tomsun28andLogic 611ddc22e3 [bugfix] fix collector docker build error (#2799)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-11-01 17:28:27 +08:00
4373ab23f3 [improve] improve the way Ai is entered and requested (#2762)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: aias00 <rokkki@163.com>
Co-authored-by: Zhang Yuxuan <1373529784@qq.com>
2024-10-31 22:02:02 +08:00
bff75757db [Task][OSPP] HertzBeat Official Template Marketplace (#2641)
Co-authored-by: Calvin <naruse_shinji@163.com>
Co-authored-by: aias00 <rokkki@163.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-10-30 20:07:49 +08:00
tomsun28 50dd262fbf [doc] update deploy doc (#2796) 2024-10-30 15:38:34 +08:00
Jastandtomsun28 dc9743b7a5 [Doc] improve website (#2795)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-10-30 11:02:16 +08:00
Logic 8dc0fdee27 [doc](download): update for v1.6.1 release (#2794) 2024-10-30 10:08:20 +08:00
1267fcae5a [Feature] add seatunnel monitor (#2782)
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: aias00 <rokkki@163.com>
Co-authored-by: Zhang Yuxuan <1373529784@qq.com>
2024-10-29 14:28:24 +08:00
afe68ba4f8 [collector]bugfix: close connection when common cache is timeout (#2786)
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: aias00 <rokkki@163.com>
2024-10-29 09:10:09 +08:00
4da00d445b [Task] [OSPP] JAVA implements the native ipmi2 communication protocol (#2726)
Signed-off-by: Gao Jian <1209640759@qq.com>
Co-authored-by: aias00 <rokkki@163.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
2024-10-28 20:43:42 +08:00
e3d09ef427 [doc]Correct PostgreSQL image name in documentation (#2789)
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: aias00 <rokkki@163.com>
2024-10-27 15:45:21 +08:00
bb0a22c42f [improve] code according to code specifications(#2784) (#2785)
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: aias00 <rokkki@163.com>
2024-10-26 17:21:57 +08:00
Jastandshown 291f7cb351 [Improve] Improve log config (#2783)
Co-authored-by: shown <yuluo08290126@gmail.com>
2024-10-26 16:58:06 +08:00
Logic ba4f1e35f8 [bugfix]Update JDBC URL prefix for TDengine connection (#2788) 2024-10-26 16:42:59 +08:00
Logic 32f8cd5188 [improve] fix release script (#2781) 2024-10-23 22:35:45 +08:00
tomsun28 1f22a610ce [improve] update docker-compose license and fix compose config yml (#2778)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2024-10-22 23:45:39 +08:00
Jast fac3f5b927 [doc] drop dead link (#2777) 2024-10-22 17:21:36 +08:00
tomsun28 efa2dc3969 [improve] email notice template use the common render (#2775)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2024-10-15 23:48:39 +08:00
tomsun28 a0995d26ec [doc] add baota extern install doc (#2768)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2024-10-11 23:12:08 +08:00
JastandZhang Yuxuan 4f18c2c930 [Improve] modify kafka log level (#2763)
Co-authored-by: Zhang Yuxuan <1373529784@qq.com>
2024-10-08 21:46:21 +08:00
Jast 739e678dd5 [doc] improve kafka monitor config (#2765) 2024-10-08 21:39:05 +08:00
tomsun28 2856c3fe65 [webapp] fix bulletin with multiple rows of results (#2761)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2024-10-07 19:45:57 +08:00
Zhang Yuxuan bad49ce17e [doc] fix JDK download mirror link (#2756) 2024-09-29 19:25:53 +08:00
puruidongandtomsun28 64c68a4593 [doc] fix error jdk download link (#2752)
Signed-off-by: puruidong <pruidong@gmail.com>
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-09-28 16:01:15 +08:00
cc47db793f [Improve] Fix cannot upload test report in the PR (#2748)
Co-authored-by: Zhang Yuxuan <1373529784@qq.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: aias00 <rokkki@163.com>
2024-09-25 22:25:45 +08:00
108cc4db5a [fix] Threshold Rules search i18n error (#2692) (#2736)
Co-authored-by: keaifa <keaifafafa@gmail.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: aias00 <rokkki@163.com>
2024-09-25 09:21:47 +08:00
7e3d009536 [improve] remove side nav user avatar (#2742)
Co-authored-by: Zhang Yuxuan <1373529784@qq.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
2024-09-24 21:33:18 +08:00
aias00andZhang Yuxuan 5dabc7b7fd [improve] support kanban tablename i18n (#2749)
Signed-off-by: aias00 <liuhongyu@apache.org>
Co-authored-by: Zhang Yuxuan <1373529784@qq.com>
2024-09-24 21:22:11 +08:00
aias00andZhang Yuxuan f2eb663e02 [improve] init default theme (#2741)
Co-authored-by: Zhang Yuxuan <1373529784@qq.com>
2024-09-24 17:50:06 +08:00
Jastandtomsun28 ebe7a6f8fe [Improve] Modify Kafka monitoring execution priority (#2743)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-09-24 11:31:59 +08:00
linDong 163a5a05ed [improve]:Improve plugin (#2744) 2024-09-24 09:38:14 +08:00
ec195c1dbf [feature] support kafka admin monitor (#2733)
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-09-22 23:16:04 +08:00
tomsun28 5fa88ec577 [release] update collector version 1.6.1 (#2739)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2024-09-22 17:56:16 +08:00
tomsun28 1e4dd6793e [license] update greptime dependency license (#2738)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2024-09-22 13:36:53 +08:00
tomsun28 a811b9f6cb [license] add ngx query builder license and update (#2737)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2024-09-22 12:19:32 +08:00
Logicandaias00 a8790c856b [release] release 1.6.1 rc2 and fix crlf encoding (#2724)
Signed-off-by: Logic <zqr10159@dromara.org>
Co-authored-by: aias00 <rokkki@163.com>
2024-09-22 00:02:28 +08:00
Jast b9fdfbd50e [bugfix] fix code describe (#2734) 2024-09-21 12:51:02 +08:00
tomsun28 85b4a4ef0c [improve] revert modify bin shells (#2735) 2024-09-21 11:37:13 +08:00
aias00 febc911639 [improve] modify bin shells (#2723) 2024-09-19 16:07:39 +08:00
Logic 001e76db4b [improve]Add release windows script and update version. (#2722)
Signed-off-by: Logic <zqr10159@dromara.org>
2024-09-19 10:38:13 +08:00
tomsun28andshown ca27605640 [improve] use post request refresh token (#2720)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
2024-09-16 16:24:07 +08:00
tomsun28 06ce10ec3a [bugfix] fix tag select component display and select error (#2719)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2024-09-16 11:07:17 +08:00
aias00 1c17c7cb44 [improve] support notify auto refresh (#2712) 2024-09-15 10:24:29 +08:00
tomsun28 a34ccdd769 [improve] refactor bulletin impl code (#2714)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2024-09-15 00:41:18 +08:00
f5a8ebeeca [Improve] module code struct (#2707)
Co-authored-by: Logic <zqr10159@dromara.org>
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: aias00 <rokkki@163.com>
2024-09-14 11:16:34 +08:00
Logicandaias00 6c36d1d60a [bugfix] template upload (#2710)
Co-authored-by: aias00 <rokkki@163.com>
2024-09-13 21:36:22 +08:00
aias00andshown 90c027d6cc [bugfix] disallow adding tag with same key same value (#2700)
Co-authored-by: shown <yuluo08290126@gmail.com>
2024-09-13 14:30:13 +08:00
liutianyou c30295cf9c [improve] Increase the priority of configuration initialization (#2709) 2024-09-13 08:10:46 +08:00
Zhang Yuxuan bb0e2ea41c [doc] Add new committer blog (#2708) 2024-09-12 20:14:09 +08:00
16f52d1b6e [bugfix] Allow anonymous access for MongoDB Atlas and standalone instances (#2704)
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: aias00 <rokkki@163.com>
2024-09-12 15:14:42 +08:00
ff3139e1de test: add unit test case for the util (#2701)
Co-authored-by: rick <LinuxSuRen@users.noreply.github.com>
Co-authored-by: aias00 <rokkki@163.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
2024-09-12 09:14:05 +08:00
Jast 65639da9c4 [doc] Resolve error link (#2706) 2024-09-12 00:11:24 +08:00
aias00 af0dc23b45 [improve] add new committer blog (#2705) 2024-09-11 17:47:20 +08:00
shown 4b81ae4abf [improve]: extract common constant str (#2698) 2024-09-11 07:32:06 +08:00
Zhang Yuxuan d5fdccf1d2 [doc] Add a new committer (#2699) 2024-09-10 13:29:48 +08:00
4d9900b56b [bugfix] fix search value not clear (#2688)
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-09-09 23:00:49 +08:00
liutianyouandLogic dab66d4f16 [doc] update doc for feishu notification (#2694)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-09-09 10:30:49 +08:00
shown cd028d8464 [improve] extract some common methods (#2691)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
2024-09-09 09:13:20 +08:00
c4c56c6f85 [doc] remove personal info (#2685)
Co-authored-by: aias00 <rokkki@163.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-09-08 17:37:59 +08:00
6a852b2b8d fix: fix e2e unstable (#2684)
Co-authored-by: aias00 <rokkki@163.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
2024-09-08 16:54:08 +08:00
aias00 c153433165 [improve] support kanban set auto refresh Interval (#2686) 2024-09-08 16:36:50 +08:00
aias00 27175ef3ef [bugfix] fix status page unknowing status value (#2689) 2024-09-08 16:32:10 +08:00
tomsun28 c507f952de [doc] add new contributor and committer (#2687)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2024-09-07 23:57:37 +08:00
liutianyou b00a50a469 [improve] beautify lark notification (#2683) 2024-09-07 10:38:44 +08:00
98354f267e [chore] make the controller response be easy (#2679)
Co-authored-by: rick <LinuxSuRen@users.noreply.github.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: aias00 <rokkki@163.com>
2024-09-06 11:26:47 +08:00
tomsun28 9080ccd2ba [bugfix] fix load error when edit monitor and can not update (#2682)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2024-09-06 08:47:58 +08:00
aias00andshown bd3420c4a7 [bugfix] fix kanban failed to add all selections (#2680)
Signed-off-by: aias00 <liuhongyu@apache.org>
Signed-off-by: aias00 <rokkki@163.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
2024-09-05 22:18:25 +08:00
aias00andshown 7506429fc4 [improve] add kanban auto refresh (#2681)
Co-authored-by: shown <yuluo08290126@gmail.com>
2024-09-05 22:10:47 +08:00
Yzzz e9bfee6e7e [optimize] In a minor issue, the values of max and min are reversed (#2678) 2024-09-05 22:02:41 +08:00
aias00 b8a2e865cd [bugfix] fix monitor edit error (#2677) 2024-09-05 09:21:46 +08:00
liutianyou 83c5a3a08a [fix] error image (#2676) 2024-09-05 08:13:41 +08:00
4b7178af02 test: add more unit tests for the collects (#2671)
Co-authored-by: rick <LinuxSuRen@users.noreply.github.com>
Co-authored-by: aias00 <rokkki@163.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
2024-09-04 19:42:22 +08:00
aias00 1841ed59d8 [bugfix] fix custom dashboard show metrics error (#2675) 2024-09-04 18:42:42 +08:00
aias00andLogic 4080f5f068 [bugfix] clear filters when ok\cancel (#2674)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-09-04 16:47:22 +08:00
aias00andLogic 25ee822c5f [bugfix] filter dashboard metrics (#2673)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-09-04 16:44:37 +08:00
aias00andLogic 969c4a95c5 [bugfix] fix bulletin name check (#2669)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-09-04 16:42:01 +08:00
aias00andLogic a15a106a46 [task] customize dashboard jump to monitor detail (#2668)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-09-04 16:39:58 +08:00
aias00 74ed750860 [bugfix] fix monitor detail display error (#2667) 2024-09-04 16:37:08 +08:00
ef377912ef [improve] improve plugin upload check (#2666)
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-09-03 23:44:11 +08:00
cb11f11ace [feature] add NVIDIA monitor (#2643)
Co-authored-by: aias00 <rokkki@163.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: Calvin <naruse_shinji@163.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-09-03 23:38:53 +08:00
589b0d915d [feature]Support grafana charts for Prometheus (#1658)
Signed-off-by: Logic <zqr10159@dromara.org>
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: liutianyou <tianyou.liu@qq.com>
Co-authored-by: aias00 <rokkki@163.com>
2024-09-03 23:09:14 +08:00
50a18f2813 [improve] improve markdown format for MD045 (#2658)
Co-authored-by: aias00 <rokkki@163.com>
Co-authored-by: Jast <shenghang@apache.org>
Co-authored-by: shown <yuluo08290126@gmail.com>
2024-09-03 23:00:00 +08:00
86ca715a64 test: add more unit tests for some services (#2653)
Co-authored-by: rick <LinuxSuRen@users.noreply.github.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: Calvin <naruse_shinji@163.com>
Co-authored-by: aias00 <rokkki@163.com>
2024-09-03 22:40:51 +08:00
7b886fe72d [doc] Add doc for linux_script and windows_script (#2646)
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: aias00 <rokkki@163.com>
2024-09-03 22:26:25 +08:00
9024b2aca2 [improve] improve markdown format for MD033 (#2657)
Co-authored-by: aias00 <rokkki@163.com>
Co-authored-by: Jast <shenghang@apache.org>
2024-09-03 22:06:50 +08:00
JastandCalvin 5cd9590907 [improve] Update ElasticSearch monitoring template. Description supports i18n (#2662)
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-09-03 21:35:14 +08:00
sherry-peng2333 8e38b8ba9b fix the mounting issues in script/docker-compose/hertzbeat-postgresql-victoria-metrics/docker-compose.yaml (#2660)
Signed-off-by: sherry-peng2333 <70619577+sherry-peng2333@users.noreply.github.com>
2024-09-03 16:25:23 +08:00
b_mountainand刘进山 47e632a088 [fix] fix byte type npe. (#2659)
Co-authored-by: 刘进山 <liujs@hsmap.com>
2024-09-03 11:32:05 +08:00
4a691777aa [improve] improve plugin params (#2655)
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-09-02 23:31:13 +08:00
wyfvsfyandaias00 ec92f4ee97 translation airflow.md to English (#2656)
Co-authored-by: aias00 <rokkki@163.com>
2024-09-02 23:01:14 +08:00
Jast 714f216470 [improve]improve doc 052 (#2654) 2024-09-02 21:55:42 +08:00
Logic 16cb8f681c [doc]Improve install doc (#2650)
Signed-off-by: Logic <zqr10159@dromara.org>
2024-09-02 21:16:11 +08:00
Calvin 3ec150c586 [improve] improve markdown format for MD003 (#2649) 2024-09-02 08:28:07 +08:00
liutianyouandaias00 31fcb0d839 [improve] added a method to obtain plugin parameters (#2644)
Co-authored-by: aias00 <rokkki@163.com>
2024-09-01 20:13:28 +08:00
Logicandliutianyou 3e1d87b59f Grafana doc (#2647)
Co-authored-by: liutianyou <tianyou.liu@qq.com>
2024-09-01 18:38:28 +08:00
liutianyou 2076693a16 [doc] help doc for mqtt (#2645) 2024-09-01 17:37:11 +08:00
7bb049f2df [improve] improve code (#2523)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: YuLuo <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: aias00 <rokkki@163.com>
2024-09-01 00:00:56 +08:00
shown 19955fa59a [improve] add md-lint command and docs (#2640) 2024-08-31 20:01:47 +08:00
049c0937bc [improve] update thread pool nums policy (#2606)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-08-31 16:07:36 +08:00
liutianyouandLogic 2763ee4dc4 [doc]update doc for custom plugin (#2245)
Signed-off-by: liutianyou <tianyou.liu@qq.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-08-31 09:47:12 +08:00
497fc915c3 test: add unit tests for BulletinController (#2642)
Signed-off-by: rick <LinuxSuRen@users.noreply.github.com>
Co-authored-by: rick <LinuxSuRen@users.noreply.github.com>
Co-authored-by: Calvin <naruse_shinji@163.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
2024-08-30 18:35:44 +08:00
Kerwin Bryant e945c42632 Fixed #2632 (#2638) 2024-08-30 17:26:05 +08:00
Logicandshown 59398bd7c6 [doc]Grafana doc (#2636)
Co-authored-by: shown <yuluo08290126@gmail.com>
2024-08-30 10:24:37 +08:00
liutianyou d49cb37c6f [improve] improve plugin (#2637) 2024-08-30 08:54:03 +08:00
89be682a88 [imporve] Adjustment of parameter verification (#2635)
Co-authored-by: 刘进山 <liujs@hsmap.com>
Co-authored-by: Calvin <naruse_shinji@163.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
2024-08-30 00:06:53 +08:00
aias00andshown 0d73ac6fc4 [improve] support master custom java opts (#2634)
Co-authored-by: shown <yuluo08290126@gmail.com>
2024-08-29 23:27:10 +08:00
17636ed582 [improve] add oceanbase help md (#2619)
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: Jast <shenghang@apache.org>
2024-08-29 23:22:56 +08:00
aias00andCalvin 9cb50b7190 [Improve] add valkey help md (#2633)
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-08-29 23:03:17 +08:00
0e49e100d8 [feature] Implement custom parameters for plugins (#2616)
Signed-off-by: liutianyou <tianyou.liu@qq.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: Kerwin Bryant <kerwin612@qq.com>
Co-authored-by: Logic <zqr10159@dromara.org>
Co-authored-by: liutianyou <tianyou.liu@qq.com>
2024-08-29 20:33:17 +08:00
Logic 24678c2ca0 [doc] Bulletin doc (#2631) 2024-08-29 12:18:35 +08:00
6074c08e1a [feat] support monitor MQTT connections (#2618)
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-08-29 11:05:54 +08:00
3eb6fb35f4 [improve]Optimize Hbase Master and Regionserver monitoring (#2624)
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-08-29 10:55:53 +08:00
liutianyouandLogic 466ac37e66 [fix] fix i8n error in bulletin (#2627)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-08-29 10:10:07 +08:00
aias00andshown a5bc6327f9 [Improve] translate redis help md (#2621)
Co-authored-by: shown <yuluo08290126@gmail.com>
2024-08-28 22:59:57 +08:00
aias00andshown 2e9021a12d [improve] translate pop3 help md (#2622)
Co-authored-by: shown <yuluo08290126@gmail.com>
2024-08-28 22:37:43 +08:00
Jast 1dd08b8b19 [improve]Centos network card information monitoring optimization (#2626) 2024-08-28 22:05:37 +08:00
6117396377 [imporve] null judge modify. (#2558)
Co-authored-by: 刘进山 <liujs@hsmap.com>
Co-authored-by: YuLuo <yuluo08290126@gmail.com>
Co-authored-by: Calvin <naruse_shinji@163.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-27 23:54:50 +08:00
d71b9aa048 simplify the convertUnit (#2595)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Eric <247677858@qq.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
2024-08-27 22:01:44 +08:00
tomsun28andshown 525980f919 [webapp] bugfix monitors pageable not work (#2602)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
2024-08-27 11:02:58 +08:00
6e430bcab6 Add push dao unit tests (#2614)
Co-authored-by: I744506 <temirlan.basitov@sap.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
2024-08-27 11:01:16 +08:00
shown 12a53c69da [optimize]: update github action (#2608)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Signed-off-by: shown <yuluo08290126@gmail.com>
2024-08-27 10:44:04 +08:00
Jastandshown 1799e00ec9 [doc]markdown md046 (#2613)
Co-authored-by: shown <yuluo08290126@gmail.com>
2024-08-27 10:40:05 +08:00
5d416e855b [Feature] Supports Bulletin to view all metrics. (#2584)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: YuLuo <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: kerwin612 <kerwin612@qq.com>
2024-08-27 06:25:38 +08:00
tomsun28andshown 5eef247a5b [improve] enable and fix test src checkstyle (#2610)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
2024-08-26 19:13:16 +08:00
Jast 77f725cf42 [fixbug]Fixbug kafka version display (#2609) 2024-08-26 17:03:56 +08:00
shownandJast b7969e78c9 [improve]: enable md040 rules (#2607)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: Jast <shenghang@apache.org>
2024-08-26 13:10:13 +08:00
2f4343c453 [Improve] improve markdown format for MD029 (#2604)
Co-authored-by: shown <yuluo08290126@gmail.com>
Co-authored-by: Jast <shenghang@apache.org>
2024-08-26 10:02:21 +08:00
857e4118f0 [improve] Improve markdown md035 (#2592)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: shown <yuluo08290126@gmail.com>
2024-08-26 09:27:40 +08:00
Gao Jianandshown c3ffad76ca [fixbug]: Fix Redfish protocol parse bug (#2597)
Co-authored-by: shown <yuluo08290126@gmail.com>
2024-08-25 19:01:40 +08:00
tomsun28andshown 102c72bcc6 [doc] fix markdown lint md013 check (#2599)
Co-authored-by: shown <yuluo08290126@gmail.com>
2024-08-25 18:46:01 +08:00
tomsun28 88aeb9fc21 [bugfix] fix alarm recover not match in converge reduce in some condition (#2603)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2024-08-25 18:24:10 +08:00
crossoverJie 20f89f3b3b [Improve]Temporarily disable import sort (#2601) 2024-08-25 12:16:18 +08:00
aias00 7facbe827c [improve] improve md format MD025 (#2587) 2024-08-25 09:30:43 +08:00
e3a1b8345f [improve] improve markdown format for MD047 (#2586)
Co-authored-by: YuLuo <yuluo08290126@gmail.com>
Co-authored-by: Jast <admin@hadoop.wiki>
2024-08-24 07:52:56 +08:00
0f0f00c700 [feature] manage dependencies version by parent pom (#2571)
Co-authored-by: Calvin <naruse_shinji@163.com>
Co-authored-by: YuLuo <yuluo08290126@gmail.com>
2024-08-23 23:06:49 +08:00
Kerwin Bryant 51699e34cd [webapp] fix #2244 and update detail ui (#2590) 2024-08-23 17:27:34 +08:00
Jast 343afd517d [Improve] improve markdown format for MD041 (#2588) 2024-08-23 11:33:06 +08:00
tomsun28andJast b602d8ceb6 [Improve] remove 1.4 version doc and improve markdown format for MD001 (#2585)
Co-authored-by: Jast <admin@hadoop.wiki>
2024-08-23 09:26:56 +08:00
bad28bccdb [improve] extra project configuration common filed to constants (#2540)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: Calvin <naruse_shinji@163.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-22 23:49:02 +08:00
aias00 eea68d2a27 [feature] add greenplum help md (#2570)
Signed-off-by: aias00 <rokkki@163.com>
2024-08-22 23:13:19 +08:00
Jastandtomsun28 fff291da82 [Improve] improve markdown format for MD024 (#2580)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-22 22:53:48 +08:00
aias00 97aada9956 [feature] add vastbase help md (#2569)
Signed-off-by: aias00 <rokkki@163.com>
2024-08-22 16:48:43 +08:00
Jastandtomsun28 d056ce2aa6 [feature] support dead link check (#2579)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-21 23:19:14 +08:00
c2d92eb57d [Improve] improve doc check (#2572)
Co-authored-by: YuLuo <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-08-21 23:06:39 +08:00
4dceb42dc7 [feature] add iceberg help md (#2573)
Co-authored-by: Calvin <naruse_shinji@163.com>
Co-authored-by: YuLuo <yuluo08290126@gmail.com>
2024-08-21 19:53:26 +08:00
YuLuoandtomsun28 1fac6ab2fa [e2e] add some configuration args to observation atest running status (#2565)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-21 18:52:01 +08:00
235df8bca1 [feature] add kvrocks template (#2564)
Co-authored-by: YuLuo <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-21 18:29:20 +08:00
YuLuoandtomsun28 603bc3222a chore: rename push service unit test class name (#2562)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-21 17:54:20 +08:00
tomsun28andYuLuo a1d73a292c [webapp] auto resize the monitor detail ui width (#2577)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: YuLuo <yuluo08290126@gmail.com>
2024-08-21 13:39:39 +08:00
aias00 bdfffeec4c [bugfix] fix kingbase spotless apply (#2575) 2024-08-21 10:54:54 +08:00
aias00 bc47768bfb [feature] add kingbase help md (#2568) 2024-08-20 23:57:09 +08:00
Jastandtomsun28 98b03b62c7 [doc] update doc style check (#2560)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-20 00:31:51 +08:00
Jast ceab3023b1 [improve] linux chart display (#2559) 2024-08-19 22:25:24 +08:00
Jastandtomsun28 a49fa3d91b [fixbug] Fixbug doc format temporary process (#2557)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-19 14:24:05 +08:00
5d87275206 [improve] support plugins using other jar (#2553)
Co-authored-by: YuLuo <yuluo08290126@gmail.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-08-19 12:36:51 +08:00
a2bd61947b [imporve] move ai package and improve ai code. (#2542)
Co-authored-by: 刘进山 <liujs@hsmap.com>
Co-authored-by: YuLuo <yuluo08290126@gmail.com>
Co-authored-by: linDong <56677297@qq.com>
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-08-19 00:48:34 +08:00
b_mountainandCalvin 7ac21d3171 [improve] Add GeneralConfigTypeEnum. (#2555)
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-08-19 00:41:49 +08:00
YuLuo 4fdc048287 [doc] add new committer docs (#2554)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
2024-08-18 22:53:58 +08:00
tomsun28andYuLuo e10e4b2d8d [improve] fix docker compose package script and update contributor doc (#2552)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: YuLuo <yuluo08290126@gmail.com>
2024-08-18 16:45:06 +08:00
aias00andYuLuo 27d66a11c1 [type:feature] add greptimedb template (#2551)
Co-authored-by: YuLuo <yuluo08290126@gmail.com>
2024-08-18 16:36:00 +08:00
YuLuo 19c7d84e53 [infra] remove redundant security bug reporting options (#2550)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
2024-08-18 15:42:35 +08:00
aias00andYuLuo 031e83d701 [bugfix] clear qbdata when cascade change (#2545)
Co-authored-by: YuLuo <yuluo08290126@gmail.com>
2024-08-18 09:30:09 +08:00
aias00andCalvin 5b50307e8c [feature] add valkey template (#2547)
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-08-18 07:33:26 +08:00
Logic 4f7ba7355f Add Contributors' chart (#2548) 2024-08-17 23:04:15 +08:00
aias00andYuLuo 4733ac2eba [bugfix] fix monitor search sync error (#2546)
Co-authored-by: YuLuo <yuluo08290126@gmail.com>
2024-08-17 17:38:21 +08:00
YuLuo e157d82a18 [infra] update actions checkout version to 4 (#2544)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
2024-08-17 15:26:03 +08:00
YuLuo f1a123ee76 [chore] fix typo (#2543)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
2024-08-17 10:14:13 +08:00
584b70a726 [improve] delete deprecate field (#2537)
Co-authored-by: YuLuo <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-17 00:18:22 +08:00
tomsun28andYuLuo 9d62270131 [improve] auto generate readable random monitor name (#2531)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: YuLuo <yuluo08290126@gmail.com>
2024-08-17 00:04:19 +08:00
53a506569a [improve]ElasticSearch historical chart display optimization (#2535)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: YuLuo <yuluo08290126@gmail.com>
2024-08-16 23:56:02 +08:00
0ec6a3b6ba [imporve] simplify NoticeConfig Code. (#2530)
Co-authored-by: 刘进山 <liujs@hsmap.com>
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-08-16 22:03:55 +08:00
kangliandtomsun28 c8560e6b16 [bugfix] webhook template json escape (#2532)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-16 17:49:57 +08:00
YuLuoandCalvin 361e573d8e [optimize] use okhttpclient connection pool (#2529)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-08-16 10:49:43 +08:00
tomsun28 c12b4c0d84 [bugfix] fix github action build docker image error (#2525)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2024-08-15 21:10:55 +08:00
tomsun28 9b065f7ec0 [infra] support build and push docker image to hub nightly everyday (#2517) 2024-08-14 00:17:35 +08:00
tomsun28 ffa81a68f7 [infra] add sub git module hertzbeat-helm-chart (#2522) 2024-08-14 00:14:30 +08:00
Calvin ed21cc3a94 [improve] fix spotless check failed (#2521) 2024-08-13 22:29:56 +08:00
35616d2763 [improve] add windows i18n (#2513)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-08-13 14:19:08 +08:00
Jast fbb74199c9 [feature] add markdown formatter (#2519) 2024-08-13 14:16:41 +08:00
YuLuoandCalvin 3a2350b86d [improve] add MemoryDataStorage unit test (#2515)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-08-12 23:34:08 +08:00
YuLuoandtomsun28 b39602f15d [improve] add MetricsDataRedisCodec unit test (#2514)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-12 23:28:22 +08:00
Jastandtomsun28 86c7c2dadf [Improve]add presto monitor metric (#2516)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-12 23:26:32 +08:00
aias00andtomsun28 ddfa60e597 [improve] add spring tidb i18n (#2512)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-12 23:04:48 +08:00
aias00 e34b64062e [improve] add shenyu\spring gateway i18n (#2511) 2024-08-12 22:56:46 +08:00
aias00andtomsun28 0634e7bb2e [improve] add redis cluster i18n (#2510)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-12 22:51:08 +08:00
aias00andtomsun28 0920910738 [improve] add pulsar push rabbitmq i18n (#2509)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-12 22:45:40 +08:00
aias00andtomsun28 8ae4d0e2d3 [improve] add oracle i18n (#2508)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-12 22:07:31 +08:00
aias00 1c5b3f9c3f [improve] add kafka influxdb jetty i18n (#2507) 2024-08-12 21:14:33 +08:00
YuLuoandtomsun28 a55a098983 [improve] Replacing characters with http constants (#2500)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-12 08:00:17 +08:00
aias00andliutianyou a8c1c48390 [improve] add more yml i18n (#2505)
Co-authored-by: liutianyou <tianyou.liu@qq.com>
2024-08-12 07:46:24 +08:00
aias00andtomsun28 9f7be0292a [improve] add hertzbeat i18n (#2506)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-11 22:12:27 +08:00
aias00andtomsun28 3250bc714d [improve] add hive i18n (#2504)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-11 22:06:03 +08:00
YuLuoandtomsun28 3d3d881722 [improve] add ObjectStoreConfigServiceImpl unit test (#2502)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-11 16:44:53 +08:00
aias00 3c01298e86 [feature] add iceberg template (#2503) 2024-08-11 16:00:48 +08:00
YuLuo c650972f3d [improve] add AccountServiceImpl unit test (#2501)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
2024-08-11 11:21:15 +08:00
YuLuoandtomsun28 df4272a2f8 [bugfix] fix unit test errors in different languages. (#2498)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-10 09:16:14 +08:00
23d16ae921 [refactor] move code from CollectorController to CollectorService (#2433)
Co-authored-by: ceekay <chandrakant.vankayalapati@github.com>
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-08-09 23:42:12 +08:00
tomsun28andKerwin Bryant aeac1ffed4 [bugfix] fix alarm threshold ava can not modify (#2494)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Kerwin Bryant <kerwin612@qq.com>
2024-08-09 17:09:31 +08:00
YuLuoandtomsun28 bac607f6dd [Improve] add WarehouseServiceImpl unit test (#2497)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-08 23:55:45 +08:00
YuLuoandtomsun28 8faa13e7b4 [Improve] add AvailableAlertDefineIni & SystemSecretServiceImpl unit test (#2496)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-08 23:03:24 +08:00
tomsun28andcrossoverJie 3113487192 [refactor] refactor connect common cache (#2469)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: crossoverJie <crossoverJie@gmail.com>
2024-08-08 22:35:51 +08:00
liutianyouandtomsun28 7a7d4792cd [improve] remove demo plugin (#2492)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-08 20:41:08 +08:00
YuLuoandtomsun28 ec8cc517d1 [Improve] add SystemGeneralConfigServiceImpl & SmsGeneralConfigServiceImpl unit test (#2490)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-07 23:31:24 +08:00
YuLuoandtomsun28 12fee7fb01 [improve] add StatusPageServiceImpl unit test (#2491)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-07 23:21:03 +08:00
YuLuoandtomsun28 339a33a0bd [Improve] add ObsObjectStoreServiceImpl unit test (#2488)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-07 23:18:24 +08:00
aias00 e3a0fb4537 [improve] add vastbase template (#2487) 2024-08-07 23:16:46 +08:00
YuLuoandtomsun28 9b328ce34c [Improve] add unit test & fix some bugs (#2482)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-07 16:32:38 +08:00
YuLuoandtomsun28 e8dc6482ff [improve] add YamlImExportServiceImpl unit test (#2470)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-07 09:18:36 +08:00
c4fa738d65 [improve] add some code style improve (#2481)
Co-authored-by: Calvin <naruse_shinji@163.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-07 09:09:16 +08:00
6ac092dcd5 [improve] use file constant & extract file utils (#2474)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: Calvin <naruse_shinji@163.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-06 22:15:26 +08:00
YuLuoandtomsun28 fe403ed880 [improve] add TemplateConfigServiceImpl unit test (#2471)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-06 21:49:31 +08:00
kangliandCalvin d6b19691fb [refactor] move code from MetricsDataController to MetricsService (#2437)
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-08-06 21:07:53 +08:00
aias00 c2c00d44c7 [doc] fix md index order and typo (#2480) 2024-08-06 19:10:23 +08:00
YuLuo e9da2d2925 [Improve] add push module controller unit test (#2451)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Signed-off-by: YuLuo <yuluo08290126@gmail.com>
2024-08-06 10:57:31 +08:00
tomsun28 58e6e1a2a7 [improve] optimize collect thread prevent cpu idling (#2468)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2024-08-06 10:17:14 +08:00
YuLuoandCalvin 0c2cc59b55 [chore] add service test tmpl file (#2472)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-08-06 00:37:55 +08:00
kangliandCalvin 111f0f6b99 [refactor] move code from AlertSilencesController to AlertSilenceService (#2436)
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-08-06 00:03:43 +08:00
e560502d8e [refactor] move code from AlertsController to AlertService (#2435)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-08-05 23:52:40 +08:00
YuLuoandtomsun28 67983c2702 [Improve] add JsonImExportServiceImpl unit test (#2461)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-05 15:42:54 +08:00
YuLuoandtomsun28 033240341b [Improve] add ExcelImExportServiceImpl unit test (#2460)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-05 15:36:33 +08:00
YuLuoandtomsun28 35a8ec4275 [Improve] add AiServiceFactoryImpl unit test (#2459)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-05 15:10:31 +08:00
linDongandtomsun28 9ac45ab343 [improve] use constant (#2458)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-05 15:07:38 +08:00
aias00andtomsun28 4b5a97044c [improve] add missed field i18n (#2465)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-05 14:37:05 +08:00
lingluojunandtomsun28 477af0959f [refactor] extracting common function for KafkaCommonDataQueue (#2453)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-05 12:34:18 +08:00
YuLuoandtomsun28 a5b8f59242 feat fix log upload, when e2e fails it still uploads (#2464)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-05 12:00:27 +08:00
linDongandtomsun28 98b8d95b92 [improve] : Optimize queues to obtain data and prevent cpu idling (#2466)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-05 11:42:07 +08:00
kangliandCalvin c0ef4a436e [refactor] move code from AlertConvergesController to AlertConvergeService (#2428)
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-08-04 23:54:43 +08:00
kangliandCalvin 254421bc46 [refactor] move code from AlertReportController to AlertService (#2434)
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-08-04 23:37:52 +08:00
Jast deb827a572 [doc] Add zookeeper doc (#2456)
merge
2024-08-04 19:22:54 +08:00
YuLuoandtomsun28 7eef0c21f1 [Improve] add push module service unit test (#2452)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-04 00:00:49 +08:00
YuLuoandtomsun28 58920978c3 [Improve] add StatusPagesController & StatusPagePublicController unit test (#2446)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-03 23:59:35 +08:00
YuLuoandtomsun28 a4c6a6045f [Improve] add MetricsController unit test (#2445)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-03 23:54:40 +08:00
YuLuoandtomsun28 6e47da758e [Improve] add GeneralConfigController unit test (#2444)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-03 23:53:19 +08:00
YuLuoandtomsun28 ae03111a75 [Improve] add AiController unit test (#2443)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-03 23:47:24 +08:00
lingluojunandtomsun28 69b8db7048 [improve] remove useless invoke method (#2450)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-03 23:32:46 +08:00
aias00andtomsun28 de657f9144 [improve] add i18n for postgresql kingbase greenplum (#2448)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-03 23:26:36 +08:00
YuLuoandtomsun28 822825b614 [improve] add TimeZoneListener test (#2432)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-03 23:20:24 +08:00
YuLuoandtomsun28 7672502c3d [Improve] add AlertSerializer & AlertDeserializer unit test (#2430)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-03 18:19:30 +08:00
YuLuo 598ed2ea16 [ci] add e2e logs to debug e2e test & delete unnecessary files (#2447)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
2024-08-03 18:10:07 +08:00
kangliandCalvin aee969a18a [refactor] move code from AlertDefinesController to AlertDefineService (#2429)
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-08-02 23:15:45 +08:00
YuLuoandtomsun28 b0438da537 [Improve] add KafkaMetricsDataSerializer & KafkaMetricsDataDeserializer unit test (#2431)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-02 18:01:53 +08:00
aias00 c85e182119 [feature] add greenplum template (#2442) 2024-08-02 17:12:40 +08:00
aias00 7446d3ebbf [feature] add oceanbase template (#2439) 2024-08-02 12:04:18 +08:00
YuLuoandtomsun28 f6e8e64e23 [Improve] add AlertSilenceController unit test (#2425)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-02 10:34:55 +08:00
Jast 2a3f4dfa80 [Improve] script command blacklist (#2438) 2024-08-02 10:05:10 +08:00
YuLuoandtomsun28 3d99835487 [Improve] add AlertConvergesController & AlertConvergeController unit test (#2424)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-01 10:31:18 +08:00
YuLuoandtomsun28 3a7d5829ad [Improve] add AlarmCommonReduce unit test (#2412)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Signed-off-by: YuLuo <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-01 10:16:26 +08:00
kangliandtomsun28 51b1a9bdc7 [bugfix] fixed jpa expired data clean error (#2329)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-08-01 10:08:11 +08:00
kangliandCalvin 181ca5aa5e [refactor] move code from MonitorsController to MonitorService (#2415)
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-08-01 00:01:11 +08:00
Limboandtomsun28 a5c444a49a [chore] update web-app readme (#2423)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-31 19:32:25 +08:00
Kerwin Bryant 2784c8fa6b Optimize the execution efficiency of Gitpod tasks (#2422) 2024-07-31 19:28:31 +08:00
kangliandCalvin ae4a5b1c63 [refactor] move code from GeneralConfigController to ConfigService (#2414)
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-07-31 00:48:10 +08:00
kangliandCalvin c7f4390638 [refactor] move code from NoticeConfigController to NoticeConfigService (#2416)
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-07-31 00:41:40 +08:00
kangliandCalvin c998d3b850 [refactor] move code from PluginController to PluginService (#2417)
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-07-31 00:36:06 +08:00
kangliandCalvin 861e9d377f [refactor] move code from TagController to TagService (#2418)
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-07-31 00:31:08 +08:00
YuLuoandtomsun28 c1252fbe2b [Improve] add AlarmConvergeReduce unit test (#2410)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-30 23:57:51 +08:00
YuLuoandtomsun28 dce9a4b15e [Improve] add AlarmSilenceReduce unit test (#2409)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-30 23:37:13 +08:00
Kerwin Bryant 15768d8077 [infra] support contribute with Gitpod (#2419) 2024-07-30 21:31:09 +08:00
linDongandtomsun28 2824542037 [doc] Fix profile (#2408)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-30 18:26:25 +08:00
aias00andtomsun28 f9bce29523 [feature] add sms config (#2399)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-30 18:20:00 +08:00
aias00andtomsun28 6b7dbd53f4 [doc] fix mistake md content (#2406)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-29 23:27:50 +08:00
aias00andtomsun28 f5e88db841 [improve] modify ssh client common config (#2403)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-29 22:46:08 +08:00
kangliandtomsun28 82219d14df [Improve] add database file server provider (#2371)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-29 22:30:47 +08:00
Loongandtomsun28 05bce69b84 [collector] bugfix Fix ssh session not closing properly (#2398)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-29 20:44:21 +08:00
YuLuoandCalvin bc49280c3c [Improve] add AlertDefineYamlImExportServiceImpl unit test (#2392)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-07-29 17:05:17 +08:00
Kerwin Bryant 90035cac5d [doc] introduction document for the new committer (#2401) 2024-07-29 12:26:57 +08:00
YuLuoandCalvin 3487e4a16b [Improve] add AlertDefineJsonImExportServiceImpl unit test (#2391)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Signed-off-by: YuLuo <yuluo08290126@gmail.com>
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-07-29 01:24:03 +08:00
YuLuoandCalvin 974b27e878 [Improve] add AlertSilenceServiceImpl unit test (#2393)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-07-29 01:10:24 +08:00
aias00andtomsun28 22459c5b6f [improve] add some code style improve (#2376)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-28 19:14:04 +08:00
linDongandtomsun28 64e156be2a [doc] add committer introduction doc (#2394)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-28 16:58:24 +08:00
Calvinandtomsun28 a9827bbcef [refactor] move code from AccountController to AccountService (#2373)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-28 10:35:01 +08:00
Calvinandtomsun28 0ed1355d76 [docs] add new_committer.md (#2390)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-28 09:55:01 +08:00
Calvinandtomsun28 0b81717a9e [docs] update img of new_committer_process.md (#2389)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-28 09:43:42 +08:00
Kerwin Bryantandtomsun28 86ca62c67a [bugfix] fixed the issue of missing form validation for the "Rule(Expr)" item in the "Threshold" form (#2387)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-28 09:32:15 +08:00
YuLuo 7488dfadc9 [Improve] add SmsAlertNotifyHandlerImpl unit test (#2384)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
2024-07-26 22:03:06 +08:00
YuLuoandtomsun28 50fe51bd95 [Improve] add WebHookAlertNotifyHandlerImpl unit test (#2383)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-26 11:55:19 +08:00
aias00andtomsun28 8233a62aea [type:feature] support alerts click to monitor detail (#2385)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-26 11:41:35 +08:00
YuLuoandtomsun28 7367b7315b [Improve] add AlertDefineExcel unit test and fix bugs (#2375)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-26 11:33:15 +08:00
tomsun28andCalvin 9e305f7a59 [bugfix] fix monitors alarms some query filter not work, update link (#2382)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Calvin <naruse_shinji@163.com>
2024-07-26 00:03:47 +08:00
YuLuoandtomsun28 3d9be220e6 [Improve] add ServerChanAlertNotifyHandlerImpl unit test (#2381)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-25 22:29:37 +08:00
YuLuoandtomsun28 659346ddd7 [Improve] add CollectServer unit test (#2379)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Signed-off-by: YuLuo <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-25 21:47:15 +08:00
kangliandtomsun28 7f0b340663 [bugfix] fix email send error (#2378)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-25 21:39:36 +08:00
YuLuo a427099db7 [Improve] add GotifyAlertNotifyHandlerImpl unit test (#2380)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
2024-07-25 21:17:29 +08:00
YuLuoandtomsun28 d1d28e6763 [Improve] add EmailAlertNotifyHandlerImpl unit test (#2370)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-25 10:13:03 +08:00
YuLuoandtomsun28 ba70b2f269 [Improve] add WeComAppAlertNotifyHandlerImpl send notify test (#2369)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-25 08:33:30 +08:00
YuLuoandtomsun28 2352ceef3d [Improve] add dispatchalarm unit test (#2364)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-25 08:14:34 +08:00
YuLuoandtomsun28 927625a79f [Improve] add timezoneutil unit test (#2362)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-25 00:23:17 +08:00
linDongandtomsun28 16a6620ff6 [fix] fix committer name (#2372)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-25 00:17:08 +08:00
YuLuoandtomsun28 a1d016e5d5 [Improve] add strbuffer unit test (#2361)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-24 23:55:27 +08:00
Kerwin Bryantandtomsun28 40aa5a4d73 Fixed the issue of style anomaly caused by incorrect usage of nz-card-tab (#2368)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-24 23:48:47 +08:00
YuLuoandtomsun28 aef7ac23c4 [Improve] add prometheusUtil unit test (#2360)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-24 23:45:53 +08:00
Zhang Yuxuanandtomsun28 348b50c4c6 [feature] Optimize script protocol and add Windows-script yml template (#2367)
Signed-off-by: Zhang Yuxuan <1373529784@qq.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-24 23:38:10 +08:00
liutianyouandtomsun28 88538890b4 [doc] supplement custom plugin doc (#2309)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-24 23:28:09 +08:00
kangliandtomsun28 fa4a3fd9e1 [imporve] add template i18n map verify (#2345)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-24 23:20:44 +08:00
Kerwin Bryantandtomsun28 3a24edb309 Fixed the issue of a fleeting vertical scrollbar appearing in tab-content (#2363)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-24 23:11:39 +08:00
aias00andtomsun28 e142a498e2 [improve] upgrade ssh core dependency version (#2349)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-24 23:05:53 +08:00
f4685aa75a [bugfix] Unable to specify collector when creating a monitor (#2311)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Logic <zqr10159@dromara.org>
Co-authored-by: Kerwin Bryant <kerwin612@qq.com>
2024-07-24 11:25:25 +08:00
kangliandtomsun28 f038ec5326 [Improve] add CommonUtil unit test (#2346)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-24 10:15:05 +08:00
aias00andtomsun28 06186c5ccc [improve] modify Intervals steps (#2348)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-24 09:43:25 +08:00
Calvinandtomsun28 6c931956fa [improve] add redis data storage test case (#2356)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-24 09:34:25 +08:00
YuLuoandtomsun28 809f679375 [Improve] add DbAlertStoreHandlerImpl unit test (#2353)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-24 09:29:15 +08:00
Logicandtomsun28 b31d8b1380 [bugfix]: correct setInterval time interval to 2 minutes (#2355)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-24 00:11:43 +08:00
Kerwin Bryantandtomsun28 1bba56bfbc Optimize the layout of the "Deploy Collector" modal (#2354)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-24 00:08:07 +08:00
YuLuoandtomsun28 357068cc8f [Improve] add CollectDispatcher & NettyDataQueue unit test (#2336)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Signed-off-by: YuLuo <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-24 00:04:38 +08:00
YuLuoandtomsun28 8a88607be9 [Improve] add collectJonService unit test (#2351)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-23 23:30:44 +08:00
YuLuoandtomsun28 15e9bd0656 [Improve] add redis data queue unit test (#2330)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Signed-off-by: YuLuo <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-23 23:13:03 +08:00
Kerwin Bryantandtomsun28 aa58f0af7f Remove the empty footer of "AppSwitchModal" (#2352)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-23 22:59:41 +08:00
Kerwin Bryantandtomsun28 115f7b40c5 [bugfix] Fixed an issue of ssl linkage port on the monitoring editing page (#2350)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-23 22:56:03 +08:00
aias00andtomsun28 d2c19cbf95 [type:feat] support KingBase database monitor (#2341)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-23 22:31:03 +08:00
aias00 173733784b [type:fix] fix threshold rule modal not clear bug (#2340) 2024-07-23 18:50:14 +08:00
Calvinandtomsun28 df4115a64c [refactor] translate chinese into english in web-app (#2343)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-23 08:59:56 +08:00
tomsun28 8d34de4422 [doc] update doc and deploy guide and committer (#2342) 2024-07-23 07:51:08 +08:00
aias00andtomsun28 a482d24770 [bugfix] fix i18n null (#2338)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-22 23:01:11 +08:00
YuLuoandtomsun28 aee8481204 [Improve] add some unit test (#2334)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-22 22:55:44 +08:00
Kerwin Bryantandtomsun28 497338e00f [bugfix] Fixed an i18n issue (#2332)
Signed-off-by: Kerwin Bryant <kerwin612@qq.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-22 22:39:10 +08:00
YuLuo e5236259ff [chore] optimize e2e folder struct (#2316)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Signed-off-by: YuLuo <yuluo08290126@gmail.com>
2024-07-22 22:32:10 +08:00
Calvinandtomsun28 712c54186e [feature] support redis cluster and sentinel mode in real time data (#2324)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-21 21:49:24 +08:00
YuLuoandtomsun28 7aa3be8f7d [Improve] add kafak queue unit test (#2317)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Signed-off-by: YuLuo <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-21 21:40:53 +08:00
YuLuo f84e1fc5bf [Improve] add unit test & fix some bugs (#2326)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
2024-07-21 21:03:37 +08:00
YuLuoandtomsun28 a8c1921fa3 [Improve] add commonThreadPoll unit test (#2327)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-21 17:33:02 +08:00
aias00andtomsun28 43afb0bc63 [type:fix] fix empty value not be handled by custom metrics (#2323)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-21 17:11:02 +08:00
YuLuoandtomsun28 ee9bdf6773 [Improve] add redis data queue impl (#2319)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-21 17:01:18 +08:00
229b4158cc [bugfix]: fix theme is invalidated after refresh (#2321)
Co-authored-by: Keaifa <keaifafafa@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-21 16:29:23 +08:00
liutianyou 3d49b288bb [doc] modify the document that uses PostgreSQL to store metadata (#2322) 2024-07-21 15:53:12 +08:00
Zhang Yuxuanandtomsun28 e0caceda92 [feature] Support collector to run scripts directly as agents to collect metrics. (#2313)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-20 15:59:05 +08:00
铁甲小宝andtomsun28 0b73e0900b [bugfix] Notice template fix (#2320)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-20 15:26:45 +08:00
Kerwin Bryantandtomsun28 1a09611ad6 [feature] Add the editing mode of "complex rule nesting" to support "threshold rules" (#2315)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-20 15:03:10 +08:00
jiangshandtomsun28 be0de49646 [manager] collectorApi unit test case and example (#2306)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-20 14:46:16 +08:00
YuLuoandtomsun28 061423d301 [chore] Update readme doc style (#2305)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-20 14:25:48 +08:00
YuLuoandtomsun28 6421fef548 [Improve] Optimize spring auto configuration registry (#2304)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-20 10:24:51 +08:00
kangliandtomsun28 70af0669c6 [bugfix] Only POST and PUT methods carry payload (#2302)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-19 16:53:29 +08:00
YuLuoandtomsun28 55b3dd7f0c [Improve] Optimize ResourceBundle & add unit test. (#2297)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-19 16:51:19 +08:00
Calvin 91111e5555 [refactor] remove chinese and change code style in Warehouse (#2312) 2024-07-19 16:28:40 +08:00
铁甲小宝 07913e7d51 A small code specification change. (#2299) 2024-07-18 01:01:29 +08:00
YuLuo 38d466b7f8 [Improve] add common/util/StrUtil unit test (#2301)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
2024-07-17 22:36:42 +08:00
tomsun28andliutianyou 9770c9321e [doc] update committer and contributor (#2295)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: liutianyou <tianyou.liu@qq.com>
2024-07-17 16:28:29 +08:00
QBH-insist 7e5283ea0d [doc] fix mysql connections field explanation (#2294) 2024-07-17 10:25:42 +08:00
YuLuoandtomsun28 8f659f0fd1 [Improve] add common memory unit test (#2280)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-17 09:51:04 +08:00
liutianyouandtomsun28 7a4ee880c3 [doc]add new committer blog (#2291)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-16 23:18:53 +08:00
linDong 3b323e1882 [test] add NoticeConfigControllerTest and MonitorsControllerTest test (#2290) 2024-07-16 22:57:02 +08:00
YuLuoandtomsun28 acc617f9bd [Improve] add springContextHolder unit test (#2287)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-16 21:33:50 +08:00
Logic 5585993503 [bugfix] added basic auth support for VictoriaMetrics status check (#2282) 2024-07-16 16:35:44 +08:00
kangliandtomsun28 fd0e216818 [bugfix] fixed self signed certificate detected bug #1534 (#2221)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-15 14:57:21 +08:00
999b37ec4f [bugfix] fixed unable to establish a connection to nginx https port bug #1655 (#2218)
Co-authored-by: Logic <zqr10159@dromara.org>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-14 23:15:48 +08:00
linDongandtomsun28 823430bca9 [improve] : Modified loading application.yml (#2256)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-14 23:04:35 +08:00
Jastandtomsun28 9a7e0411a1 [fixbug]fix parameter parsing problem (#2251)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-14 01:10:35 +08:00
CalvinandLogic 3a2e0b3dd2 [feature] support collect data from header (#2266)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-07-13 09:07:58 +08:00
tomsun28andLogic 25d27880aa [doc] update download link doc (#2264)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-07-13 09:03:02 +08:00
liutianyouandtomsun28 8a11dacdba [bugfix] fix error when delete plugin (#2265)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-11 16:04:37 +08:00
Kerwin Bryant 467c595802 Fixed issue of plugin-upload form (#2267) 2024-07-11 15:58:05 +08:00
Kerwin Bryant c70cc5d9b7 Fixed failure of form validation (#2261) 2024-07-10 23:17:02 +08:00
Kerwin Bryant 8f9143001f Fixed failure of alert form validation (#2259) 2024-07-10 16:21:53 +08:00
Kerwin Bryant 3e50b96322 Fixed failure of monitoring form validation (#2258) 2024-07-10 15:42:10 +08:00
Kerwin Bryantandtomsun28 9cf0e6f4ee Decouple tag selection into an independent basic component. (#2257)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-09 23:55:48 +08:00
Logicandtomsun28 d47d3be6b4 [docs] Update guides for HertzBeat 1.6.0 upgrade and MySQL driver url (#2255)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-09 23:50:10 +08:00
Kerwin Bryant 6cabe3ca0c Further enhance and refine the optimizations implemented in #2215. (#2249)
Signed-off-by: Kerwin Bryant <kerwin612@qq.com>
2024-07-09 16:19:06 +08:00
Kerwin Bryant 874f7bdab3 Optimize the processing logic for Depend-type fields (#2248) 2024-07-09 10:52:12 +08:00
crossoverJieandtomsun28 f90d1e6242 [doc] Rename the blog file. (#2247)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-08 23:19:12 +08:00
Jastandtomsun28 afcb0c19fb [doc] add new committer blog (#2246)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-08 23:17:41 +08:00
Jastandtomsun28 0e7323fc04 [improve]update doc and prestodb properties (#2243)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-08 22:55:19 +08:00
feb60a7da9 [improve] : Optimize refactoring code, and supplement documentation (#2239)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-07-08 20:28:24 +08:00
linDongandcrossoverJie 2e7616cd56 [test] : Added the AppControllerTest test case (#2237)
Co-authored-by: crossoverJie <crossoverJie@gmail.com>
2024-07-08 19:38:21 +08:00
liutianyouandLogic 2d53abdaab [feature] add plugin management and support plugin hot reloading (#2238)
Signed-off-by: liutianyou <tianyou.liu@qq.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-07-08 18:53:49 +08:00
Kerwin BryantandLogic 9fed2c8a36 Optimize the monitor-edit page (#2242)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-07-08 18:27:12 +08:00
Kerwin BryantandLogic a4db859eee For Spring applications, newly added support basic-auth. (#2241)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-07-08 18:24:39 +08:00
linDongandLogic 9a3a2f0a54 [improve] : Delete Chinese comments, modify word errors, add Operatio… (#2236)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-07-08 17:42:47 +08:00
linDongand铁甲小宝 da05b6a151 [feature] Add presto db monitor (#2234)
Co-authored-by: 铁甲小宝 <2922035952@qq.com>
2024-07-08 14:39:38 +08:00
YuLuoandtomsun28 78621f2f14 [Improve] add TimePeriodUtil & ResourceBundleUtil unit test (#2233)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-07 20:50:09 +08:00
crossoverJieandtomsun28 a618ff00ea [doc] Introduce Committer (#2232)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-07 20:44:40 +08:00
Calvin 044c6d4bad [e2e] complete e2e test case (#2231) 2024-07-07 20:33:13 +08:00
Calvinandtomsun28 53787cc215 [bugfix] auto config timezone for Jackson (#2122)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-07 14:52:13 +08:00
d884278fed [fix] add springboot3.0 autoconfig (#2230)
Co-authored-by: jiawei.guo <18613599970@163.con>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-07 09:45:57 +08:00
YuLuoandtomsun28 21a7788522 [Improve] add ProtoJsonUtil unit test (#2228)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-06 23:23:36 +08:00
YuLuoandtomsun28 c7d192996a [Improve] add MapCap & LruMap unit test (#2227)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-06 22:55:58 +08:00
Calvin 78ce1cdc1f [refactor] remove chinese in application.yml (#2226) 2024-07-06 18:43:33 +08:00
tomsun28andLogic 12230b47ca [doc] update new contributors wall (#2225)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-07-06 09:15:51 +08:00
Jastandtomsun28 753ea44d2b [improve] optimize code structure and doc modify (#2222)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-05 23:54:08 +08:00
Logicandtomsun28 c3faea07c2 [improve] WeCom app supports sending to specific users, departments, tags (#2220)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-05 23:37:31 +08:00
mchgood 4149a027a7 [Improve] add @Override (#2224) 2024-07-05 22:52:51 +08:00
Kerwin Bryant 65d69eb191 Fixed style issue of chart in detail-page (#2219) 2024-07-05 17:29:21 +08:00
Kerwin Bryantandtomsun28 5e2e78fe95 Hide the area when there are no advanced settings (#2215)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-05 15:51:46 +08:00
Kerwin Bryantandtomsun28 e992da78cd Two new functions are added to the notification center (#2214)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-05 15:44:22 +08:00
YuLuo 2fd0090e83 [Chore] translate zh -> en in pom.xml (#2213)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
2024-07-05 15:34:50 +08:00
linDongandLogic a86fc85ffc [feature] : add SparkDesk Ai (#2185)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-07-05 11:23:03 +08:00
f3cecea307 [doc] add redis-cluster help document[New] (#2210)
Co-authored-by: Zhengke Zhou <zhengke.zhou@rightcapital.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-07-05 11:12:48 +08:00
Kerwin Bryant cbf6536923 Optimize the user experience of monitoring list pages. (#2211) 2024-07-05 11:07:42 +08:00
Kerwin Bryant 336eaffd27 Optimize the user experience of monitoring list pages. (#2209) 2024-07-05 10:04:58 +08:00
Kerwin BryantandLogic b9f8b7de72 Unified the search interaction of the list page. (#2207)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-07-05 09:58:11 +08:00
YuLuoandLogic 5b44a95298 [Improve] add IpDomainUtil & IntervaiExpressionUtil unit test (#2204)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-07-05 09:51:50 +08:00
YuLuoandLogic 97e5435296 [chore] update community contribution.md files (#2199)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-07-05 09:43:44 +08:00
JastandLogic 9b31fe785f [improve]add zookeeper envi monitor (#2202)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-07-05 09:40:35 +08:00
Kerwin BryantandLogic f6fcd52a50 Optimize the tags-selection. (#2198)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-07-05 09:35:41 +08:00
Kerwin Bryantandtomsun28 19a59004de Optimize the detail-page of monitor. (#2196)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-05 09:32:12 +08:00
Kerwin Bryantandtomsun28 f9b04ceb0c Add a missing multi-language translation. (#2194)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-04 19:44:39 +08:00
kangliandtomsun28 7ee227196d [bugfix] fixed "Alert Threshold Association with Monitors" is invalid bug #2105 (#2191)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-04 19:11:17 +08:00
Kerwin Bryantandtomsun28 20f3b01251 Optimize the [Threshold Rule] Form. (#2190)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-04 18:56:08 +08:00
Kerwin Bryant 9260bca057 Optimize the dashboard. (#2193) 2024-07-04 18:53:05 +08:00
Kerwin Bryantandtomsun28 6cdffbefac Optimize the visual experience of the monitoring details page. (#2189)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-04 10:49:31 +08:00
crossoverJieandtomsun28 0699e89346 [Improve] Refactor the notification sending logic. (#2180)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-04 10:21:01 +08:00
linDongandtomsun28 6222c51f41 [doc] add kimiAi doc (#2184)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-04 10:11:57 +08:00
Jastandtomsun28 ccbc7c698e [doc] add status page doc (#2186)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-04 09:10:49 +08:00
Kerwin BryantandLogic b5c7705f4a [bugfix] fixed issue of status-page (#2182)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-07-04 09:02:16 +08:00
Kerwin Bryant eeba46af9f Fixed issue of acions in list-page. (#2181) 2024-07-04 08:47:25 +08:00
b4d0e77c99 [feature] : support kimi Ai (#2171)
Co-authored-by: Logic <zqr10159@dromara.org>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-04 07:52:48 +08:00
Kerwin Bryant 1cb293ac03 [bugfix] fixed issue of monitor-select-menu-modal (#2177) 2024-07-04 07:47:19 +08:00
Kerwin Bryantandtomsun28 2ffdda8f26 [improve] optimize the monitoring editing form. (#2172)
Signed-off-by: Kerwin Bryant <kerwin612@qq.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-03 14:31:48 +08:00
Logic 4f1c62fa3a [doc]Add new committer crossoverJie. (#2170) 2024-07-02 19:58:30 +08:00
Kerwin BryantandLogic bfe68d8a06 Optimize the style of the header on the monitoring details page. (#2167)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-07-02 15:09:08 +08:00
Kerwin BryantandLogic 215271716d Optimize the content styling of the monitoring details page. (#2168)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-07-02 15:06:59 +08:00
Kerwin Bryant fafc6a8212 Optimize the help-message-show component (#2169) 2024-07-02 14:48:03 +08:00
liutianyouandtomsun28 e860e63f62 [bugfix] modify the prompt information for deleting used tags (#2165)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-02 09:40:05 +08:00
mchgood 702446190d [doc] update contribution.md (#2164)
Signed-off-by: mchgood <38482005+mchgood@users.noreply.github.com>
2024-07-01 23:02:59 +08:00
linDong 7251fb4185 [docs] : Alibaba Ai config doc (#2162) 2024-07-01 21:49:20 +08:00
12bb21cb8d [feature] :support alibaba Ai (#2153)
Co-authored-by: Logic <zqr10159@dromara.org>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-01 21:35:29 +08:00
Kerwin Bryant a7f30fc1f6 [bugfix] add missing multi-language translations. (#2163) 2024-07-01 13:57:32 +08:00
liutianyouandtomsun28 2cc779ce1c [fix] remove i18 message in restful api (#2161)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-07-01 09:59:11 +08:00
Kerwin Bryant 27c394d9f7 [bugfix] fixed notify module error (#2160) 2024-06-30 09:24:14 +08:00
b25f1834e8 Modified docker command documentation (#2158)
Co-authored-by: daixianglong <daixianglong@xiaomi.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-06-28 16:28:43 +08:00
Kerwin Bryant c878ac8fad [improve] support for formControlName to the multi-func-input component. (#2157) 2024-06-28 16:12:58 +08:00
JastandLogic 0ebcffa408 [improve] optimize delimiters (#2155)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-06-28 10:58:39 +08:00
Kerwin Bryant 5ef96061c9 [improve] add support for search type to the multi-func-input component. (#2154) 2024-06-28 10:28:55 +08:00
liutianyou c06f53c926 [bugfix] fix deleting component error (#2152) 2024-06-28 00:17:54 +08:00
Kerwin Bryant 51765d8f9a Add a basic component for "Monitoring Selection Menu" (#2150) 2024-06-27 19:35:19 +08:00
Kerwin Bryant 1fe37d3789 [feature] add a search to the setting define page. (#2148) 2024-06-27 11:32:25 +08:00
Kerwin BryantandLogic baf2d5f536 Fixed the issue that the [first loading] does not appear (#2144)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-06-26 18:22:43 +08:00
Kerwin BryantandLogic 5757d7427d Add a loading animation to the /setting/define page. (#2145)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-06-26 18:18:55 +08:00
Kerwin BryantandLogic cbb4b8c736 Add a new common toolbar component. (#2143)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-06-26 18:14:16 +08:00
liutianyouandLogic dbac0dfe63 [bugfix] add incident publishing form validation (#2139)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-06-26 18:11:45 +08:00
Kerwin Bryant 8c0b39f69b [improve] continuously supplement and improve the goals set in #2140 (#2142) 2024-06-26 10:24:28 +08:00
a54d8cdd11 [improve] : fix AiService getType method data type,complete information for LICENSE (#2141)
Co-authored-by: Logic <zqr10159@dromara.org>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-06-25 23:42:15 +08:00
Kerwin BryantandLogic ec1c41cf68 Unify the border-radius values of the all components. (#2140)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-06-25 23:30:13 +08:00
tomsun28 93635a0482 [doc] add new committer shenghang (#2137) 2024-06-25 23:20:14 +08:00
Jastandtomsun28 59266ccb8a [doc] doc add committer process (#2136)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-06-25 22:07:19 +08:00
Kerwin Bryant bc4b399a21 [bugfix] fixed the layout styling issue of the left list on the setting/define. (#2134) 2024-06-25 21:43:55 +08:00
Kerwin Bryantandtomsun28 87756f16d9 [improve] support for password type to the app-multi-func-input component. (#2132)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-06-25 15:38:50 +08:00
e1cda5066e [docs] : Add an ai configuration document (#2130)
Co-authored-by: Logic <zqr10159@dromara.org>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-06-25 15:26:31 +08:00
fa0e9ef50a [feature] support ai api with zhipu ai (#2120)
Co-authored-by: Logic <zqr10159@dromara.org>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-06-25 14:34:22 +08:00
Kerwin Bryant a10c2bfbd8 Fixed the issues similar to #2127 on the alert center page. (#2131) 2024-06-25 12:08:11 +08:00
liutianyouandtomsun28 33877615c5 [improve] add configuration for mounting logs (#2128)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-06-25 08:32:09 +08:00
linDongandtomsun28 13411105ed [bug]fix the monitor status is abnormal (#2070)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-06-25 00:04:13 +08:00
e2faa44f18 [fixbug] fix string type data parsing problem (#2066)
Co-authored-by: zhangshenghang <admin@hadoop.wiki>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-06-24 17:45:12 +08:00
Kerwin Bryant 657de4f5b6 Add an input box component with a removal function. (#2127) 2024-06-24 17:19:26 +08:00
Kerwin Bryantandtomsun28 dfa6895a7e [bugfix] fixed the bug of the status filter in the alert center. (#2125)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-06-24 11:18:03 +08:00
Kerwin Bryant a9de486744 [bugfix] fix the status filter in the monitoring center (#2124) 2024-06-24 11:08:25 +08:00
Kerwin Bryant 31d8712299 Fixed the i18n issue similarly to #2117. (#2119) 2024-06-22 13:59:02 +08:00
Kerwin BryantandLogic c4a6e36977 Fixed the i18n issue of the [New Notice Policy] form. (#2117)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-06-21 20:09:11 +08:00
Kerwin BryantandLogic 41c3bf50ee Uniformly use [...] to replace the phrase [More]. (#2115)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-06-21 20:07:01 +08:00
Kerwin BryantandLogic 957cce93d9 Optimize the layout of the [New Threshold Rule] form. (#2116)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-06-21 19:14:30 +08:00
9b7b00e09c Optimize the visual experience of the nz-table template. (#2112)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-06-21 15:25:33 +08:00
tomsun28andLogic b3976295f5 [improve] update collector info, support env config or auto fetch (#2100)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-06-21 15:17:57 +08:00
Kerwin Bryantandtomsun28 1be2631af7 optimize the visual experience of the level2Message module. (#2111)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-06-21 11:22:22 +08:00
Kerwin Bryant 5f5f4d0346 [bugfix] the prompt information on the Collector Cluster page (#2114) 2024-06-21 10:55:04 +08:00
Kerwin BryantandLogic 95c30f54cd fixed #2107 (#2108)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-06-20 20:55:03 +08:00
Kerwin BryantandLogic 855abf6ada Fixed a style issue within the dialog on the about-page. (#2109)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-06-20 20:52:04 +08:00
Kerwin Bryant bdf82751a5 Optimize the code by removing unnecessary attribute values (#2110) 2024-06-20 20:45:40 +08:00
f49e20535c [improve] optimization notification code validation (#2102)
Co-authored-by: zhangshenghang <admin@hadoop.wiki>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-06-20 09:14:16 +08:00
dennis zhuang a32757ea7a [feat] supports TTL for greptimedb data storage (#2101) 2024-06-20 08:57:06 +08:00
liutianyou bd52e0527e [bugfix] fix extract double and unit error when unit is Ki (#2099) 2024-06-19 21:46:20 +08:00
dennis zhuang 1bac42b094 fix: greptimedb can't work with version >= 0.5 (#2095) 2024-06-19 18:54:04 +08:00
Rickandrick a71c61a0d8 [fix] the e2e failure without broken the ci (#2093)
Co-authored-by: rick <LinuxSuRen@users.noreply.github.com>
2024-06-19 00:07:35 +08:00
crossoverJieandtomsun28 56db540721 [doc] add codecov badge (#2089)
Signed-off-by: crossoverJie <crossoverJie@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-06-18 10:51:36 +08:00
bc104dfe9f [doc] mysql monitoring help document adds steps for importing drivers (#2091)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-06-18 08:49:05 +08:00
tomsun28andLogic fc6ea4a2e0 [bugfix] fix some template menus hidden when too long (#2092)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-06-18 08:34:09 +08:00
Nctllnty 55c48d167c [bugfix] notice rules api access 409 error when upgrade 1.6.0 (#2090) 2024-06-18 07:25:56 +08:00
Rickandtomsun28 393bb95878 [chore] bump api-testing from v0.0.16 to v0.0.17 (#2087)
Signed-off-by: Rick <1450685+LinuxSuRen@users.noreply.github.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-06-17 22:49:33 +08:00
Jastandzhangshenghang 915fcbf1d9 [improve] enterprise wechat validate (#2086)
Co-authored-by: zhangshenghang <admin@hadoop.wiki>
2024-06-17 22:43:30 +08:00
Calvinandtomsun28 26b982a59b [license] update license document for jutf7 (#2082)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-06-17 08:00:38 +08:00
crossoverJieandtomsun28 3186aa5eb6 [Improve] support jacoco and codecov (#1985)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-06-16 22:53:43 +08:00
Zhang Yuxuanandtomsun28 a6ac326581 [feature] after new, edit, resume a monitor, display its status directly and correctly (#2065)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-06-16 16:27:35 +08:00
53b796ff57 [improve]add flink on yarn monitoring (#2078)
Co-authored-by: zhangshenghang <admin@hadoop.wiki>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-06-16 15:35:55 +08:00
Calvinandtomsun28 b7217b5d48 [feature] add column version and public Ip on collector page (#2072)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-06-16 14:48:18 +08:00
tomsun28 b8f2bf30fd [doc] add hertzbeat 1.6.0 release blog (#2083) 2024-06-16 09:08:58 +08:00
Leon Liandtomsun28 bc4ddefc76 [collector] fix the wrong condition for checking the response (#2067)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-06-15 10:26:25 +08:00
Zhang Yuxuanandtomsun28 2fcd100fec [feature] add automatic refresh to the monitoring center (#2064)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-06-14 22:58:24 +08:00
liutianyouandtomsun28 365de4657e [fix] fix unit test passing but outputting exception stack (#2063)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-06-14 22:55:43 +08:00
Zhang Yuxuanandtomsun28 d4e6317a30 [feature] Implement IMAP protocol support (#2059)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-06-14 22:47:40 +08:00
cc19831f7c [feature] support mongodb atlas cluster (#2052)
Co-authored-by: zhangshenghang <admin@hadoop.wiki>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-06-14 21:28:35 +08:00
Gao Jianandtomsun28 f10e5dbd06 [Improve] Fix possible potential thread unsafe issues (#2043)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-06-14 21:18:57 +08:00
af1f59e009 [feature] designated personnel send message (#2038)
Co-authored-by: zhangshenghang <admin@hadoop.wiki>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-06-13 23:28:58 +08:00
aias00andlimbo 009a512ba0 [feature] upgrade webapp angular deps version #1707 (#1987)
Signed-off-by: aias00 <rokkki@163.com>
Co-authored-by: limbo <yykaue@qq.com>
2024-06-12 15:13:56 +08:00
tomsun28 dc381ea338 [improve] update docker compose and k8s helm deploy script (#2076) 2024-06-11 17:52:30 +08:00
Logic 3ed52c54af [doc] hertzbeat 1.6.0 upgrade guide (#2077) 2024-06-11 16:51:26 +08:00
tomsun28and铁甲小宝 c5808a0430 [doc] update release 1.6.0 doc (#2074)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: 铁甲小宝 <2922035952@qq.com>
2024-06-11 00:18:14 +08:00
Calvin ed390a50c9 [fixed] required field check for tag settings (#2071) 2024-06-09 22:54:40 +08:00
linDongandtomsun28 cfe93bf19d [doc] add telnet protocol custom doc (#2061)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-06-05 02:45:41 +08:00
tomsun28 708b5a2b1b [improve] update dependency licenses and remove the aliyun sms depend (#2058)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2024-06-02 18:03:25 +08:00
liutianyouandtomsun28 f602bec140 [improve] add filename check in home ci (#2049)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-30 21:56:02 +08:00
xfl12345andtomsun28 4442383688 [doc] add the missing parts of docs, fix layout, sync the English version with the Chinese version (#2048)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-30 08:33:56 +08:00
lwyangandtomsun28 aaf3cf09c2 [docs] fix several typos in docs (#2047)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-30 08:29:24 +08:00
Zhang Yuxuanandtomsun28 f4fa8fcc52 [doc] remove duplicate indices page (#2045)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-29 22:15:43 +08:00
Zhang Yuxuan 26486135bf [improve] add test for MemcachedCollectImpl (#2044) 2024-05-29 22:13:53 +08:00
tomsun28andLogic a23d4466f6 [bugfix] fix collector and frontend dependent license error (#2037)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-05-27 14:50:44 +08:00
crossoverJie 228ace0296 [improve] checkstyle include testSource (#2036) 2024-05-27 11:11:21 +08:00
Zhang Yuxuanandtomsun28 b95a2a29ec [improve] increase the length limit of the username field (#2035)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-26 20:43:02 +08:00
Zhang Yuxuanandtomsun28 a2cebbf6ef [improve] fix code style (#2034)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-26 20:32:12 +08:00
Zhang Yuxuan 49ebdfbeae [improve] add IcmpCollectImplTest (#2033) 2024-05-26 17:04:44 +08:00
f9f12a2b9e [fixbug] required field check (#2022)
Signed-off-by: Jast <745925668@qq.com>
Co-authored-by: zhangshenghang <admin@hadoop.wiki>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-25 12:28:29 +08:00
Ceilzcx 1c82ce90f1 [improve] deprecate support iotdb 0.* version (#2032) 2024-05-25 12:21:10 +08:00
tomsun28 ba735545fb [improve] tips need update initial default password (#2030)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2024-05-25 00:22:00 +08:00
Calvin ddf6daa9f0 bugfix: fix overflow of integers (#2029) 2024-05-24 22:53:14 +08:00
tomsun28 a78f71d725 [improve] update monitor state desc (#2028)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2024-05-23 17:49:59 +08:00
linDongandtomsun28 8115e39828 [bugfix] modify popup confirm to clear cache and cancel popup save (#2026)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-23 09:58:51 +08:00
Bill Lauandtomsun28 7a670e88e8 [bugfix] tag with empty value shouldn't transform to tag: (#2025)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-23 00:51:36 +08:00
liutianyouandtomsun28 34b9581395 [improve] add ci for home (#2024)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-23 00:36:41 +08:00
Gao Jianandtomsun28 ddf1010116 [fix] Fix possible potential thread safe bugs (#2021)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-23 00:18:53 +08:00
YuLuoandtomsun28 18ee736669 [optimize] optimize code style and logic, add unit test (#2010)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Signed-off-by: YuLuo <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-22 23:33:00 +08:00
YuLuoandtomsun28 a8fd25afb1 [improve] optimize collector httpsd discovery (#1991)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-22 22:47:32 +08:00
liutianyouandtomsun28 9cc7597ad5 [doc] translate help document for memcached monitoring (#2019)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-21 18:30:21 +08:00
d93963b05d [Improve] Improve clickhouse monitor And Improve Pulsar monitor (#2015)
Co-authored-by: zhangshenghang <admin@hadoop.wiki>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-21 17:35:23 +08:00
tomsun28andLogic 080e904b1a [doc] home verify release doc update (#2014)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-05-20 17:12:19 +08:00
7c9b3988fb [feature] add Apache Pulsar monitor (#2013)
Co-authored-by: zhangshenghang <admin@hadoop.wiki>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-20 12:06:01 +08:00
liutianyouandtomsun28 066091dc29 [doc] add document for time expression (#2012)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-20 11:34:43 +08:00
liutianyou f9a2d9a3e0 [feature] Support time calculation expressions. (#2009) 2024-05-20 11:32:35 +08:00
Bill Lauandtomsun28 074fcd4df0 [web-app] feature: case insensitive search (#2007)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-19 08:04:31 +08:00
boatrainlszandtomsun28 22086c6c3a [doc] fix doc highlighting (#2006)
Signed-off-by: boatrainlsz <yinger521999@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-19 07:39:42 +08:00
Johnandtomsun28 7190bb3ad4 [improve] bump up eslint-plugin-jsdoc to 48.2.5 to support node 20+ (#2005)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-19 07:37:49 +08:00
YuLuoandtomsun28 d6d6d3c81e [chore] optimize code style (#2000)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-19 07:34:34 +08:00
tomsun28 2d925eba0a [bugfix] fix collector startup error classpath (#2004)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2024-05-18 14:28:50 +08:00
tomsun28andLogic a628c7d49e [improve] update release license notice and package (#2003)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-05-18 01:41:26 +08:00
YuLuoandtomsun28 dabd992e0e [improve] add common util test (#2001)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-17 23:48:18 +08:00
linDongandtomsun28 b473de40e0 [feature] add at function for wechat (#1994)
Signed-off-by: linDong <56677297@qq.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-17 23:42:19 +08:00
Jastandzhangshenghang 479b454d99 [improve] http protocol prometheus parsing optimization (#1996)
Co-authored-by: zhangshenghang <admin@hadoop.wiki>
2024-05-17 00:05:43 +08:00
John cc4e328ac6 [doc] Translate part of documentation development.md under zh-cn directory from en to zh-cn (#1995) 2024-05-16 14:34:12 +08:00
YuLuo 44a8f7b0e1 [chore] optimize manager code style (#1993)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
2024-05-16 09:04:42 +08:00
Gao Jianandtomsun28 1dbfc2bd48 [fix] Compatible with MongoDB versions earlier than 3.6 (#1988)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-15 09:17:16 +08:00
YuLuoandtomsun28 0f788b346b [chore] optimize code style (#1984)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-15 00:00:08 +08:00
056b686599 [doc] update threshold alarm doc (#1983)
Co-authored-by: zhangshenghang <admin@hadoop.wiki>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-14 23:40:06 +08:00
Zhang Yuxuanandtomsun28 4a77aafc12 [feature] Implement cascading parameter list (#1978)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-14 14:41:48 +08:00
tomsun28andLogic 280770e8e2 [doc] update contributors and update status page style (#1981)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-05-13 23:55:53 +08:00
Logic d2ac59a5d5 [doc] hertzbeat plugin doc. (#1980) 2024-05-13 23:27:31 +08:00
YuLuoand东风 c4ed7d5c31 [chore] update code style and add some comment (#1975)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: 东风 <zhangyang_2002@foxmail.com>
2024-05-13 21:21:44 +08:00
lwjxyandtomsun28 b368bb8d6f [improve] update login page and status page color (#1977)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-13 18:32:14 +08:00
Logic de0de1c99f [feature]Hertzbeat custom plugin. (#1973) 2024-05-13 18:12:28 +08:00
YuLuoand东风 a69d05a2ea [improve] optimize DateUtil and add test case (#1974)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: 东风 <zhangyang_2002@foxmail.com>
2024-05-13 17:02:25 +08:00
Zhang Yuxuan ca93a658cb [improve] Implement cascading parameter list for SNMP protocol (#1976) 2024-05-13 15:30:26 +08:00
9263727f8f [feature] add apache hugegraph monitor (#1972)
Co-authored-by: zhangshenghang <admin@hadoop.wiki>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-13 11:07:25 +08:00
YuLuoandtomsun28 39a587f0c3 [bugfix] fix AlertTemplateUtilTest test exception and update code style (#1969)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-13 11:01:49 +08:00
YuLuo aa3331eb1b [chore] update .gitignore to save .idea/icon.png (#1971) 2024-05-13 07:24:16 +08:00
crossoverJieandtomsun28 d52ae67b12 [improve][HIP] HIP-01: Implement refactoring AbstractCollect (#1966)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-13 00:05:51 +08:00
YuLuo 1a3c41fd7b [doc] update readme-cn docs (#1964)
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
2024-05-12 22:22:39 +08:00
liutianyou 9ae0d686ce [doc] add help doc for influxdb-promql and kafka-promql monitoring (#1965) 2024-05-12 16:47:28 +08:00
f1a9e83344 [fixbug] expression rule adaptation (#1963)
Co-authored-by: zhangshenghang <shenghang.zhang@avrisdigital.com>
Co-authored-by: zhangshenghang <admin@hadoop.wiki>
Co-authored-by: crossoverJie <crossoverJie@gmail.com>
Co-authored-by: yqxxgh <42080876+yqxxgh@users.noreply.github.com>
Co-authored-by: Ceilzcx <48920254+Ceilzcx@users.noreply.github.com>
Co-authored-by: aias00 <rokkki@163.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-05-11 22:22:22 +08:00
xiaoming studentandtomsun28 d34372308e [bugfix] fix the front-end popup cannot exit (#1957)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-11 21:33:57 +08:00
dc0eb6a7a0 [fixbug] Fix the problem of no data for springboot3 monitoring (#1961)
Co-authored-by: zhangshenghang <shenghang.zhang@avrisdigital.com>
Co-authored-by: zhangshenghang <admin@hadoop.wiki>
Co-authored-by: crossoverJie <crossoverJie@gmail.com>
Co-authored-by: yqxxgh <42080876+yqxxgh@users.noreply.github.com>
Co-authored-by: Ceilzcx <48920254+Ceilzcx@users.noreply.github.com>
Co-authored-by: aias00 <rokkki@163.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-11 19:03:45 +08:00
liutianyouandtomsun28 c79ada54e5 [doc] add help document for eulerOS monitoring (#1960)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-11 10:50:56 +08:00
crossoverJie 133a783bb4 [bugfix] fix ConnectionCommonCache possible npe (#1959) 2024-05-11 10:43:20 +08:00
crossoverJieandtomsun28 78ca5aebf3 [improve][HIP] HIP-01: Refactoring AbstractCollect (#1930)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-10 14:28:29 +08:00
tomsun28 95a7a13dfd [improve] add llm, server menu and update doc (#1955)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2024-05-10 14:11:51 +08:00
Logicandtomsun28 93477a5ce8 [bugfix] replace monitors to alert. (#1954)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-10 08:26:08 +08:00
69318356b2 [test] add test for NgqlCollectImpl (#1953)
Co-authored-by: Logic <zqr10159@dromara.org>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-10 08:23:03 +08:00
tomsun28andLogic d1354aa49d [improve] update build script (#1949)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-05-10 00:41:59 +08:00
48c13b8f87 [doc] update iotdb init document (#1948)
Co-authored-by: zhangshenghang <shenghang.zhang@avrisdigital.com>
Co-authored-by: zhangshenghang <admin@hadoop.wiki>
Co-authored-by: crossoverJie <crossoverJie@gmail.com>
Co-authored-by: yqxxgh <42080876+yqxxgh@users.noreply.github.com>
Co-authored-by: Ceilzcx <48920254+Ceilzcx@users.noreply.github.com>
Co-authored-by: aias00 <rokkki@163.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-09 22:59:53 +08:00
xuziyangandtomsun28 9608a31d83 [refactoring] AbstractHistoryDataStorage implement the DisposableBean (#1946)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-09 22:54:43 +08:00
xuziyangandtomsun28 9765e06cac [refactoring] Inject a single instance of the data store (#1944)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-09 22:22:24 +08:00
Zhang Yuxuan 987e9d3103 [feature] Support monitoring of OpenAI accounts (#1947) 2024-05-09 20:55:28 +08:00
铁甲小宝andLogic 6d18a8f23d [doc] add the Open Source Summer Project blog. (#1943)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-05-09 15:25:33 +08:00
tomsun28 915c92e6f8 [improve] prepare for release hertzbeat v1.6.0 (#1929) 2024-05-09 15:22:53 +08:00
tomsun28 81da126bfc [bugfix] fix alarm center tags display error (#1938) 2024-05-09 12:02:58 +08:00
crossoverJieandtomsun28 27013fd635 [test] Add test for NtpCollectImpl (#1940)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-09 08:44:26 +08:00
liutianyou 3f05dcd65d [doc] add help document for redhat monitoring and rocky linux monitoring (#1939) 2024-05-09 08:35:48 +08:00
afec4bf0e2 [feature] add apache yarn monitor (#1937)
Co-authored-by: zhangshenghang <shenghang.zhang@avrisdigital.com>
Co-authored-by: zhangshenghang <admin@hadoop.wiki>
Co-authored-by: crossoverJie <crossoverJie@gmail.com>
Co-authored-by: yqxxgh <42080876+yqxxgh@users.noreply.github.com>
Co-authored-by: Ceilzcx <48920254+Ceilzcx@users.noreply.github.com>
Co-authored-by: aias00 <rokkki@163.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-05-08 19:13:03 +08:00
tomsun28andLogic b2acd530ab [bugfix] fix ssl-cert days_remaining and npe (#1934)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-05-08 19:05:43 +08:00
xuziyang 6473d20c5b [refactor] split AbstractRealTimeDataStorage class (#1935) 2024-05-08 17:55:45 +08:00
liutianyouandtomsun28 55f3057899 [bugfix] fixed name error in monitoring template and improve NGQL protocol (#1931)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-08 16:07:16 +08:00
xuziyangandtomsun28 c951b12ec4 [refactor] split AbstractHistoryDataStorage class (#1926)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-08 09:36:46 +08:00
liutianyou 26df2c45bc [doc] add help document for freebsd monitoring (#1928) 2024-05-07 22:59:42 +08:00
tomsun28 7974d9217f bugfix collector startup error can not find JdbcClient (#1925) 2024-05-07 17:56:22 +08:00
536aa44d6d [doc] update contribution and add run-build guide (#1919)
Co-authored-by: Logic <zqr10159@dromara.org>
Co-authored-by: 铁甲小宝 <2922035952@qq.com>
2024-05-07 13:25:55 +08:00
Clownswandtomsun28 492b89fa2e [bugfix] fix TdEngine Init not found Database (#1891)
Signed-off-by: Clownsw <msmliexx1@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-07 11:47:18 +08:00
crossoverJieandtomsun28 7b492a80d6 [test] Add test for TelnetCollectImplTest (#1924)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-07 09:26:34 +08:00
liutianyou 7a95fd2165 [doc] Add documentation for nebulaGraph cluster monitoring and custom monitoring using NGQL, and clean up useless parameters (#1923) 2024-05-07 08:04:50 +08:00
946c6cd877 [doc] update hbase documentation description (#1921)
Co-authored-by: zhangshenghang <shenghang.zhang@avrisdigital.com>
Co-authored-by: zhangshenghang <admin@hadoop.wiki>
Co-authored-by: crossoverJie <crossoverJie@gmail.com>
Co-authored-by: yqxxgh <42080876+yqxxgh@users.noreply.github.com>
Co-authored-by: Ceilzcx <48920254+Ceilzcx@users.noreply.github.com>
Co-authored-by: aias00 <rokkki@163.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-06 21:39:44 +08:00
49fbf2a7c9 [featrue] add apache hdfs monitor (#1920)
Co-authored-by: zhangshenghang <shenghang.zhang@avrisdigital.com>
Co-authored-by: zhangshenghang <admin@hadoop.wiki>
Co-authored-by: crossoverJie <crossoverJie@gmail.com>
Co-authored-by: yqxxgh <42080876+yqxxgh@users.noreply.github.com>
Co-authored-by: Ceilzcx <48920254+Ceilzcx@users.noreply.github.com>
Co-authored-by: aias00 <rokkki@163.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-06 21:38:07 +08:00
crossoverJieandtomsun28 f79317827e [doc] Improve the Contribution Documentation. (#1918)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-05 23:33:08 +08:00
liutianyou d8887da144 [feature] support use ngql query metrics from nebulaGraph (#1917) 2024-05-05 22:36:43 +08:00
tomsun28and铁甲小宝 30eeed0ab3 [improve] clean up home webapp unused code (#1915)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: 铁甲小宝 <2922035952@qq.com>
2024-05-05 15:33:11 +08:00
crossoverJie 6c08ab7a44 [doc] Add HIP document and template (#1913) 2024-05-05 00:34:35 +08:00
Jin d5d149eb35 [doc] translates chinese comment to english. (#1914) 2024-05-04 20:10:55 +08:00
crossoverJie 5a6c02c571 [test] add test for WebsocketCollectImpl (#1912) 2024-05-04 16:57:22 +08:00
aias00 7bc72c637e [bugfix] fix HTTP API bug #1895 (#1909) 2024-05-04 11:07:14 +08:00
aias00andtomsun28 ff79d6d36d [bugfix] fix customized menu invalid bug #1898 (#1908)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-04 10:55:17 +08:00
Ceilzcx 388d616d06 [improve] refactor code (#1901) 2024-05-04 10:49:05 +08:00
yqxxgh 977d373c8b [improve]fix github unknown licenses found (#1907) 2024-05-03 23:15:51 +08:00
crossoverJie 48fedca436 [test] add test for UdpCollectImpl (#1906) 2024-05-03 16:28:58 +08:00
tomsun28 37083e3b6f [doc] update doc add download page and pic (#1904) 2024-05-02 17:51:22 +08:00
tomsun28 f86651aae7 [bugfix] fix can not use empty collection as query params in eclipselink (#1900)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2024-05-02 13:31:31 +08:00
Ceilzcxandtomsun28 69802634d4 [bugfix] fix when manager restart, collect register error (#1896)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-01 20:38:28 +08:00
d7c6319868 [doc] add opensuse doc (#1902)
Co-authored-by: zhangshenghang <shenghang.zhang@avrisdigital.com>
Co-authored-by: zhangshenghang <admin@hadoop.wiki>
2024-05-01 20:31:37 +08:00
tomsun28 b101cc14c8 [feature] support random jwt secret when not custom (#1897) 2024-05-01 14:01:15 +08:00
Clownswandtomsun28 8d684e964d [improve] support Time Type to Tengine Data Storage (#1890)
Signed-off-by: Clownsw <msmliexx1@gmail.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-05-01 10:57:34 +08:00
3046cc8646 [bugfix] fixed some metrics of Jexlespression not matching in Elasticsearch (#1894)
Co-authored-by: zhangshenghang <shenghang.zhang@avrisdigital.com>
Co-authored-by: zhangshenghang <admin@hadoop.wiki>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-30 22:41:06 +08:00
crossoverJieandtomsun28 95905c8dcb [improve] missing a generic (#1889)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-30 21:50:30 +08:00
a0ac402e8d [doc] add almalinux documentation (#1892)
Co-authored-by: zhangshenghang <shenghang.zhang@avrisdigital.com>
Co-authored-by: zhangshenghang <admin@hadoop.wiki>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-04-30 16:07:07 +08:00
feiyang li 841220675a [doc] add help doc for flink monitoring (#1893) 2024-04-30 16:04:41 +08:00
tomsun28andLogic 8e6b788e41 bugfix statistical metrics data matching fails (#1884)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-04-30 10:23:03 +08:00
xuziyangandtomsun28 a6ebf9010a [refactor] StoreProperties is no longer useful, delete it (#1887)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-30 09:56:10 +08:00
Zhang Yuxuan c6a995a31a [doc] I18n for monitoring template yml metrics (#1888)
Signed-off-by: Zhang Yuxuan <1373529784@qq.com>
2024-04-29 21:33:02 +08:00
Logicandtomsun28 096f963b43 [bugfix][doc] add kafka sidebar. (#1883)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-29 12:43:49 +08:00
handyandtomsun28 7210f6823d [refactor] eliminate unnecessary unboxing and generics (#1882)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-29 12:39:52 +08:00
crossoverJie 5cdc0d55f8 [improve] Refactor common cache code (#1881) 2024-04-29 00:45:45 +08:00
xuziyangandtomsun28 5db6daeb3d [feature] support the VictoriaMetrics cluster (#1880)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-28 22:44:34 +08:00
Logic f1686df191 [bugfix] fix top10 process command. (#1876) 2024-04-28 22:35:02 +08:00
crossoverJieandLogic 13129faeff [improve] Use java.lang.AutoCloseable instead of CacheCloseable (#1879)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-04-28 16:48:28 +08:00
xuziyangandLogic 6cf38cfaf9 [improve] Delete the timestamp field in the class MetricFamily.Metric (#1878)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-04-28 16:43:14 +08:00
tomsun28 a10786cff8 [featurn] support flyway database migration (#1875) 2024-04-28 15:56:47 +08:00
liutianyouand铁甲小宝 6111adb9c5 [doc] update help document (#1861)
Co-authored-by: 铁甲小宝 <2922035952@qq.com>
2024-04-28 13:50:08 +08:00
tomsun28andLogic 3900143f97 [improve] add website apache incubator footer (#1860)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Signed-off-by: Logic <zqr10159@dromara.org>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-04-28 11:28:40 +08:00
a14aeb2265 [bugfix] centos top10 shows missing one (#1870)
Co-authored-by: zhangshenghang <shenghang.zhang@avrisdigital.com>
Co-authored-by: zhangshenghang <admin@hadoop.wiki>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-28 09:14:51 +08:00
llp2333andtomsun28 5fdc6557d6 [bugfix] fix debian monitoring template issue about process monitoring (#1868)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-28 09:03:29 +08:00
Gao Jianandtomsun28 d3eff79a90 [feature] Support Redfish protocol to monitoring server (#1867)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-28 08:47:53 +08:00
crossoverJie fd56652ffb [improve] Imporve checkstyle of test code. (#1864) 2024-04-28 08:42:58 +08:00
liutianyou 48e35bee19 [doc] add help document for rocketmq (#1874) 2024-04-27 21:42:22 +08:00
铁甲小宝andtomsun28 d3209b645f [feature] add influxdb metrics monitoring (#1730)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-27 15:16:48 +08:00
c4aee27f1c [bugfix] jpa data save logic repair (#1863)
Co-authored-by: zhangshenghang <shenghang.zhang@avrisdigital.com>
Co-authored-by: zhangshenghang <admin@hadoop.wiki>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-27 13:53:34 +08:00
tomsun28 6c35f57b2e [improve] use apache jexl replace of aviator (#1859) 2024-04-27 12:16:38 +08:00
crossoverJieandtomsun28 025a7d9259 [test] add test for FtpCollectImpl (#1856)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-26 23:29:53 +08:00
72ff8c34ac [feature] Add Linux process monitoring (#1857)
Co-authored-by: zhangshenghang <shenghang.zhang@avrisdigital.com>
Co-authored-by: zhangshenghang <admin@hadoop.wiki>
Co-authored-by: 铁甲小宝 <2922035952@qq.com>
2024-04-26 21:12:01 +08:00
liutianyouand铁甲小宝 1905d83dbf [doc] fix error and add help document for prometheus task (#1852)
Co-authored-by: 铁甲小宝 <2922035952@qq.com>
2024-04-26 21:07:38 +08:00
Hyeon Sung 9545c8de11 [doc] translates chinese comment to english. (#1853) 2024-04-26 20:41:50 +08:00
8ffe0dae5c [cleanup] delete the corresponding chinese comments (#1847)
Signed-off-by: 苦草 <34374227+hudongdong129@users.noreply.github.com>
Co-authored-by: hudongdong <hudongdong668@hellobike.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-26 09:00:52 +08:00
7951e1da0f [bigfix]Fix Debian system Top10 monitoring bug (#1846)
Co-authored-by: zhangshenghang <shenghang.zhang@avrisdigital.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-25 22:58:55 +08:00
4da1110ca0 [bugfix] modify the command in the mongodb monitoring template (#1844)
Co-authored-by: liutianyou <tianyou@emial.cn>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-25 20:40:20 +08:00
49db98ade4 [refactor] trans and use assert (#1841)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: 铁甲小宝 <2922035952@qq.com>
2024-04-25 15:50:23 +08:00
xuziyangandtomsun28 d4bc3f93c6 [fix] fix the wrong comment (#1843)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-25 15:42:36 +08:00
crossoverJieandtomsun28 997c958ae0 [test] add test for HttpsdImpl (#1840)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-25 15:03:32 +08:00
xuziyangandtomsun28 41de1b9b5d [refactor] split the WarehouseProperties class (#1830)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-25 14:54:38 +08:00
LiuTianyouandtomsun28 c0c9ff0792 [improve] optimize websocket monitor (#1838)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-25 14:47:36 +08:00
4a3e27382c [feature] add Apache Hbase RegionServer monitoring (#1833)
Co-authored-by: zhangshenghang <shenghang.zhang@avrisdigital.com>
Co-authored-by: zhangshenghang <admin@hadoop.wiki>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-25 14:30:39 +08:00
Jastandzhangshenghang 2fa3b5aed0 [doc]Doc add debian system (#1842)
Co-authored-by: zhangshenghang <shenghang.zhang@avrisdigital.com>
2024-04-25 14:10:21 +08:00
P.Pandtomsun28 381ad50b1d [collector] fix: inverts the compareTo sort of MetricsCollect run queue (#1837)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-24 23:54:31 +08:00
690eade95d [doc] add help document for mongodb monitoring (#1834)
Co-authored-by: liutianyou <tianyou@emial.cn>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-24 23:19:51 +08:00
Hyeon Sungandtomsun28 54c163abfb [refactor] code simplification, structure changes and translation (#1827)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-24 23:12:06 +08:00
Zhang Yuxuan 63562421a5 [docs] Optimize: add help docs for UDP port & Springboot3 help doc (#1832) 2024-04-24 21:08:33 +08:00
Jastandzhangshenghang 8c6ed728f2 [doc]Add and modify Doris FE Chinese and English documentation (#1828)
Co-authored-by: zhangshenghang <shenghang.zhang@avrisdigital.com>
2024-04-24 15:03:36 +08:00
Hyeon SungandLogic aa4d28bf34 [Refactor] Preventing Unnecessary Object Creation and Using Utility Methods (#1818)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-04-24 00:36:17 +08:00
LiuTianyouandtomsun28 024152ec32 [bugfix] dns monitoring template add query class parameter (#1825)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-24 00:09:28 +08:00
crossoverJie ab52a49723 [improve] add whitespace checkstyle (#1824) 2024-04-23 23:52:29 +08:00
fed2f538b4 [improve] use eclipselink orm replace of hibernate orm (#1801)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-04-23 22:33:44 +08:00
AlanandLogic 997bbe39c0 [doc] Add help document for tidb and nacos monitoring (#1823)
Signed-off-by: Alan <m134679102365478@163.com>
Signed-off-by: Logic <zqr10159@dromara.org>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-04-23 21:24:42 +08:00
7ae4650b94 [doc] resolve code conflicts and coverage caused by pr(#1813) merge (#1821)
Co-authored-by: liutianyou <tianyou@emial.cn>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-04-23 21:10:47 +08:00
Jastandzhangshenghang cbe38c7929 [feature] add monitoring for Hbase Master (#1820)
Co-authored-by: zhangshenghang <shenghang.zhang@avrisdigital.com>
2024-04-23 19:25:43 +08:00
Hyeon SungandLogic 264d24ebdc Remove and translate chinese to english in code (#1816)
Signed-off-by: Hyeon Sung <gorae930301@gmail.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-04-23 14:49:54 +08:00
Logic ae65e7594e [remove][improve] mail config (#1819) 2024-04-23 13:53:07 +08:00
RickandLogic df9ab107c7 chore: upgrade the api-testing (e2e) to v0.0.16 (#1817)
Signed-off-by: Rick <1450685+LinuxSuRen@users.noreply.github.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-04-23 10:14:43 +08:00
Alan 54faa02380 [doc] add help documentation for huawei switch monitoring (#1813)
Signed-off-by: Alan <m134679102365478@163.com>
2024-04-23 10:07:32 +08:00
LiuTianyouandLogic 8755c11d98 [doc] Add help document for elasticsearch monitoring and ftp monitoring (#1815)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-04-22 23:49:06 +08:00
Hyeon Sung c40405cd58 Comparing N objects for null with Assert.noNullElements(). (#1814) 2024-04-22 23:45:45 +08:00
crossoverJieand淞筱 d88851d7ea [improve] Fix typo ReqStatusResponse (#1811)
Signed-off-by: 淞筱 <105542329+a-little-fool@users.noreply.github.com>
Co-authored-by: 淞筱 <105542329+a-little-fool@users.noreply.github.com>
2024-04-22 21:12:17 +08:00
crossoverJie b3cb1b074c [test] add RedisClusterCollectImplTest (#1789) 2024-04-22 17:26:59 +08:00
tomsun28and铁甲小宝 b2f94ec1e2 [website] update team page (#1803)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: 铁甲小宝 <2922035952@qq.com>
2024-04-22 13:36:18 +08:00
crossoverJieandtomsun28 8e2ebe3034 [test] add nginx collect test (#1809)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-22 11:45:57 +08:00
e7ec15f68a [refactor] upgrade syntax to jdk17 instanceof & switch (#1807)
Co-authored-by: Logic <zqr10159@dromara.org>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-22 11:36:21 +08:00
xuziyangandtomsun28 f1ed92a525 [refactor] change the warehouse properties the type to record (#1806)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-22 11:28:04 +08:00
Hyeon Sung 16cec10fa3 [improve] preventing NPE (#1808) 2024-04-22 10:32:44 +08:00
42fff48e2a [doc] add help document for dns monitoring (#1804)
Co-authored-by: LiuTianyou <641108368@qq.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-21 21:51:47 +08:00
crossoverJie 6f942bc601 [feature] Improve the import checkstyle (#1802) 2024-04-21 16:44:23 +08:00
Keshav Carpenterandtomsun28 3eb1e19998 [doc] add team page in website (#1800)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-21 11:46:13 +08:00
栗磊andtomsun28 5e155e0d45 [improve] when multiple lines are returned, each alarm is triggered instead of only the first alarm (#1797)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-21 11:18:53 +08:00
Logicandtomsun28 0d17a47160 [improve] add external lib folder to store mysql and oracle driver. (#1783)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-21 10:48:40 +08:00
YxYLandtomsun28 38fb151775 [feature] update-checkstyle limit the java file header (#1799)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-20 23:52:15 +08:00
LiuTianyouandLiuTianyou 12e45a703b [doc] add help documentation for clickhouse monitoring (#1798)
Co-authored-by: LiuTianyou <641108368@qq.com>
2024-04-20 23:49:46 +08:00
铁甲小宝andtomsun28 8ce4731393 [bugfix] fix snmp template unit conversion problem (#1796)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-20 12:09:27 +08:00
xuziyang e7c627bc41 [refactor] database-related properties class, type changed to record (#1786) 2024-04-20 11:56:48 +08:00
tomsun28and淞筱 0d6002db37 [doc] translate alerter moudle code chinese to english (#1765)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: 淞筱 <105542329+a-little-fool@users.noreply.github.com>
2024-04-20 11:50:03 +08:00
tomorrowshipyltmandLogic 125c30d680 '[docs]bugfix: display syntax error of ipmi protocol' (#1793)
Signed-off-by: tomorrowshipyltm <61336903+tomorrowshipyltm@users.noreply.github.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-04-20 11:16:36 +08:00
handyandtomsun28 ac2c4c0f37 [refactor] add override annotation (#1782)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-20 10:50:10 +08:00
crossoverJie f7fb2356c7 [test] Add RedisSingleCollectImplTest (#1784) 2024-04-19 23:35:36 +08:00
Logic f9d47797b6 [improve] add frontend license. (#1776) 2024-04-18 18:08:03 +08:00
lwqzzandLogic d209bd3277 Added the function of sending SMS messages through Alibaba Cloud. (#1768)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-04-18 17:20:39 +08:00
Manan PujaraandLogic 7d5082f060 remove and translate chinese to english in collector,script,push,remoting and manager module (#1774)
Signed-off-by: Manan Pujara <104253184+MananPoojara@users.noreply.github.com>
Signed-off-by: Logic <zqr10159@dromara.org>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-04-18 16:02:05 +08:00
Hyeon SungandLogic 4627fb5a8b Replace deprecated methods with builder pattern for RedisURI construction (#1772)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-04-18 15:51:20 +08:00
xuziyangandLogic 79017f3634 [doc] remove and translate chinese to english in warehous (#1773)
Co-authored-by: Logic <zqr10159@dromara.org>
2024-04-18 15:35:27 +08:00
Hyeon Sungandtomsun28 7ca110e7b7 [improve] remove unnecessary if-else statement. (#1770)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-18 11:08:10 +08:00
风如歌andtomsun28 d6ce092cd4 [doc] translate common moudle code chinese to english (#1766)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-18 10:20:55 +08:00
tomsun28andLogic ecae143b2a [improve] update new hertzbeat brand logo, update doc (#1761)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-04-17 21:23:02 +08:00
tomsun28 9ec4e55e70 [improve] create disclaimer file, add incubating in describe (#1764)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2024-04-17 20:07:09 +08:00
Hyeon Sungand铁甲小宝 7fe6d2d798 [refactor] method improvement rationale (#1757)
Signed-off-by: Hyeon Sung <gorae930301@gmail.com>
Co-authored-by: 铁甲小宝 <2922035952@qq.com>
2024-04-17 17:15:14 +08:00
PeixyJ ea7fd2b268 fix : ingress tls inoperative (#1760) 2024-04-17 16:08:02 +08:00
crossoverJie 03515dee54 [doc] change e2e path (#1758)
Signed-off-by: crossoverJie <crossoverJie@gmail.com>
2024-04-17 12:22:16 +08:00
淞筱andtomsun28 bb55cafb2c [improve] home add apache info (#1740)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-16 18:02:09 +08:00
tomsun28 c4d1512665 [improve] update asf config set required status checks context (#1751) 2024-04-15 22:24:29 +08:00
tomsun28 8772e709ba [improve] auto label when pr, update asf config (#1749) 2024-04-15 19:58:27 +08:00
Keshav Carpenterandfm-keshavcarpenter b3a869d8d7 [imporve] remove unlicensed dependency 'wolfy87 eventemitter' (#1745)
Co-authored-by: fm-keshavcarpenter <keshav.carpenter@flexmoney.in>
2024-04-15 18:11:17 +08:00
makechoicenowandzhouge e06350809a [bugfix] fix statuspage index exception (#1747)
Co-authored-by: zhouge <zhouge@zhougedeMacBook-Pro.local>
2024-04-15 18:10:10 +08:00
Gao Jian 778666c504 [Improve] run hertzbeat in docker compose support dependen service condition (#1748) 2024-04-15 17:52:44 +08:00
铁甲小宝and花城 37869aa547 Back-end dependency upgrade (#1743)
Signed-off-by: 花城 <71161318+wang1027-wqh@users.noreply.github.com>
Co-authored-by: 花城 <71161318+wang1027-wqh@users.noreply.github.com>
2024-04-15 16:51:15 +08:00
花城and花城 58d3efa572 Backend LICENSE Initialize (#1744)
Co-authored-by: 花城 <wqh382130@fliggy.com>
2024-04-15 15:55:51 +08:00
Logic 3c1a5905ad [improve] add lisence. (#1746) 2024-04-15 13:51:27 +08:00
Logic 97f27b4cbd [improve] support multiple receivers. (#1731) 2024-04-14 20:09:32 +08:00
tomsun28 828e46c200 [improve] initial doc clean up (#1741) 2024-04-14 14:56:42 +08:00
mikiandcttq-iot 37a2323141 [fixed] fixed click collector online offline button error (#1734)
Co-authored-by: cttq-iot <111329082+cttq-iot@users.noreply.github.com>
2024-04-14 08:36:26 +08:00
Logic bdc069944f [doc]Update star chart (#1737)
Signed-off-by: Logic <zqr10159@dromara.org>
2024-04-13 00:19:35 +08:00
tomsun28 4f7d2ae591 update asf branch protected check (#1738)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2024-04-13 00:16:49 +08:00
allcontributors[bot] 110b4b7ee9 [doc] add WinterKi1ler as a contributor for code (#1736)
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2024-04-12 16:21:42 +08:00
WinterKi1lerandtomsun28 2fa668833a fix sec: upgrade com.h2database:h2 to (#1718)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-12 16:10:30 +08:00
handyandtomsun28 d7f9093d8e update manager and collector logback config(#1704) (#1723)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-10 12:07:08 +08:00
tomsun28 72f968d580 [improve] initial license clean up (#1725) 2024-04-10 10:02:20 +08:00
vinciandtomsun28 48e2ac0522 [Improve] migrate to apache(#1724)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-04-09 22:36:54 +08:00
tomsun28andLogic f8190c479a update home website doc (#1712)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-04-06 18:05:14 +08:00
tomsun28andLogic c7a82e1a80 support custom main menus in monitor template (#1703)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-04-02 19:00:22 +08:00
tomsun28andLogic f33226fda6 bugfix npe monitor jobid may be null (#1701)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-04-01 22:03:54 +08:00
tomsun28 eda782ff46 fix status page logo overflow (#1700) 2024-04-01 14:33:11 +08:00
tomsun28and铁甲小宝 ae06022983 monitor center add search type modal (#1699)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: 铁甲小宝 <85919258+TJxiaobao@users.noreply.github.com>
2024-03-31 23:11:30 +08:00
Xin 066fb9eada [bugfix] fix bug where reopening pop-up window still retained previously edited data after closing. (#1698) 2024-03-31 10:05:26 +08:00
tomsun28andLogic 2f74dfe52e bugfix old data decode error when use new common-secret (#1696)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: Logic <zqr10159@dromara.org>
2024-03-29 19:54:29 +08:00
东风 5db2674215 mongodb monitoring support custom connection timeout param (#1697) 2024-03-29 18:01:39 +08:00
allcontributors[bot]andtomsun28 4852a572b3 [doc] add LiuTianyou as a contributor for code (#1687)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-03-26 15:40:49 +08:00
c18becfa1a [bugfix]fix the issue of add redis cluster node test error report(#1601) (#1684)
Co-authored-by: LiuTianyou <641108368@qq.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2024-03-26 15:36:44 +08:00
tomsun28and东风 96988776fa support config common aes secret (#1683)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: 东风 <zhangyang_2002@foxmail.com>
2024-03-26 10:29:07 +08:00
tomsun28 1d11a97d28 bugfix can not find mysql dependency when startup (#1686)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2024-03-25 17:59:24 +08:00
tomsun28 829696d141 update webapp menu layout and doc (#1682)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2024-03-25 10:09:22 +08:00
3880 changed files with 304500 additions and 148197 deletions
+703 -3
View File
@@ -1,13 +1,12 @@
{
"projectName": "hertzbeat",
"projectOwner": "dromara",
"projectOwner": "apache",
"repoType": "github",
"repoHost": "https://github.com",
"files": [
"README.md",
"README_CN.md",
"home/docs/others/developer.md",
"home/i18n/zh-cn/docusaurus-plugin-content-docs/current/others/developer.md"
"home/src/pages/team/index.jsx"
],
"imageSize": 100,
"commit": true,
@@ -1598,6 +1597,707 @@
"contributions": [
"code"
]
},
{
"login": "LiuTianyou",
"name": "LiuTianyou",
"avatar_url": "https://avatars.githubusercontent.com/u/30208283?v=4",
"profile": "https://github.com/LiuTianyou",
"contributions": [
"code",
"doc"
]
},
{
"login": "WinterKi1ler",
"name": "WinterKi1ler",
"avatar_url": "https://avatars.githubusercontent.com/u/160592092?v=4",
"profile": "https://github.com/WinterKi1ler",
"contributions": [
"code"
]
},
{
"login": "miki-hmt",
"name": "miki",
"avatar_url": "https://avatars.githubusercontent.com/u/45377370?v=4",
"profile": "http://sharehoo.cn/",
"contributions": [
"code"
]
},
{
"login": "alpha951",
"name": "Keshav Carpenter",
"avatar_url": "https://avatars.githubusercontent.com/u/85513042?v=4",
"profile": "https://codeflex.substack.com/",
"contributions": [
"code",
"doc"
]
},
{
"login": "makechoicenow",
"name": "makechoicenow",
"avatar_url": "https://avatars.githubusercontent.com/u/9911918?v=4",
"profile": "https://github.com/makechoicenow",
"contributions": [
"code"
]
},
{
"login": "gjjjj0101",
"name": "Gao Jian",
"avatar_url": "https://avatars.githubusercontent.com/u/71874373?v=4",
"profile": "https://github.com/gjjjj0101",
"contributions": [
"code",
"design",
"test"
]
},
{
"login": "dukbong",
"name": "Hyeon Sung",
"avatar_url": "https://avatars.githubusercontent.com/u/37864182?v=4",
"profile": "https://jangto.tistory.com/",
"contributions": [
"code"
]
},
{
"login": "crossoverJie",
"name": "crossoverJie",
"avatar_url": "https://avatars.githubusercontent.com/u/15684156?v=4",
"profile": "https://crossoverjie.top/",
"contributions": [
"code",
"doc"
]
},
{
"login": "PeixyJ",
"name": "PeixyJ",
"avatar_url": "https://avatars.githubusercontent.com/u/45998593?v=4",
"profile": "https://github.com/PeixyJ",
"contributions": [
"code"
]
},
{
"login": "Hi-Mr-Wind",
"name": "风如歌",
"avatar_url": "https://avatars.githubusercontent.com/u/85803831?v=4",
"profile": "https://github.com/Hi-Mr-Wind",
"contributions": [
"code"
]
},
{
"login": "MananPoojara",
"name": "Manan Pujara",
"avatar_url": "https://avatars.githubusercontent.com/u/104253184?v=4",
"profile": "https://github.com/MananPoojara",
"contributions": [
"code"
]
},
{
"login": "xuziyang",
"name": "xuziyang",
"avatar_url": "https://avatars.githubusercontent.com/u/8465969?v=4",
"profile": "https://github.com/xuziyang",
"contributions": [
"code"
]
},
{
"login": "lwqzz",
"name": "lwqzz",
"avatar_url": "https://avatars.githubusercontent.com/u/62584513?v=4",
"profile": "https://github.com/lwqzz",
"contributions": [
"code"
]
},
{
"login": "YxYL6125",
"name": "YxYL",
"avatar_url": "https://avatars.githubusercontent.com/u/91076160?v=4",
"profile": "https://github.com/YxYL6125",
"contributions": [
"code"
]
},
{
"login": "tomorrowshipyltm",
"name": "tomorrowshipyltm",
"avatar_url": "https://avatars.githubusercontent.com/u/61336903?v=4",
"profile": "https://github.com/tomorrowshipyltm",
"contributions": [
"doc"
]
},
{
"login": "15613060203",
"name": "栗磊",
"avatar_url": "https://avatars.githubusercontent.com/u/41351615?v=4",
"profile": "https://github.com/15613060203",
"contributions": [
"code"
]
},
{
"login": "Alanxtl",
"name": "Alan",
"avatar_url": "https://avatars.githubusercontent.com/u/25652981?v=4",
"profile": "https://github.com/Alanxtl",
"contributions": [
"doc"
]
},
{
"login": "zhangshenghang",
"name": "Jast",
"avatar_url": "https://avatars.githubusercontent.com/u/29418975?v=4",
"profile": "http://www.hadoop.wiki/",
"contributions": [
"code"
]
},
{
"login": "zuobiao-zhou",
"name": "Zhang Yuxuan",
"avatar_url": "https://avatars.githubusercontent.com/u/61108539?v=4",
"profile": "https://github.com/zuobiao-zhou",
"contributions": [
"code"
]
},
{
"login": "Pzz-2021",
"name": "P.P.",
"avatar_url": "https://avatars.githubusercontent.com/u/118056735?v=4",
"profile": "https://github.com/Pzz-2021",
"contributions": [
"code"
]
},
{
"login": "LLP2333",
"name": "llp2333",
"avatar_url": "https://avatars.githubusercontent.com/u/61670545?v=4",
"profile": "https://github.com/LLP2333",
"contributions": [
"code"
]
},
{
"login": "HeartLinked",
"name": "feiyang li",
"avatar_url": "https://avatars.githubusercontent.com/u/78212101?v=4",
"profile": "https://github.com/HeartLinked",
"contributions": [
"doc"
]
},
{
"login": "Aias00",
"name": "aias00",
"avatar_url": "https://avatars.githubusercontent.com/u/25810623?v=4",
"profile": "https://github.com/Aias00",
"contributions": [
"code"
]
},
{
"login": "westboy",
"name": "Jin",
"avatar_url": "https://avatars.githubusercontent.com/u/6385565?v=4",
"profile": "https://github.com/westboy",
"contributions": [
"doc"
]
},
{
"login": "yuluo-yx",
"name": "YuLuo",
"avatar_url": "https://avatars.githubusercontent.com/u/77964041?v=4",
"profile": "https://blog.csdn.net/qq_52397471",
"contributions": [
"code"
]
},
{
"login": "Yanshuming1",
"name": "linDong",
"avatar_url": "https://avatars.githubusercontent.com/u/118667222?v=4",
"profile": "https://github.com/Yanshuming1",
"contributions": [
"code"
]
},
{
"login": "lwjxy",
"name": "lwjxy",
"avatar_url": "https://avatars.githubusercontent.com/u/52726400?v=4",
"profile": "https://github.com/lwjxy",
"contributions": [
"code"
]
},
{
"login": "Thespica",
"name": "John",
"avatar_url": "https://avatars.githubusercontent.com/u/119573640?v=4",
"profile": "https://thespica.github.io/",
"contributions": [
"code",
"doc"
]
},
{
"login": "boatrainlsz",
"name": "boatrainlsz",
"avatar_url": "https://avatars.githubusercontent.com/u/18243785?v=4",
"profile": "https://github.com/boatrainlsz",
"contributions": [
"doc"
]
},
{
"login": "JavaProgrammerLB",
"name": "Bill Lau",
"avatar_url": "https://avatars.githubusercontent.com/u/3973419?v=4",
"profile": "https://www.yitianyigexiangfa.com/",
"contributions": [
"code"
]
},
{
"login": "lw-yang",
"name": "lwyang",
"avatar_url": "https://avatars.githubusercontent.com/u/23456873?v=4",
"profile": "https://github.com/lw-yang",
"contributions": [
"doc"
]
},
{
"login": "xfl12345",
"name": "xfl12345",
"avatar_url": "https://avatars.githubusercontent.com/u/17960863?v=4",
"profile": "https://github.com/xfl12345",
"contributions": [
"doc"
]
},
{
"login": "yykaue",
"name": "Limbo",
"avatar_url": "https://avatars.githubusercontent.com/u/22905143?v=4",
"profile": "https://github.com/yykaue",
"contributions": [
"code"
]
},
{
"login": "irenhongyan",
"name": "哈哈哈哈哈哈哈哈哈",
"avatar_url": "https://avatars.githubusercontent.com/u/53438321?v=4",
"profile": "https://github.com/irenhongyan",
"contributions": [
"code"
]
},
{
"login": "ileonli",
"name": "Leon Li",
"avatar_url": "https://avatars.githubusercontent.com/u/45332412?v=4",
"profile": "https://github.com/ileonli",
"contributions": [
"code"
]
},
{
"login": "killme2008",
"name": "dennis zhuang",
"avatar_url": "https://avatars.githubusercontent.com/u/14142?v=4",
"profile": "http://fnil.net/",
"contributions": [
"code"
]
},
{
"login": "kerwin612",
"name": "Kerwin Bryant",
"avatar_url": "https://avatars.githubusercontent.com/u/3371163?v=4",
"profile": "https://github.com/kerwin612",
"contributions": [
"code",
"design"
]
},
{
"login": "ShineDevelopment",
"name": "daixianglong",
"avatar_url": "https://avatars.githubusercontent.com/u/59306780?v=4",
"profile": "https://github.com/ShineDevelopment",
"contributions": [
"doc"
]
},
{
"login": "mchgood",
"name": "mchgood",
"avatar_url": "https://avatars.githubusercontent.com/u/38482005?v=4",
"profile": "https://github.com/mchgood",
"contributions": [
"doc"
]
},
{
"login": "pwallk",
"name": "kangli",
"avatar_url": "https://avatars.githubusercontent.com/u/69385076?v=4",
"profile": "https://github.com/pwallk",
"contributions": [
"code"
]
},
{
"login": "cdphantom",
"name": "cdphantom",
"avatar_url": "https://avatars.githubusercontent.com/u/12674795?v=4",
"profile": "https://github.com/cdphantom",
"contributions": [
"code"
]
},
{
"login": "asd108908382",
"name": "jiawei.guo",
"avatar_url": "https://avatars.githubusercontent.com/u/77717999?v=4",
"profile": "https://github.com/asd108908382",
"contributions": [
"code"
]
},
{
"login": "QBH-insist",
"name": "QBH-insist",
"avatar_url": "https://avatars.githubusercontent.com/u/39401478?v=4",
"profile": "https://github.com/QBH-insist",
"contributions": [
"code"
]
},
{
"login": "jiangsh-ui",
"name": "jiangsh",
"avatar_url": "https://avatars.githubusercontent.com/u/86990361?v=4",
"profile": "https://github.com/jiangsh-ui",
"contributions": [
"code"
]
},
{
"login": "keaifafafa",
"name": "Keaifa",
"avatar_url": "https://avatars.githubusercontent.com/u/83876361?v=4",
"profile": "https://github.com/keaifafafa",
"contributions": [
"code"
]
},
{
"login": "loong95",
"name": "Loong",
"avatar_url": "https://avatars.githubusercontent.com/u/16333958?v=4",
"profile": "https://github.com/loong95",
"contributions": [
"code"
]
},
{
"login": "ceekay47",
"name": "Chandrakant Vankayalapati",
"avatar_url": "https://avatars.githubusercontent.com/u/104664857?v=4",
"profile": "https://github.com/ceekay47",
"contributions": [
"code"
]
},
{
"login": "MRgenial",
"name": "b_mountain",
"avatar_url": "https://avatars.githubusercontent.com/u/49973336?v=4",
"profile": "https://github.com/MRgenial",
"contributions": [
"code"
]
},
{
"login": "TemirlanBasitov",
"name": "TemirlanBasitov",
"avatar_url": "https://avatars.githubusercontent.com/u/57500808?v=4",
"profile": "https://github.com/TemirlanBasitov",
"contributions": [
"code"
]
},
{
"login": "wyfvsfy",
"name": "wyfvsfy",
"avatar_url": "https://avatars.githubusercontent.com/u/11973517?v=4",
"profile": "https://github.com/wyfvsfy",
"contributions": [
"doc"
]
},
{
"login": "sherry-peng2333",
"name": "sherry-peng2333",
"avatar_url": "https://avatars.githubusercontent.com/u/70619577?v=4",
"profile": "https://github.com/sherry-peng2333",
"contributions": [
"code"
]
},
{
"login": "lixiaobaivv",
"name": "Yzzz",
"avatar_url": "https://avatars.githubusercontent.com/u/39290771?v=4",
"profile": "https://github.com/lixiaobaivv",
"contributions": [
"code"
]
},
{
"login": "pruidong",
"name": "puruidong",
"avatar_url": "https://avatars.githubusercontent.com/u/13309008?v=4",
"profile": "http://www.bckf.cn/",
"contributions": [
"doc"
]
},
{
"login": "shinestare",
"name": "shinestare",
"avatar_url": "https://avatars.githubusercontent.com/u/13570619?v=4",
"profile": "https://github.com/shinestare",
"contributions": [
"code"
]
},
{
"login": "po-168",
"name": "po-168",
"avatar_url": "https://avatars.githubusercontent.com/u/185745593?v=4",
"profile": "https://github.com/po-168",
"contributions": [
"code"
]
},
{
"login": "All-The-Best-for",
"name": "wbs99",
"avatar_url": "https://avatars.githubusercontent.com/u/76414672?v=4",
"profile": "https://github.com/All-The-Best-for",
"contributions": [
"code"
]
},
{
"login": "starryCoder",
"name": "starryCoder",
"avatar_url": "https://avatars.githubusercontent.com/u/46510059?v=4",
"profile": "https://github.com/starryCoder",
"contributions": [
"code"
]
},
{
"login": "hasimmollah",
"name": "hasimmollah",
"avatar_url": "https://avatars.githubusercontent.com/u/32538599?v=4",
"profile": "https://github.com/hasimmollah",
"contributions": [
"code"
]
},
{
"login": "ayu-v0",
"name": "Ayu",
"avatar_url": "https://avatars.githubusercontent.com/u/127600988?v=4",
"profile": "https://github.com/ayu-v0",
"contributions": [
"code"
]
},
{
"login": "Rancho-7",
"name": "Nick Guo",
"avatar_url": "https://avatars.githubusercontent.com/u/59016860?v=4",
"profile": "https://github.com/Rancho-7",
"contributions": [
"doc"
]
},
{
"login": "doveLin0818",
"name": "doveLin",
"avatar_url": "https://avatars.githubusercontent.com/u/190927907?v=4",
"profile": "https://github.com/doveLin0818",
"contributions": [
"code"
]
},
{
"login": "yunfan24",
"name": "yunfan24",
"avatar_url": "https://avatars.githubusercontent.com/u/91836599?v=4",
"profile": "https://zzrl.cc/",
"contributions": [
"code"
]
},
{
"login": "lctking",
"name": "nullwli",
"avatar_url": "https://avatars.githubusercontent.com/u/168249998?v=4",
"profile": "https://github.com/lctking",
"contributions": [
"code"
]
},
{
"login": "simonsigre",
"name": "Simon Sigré",
"avatar_url": "https://avatars.githubusercontent.com/u/14932913?v=4",
"profile": "https://simonsigre.com/",
"contributions": [
"doc"
]
},
{
"login": "ponfee",
"name": "ponfee",
"avatar_url": "https://avatars.githubusercontent.com/u/46117331?v=4",
"profile": "http://www.ponfee.cn/",
"contributions": [
"code"
]
},
{
"login": "Vedant7789",
"name": "Vedant7789",
"avatar_url": "https://avatars.githubusercontent.com/u/147625492?v=4",
"profile": "https://github.com/Vedant7789",
"contributions": [
"code"
]
},
{
"login": "Craaaaazy77",
"name": "Craaaaazy77",
"avatar_url": "https://avatars.githubusercontent.com/u/23025522?v=4",
"profile": "https://github.com/Craaaaazy77",
"contributions": [
"doc"
]
},
{
"login": "Suvrat1629",
"name": "Suvrat1629",
"avatar_url": "https://avatars.githubusercontent.com/u/140749446?v=4",
"profile": "https://github.com/Suvrat1629",
"contributions": [
"code"
]
},
{
"login": "ghyghoo8",
"name": "ghy",
"avatar_url": "https://avatars.githubusercontent.com/u/363129?v=4",
"profile": "http://ghyghoo8.github.io/",
"contributions": [
"code"
]
},
{
"login": "helei1030",
"name": "helei1030",
"avatar_url": "https://avatars.githubusercontent.com/u/11839080?v=4",
"profile": "https://github.com/helei1030",
"contributions": [
"doc"
]
},
{
"login": "pjfanning",
"name": "PJ Fanning",
"avatar_url": "https://avatars.githubusercontent.com/u/11783444?v=4",
"profile": "https://medium.com/@pjfanning",
"contributions": [
"code"
]
},
{
"login": "MonsterChenzhuo",
"name": "monster",
"avatar_url": "https://avatars.githubusercontent.com/u/60029759?v=4",
"profile": "https://github.com/MonsterChenzhuo",
"contributions": [
"code"
]
},
{
"login": "MasamiYui",
"name": "Sherlock Yin",
"avatar_url": "https://avatars.githubusercontent.com/u/22274133?v=4",
"profile": "https://github.com/MasamiYui",
"contributions": [
"code"
]
},
{
"login": "wanhao23",
"name": "wanhao",
"avatar_url": "https://avatars.githubusercontent.com/u/29560961?v=4",
"profile": "https://github.com/wanhao23",
"contributions": [
"code",
"doc"
]
},
{
"login": "jonasHanhan",
"name": "jonasHanhan",
"avatar_url": "https://avatars.githubusercontent.com/u/130035609?v=4",
"profile": "https://github.com/jonasHanhan",
"contributions": [
"code"
]
},
{
"login": "NikhilMurugesan",
"name": "NikhilMurugesan",
"avatar_url": "https://avatars.githubusercontent.com/u/49281792?v=4",
"profile": "https://github.com/NikhilMurugesan",
"contributions": [
"code"
]
},
{
"login": "myangle1120",
"name": "myangle1120",
"avatar_url": "https://avatars.githubusercontent.com/u/19237013?v=4",
"profile": "https://github.com/myangle1120",
"contributions": [
"code"
]
}
],
"contributorsPerLine": 7,
+60
View File
@@ -0,0 +1,60 @@
#
# 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.
#
github:
description: Apache HertzBeat(incubating) is a real-time monitoring system with agentless, performance cluster, prometheus-compatible, custom monitoring and status page building capabilities.
homepage: https://hertzbeat.apache.org/
labels:
- monitoring
- monitor
- notifications
- alerting
- self-hosted
- prometheus
- zabbix
- grafana
- metrics
- observability
- uptime
- uptime-monitoring
- status
- status-page
- devops
- server
- linux
- database
- mysql
- cloud
enabled_merge_buttons:
squash: true
merge: false
rebase: false
protected_branches:
master:
required_status_checks:
strict: true
contexts:
- check-license-header
required_pull_request_reviews:
dismiss_stale_reviews: true
required_approving_review_count: 1
notifications:
commits: notifications@hertzbeat.apache.org
issues: notifications@hertzbeat.apache.org
pullrequests: notifications@hertzbeat.apache.org
jobs: notifications@hertzbeat.apache.org
discussions: dev@hertzbeat.apache.org
+38
View File
@@ -0,0 +1,38 @@
{
"name": "Hertzbeat DevContainer",
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
"features": {
"ghcr.io/devcontainers/features/java:1": {
"version": "17",
"installMaven": "true",
"installGradle": "false"
},
"ghcr.io/devcontainers/features/node:1": {
"version": "20"
},
"ghcr.io/devcontainers/features/git-lfs:1.1.0": {}
},
"customizations": {
"vscode": {
"settings": {},
// same extensions as Gitpod, should match /.gitpod.yml
"extensions": [
"vscjava.vscode-java-pack",
"editorconfig.editorconfig",
"dbaeumer.vscode-eslint",
"stylelint.vscode-stylelint",
"DavidAnson.vscode-markdownlint",
"ms-azuretools.vscode-docker",
"cweijan.vscode-database-client2",
"GitHub.vscode-pull-request-github"
]
}
},
"portsAttributes": {
"4200": {
"label": "Hertzbeat Web",
"onAutoForward": "notify"
}
},
"postCreateCommand": "java -version"
}
+23
View File
@@ -0,0 +1,23 @@
#
# 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.
#
/home export-ignore
/hip export-ignore
/.github export-ignore
/.idea export-ignore
.gitattributes export-ignore
.gitignore export-ignore
-3
View File
@@ -1,3 +0,0 @@
# These are supported funding model platforms
custom: ['https://hertzbeat.com/docs/others/sponsor']
+17
View File
@@ -1,3 +1,20 @@
# 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.
name: 🐛 Bug Report
description: Problems and issues with code of HertzBeat 🤔.
title: "[BUG] <title>"
+18 -4
View File
@@ -1,8 +1,22 @@
# 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.
blank_issues_enabled: false
contact_links:
- name: Community Support
url: https://github.com/dromara/hertzbeat/discussions
url: https://github.com/apache/hertzbeat/discussions
about: Please ask and answer questions here.
- name: Security Bug Bounty
url: https://github.com/dromara/hertzbeat/issues
about: Please report security vulnerabilities here.
+19 -2
View File
@@ -1,3 +1,20 @@
# 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.
name: 🚀 Feature Request
description: I have a suggestion (and may want to implement it 🙂)!
title: "[Feature] <title>"
@@ -7,7 +24,7 @@ body:
attributes:
label: Feature Request
description: >
Tip: Have you checked the docs https://hertzbeat.com/docs/, GitHub issues whether someone else has already reported your issue? Maybe the feature already exists?
Tip: Have you checked the docs https://hertzbeat.apache.org/docs/, GitHub issues whether someone else has already reported your issue? Maybe the feature already exists?
placeholder: >
A concise description of what you're experiencing.
validations:
@@ -36,4 +53,4 @@ body:
validations:
required: false
- type: markdown
value: "Please read the [Contribution Guideline](https://hertzbeat.com/docs/others/contributing) before submitting the PR"
value: "Please read the [Contribution Guideline](https://hertzbeat.apache.org/docs/community/contribution) before submitting the PR"
+17
View File
@@ -1,3 +1,20 @@
# 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.
name: 🤔 Question
description: Usage question that isn't answered in docs or discussion
title: "[Question] <title>"
+19 -2
View File
@@ -1,7 +1,24 @@
# 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.
name: 🚀 Task
description: Used to create tasks for the community.
title: "[Task] <title>"
labels: ["status: volunteer wanted"]
labels: ["discussion"]
body:
- type: textarea
attributes:
@@ -22,4 +39,4 @@ body:
- type: markdown
attributes:
value: |
Please read the [Contribution Guideline](https://hertzbeat.com/docs/others/contributing/) before submitting the PR
Please read the [Contribution Guideline](https://hertzbeat.apache.org/docs/community/contribution) before submitting the PR
+18 -1
View File
@@ -1,3 +1,20 @@
# 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.
name: 🤔 Volunteer
description: Some volunteer help
title: "[Volunteer] <title>"
@@ -13,5 +30,5 @@ body:
- type: markdown
attributes:
value: |
Please read the [Contribution Guideline](https://hertzbeat.com/docs/others/contributing/) before submitting the PR
Please read the [Contribution Guideline](https://hertzbeat.apache.org/docs/community/contribution) before submitting the PR
+2 -3
View File
@@ -5,11 +5,10 @@
## Checklist
- [x] I hereby agree to the terms of the [HertzBeat CLA](https://gist.github.com/tomsun28/511c04e7643901cb550bb6ecc75a661b)
- [ ] I have read the [Contributing Guide](https://hertzbeat.com/docs/others/contributing/)
- [ ] I have read the [Contributing Guide](https://hertzbeat.apache.org/docs/community/code_style_and_quality_guide)
- [ ] I have written the necessary doc or comment.
- [ ] I have added the necessary unit tests and all cases have passed.
## Add or update API
- [ ] I have added the necessary [e2e tests](../e2e) and all cases have passed.
- [ ] I have added the necessary [e2e tests](https://github.com/apache/hertzbeat/tree/master/e2e) and all cases have passed.
+115
View File
@@ -0,0 +1,115 @@
# 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.
#
infra:
- changed-files:
- any-glob-to-any-file:
- ".github/**/*"
- ".asf.yaml"
- ".gitignore"
- ".licenserc.yaml"
- "SECURITY.md"
- "CODE_OF_CONDUCT.md"
- "CONTRIBUTING.md"
license:
- changed-files:
- any-glob-to-any-file:
- "material/licenses/**/*"
- "LICENSE"
- "NOTICE"
script:
- changed-files:
- any-glob-to-any-file:
- "script/**/*"
helm:
- changed-files:
- any-glob-to-any-file:
- "script/helm/**/*"
kubernetes:
- changed-files:
- any-glob-to-any-file:
- "script/helm/**/*"
build:
- changed-files:
- any-glob-to-any-file:
- "script/assembly/**/*"
docker:
- changed-files:
- any-glob-to-any-file:
- "script/docker/**/*"
- "script/docker-compose/**/*"
docker-compose:
- changed-files:
- any-glob-to-any-file:
- "script/docker-compose/**/*"
doc:
- changed-files:
- any-glob-to-any-file:
- "**/README.md"
- "**/README_CN.md"
- "home/**/*"
home:
- changed-files:
- any-glob-to-any-file:
- "home/src/**/*"
webapp:
- changed-files:
- any-glob-to-any-file:
- "web-app/**/*"
e2e:
- changed-files:
- any-glob-to-any-file:
- "e2e/**/*"
backend:
- changed-files:
- any-glob-to-any-file:
- "alerter/**/*"
- "collector/**/*"
- "common/**/*"
- "grafana/**/*"
- "manager/**/*"
- "push/**/*"
- "remoting/**/*"
- "warehouse/**/*"
collector:
- changed-files:
- any-glob-to-any-file:
- "collector/**/*"
monitoring-template:
- changed-files:
- any-glob-to-any-file:
- "manager/src/main/resources/define/**/*"
HIP:
- changed-files:
- any-glob-to-any-file:
- 'hip/**'
+68 -23
View File
@@ -1,3 +1,20 @@
# 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.
# This workflow will build a Java project with Maven
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
@@ -5,34 +22,62 @@ name: Backend CI
on:
push:
branches: [ master, dev ]
branches: [ master, dev, action* ]
paths-ignore:
- '**.md'
- 'home/**'
- 'web-app/**'
- 'script/**'
- 'material/**'
pull_request:
branches: [ master, dev ]
paths-ignore:
- '**.md'
- 'home/**'
- 'web-app/**'
- 'script/**'
- 'material/**'
jobs:
build:
backend-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 17
uses: actions/setup-java@v1
with:
java-version: 17
- name: Build with Maven
run: mvn clean -B package --file pom.xml
- name: Build Image
env:
IMAGE_PUSH: false
IMAGE_LOAD: true
IMAGE_PLATFORM: linux/amd64
run: |
docker buildx create --use --name mybuilder --driver docker-container
docker buildx use mybuilder
- uses: actions/checkout@v4
- uses: ./script/ci/github-actions/setup-deps
./script/docker/server/build.sh
- name: Run E2E
run: |
sudo curl -L https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
sudo chmod u+x /usr/local/bin/docker-compose
- name: Build with Maven
run: mvn clean -B package -Prelease -Dmaven.test.skip=false --file pom.xml
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v4.0.1
with:
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true
- name: Build Image
uses: docker/build-push-action@v3
with:
context: ./dist
file: ./script/docker/server/Dockerfile
push: false
tags: apache/hertzbeat:test
- name: Run E2E
run: |
sudo curl -L https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
sudo chmod u+x /usr/local/bin/docker-compose
cd e2e
sudo docker-compose version
sudo docker-compose up --exit-code-from testing --remove-orphans
# upload application logs
- name: Upload logs & API test reports
uses: actions/upload-artifact@v4
if: always()
with:
name: hz-logs-${{ github.run_id }}
path: |
e2e/logs/
e2e/report/
cd e2e && ./start.sh
+18 -1
View File
@@ -1,3 +1,20 @@
# 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.
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
@@ -30,7 +47,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
+64
View File
@@ -0,0 +1,64 @@
# 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.
name: DOC CI
on:
push:
branches: [ master, dev ]
paths:
- 'home/**'
pull_request:
branches: [ master, dev ]
paths:
- 'home/**'
jobs:
docs-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-python@v4
with:
python-version: '3.8'
- name: Check Markdown
uses: DavidAnson/markdownlint-cli2-action@v16
with:
globs: './home/**/*.md'
- name: Check filenames
run: python ./script/ci/docs/check_file_name.py ./script/ci/docs/check_file_name.json
- name: Dead Link Check
run: |
sudo npm install -g markdown-link-check@3.8.7
for file in $(find ./home -name "*.md"); do
if ! grep -Fxq "$file" ./script/ci/exclude_files.txt; then
markdown-link-check -c ./script/ci/link_check.json -q "$file"
fi
done
- name: NPM INSTALL
working-directory: home
run: npm install
- name: NPM BUILD
working-directory: home
run: npm run build
+21 -5
View File
@@ -1,3 +1,20 @@
# 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.
name: 'HertzBeat Doc Pdf Builder'
on:
page_build
@@ -16,13 +33,13 @@ jobs:
yes "" | sudo ./install.sh
- name: Build CN PDF
run: npx docusaurus-prince-pdf -u https://hertzbeat.com/zh-cn/docs --output docs-cn.pdf
run: npx docusaurus-prince-pdf -u https://hertzbeat.apache.org/zh-cn/docs --output docs-cn.pdf
- name: Build EN PDF
run: npx docusaurus-prince-pdf -u https://hertzbeat.com/docs --output docs-en.pdf
run: npx docusaurus-prince-pdf -u https://hertzbeat.apache.org/docs --output docs-en.pdf
- name: Upload results
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: docs-cn-pdf
path: docs-cn.pdf
@@ -30,10 +47,9 @@ jobs:
retention-days: 1
- name: Upload results
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: docs-en-pdf
path: docs-en.pdf
if-no-files-found: error
retention-days: 1
+22 -1
View File
@@ -1,3 +1,20 @@
# 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.
# This workflow will build a Java project with Maven
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
@@ -6,14 +23,18 @@ name: Frontend CI
on:
push:
branches: [ master, dev ]
paths:
- 'web-app/**'
pull_request:
branches: [ master, dev ]
paths:
- 'web-app/**'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Yarn Install
working-directory: web-app
run: yarn
-15
View File
@@ -1,15 +0,0 @@
name: 'Issues Translator'
on:
issue_comment:
types: [created]
issues:
types: [opened]
jobs:
translate:
runs-on: ubuntu-latest
steps:
- uses: usthe/issues-translate-action@v2.7
with:
IS_MODIFY_TITLE: true
BOT_GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
+39
View File
@@ -0,0 +1,39 @@
# 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.
# This workflow will build a Java project with Maven
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
name: License Checker
on:
push:
branches: [ master, dev ]
pull_request:
branches: [ master, dev ]
jobs:
check-license-header:
name: check-license-header
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Check license header
uses: apache/skywalking-eyes@v0.6.0
+72
View File
@@ -0,0 +1,72 @@
# 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.
name: Nightly CI
on:
schedule:
# trigger at 00:00 everyday
- cron: '0 0 * * *'
push:
branches: [ action* ]
jobs:
build:
runs-on: ubuntu-latest
if: ${{ github.repository == 'apache/hertzbeat' }}
steps:
- uses: actions/checkout@v4
- uses: ./script/ci/github-actions/setup-deps
- name: Build the Frontend
run: |
cd web-app
yarn install
yarn package
- name: Build the Backend
run: |
mvn clean install
mvn clean package -Prelease -DskipTests
cd collector
mvn clean package -Pcluster -DskipTests
- uses: docker/setup-qemu-action@v3
- uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USER }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and Push Server
uses: docker/build-push-action@v6
with:
context: ./dist
file: ./script/docker/server/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: apache/hertzbeat:nightly
- name: Build and Push Collector
uses: docker/build-push-action@v6
with:
context: ./dist
file: ./script/docker/collector/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: apache/hertzbeat-collector:nightly
+34
View File
@@ -0,0 +1,34 @@
#
# 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.
#
name: "Pull Request Robot"
on:
- pull_request_target
jobs:
labeler:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- name: Label pull request
uses: actions/labeler@v5
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
configuration-path: .github/labeler.yml
sync-labels: true
+4
View File
@@ -28,6 +28,9 @@ jdk/
*.iml
*.ipr
### For icon.png ###
!.idea/icon.png
### NetBeans ###
nbproject/private/
build/
@@ -50,3 +53,4 @@ node_modules
# debug env
application-dev.yml
application-mysql.yml
application-pg.yml
+21
View File
@@ -0,0 +1,21 @@
#
# 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.
#
[submodule "script/helm/hertzbeat-helm-chart"]
path = script/helm/hertzbeat-helm-chart
url = git@github.com:apache/hertzbeat-helm-chart.git
branch = main
+52 -7
View File
@@ -1,8 +1,53 @@
# This configuration file was automatically generated by Gitpod.
# Please adjust to your needs (see https://www.gitpod.io/docs/introduction/learn-gitpod/gitpod-yaml)
# and commit this file to your remote git repository to share the goodness with others.
# Learn more from ready-to-use templates: https://www.gitpod.io/docs/introduction/getting-started/quickstart
tasks:
- init: mvn install -DskipTests=false
- name: Run backend
before: cd hertzbeat-manager
command: |
gp sync-await setup-backend
mvn spring-boot:run
- name: Run frontend
before: cd web-app
command: |
gp sync-await setup-frontend
yarn start --public-host "`gp url 4200`"
openMode: split-right
- name: Setup backend
init: |
sdk install java 17.0.11.fx-zulu < /dev/null
sdk default java 17.0.11.fx-zulu < /dev/null
mvn clean install -DskipTests
command: |
gp sync-done setup-backend
exit 0
- name: Setup frontend
init: |
cd web-app && yarn install
command: |
gp sync-done setup-frontend
exit 0
openMode: split-right
vscode:
extensions:
- vscjava.vscode-java-pack
- editorconfig.editorconfig
- dbaeumer.vscode-eslint
- stylelint.vscode-stylelint
- DavidAnson.vscode-markdownlint
- ms-azuretools.vscode-docker
- cweijan.vscode-database-client2
- GitHub.vscode-pull-request-github
ports:
- port: 4200
name: Hertzbeat
onOpen: open-browser
- port: 1157
onOpen: ignore
- port: 1158
onOpen: ignore
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

+105
View File
@@ -0,0 +1,105 @@
#
# 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.
#
header:
license:
spdx-id: Apache-2.0
copyright-owner: Apache Software Foundation
paths-ignore:
- '**/*.md'
- '**/*.json'
- '**/*.iml'
- '**/*.ini'
- '**/*.svg'
- '**/*.png'
- '**/*.MD'
- '**/*.ftl'
- '**/*.tpl'
- '**/*.pl'
- '**/*.dict'
- '**/*.awk'
- "**/*.lock"
- '**/*.crt'
- '**/*.pem'
- '**/*.js'
- '**/*.less'
- '**/*.txt'
- '**/target/**'
- '.gitattributes'
- '**/.gitignore'
- '**/.gitkeep'
- 'home/**'
- 'material/**'
- 'LICENSE'
- 'NOTICE'
- 'DISCLAIMER'
- '**/LICENSE'
- '**/NOTICE'
- '.all-contributorsrc'
- '**/*.AbstractCollect'
- '**/*.Plugin'
- '**/*.MockMaker'
- '.prettierrc'
- '.browserslistrc'
- '.editorconfig'
- '.eslintignore'
- '.eslintrc.js'
- '.stylelintrc'
- '.prettierignore'
- '.prettierrc.js'
- '.gitpod.Dockerfile'
- '.gitpod.yml'
- 'karma.conf.js'
- 'proxy.conf.js'
- '.helmignore'
- 'web-app/src/app/core/**'
- 'web-app/src/app/layout/**'
- 'web-app/src/app/routes/exception/**'
- 'web-app/src/app/routes/routes.module.ts'
- 'web-app/src/app/routes/routes-routing.module.ts'
- 'web-app/src/app/shared/json-schema/**'
- 'web-app/src/app/shared/index.ts'
- 'web-app/src/app/shared/shared.module.ts'
- 'web-app/src/app/shared/shared-delon.module.ts'
- 'web-app/src/app/shared/shared-zorro.module.ts'
- 'web-app/src/app/app.module.ts'
- 'web-app/src/app/app.component.ts'
- 'web-app/src/app/global-config.module.ts'
- 'web-app/src/app/icons-provider.module.ts'
- 'web-app/src/assets/color.less'
- 'web-app/src/assets/style.compact.less'
- 'web-app/src/assets/style.dark.less'
- 'web-app/src/environments/**'
- 'web-app/src/styles/**'
- 'web-app/src/index.html'
- 'web-app/src/main.ts'
- 'web-app/src/polyfills.ts'
- 'web-app/src/style-icons.ts'
- 'web-app/src/style-icons-auto.ts'
- 'web-app/src/style.less'
- 'web-app/src/test.ts'
- 'web-app/src/typings.d.ts'
comment: on-failure
dependency:
files:
- pom.xml
- web-app/package.json
+47
View File
@@ -0,0 +1,47 @@
//
// 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.
//
{
"config": {
"default": true,
"MD001": true,
"MD003": true,
"MD013": {
"line_length": 600,
"code_blocks": false,
"tables": false
},
"MD024": {
"siblings_only": true
},
"MD025": true,
"MD029": true,
"MD033": {
"allowed_elements": ["table", "tr", "td", "a", "img", "sub", "b", "br", "img", "tbody", "mark", "font"]
},
"MD036": false,
"MD040": true,
"MD045": true,
"MD046": true,
"MD047": true,
"MD052": true
},
"ignore": [
"node_modules/",
"target/",
"dist/"
]
}
+1 -1
View File
@@ -55,7 +55,7 @@ further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing or otherwise unacceptable behavior may be
reported by contacting the project team at gongchao@apache.org. All
reported by contacting the project team at dev@hertzbeat.apache.org. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate for the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
+100 -82
View File
@@ -30,20 +30,34 @@ Even small corrections to typos are very welcome :)
> This is a front-end and back-end separation project. To start the local code, the back-end [manager](manager) and the front-end [web-app](web-app) must be started separately.
- Backend start
#### Backend start
1. Requires `maven3+`, `java17` and `lombok` environments
2. (Optional) Modify the configuration file-`manager/src/main/resources/application.yml`
3. Start `springboot manager` service `manager/src/main/java/org/dromara/hertzbeat/manager/Manager.java`
1. Requires `maven3+`, `java17` and `lombok` environments
- Front-web start
2. (Optional) Modify the configuration file: `manager/src/main/resources/application.yml`
3. Execute under the project root directory: `mvn clean install -DskipTests`
4. Add VM Options: `--add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED`
5. Start `springboot manager` service: `manager/src/main/java/org/apache/hertzbeat/hertzbeat-manager/Manager.java`
#### Frontend start
1. Need `Node Yarn` Environment, Make sure `Node.js >= 18`
2. Cd to the `web-app` directory: `cd web-app`
3. Install yarn if not existed `npm install -g yarn`
4. Install Dependencies: `yarn install` or `yarn install --registry=https://registry.npmmirror.com` in `web-app`
5. Install angular-cli globally: `yarn global add @angular/cli@15` or `yarn global add @angular/cli@15 --registry=https://registry.npmmirror.com`
6. After the local backend is started, start the local frontend in the web-app directory: `ng serve --open`
7. Browser access to localhost:4200 to start, default account/password is *admin/hertzbeat*
1. Need `nodejs npm angular-cli` environment, Make sure `Node.js >= 18`
2. Install yarn: `npm install -g yarn`
3. Execute under the front-end project directory web-app: `yarn install`
4. Install angular-cli globally: `yarn global add @angular/cli@15`
5. After the local backend is started, start the local frontend in the web-app directory: `ng serve --open`
6. Browser access to localhost:4200 to start
### Find tasks
@@ -54,25 +68,25 @@ Of course, if you have a good idea, you can also propose it directly on GitHub D
### Submit Pull Request
1. First you need to fork your target [hertzbeat repository](https://github.com/dromara/hertzbeat).
1. First you need to fork your target [hertzbeat repository](https://github.com/apache/hertzbeat).
2. Then download the code locally with git command:
```shell
git clone git@github.com:${YOUR_USERNAME}/hertzbeat.git #Recommended
```
```shell
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.
4. Then, you can refer to the following command to submit the code:
```shell
git checkout -b a-feature-branch #Recommended
```
```shell
git checkout -b a-feature-branch #Recommended
```
5. Submit the coed as a commit, the commit message format specification required: [module name or type name]feature or bugfix or doc: custom message.
```shell
git add <modified file/path>
git commit -m '[docs]feature: necessary instructions' #Recommended
```
```shell
git add <modified file/path>
git commit -m '[docs]feature: necessary instructions' #Recommended
```
6. Push to the remote repository
```shell
git push origin a-feature-branch
```
```shell
git push origin a-feature-branch
```
7. Then you can initiate a new PR (Pull Request) on GitHub.
Please note that the title of the PR needs to conform to our spec, and write the necessary description in the PR to facilitate code review by Committers and other contributors.
@@ -99,40 +113,35 @@ git push origin --delete a-dev-branch
On the master/main branch, you can do the following to sync the upstream repository:
```shell
git remote add upstream https://github.com/dromara/hertzbeat.git #Bind the remote warehouse, if it has been executed, it does not need to be executed again
git remote add upstream https://github.com/apache/hertzbeat.git #Bind the remote warehouse, if it has been executed, it does not need to be executed again
git checkout master
git pull upstream master
```
### HertzBeat Improvement Proposal (HIP)
If you have major new features(e.g., support metrics push gateway, support logs monitoring), you need to write a design document known as a HertzBeat Improvement Proposal (HIP). Before starting to write a HIP, make sure you follow the process [here](https://github.com/apache/hertzbeat/tree/master/hip).
### How to become a Committer?
With the above steps, you are a contributor to HertzBeat. Repeat the previous steps to stay active in the community, keep at, you can become a Committer!
### Join Discussion
[Gitter Channel](https://gitter.im/hertzbeat/community)
[Join the Mailing Lists](https://lists.apache.org/list.html?dev@hertzbeat.apache.org) : Mail to `dev-subscribe@hertzbeat.apache.org` to subscribe mailing lists.
[Github Discussion](https://github.com/dromara/hertzbeat/discussions)
[User Club](https://support.qq.com/products/379369)
Add WeChat account `tan-cloud` to pull you into the WeChat group.
QQ group number `236915833`, verify code: `tancloud`
Public WeChat: `tancloudtech`
Add WeChat account `ahertzbeat` to pull you into the WeChat group.
## 🥐 Architecture
- **[manager](https://github.com/dromara/hertzbeat/tree/master/manager)** Provide monitoring management, system management basic services.
- **[manager](https://github.com/apache/hertzbeat/tree/master/hertzbeat-manager)** Provide monitoring management, system management basic services.
> Provides monitoring management, monitoring configuration management, system user management, etc.
- **[collector](https://github.com/dromara/hertzbeat/tree/master/collector)** Provide metrics data collection services.
- **[collector](https://github.com/apache/hertzbeat/tree/master/collector)** Provide metrics data collection services.
> Use common protocols to remotely collect and obtain peer-to-peer metrics data.
- **[warehouse](https://github.com/dromara/hertzbeat/tree/master/warehouse)** Provide monitoring data warehousing services.
- **[warehouse](https://github.com/apache/hertzbeat/tree/master/warehouse)** Provide monitoring data warehousing services.
> Metrics data management, data query, calculation and statistics.
- **[alerter](https://github.com/dromara/hertzbeat/tree/master/alerter)** Provide alert service.
- **[alerter](https://github.com/apache/hertzbeat/tree/master/hertzbeat-alerter)** Provide alert service.
> Alarm calculation trigger, monitoring status linkage, alarm configuration, and alarm notification.
- **[web-app](https://github.com/dromara/hertzbeat/tree/master/web-app)** Provide web ui.
- **[web-app](https://github.com/apache/hertzbeat/tree/master/web-app)** Provide web ui.
> Angular Web UI.
![hertzBeat](home/static/img/docs/hertzbeat-arch.png)
@@ -174,20 +183,34 @@ Public WeChat: `tancloudtech`
> 让 HertzBeat 的代码在您的开发工具上运行起来,并且能够断点调试。
> 此为前后端分离项目,本地代码启动需将后端[manager](manager)和前端[web-app](web-app)分别启动生效。
- 后端启动
#### 后端启动
1. 需要 `maven3+`, `java17` 和 `lombok` 环境
1. 需要`maven3+`, `java17``lombok`环境
2. (可选)修改配置文件配置信息-`manager/src/main/resources/application.yml`
3. 启动`springboot manager`服务 `manager/src/main/java/org/dromara/hertzbeat/manager/Manager.java`
- 前端启动
3. 在项目根目录运行编译: `mvn clean install -DskipTests`
1. 需要`nodejs npm angular-cli`环境, 确保你的版本 `Node.js >= 18`
2. 安装yarn `npm install -g yarn`
3. 在前端工程目录web-app下执行 `yarn install`
4. 全局安装angular-cli `yarn global add @angular/cli@15`
5. 待本地后端启动后,在web-app目录下启动本地前端 `ng serve --open`
6. 浏览器访问 localhost:4200 即可开始,默认账号密码 admin/hertzbeat
4. 在 `jvm` 加入参数 `--add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED`
5. 启动`springboot manager`服务 `manager/src/main/java/org/apache/hertzbeat/hertzbeat-manager/Manager.java`
#### 前端启动
1. 需要 `nodejs yarn` 环境, Make sure `Node.js >= 18`
2. 进入 `web-app` 目录: `cd web-app`
3. 安装yarn: `npm install -g yarn`
4. 在前端工程目录 `web-app` 下执行: `yarn install` or `yarn install --registry=https://registry.npmmirror.com` in `web-app`
5. 全局安装 `angular-cli`: `yarn global add @angular/cli@15` or `yarn global add @angular/cli@15 --registry=https://registry.npmmirror.com`
6. 待本地后端启动后,在web-app目录下启动本地前端 `ng serve --open`
7. 浏览器访问 localhost:4200 即可开始,默认账号密码 *admin/hertzbeat*
### 寻找任务
@@ -198,25 +221,25 @@ Public WeChat: `tancloudtech`
### 提交 Pull Request
1. 首先您需要 Fork 目标仓库 [hertzbeat repository](https://github.com/dromara/hertzbeat).
1. 首先您需要 Fork 目标仓库 [hertzbeat repository](https://github.com/apache/hertzbeat).
2. 然后 用git命令 将代码下载到本地:
```shell
git clone git@github.com:${YOUR_USERNAME}/hertzbeat.git #Recommended
```
```shell
git clone git@github.com:${YOUR_USERNAME}/hertzbeat.git #Recommended
```
3. 下载完成后,请参考目标仓库的入门指南或者 README 文件对项目进行初始化。
4. 接着,您可以参考如下命令进行代码的提交, 切换新的分支, 进行开发:
```shell
git checkout -b a-feature-branch #Recommended
```
```shell
git checkout -b a-feature-branch #Recommended
```
5. 提交 commit , commit 描述信息需要符合约定格式: [module name or type name]feature or bugfix or doc: custom message.
```shell
git add <modified file/path>
git commit -m '[docs]feature: necessary instructions' #Recommended
```
```shell
git add <modified file/path>
git commit -m '[docs]feature: necessary instructions' #Recommended
```
6. 推送到远程仓库
```shell
git push origin a-feature-branch
```
```shell
git push origin a-feature-branch
```
7. 然后您就可以在 GitHub 上发起新的 PR (Pull Request)。
请注意 PR 的标题需要符合我们的规范,并且在 PR 中写上必要的说明,来方便 Committer 和其他贡献者进行代码审查。
@@ -243,40 +266,35 @@ git push origin --delete a-dev-branch
在主分支上,您可以执行以下操作来同步上游仓库:
```shell
git remote add upstream https://github.com/dromara/hertzbeat.git #Bind the remote warehouse, if it has been executed, it does not need to be executed again
git remote add upstream https://github.com/apache/hertzbeat.git #Bind the remote warehouse, if it has been executed, it does not need to be executed again
git checkout master
git pull upstream master
```
### HertzBeat 改进提案 (HIP)
如果您有重大的新特性(例如,支持指标推送网关,日志监控等),您需要编写一个被称为 HertzBeat 改进提案(HertzBeat Improvement ProposalHIP)的设计文档。在开始编写 HIP 之前,请确保您遵循了[这里](https://github.com/apache/hertzbeat/tree/master/hip)的流程。
### 如何成为Committer
通过上述步骤,您就是 HertzBeat 的贡献者了。重复前面的步骤,在社区中保持活跃,坚持下去,您就能成为 Committer!
### 加入讨论交流
### 加入讨论交流
[Gitter Channel](https://gitter.im/hertzbeat/community)
[Join the Mailing Lists](https://lists.apache.org/list.html?dev@hertzbeat.apache.org) : Mail to `dev-subscribe@hertzbeat.apache.org` to subscribe mailing lists.
[Github Discussion](https://github.com/dromara/hertzbeat/discussions)
[HertzBeat答疑网站](https://support.qq.com/products/379369)
加微信号 `tan-cloud` 拉您进微信交流群
加QQ群号 `236915833` 进QQ交流群, 验证信息: `tancloud`
微信公众号: `tancloudtech`
Add WeChat account `ahertzbeat` to pull you into the WeChat group.
### 模块
- **[manager](https://github.com/dromara/hertzbeat/tree/master/manager)** 提供监控管理,系统管理基础服务
- **[manager](https://github.com/apache/hertzbeat/tree/master/hertzbeat-manager)** 提供监控管理,系统管理基础服务
> 提供对监控的管理,监控应用配置的管理,系统用户租户后台管理等。
- **[collector](https://github.com/dromara/hertzbeat/tree/master/collector)** 提供监控数据采集服务
- **[collector](https://github.com/apache/hertzbeat/tree/master/collector)** 提供监控数据采集服务
> 使用通用协议远程采集获取对端指标数据。
- **[warehouse](https://github.com/dromara/hertzbeat/tree/master/warehouse)** 提供监控数据仓储服务
- **[warehouse](https://github.com/apache/hertzbeat/tree/master/warehouse)** 提供监控数据仓储服务
> 采集指标结果数据管理,数据落盘,查询,计算统计。
- **[alerter](https://github.com/dromara/hertzbeat/tree/master/alerter)** 提供告警服务
- **[alerter](https://github.com/apache/hertzbeat/tree/master/hertzbeat-alerter)** 提供告警服务
> 告警计算触发,任务状态联动,告警配置,告警通知。
- **[web-app](https://github.com/dromara/hertzbeat/tree/master/web-app)** 提供可视化控制台页面
- **[web-app](https://github.com/apache/hertzbeat/tree/master/web-app)** 提供可视化控制台页面
> 监控告警系统可视化控制台前端
![hertzBeat](home/static/img/docs/hertzbeat-arch.png)
+10
View File
@@ -0,0 +1,10 @@
Apache HertzBeat (incubating) is an effort undergoing incubation at the Apache
Software Foundation (ASF), sponsored by the Apache Incubator PMC.
Incubation is required of all newly accepted projects until a further review
indicates that the infrastructure, communications, and decision making process
have stabilized in a manner consistent with other successful ASF projects.
While incubation status is not necessarily a reflection of the completeness
or stability of the code, it does indicate that the project has yet to be
fully endorsed by the ASF.
+202 -172
View File
@@ -1,207 +1,237 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and
distribution as defined by Sections 1 through 9 of this document.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the
copyright owner that is granting the License.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other
entities that control, are controlled by, or are under common control with
that entity. For the purposes of this definition, "control" means (i) the
power, direct or indirect, to cause the direction or management of such
entity, whether by contract or otherwise, or (ii) ownership of
fifty percent (50%) or more of the outstanding shares, or (iii) beneficial
ownership of such entity.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising
permissions granted by this License.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation source,
and configuration files.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical transformation
or translation of a Source form, including but not limited to compiled
object code, generated documentation, and conversions to
other media types.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object
form, made available under the License, as indicated by a copyright notice
that is included in or attached to the work (an example is provided in the
Appendix below).
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form,
that is based on (or derived from) the Work and for which the editorial
revisions, annotations, elaborations, or other modifications represent,
as a whole, an original work of authorship. For the purposes of this
License, Derivative Works shall not include works that remain separable
from, or merely link (or bind by name) to the interfaces of, the Work and
Derivative Works thereof.
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original
version of the Work and any modifications or additions to that Work or
Derivative Works thereof, that is intentionally submitted to Licensor for
inclusion in the Work by the copyright owner or by an individual or
Legal Entity authorized to submit on behalf of the copyright owner.
For the purposes of this definition, "submitted" means any form of
electronic, verbal, or written communication sent to the Licensor or its
representatives, including but not limited to communication on electronic
mailing lists, source code control systems, and issue tracking systems
that are managed by, or on behalf of, the Licensor for the purpose of
discussing and improving the Work, but excluding communication that is
conspicuously marked or otherwise designated in writing by the copyright
owner as "Not a Contribution."
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on
behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
Subject to the terms and conditions of this License, each Contributor
hereby grants to You a perpetual, worldwide, non-exclusive, no-charge,
royalty-free, irrevocable copyright license to reproduce, prepare
Derivative Works of, publicly display, publicly perform, sublicense,
and distribute the Work and such Derivative Works in
Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
3. Grant of Patent License.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
Subject to the terms and conditions of this License, each Contributor
hereby grants to You a perpetual, worldwide, non-exclusive, no-charge,
royalty-free, irrevocable (except as stated in this section) patent
license to make, have made, use, offer to sell, sell, import, and
otherwise transfer the Work, where such license applies only to those
patent claims licensable by such Contributor that are necessarily
infringed by their Contribution(s) alone or by combination of their
Contribution(s) with the Work to which such Contribution(s) was submitted.
If You institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
Contribution incorporated within the Work constitutes direct or
contributory patent infringement, then any patent licenses granted to
You under this License for that Work shall terminate as of the date such
litigation is filed.
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
4. Redistribution.
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
You may reproduce and distribute copies of the Work or Derivative Works
thereof in any medium, with or without modifications, and in Source or
Object form, provided that You meet the following conditions:
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
1. You must give any other recipients of the Work or Derivative Works a
copy of this License; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
2. You must cause any modified files to carry prominent notices stating
that You changed the files; and
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
3. You must retain, in the Source form of any Derivative Works that You
distribute, all copyright, patent, trademark, and attribution notices from
the Source form of the Work, excluding those notices that do not pertain
to any part of the Derivative Works; and
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
4. If the Work includes a "NOTICE" text file as part of its distribution,
then any Derivative Works that You distribute must include a readable copy
of the attribution notices contained within such NOTICE file, excluding
those notices that do not pertain to any part of the Derivative Works,
in at least one of the following places: within a NOTICE text file
distributed as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or, within a
display generated by the Derivative Works, if and wherever such
third-party notices normally appear. The contents of the NOTICE file are
for informational purposes only and do not modify the License.
You may add Your own attribution notices within Derivative Works that You
distribute, alongside or as an addendum to the NOTICE text from the Work,
provided that such additional attribution notices cannot be construed
as modifying the License.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
You may add Your own copyright statement to Your modifications and may
provide additional or different license terms and conditions for use,
reproduction, or distribution of Your modifications, or for any such
Derivative Works as a whole, provided Your use, reproduction, and
distribution of the Work otherwise complies with the conditions
stated in this License.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
5. Submission of Contributions.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
Unless You explicitly state otherwise, any Contribution intentionally
submitted for inclusion in the Work by You to the Licensor shall be under
the terms and conditions of this License, without any additional
terms or conditions. Notwithstanding the above, nothing herein shall
supersede or modify the terms of any separate license agreement you may
have executed with Licensor regarding such Contributions.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
6. Trademarks.
END OF TERMS AND CONDITIONS
This License does not grant permission to use the trade names, trademarks,
service marks, or product names of the Licensor, except as required for
reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.
APPENDIX: How to apply the Apache License to your work.
7. Disclaimer of Warranty.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Unless required by applicable law or agreed to in writing, Licensor
provides the Work (and each Contributor provides its Contributions)
on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
either express or implied, including, without limitation, any warranties
or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS
FOR A PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any risks
associated with Your exercise of permissions under this License.
Copyright [yyyy] [name of copyright owner]
8. Limitation of Liability.
Licensed 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
In no event and under no legal theory, whether in tort
(including negligence), contract, or otherwise, unless required by
applicable law (such as deliberate and grossly negligent acts) or agreed
to in writing, shall any Contributor be liable to You for damages,
including any direct, indirect, special, incidental, or consequential
damages of any character arising as a result of this License or out of
the use or inability to use the Work (including but not limited to damages
for loss of goodwill, work stoppage, computer failure or malfunction,
or any and all other commercial damages or losses), even if such
Contributor has been advised of the possibility of such damages.
http://www.apache.org/licenses/LICENSE-2.0
9. Accepting Warranty or Additional Liability.
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.
While redistributing the Work or Derivative Works thereof, You may choose
to offer, and charge a fee for, acceptance of support, warranty,
indemnity, or other liability obligations and/or rights consistent with
this License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf of any
other Contributor, and only if You agree to indemnify, defend, and hold
each Contributor harmless for any liability incurred by, or claims
asserted against, such Contributor by reason of your accepting any such
warranty or additional liability.
========================================================================
MIT License
========================================================================
END OF TERMS AND CONDITIONS
The following components are provided under the MIT License
These files from https://github.com/ng-alain/ng-alain
The text of the license is included in material/licenses/frontend/LICENSE-ng-alain.txt
APPENDIX: How to apply the Apache License to your work
To apply the Apache License to your work, attach the following boilerplate
notice, with the fields enclosed by brackets "[]" replaced with your own
identifying information. (Don't include the brackets!) The text should be
enclosed in the appropriate comment syntax for the file format. We also
recommend that a file or class name and description of purpose be included
on the same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [HertzBeat of copyright https://www.tancloud.cn]
Licensed 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.
web-app/src/app/core/**
web-app/src/app/layout/**
web-app/src/app/routes/exception/**
web-app/src/app/routes/routes.module.ts
web-app/src/app/routes/routes-routing.module.ts
web-app/src/app/shared/json-schema/**
web-app/src/app/shared/index.ts
web-app/src/app/shared/shared.module.ts
web-app/src/app/shared/shared-delon.module.ts
web-app/src/app/shared/shared-zorro.module.ts
web-app/src/app/app.module.ts
web-app/src/app/app.component.ts
web-app/src/app/global-config.module.ts
web-app/src/app/icons-provider.module.ts
web-app/src/assets/color.less
web-app/src/assets/style.compact.less
web-app/src/assets/style.dark.less
web-app/src/environments/**
web-app/src/styles/**
web-app/src/index.html
web-app/src/main.ts
web-app/src/polyfills.ts
web-app/src/style-icons.ts
web-app/src/style-icons-auto.ts
web-app/src/style.less
web-app/src/test.ts
web-app/src/typings.d.ts
+4 -11
View File
@@ -1,12 +1,5 @@
HertzBeat-An open-source, real-time monitoring system.
HertzBeat-易用友好的实时监控系统。
Apache HertzBeat (incubating)
Copyright 2024 The Apache Software Foundation
HertzBeat Declaration / HertzBeat声明
It can be used directly without authorization. All copyrights, patents, trademarks and ownership statements in the product and source code must be retained.
可直接免费商用,但必须保留本作品及源码中的所有版权、专利、商标和归属声明。
The attribution statement and copyright notice in the footer cannot be ignored, otherwise it will be deemed as infringement.
页面等页脚中归属声明及版权声明不可忽略,否则视为侵权。
Copyright https://www.hertzbeat.com https://www.tancloud.cn All Rights Reserved.
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
+347 -271
View File
@@ -1,31 +1,32 @@
<p align="center">
<a href="https://hertzbeat.com">
<img alt="hertzbeat" src="https://cdn.jsdelivr.net/gh/dromara/hertzbeat/home/static/img/hertzbeat-brand.svg" width="260">
<a href="https://hertzbeat.apache.org">
<img alt="hertzbeat" src="/home/static/img/hertzbeat-brand.svg" width="260">
</a>
</p>
[comment]: <> (<img alt="sureness" src="https://cdn.jsdelivr.net/gh/dromara/hertzbeat/home/static/img/hertzbeat-brand.svg" width="300">)
<h4 align="center">
<a href="README.md">English Document</a> | <a href="README_CN.md">中文文档</a>
</h4>
## HertzBeat | [中文文档](README_CN.md)
> A real-time monitoring system with agentless, performance cluster, prometheus-compatible, custom monitoring and status page building capabilities.
> 实时监控系统,无需Agent,性能集群,兼容Prometheus,自定义监控和状态页构建能力。
> A real-time monitoring system with agentless, performance cluster, prometheus-compatible, custom monitoring and status page building capabilities.
[![Discord](https://img.shields.io/badge/Chat-Discord-7289DA?logo=discord)](https://discord.gg/Fb6M73htGr)
[![Reddit](https://img.shields.io/badge/Reddit-Community-7289DA?logo=reddit)](https://www.reddit.com/r/hertzbeat/)
[![Twitter](https://img.shields.io/twitter/follow/hertzbeat1024?logo=twitter)](https://twitter.com/hertzbeat1024)
[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/8139/badge)](https://www.bestpractices.dev/projects/8139)
[![Docker Pulls](https://img.shields.io/docker/pulls/tancloud/hertzbeat?style=%20for-the-badge&logo=docker&label=DockerHub%20Download)](https://hub.docker.com/repository/docker/tancloud/hertzbeat/general)
[![codecov](https://codecov.io/gh/apache/HertzBeat/branch/master/graph/badge.svg)](https://app.codecov.io/gh/apache/hertzbeat)
[![Docker Pulls](https://img.shields.io/docker/pulls/apache/hertzbeat?style=%20for-the-badge&logo=docker&label=DockerHub%20Download)](https://hub.docker.com/r/apache/hertzbeat)
[![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/hertzbeat)](https://artifacthub.io/packages/search?repo=hertzbeat)
[![QQ](https://img.shields.io/badge/QQ-236915833-orange)](https://jq.qq.com/?_wv=1027&k=aVIVB2K9)
[![YouTube Channel Subscribers](https://img.shields.io/youtube/channel/subscribers/UCri75zfWX0GHqJFPENEbLow?logo=youtube&label=YouTube%20Channel)](https://www.youtube.com/channel/UCri75zfWX0GHqJFPENEbLow)
[![Contribute with Gitpod](https://img.shields.io/badge/Contribute%20with-Gitpod-908a85?logo=gitpod&color=green)](https://gitpod.io/#https://github.com/apache/hertzbeat)
**Home: [hertzbeat.dromara.org](https://hertzbeat.dromara.org) Global | [hertzbeat.com](https://hertzbeat.com) China**
**Home: [hertzbeat.apache.org](https://hertzbeat.apache.org)**
**Email: <a href="mailto:dev-subscribe@hertzbeat.apache.org">Mail to `dev-subscribe@hertzbeat.apache.org`</a> to subscribe mailing lists**
## 🎡 <font color="green">Introduction</font>
[HertzBeat](https://github.com/dromara/hertzbeat) is an easy-to-use, open source, real-time monitoring system with agentless, high performance cluster, prometheus-compatible, offers powerful custom monitoring and status page building capabilities.
[Apache HertzBeat](https://github.com/apache/hertzbeat) (incubating) is an easy-to-use, open source, real-time monitoring system with agentless, high performance cluster, prometheus-compatible, offers powerful custom monitoring and status page building capabilities.
### Features
@@ -59,42 +60,42 @@
> Welcome everyone to contribute your customized general monitoring type YML template during use.
- [Website](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-website.yml), [Port Telnet](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-port.yml),
[Http Api](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-api.yml), [Ping Connect](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-ping.yml),
[Jvm](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-jvm.yml), [SiteMap](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-fullsite.yml),
[Ssl Certificate](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-ssl_cert.yml), [SpringBoot2](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-springboot2.yml),
[FTP Server](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-ftp.yml), [SpringBoot3](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-springboot3.yml),
[Udp Port](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-udp.yml), [Dns](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-dns.yml),
[Pop3](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-pop3.yml), [Ntp](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-ntp.yml),
[Api Code](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-api_code.yml), [Smtp](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-smtp.yml),
[Nginx](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-nginx.yml)
- [Mysql](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-mysql.yml), [PostgreSQL](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-postgresql.yml),
[MariaDB](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-mariadb.yml), [Redis](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-redis.yml),
[ElasticSearch](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-elasticsearch.yml), [SqlServer](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-sqlserver.yml),
[Oracle](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-oracle.yml), [MongoDB](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-mongodb.yml),
[DM](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-dm.yml), [OpenGauss](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-opengauss.yml),
[ClickHouse](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-clickhouse.yml), [IoTDB](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-iotdb.yml),
[Redis Cluster](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-redis_cluster.yml), [Redis Sentinel](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-redis_sentinel.yml)
[Doris BE](https://github.com/dromara/hertzbeat/blob/master/manager/src/main/resources/define/app-doris_be.yml), [Doris FE](https://github.com/dromara/hertzbeat/blob/master/manager/src/main/resources/define/app-doris_fe.yml),
[Memcached](https://github.com/dromara/hertzbeat/blob/master/manager/src/main/resources/define/app-memcached.yml), [NebulaGraph](https://github.com/dromara/hertzbeat/blob/master/manager/src/main/resources/define/app-nebulaGraph.yml)
- [Linux](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-linux.yml), [Ubuntu](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-ubuntu.yml),
[CentOS](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-centos.yml), [Windows](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-windows.yml),
[EulerOS](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-euleros.yml), [Fedora CoreOS](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-coreos.yml),
[OpenSUSE](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-opensuse.yml), [Rocky Linux](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-rockylinux.yml),
[Red Hat](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-redhat.yml), [FreeBSD](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-freebsd.yml),
[AlmaLinux](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-almalinux.yml), [Debian Linux](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-debian.yml)
- [Tomcat](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-tomcat.yml), [Nacos](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-nacos.yml),
[Zookeeper](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-zookeeper.yml), [RabbitMQ](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-rabbitmq.yml),
[Flink](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-flink.yml), [Kafka](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-kafka.yml),
[ShenYu](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-shenyu.yml), [DynamicTp](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-dynamic_tp.yml),
[Jetty](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-jetty.yml), [ActiveMQ](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-activemq.yml),
[Spring Gateway](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-spring_gateway.yml), [EMQX MQTT](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-emqx.yml),
[AirFlow](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-airflow.yml), [Hive](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-hive.yml),
[Spark](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-spark.yml), [Hadoop](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-hadoop.yml)
- [Kubernetes](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-kubernetes.yml), [Docker](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-docker.yml)
- [CiscoSwitch](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-cisco_switch.yml), [HpeSwitch](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-hpe_switch.yml),
[HuaweiSwitch](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-huawei_switch.yml), [TpLinkSwitch](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-tplink_switch.yml),
[H3cSwitch](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-h3c_switch.yml)
- [Website](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-website.yml), [Port Telnet](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-port.yml),
[Http Api](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-api.yml), [Ping Connect](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-ping.yml),
[Jvm](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-jvm.yml), [SiteMap](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-fullsite.yml),
[Ssl Certificate](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-ssl_cert.yml), [SpringBoot2](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-springboot2.yml),
[FTP Server](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-ftp.yml), [SpringBoot3](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-springboot3.yml),
[Udp Port](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-udp_port.yml), [Dns](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-dns.yml),
[Pop3](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-pop3.yml), [Ntp](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-ntp.yml),
[Api Code](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-api_code.yml), [Smtp](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-smtp.yml),
[Nginx](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-nginx.yml)
- [Mysql](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-mysql.yml), [PostgreSQL](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-postgresql.yml),
[MariaDB](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-mariadb.yml), [Redis](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-redis.yml),
[ElasticSearch](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-elasticsearch.yml), [SqlServer](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-sqlserver.yml),
[Oracle](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-oracle.yml), [MongoDB](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-mongodb.yml),
[DM](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-dm.yml), [OpenGauss](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-opengauss.yml),
[ClickHouse](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-clickhouse.yml), [IoTDB](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-iotdb.yml),
[Redis Cluster](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-redis_cluster.yml), [Redis Sentinel](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-redis_sentinel.yml)
[Doris BE](https://github.com/apache/hertzbeat/blob/master/hertzbeat-manager/src/main/resources/define/app-doris_be.yml), [Doris FE](https://github.com/apache/hertzbeat/blob/master/hertzbeat-manager/src/main/resources/define/app-doris_fe.yml),
[Memcached](https://github.com/apache/hertzbeat/blob/master/hertzbeat-manager/src/main/resources/define/app-memcached.yml), [NebulaGraph](https://github.com/apache/hertzbeat/blob/master/hertzbeat-manager/src/main/resources/define/app-nebula_graph.yml)
- [Linux](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-linux.yml), [Ubuntu](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-ubuntu.yml),
[CentOS](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-centos.yml), [Windows](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-windows.yml),
[EulerOS](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-euleros.yml), [Fedora CoreOS](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-coreos.yml),
[OpenSUSE](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-opensuse.yml), [Rocky Linux](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-rockylinux.yml),
[Red Hat](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-redhat.yml), [FreeBSD](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-freebsd.yml),
[AlmaLinux](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-almalinux.yml), [Debian Linux](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-debian.yml)
- [Tomcat](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-tomcat.yml), [Nacos](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-nacos.yml),
[Zookeeper](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-zookeeper.yml), [RabbitMQ](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-rabbitmq.yml),
[Flink](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-flink.yml), [Kafka](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-kafka.yml),
[ShenYu](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-shenyu.yml), [DynamicTp](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-dynamic_tp.yml),
[Jetty](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-jetty.yml), [ActiveMQ](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-activemq.yml),
[Spring Gateway](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-spring_gateway.yml), [EMQX MQTT](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-emqx.yml),
[AirFlow](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-airflow.yml), [Hive](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-hive.yml),
[Spark](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-spark.yml), [Hadoop](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-hadoop.yml)
- [Kubernetes](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-kubernetes.yml), [Docker](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-docker.yml)
- [CiscoSwitch](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-cisco_switch.yml), [HpeSwitch](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-hpe_switch.yml),
[HuaweiSwitch](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-huawei_switch.yml), [TpLinkSwitch](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-tplink_switch.yml),
[H3cSwitch](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-h3c_switch.yml)
- And More Your Custom Template.
- Notified Support `Discord` `Slack` `Telegram` `Email` `Dingtalk` `WeChat` `FeiShu` `Webhook` `SMS` `ServerChan`.
@@ -109,36 +110,36 @@
##### 1Install quickly via docker
1. Just one command to get started:
1. Just one command to get started
```docker run -d -p 1157:1157 -p 1158:1158 --name hertzbeat tancloud/hertzbeat```
```or use quay.io (if dockerhub network connect timeout)```
```docker run -d -p 1157:1157 -p 1158:1158 --name hertzbeat quay.io/tancloud/hertzbeat```
```shell
docker run -d -p 1157:1157 -p 1158:1158 --name hertzbeat apache/hertzbeat
```
2. Access `http://localhost:1157` to start, default account: `admin/hertzbeat`
3. Deploy collector clusters (Optional)
```
docker run -d -e IDENTITY=custom-collector-name -e MANAGER_HOST=127.0.0.1 -e MANAGER_PORT=1158 --name hertzbeat-collector tancloud/hertzbeat-collector
```
- `-e IDENTITY=custom-collector-name` : set the collector unique identity name.
- `-e MODE=public` : set the running mode(public or private), public cluster or private cloud-edge.
- `-e MANAGER_HOST=127.0.0.1` : set the main hertzbeat server ip.
- `-e MANAGER_PORT=1158` : set the main hertzbeat server port, default 1158.
```shell
docker run -d -e IDENTITY=custom-collector-name -e MANAGER_HOST=127.0.0.1 -e MANAGER_PORT=1158 --name hertzbeat-collector apache/hertzbeat-collector
```
Detailed config refer to [Install HertzBeat via Docker](https://hertzbeat.com/docs/start/docker-deploy)
- `-e IDENTITY=custom-collector-name` : set the collector unique identity name.
- `-e MODE=public` : set the running mode(public or private), public cluster or private cloud-edge.
- `-e MANAGER_HOST=127.0.0.1` : set the main hertzbeat server ip.
- `-e MANAGER_PORT=1158` : set the main hertzbeat server port, default 1158.
Detailed config refer to [Install HertzBeat via Docker](https://hertzbeat.apache.org/docs/start/docker-deploy)
##### 2Install via package
1. Download the release package `hertzbeat-xx.tar.gz` [GITEE Release](https://gitee.com/dromara/hertzbeat/releases) [GITHUB Release](https://github.com/dromara/hertzbeat/releases)
1. Download the release package `hertzbeat-xx.tar.gz` [Download](https://hertzbeat.apache.org/docs/download)
2. Configure the HertzBeat configuration yml file `hertzbeat/config/application.yml` (optional)
3. Run command `$ ./bin/startup.sh ` or `bin/startup.bat`
4. Access `http://localhost:1157` to start, default account: `admin/hertzbeat`
5. Deploy collector clusters (Optional)
- Download the release package `hertzbeat-collector-xx.tar.gz` to new machine [GITEE Release](https://gitee.com/dromara/hertzbeat/releases) [GITHUB Release](https://github.com/dromara/hertzbeat/releases)
- Download the release package `hertzbeat-collector-xx.tar.gz` to new machine [Download](https://hertzbeat.apache.org/docs/download)
- Configure the collector configuration yml file `hertzbeat-collector/config/application.yml`: unique `identity` name, running `mode` (public or private), hertzbeat `manager-host`, hertzbeat `manager-port`
```yaml
collector:
@@ -154,24 +155,24 @@ Detailed config refer to [Install HertzBeat via Docker](https://hertzbeat.com/do
- Run command `$ ./bin/startup.sh ` or `bin/startup.bat`
- Access `http://localhost:1157` and you will see the registered new collector in dashboard
Detailed config refer to [Install HertzBeat via Package](https://hertzbeat.com/docs/start/package-deploy)
Detailed config refer to [Install HertzBeat via Package](https://hertzbeat.apache.org/docs/start/package-deploy)
##### 3Start via source code
1. Local source code debugging needs to start the back-end project `manager` and the front-end project `web-app`.
2. Backendneed `maven3+`, `java17`, `lombok`, start the `manager` service.
2. Backendneed `maven3+`, `java17`, `lombok`, add VM options in IDE: ` --add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED `, then start the `manager` service.
3. Webneed `nodejs npm angular-cli` environment, Run `ng serve --open` in `web-app` directory after backend startup.
4. Access `http://localhost:4200` to start, default account: `admin/hertzbeat`
Detailed steps refer to [CONTRIBUTING](CONTRIBUTING.md)
##### 4Install All(hertzbeat+mysql+tsdb) via Docker-compose
##### 4Install All(hertzbeat+postgresql+tsdb) via Docker-compose
Install the mysql/postgresql database, iotdb/tdengine/victoria-metrics database and hertzbeat at one time through [docker-compose deployment script](script/docker-compose).
Install the postgresql/mysql database, victoria-metrics/iotdb/tdengine database and hertzbeat at one time through [docker-compose deployment script](script/docker-compose).
Detailed steps refer to [Install via Docker-Compose](script/docker-compose/README.md)
##### 5. Install All(hertzbeat+collector+mysql+tsdb) via kubernetes helm charts
##### 5: Install All(hertzbeat+collector+postgresql+tsdb) via kubernetes helm charts
Install HertzBeat cluster in a Kubernetes cluster by Helm chart.
@@ -179,10 +180,6 @@ Detailed steps refer to [Artifact Hub](https://artifacthub.io/packages/helm/hert
**HAVE FUN**
## 🥐 Roadmap
![hertzBeat](home/static/img/docs/hertzbeat-roadmap.png)
## ✨ Contributors
Thanks to these wonderful people, welcome to join us:
@@ -194,223 +191,322 @@ Thanks to these wonderful people, welcome to join us:
<table>
<tbody>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/tomsun28"><img src="https://avatars.githubusercontent.com/u/24788200?v=4?s=100" width="100px;" alt="tomsun28"/><br /><sub><b>tomsun28</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=tomsun28" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=tomsun28" title="Documentation">📖</a> <a href="#design-tomsun28" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><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/dromara/hertzbeat/commits?author=wang1027-wqh" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=wang1027-wqh" title="Documentation">📖</a> <a href="#design-wang1027-wqh" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.maxkey.top/"><img src="https://avatars.githubusercontent.com/u/1563377?v=4?s=100" width="100px;" alt="MaxKey"/><br /><sub><b>MaxKey</b></sub></a><br /><a href="https://github.com/dromara/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" valign="top" width="14.28%"><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/dromara/hertzbeat/commits?author=gcdd1993" title="Code">💻</a> <a href="#design-gcdd1993" title="Design">🎨</a> <a href="https://github.com/dromara/hertzbeat/issues?q=author%3Agcdd1993" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/a25017012"><img src="https://avatars.githubusercontent.com/u/32265356?v=4?s=100" width="100px;" alt="yuye"/><br /><sub><b>yuye</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=a25017012" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=a25017012" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jx10086"><img src="https://avatars.githubusercontent.com/u/5323228?v=4?s=100" width="100px;" alt="jx10086"/><br /><sub><b>jx10086</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=jx10086" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/issues?q=author%3Ajx10086" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/winnerTimer"><img src="https://avatars.githubusercontent.com/u/76024658?v=4?s=100" width="100px;" alt="winnerTimer"/><br /><sub><b>winnerTimer</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=winnerTimer" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/issues?q=author%3AwinnerTimer" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/tomsun28"><img src="https://avatars.githubusercontent.com/u/24788200?v=4?s=100" width="100px;" alt="tomsun28"/><br /><sub><b>tomsun28</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=tomsun28" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=tomsun28" title="Documentation">📖</a> <a href="#design-tomsun28" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><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/apache/hertzbeat/commits?author=wang1027-wqh" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=wang1027-wqh" title="Documentation">📖</a> <a href="#design-wang1027-wqh" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.maxkey.top/"><img src="https://avatars.githubusercontent.com/u/1563377?v=4?s=100" width="100px;" alt="MaxKey"/><br /><sub><b>MaxKey</b></sub></a><br /><a href="https://github.com/apache/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" valign="top" width="14.28%"><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/apache/hertzbeat/commits?author=gcdd1993" title="Code">💻</a> <a href="#design-gcdd1993" title="Design">🎨</a> <a href="https://github.com/apache/hertzbeat/issues?q=author%3Agcdd1993" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/a25017012"><img src="https://avatars.githubusercontent.com/u/32265356?v=4?s=100" width="100px;" alt="yuye"/><br /><sub><b>yuye</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=a25017012" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=a25017012" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jx10086"><img src="https://avatars.githubusercontent.com/u/5323228?v=4?s=100" width="100px;" alt="jx10086"/><br /><sub><b>jx10086</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=jx10086" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/issues?q=author%3Ajx10086" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/winnerTimer"><img src="https://avatars.githubusercontent.com/u/76024658?v=4?s=100" width="100px;" alt="winnerTimer"/><br /><sub><b>winnerTimer</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=winnerTimer" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/issues?q=author%3AwinnerTimer" title="Bug reports">🐛</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/goo-kits"><img src="https://avatars.githubusercontent.com/u/13163673?v=4?s=100" width="100px;" alt="goo-kits"/><br /><sub><b>goo-kits</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=goo-kits" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/issues?q=author%3Agoo-kits" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/brave4Time"><img src="https://avatars.githubusercontent.com/u/105094014?v=4?s=100" width="100px;" alt="brave4Time"/><br /><sub><b>brave4Time</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=brave4Time" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/issues?q=author%3Abrave4Time" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/walkerlee-lab"><img src="https://avatars.githubusercontent.com/u/8426753?v=4?s=100" width="100px;" alt="WalkerLee"/><br /><sub><b>WalkerLee</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=walkerlee-lab" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/issues?q=author%3Awalkerlee-lab" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/fullofjoy"><img src="https://avatars.githubusercontent.com/u/30247571?v=4?s=100" width="100px;" alt="jianghang"/><br /><sub><b>jianghang</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=fullofjoy" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/issues?q=author%3Afullofjoy" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ChineseTony"><img src="https://avatars.githubusercontent.com/u/24618786?v=4?s=100" width="100px;" alt="ChineseTony"/><br /><sub><b>ChineseTony</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=ChineseTony" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/issues?q=author%3AChineseTony" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wyt199905"><img src="https://avatars.githubusercontent.com/u/85098809?v=4?s=100" width="100px;" alt="wyt199905"/><br /><sub><b>wyt199905</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=wyt199905" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/weifuqing"><img src="https://avatars.githubusercontent.com/u/13931013?v=4?s=100" width="100px;" alt="卫傅庆"/><br /><sub><b>卫傅庆</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=weifuqing" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/issues?q=author%3Aweifuqing" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/goo-kits"><img src="https://avatars.githubusercontent.com/u/13163673?v=4?s=100" width="100px;" alt="goo-kits"/><br /><sub><b>goo-kits</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=goo-kits" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/issues?q=author%3Agoo-kits" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/brave4Time"><img src="https://avatars.githubusercontent.com/u/105094014?v=4?s=100" width="100px;" alt="brave4Time"/><br /><sub><b>brave4Time</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=brave4Time" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/issues?q=author%3Abrave4Time" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/walkerlee-lab"><img src="https://avatars.githubusercontent.com/u/8426753?v=4?s=100" width="100px;" alt="WalkerLee"/><br /><sub><b>WalkerLee</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=walkerlee-lab" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/issues?q=author%3Awalkerlee-lab" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/fullofjoy"><img src="https://avatars.githubusercontent.com/u/30247571?v=4?s=100" width="100px;" alt="jianghang"/><br /><sub><b>jianghang</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=fullofjoy" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/issues?q=author%3Afullofjoy" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ChineseTony"><img src="https://avatars.githubusercontent.com/u/24618786?v=4?s=100" width="100px;" alt="ChineseTony"/><br /><sub><b>ChineseTony</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ChineseTony" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/issues?q=author%3AChineseTony" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wyt199905"><img src="https://avatars.githubusercontent.com/u/85098809?v=4?s=100" width="100px;" alt="wyt199905"/><br /><sub><b>wyt199905</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=wyt199905" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/weifuqing"><img src="https://avatars.githubusercontent.com/u/13931013?v=4?s=100" width="100px;" alt="卫傅庆"/><br /><sub><b>卫傅庆</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=weifuqing" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/issues?q=author%3Aweifuqing" title="Bug reports">🐛</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zklmcookle"><img src="https://avatars.githubusercontent.com/u/107192352?v=4?s=100" width="100px;" alt="zklmcookle"/><br /><sub><b>zklmcookle</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=zklmcookle" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/DevilX5"><img src="https://avatars.githubusercontent.com/u/13269921?v=4?s=100" width="100px;" alt="DevilX5"/><br /><sub><b>DevilX5</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=DevilX5" title="Documentation">📖</a> <a href="https://github.com/dromara/hertzbeat/commits?author=DevilX5" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/djzeng"><img src="https://avatars.githubusercontent.com/u/14074864?v=4?s=100" width="100px;" alt="tea"/><br /><sub><b>tea</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=djzeng" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yangshihui"><img src="https://avatars.githubusercontent.com/u/28550208?v=4?s=100" width="100px;" alt="yangshihui"/><br /><sub><b>yangshihui</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=yangshihui" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/issues?q=author%3Ayangshihui" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/DreamGirl524"><img src="https://avatars.githubusercontent.com/u/81132838?v=4?s=100" width="100px;" alt="DreamGirl524"/><br /><sub><b>DreamGirl524</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=DreamGirl524" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=DreamGirl524" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/gzwlly"><img src="https://avatars.githubusercontent.com/u/83171907?v=4?s=100" width="100px;" alt="gzwlly"/><br /><sub><b>gzwlly</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=gzwlly" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/cuipiheqiuqiu"><img src="https://avatars.githubusercontent.com/u/76642201?v=4?s=100" width="100px;" alt="cuipiheqiuqiu"/><br /><sub><b>cuipiheqiuqiu</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=cuipiheqiuqiu" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=cuipiheqiuqiu" title="Tests">⚠️</a> <a href="#design-cuipiheqiuqiu" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zklmcookle"><img src="https://avatars.githubusercontent.com/u/107192352?v=4?s=100" width="100px;" alt="zklmcookle"/><br /><sub><b>zklmcookle</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=zklmcookle" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/DevilX5"><img src="https://avatars.githubusercontent.com/u/13269921?v=4?s=100" width="100px;" alt="DevilX5"/><br /><sub><b>DevilX5</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=DevilX5" title="Documentation">📖</a> <a href="https://github.com/apache/hertzbeat/commits?author=DevilX5" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/djzeng"><img src="https://avatars.githubusercontent.com/u/14074864?v=4?s=100" width="100px;" alt="tea"/><br /><sub><b>tea</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=djzeng" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yangshihui"><img src="https://avatars.githubusercontent.com/u/28550208?v=4?s=100" width="100px;" alt="yangshihui"/><br /><sub><b>yangshihui</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=yangshihui" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/issues?q=author%3Ayangshihui" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/DreamGirl524"><img src="https://avatars.githubusercontent.com/u/81132838?v=4?s=100" width="100px;" alt="DreamGirl524"/><br /><sub><b>DreamGirl524</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=DreamGirl524" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=DreamGirl524" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/gzwlly"><img src="https://avatars.githubusercontent.com/u/83171907?v=4?s=100" width="100px;" alt="gzwlly"/><br /><sub><b>gzwlly</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=gzwlly" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/cuipiheqiuqiu"><img src="https://avatars.githubusercontent.com/u/76642201?v=4?s=100" width="100px;" alt="cuipiheqiuqiu"/><br /><sub><b>cuipiheqiuqiu</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=cuipiheqiuqiu" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=cuipiheqiuqiu" title="Tests">⚠️</a> <a href="#design-cuipiheqiuqiu" title="Design">🎨</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/oyiyou"><img src="https://avatars.githubusercontent.com/u/39228891?v=4?s=100" width="100px;" alt="lambert"/><br /><sub><b>lambert</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=oyiyou" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://mroldx.xyz/"><img src="https://avatars.githubusercontent.com/u/34847828?v=4?s=100" width="100px;" alt="mroldx"/><br /><sub><b>mroldx</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=mroldx" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/woshiniusange"><img src="https://avatars.githubusercontent.com/u/91513022?v=4?s=100" width="100px;" alt="woshiniusange"/><br /><sub><b>woshiniusange</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=woshiniusange" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://vampireachao.github.io/"><img src="https://avatars.githubusercontent.com/u/52746628?v=4?s=100" width="100px;" alt="VampireAchao"/><br /><sub><b>VampireAchao</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=VampireAchao" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Ceilzcx"><img src="https://avatars.githubusercontent.com/u/48920254?v=4?s=100" width="100px;" alt="zcx"/><br /><sub><b>zcx</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=Ceilzcx" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/issues?q=author%3ACeilzcx" title="Bug reports">🐛</a> <a href="#design-Ceilzcx" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/CharlieXCL"><img src="https://avatars.githubusercontent.com/u/91540487?v=4?s=100" width="100px;" alt="CharlieXCL"/><br /><sub><b>CharlieXCL</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=CharlieXCL" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Privauto"><img src="https://avatars.githubusercontent.com/u/36581456?v=4?s=100" width="100px;" alt="Privauto"/><br /><sub><b>Privauto</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=Privauto" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=Privauto" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/oyiyou"><img src="https://avatars.githubusercontent.com/u/39228891?v=4?s=100" width="100px;" alt="lambert"/><br /><sub><b>lambert</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=oyiyou" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://mroldx.xyz/"><img src="https://avatars.githubusercontent.com/u/34847828?v=4?s=100" width="100px;" alt="mroldx"/><br /><sub><b>mroldx</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=mroldx" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/woshiniusange"><img src="https://avatars.githubusercontent.com/u/91513022?v=4?s=100" width="100px;" alt="woshiniusange"/><br /><sub><b>woshiniusange</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=woshiniusange" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://vampireachao.github.io/"><img src="https://avatars.githubusercontent.com/u/52746628?v=4?s=100" width="100px;" alt="VampireAchao"/><br /><sub><b>VampireAchao</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=VampireAchao" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Ceilzcx"><img src="https://avatars.githubusercontent.com/u/48920254?v=4?s=100" width="100px;" alt="zcx"/><br /><sub><b>zcx</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Ceilzcx" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/issues?q=author%3ACeilzcx" title="Bug reports">🐛</a> <a href="#design-Ceilzcx" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/CharlieXCL"><img src="https://avatars.githubusercontent.com/u/91540487?v=4?s=100" width="100px;" alt="CharlieXCL"/><br /><sub><b>CharlieXCL</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=CharlieXCL" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Privauto"><img src="https://avatars.githubusercontent.com/u/36581456?v=4?s=100" width="100px;" alt="Privauto"/><br /><sub><b>Privauto</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Privauto" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=Privauto" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/emrys-he"><img src="https://avatars.githubusercontent.com/u/5848915?v=4?s=100" width="100px;" alt="emrys"/><br /><sub><b>emrys</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=emrys-he" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/SxLiuYu"><img src="https://avatars.githubusercontent.com/u/95198625?v=4?s=100" width="100px;" alt="SxLiuYu"/><br /><sub><b>SxLiuYu</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/issues?q=author%3ASxLiuYu" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://allcontributors.org"><img src="https://avatars.githubusercontent.com/u/46410174?v=4?s=100" width="100px;" alt="All Contributors"/><br /><sub><b>All Contributors</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=all-contributors" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/gxc-myh"><img src="https://avatars.githubusercontent.com/u/85919258?v=4?s=100" width="100px;" alt="铁甲小宝"/><br /><sub><b>铁甲小宝</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=gxc-myh" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=gxc-myh" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/click33"><img src="https://avatars.githubusercontent.com/u/36243476?v=4?s=100" width="100px;" alt="click33"/><br /><sub><b>click33</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=click33" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://jpom.io/"><img src="https://avatars.githubusercontent.com/u/16408873?v=4?s=100" width="100px;" alt="蒋小小"/><br /><sub><b>蒋小小</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=bwcx-jzy" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.zhihu.com/people/kevinbauer"><img src="https://avatars.githubusercontent.com/u/28581579?v=4?s=100" width="100px;" alt="Kevin Huang"/><br /><sub><b>Kevin Huang</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=kevinhuangwl" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/emrys-he"><img src="https://avatars.githubusercontent.com/u/5848915?v=4?s=100" width="100px;" alt="emrys"/><br /><sub><b>emrys</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=emrys-he" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/SxLiuYu"><img src="https://avatars.githubusercontent.com/u/95198625?v=4?s=100" width="100px;" alt="SxLiuYu"/><br /><sub><b>SxLiuYu</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/issues?q=author%3ASxLiuYu" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://allcontributors.org"><img src="https://avatars.githubusercontent.com/u/46410174?v=4?s=100" width="100px;" alt="All Contributors"/><br /><sub><b>All Contributors</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=all-contributors" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/gxc-myh"><img src="https://avatars.githubusercontent.com/u/85919258?v=4?s=100" width="100px;" alt="铁甲小宝"/><br /><sub><b>铁甲小宝</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=gxc-myh" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=gxc-myh" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/click33"><img src="https://avatars.githubusercontent.com/u/36243476?v=4?s=100" width="100px;" alt="click33"/><br /><sub><b>click33</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=click33" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://jpom.io/"><img src="https://avatars.githubusercontent.com/u/16408873?v=4?s=100" width="100px;" alt="蒋小小"/><br /><sub><b>蒋小小</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=bwcx-jzy" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.zhihu.com/people/kevinbauer"><img src="https://avatars.githubusercontent.com/u/28581579?v=4?s=100" width="100px;" alt="Kevin Huang"/><br /><sub><b>Kevin Huang</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=kevinhuangwl" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/TJxiaobao"><img src="https://avatars.githubusercontent.com/u/85919258?v=4?s=100" width="100px;" alt="铁甲小宝"/><br /><sub><b>铁甲小宝</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/issues?q=author%3ATJxiaobao" title="Bug reports">🐛</a> <a href="https://github.com/dromara/hertzbeat/commits?author=TJxiaobao" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=TJxiaobao" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Jack-123-power"><img src="https://avatars.githubusercontent.com/u/84333501?v=4?s=100" width="100px;" alt="Captain Jack"/><br /><sub><b>Captain Jack</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=Jack-123-power" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/haibo-duan"><img src="https://avatars.githubusercontent.com/u/7974845?v=4?s=100" width="100px;" alt="haibo.duan"/><br /><sub><b>haibo.duan</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=haibo-duan" title="Tests">⚠️</a> <a href="https://github.com/dromara/hertzbeat/commits?author=haibo-duan" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/assassinfym"><img src="https://avatars.githubusercontent.com/u/15188754?v=4?s=100" width="100px;" alt="assassin"/><br /><sub><b>assassin</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/issues?q=author%3Aassassinfym" title="Bug reports">🐛</a> <a href="https://github.com/dromara/hertzbeat/commits?author=assassinfym" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/csyshu"><img src="https://avatars.githubusercontent.com/u/46591658?v=4?s=100" width="100px;" alt="Reverse wind"/><br /><sub><b>Reverse wind</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=csyshu" title="Tests">⚠️</a> <a href="https://github.com/dromara/hertzbeat/commits?author=csyshu" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/luxx-lq"><img src="https://avatars.githubusercontent.com/u/58515565?v=4?s=100" width="100px;" alt="luxx"/><br /><sub><b>luxx</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=luxx-lq" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://bandism.net/"><img src="https://avatars.githubusercontent.com/u/22633385?v=4?s=100" width="100px;" alt="Ikko Ashimine"/><br /><sub><b>Ikko Ashimine</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=eltociear" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/TJxiaobao"><img src="https://avatars.githubusercontent.com/u/85919258?v=4?s=100" width="100px;" alt="铁甲小宝"/><br /><sub><b>铁甲小宝</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/issues?q=author%3ATJxiaobao" title="Bug reports">🐛</a> <a href="https://github.com/apache/hertzbeat/commits?author=TJxiaobao" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=TJxiaobao" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Jack-123-power"><img src="https://avatars.githubusercontent.com/u/84333501?v=4?s=100" width="100px;" alt="Captain Jack"/><br /><sub><b>Captain Jack</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Jack-123-power" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/haibo-duan"><img src="https://avatars.githubusercontent.com/u/7974845?v=4?s=100" width="100px;" alt="haibo.duan"/><br /><sub><b>haibo.duan</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=haibo-duan" title="Tests">⚠️</a> <a href="https://github.com/apache/hertzbeat/commits?author=haibo-duan" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/assassinfym"><img src="https://avatars.githubusercontent.com/u/15188754?v=4?s=100" width="100px;" alt="assassin"/><br /><sub><b>assassin</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/issues?q=author%3Aassassinfym" title="Bug reports">🐛</a> <a href="https://github.com/apache/hertzbeat/commits?author=assassinfym" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/csyshu"><img src="https://avatars.githubusercontent.com/u/46591658?v=4?s=100" width="100px;" alt="Reverse wind"/><br /><sub><b>Reverse wind</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=csyshu" title="Tests">⚠️</a> <a href="https://github.com/apache/hertzbeat/commits?author=csyshu" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/luxx-lq"><img src="https://avatars.githubusercontent.com/u/58515565?v=4?s=100" width="100px;" alt="luxx"/><br /><sub><b>luxx</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=luxx-lq" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://bandism.net/"><img src="https://avatars.githubusercontent.com/u/22633385?v=4?s=100" width="100px;" alt="Ikko Ashimine"/><br /><sub><b>Ikko Ashimine</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=eltociear" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zenan08"><img src="https://avatars.githubusercontent.com/u/80514991?v=4?s=100" width="100px;" alt="leizenan"/><br /><sub><b>leizenan</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=zenan08" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/BKing2020"><img src="https://avatars.githubusercontent.com/u/28869121?v=4?s=100" width="100px;" alt="BKing"/><br /><sub><b>BKing</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=BKing2020" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xingshuaiLi"><img src="https://avatars.githubusercontent.com/u/119487588?v=4?s=100" width="100px;" alt="xingshuaiLi"/><br /><sub><b>xingshuaiLi</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=xingshuaiLi" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wangke6666"><img src="https://avatars.githubusercontent.com/u/113656595?v=4?s=100" width="100px;" alt="wangke6666"/><br /><sub><b>wangke6666</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=wangke6666" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/LWBobo"><img src="https://avatars.githubusercontent.com/u/50368698?v=4?s=100" width="100px;" alt="刺猬"/><br /><sub><b>刺猬</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/issues?q=author%3ALWBobo" title="Bug reports">🐛</a> <a href="https://github.com/dromara/hertzbeat/commits?author=LWBobo" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.zanglikun.com"><img src="https://avatars.githubusercontent.com/u/61591648?v=4?s=100" width="100px;" alt="Haste"/><br /><sub><b>Haste</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=zanglikun" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/SuitSmile"><img src="https://avatars.githubusercontent.com/u/38679717?v=4?s=100" width="100px;" alt="zhongshi.yi"/><br /><sub><b>zhongshi.yi</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=SuitSmile" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zenan08"><img src="https://avatars.githubusercontent.com/u/80514991?v=4?s=100" width="100px;" alt="leizenan"/><br /><sub><b>leizenan</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=zenan08" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/BKing2020"><img src="https://avatars.githubusercontent.com/u/28869121?v=4?s=100" width="100px;" alt="BKing"/><br /><sub><b>BKing</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=BKing2020" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xingshuaiLi"><img src="https://avatars.githubusercontent.com/u/119487588?v=4?s=100" width="100px;" alt="xingshuaiLi"/><br /><sub><b>xingshuaiLi</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=xingshuaiLi" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wangke6666"><img src="https://avatars.githubusercontent.com/u/113656595?v=4?s=100" width="100px;" alt="wangke6666"/><br /><sub><b>wangke6666</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=wangke6666" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/LWBobo"><img src="https://avatars.githubusercontent.com/u/50368698?v=4?s=100" width="100px;" alt="刺猬"/><br /><sub><b>刺猬</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/issues?q=author%3ALWBobo" title="Bug reports">🐛</a> <a href="https://github.com/apache/hertzbeat/commits?author=LWBobo" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.zanglikun.com"><img src="https://avatars.githubusercontent.com/u/61591648?v=4?s=100" width="100px;" alt="Haste"/><br /><sub><b>Haste</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=zanglikun" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/SuitSmile"><img src="https://avatars.githubusercontent.com/u/38679717?v=4?s=100" width="100px;" alt="zhongshi.yi"/><br /><sub><b>zhongshi.yi</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=SuitSmile" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://www.smallq.cn"><img src="https://avatars.githubusercontent.com/u/39754275?v=4?s=100" width="100px;" alt="Qi Zhang"/><br /><sub><b>Qi Zhang</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=zzzhangqi" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MrAndyMing"><img src="https://avatars.githubusercontent.com/u/49541483?v=4?s=100" width="100px;" alt="MrAndyMing"/><br /><sub><b>MrAndyMing</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=MrAndyMing" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://idongliming.github.io/"><img src="https://avatars.githubusercontent.com/u/31564353?v=4?s=100" width="100px;" alt="idongliming"/><br /><sub><b>idongliming</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=idongliming" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://earthjasonlin.github.io"><img src="https://avatars.githubusercontent.com/u/83632110?v=4?s=100" width="100px;" alt="Zichao Lin"/><br /><sub><b>Zichao Lin</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=earthjasonlin" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=earthjasonlin" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://blog.liudonghua.com"><img src="https://avatars.githubusercontent.com/u/2276718?v=4?s=100" width="100px;" alt="liudonghua"/><br /><sub><b>liudonghua</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=liudonghua123" title="Code">💻</a> <a href="#ideas-liudonghua123" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/orangeyts"><img src="https://avatars.githubusercontent.com/u/4250869?v=4?s=100" width="100px;" alt="Jerry"/><br /><sub><b>Jerry</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=orangeyts" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=orangeyts" title="Tests">⚠️</a> <a href="#ideas-orangeyts" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://dynamictp.cn"><img src="https://avatars.githubusercontent.com/u/13051908?v=4?s=100" width="100px;" alt="yanhom"/><br /><sub><b>yanhom</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=yanhom1314" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.smallq.cn"><img src="https://avatars.githubusercontent.com/u/39754275?v=4?s=100" width="100px;" alt="Qi Zhang"/><br /><sub><b>Qi Zhang</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=zzzhangqi" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MrAndyMing"><img src="https://avatars.githubusercontent.com/u/49541483?v=4?s=100" width="100px;" alt="MrAndyMing"/><br /><sub><b>MrAndyMing</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=MrAndyMing" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://idongliming.github.io/"><img src="https://avatars.githubusercontent.com/u/31564353?v=4?s=100" width="100px;" alt="idongliming"/><br /><sub><b>idongliming</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=idongliming" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://earthjasonlin.github.io"><img src="https://avatars.githubusercontent.com/u/83632110?v=4?s=100" width="100px;" alt="Zichao Lin"/><br /><sub><b>Zichao Lin</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=earthjasonlin" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=earthjasonlin" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://blog.liudonghua.com"><img src="https://avatars.githubusercontent.com/u/2276718?v=4?s=100" width="100px;" alt="liudonghua"/><br /><sub><b>liudonghua</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=liudonghua123" title="Code">💻</a> <a href="#ideas-liudonghua123" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/orangeyts"><img src="https://avatars.githubusercontent.com/u/4250869?v=4?s=100" width="100px;" alt="Jerry"/><br /><sub><b>Jerry</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=orangeyts" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=orangeyts" title="Tests">⚠️</a> <a href="#ideas-orangeyts" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://dynamictp.cn"><img src="https://avatars.githubusercontent.com/u/13051908?v=4?s=100" width="100px;" alt="yanhom"/><br /><sub><b>yanhom</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=yanhom1314" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://www.jianshu.com/u/a8f822c04f67"><img src="https://avatars.githubusercontent.com/u/18587688?v=4?s=100" width="100px;" alt="fsl"/><br /><sub><b>fsl</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=fengshunli" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xttttv"><img src="https://avatars.githubusercontent.com/u/116323904?v=4?s=100" width="100px;" alt="xttttv"/><br /><sub><b>xttttv</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=xttttv" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/NavinKumarBarnwal"><img src="https://avatars.githubusercontent.com/u/44504274?v=4?s=100" width="100px;" alt="NavinKumarBarnwal"/><br /><sub><b>NavinKumarBarnwal</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=NavinKumarBarnwal" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/z641205699"><img src="https://avatars.githubusercontent.com/u/45276423?v=4?s=100" width="100px;" alt="Zakkary"/><br /><sub><b>Zakkary</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=z641205699" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/898349230"><img src="https://avatars.githubusercontent.com/u/21972532?v=4?s=100" width="100px;" alt="sunxinbo"/><br /><sub><b>sunxinbo</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=898349230" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=898349230" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ldzbook"><img src="https://avatars.githubusercontent.com/u/13903790?v=4?s=100" width="100px;" alt="ldzbook"/><br /><sub><b>ldzbook</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=ldzbook" title="Documentation">📖</a> <a href="https://github.com/dromara/hertzbeat/issues?q=author%3Aldzbook" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/SurryChen"><img src="https://avatars.githubusercontent.com/u/91116490?v=4?s=100" width="100px;" alt="余与雨"/><br /><sub><b>余与雨</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=SurryChen" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=SurryChen" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.jianshu.com/u/a8f822c04f67"><img src="https://avatars.githubusercontent.com/u/18587688?v=4?s=100" width="100px;" alt="fsl"/><br /><sub><b>fsl</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=fengshunli" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xttttv"><img src="https://avatars.githubusercontent.com/u/116323904?v=4?s=100" width="100px;" alt="xttttv"/><br /><sub><b>xttttv</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=xttttv" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/NavinKumarBarnwal"><img src="https://avatars.githubusercontent.com/u/44504274?v=4?s=100" width="100px;" alt="NavinKumarBarnwal"/><br /><sub><b>NavinKumarBarnwal</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=NavinKumarBarnwal" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/z641205699"><img src="https://avatars.githubusercontent.com/u/45276423?v=4?s=100" width="100px;" alt="Zakkary"/><br /><sub><b>Zakkary</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=z641205699" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/898349230"><img src="https://avatars.githubusercontent.com/u/21972532?v=4?s=100" width="100px;" alt="sunxinbo"/><br /><sub><b>sunxinbo</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=898349230" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=898349230" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ldzbook"><img src="https://avatars.githubusercontent.com/u/13903790?v=4?s=100" width="100px;" alt="ldzbook"/><br /><sub><b>ldzbook</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ldzbook" title="Documentation">📖</a> <a href="https://github.com/apache/hertzbeat/issues?q=author%3Aldzbook" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/SurryChen"><img src="https://avatars.githubusercontent.com/u/91116490?v=4?s=100" width="100px;" alt="余与雨"/><br /><sub><b>余与雨</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=SurryChen" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=SurryChen" title="Tests">⚠️</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MysticalDream"><img src="https://avatars.githubusercontent.com/u/78899028?v=4?s=100" width="100px;" alt="MysticalDream"/><br /><sub><b>MysticalDream</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=MysticalDream" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=MysticalDream" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zhouyoulin12"><img src="https://avatars.githubusercontent.com/u/17086633?v=4?s=100" width="100px;" alt="zhouyoulin12"/><br /><sub><b>zhouyoulin12</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=zhouyoulin12" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=zhouyoulin12" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jerjjj"><img src="https://avatars.githubusercontent.com/u/93431283?v=4?s=100" width="100px;" alt="jerjjj"/><br /><sub><b>jerjjj</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=jerjjj" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://wjl110.xyz/"><img src="https://avatars.githubusercontent.com/u/53851034?v=4?s=100" width="100px;" alt="wjl110"/><br /><sub><b>wjl110</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=wjl110" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ngyhd"><img src="https://avatars.githubusercontent.com/u/29095207?v=4?s=100" width="100px;" alt="Sean"/><br /><sub><b>Sean</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=ngyhd" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Daydreamer-ia"><img src="https://avatars.githubusercontent.com/u/83362909?v=4?s=100" width="100px;" alt="chenyiqin"/><br /><sub><b>chenyiqin</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=Daydreamer-ia" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=Daydreamer-ia" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hudongdong129"><img src="https://avatars.githubusercontent.com/u/34374227?v=4?s=100" width="100px;" alt="hudongdong129"/><br /><sub><b>hudongdong129</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=hudongdong129" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=hudongdong129" title="Tests">⚠️</a> <a href="https://github.com/dromara/hertzbeat/commits?author=hudongdong129" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MysticalDream"><img src="https://avatars.githubusercontent.com/u/78899028?v=4?s=100" width="100px;" alt="MysticalDream"/><br /><sub><b>MysticalDream</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=MysticalDream" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=MysticalDream" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zhouyoulin12"><img src="https://avatars.githubusercontent.com/u/17086633?v=4?s=100" width="100px;" alt="zhouyoulin12"/><br /><sub><b>zhouyoulin12</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=zhouyoulin12" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=zhouyoulin12" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jerjjj"><img src="https://avatars.githubusercontent.com/u/93431283?v=4?s=100" width="100px;" alt="jerjjj"/><br /><sub><b>jerjjj</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=jerjjj" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://wjl110.xyz/"><img src="https://avatars.githubusercontent.com/u/53851034?v=4?s=100" width="100px;" alt="wjl110"/><br /><sub><b>wjl110</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=wjl110" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ngyhd"><img src="https://avatars.githubusercontent.com/u/29095207?v=4?s=100" width="100px;" alt="Sean"/><br /><sub><b>Sean</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ngyhd" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Daydreamer-ia"><img src="https://avatars.githubusercontent.com/u/83362909?v=4?s=100" width="100px;" alt="chenyiqin"/><br /><sub><b>chenyiqin</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Daydreamer-ia" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=Daydreamer-ia" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hudongdong129"><img src="https://avatars.githubusercontent.com/u/34374227?v=4?s=100" width="100px;" alt="hudongdong129"/><br /><sub><b>hudongdong129</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=hudongdong129" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=hudongdong129" title="Tests">⚠️</a> <a href="https://github.com/apache/hertzbeat/commits?author=hudongdong129" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/TherChenYang"><img src="https://avatars.githubusercontent.com/u/124348939?v=4?s=100" width="100px;" alt="TherChenYang"/><br /><sub><b>TherChenYang</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=TherChenYang" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=TherChenYang" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/HattoriHenzo"><img src="https://avatars.githubusercontent.com/u/5141285?v=4?s=100" width="100px;" alt="HattoriHenzo"/><br /><sub><b>HattoriHenzo</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=HattoriHenzo" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=HattoriHenzo" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ycilry"><img src="https://avatars.githubusercontent.com/u/63967101?v=4?s=100" width="100px;" alt="ycilry"/><br /><sub><b>ycilry</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=ycilry" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/aoshiguchen"><img src="https://avatars.githubusercontent.com/u/10580997?v=4?s=100" width="100px;" alt="aoshiguchen"/><br /><sub><b>aoshiguchen</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=aoshiguchen" title="Documentation">📖</a> <a href="https://github.com/dromara/hertzbeat/commits?author=aoshiguchen" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/caibenxiang"><img src="https://avatars.githubusercontent.com/u/4568241?v=4?s=100" width="100px;" alt="蔡本祥"/><br /><sub><b>蔡本祥</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=caibenxiang" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.fckeverything.cn:4000/"><img src="https://avatars.githubusercontent.com/u/13827124?v=4?s=100" width="100px;" alt="浮游"/><br /><sub><b>浮游</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=lifefloating" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Grass-Life"><img src="https://avatars.githubusercontent.com/u/114381513?v=4?s=100" width="100px;" alt="Grass-Life"/><br /><sub><b>Grass-Life</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=Grass-Life" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/TherChenYang"><img src="https://avatars.githubusercontent.com/u/124348939?v=4?s=100" width="100px;" alt="TherChenYang"/><br /><sub><b>TherChenYang</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=TherChenYang" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=TherChenYang" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/HattoriHenzo"><img src="https://avatars.githubusercontent.com/u/5141285?v=4?s=100" width="100px;" alt="HattoriHenzo"/><br /><sub><b>HattoriHenzo</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=HattoriHenzo" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=HattoriHenzo" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ycilry"><img src="https://avatars.githubusercontent.com/u/63967101?v=4?s=100" width="100px;" alt="ycilry"/><br /><sub><b>ycilry</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ycilry" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/aoshiguchen"><img src="https://avatars.githubusercontent.com/u/10580997?v=4?s=100" width="100px;" alt="aoshiguchen"/><br /><sub><b>aoshiguchen</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=aoshiguchen" title="Documentation">📖</a> <a href="https://github.com/apache/hertzbeat/commits?author=aoshiguchen" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/caibenxiang"><img src="https://avatars.githubusercontent.com/u/4568241?v=4?s=100" width="100px;" alt="蔡本祥"/><br /><sub><b>蔡本祥</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=caibenxiang" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.fckeverything.cn:4000/"><img src="https://avatars.githubusercontent.com/u/13827124?v=4?s=100" width="100px;" alt="浮游"/><br /><sub><b>浮游</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=lifefloating" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Grass-Life"><img src="https://avatars.githubusercontent.com/u/114381513?v=4?s=100" width="100px;" alt="Grass-Life"/><br /><sub><b>Grass-Life</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Grass-Life" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xiaohe428"><img src="https://avatars.githubusercontent.com/u/99130317?v=4?s=100" width="100px;" alt="xiaohe428"/><br /><sub><b>xiaohe428</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=xiaohe428" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=xiaohe428" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/baiban114"><img src="https://avatars.githubusercontent.com/u/59152619?v=4?s=100" width="100px;" alt="TableRow"/><br /><sub><b>TableRow</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=baiban114" title="Documentation">📖</a> <a href="https://github.com/dromara/hertzbeat/commits?author=baiban114" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ByteIDance"><img src="https://avatars.githubusercontent.com/u/100207562?v=4?s=100" width="100px;" alt="ByteIDance"/><br /><sub><b>ByteIDance</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=ByteIDance" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mangel2002"><img src="https://avatars.githubusercontent.com/u/9348020?v=4?s=100" width="100px;" alt="Jangfe"/><br /><sub><b>Jangfe</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=mangel2002" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zqr10159"><img src="https://avatars.githubusercontent.com/u/30048352?v=4?s=100" width="100px;" alt="zqr10159"/><br /><sub><b>zqr10159</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=zqr10159" title="Documentation">📖</a> <a href="https://github.com/dromara/hertzbeat/commits?author=zqr10159" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/vinci-897"><img src="https://avatars.githubusercontent.com/u/55838224?v=4?s=100" width="100px;" alt="vinci"/><br /><sub><b>vinci</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=vinci-897" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=vinci-897" title="Documentation">📖</a> <a href="#design-vinci-897" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/js110"><img src="https://avatars.githubusercontent.com/u/51191863?v=4?s=100" width="100px;" alt="js110"/><br /><sub><b>js110</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=js110" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xiaohe428"><img src="https://avatars.githubusercontent.com/u/99130317?v=4?s=100" width="100px;" alt="xiaohe428"/><br /><sub><b>xiaohe428</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=xiaohe428" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=xiaohe428" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/baiban114"><img src="https://avatars.githubusercontent.com/u/59152619?v=4?s=100" width="100px;" alt="TableRow"/><br /><sub><b>TableRow</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=baiban114" title="Documentation">📖</a> <a href="https://github.com/apache/hertzbeat/commits?author=baiban114" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ByteIDance"><img src="https://avatars.githubusercontent.com/u/100207562?v=4?s=100" width="100px;" alt="ByteIDance"/><br /><sub><b>ByteIDance</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ByteIDance" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mangel2002"><img src="https://avatars.githubusercontent.com/u/9348020?v=4?s=100" width="100px;" alt="Jangfe"/><br /><sub><b>Jangfe</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=mangel2002" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zqr10159"><img src="https://avatars.githubusercontent.com/u/30048352?v=4?s=100" width="100px;" alt="zqr10159"/><br /><sub><b>zqr10159</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=zqr10159" title="Documentation">📖</a> <a href="https://github.com/apache/hertzbeat/commits?author=zqr10159" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/vinci-897"><img src="https://avatars.githubusercontent.com/u/55838224?v=4?s=100" width="100px;" alt="vinci"/><br /><sub><b>vinci</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=vinci-897" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=vinci-897" title="Documentation">📖</a> <a href="#design-vinci-897" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/js110"><img src="https://avatars.githubusercontent.com/u/51191863?v=4?s=100" width="100px;" alt="js110"/><br /><sub><b>js110</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=js110" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/JavaLionLi"><img src="https://avatars.githubusercontent.com/u/31852897?v=4?s=100" width="100px;" alt="CrazyLionLi"/><br /><sub><b>CrazyLionLi</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=JavaLionLi" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.banmajio.com"><img src="https://avatars.githubusercontent.com/u/53471385?v=4?s=100" width="100px;" alt="banmajio"/><br /><sub><b>banmajio</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=banmajio" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://suder.fun"><img src="https://avatars.githubusercontent.com/u/69955165?v=4?s=100" width="100px;" alt="topsuder"/><br /><sub><b>topsuder</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=topsuder" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/richar2022"><img src="https://avatars.githubusercontent.com/u/129016397?v=4?s=100" width="100px;" alt="richar2022"/><br /><sub><b>richar2022</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=richar2022" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/fcb-xiaobo"><img src="https://avatars.githubusercontent.com/u/60566194?v=4?s=100" width="100px;" alt="fcb-xiaobo"/><br /><sub><b>fcb-xiaobo</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=fcb-xiaobo" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wenkyzhang"><img src="https://avatars.githubusercontent.com/u/13983669?v=4?s=100" width="100px;" alt="wenkyzhang"/><br /><sub><b>wenkyzhang</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=wenkyzhang" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ZangJuxy"><img src="https://avatars.githubusercontent.com/u/71380295?v=4?s=100" width="100px;" alt="ZangJuxy"/><br /><sub><b>ZangJuxy</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=ZangJuxy" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/JavaLionLi"><img src="https://avatars.githubusercontent.com/u/31852897?v=4?s=100" width="100px;" alt="CrazyLionLi"/><br /><sub><b>CrazyLionLi</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=JavaLionLi" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.banmajio.com"><img src="https://avatars.githubusercontent.com/u/53471385?v=4?s=100" width="100px;" alt="banmajio"/><br /><sub><b>banmajio</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=banmajio" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://suder.fun"><img src="https://avatars.githubusercontent.com/u/69955165?v=4?s=100" width="100px;" alt="topsuder"/><br /><sub><b>topsuder</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=topsuder" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/richar2022"><img src="https://avatars.githubusercontent.com/u/129016397?v=4?s=100" width="100px;" alt="richar2022"/><br /><sub><b>richar2022</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=richar2022" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/fcb-xiaobo"><img src="https://avatars.githubusercontent.com/u/60566194?v=4?s=100" width="100px;" alt="fcb-xiaobo"/><br /><sub><b>fcb-xiaobo</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=fcb-xiaobo" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wenkyzhang"><img src="https://avatars.githubusercontent.com/u/13983669?v=4?s=100" width="100px;" alt="wenkyzhang"/><br /><sub><b>wenkyzhang</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=wenkyzhang" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ZangJuxy"><img src="https://avatars.githubusercontent.com/u/71380295?v=4?s=100" width="100px;" alt="ZangJuxy"/><br /><sub><b>ZangJuxy</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ZangJuxy" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/l646505418"><img src="https://avatars.githubusercontent.com/u/50475131?v=4?s=100" width="100px;" alt="l646505418"/><br /><sub><b>l646505418</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=l646505418" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.carpewang.com"><img src="https://avatars.githubusercontent.com/u/78642589?v=4?s=100" width="100px;" alt="Carpe-Wang"/><br /><sub><b>Carpe-Wang</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=Carpe-Wang" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/moshu023"><img src="https://avatars.githubusercontent.com/u/48593205?v=4?s=100" width="100px;" alt="莫枢"/><br /><sub><b>莫枢</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=moshu023" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/huangcanda"><img src="https://avatars.githubusercontent.com/u/4470566?v=4?s=100" width="100px;" alt="huangcanda"/><br /><sub><b>huangcanda</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=huangcanda" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.zrkizzy.com"><img src="https://avatars.githubusercontent.com/u/85340613?v=4?s=100" width="100px;" alt="世纪末的架构师"/><br /><sub><b>世纪末的架构师</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=Architect-Java" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ShuningWan"><img src="https://avatars.githubusercontent.com/u/31086770?v=4?s=100" width="100px;" alt="ShuningWan"/><br /><sub><b>ShuningWan</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=ShuningWan" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MrYZhou"><img src="https://avatars.githubusercontent.com/u/44339602?v=4?s=100" width="100px;" alt="MrYZhou"/><br /><sub><b>MrYZhou</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=MrYZhou" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/l646505418"><img src="https://avatars.githubusercontent.com/u/50475131?v=4?s=100" width="100px;" alt="l646505418"/><br /><sub><b>l646505418</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=l646505418" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.carpewang.com"><img src="https://avatars.githubusercontent.com/u/78642589?v=4?s=100" width="100px;" alt="Carpe-Wang"/><br /><sub><b>Carpe-Wang</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Carpe-Wang" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/moshu023"><img src="https://avatars.githubusercontent.com/u/48593205?v=4?s=100" width="100px;" alt="莫枢"/><br /><sub><b>莫枢</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=moshu023" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/huangcanda"><img src="https://avatars.githubusercontent.com/u/4470566?v=4?s=100" width="100px;" alt="huangcanda"/><br /><sub><b>huangcanda</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=huangcanda" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.zrkizzy.com"><img src="https://avatars.githubusercontent.com/u/85340613?v=4?s=100" width="100px;" alt="世纪末的架构师"/><br /><sub><b>世纪末的架构师</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Architect-Java" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ShuningWan"><img src="https://avatars.githubusercontent.com/u/31086770?v=4?s=100" width="100px;" alt="ShuningWan"/><br /><sub><b>ShuningWan</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ShuningWan" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MrYZhou"><img src="https://avatars.githubusercontent.com/u/44339602?v=4?s=100" width="100px;" alt="MrYZhou"/><br /><sub><b>MrYZhou</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=MrYZhou" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/suncqujsj"><img src="https://avatars.githubusercontent.com/u/8012932?v=4?s=100" width="100px;" alt="suncqujsj"/><br /><sub><b>suncqujsj</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=suncqujsj" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sunqinbo"><img src="https://avatars.githubusercontent.com/u/1428540?v=4?s=100" width="100px;" alt="sunqinbo"/><br /><sub><b>sunqinbo</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=sunqinbo" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/haoww"><img src="https://avatars.githubusercontent.com/u/32739294?v=4?s=100" width="100px;" alt="haoww"/><br /><sub><b>haoww</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=haoww" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/i-mayuan"><img src="https://avatars.githubusercontent.com/u/101498477?v=4?s=100" width="100px;" alt="i-mayuan"/><br /><sub><b>i-mayuan</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=i-mayuan" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/fengruge"><img src="https://avatars.githubusercontent.com/u/85803831?v=4?s=100" width="100px;" alt="fengruge"/><br /><sub><b>fengruge</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=fengruge" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/aystzh"><img src="https://avatars.githubusercontent.com/u/38125392?v=4?s=100" width="100px;" alt="zhanghuan"/><br /><sub><b>zhanghuan</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=aystzh" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/shenyumin"><img src="https://avatars.githubusercontent.com/u/8438506?v=4?s=100" width="100px;" alt="shenymin"/><br /><sub><b>shenymin</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=shenyumin" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/suncqujsj"><img src="https://avatars.githubusercontent.com/u/8012932?v=4?s=100" width="100px;" alt="suncqujsj"/><br /><sub><b>suncqujsj</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=suncqujsj" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sunqinbo"><img src="https://avatars.githubusercontent.com/u/1428540?v=4?s=100" width="100px;" alt="sunqinbo"/><br /><sub><b>sunqinbo</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=sunqinbo" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/haoww"><img src="https://avatars.githubusercontent.com/u/32739294?v=4?s=100" width="100px;" alt="haoww"/><br /><sub><b>haoww</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=haoww" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/i-mayuan"><img src="https://avatars.githubusercontent.com/u/101498477?v=4?s=100" width="100px;" alt="i-mayuan"/><br /><sub><b>i-mayuan</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=i-mayuan" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/fengruge"><img src="https://avatars.githubusercontent.com/u/85803831?v=4?s=100" width="100px;" alt="fengruge"/><br /><sub><b>fengruge</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=fengruge" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/aystzh"><img src="https://avatars.githubusercontent.com/u/38125392?v=4?s=100" width="100px;" alt="zhanghuan"/><br /><sub><b>zhanghuan</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=aystzh" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/shenyumin"><img src="https://avatars.githubusercontent.com/u/8438506?v=4?s=100" width="100px;" alt="shenymin"/><br /><sub><b>shenymin</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=shenyumin" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/dhruva1995"><img src="https://avatars.githubusercontent.com/u/12976351?v=4?s=100" width="100px;" alt="Dhruva Chandra"/><br /><sub><b>Dhruva Chandra</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=dhruva1995" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/weiwang988"><img src="https://avatars.githubusercontent.com/u/58241726?v=4?s=100" width="100px;" alt="miss_z"/><br /><sub><b>miss_z</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=weiwang988" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wyt990"><img src="https://avatars.githubusercontent.com/u/86013697?v=4?s=100" width="100px;" alt="wyt990"/><br /><sub><b>wyt990</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=wyt990" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/licocon"><img src="https://avatars.githubusercontent.com/u/36863277?v=4?s=100" width="100px;" alt="licocon"/><br /><sub><b>licocon</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=licocon" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/2406450951"><img src="https://avatars.githubusercontent.com/u/48074721?v=4?s=100" width="100px;" alt="Mi Na"/><br /><sub><b>Mi Na</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=2406450951" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Kylin-Guo"><img src="https://avatars.githubusercontent.com/u/131239856?v=4?s=100" width="100px;" alt="Kylin-Guo"/><br /><sub><b>Kylin-Guo</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=Kylin-Guo" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/1797899698"><img src="https://avatars.githubusercontent.com/u/40411650?v=4?s=100" width="100px;" alt="Mr灬Dong先生"/><br /><sub><b>Mr灬Dong先生</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=1797899698" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/dhruva1995"><img src="https://avatars.githubusercontent.com/u/12976351?v=4?s=100" width="100px;" alt="Dhruva Chandra"/><br /><sub><b>Dhruva Chandra</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=dhruva1995" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/weiwang988"><img src="https://avatars.githubusercontent.com/u/58241726?v=4?s=100" width="100px;" alt="miss_z"/><br /><sub><b>miss_z</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=weiwang988" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wyt990"><img src="https://avatars.githubusercontent.com/u/86013697?v=4?s=100" width="100px;" alt="wyt990"/><br /><sub><b>wyt990</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=wyt990" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/licocon"><img src="https://avatars.githubusercontent.com/u/36863277?v=4?s=100" width="100px;" alt="licocon"/><br /><sub><b>licocon</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=licocon" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/2406450951"><img src="https://avatars.githubusercontent.com/u/48074721?v=4?s=100" width="100px;" alt="Mi Na"/><br /><sub><b>Mi Na</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=2406450951" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Kylin-Guo"><img src="https://avatars.githubusercontent.com/u/131239856?v=4?s=100" width="100px;" alt="Kylin-Guo"/><br /><sub><b>Kylin-Guo</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Kylin-Guo" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/1797899698"><img src="https://avatars.githubusercontent.com/u/40411650?v=4?s=100" width="100px;" alt="Mr灬Dong先生"/><br /><sub><b>Mr灬Dong先生</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=1797899698" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="http://neilblaze.live"><img src="https://avatars.githubusercontent.com/u/48355572?v=4?s=100" width="100px;" alt="Pratyay Banerjee"/><br /><sub><b>Pratyay Banerjee</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=Neilblaze" title="Documentation">📖</a> <a href="https://github.com/dromara/hertzbeat/commits?author=Neilblaze" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yujianzhong520"><img src="https://avatars.githubusercontent.com/u/63705063?v=4?s=100" width="100px;" alt="yujianzhong520"/><br /><sub><b>yujianzhong520</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=yujianzhong520" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://sppan24.github.io/"><img src="https://avatars.githubusercontent.com/u/15795173?v=4?s=100" width="100px;" alt="SPPan"/><br /><sub><b>SPPan</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=sppan24" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/1130600015"><img src="https://avatars.githubusercontent.com/u/67859663?v=4?s=100" width="100px;" alt="ZhangJiashu"/><br /><sub><b>ZhangJiashu</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=1130600015" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/QZmp236478"><img src="https://avatars.githubusercontent.com/u/56623162?v=4?s=100" width="100px;" alt="impress"/><br /><sub><b>impress</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=QZmp236478" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jx3775250"><img src="https://avatars.githubusercontent.com/u/40455946?v=4?s=100" width="100px;" alt="凌晨一点半"/><br /><sub><b>凌晨一点半</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=jx3775250" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/eeshaanSA"><img src="https://avatars.githubusercontent.com/u/100678386?v=4?s=100" width="100px;" alt="Eeshaan Sawant"/><br /><sub><b>Eeshaan Sawant</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=eeshaanSA" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://neilblaze.live"><img src="https://avatars.githubusercontent.com/u/48355572?v=4?s=100" width="100px;" alt="Pratyay Banerjee"/><br /><sub><b>Pratyay Banerjee</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Neilblaze" title="Documentation">📖</a> <a href="https://github.com/apache/hertzbeat/commits?author=Neilblaze" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yujianzhong520"><img src="https://avatars.githubusercontent.com/u/63705063?v=4?s=100" width="100px;" alt="yujianzhong520"/><br /><sub><b>yujianzhong520</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=yujianzhong520" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://sppan24.github.io/"><img src="https://avatars.githubusercontent.com/u/15795173?v=4?s=100" width="100px;" alt="SPPan"/><br /><sub><b>SPPan</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=sppan24" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/1130600015"><img src="https://avatars.githubusercontent.com/u/67859663?v=4?s=100" width="100px;" alt="ZhangJiashu"/><br /><sub><b>ZhangJiashu</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=1130600015" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/QZmp236478"><img src="https://avatars.githubusercontent.com/u/56623162?v=4?s=100" width="100px;" alt="impress"/><br /><sub><b>impress</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=QZmp236478" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jx3775250"><img src="https://avatars.githubusercontent.com/u/40455946?v=4?s=100" width="100px;" alt="凌晨一点半"/><br /><sub><b>凌晨一点半</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=jx3775250" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/eeshaanSA"><img src="https://avatars.githubusercontent.com/u/100678386?v=4?s=100" width="100px;" alt="Eeshaan Sawant"/><br /><sub><b>Eeshaan Sawant</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=eeshaanSA" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/nandofromthebando"><img src="https://avatars.githubusercontent.com/u/87321214?v=4?s=100" width="100px;" alt="nandofromthebando"/><br /><sub><b>nandofromthebando</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=nandofromthebando" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/caiboking"><img src="https://avatars.githubusercontent.com/u/6509883?v=4?s=100" width="100px;" alt="caiboking"/><br /><sub><b>caiboking</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=caiboking" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/baixing99"><img src="https://avatars.githubusercontent.com/u/73473087?v=4?s=100" width="100px;" alt="baixing99"/><br /><sub><b>baixing99</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=baixing99" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ifrenzyc"><img src="https://avatars.githubusercontent.com/u/543927?v=4?s=100" width="100px;" alt="Yang Chuang"/><br /><sub><b>Yang Chuang</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=ifrenzyc" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wlin20"><img src="https://avatars.githubusercontent.com/u/20657577?v=4?s=100" width="100px;" alt="wlin20"/><br /><sub><b>wlin20</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=wlin20" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/guojing1983"><img src="https://avatars.githubusercontent.com/u/60596094?v=4?s=100" width="100px;" alt="guojing1983"/><br /><sub><b>guojing1983</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=guojing1983" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/itxxq"><img src="https://avatars.githubusercontent.com/u/46962357?v=4?s=100" width="100px;" alt="moxi"/><br /><sub><b>moxi</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=itxxq" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/nandofromthebando"><img src="https://avatars.githubusercontent.com/u/87321214?v=4?s=100" width="100px;" alt="nandofromthebando"/><br /><sub><b>nandofromthebando</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=nandofromthebando" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/caiboking"><img src="https://avatars.githubusercontent.com/u/6509883?v=4?s=100" width="100px;" alt="caiboking"/><br /><sub><b>caiboking</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=caiboking" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/baixing99"><img src="https://avatars.githubusercontent.com/u/73473087?v=4?s=100" width="100px;" alt="baixing99"/><br /><sub><b>baixing99</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=baixing99" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ifrenzyc"><img src="https://avatars.githubusercontent.com/u/543927?v=4?s=100" width="100px;" alt="Yang Chuang"/><br /><sub><b>Yang Chuang</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ifrenzyc" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wlin20"><img src="https://avatars.githubusercontent.com/u/20657577?v=4?s=100" width="100px;" alt="wlin20"/><br /><sub><b>wlin20</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=wlin20" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/guojing1983"><img src="https://avatars.githubusercontent.com/u/60596094?v=4?s=100" width="100px;" alt="guojing1983"/><br /><sub><b>guojing1983</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=guojing1983" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/itxxq"><img src="https://avatars.githubusercontent.com/u/46962357?v=4?s=100" width="100px;" alt="moxi"/><br /><sub><b>moxi</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=itxxq" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/qq471754603"><img src="https://avatars.githubusercontent.com/u/23146592?v=4?s=100" width="100px;" alt="qq471754603"/><br /><sub><b>qq471754603</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=qq471754603" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/san346596324"><img src="https://avatars.githubusercontent.com/u/30828520?v=4?s=100" width="100px;" alt="渭雨"/><br /><sub><b>渭雨</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=san346596324" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/luoxuanzao"><img src="https://avatars.githubusercontent.com/u/44692579?v=4?s=100" width="100px;" alt="liuxuezhuo"/><br /><sub><b>liuxuezhuo</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=luoxuanzao" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lisongning"><img src="https://avatars.githubusercontent.com/u/93140178?v=4?s=100" width="100px;" alt="lisongning"/><br /><sub><b>lisongning</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=lisongning" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/YutingNie"><img src="https://avatars.githubusercontent.com/u/104416402?v=4?s=100" width="100px;" alt="YutingNie"/><br /><sub><b>YutingNie</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=YutingNie" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=YutingNie" title="Documentation">📖</a> <a href="#design-YutingNie" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mikezzb"><img src="https://avatars.githubusercontent.com/u/23418428?v=4?s=100" width="100px;" alt="Mike Zhou"/><br /><sub><b>Mike Zhou</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=mikezzb" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=mikezzb" title="Documentation">📖</a> <a href="#design-mikezzb" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/a-little-fool"><img src="https://avatars.githubusercontent.com/u/105542329?v=4?s=100" width="100px;" alt="小笨蛋"/><br /><sub><b>小笨蛋</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=a-little-fool" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/qq471754603"><img src="https://avatars.githubusercontent.com/u/23146592?v=4?s=100" width="100px;" alt="qq471754603"/><br /><sub><b>qq471754603</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=qq471754603" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/san346596324"><img src="https://avatars.githubusercontent.com/u/30828520?v=4?s=100" width="100px;" alt="渭雨"/><br /><sub><b>渭雨</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=san346596324" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/luoxuanzao"><img src="https://avatars.githubusercontent.com/u/44692579?v=4?s=100" width="100px;" alt="liuxuezhuo"/><br /><sub><b>liuxuezhuo</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=luoxuanzao" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lisongning"><img src="https://avatars.githubusercontent.com/u/93140178?v=4?s=100" width="100px;" alt="lisongning"/><br /><sub><b>lisongning</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=lisongning" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/YutingNie"><img src="https://avatars.githubusercontent.com/u/104416402?v=4?s=100" width="100px;" alt="YutingNie"/><br /><sub><b>YutingNie</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=YutingNie" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=YutingNie" title="Documentation">📖</a> <a href="#design-YutingNie" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mikezzb"><img src="https://avatars.githubusercontent.com/u/23418428?v=4?s=100" width="100px;" alt="Mike Zhou"/><br /><sub><b>Mike Zhou</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=mikezzb" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=mikezzb" title="Documentation">📖</a> <a href="#design-mikezzb" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/a-little-fool"><img src="https://avatars.githubusercontent.com/u/105542329?v=4?s=100" width="100px;" alt="小笨蛋"/><br /><sub><b>小笨蛋</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=a-little-fool" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/littlezhongzer"><img src="https://avatars.githubusercontent.com/u/33685289?v=4?s=100" width="100px;" alt="littlezhongzer"/><br /><sub><b>littlezhongzer</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=littlezhongzer" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ChenXiangxxxxx"><img src="https://avatars.githubusercontent.com/u/90089594?v=4?s=100" width="100px;" alt="ChenXiangxxxxx"/><br /><sub><b>ChenXiangxxxxx</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=ChenXiangxxxxx" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Mr-zhou315"><img src="https://avatars.githubusercontent.com/u/10276100?v=4?s=100" width="100px;" alt="Mr.zhou"/><br /><sub><b>Mr.zhou</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=Mr-zhou315" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/XimfengYao"><img src="https://avatars.githubusercontent.com/u/17541537?v=4?s=100" width="100px;" alt="姚贤丰"/><br /><sub><b>姚贤丰</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=XimfengYao" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/LINGLUOJUN"><img src="https://avatars.githubusercontent.com/u/16778977?v=4?s=100" width="100px;" alt="lingluojun"/><br /><sub><b>lingluojun</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=LINGLUOJUN" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.luelueking.com"><img src="https://avatars.githubusercontent.com/u/93204032?v=4?s=100" width="100px;" alt="1ue"/><br /><sub><b>1ue</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=luelueking" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.jimmyqiao.top"><img src="https://avatars.githubusercontent.com/u/67301054?v=4?s=100" width="100px;" alt="qyaaaa"/><br /><sub><b>qyaaaa</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=qyaaaa" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/littlezhongzer"><img src="https://avatars.githubusercontent.com/u/33685289?v=4?s=100" width="100px;" alt="littlezhongzer"/><br /><sub><b>littlezhongzer</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=littlezhongzer" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ChenXiangxxxxx"><img src="https://avatars.githubusercontent.com/u/90089594?v=4?s=100" width="100px;" alt="ChenXiangxxxxx"/><br /><sub><b>ChenXiangxxxxx</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ChenXiangxxxxx" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Mr-zhou315"><img src="https://avatars.githubusercontent.com/u/10276100?v=4?s=100" width="100px;" alt="Mr.zhou"/><br /><sub><b>Mr.zhou</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Mr-zhou315" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/XimfengYao"><img src="https://avatars.githubusercontent.com/u/17541537?v=4?s=100" width="100px;" alt="姚贤丰"/><br /><sub><b>姚贤丰</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=XimfengYao" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/LINGLUOJUN"><img src="https://avatars.githubusercontent.com/u/16778977?v=4?s=100" width="100px;" alt="lingluojun"/><br /><sub><b>lingluojun</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=LINGLUOJUN" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.luelueking.com"><img src="https://avatars.githubusercontent.com/u/93204032?v=4?s=100" width="100px;" alt="1ue"/><br /><sub><b>1ue</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=luelueking" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.jimmyqiao.top"><img src="https://avatars.githubusercontent.com/u/67301054?v=4?s=100" width="100px;" alt="qyaaaa"/><br /><sub><b>qyaaaa</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=qyaaaa" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://novohit.top"><img src="https://avatars.githubusercontent.com/u/101090395?v=4?s=100" width="100px;" alt="novohit"/><br /><sub><b>novohit</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=novohit" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/rbsrcy"><img src="https://avatars.githubusercontent.com/u/4798540?v=4?s=100" width="100px;" alt="zhuoshangyi"/><br /><sub><b>zhuoshangyi</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=rbsrcy" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ruanliang-hualun"><img src="https://avatars.githubusercontent.com/u/65543716?v=4?s=100" width="100px;" alt="ruanliang"/><br /><sub><b>ruanliang</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=ruanliang-hualun" title="Documentation">📖</a> <a href="https://github.com/dromara/hertzbeat/commits?author=ruanliang-hualun" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Eden4701"><img src="https://avatars.githubusercontent.com/u/68422437?v=4?s=100" width="100px;" alt="Eden4701"/><br /><sub><b>Eden4701</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=Eden4701" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=Eden4701" title="Documentation">📖</a> <a href="#design-Eden4701" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/XiaTian688"><img src="https://avatars.githubusercontent.com/u/111830921?v=4?s=100" width="100px;" alt="XiaTian688"/><br /><sub><b>XiaTian688</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=XiaTian688" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/liyin"><img src="https://avatars.githubusercontent.com/u/863169?v=4?s=100" width="100px;" alt="liyinjiang"/><br /><sub><b>liyinjiang</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=liyin" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jiashu1024"><img src="https://avatars.githubusercontent.com/u/67859663?v=4?s=100" width="100px;" alt="ZhangJiashu"/><br /><sub><b>ZhangJiashu</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=jiashu1024" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://novohit.top"><img src="https://avatars.githubusercontent.com/u/101090395?v=4?s=100" width="100px;" alt="novohit"/><br /><sub><b>novohit</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=novohit" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/rbsrcy"><img src="https://avatars.githubusercontent.com/u/4798540?v=4?s=100" width="100px;" alt="zhuoshangyi"/><br /><sub><b>zhuoshangyi</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=rbsrcy" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ruanliang-hualun"><img src="https://avatars.githubusercontent.com/u/65543716?v=4?s=100" width="100px;" alt="ruanliang"/><br /><sub><b>ruanliang</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ruanliang-hualun" title="Documentation">📖</a> <a href="https://github.com/apache/hertzbeat/commits?author=ruanliang-hualun" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Eden4701"><img src="https://avatars.githubusercontent.com/u/68422437?v=4?s=100" width="100px;" alt="Eden4701"/><br /><sub><b>Eden4701</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Eden4701" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=Eden4701" title="Documentation">📖</a> <a href="#design-Eden4701" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/XiaTian688"><img src="https://avatars.githubusercontent.com/u/111830921?v=4?s=100" width="100px;" alt="XiaTian688"/><br /><sub><b>XiaTian688</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=XiaTian688" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/liyin"><img src="https://avatars.githubusercontent.com/u/863169?v=4?s=100" width="100px;" alt="liyinjiang"/><br /><sub><b>liyinjiang</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=liyin" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jiashu1024"><img src="https://avatars.githubusercontent.com/u/67859663?v=4?s=100" width="100px;" alt="ZhangJiashu"/><br /><sub><b>ZhangJiashu</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=jiashu1024" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/1036664317"><img src="https://avatars.githubusercontent.com/u/7696697?v=4?s=100" width="100px;" alt="moghn"/><br /><sub><b>moghn</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=1036664317" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xiaoguolong"><img src="https://avatars.githubusercontent.com/u/33684988?v=4?s=100" width="100px;" alt="xiaoguolong"/><br /><sub><b>xiaoguolong</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=xiaoguolong" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Clownsw"><img src="https://avatars.githubusercontent.com/u/28394742?v=4?s=100" width="100px;" alt="Smliexx"/><br /><sub><b>Smliexx</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=Clownsw" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Calvin979"><img src="https://avatars.githubusercontent.com/u/131688897?v=4?s=100" width="100px;" alt="Naruse"/><br /><sub><b>Naruse</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=Calvin979" title="Documentation">📖</a> <a href="https://github.com/dromara/hertzbeat/commits?author=Calvin979" title="Code">💻</a> <a href="#design-Calvin979" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bbelide2"><img src="https://avatars.githubusercontent.com/u/26840796?v=4?s=100" width="100px;" alt="Bala Sukesh"/><br /><sub><b>Bala Sukesh</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=bbelide2" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jinyaoMa"><img src="https://avatars.githubusercontent.com/u/25066570?v=4?s=100" width="100px;" alt="Jinyao Ma"/><br /><sub><b>Jinyao Ma</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=jinyaoMa" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://linuxsuren.github.io/open-source-best-practice/"><img src="https://avatars.githubusercontent.com/u/1450685?v=4?s=100" width="100px;" alt="Rick"/><br /><sub><b>Rick</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=LinuxSuRen" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=LinuxSuRen" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/1036664317"><img src="https://avatars.githubusercontent.com/u/7696697?v=4?s=100" width="100px;" alt="moghn"/><br /><sub><b>moghn</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=1036664317" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xiaoguolong"><img src="https://avatars.githubusercontent.com/u/33684988?v=4?s=100" width="100px;" alt="xiaoguolong"/><br /><sub><b>xiaoguolong</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=xiaoguolong" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Clownsw"><img src="https://avatars.githubusercontent.com/u/28394742?v=4?s=100" width="100px;" alt="Smliexx"/><br /><sub><b>Smliexx</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Clownsw" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Calvin979"><img src="https://avatars.githubusercontent.com/u/131688897?v=4?s=100" width="100px;" alt="Naruse"/><br /><sub><b>Naruse</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Calvin979" title="Documentation">📖</a> <a href="https://github.com/apache/hertzbeat/commits?author=Calvin979" title="Code">💻</a> <a href="#design-Calvin979" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bbelide2"><img src="https://avatars.githubusercontent.com/u/26840796?v=4?s=100" width="100px;" alt="Bala Sukesh"/><br /><sub><b>Bala Sukesh</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=bbelide2" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jinyaoMa"><img src="https://avatars.githubusercontent.com/u/25066570?v=4?s=100" width="100px;" alt="Jinyao Ma"/><br /><sub><b>Jinyao Ma</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=jinyaoMa" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://linuxsuren.github.io/open-source-best-practice/"><img src="https://avatars.githubusercontent.com/u/1450685?v=4?s=100" width="100px;" alt="Rick"/><br /><sub><b>Rick</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=LinuxSuRen" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=LinuxSuRen" title="Tests">⚠️</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ZY945"><img src="https://avatars.githubusercontent.com/u/74083801?v=4?s=100" width="100px;" alt="东风"/><br /><sub><b>东风</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=ZY945" title="Code">💻</a> <a href="#design-ZY945" title="Design">🎨</a> <a href="https://github.com/dromara/hertzbeat/commits?author=ZY945" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/prolevel1"><img src="https://avatars.githubusercontent.com/u/51995525?v=4?s=100" width="100px;" alt="sonam singh"/><br /><sub><b>sonam singh</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=prolevel1" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ZhangZixuan1994"><img src="https://avatars.githubusercontent.com/u/20011653?v=4?s=100" width="100px;" alt="ZhangZixuan1994"/><br /><sub><b>ZhangZixuan1994</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=ZhangZixuan1994" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hurenjie1"><img src="https://avatars.githubusercontent.com/u/40120355?v=4?s=100" width="100px;" alt="SHIG"/><br /><sub><b>SHIG</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=hurenjie1" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://tslj1024.github.io/"><img src="https://avatars.githubusercontent.com/u/155222677?v=4?s=100" width="100px;" alt="泰上老菌"/><br /><sub><b>泰上老菌</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=tslj1024" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ldysdu"><img src="https://avatars.githubusercontent.com/u/15815338?v=4?s=100" width="100px;" alt="ldysdu"/><br /><sub><b>ldysdu</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=ldysdu" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/GEM0816g"><img src="https://avatars.githubusercontent.com/u/85116017?v=4?s=100" width="100px;" alt="梁同学"/><br /><sub><b>梁同学</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=GEM0816g" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ZY945"><img src="https://avatars.githubusercontent.com/u/74083801?v=4?s=100" width="100px;" alt="东风"/><br /><sub><b>东风</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ZY945" title="Code">💻</a> <a href="#design-ZY945" title="Design">🎨</a> <a href="https://github.com/apache/hertzbeat/commits?author=ZY945" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/prolevel1"><img src="https://avatars.githubusercontent.com/u/51995525?v=4?s=100" width="100px;" alt="sonam singh"/><br /><sub><b>sonam singh</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=prolevel1" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ZhangZixuan1994"><img src="https://avatars.githubusercontent.com/u/20011653?v=4?s=100" width="100px;" alt="ZhangZixuan1994"/><br /><sub><b>ZhangZixuan1994</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ZhangZixuan1994" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hurenjie1"><img src="https://avatars.githubusercontent.com/u/40120355?v=4?s=100" width="100px;" alt="SHIG"/><br /><sub><b>SHIG</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=hurenjie1" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://tslj1024.github.io/"><img src="https://avatars.githubusercontent.com/u/155222677?v=4?s=100" width="100px;" alt="泰上老菌"/><br /><sub><b>泰上老菌</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=tslj1024" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ldysdu"><img src="https://avatars.githubusercontent.com/u/15815338?v=4?s=100" width="100px;" alt="ldysdu"/><br /><sub><b>ldysdu</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ldysdu" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/GEM0816g"><img src="https://avatars.githubusercontent.com/u/85116017?v=4?s=100" width="100px;" alt="梁同学"/><br /><sub><b>梁同学</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=GEM0816g" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/avvCode"><img src="https://avatars.githubusercontent.com/u/113538532?v=4?s=100" width="100px;" alt="avv"/><br /><sub><b>avv</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=avvCode" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yqxxgh"><img src="https://avatars.githubusercontent.com/u/42080876?v=4?s=100" width="100px;" alt="yqxxgh"/><br /><sub><b>yqxxgh</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=yqxxgh" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/CharlieShi46"><img src="https://avatars.githubusercontent.com/u/149798885?v=4?s=100" width="100px;" alt="CharlieShi46"/><br /><sub><b>CharlieShi46</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=CharlieShi46" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Nctllnty"><img src="https://avatars.githubusercontent.com/u/33241818?v=4?s=100" width="100px;" alt="Nctllnty"/><br /><sub><b>Nctllnty</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=Nctllnty" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Wang-Yonghao"><img src="https://avatars.githubusercontent.com/u/48146606?v=4?s=100" width="100px;" alt="Wang-Yonghao"/><br /><sub><b>Wang-Yonghao</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=Wang-Yonghao" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.yuque.com/dudiao/yy"><img src="https://avatars.githubusercontent.com/u/38355949?v=4?s=100" width="100px;" alt="读钓"/><br /><sub><b>读钓</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=dudiao" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/starmilkxin"><img src="https://avatars.githubusercontent.com/u/55646681?v=4?s=100" width="100px;" alt="Xin"/><br /><sub><b>Xin</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=starmilkxin" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/avvCode"><img src="https://avatars.githubusercontent.com/u/113538532?v=4?s=100" width="100px;" alt="avv"/><br /><sub><b>avv</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=avvCode" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yqxxgh"><img src="https://avatars.githubusercontent.com/u/42080876?v=4?s=100" width="100px;" alt="yqxxgh"/><br /><sub><b>yqxxgh</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=yqxxgh" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/CharlieShi46"><img src="https://avatars.githubusercontent.com/u/149798885?v=4?s=100" width="100px;" alt="CharlieShi46"/><br /><sub><b>CharlieShi46</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=CharlieShi46" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Nctllnty"><img src="https://avatars.githubusercontent.com/u/33241818?v=4?s=100" width="100px;" alt="Nctllnty"/><br /><sub><b>Nctllnty</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Nctllnty" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Wang-Yonghao"><img src="https://avatars.githubusercontent.com/u/48146606?v=4?s=100" width="100px;" alt="Wang-Yonghao"/><br /><sub><b>Wang-Yonghao</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Wang-Yonghao" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.yuque.com/dudiao/yy"><img src="https://avatars.githubusercontent.com/u/38355949?v=4?s=100" width="100px;" alt="读钓"/><br /><sub><b>读钓</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=dudiao" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/starmilkxin"><img src="https://avatars.githubusercontent.com/u/55646681?v=4?s=100" width="100px;" alt="Xin"/><br /><sub><b>Xin</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=starmilkxin" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/handy-git"><img src="https://avatars.githubusercontent.com/u/32837980?v=4?s=100" width="100px;" alt="handy"/><br /><sub><b>handy</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=handy-git" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/handy-git"><img src="https://avatars.githubusercontent.com/u/32837980?v=4?s=100" width="100px;" alt="handy"/><br /><sub><b>handy</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=handy-git" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/LiuTianyou"><img src="https://avatars.githubusercontent.com/u/30208283?v=4?s=100" width="100px;" alt="LiuTianyou"/><br /><sub><b>LiuTianyou</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=LiuTianyou" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=LiuTianyou" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/WinterKi1ler"><img src="https://avatars.githubusercontent.com/u/160592092?v=4?s=100" width="100px;" alt="WinterKi1ler"/><br /><sub><b>WinterKi1ler</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=WinterKi1ler" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://sharehoo.cn/"><img src="https://avatars.githubusercontent.com/u/45377370?v=4?s=100" width="100px;" alt="miki"/><br /><sub><b>miki</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=miki-hmt" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://codeflex.substack.com/"><img src="https://avatars.githubusercontent.com/u/85513042?v=4?s=100" width="100px;" alt="Keshav Carpenter"/><br /><sub><b>Keshav Carpenter</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=alpha951" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=alpha951" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/makechoicenow"><img src="https://avatars.githubusercontent.com/u/9911918?v=4?s=100" width="100px;" alt="makechoicenow"/><br /><sub><b>makechoicenow</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=makechoicenow" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/gjjjj0101"><img src="https://avatars.githubusercontent.com/u/71874373?v=4?s=100" width="100px;" alt="Gao Jian"/><br /><sub><b>Gao Jian</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=gjjjj0101" title="Code">💻</a> <a href="#design-gjjjj0101" title="Design">🎨</a> <a href="https://github.com/apache/hertzbeat/commits?author=gjjjj0101" title="Tests">⚠️</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://jangto.tistory.com/"><img src="https://avatars.githubusercontent.com/u/37864182?v=4?s=100" width="100px;" alt="Hyeon Sung"/><br /><sub><b>Hyeon Sung</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=dukbong" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://crossoverjie.top/"><img src="https://avatars.githubusercontent.com/u/15684156?v=4?s=100" width="100px;" alt="crossoverJie"/><br /><sub><b>crossoverJie</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=crossoverJie" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=crossoverJie" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/PeixyJ"><img src="https://avatars.githubusercontent.com/u/45998593?v=4?s=100" width="100px;" alt="PeixyJ"/><br /><sub><b>PeixyJ</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=PeixyJ" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Hi-Mr-Wind"><img src="https://avatars.githubusercontent.com/u/85803831?v=4?s=100" width="100px;" alt="风如歌"/><br /><sub><b>风如歌</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Hi-Mr-Wind" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MananPoojara"><img src="https://avatars.githubusercontent.com/u/104253184?v=4?s=100" width="100px;" alt="Manan Pujara"/><br /><sub><b>Manan Pujara</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=MananPoojara" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xuziyang"><img src="https://avatars.githubusercontent.com/u/8465969?v=4?s=100" width="100px;" alt="xuziyang"/><br /><sub><b>xuziyang</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=xuziyang" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lwqzz"><img src="https://avatars.githubusercontent.com/u/62584513?v=4?s=100" width="100px;" alt="lwqzz"/><br /><sub><b>lwqzz</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=lwqzz" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/YxYL6125"><img src="https://avatars.githubusercontent.com/u/91076160?v=4?s=100" width="100px;" alt="YxYL"/><br /><sub><b>YxYL</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=YxYL6125" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/tomorrowshipyltm"><img src="https://avatars.githubusercontent.com/u/61336903?v=4?s=100" width="100px;" alt="tomorrowshipyltm"/><br /><sub><b>tomorrowshipyltm</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=tomorrowshipyltm" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/15613060203"><img src="https://avatars.githubusercontent.com/u/41351615?v=4?s=100" width="100px;" alt="栗磊"/><br /><sub><b>栗磊</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=15613060203" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Alanxtl"><img src="https://avatars.githubusercontent.com/u/25652981?v=4?s=100" width="100px;" alt="Alan"/><br /><sub><b>Alan</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Alanxtl" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.hadoop.wiki/"><img src="https://avatars.githubusercontent.com/u/29418975?v=4?s=100" width="100px;" alt="Jast"/><br /><sub><b>Jast</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=zhangshenghang" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zuobiao-zhou"><img src="https://avatars.githubusercontent.com/u/61108539?v=4?s=100" width="100px;" alt="Zhang Yuxuan"/><br /><sub><b>Zhang Yuxuan</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=zuobiao-zhou" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Pzz-2021"><img src="https://avatars.githubusercontent.com/u/118056735?v=4?s=100" width="100px;" alt="P.P."/><br /><sub><b>P.P.</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Pzz-2021" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/LLP2333"><img src="https://avatars.githubusercontent.com/u/61670545?v=4?s=100" width="100px;" alt="llp2333"/><br /><sub><b>llp2333</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=LLP2333" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/HeartLinked"><img src="https://avatars.githubusercontent.com/u/78212101?v=4?s=100" width="100px;" alt="feiyang li"/><br /><sub><b>feiyang li</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=HeartLinked" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Aias00"><img src="https://avatars.githubusercontent.com/u/25810623?v=4?s=100" width="100px;" alt="aias00"/><br /><sub><b>aias00</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Aias00" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/westboy"><img src="https://avatars.githubusercontent.com/u/6385565?v=4?s=100" width="100px;" alt="Jin"/><br /><sub><b>Jin</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=westboy" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://blog.csdn.net/qq_52397471"><img src="https://avatars.githubusercontent.com/u/77964041?v=4?s=100" width="100px;" alt="YuLuo"/><br /><sub><b>YuLuo</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=yuluo-yx" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Yanshuming1"><img src="https://avatars.githubusercontent.com/u/118667222?v=4?s=100" width="100px;" alt="linDong"/><br /><sub><b>linDong</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Yanshuming1" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lwjxy"><img src="https://avatars.githubusercontent.com/u/52726400?v=4?s=100" width="100px;" alt="lwjxy"/><br /><sub><b>lwjxy</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=lwjxy" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://thespica.github.io/"><img src="https://avatars.githubusercontent.com/u/119573640?v=4?s=100" width="100px;" alt="John"/><br /><sub><b>John</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Thespica" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=Thespica" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/boatrainlsz"><img src="https://avatars.githubusercontent.com/u/18243785?v=4?s=100" width="100px;" alt="boatrainlsz"/><br /><sub><b>boatrainlsz</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=boatrainlsz" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.yitianyigexiangfa.com/"><img src="https://avatars.githubusercontent.com/u/3973419?v=4?s=100" width="100px;" alt="Bill Lau"/><br /><sub><b>Bill Lau</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=JavaProgrammerLB" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lw-yang"><img src="https://avatars.githubusercontent.com/u/23456873?v=4?s=100" width="100px;" alt="lwyang"/><br /><sub><b>lwyang</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=lw-yang" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xfl12345"><img src="https://avatars.githubusercontent.com/u/17960863?v=4?s=100" width="100px;" alt="xfl12345"/><br /><sub><b>xfl12345</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=xfl12345" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yykaue"><img src="https://avatars.githubusercontent.com/u/22905143?v=4?s=100" width="100px;" alt="Limbo"/><br /><sub><b>Limbo</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=yykaue" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/irenhongyan"><img src="https://avatars.githubusercontent.com/u/53438321?v=4?s=100" width="100px;" alt="哈哈哈哈哈哈哈哈哈"/><br /><sub><b>哈哈哈哈哈哈哈哈哈</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=irenhongyan" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ileonli"><img src="https://avatars.githubusercontent.com/u/45332412?v=4?s=100" width="100px;" alt="Leon Li"/><br /><sub><b>Leon Li</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ileonli" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://fnil.net/"><img src="https://avatars.githubusercontent.com/u/14142?v=4?s=100" width="100px;" alt="dennis zhuang"/><br /><sub><b>dennis zhuang</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=killme2008" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/kerwin612"><img src="https://avatars.githubusercontent.com/u/3371163?v=4?s=100" width="100px;" alt="Kerwin Bryant"/><br /><sub><b>Kerwin Bryant</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=kerwin612" title="Code">💻</a> <a href="#design-kerwin612" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ShineDevelopment"><img src="https://avatars.githubusercontent.com/u/59306780?v=4?s=100" width="100px;" alt="daixianglong"/><br /><sub><b>daixianglong</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ShineDevelopment" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mchgood"><img src="https://avatars.githubusercontent.com/u/38482005?v=4?s=100" width="100px;" alt="mchgood"/><br /><sub><b>mchgood</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=mchgood" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/pwallk"><img src="https://avatars.githubusercontent.com/u/69385076?v=4?s=100" width="100px;" alt="kangli"/><br /><sub><b>kangli</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=pwallk" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/cdphantom"><img src="https://avatars.githubusercontent.com/u/12674795?v=4?s=100" width="100px;" alt="cdphantom"/><br /><sub><b>cdphantom</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=cdphantom" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/asd108908382"><img src="https://avatars.githubusercontent.com/u/77717999?v=4?s=100" width="100px;" alt="jiawei.guo"/><br /><sub><b>jiawei.guo</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=asd108908382" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/QBH-insist"><img src="https://avatars.githubusercontent.com/u/39401478?v=4?s=100" width="100px;" alt="QBH-insist"/><br /><sub><b>QBH-insist</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=QBH-insist" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jiangsh-ui"><img src="https://avatars.githubusercontent.com/u/86990361?v=4?s=100" width="100px;" alt="jiangsh"/><br /><sub><b>jiangsh</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=jiangsh-ui" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/keaifafafa"><img src="https://avatars.githubusercontent.com/u/83876361?v=4?s=100" width="100px;" alt="Keaifa"/><br /><sub><b>Keaifa</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=keaifafafa" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/loong95"><img src="https://avatars.githubusercontent.com/u/16333958?v=4?s=100" width="100px;" alt="Loong"/><br /><sub><b>Loong</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=loong95" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ceekay47"><img src="https://avatars.githubusercontent.com/u/104664857?v=4?s=100" width="100px;" alt="Chandrakant Vankayalapati"/><br /><sub><b>Chandrakant Vankayalapati</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ceekay47" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MRgenial"><img src="https://avatars.githubusercontent.com/u/49973336?v=4?s=100" width="100px;" alt="b_mountain"/><br /><sub><b>b_mountain</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=MRgenial" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/TemirlanBasitov"><img src="https://avatars.githubusercontent.com/u/57500808?v=4?s=100" width="100px;" alt="TemirlanBasitov"/><br /><sub><b>TemirlanBasitov</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=TemirlanBasitov" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wyfvsfy"><img src="https://avatars.githubusercontent.com/u/11973517?v=4?s=100" width="100px;" alt="wyfvsfy"/><br /><sub><b>wyfvsfy</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=wyfvsfy" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sherry-peng2333"><img src="https://avatars.githubusercontent.com/u/70619577?v=4?s=100" width="100px;" alt="sherry-peng2333"/><br /><sub><b>sherry-peng2333</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=sherry-peng2333" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lixiaobaivv"><img src="https://avatars.githubusercontent.com/u/39290771?v=4?s=100" width="100px;" alt="Yzzz"/><br /><sub><b>Yzzz</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=lixiaobaivv" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.bckf.cn/"><img src="https://avatars.githubusercontent.com/u/13309008?v=4?s=100" width="100px;" alt="puruidong"/><br /><sub><b>puruidong</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=pruidong" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/shinestare"><img src="https://avatars.githubusercontent.com/u/13570619?v=4?s=100" width="100px;" alt="shinestare"/><br /><sub><b>shinestare</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=shinestare" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/po-168"><img src="https://avatars.githubusercontent.com/u/185745593?v=4?s=100" width="100px;" alt="po-168"/><br /><sub><b>po-168</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=po-168" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/All-The-Best-for"><img src="https://avatars.githubusercontent.com/u/76414672?v=4?s=100" width="100px;" alt="wbs99"/><br /><sub><b>wbs99</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=All-The-Best-for" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/starryCoder"><img src="https://avatars.githubusercontent.com/u/46510059?v=4?s=100" width="100px;" alt="starryCoder"/><br /><sub><b>starryCoder</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=starryCoder" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hasimmollah"><img src="https://avatars.githubusercontent.com/u/32538599?v=4?s=100" width="100px;" alt="hasimmollah"/><br /><sub><b>hasimmollah</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=hasimmollah" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ayu-v0"><img src="https://avatars.githubusercontent.com/u/127600988?v=4?s=100" width="100px;" alt="Ayu"/><br /><sub><b>Ayu</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ayu-v0" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Rancho-7"><img src="https://avatars.githubusercontent.com/u/59016860?v=4?s=100" width="100px;" alt="Nick Guo"/><br /><sub><b>Nick Guo</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Rancho-7" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/doveLin0818"><img src="https://avatars.githubusercontent.com/u/190927907?v=4?s=100" width="100px;" alt="doveLin"/><br /><sub><b>doveLin</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=doveLin0818" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://zzrl.cc/"><img src="https://avatars.githubusercontent.com/u/91836599?v=4?s=100" width="100px;" alt="yunfan24"/><br /><sub><b>yunfan24</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=yunfan24" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lctking"><img src="https://avatars.githubusercontent.com/u/168249998?v=4?s=100" width="100px;" alt="nullwli"/><br /><sub><b>nullwli</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=lctking" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://simonsigre.com/"><img src="https://avatars.githubusercontent.com/u/14932913?v=4?s=100" width="100px;" alt="Simon Sigré"/><br /><sub><b>Simon Sigré</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=simonsigre" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.ponfee.cn/"><img src="https://avatars.githubusercontent.com/u/46117331?v=4?s=100" width="100px;" alt="ponfee"/><br /><sub><b>ponfee</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ponfee" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Vedant7789"><img src="https://avatars.githubusercontent.com/u/147625492?v=4?s=100" width="100px;" alt="Vedant7789"/><br /><sub><b>Vedant7789</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Vedant7789" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Craaaaazy77"><img src="https://avatars.githubusercontent.com/u/23025522?v=4?s=100" width="100px;" alt="Craaaaazy77"/><br /><sub><b>Craaaaazy77</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Craaaaazy77" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Suvrat1629"><img src="https://avatars.githubusercontent.com/u/140749446?v=4?s=100" width="100px;" alt="Suvrat1629"/><br /><sub><b>Suvrat1629</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Suvrat1629" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://ghyghoo8.github.io/"><img src="https://avatars.githubusercontent.com/u/363129?v=4?s=100" width="100px;" alt="ghy"/><br /><sub><b>ghy</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ghyghoo8" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/helei1030"><img src="https://avatars.githubusercontent.com/u/11839080?v=4?s=100" width="100px;" alt="helei1030"/><br /><sub><b>helei1030</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=helei1030" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://medium.com/@pjfanning"><img src="https://avatars.githubusercontent.com/u/11783444?v=4?s=100" width="100px;" alt="PJ Fanning"/><br /><sub><b>PJ Fanning</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=pjfanning" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MonsterChenzhuo"><img src="https://avatars.githubusercontent.com/u/60029759?v=4?s=100" width="100px;" alt="monster"/><br /><sub><b>monster</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=MonsterChenzhuo" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MasamiYui"><img src="https://avatars.githubusercontent.com/u/22274133?v=4?s=100" width="100px;" alt="Sherlock Yin"/><br /><sub><b>Sherlock Yin</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=MasamiYui" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wanhao23"><img src="https://avatars.githubusercontent.com/u/29560961?v=4?s=100" width="100px;" alt="wanhao"/><br /><sub><b>wanhao</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=wanhao23" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=wanhao23" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jonasHanhan"><img src="https://avatars.githubusercontent.com/u/130035609?v=4?s=100" width="100px;" alt="jonasHanhan"/><br /><sub><b>jonasHanhan</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=jonasHanhan" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/NikhilMurugesan"><img src="https://avatars.githubusercontent.com/u/49281792?v=4?s=100" width="100px;" alt="NikhilMurugesan"/><br /><sub><b>NikhilMurugesan</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=NikhilMurugesan" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/myangle1120"><img src="https://avatars.githubusercontent.com/u/19237013?v=4?s=100" width="100px;" alt="myangle1120"/><br /><sub><b>myangle1120</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=myangle1120" title="Code">💻</a></td>
</tr>
</tbody>
</table>
@@ -420,19 +516,21 @@ Thanks to these wonderful people, welcome to join us:
<!-- ALL-CONTRIBUTORS-LIST:END -->
## 💬 Join discussion
HertzBeat is a top project under the [Dromara Open Source Community](https://dromara.org/). Gitee GVP.
## 💬 Join discussion
##### Channel
**[Chat On Discord](https://discord.gg/Fb6M73htGr)**
[Join the Mailing Lists](https://lists.apache.org/list.html?dev@hertzbeat.apache.org) : Mail to `dev-subscribe@hertzbeat.apache.org` to subscribe mailing lists.
**WeChat Group** : Add friend `tan-cloud` and will invite you to the group.
[Chat On Discord](https://discord.gg/Fb6M73htGr)
[QQ Group](https://jq.qq.com/?_wv=1027&k=Bud9OzdI) : Group num `236915833`
WeChat Group : Add friend `ahertzbeat` and invite to the group.
[Github Discussion](https://github.com/dromara/hertzbeat/discussions)
WeChat Public : Search ID `usthecom`.
[QQ Group](https://jq.qq.com/?_wv=1027&k=Bud9OzdI) : Group num `630061200`
[Github Discussion](https://github.com/apache/hertzbeat/discussions)
[Reddit Community](https://www.reddit.com/r/hertzbeat/)
@@ -440,27 +538,11 @@ HertzBeat is a top project under the [Dromara Open Source Community](https://dro
[Subscribe YouTube](https://www.youtube.com/channel/UCri75zfWX0GHqJFPENEbLow)
##### Friends
- [Sa-Token](https://github.com/dromara/Sa-Token) : 一个轻量级 java 权限认证框架,让鉴权变得简单、优雅
- [DynamicTp](https://github.com/dromara/dynamic-tp) : 轻量级动态线程池,内置监控告警功能,集成三方中间件线程池管理,基于主流配置中心
- [Hippo4j](https://github.com/opengoofy/hippo4j/) : 强大的动态线程池框架,附带监控报警功能
- [Jpom](https://gitee.com/dromara/Jpom) : 简而轻的低侵入式在线构建、自动部署、日常运维、项目监控软件
- [ArgusDBM](https://github.com/zmops/ArgusDBM) : 开源数据库一体化监控平台,致力于监控所有数据库
- [WangMarket](http://www.wang.market/) : 开源 SAAS 云建站系统
- [API Testing](https://github.com/LinuxSuRen/api-testing):轻量级、可扩展的接口开发、测试工具
##### Sponsor
- Thanks [吉实信息(构建全新的微波+光交易网络)](https://www.flarespeed.com) sponsored server node.
##### Open-Source Project Build From Open-Source
HertzBeat is built on so many great open source projects, thanks to them!
- `Java Spring SpringBoot Jpa Maven Assembly Netty Lombok Sureness Aviator Protobuf HttpClient Guava SnakeYaml JsonPath ...`
- `Java Spring SpringBoot Jpa Maven Assembly Netty Lombok Sureness Protobuf HttpClient Guava SnakeYaml JsonPath ...`
- `TypeScript Angular NG-ZORRO NG-ALAIN NodeJs Npm Html Less Echarts Rxjs ZoneJs MonacoEditor SlickCarousel Docusaurus ...`
## Landscape
@@ -472,11 +554,5 @@ HertzBeat has been included in the <a href="https://landscape.cncf.io/guide?item
CNCF Observability And Analysis - Monitoring Landscape.</a>
</p>
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=dromara/hertzbeat&type=Date)](https://star-history.com/#dromara/hertzbeat&Date)
## 🛡️ License
[`Apache License, Version 2.0`](https://www.apache.org/licenses/LICENSE-2.0.html)
+360 -280
View File
@@ -1,35 +1,37 @@
<p align="center">
<a href="https://hertzbeat.com">
<img alt="hertzbeat" src="https://cdn.jsdelivr.net/gh/dromara/hertzbeat/home/static/img/hertzbeat-brand.svg" width="260">
<a href="https://hertzbeat.apache.org">
<img alt="hertzbeat" src="/home/static/img/hertzbeat-brand.svg" width="260">
</a>
</p>
[comment]: <> (<img alt="sureness" src="https://cdn.jsdelivr.net/gh/dromara/hertzbeat/home/static/img/hertzbeat-brand.svg" width="300">)
<h4 align="center">
<a href="README_CN.md">中文文档</a> | <a href="README.md">English Document</a>
</h4>
## HertzBeat 赫兹跳动 | [English Documentation](README.md)
> 实时监控系统,无需Agent,性能集群,兼容Prometheus,自定义监控和状态页构建能力。
> 实时监控系统,无需 Agent,性能集群,兼容 Prometheus,自定义监控和状态页构建能力。
[![Discord](https://img.shields.io/badge/Chat-Discord-7289DA?logo=discord)](https://discord.gg/Fb6M73htGr)
[![Reddit](https://img.shields.io/badge/Reddit-Community-7289DA?logo=reddit)](https://www.reddit.com/r/hertzbeat/)
[![Twitter](https://img.shields.io/twitter/follow/hertzbeat1024?logo=twitter)](https://twitter.com/hertzbeat1024)
[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/8139/badge)](https://www.bestpractices.dev/projects/8139)
[![Docker Pulls](https://img.shields.io/docker/pulls/tancloud/hertzbeat?style=%20for-the-badge&logo=docker&label=DockerHub%20Download)](https://hub.docker.com/repository/docker/tancloud/hertzbeat/general)
[![codecov](https://codecov.io/gh/apache/HertzBeat/branch/master/graph/badge.svg)](https://app.codecov.io/gh/apache/hertzbeat)
[![Docker Pulls](https://img.shields.io/docker/pulls/apache/hertzbeat?style=%20for-the-badge&logo=docker&label=DockerHub%20Download)](https://hub.docker.com/r/apache/hertzbeat)
[![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/hertzbeat)](https://artifacthub.io/packages/search?repo=hertzbeat)
[![QQ](https://img.shields.io/badge/qq-236915833-orange)](https://jq.qq.com/?_wv=1027&k=aVIVB2K9)
[![YouTube Channel Subscribers](https://img.shields.io/youtube/channel/subscribers/UCri75zfWX0GHqJFPENEbLow?logo=youtube&label=YouTube%20Channel)](https://www.youtube.com/channel/UCri75zfWX0GHqJFPENEbLow)
[![Contribute with Gitpod](https://img.shields.io/badge/Contribute%20with-Gitpod-908a85?logo=gitpod&color=green)](https://gitpod.io/#https://github.com/apache/hertzbeat)
**官网: [hertzbeat.dromara.org](https://hertzbeat.dromara.org) 全球网络 | [hertzbeat.com](https://hertzbeat.com) 中国网络**
**官网: [hertzbeat.apache.org](https://hertzbeat.apache.org)**
**邮件: <a href="mailto:dev-subscribe@hertzbeat.apache.org">发送至 ```dev-subscribe@hertzbeat.apache.org```</a>** 订阅邮件列表
## 🎡 <font color="green">介绍</font>
[HertzBeat 赫兹跳动](https://github.com/dromara/hertzbeat) 是一个易用友好的开源实时监控告警系统,无需 Agent,高性能集群,兼容 Prometheus,提供强大的自定义监控和状态页构建能力。
[Apache HertzBeat](https://github.com/apache/hertzbeat) incubating是一个易用友好的开源实时监控告警系统,无需 Agent,高性能集群,兼容 Prometheus,提供强大的自定义监控和状态页构建能力。
### 特点
-**监控+告警+通知** 为一体,支持对应用服务,应用程序,数据库,缓存,操作系统,大数据,中间件,Web服务器,云原生,网络,自定义等监控阈值告警通知一步到位。
-**监控+告警+通知** 为一体,支持对应用服务,应用程序,数据库,缓存,操作系统,大数据,中间件,Web 服务器,云原生,网络,自定义等监控阈值告警通知一步到位。
- 易用友好,无需 `Agent`,全 `WEB` 页面操作,鼠标点一点就能监控告警,零上手学习成本。
-`Http, Jmx, Ssh, Snmp, Jdbc, Prometheus` 等协议规范可配置化,只需在浏览器配置监控模版 `YML` 就能使用这些协议去自定义采集想要的指标。您相信只需配置下就能立刻适配一款 `K8s``Docker` 等新的监控类型吗?
- 兼容 `Prometheus` 的系统生态并且更多,只需页面操作就可以监控 `Prometheus` 所能监控的。
@@ -40,7 +42,7 @@
> `HertzBeat`的强大自定义,多类型支持,高性能,易扩展,低耦合,希望能帮助用户快速搭建自有监控系统。
----
----
![hertzbeat](home/static/img/home/1.png)
@@ -48,7 +50,7 @@
![hertzbeat](home/static/img/home/9.png)
----
----
## 🥐 模块
@@ -56,88 +58,88 @@
## ⛄ 已支持
> 我们将监控采集类型(mysql,jvm,k8s)都定义为yml监控模版,用户可以导入这些模版来支持对应类型的监控!
> 我们将监控采集类型mysql,jvm,k8s都定义为 `yml` 监控模版,用户可以导入这些模版来支持对应类型的监控!
> 欢迎大家一起贡献你使用过程中自定义的通用监控类型监控模版。
- [Website](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-website.yml), [Port Telnet](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-port.yml),
[Http Api](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-api.yml), [Ping Connect](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-ping.yml),
[Jvm](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-jvm.yml), [SiteMap](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-fullsite.yml),
[Ssl Certificate](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-ssl_cert.yml), [SpringBoot2](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-springboot2.yml),
[FTP Server](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-ftp.yml), [SpringBoot3](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-springboot3.yml),
[Udp Port](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-udp.yml), [Dns](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-dns.yml),
[Pop3](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-pop3.yml), [Ntp](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-ntp.yml),
[Api Code](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-api_code.yml), [Smtp](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-smtp.yml),
[Nginx](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-nginx.yml)
- [Mysql](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-mysql.yml), [PostgreSQL](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-postgresql.yml),
[MariaDB](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-mariadb.yml), [Redis](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-redis.yml),
[ElasticSearch](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-elasticsearch.yml), [SqlServer](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-sqlserver.yml),
[Oracle](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-oracle.yml), [MongoDB](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-mongodb.yml),
[DM](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-dm.yml), [OpenGauss](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-opengauss.yml),
[ClickHouse](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-clickhouse.yml), [IoTDB](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-iotdb.yml),
[Redis Cluster](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-redis_cluster.yml), [Redis Sentinel](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-redis_sentinel.yml)
[Doris BE](https://github.com/dromara/hertzbeat/blob/master/manager/src/main/resources/define/app-doris_be.yml), [Doris FE](https://github.com/dromara/hertzbeat/blob/master/manager/src/main/resources/define/app-doris_fe.yml),
[Memcached](https://github.com/dromara/hertzbeat/blob/master/manager/src/main/resources/define/app-memcached.yml), [NebulaGraph](https://github.com/dromara/hertzbeat/blob/master/manager/src/main/resources/define/app-nebulaGraph.yml)
- [Linux](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-linux.yml), [Ubuntu](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-ubuntu.yml),
[CentOS](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-centos.yml), [Windows](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-windows.yml),
[EulerOS](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-euleros.yml), [Fedora CoreOS](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-coreos.yml),
[OpenSUSE](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-opensuse.yml), [Rocky Linux](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-rockylinux.yml),
[Red Hat](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-redhat.yml), [FreeBSD](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-freebsd.yml),
[AlmaLinux](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-almalinux.yml), [Debian Linux](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-debian.yml)
- [Tomcat](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-tomcat.yml), [Nacos](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-nacos.yml),
[Zookeeper](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-zookeeper.yml), [RabbitMQ](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-rabbitmq.yml),
[Flink](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-flink.yml), [Kafka](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-kafka.yml),
[ShenYu](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-shenyu.yml), [DynamicTp](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-dynamic_tp.yml),
[Jetty](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-jetty.yml), [ActiveMQ](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-activemq.yml),
[Spring Gateway](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-spring_gateway.yml), [EMQX MQTT](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-emqx.yml),
[AirFlow](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-airflow.yml), [Hive](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-hive.yml),
[Spark](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-spark.yml), [Hadoop](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-hadoop.yml)
- [Kubernetes](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-kubernetes.yml), [Docker](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-docker.yml)
- [CiscoSwitch](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-cisco_switch.yml), [HpeSwitch](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-hpe_switch.yml),
[HuaweiSwitch](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-huawei_switch.yml), [TpLinkSwitch](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-tplink_switch.yml),
[H3cSwitch](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-h3c_switch.yml)
- [Website](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-website.yml), [Port Telnet](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-port.yml),
[Http Api](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-api.yml), [Ping Connect](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-ping.yml),
[Jvm](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-jvm.yml), [SiteMap](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-fullsite.yml),
[Ssl Certificate](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-ssl_cert.yml), [SpringBoot2](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-springboot2.yml),
[FTP Server](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-ftp.yml), [SpringBoot3](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-springboot3.yml),
[Udp Port](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-udp_port.yml), [Dns](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-dns.yml),
[Pop3](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-pop3.yml), [Ntp](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-ntp.yml),
[Api Code](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-api_code.yml), [Smtp](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-smtp.yml),
[Nginx](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-nginx.yml)
- [Mysql](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-mysql.yml), [PostgreSQL](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-postgresql.yml),
[MariaDB](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-mariadb.yml), [Redis](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-redis.yml),
[ElasticSearch](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-elasticsearch.yml), [SqlServer](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-sqlserver.yml),
[Oracle](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-oracle.yml), [MongoDB](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-mongodb.yml),
[DM](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-dm.yml), [OpenGauss](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-opengauss.yml),
[ClickHouse](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-clickhouse.yml), [IoTDB](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-iotdb.yml),
[Redis Cluster](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-redis_cluster.yml), [Redis Sentinel](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-redis_sentinel.yml)
[Doris BE](https://github.com/apache/hertzbeat/blob/master/hertzbeat-manager/src/main/resources/define/app-doris_be.yml), [Doris FE](https://github.com/apache/hertzbeat/blob/master/hertzbeat-manager/src/main/resources/define/app-doris_fe.yml),
[Memcached](https://github.com/apache/hertzbeat/blob/master/hertzbeat-manager/src/main/resources/define/app-memcached.yml), [NebulaGraph](https://github.com/apache/hertzbeat/blob/master/hertzbeat-manager/src/main/resources/define/app-nebula_graph.yml)
- [Linux](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-linux.yml), [Ubuntu](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-ubuntu.yml),
[CentOS](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-centos.yml), [Windows](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-windows.yml),
[EulerOS](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-euleros.yml), [Fedora CoreOS](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-coreos.yml),
[OpenSUSE](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-opensuse.yml), [Rocky Linux](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-rockylinux.yml),
[Red Hat](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-redhat.yml), [FreeBSD](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-freebsd.yml),
[AlmaLinux](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-almalinux.yml), [Debian Linux](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-debian.yml)
- [Tomcat](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-tomcat.yml), [Nacos](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-nacos.yml),
[Zookeeper](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-zookeeper.yml), [RabbitMQ](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-rabbitmq.yml),
[Flink](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-flink.yml), [Kafka](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-kafka.yml),
[ShenYu](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-shenyu.yml), [DynamicTp](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-dynamic_tp.yml),
[Jetty](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-jetty.yml), [ActiveMQ](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-activemq.yml),
[Spring Gateway](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-spring_gateway.yml), [EMQX MQTT](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-emqx.yml),
[AirFlow](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-airflow.yml), [Hive](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-hive.yml),
[Spark](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-spark.yml), [Hadoop](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-hadoop.yml)
- [Kubernetes](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-kubernetes.yml), [Docker](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-docker.yml)
- [CiscoSwitch](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-cisco_switch.yml), [HpeSwitch](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-hpe_switch.yml),
[HuaweiSwitch](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-huawei_switch.yml), [TpLinkSwitch](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-tplink_switch.yml),
[H3cSwitch](https://raw.githubusercontent.com/apache/hertzbeat/master/hertzbeat-manager/src/main/resources/define/app-h3c_switch.yml)
- 和更多自定义监控模版。
- 通知支持 `Discord` `Slack` `Telegram` `邮件` `钉钉` `微信` `飞书` `短信` `Webhook` `Server酱`
## 🐕 快速开始
- 如果您是想将HertzBeat部署到内网环境搭建监控系统,请参考下面的部署文档进行操作。
- 如果您是想将 HertzBeat 部署到内网环境搭建监控系统,请参考下面的部署文档进行操作。
### 🍞 HertzBeat安装
> HertzBeat支持通过源码安装启动,Docker容器运行和安装包方式安装部署,CPU架构支持x86/arm64。
### 🍞 HertzBeat 安装
> HertzBeat 支持通过源码安装启动,Docker 容器运行和安装包方式安装部署,CPU 架构支持 x86/arm64。
##### 方式一:Docker方式快速安装
##### 方式一:Docker 方式快速安装
1. `docker` 环境仅需一条命令即可开始
```docker run -d -p 1157:1157 -p 1158:1158 --name hertzbeat tancloud/hertzbeat```
```或者使用 quay.io (若 dockerhub 网络链接超时)```
```docker run -d -p 1157:1157 -p 1158:1158 --name hertzbeat quay.io/tancloud/hertzbeat```
```shell
docker run -d -p 1157:1157 -p 1158:1158 --name hertzbeat apache/hertzbeat
```
2. 浏览器访问 `http://localhost:1157` 即可开始,默认账号密码 `admin/hertzbeat`
3. 部署采集器集群(可选)
3. 部署采集器集群可选
```shell
docker run -d -e IDENTITY=custom-collector-name -e MANAGER_HOST=127.0.0.1 -e MANAGER_PORT=1158 --name hertzbeat-collector apache/hertzbeat-collector
```
```
docker run -d -e IDENTITY=custom-collector-name -e MANAGER_HOST=127.0.0.1 -e MANAGER_PORT=1158 --name hertzbeat-collector tancloud/hertzbeat-collector
```
- `-e IDENTITY=custom-collector-name` : 配置此采集器的唯一性标识符名称,多个采集器名称不能相同,建议自定义英文名称。
- `-e MODE=public` : 配置运行模式(public or private), 公共集群模式或私有云边模式。
- `-e MANAGER_HOST=127.0.0.1` : 配置连接主HertaBeat服务的对外IP。
- `-e MANAGER_PORT=1158` : 配置连接主HertzBeat服务的对外端口,默认1158。
- `-e MODE=public` : 配置运行模式(public or private), 公共集群模式或私有云边模式。
- `-e MANAGER_HOST=127.0.0.1` : 配置连接主 HertaBeat 服务的对外 IP。
- `-e MANAGER_PORT=1158` : 配置连接主 HertzBeat 服务的对外端口,默认1158。
更多配置详细步骤参考 [通过Docker方式安装HertzBeat](https://hertzbeat.com/docs/start/docker-deploy)
更多配置详细步骤参考 [通过 Docker 方式安装 HertzBeat](https://hertzbeat.apache.org/docs/start/docker-deploy)
##### 方式二:通过安装包安装
1. 下载您系统环境对应的安装包`hertzbeat-xx.tar.gz` [GITEE Release](https://gitee.com/dromara/hertzbeat/releases) [GITHUB Release](https://github.com/dromara/hertzbeat/releases)
2. 配置 HertzBeat 的配置文件 `hertzbeat/config/application.yml`(可选)
1. 下载您系统环境对应的安装包 `hertzbeat-xx.tar.gz` [Download](https://hertzbeat.apache.org/docs/download)
2. 配置 HertzBeat 的配置文件 `hertzbeat/config/application.yml` (可选)
3. 部署启动 `$ ./bin/startup.sh ` 或 `bin/startup.bat`
4. 浏览器访问 `http://localhost:1157` 即可开始,默认账号密码 `admin/hertzbeat`
5. 部署采集器集群(可选)
- 下载采集器安装包`hertzbeat-collector-xx.tar.gz`到规划的另一台部署主机上 [GITEE Release](https://gitee.com/dromara/hertzbeat/releases) [GITHUB Release](https://github.com/dromara/hertzbeat/releases)
- 配置采集器的配置文件 `hertzbeat-collector/config/application.yml` 里面的连接主HertzBeat服务的对外IP,端口,当前采集器名称(需保证唯一性)等参数 `identity` `mode` (public or private) `manager-host` `manager-port`
5. 部署采集器集群可选
- 下载采集器安装包 `hertzbeat-collector-xx.tar.gz` 到规划的另一台部署主机上 [Download](https://hertzbeat.apache.org/docs/download)
- 配置采集器的配置文件 `hertzbeat-collector/config/application.yml` 里面的连接主 HertzBeat 服务的对外 IP,端口,当前采集器名称(需保证唯一性)等参数 `identity` `mode` (public or private) `manager-host` `manager-port`
```yaml
collector:
dispatch:
@@ -150,26 +152,26 @@ docker run -d -e IDENTITY=custom-collector-name -e MANAGER_HOST=127.0.0.1 -e MAN
manager-port: ${MANAGER_PORT:1158}
```
- 启动 `$ ./bin/startup.sh ` 或 `bin/startup.bat`
- 浏览器访问主HertzBeat服务 `http://localhost:1157` 查看概览页面即可看到注册上来的新采集器
- 浏览器访问主 HertzBeat 服务 `http://localhost:1157` 查看概览页面即可看到注册上来的新采集器
更多配置详细步骤参考 [通过安装包安装HertzBeat](https://hertzbeat.com/docs/start/package-deploy)
更多配置详细步骤参考 [通过安装包安装HertzBeat](https://hertzbeat.apache.org/docs/start/package-deploy)
##### 方式三:本地代码启动
1. 此为前后端分离项目,本地代码调试需要分别启动后端工程`manager`和前端工程`web-app`
2. 后端:需要`maven3+`, `java17``lombok`环境,修改`YML`配置信息启动`manager`服务
3. 前端:需要`nodejs npm angular-cli`环境,待本地后端启动后,在`web-app`目录下启动 `ng serve --open`
1. 此为前后端分离项目,本地代码调试需要分别启动后端工程 `manager` 和前端工程 `web-app`
2. 后端:需要 `maven3+`, `java17``lombok` 环境,修改 `YML` 配置信息,添加JVM参数`--add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED`后启动 `manager` 服务即可。
3. 前端:需要 `nodejs npm angular-cli`环境,待本地后端启动后,在 `web-app` 目录下启动 `ng serve --open`
4. 浏览器访问 `http://localhost:4200` 即可开始,默认账号密码 `admin/hertzbeat`
详细步骤参考 [参与贡献之本地代码启动](CONTRIBUTING.md)
##### 方式四:Docker-Compose 统一安装 hertzbeat+mysql+tsdb
##### 方式四:Docker-Compose 统一安装 hertzbeat+postgresql+tsdb
通过 [Docker-Compose 部署脚本](script/docker-compose) 一次性把 mysql/postgresql 数据库, iotdb/tdengine/victoria-metrics 时序数据库和 hertzbeat 安装部署。
通过 [Docker-Compose 部署脚本](script/docker-compose) 一次性把 postgresql/mysql 数据库, victoria-metrics/iotdb/tdengine 时序数据库和 hertzbeat 安装部署。
详细步骤参考 [通过Docker-Compose安装HertzBeat](script/docker-compose/README.md)
详细步骤参考 [通过 Docker-Compose 安装 HertzBeat](script/docker-compose/README.md)
##### 方式五:Kubernetes Helm Charts 部署 hertzbeat+collector+mysql+tsdb
##### 方式五:Kubernetes Helm Charts 部署 hertzbeat+collector+postgresql+tsdb
通过 Helm Chart 一次性将 HertzBeat 集群组件部署到 Kubernetes 集群中。
@@ -177,10 +179,6 @@ docker run -d -e IDENTITY=custom-collector-name -e MANAGER_HOST=127.0.0.1 -e MAN
**HAVE FUN**
## 🥐 路线图
![hertzBeat](home/static/img/docs/hertzbeat-roadmap.png)
## ✨ Contributors
Thanks these wonderful people, welcome to join us:
@@ -192,223 +190,322 @@ Thanks these wonderful people, welcome to join us:
<table>
<tbody>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/tomsun28"><img src="https://avatars.githubusercontent.com/u/24788200?v=4?s=100" width="100px;" alt="tomsun28"/><br /><sub><b>tomsun28</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=tomsun28" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=tomsun28" title="Documentation">📖</a> <a href="#design-tomsun28" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><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/dromara/hertzbeat/commits?author=wang1027-wqh" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=wang1027-wqh" title="Documentation">📖</a> <a href="#design-wang1027-wqh" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.maxkey.top/"><img src="https://avatars.githubusercontent.com/u/1563377?v=4?s=100" width="100px;" alt="MaxKey"/><br /><sub><b>MaxKey</b></sub></a><br /><a href="https://github.com/dromara/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" valign="top" width="14.28%"><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/dromara/hertzbeat/commits?author=gcdd1993" title="Code">💻</a> <a href="#design-gcdd1993" title="Design">🎨</a> <a href="https://github.com/dromara/hertzbeat/issues?q=author%3Agcdd1993" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/a25017012"><img src="https://avatars.githubusercontent.com/u/32265356?v=4?s=100" width="100px;" alt="yuye"/><br /><sub><b>yuye</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=a25017012" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=a25017012" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jx10086"><img src="https://avatars.githubusercontent.com/u/5323228?v=4?s=100" width="100px;" alt="jx10086"/><br /><sub><b>jx10086</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=jx10086" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/issues?q=author%3Ajx10086" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/winnerTimer"><img src="https://avatars.githubusercontent.com/u/76024658?v=4?s=100" width="100px;" alt="winnerTimer"/><br /><sub><b>winnerTimer</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=winnerTimer" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/issues?q=author%3AwinnerTimer" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/tomsun28"><img src="https://avatars.githubusercontent.com/u/24788200?v=4?s=100" width="100px;" alt="tomsun28"/><br /><sub><b>tomsun28</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=tomsun28" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=tomsun28" title="Documentation">📖</a> <a href="#design-tomsun28" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><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/apache/hertzbeat/commits?author=wang1027-wqh" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=wang1027-wqh" title="Documentation">📖</a> <a href="#design-wang1027-wqh" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.maxkey.top/"><img src="https://avatars.githubusercontent.com/u/1563377?v=4?s=100" width="100px;" alt="MaxKey"/><br /><sub><b>MaxKey</b></sub></a><br /><a href="https://github.com/apache/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" valign="top" width="14.28%"><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/apache/hertzbeat/commits?author=gcdd1993" title="Code">💻</a> <a href="#design-gcdd1993" title="Design">🎨</a> <a href="https://github.com/apache/hertzbeat/issues?q=author%3Agcdd1993" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/a25017012"><img src="https://avatars.githubusercontent.com/u/32265356?v=4?s=100" width="100px;" alt="yuye"/><br /><sub><b>yuye</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=a25017012" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=a25017012" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jx10086"><img src="https://avatars.githubusercontent.com/u/5323228?v=4?s=100" width="100px;" alt="jx10086"/><br /><sub><b>jx10086</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=jx10086" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/issues?q=author%3Ajx10086" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/winnerTimer"><img src="https://avatars.githubusercontent.com/u/76024658?v=4?s=100" width="100px;" alt="winnerTimer"/><br /><sub><b>winnerTimer</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=winnerTimer" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/issues?q=author%3AwinnerTimer" title="Bug reports">🐛</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/goo-kits"><img src="https://avatars.githubusercontent.com/u/13163673?v=4?s=100" width="100px;" alt="goo-kits"/><br /><sub><b>goo-kits</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=goo-kits" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/issues?q=author%3Agoo-kits" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/brave4Time"><img src="https://avatars.githubusercontent.com/u/105094014?v=4?s=100" width="100px;" alt="brave4Time"/><br /><sub><b>brave4Time</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=brave4Time" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/issues?q=author%3Abrave4Time" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/walkerlee-lab"><img src="https://avatars.githubusercontent.com/u/8426753?v=4?s=100" width="100px;" alt="WalkerLee"/><br /><sub><b>WalkerLee</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=walkerlee-lab" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/issues?q=author%3Awalkerlee-lab" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/fullofjoy"><img src="https://avatars.githubusercontent.com/u/30247571?v=4?s=100" width="100px;" alt="jianghang"/><br /><sub><b>jianghang</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=fullofjoy" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/issues?q=author%3Afullofjoy" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ChineseTony"><img src="https://avatars.githubusercontent.com/u/24618786?v=4?s=100" width="100px;" alt="ChineseTony"/><br /><sub><b>ChineseTony</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=ChineseTony" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/issues?q=author%3AChineseTony" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wyt199905"><img src="https://avatars.githubusercontent.com/u/85098809?v=4?s=100" width="100px;" alt="wyt199905"/><br /><sub><b>wyt199905</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=wyt199905" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/weifuqing"><img src="https://avatars.githubusercontent.com/u/13931013?v=4?s=100" width="100px;" alt="卫傅庆"/><br /><sub><b>卫傅庆</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=weifuqing" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/issues?q=author%3Aweifuqing" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/goo-kits"><img src="https://avatars.githubusercontent.com/u/13163673?v=4?s=100" width="100px;" alt="goo-kits"/><br /><sub><b>goo-kits</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=goo-kits" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/issues?q=author%3Agoo-kits" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/brave4Time"><img src="https://avatars.githubusercontent.com/u/105094014?v=4?s=100" width="100px;" alt="brave4Time"/><br /><sub><b>brave4Time</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=brave4Time" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/issues?q=author%3Abrave4Time" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/walkerlee-lab"><img src="https://avatars.githubusercontent.com/u/8426753?v=4?s=100" width="100px;" alt="WalkerLee"/><br /><sub><b>WalkerLee</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=walkerlee-lab" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/issues?q=author%3Awalkerlee-lab" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/fullofjoy"><img src="https://avatars.githubusercontent.com/u/30247571?v=4?s=100" width="100px;" alt="jianghang"/><br /><sub><b>jianghang</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=fullofjoy" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/issues?q=author%3Afullofjoy" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ChineseTony"><img src="https://avatars.githubusercontent.com/u/24618786?v=4?s=100" width="100px;" alt="ChineseTony"/><br /><sub><b>ChineseTony</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ChineseTony" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/issues?q=author%3AChineseTony" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wyt199905"><img src="https://avatars.githubusercontent.com/u/85098809?v=4?s=100" width="100px;" alt="wyt199905"/><br /><sub><b>wyt199905</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=wyt199905" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/weifuqing"><img src="https://avatars.githubusercontent.com/u/13931013?v=4?s=100" width="100px;" alt="卫傅庆"/><br /><sub><b>卫傅庆</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=weifuqing" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/issues?q=author%3Aweifuqing" title="Bug reports">🐛</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zklmcookle"><img src="https://avatars.githubusercontent.com/u/107192352?v=4?s=100" width="100px;" alt="zklmcookle"/><br /><sub><b>zklmcookle</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=zklmcookle" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/DevilX5"><img src="https://avatars.githubusercontent.com/u/13269921?v=4?s=100" width="100px;" alt="DevilX5"/><br /><sub><b>DevilX5</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=DevilX5" title="Documentation">📖</a> <a href="https://github.com/dromara/hertzbeat/commits?author=DevilX5" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/djzeng"><img src="https://avatars.githubusercontent.com/u/14074864?v=4?s=100" width="100px;" alt="tea"/><br /><sub><b>tea</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=djzeng" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yangshihui"><img src="https://avatars.githubusercontent.com/u/28550208?v=4?s=100" width="100px;" alt="yangshihui"/><br /><sub><b>yangshihui</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=yangshihui" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/issues?q=author%3Ayangshihui" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/DreamGirl524"><img src="https://avatars.githubusercontent.com/u/81132838?v=4?s=100" width="100px;" alt="DreamGirl524"/><br /><sub><b>DreamGirl524</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=DreamGirl524" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=DreamGirl524" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/gzwlly"><img src="https://avatars.githubusercontent.com/u/83171907?v=4?s=100" width="100px;" alt="gzwlly"/><br /><sub><b>gzwlly</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=gzwlly" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/cuipiheqiuqiu"><img src="https://avatars.githubusercontent.com/u/76642201?v=4?s=100" width="100px;" alt="cuipiheqiuqiu"/><br /><sub><b>cuipiheqiuqiu</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=cuipiheqiuqiu" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=cuipiheqiuqiu" title="Tests">⚠️</a> <a href="#design-cuipiheqiuqiu" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zklmcookle"><img src="https://avatars.githubusercontent.com/u/107192352?v=4?s=100" width="100px;" alt="zklmcookle"/><br /><sub><b>zklmcookle</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=zklmcookle" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/DevilX5"><img src="https://avatars.githubusercontent.com/u/13269921?v=4?s=100" width="100px;" alt="DevilX5"/><br /><sub><b>DevilX5</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=DevilX5" title="Documentation">📖</a> <a href="https://github.com/apache/hertzbeat/commits?author=DevilX5" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/djzeng"><img src="https://avatars.githubusercontent.com/u/14074864?v=4?s=100" width="100px;" alt="tea"/><br /><sub><b>tea</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=djzeng" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yangshihui"><img src="https://avatars.githubusercontent.com/u/28550208?v=4?s=100" width="100px;" alt="yangshihui"/><br /><sub><b>yangshihui</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=yangshihui" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/issues?q=author%3Ayangshihui" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/DreamGirl524"><img src="https://avatars.githubusercontent.com/u/81132838?v=4?s=100" width="100px;" alt="DreamGirl524"/><br /><sub><b>DreamGirl524</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=DreamGirl524" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=DreamGirl524" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/gzwlly"><img src="https://avatars.githubusercontent.com/u/83171907?v=4?s=100" width="100px;" alt="gzwlly"/><br /><sub><b>gzwlly</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=gzwlly" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/cuipiheqiuqiu"><img src="https://avatars.githubusercontent.com/u/76642201?v=4?s=100" width="100px;" alt="cuipiheqiuqiu"/><br /><sub><b>cuipiheqiuqiu</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=cuipiheqiuqiu" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=cuipiheqiuqiu" title="Tests">⚠️</a> <a href="#design-cuipiheqiuqiu" title="Design">🎨</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/oyiyou"><img src="https://avatars.githubusercontent.com/u/39228891?v=4?s=100" width="100px;" alt="lambert"/><br /><sub><b>lambert</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=oyiyou" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://mroldx.xyz/"><img src="https://avatars.githubusercontent.com/u/34847828?v=4?s=100" width="100px;" alt="mroldx"/><br /><sub><b>mroldx</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=mroldx" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/woshiniusange"><img src="https://avatars.githubusercontent.com/u/91513022?v=4?s=100" width="100px;" alt="woshiniusange"/><br /><sub><b>woshiniusange</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=woshiniusange" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://vampireachao.github.io/"><img src="https://avatars.githubusercontent.com/u/52746628?v=4?s=100" width="100px;" alt="VampireAchao"/><br /><sub><b>VampireAchao</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=VampireAchao" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Ceilzcx"><img src="https://avatars.githubusercontent.com/u/48920254?v=4?s=100" width="100px;" alt="zcx"/><br /><sub><b>zcx</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=Ceilzcx" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/issues?q=author%3ACeilzcx" title="Bug reports">🐛</a> <a href="#design-Ceilzcx" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/CharlieXCL"><img src="https://avatars.githubusercontent.com/u/91540487?v=4?s=100" width="100px;" alt="CharlieXCL"/><br /><sub><b>CharlieXCL</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=CharlieXCL" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Privauto"><img src="https://avatars.githubusercontent.com/u/36581456?v=4?s=100" width="100px;" alt="Privauto"/><br /><sub><b>Privauto</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=Privauto" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=Privauto" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/oyiyou"><img src="https://avatars.githubusercontent.com/u/39228891?v=4?s=100" width="100px;" alt="lambert"/><br /><sub><b>lambert</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=oyiyou" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://mroldx.xyz/"><img src="https://avatars.githubusercontent.com/u/34847828?v=4?s=100" width="100px;" alt="mroldx"/><br /><sub><b>mroldx</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=mroldx" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/woshiniusange"><img src="https://avatars.githubusercontent.com/u/91513022?v=4?s=100" width="100px;" alt="woshiniusange"/><br /><sub><b>woshiniusange</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=woshiniusange" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://vampireachao.github.io/"><img src="https://avatars.githubusercontent.com/u/52746628?v=4?s=100" width="100px;" alt="VampireAchao"/><br /><sub><b>VampireAchao</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=VampireAchao" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Ceilzcx"><img src="https://avatars.githubusercontent.com/u/48920254?v=4?s=100" width="100px;" alt="zcx"/><br /><sub><b>zcx</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Ceilzcx" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/issues?q=author%3ACeilzcx" title="Bug reports">🐛</a> <a href="#design-Ceilzcx" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/CharlieXCL"><img src="https://avatars.githubusercontent.com/u/91540487?v=4?s=100" width="100px;" alt="CharlieXCL"/><br /><sub><b>CharlieXCL</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=CharlieXCL" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Privauto"><img src="https://avatars.githubusercontent.com/u/36581456?v=4?s=100" width="100px;" alt="Privauto"/><br /><sub><b>Privauto</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Privauto" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=Privauto" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/emrys-he"><img src="https://avatars.githubusercontent.com/u/5848915?v=4?s=100" width="100px;" alt="emrys"/><br /><sub><b>emrys</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=emrys-he" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/SxLiuYu"><img src="https://avatars.githubusercontent.com/u/95198625?v=4?s=100" width="100px;" alt="SxLiuYu"/><br /><sub><b>SxLiuYu</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/issues?q=author%3ASxLiuYu" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://allcontributors.org"><img src="https://avatars.githubusercontent.com/u/46410174?v=4?s=100" width="100px;" alt="All Contributors"/><br /><sub><b>All Contributors</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=all-contributors" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/gxc-myh"><img src="https://avatars.githubusercontent.com/u/85919258?v=4?s=100" width="100px;" alt="铁甲小宝"/><br /><sub><b>铁甲小宝</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=gxc-myh" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=gxc-myh" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/click33"><img src="https://avatars.githubusercontent.com/u/36243476?v=4?s=100" width="100px;" alt="click33"/><br /><sub><b>click33</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=click33" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://jpom.io/"><img src="https://avatars.githubusercontent.com/u/16408873?v=4?s=100" width="100px;" alt="蒋小小"/><br /><sub><b>蒋小小</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=bwcx-jzy" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.zhihu.com/people/kevinbauer"><img src="https://avatars.githubusercontent.com/u/28581579?v=4?s=100" width="100px;" alt="Kevin Huang"/><br /><sub><b>Kevin Huang</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=kevinhuangwl" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/emrys-he"><img src="https://avatars.githubusercontent.com/u/5848915?v=4?s=100" width="100px;" alt="emrys"/><br /><sub><b>emrys</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=emrys-he" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/SxLiuYu"><img src="https://avatars.githubusercontent.com/u/95198625?v=4?s=100" width="100px;" alt="SxLiuYu"/><br /><sub><b>SxLiuYu</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/issues?q=author%3ASxLiuYu" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://allcontributors.org"><img src="https://avatars.githubusercontent.com/u/46410174?v=4?s=100" width="100px;" alt="All Contributors"/><br /><sub><b>All Contributors</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=all-contributors" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/gxc-myh"><img src="https://avatars.githubusercontent.com/u/85919258?v=4?s=100" width="100px;" alt="铁甲小宝"/><br /><sub><b>铁甲小宝</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=gxc-myh" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=gxc-myh" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/click33"><img src="https://avatars.githubusercontent.com/u/36243476?v=4?s=100" width="100px;" alt="click33"/><br /><sub><b>click33</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=click33" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://jpom.io/"><img src="https://avatars.githubusercontent.com/u/16408873?v=4?s=100" width="100px;" alt="蒋小小"/><br /><sub><b>蒋小小</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=bwcx-jzy" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.zhihu.com/people/kevinbauer"><img src="https://avatars.githubusercontent.com/u/28581579?v=4?s=100" width="100px;" alt="Kevin Huang"/><br /><sub><b>Kevin Huang</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=kevinhuangwl" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/TJxiaobao"><img src="https://avatars.githubusercontent.com/u/85919258?v=4?s=100" width="100px;" alt="铁甲小宝"/><br /><sub><b>铁甲小宝</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/issues?q=author%3ATJxiaobao" title="Bug reports">🐛</a> <a href="https://github.com/dromara/hertzbeat/commits?author=TJxiaobao" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=TJxiaobao" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Jack-123-power"><img src="https://avatars.githubusercontent.com/u/84333501?v=4?s=100" width="100px;" alt="Captain Jack"/><br /><sub><b>Captain Jack</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=Jack-123-power" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/haibo-duan"><img src="https://avatars.githubusercontent.com/u/7974845?v=4?s=100" width="100px;" alt="haibo.duan"/><br /><sub><b>haibo.duan</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=haibo-duan" title="Tests">⚠️</a> <a href="https://github.com/dromara/hertzbeat/commits?author=haibo-duan" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/assassinfym"><img src="https://avatars.githubusercontent.com/u/15188754?v=4?s=100" width="100px;" alt="assassin"/><br /><sub><b>assassin</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/issues?q=author%3Aassassinfym" title="Bug reports">🐛</a> <a href="https://github.com/dromara/hertzbeat/commits?author=assassinfym" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/csyshu"><img src="https://avatars.githubusercontent.com/u/46591658?v=4?s=100" width="100px;" alt="Reverse wind"/><br /><sub><b>Reverse wind</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=csyshu" title="Tests">⚠️</a> <a href="https://github.com/dromara/hertzbeat/commits?author=csyshu" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/luxx-lq"><img src="https://avatars.githubusercontent.com/u/58515565?v=4?s=100" width="100px;" alt="luxx"/><br /><sub><b>luxx</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=luxx-lq" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://bandism.net/"><img src="https://avatars.githubusercontent.com/u/22633385?v=4?s=100" width="100px;" alt="Ikko Ashimine"/><br /><sub><b>Ikko Ashimine</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=eltociear" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/TJxiaobao"><img src="https://avatars.githubusercontent.com/u/85919258?v=4?s=100" width="100px;" alt="铁甲小宝"/><br /><sub><b>铁甲小宝</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/issues?q=author%3ATJxiaobao" title="Bug reports">🐛</a> <a href="https://github.com/apache/hertzbeat/commits?author=TJxiaobao" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=TJxiaobao" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Jack-123-power"><img src="https://avatars.githubusercontent.com/u/84333501?v=4?s=100" width="100px;" alt="Captain Jack"/><br /><sub><b>Captain Jack</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Jack-123-power" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/haibo-duan"><img src="https://avatars.githubusercontent.com/u/7974845?v=4?s=100" width="100px;" alt="haibo.duan"/><br /><sub><b>haibo.duan</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=haibo-duan" title="Tests">⚠️</a> <a href="https://github.com/apache/hertzbeat/commits?author=haibo-duan" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/assassinfym"><img src="https://avatars.githubusercontent.com/u/15188754?v=4?s=100" width="100px;" alt="assassin"/><br /><sub><b>assassin</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/issues?q=author%3Aassassinfym" title="Bug reports">🐛</a> <a href="https://github.com/apache/hertzbeat/commits?author=assassinfym" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/csyshu"><img src="https://avatars.githubusercontent.com/u/46591658?v=4?s=100" width="100px;" alt="Reverse wind"/><br /><sub><b>Reverse wind</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=csyshu" title="Tests">⚠️</a> <a href="https://github.com/apache/hertzbeat/commits?author=csyshu" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/luxx-lq"><img src="https://avatars.githubusercontent.com/u/58515565?v=4?s=100" width="100px;" alt="luxx"/><br /><sub><b>luxx</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=luxx-lq" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://bandism.net/"><img src="https://avatars.githubusercontent.com/u/22633385?v=4?s=100" width="100px;" alt="Ikko Ashimine"/><br /><sub><b>Ikko Ashimine</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=eltociear" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zenan08"><img src="https://avatars.githubusercontent.com/u/80514991?v=4?s=100" width="100px;" alt="leizenan"/><br /><sub><b>leizenan</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=zenan08" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/BKing2020"><img src="https://avatars.githubusercontent.com/u/28869121?v=4?s=100" width="100px;" alt="BKing"/><br /><sub><b>BKing</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=BKing2020" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xingshuaiLi"><img src="https://avatars.githubusercontent.com/u/119487588?v=4?s=100" width="100px;" alt="xingshuaiLi"/><br /><sub><b>xingshuaiLi</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=xingshuaiLi" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wangke6666"><img src="https://avatars.githubusercontent.com/u/113656595?v=4?s=100" width="100px;" alt="wangke6666"/><br /><sub><b>wangke6666</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=wangke6666" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/LWBobo"><img src="https://avatars.githubusercontent.com/u/50368698?v=4?s=100" width="100px;" alt="刺猬"/><br /><sub><b>刺猬</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/issues?q=author%3ALWBobo" title="Bug reports">🐛</a> <a href="https://github.com/dromara/hertzbeat/commits?author=LWBobo" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.zanglikun.com"><img src="https://avatars.githubusercontent.com/u/61591648?v=4?s=100" width="100px;" alt="Haste"/><br /><sub><b>Haste</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=zanglikun" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/SuitSmile"><img src="https://avatars.githubusercontent.com/u/38679717?v=4?s=100" width="100px;" alt="zhongshi.yi"/><br /><sub><b>zhongshi.yi</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=SuitSmile" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zenan08"><img src="https://avatars.githubusercontent.com/u/80514991?v=4?s=100" width="100px;" alt="leizenan"/><br /><sub><b>leizenan</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=zenan08" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/BKing2020"><img src="https://avatars.githubusercontent.com/u/28869121?v=4?s=100" width="100px;" alt="BKing"/><br /><sub><b>BKing</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=BKing2020" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xingshuaiLi"><img src="https://avatars.githubusercontent.com/u/119487588?v=4?s=100" width="100px;" alt="xingshuaiLi"/><br /><sub><b>xingshuaiLi</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=xingshuaiLi" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wangke6666"><img src="https://avatars.githubusercontent.com/u/113656595?v=4?s=100" width="100px;" alt="wangke6666"/><br /><sub><b>wangke6666</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=wangke6666" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/LWBobo"><img src="https://avatars.githubusercontent.com/u/50368698?v=4?s=100" width="100px;" alt="刺猬"/><br /><sub><b>刺猬</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/issues?q=author%3ALWBobo" title="Bug reports">🐛</a> <a href="https://github.com/apache/hertzbeat/commits?author=LWBobo" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.zanglikun.com"><img src="https://avatars.githubusercontent.com/u/61591648?v=4?s=100" width="100px;" alt="Haste"/><br /><sub><b>Haste</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=zanglikun" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/SuitSmile"><img src="https://avatars.githubusercontent.com/u/38679717?v=4?s=100" width="100px;" alt="zhongshi.yi"/><br /><sub><b>zhongshi.yi</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=SuitSmile" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://www.smallq.cn"><img src="https://avatars.githubusercontent.com/u/39754275?v=4?s=100" width="100px;" alt="Qi Zhang"/><br /><sub><b>Qi Zhang</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=zzzhangqi" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MrAndyMing"><img src="https://avatars.githubusercontent.com/u/49541483?v=4?s=100" width="100px;" alt="MrAndyMing"/><br /><sub><b>MrAndyMing</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=MrAndyMing" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://idongliming.github.io/"><img src="https://avatars.githubusercontent.com/u/31564353?v=4?s=100" width="100px;" alt="idongliming"/><br /><sub><b>idongliming</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=idongliming" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://earthjasonlin.github.io"><img src="https://avatars.githubusercontent.com/u/83632110?v=4?s=100" width="100px;" alt="Zichao Lin"/><br /><sub><b>Zichao Lin</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=earthjasonlin" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=earthjasonlin" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://blog.liudonghua.com"><img src="https://avatars.githubusercontent.com/u/2276718?v=4?s=100" width="100px;" alt="liudonghua"/><br /><sub><b>liudonghua</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=liudonghua123" title="Code">💻</a> <a href="#ideas-liudonghua123" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/orangeyts"><img src="https://avatars.githubusercontent.com/u/4250869?v=4?s=100" width="100px;" alt="Jerry"/><br /><sub><b>Jerry</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=orangeyts" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=orangeyts" title="Tests">⚠️</a> <a href="#ideas-orangeyts" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://dynamictp.cn"><img src="https://avatars.githubusercontent.com/u/13051908?v=4?s=100" width="100px;" alt="yanhom"/><br /><sub><b>yanhom</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=yanhom1314" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.smallq.cn"><img src="https://avatars.githubusercontent.com/u/39754275?v=4?s=100" width="100px;" alt="Qi Zhang"/><br /><sub><b>Qi Zhang</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=zzzhangqi" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MrAndyMing"><img src="https://avatars.githubusercontent.com/u/49541483?v=4?s=100" width="100px;" alt="MrAndyMing"/><br /><sub><b>MrAndyMing</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=MrAndyMing" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://idongliming.github.io/"><img src="https://avatars.githubusercontent.com/u/31564353?v=4?s=100" width="100px;" alt="idongliming"/><br /><sub><b>idongliming</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=idongliming" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://earthjasonlin.github.io"><img src="https://avatars.githubusercontent.com/u/83632110?v=4?s=100" width="100px;" alt="Zichao Lin"/><br /><sub><b>Zichao Lin</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=earthjasonlin" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=earthjasonlin" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://blog.liudonghua.com"><img src="https://avatars.githubusercontent.com/u/2276718?v=4?s=100" width="100px;" alt="liudonghua"/><br /><sub><b>liudonghua</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=liudonghua123" title="Code">💻</a> <a href="#ideas-liudonghua123" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/orangeyts"><img src="https://avatars.githubusercontent.com/u/4250869?v=4?s=100" width="100px;" alt="Jerry"/><br /><sub><b>Jerry</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=orangeyts" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=orangeyts" title="Tests">⚠️</a> <a href="#ideas-orangeyts" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://dynamictp.cn"><img src="https://avatars.githubusercontent.com/u/13051908?v=4?s=100" width="100px;" alt="yanhom"/><br /><sub><b>yanhom</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=yanhom1314" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://www.jianshu.com/u/a8f822c04f67"><img src="https://avatars.githubusercontent.com/u/18587688?v=4?s=100" width="100px;" alt="fsl"/><br /><sub><b>fsl</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=fengshunli" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xttttv"><img src="https://avatars.githubusercontent.com/u/116323904?v=4?s=100" width="100px;" alt="xttttv"/><br /><sub><b>xttttv</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=xttttv" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/NavinKumarBarnwal"><img src="https://avatars.githubusercontent.com/u/44504274?v=4?s=100" width="100px;" alt="NavinKumarBarnwal"/><br /><sub><b>NavinKumarBarnwal</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=NavinKumarBarnwal" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/z641205699"><img src="https://avatars.githubusercontent.com/u/45276423?v=4?s=100" width="100px;" alt="Zakkary"/><br /><sub><b>Zakkary</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=z641205699" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/898349230"><img src="https://avatars.githubusercontent.com/u/21972532?v=4?s=100" width="100px;" alt="sunxinbo"/><br /><sub><b>sunxinbo</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=898349230" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=898349230" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ldzbook"><img src="https://avatars.githubusercontent.com/u/13903790?v=4?s=100" width="100px;" alt="ldzbook"/><br /><sub><b>ldzbook</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=ldzbook" title="Documentation">📖</a> <a href="https://github.com/dromara/hertzbeat/issues?q=author%3Aldzbook" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/SurryChen"><img src="https://avatars.githubusercontent.com/u/91116490?v=4?s=100" width="100px;" alt="余与雨"/><br /><sub><b>余与雨</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=SurryChen" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=SurryChen" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.jianshu.com/u/a8f822c04f67"><img src="https://avatars.githubusercontent.com/u/18587688?v=4?s=100" width="100px;" alt="fsl"/><br /><sub><b>fsl</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=fengshunli" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xttttv"><img src="https://avatars.githubusercontent.com/u/116323904?v=4?s=100" width="100px;" alt="xttttv"/><br /><sub><b>xttttv</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=xttttv" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/NavinKumarBarnwal"><img src="https://avatars.githubusercontent.com/u/44504274?v=4?s=100" width="100px;" alt="NavinKumarBarnwal"/><br /><sub><b>NavinKumarBarnwal</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=NavinKumarBarnwal" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/z641205699"><img src="https://avatars.githubusercontent.com/u/45276423?v=4?s=100" width="100px;" alt="Zakkary"/><br /><sub><b>Zakkary</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=z641205699" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/898349230"><img src="https://avatars.githubusercontent.com/u/21972532?v=4?s=100" width="100px;" alt="sunxinbo"/><br /><sub><b>sunxinbo</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=898349230" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=898349230" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ldzbook"><img src="https://avatars.githubusercontent.com/u/13903790?v=4?s=100" width="100px;" alt="ldzbook"/><br /><sub><b>ldzbook</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ldzbook" title="Documentation">📖</a> <a href="https://github.com/apache/hertzbeat/issues?q=author%3Aldzbook" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/SurryChen"><img src="https://avatars.githubusercontent.com/u/91116490?v=4?s=100" width="100px;" alt="余与雨"/><br /><sub><b>余与雨</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=SurryChen" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=SurryChen" title="Tests">⚠️</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MysticalDream"><img src="https://avatars.githubusercontent.com/u/78899028?v=4?s=100" width="100px;" alt="MysticalDream"/><br /><sub><b>MysticalDream</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=MysticalDream" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=MysticalDream" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zhouyoulin12"><img src="https://avatars.githubusercontent.com/u/17086633?v=4?s=100" width="100px;" alt="zhouyoulin12"/><br /><sub><b>zhouyoulin12</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=zhouyoulin12" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=zhouyoulin12" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jerjjj"><img src="https://avatars.githubusercontent.com/u/93431283?v=4?s=100" width="100px;" alt="jerjjj"/><br /><sub><b>jerjjj</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=jerjjj" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://wjl110.xyz/"><img src="https://avatars.githubusercontent.com/u/53851034?v=4?s=100" width="100px;" alt="wjl110"/><br /><sub><b>wjl110</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=wjl110" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ngyhd"><img src="https://avatars.githubusercontent.com/u/29095207?v=4?s=100" width="100px;" alt="Sean"/><br /><sub><b>Sean</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=ngyhd" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Daydreamer-ia"><img src="https://avatars.githubusercontent.com/u/83362909?v=4?s=100" width="100px;" alt="chenyiqin"/><br /><sub><b>chenyiqin</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=Daydreamer-ia" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=Daydreamer-ia" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hudongdong129"><img src="https://avatars.githubusercontent.com/u/34374227?v=4?s=100" width="100px;" alt="hudongdong129"/><br /><sub><b>hudongdong129</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=hudongdong129" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=hudongdong129" title="Tests">⚠️</a> <a href="https://github.com/dromara/hertzbeat/commits?author=hudongdong129" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MysticalDream"><img src="https://avatars.githubusercontent.com/u/78899028?v=4?s=100" width="100px;" alt="MysticalDream"/><br /><sub><b>MysticalDream</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=MysticalDream" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=MysticalDream" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zhouyoulin12"><img src="https://avatars.githubusercontent.com/u/17086633?v=4?s=100" width="100px;" alt="zhouyoulin12"/><br /><sub><b>zhouyoulin12</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=zhouyoulin12" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=zhouyoulin12" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jerjjj"><img src="https://avatars.githubusercontent.com/u/93431283?v=4?s=100" width="100px;" alt="jerjjj"/><br /><sub><b>jerjjj</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=jerjjj" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://wjl110.xyz/"><img src="https://avatars.githubusercontent.com/u/53851034?v=4?s=100" width="100px;" alt="wjl110"/><br /><sub><b>wjl110</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=wjl110" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ngyhd"><img src="https://avatars.githubusercontent.com/u/29095207?v=4?s=100" width="100px;" alt="Sean"/><br /><sub><b>Sean</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ngyhd" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Daydreamer-ia"><img src="https://avatars.githubusercontent.com/u/83362909?v=4?s=100" width="100px;" alt="chenyiqin"/><br /><sub><b>chenyiqin</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Daydreamer-ia" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=Daydreamer-ia" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hudongdong129"><img src="https://avatars.githubusercontent.com/u/34374227?v=4?s=100" width="100px;" alt="hudongdong129"/><br /><sub><b>hudongdong129</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=hudongdong129" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=hudongdong129" title="Tests">⚠️</a> <a href="https://github.com/apache/hertzbeat/commits?author=hudongdong129" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/TherChenYang"><img src="https://avatars.githubusercontent.com/u/124348939?v=4?s=100" width="100px;" alt="TherChenYang"/><br /><sub><b>TherChenYang</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=TherChenYang" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=TherChenYang" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/HattoriHenzo"><img src="https://avatars.githubusercontent.com/u/5141285?v=4?s=100" width="100px;" alt="HattoriHenzo"/><br /><sub><b>HattoriHenzo</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=HattoriHenzo" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=HattoriHenzo" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ycilry"><img src="https://avatars.githubusercontent.com/u/63967101?v=4?s=100" width="100px;" alt="ycilry"/><br /><sub><b>ycilry</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=ycilry" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/aoshiguchen"><img src="https://avatars.githubusercontent.com/u/10580997?v=4?s=100" width="100px;" alt="aoshiguchen"/><br /><sub><b>aoshiguchen</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=aoshiguchen" title="Documentation">📖</a> <a href="https://github.com/dromara/hertzbeat/commits?author=aoshiguchen" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/caibenxiang"><img src="https://avatars.githubusercontent.com/u/4568241?v=4?s=100" width="100px;" alt="蔡本祥"/><br /><sub><b>蔡本祥</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=caibenxiang" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.fckeverything.cn:4000/"><img src="https://avatars.githubusercontent.com/u/13827124?v=4?s=100" width="100px;" alt="浮游"/><br /><sub><b>浮游</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=lifefloating" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Grass-Life"><img src="https://avatars.githubusercontent.com/u/114381513?v=4?s=100" width="100px;" alt="Grass-Life"/><br /><sub><b>Grass-Life</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=Grass-Life" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/TherChenYang"><img src="https://avatars.githubusercontent.com/u/124348939?v=4?s=100" width="100px;" alt="TherChenYang"/><br /><sub><b>TherChenYang</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=TherChenYang" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=TherChenYang" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/HattoriHenzo"><img src="https://avatars.githubusercontent.com/u/5141285?v=4?s=100" width="100px;" alt="HattoriHenzo"/><br /><sub><b>HattoriHenzo</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=HattoriHenzo" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=HattoriHenzo" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ycilry"><img src="https://avatars.githubusercontent.com/u/63967101?v=4?s=100" width="100px;" alt="ycilry"/><br /><sub><b>ycilry</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ycilry" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/aoshiguchen"><img src="https://avatars.githubusercontent.com/u/10580997?v=4?s=100" width="100px;" alt="aoshiguchen"/><br /><sub><b>aoshiguchen</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=aoshiguchen" title="Documentation">📖</a> <a href="https://github.com/apache/hertzbeat/commits?author=aoshiguchen" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/caibenxiang"><img src="https://avatars.githubusercontent.com/u/4568241?v=4?s=100" width="100px;" alt="蔡本祥"/><br /><sub><b>蔡本祥</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=caibenxiang" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.fckeverything.cn:4000/"><img src="https://avatars.githubusercontent.com/u/13827124?v=4?s=100" width="100px;" alt="浮游"/><br /><sub><b>浮游</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=lifefloating" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Grass-Life"><img src="https://avatars.githubusercontent.com/u/114381513?v=4?s=100" width="100px;" alt="Grass-Life"/><br /><sub><b>Grass-Life</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Grass-Life" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xiaohe428"><img src="https://avatars.githubusercontent.com/u/99130317?v=4?s=100" width="100px;" alt="xiaohe428"/><br /><sub><b>xiaohe428</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=xiaohe428" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=xiaohe428" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/baiban114"><img src="https://avatars.githubusercontent.com/u/59152619?v=4?s=100" width="100px;" alt="TableRow"/><br /><sub><b>TableRow</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=baiban114" title="Documentation">📖</a> <a href="https://github.com/dromara/hertzbeat/commits?author=baiban114" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ByteIDance"><img src="https://avatars.githubusercontent.com/u/100207562?v=4?s=100" width="100px;" alt="ByteIDance"/><br /><sub><b>ByteIDance</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=ByteIDance" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mangel2002"><img src="https://avatars.githubusercontent.com/u/9348020?v=4?s=100" width="100px;" alt="Jangfe"/><br /><sub><b>Jangfe</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=mangel2002" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zqr10159"><img src="https://avatars.githubusercontent.com/u/30048352?v=4?s=100" width="100px;" alt="zqr10159"/><br /><sub><b>zqr10159</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=zqr10159" title="Documentation">📖</a> <a href="https://github.com/dromara/hertzbeat/commits?author=zqr10159" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/vinci-897"><img src="https://avatars.githubusercontent.com/u/55838224?v=4?s=100" width="100px;" alt="vinci"/><br /><sub><b>vinci</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=vinci-897" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=vinci-897" title="Documentation">📖</a> <a href="#design-vinci-897" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/js110"><img src="https://avatars.githubusercontent.com/u/51191863?v=4?s=100" width="100px;" alt="js110"/><br /><sub><b>js110</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=js110" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xiaohe428"><img src="https://avatars.githubusercontent.com/u/99130317?v=4?s=100" width="100px;" alt="xiaohe428"/><br /><sub><b>xiaohe428</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=xiaohe428" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=xiaohe428" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/baiban114"><img src="https://avatars.githubusercontent.com/u/59152619?v=4?s=100" width="100px;" alt="TableRow"/><br /><sub><b>TableRow</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=baiban114" title="Documentation">📖</a> <a href="https://github.com/apache/hertzbeat/commits?author=baiban114" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ByteIDance"><img src="https://avatars.githubusercontent.com/u/100207562?v=4?s=100" width="100px;" alt="ByteIDance"/><br /><sub><b>ByteIDance</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ByteIDance" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mangel2002"><img src="https://avatars.githubusercontent.com/u/9348020?v=4?s=100" width="100px;" alt="Jangfe"/><br /><sub><b>Jangfe</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=mangel2002" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zqr10159"><img src="https://avatars.githubusercontent.com/u/30048352?v=4?s=100" width="100px;" alt="zqr10159"/><br /><sub><b>zqr10159</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=zqr10159" title="Documentation">📖</a> <a href="https://github.com/apache/hertzbeat/commits?author=zqr10159" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/vinci-897"><img src="https://avatars.githubusercontent.com/u/55838224?v=4?s=100" width="100px;" alt="vinci"/><br /><sub><b>vinci</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=vinci-897" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=vinci-897" title="Documentation">📖</a> <a href="#design-vinci-897" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/js110"><img src="https://avatars.githubusercontent.com/u/51191863?v=4?s=100" width="100px;" alt="js110"/><br /><sub><b>js110</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=js110" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/JavaLionLi"><img src="https://avatars.githubusercontent.com/u/31852897?v=4?s=100" width="100px;" alt="CrazyLionLi"/><br /><sub><b>CrazyLionLi</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=JavaLionLi" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.banmajio.com"><img src="https://avatars.githubusercontent.com/u/53471385?v=4?s=100" width="100px;" alt="banmajio"/><br /><sub><b>banmajio</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=banmajio" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://suder.fun"><img src="https://avatars.githubusercontent.com/u/69955165?v=4?s=100" width="100px;" alt="topsuder"/><br /><sub><b>topsuder</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=topsuder" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/richar2022"><img src="https://avatars.githubusercontent.com/u/129016397?v=4?s=100" width="100px;" alt="richar2022"/><br /><sub><b>richar2022</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=richar2022" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/fcb-xiaobo"><img src="https://avatars.githubusercontent.com/u/60566194?v=4?s=100" width="100px;" alt="fcb-xiaobo"/><br /><sub><b>fcb-xiaobo</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=fcb-xiaobo" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wenkyzhang"><img src="https://avatars.githubusercontent.com/u/13983669?v=4?s=100" width="100px;" alt="wenkyzhang"/><br /><sub><b>wenkyzhang</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=wenkyzhang" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ZangJuxy"><img src="https://avatars.githubusercontent.com/u/71380295?v=4?s=100" width="100px;" alt="ZangJuxy"/><br /><sub><b>ZangJuxy</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=ZangJuxy" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/JavaLionLi"><img src="https://avatars.githubusercontent.com/u/31852897?v=4?s=100" width="100px;" alt="CrazyLionLi"/><br /><sub><b>CrazyLionLi</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=JavaLionLi" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.banmajio.com"><img src="https://avatars.githubusercontent.com/u/53471385?v=4?s=100" width="100px;" alt="banmajio"/><br /><sub><b>banmajio</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=banmajio" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://suder.fun"><img src="https://avatars.githubusercontent.com/u/69955165?v=4?s=100" width="100px;" alt="topsuder"/><br /><sub><b>topsuder</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=topsuder" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/richar2022"><img src="https://avatars.githubusercontent.com/u/129016397?v=4?s=100" width="100px;" alt="richar2022"/><br /><sub><b>richar2022</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=richar2022" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/fcb-xiaobo"><img src="https://avatars.githubusercontent.com/u/60566194?v=4?s=100" width="100px;" alt="fcb-xiaobo"/><br /><sub><b>fcb-xiaobo</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=fcb-xiaobo" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wenkyzhang"><img src="https://avatars.githubusercontent.com/u/13983669?v=4?s=100" width="100px;" alt="wenkyzhang"/><br /><sub><b>wenkyzhang</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=wenkyzhang" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ZangJuxy"><img src="https://avatars.githubusercontent.com/u/71380295?v=4?s=100" width="100px;" alt="ZangJuxy"/><br /><sub><b>ZangJuxy</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ZangJuxy" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/l646505418"><img src="https://avatars.githubusercontent.com/u/50475131?v=4?s=100" width="100px;" alt="l646505418"/><br /><sub><b>l646505418</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=l646505418" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.carpewang.com"><img src="https://avatars.githubusercontent.com/u/78642589?v=4?s=100" width="100px;" alt="Carpe-Wang"/><br /><sub><b>Carpe-Wang</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=Carpe-Wang" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/moshu023"><img src="https://avatars.githubusercontent.com/u/48593205?v=4?s=100" width="100px;" alt="莫枢"/><br /><sub><b>莫枢</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=moshu023" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/huangcanda"><img src="https://avatars.githubusercontent.com/u/4470566?v=4?s=100" width="100px;" alt="huangcanda"/><br /><sub><b>huangcanda</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=huangcanda" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.zrkizzy.com"><img src="https://avatars.githubusercontent.com/u/85340613?v=4?s=100" width="100px;" alt="世纪末的架构师"/><br /><sub><b>世纪末的架构师</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=Architect-Java" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ShuningWan"><img src="https://avatars.githubusercontent.com/u/31086770?v=4?s=100" width="100px;" alt="ShuningWan"/><br /><sub><b>ShuningWan</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=ShuningWan" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MrYZhou"><img src="https://avatars.githubusercontent.com/u/44339602?v=4?s=100" width="100px;" alt="MrYZhou"/><br /><sub><b>MrYZhou</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=MrYZhou" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/l646505418"><img src="https://avatars.githubusercontent.com/u/50475131?v=4?s=100" width="100px;" alt="l646505418"/><br /><sub><b>l646505418</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=l646505418" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.carpewang.com"><img src="https://avatars.githubusercontent.com/u/78642589?v=4?s=100" width="100px;" alt="Carpe-Wang"/><br /><sub><b>Carpe-Wang</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Carpe-Wang" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/moshu023"><img src="https://avatars.githubusercontent.com/u/48593205?v=4?s=100" width="100px;" alt="莫枢"/><br /><sub><b>莫枢</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=moshu023" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/huangcanda"><img src="https://avatars.githubusercontent.com/u/4470566?v=4?s=100" width="100px;" alt="huangcanda"/><br /><sub><b>huangcanda</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=huangcanda" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.zrkizzy.com"><img src="https://avatars.githubusercontent.com/u/85340613?v=4?s=100" width="100px;" alt="世纪末的架构师"/><br /><sub><b>世纪末的架构师</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Architect-Java" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ShuningWan"><img src="https://avatars.githubusercontent.com/u/31086770?v=4?s=100" width="100px;" alt="ShuningWan"/><br /><sub><b>ShuningWan</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ShuningWan" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MrYZhou"><img src="https://avatars.githubusercontent.com/u/44339602?v=4?s=100" width="100px;" alt="MrYZhou"/><br /><sub><b>MrYZhou</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=MrYZhou" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/suncqujsj"><img src="https://avatars.githubusercontent.com/u/8012932?v=4?s=100" width="100px;" alt="suncqujsj"/><br /><sub><b>suncqujsj</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=suncqujsj" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sunqinbo"><img src="https://avatars.githubusercontent.com/u/1428540?v=4?s=100" width="100px;" alt="sunqinbo"/><br /><sub><b>sunqinbo</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=sunqinbo" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/haoww"><img src="https://avatars.githubusercontent.com/u/32739294?v=4?s=100" width="100px;" alt="haoww"/><br /><sub><b>haoww</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=haoww" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/i-mayuan"><img src="https://avatars.githubusercontent.com/u/101498477?v=4?s=100" width="100px;" alt="i-mayuan"/><br /><sub><b>i-mayuan</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=i-mayuan" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/fengruge"><img src="https://avatars.githubusercontent.com/u/85803831?v=4?s=100" width="100px;" alt="fengruge"/><br /><sub><b>fengruge</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=fengruge" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/aystzh"><img src="https://avatars.githubusercontent.com/u/38125392?v=4?s=100" width="100px;" alt="zhanghuan"/><br /><sub><b>zhanghuan</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=aystzh" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/shenyumin"><img src="https://avatars.githubusercontent.com/u/8438506?v=4?s=100" width="100px;" alt="shenymin"/><br /><sub><b>shenymin</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=shenyumin" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/suncqujsj"><img src="https://avatars.githubusercontent.com/u/8012932?v=4?s=100" width="100px;" alt="suncqujsj"/><br /><sub><b>suncqujsj</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=suncqujsj" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sunqinbo"><img src="https://avatars.githubusercontent.com/u/1428540?v=4?s=100" width="100px;" alt="sunqinbo"/><br /><sub><b>sunqinbo</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=sunqinbo" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/haoww"><img src="https://avatars.githubusercontent.com/u/32739294?v=4?s=100" width="100px;" alt="haoww"/><br /><sub><b>haoww</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=haoww" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/i-mayuan"><img src="https://avatars.githubusercontent.com/u/101498477?v=4?s=100" width="100px;" alt="i-mayuan"/><br /><sub><b>i-mayuan</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=i-mayuan" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/fengruge"><img src="https://avatars.githubusercontent.com/u/85803831?v=4?s=100" width="100px;" alt="fengruge"/><br /><sub><b>fengruge</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=fengruge" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/aystzh"><img src="https://avatars.githubusercontent.com/u/38125392?v=4?s=100" width="100px;" alt="zhanghuan"/><br /><sub><b>zhanghuan</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=aystzh" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/shenyumin"><img src="https://avatars.githubusercontent.com/u/8438506?v=4?s=100" width="100px;" alt="shenymin"/><br /><sub><b>shenymin</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=shenyumin" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/dhruva1995"><img src="https://avatars.githubusercontent.com/u/12976351?v=4?s=100" width="100px;" alt="Dhruva Chandra"/><br /><sub><b>Dhruva Chandra</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=dhruva1995" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/weiwang988"><img src="https://avatars.githubusercontent.com/u/58241726?v=4?s=100" width="100px;" alt="miss_z"/><br /><sub><b>miss_z</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=weiwang988" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wyt990"><img src="https://avatars.githubusercontent.com/u/86013697?v=4?s=100" width="100px;" alt="wyt990"/><br /><sub><b>wyt990</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=wyt990" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/licocon"><img src="https://avatars.githubusercontent.com/u/36863277?v=4?s=100" width="100px;" alt="licocon"/><br /><sub><b>licocon</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=licocon" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/2406450951"><img src="https://avatars.githubusercontent.com/u/48074721?v=4?s=100" width="100px;" alt="Mi Na"/><br /><sub><b>Mi Na</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=2406450951" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Kylin-Guo"><img src="https://avatars.githubusercontent.com/u/131239856?v=4?s=100" width="100px;" alt="Kylin-Guo"/><br /><sub><b>Kylin-Guo</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=Kylin-Guo" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/1797899698"><img src="https://avatars.githubusercontent.com/u/40411650?v=4?s=100" width="100px;" alt="Mr灬Dong先生"/><br /><sub><b>Mr灬Dong先生</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=1797899698" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/dhruva1995"><img src="https://avatars.githubusercontent.com/u/12976351?v=4?s=100" width="100px;" alt="Dhruva Chandra"/><br /><sub><b>Dhruva Chandra</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=dhruva1995" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/weiwang988"><img src="https://avatars.githubusercontent.com/u/58241726?v=4?s=100" width="100px;" alt="miss_z"/><br /><sub><b>miss_z</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=weiwang988" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wyt990"><img src="https://avatars.githubusercontent.com/u/86013697?v=4?s=100" width="100px;" alt="wyt990"/><br /><sub><b>wyt990</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=wyt990" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/licocon"><img src="https://avatars.githubusercontent.com/u/36863277?v=4?s=100" width="100px;" alt="licocon"/><br /><sub><b>licocon</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=licocon" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/2406450951"><img src="https://avatars.githubusercontent.com/u/48074721?v=4?s=100" width="100px;" alt="Mi Na"/><br /><sub><b>Mi Na</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=2406450951" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Kylin-Guo"><img src="https://avatars.githubusercontent.com/u/131239856?v=4?s=100" width="100px;" alt="Kylin-Guo"/><br /><sub><b>Kylin-Guo</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Kylin-Guo" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/1797899698"><img src="https://avatars.githubusercontent.com/u/40411650?v=4?s=100" width="100px;" alt="Mr灬Dong先生"/><br /><sub><b>Mr灬Dong先生</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=1797899698" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="http://neilblaze.live"><img src="https://avatars.githubusercontent.com/u/48355572?v=4?s=100" width="100px;" alt="Pratyay Banerjee"/><br /><sub><b>Pratyay Banerjee</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=Neilblaze" title="Documentation">📖</a> <a href="https://github.com/dromara/hertzbeat/commits?author=Neilblaze" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yujianzhong520"><img src="https://avatars.githubusercontent.com/u/63705063?v=4?s=100" width="100px;" alt="yujianzhong520"/><br /><sub><b>yujianzhong520</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=yujianzhong520" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://sppan24.github.io/"><img src="https://avatars.githubusercontent.com/u/15795173?v=4?s=100" width="100px;" alt="SPPan"/><br /><sub><b>SPPan</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=sppan24" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/1130600015"><img src="https://avatars.githubusercontent.com/u/67859663?v=4?s=100" width="100px;" alt="ZhangJiashu"/><br /><sub><b>ZhangJiashu</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=1130600015" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/QZmp236478"><img src="https://avatars.githubusercontent.com/u/56623162?v=4?s=100" width="100px;" alt="impress"/><br /><sub><b>impress</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=QZmp236478" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jx3775250"><img src="https://avatars.githubusercontent.com/u/40455946?v=4?s=100" width="100px;" alt="凌晨一点半"/><br /><sub><b>凌晨一点半</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=jx3775250" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/eeshaanSA"><img src="https://avatars.githubusercontent.com/u/100678386?v=4?s=100" width="100px;" alt="Eeshaan Sawant"/><br /><sub><b>Eeshaan Sawant</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=eeshaanSA" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://neilblaze.live"><img src="https://avatars.githubusercontent.com/u/48355572?v=4?s=100" width="100px;" alt="Pratyay Banerjee"/><br /><sub><b>Pratyay Banerjee</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Neilblaze" title="Documentation">📖</a> <a href="https://github.com/apache/hertzbeat/commits?author=Neilblaze" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yujianzhong520"><img src="https://avatars.githubusercontent.com/u/63705063?v=4?s=100" width="100px;" alt="yujianzhong520"/><br /><sub><b>yujianzhong520</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=yujianzhong520" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://sppan24.github.io/"><img src="https://avatars.githubusercontent.com/u/15795173?v=4?s=100" width="100px;" alt="SPPan"/><br /><sub><b>SPPan</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=sppan24" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/1130600015"><img src="https://avatars.githubusercontent.com/u/67859663?v=4?s=100" width="100px;" alt="ZhangJiashu"/><br /><sub><b>ZhangJiashu</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=1130600015" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/QZmp236478"><img src="https://avatars.githubusercontent.com/u/56623162?v=4?s=100" width="100px;" alt="impress"/><br /><sub><b>impress</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=QZmp236478" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jx3775250"><img src="https://avatars.githubusercontent.com/u/40455946?v=4?s=100" width="100px;" alt="凌晨一点半"/><br /><sub><b>凌晨一点半</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=jx3775250" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/eeshaanSA"><img src="https://avatars.githubusercontent.com/u/100678386?v=4?s=100" width="100px;" alt="Eeshaan Sawant"/><br /><sub><b>Eeshaan Sawant</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=eeshaanSA" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/nandofromthebando"><img src="https://avatars.githubusercontent.com/u/87321214?v=4?s=100" width="100px;" alt="nandofromthebando"/><br /><sub><b>nandofromthebando</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=nandofromthebando" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/caiboking"><img src="https://avatars.githubusercontent.com/u/6509883?v=4?s=100" width="100px;" alt="caiboking"/><br /><sub><b>caiboking</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=caiboking" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/baixing99"><img src="https://avatars.githubusercontent.com/u/73473087?v=4?s=100" width="100px;" alt="baixing99"/><br /><sub><b>baixing99</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=baixing99" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ifrenzyc"><img src="https://avatars.githubusercontent.com/u/543927?v=4?s=100" width="100px;" alt="Yang Chuang"/><br /><sub><b>Yang Chuang</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=ifrenzyc" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wlin20"><img src="https://avatars.githubusercontent.com/u/20657577?v=4?s=100" width="100px;" alt="wlin20"/><br /><sub><b>wlin20</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=wlin20" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/guojing1983"><img src="https://avatars.githubusercontent.com/u/60596094?v=4?s=100" width="100px;" alt="guojing1983"/><br /><sub><b>guojing1983</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=guojing1983" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/itxxq"><img src="https://avatars.githubusercontent.com/u/46962357?v=4?s=100" width="100px;" alt="moxi"/><br /><sub><b>moxi</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=itxxq" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/nandofromthebando"><img src="https://avatars.githubusercontent.com/u/87321214?v=4?s=100" width="100px;" alt="nandofromthebando"/><br /><sub><b>nandofromthebando</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=nandofromthebando" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/caiboking"><img src="https://avatars.githubusercontent.com/u/6509883?v=4?s=100" width="100px;" alt="caiboking"/><br /><sub><b>caiboking</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=caiboking" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/baixing99"><img src="https://avatars.githubusercontent.com/u/73473087?v=4?s=100" width="100px;" alt="baixing99"/><br /><sub><b>baixing99</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=baixing99" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ifrenzyc"><img src="https://avatars.githubusercontent.com/u/543927?v=4?s=100" width="100px;" alt="Yang Chuang"/><br /><sub><b>Yang Chuang</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ifrenzyc" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wlin20"><img src="https://avatars.githubusercontent.com/u/20657577?v=4?s=100" width="100px;" alt="wlin20"/><br /><sub><b>wlin20</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=wlin20" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/guojing1983"><img src="https://avatars.githubusercontent.com/u/60596094?v=4?s=100" width="100px;" alt="guojing1983"/><br /><sub><b>guojing1983</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=guojing1983" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/itxxq"><img src="https://avatars.githubusercontent.com/u/46962357?v=4?s=100" width="100px;" alt="moxi"/><br /><sub><b>moxi</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=itxxq" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/qq471754603"><img src="https://avatars.githubusercontent.com/u/23146592?v=4?s=100" width="100px;" alt="qq471754603"/><br /><sub><b>qq471754603</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=qq471754603" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/san346596324"><img src="https://avatars.githubusercontent.com/u/30828520?v=4?s=100" width="100px;" alt="渭雨"/><br /><sub><b>渭雨</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=san346596324" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/luoxuanzao"><img src="https://avatars.githubusercontent.com/u/44692579?v=4?s=100" width="100px;" alt="liuxuezhuo"/><br /><sub><b>liuxuezhuo</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=luoxuanzao" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lisongning"><img src="https://avatars.githubusercontent.com/u/93140178?v=4?s=100" width="100px;" alt="lisongning"/><br /><sub><b>lisongning</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=lisongning" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/YutingNie"><img src="https://avatars.githubusercontent.com/u/104416402?v=4?s=100" width="100px;" alt="YutingNie"/><br /><sub><b>YutingNie</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=YutingNie" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=YutingNie" title="Documentation">📖</a> <a href="#design-YutingNie" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mikezzb"><img src="https://avatars.githubusercontent.com/u/23418428?v=4?s=100" width="100px;" alt="Mike Zhou"/><br /><sub><b>Mike Zhou</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=mikezzb" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=mikezzb" title="Documentation">📖</a> <a href="#design-mikezzb" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/a-little-fool"><img src="https://avatars.githubusercontent.com/u/105542329?v=4?s=100" width="100px;" alt="小笨蛋"/><br /><sub><b>小笨蛋</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=a-little-fool" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/qq471754603"><img src="https://avatars.githubusercontent.com/u/23146592?v=4?s=100" width="100px;" alt="qq471754603"/><br /><sub><b>qq471754603</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=qq471754603" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/san346596324"><img src="https://avatars.githubusercontent.com/u/30828520?v=4?s=100" width="100px;" alt="渭雨"/><br /><sub><b>渭雨</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=san346596324" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/luoxuanzao"><img src="https://avatars.githubusercontent.com/u/44692579?v=4?s=100" width="100px;" alt="liuxuezhuo"/><br /><sub><b>liuxuezhuo</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=luoxuanzao" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lisongning"><img src="https://avatars.githubusercontent.com/u/93140178?v=4?s=100" width="100px;" alt="lisongning"/><br /><sub><b>lisongning</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=lisongning" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/YutingNie"><img src="https://avatars.githubusercontent.com/u/104416402?v=4?s=100" width="100px;" alt="YutingNie"/><br /><sub><b>YutingNie</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=YutingNie" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=YutingNie" title="Documentation">📖</a> <a href="#design-YutingNie" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mikezzb"><img src="https://avatars.githubusercontent.com/u/23418428?v=4?s=100" width="100px;" alt="Mike Zhou"/><br /><sub><b>Mike Zhou</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=mikezzb" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=mikezzb" title="Documentation">📖</a> <a href="#design-mikezzb" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/a-little-fool"><img src="https://avatars.githubusercontent.com/u/105542329?v=4?s=100" width="100px;" alt="小笨蛋"/><br /><sub><b>小笨蛋</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=a-little-fool" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/littlezhongzer"><img src="https://avatars.githubusercontent.com/u/33685289?v=4?s=100" width="100px;" alt="littlezhongzer"/><br /><sub><b>littlezhongzer</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=littlezhongzer" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ChenXiangxxxxx"><img src="https://avatars.githubusercontent.com/u/90089594?v=4?s=100" width="100px;" alt="ChenXiangxxxxx"/><br /><sub><b>ChenXiangxxxxx</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=ChenXiangxxxxx" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Mr-zhou315"><img src="https://avatars.githubusercontent.com/u/10276100?v=4?s=100" width="100px;" alt="Mr.zhou"/><br /><sub><b>Mr.zhou</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=Mr-zhou315" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/XimfengYao"><img src="https://avatars.githubusercontent.com/u/17541537?v=4?s=100" width="100px;" alt="姚贤丰"/><br /><sub><b>姚贤丰</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=XimfengYao" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/LINGLUOJUN"><img src="https://avatars.githubusercontent.com/u/16778977?v=4?s=100" width="100px;" alt="lingluojun"/><br /><sub><b>lingluojun</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=LINGLUOJUN" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.luelueking.com"><img src="https://avatars.githubusercontent.com/u/93204032?v=4?s=100" width="100px;" alt="1ue"/><br /><sub><b>1ue</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=luelueking" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.jimmyqiao.top"><img src="https://avatars.githubusercontent.com/u/67301054?v=4?s=100" width="100px;" alt="qyaaaa"/><br /><sub><b>qyaaaa</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=qyaaaa" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/littlezhongzer"><img src="https://avatars.githubusercontent.com/u/33685289?v=4?s=100" width="100px;" alt="littlezhongzer"/><br /><sub><b>littlezhongzer</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=littlezhongzer" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ChenXiangxxxxx"><img src="https://avatars.githubusercontent.com/u/90089594?v=4?s=100" width="100px;" alt="ChenXiangxxxxx"/><br /><sub><b>ChenXiangxxxxx</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ChenXiangxxxxx" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Mr-zhou315"><img src="https://avatars.githubusercontent.com/u/10276100?v=4?s=100" width="100px;" alt="Mr.zhou"/><br /><sub><b>Mr.zhou</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Mr-zhou315" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/XimfengYao"><img src="https://avatars.githubusercontent.com/u/17541537?v=4?s=100" width="100px;" alt="姚贤丰"/><br /><sub><b>姚贤丰</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=XimfengYao" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/LINGLUOJUN"><img src="https://avatars.githubusercontent.com/u/16778977?v=4?s=100" width="100px;" alt="lingluojun"/><br /><sub><b>lingluojun</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=LINGLUOJUN" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.luelueking.com"><img src="https://avatars.githubusercontent.com/u/93204032?v=4?s=100" width="100px;" alt="1ue"/><br /><sub><b>1ue</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=luelueking" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.jimmyqiao.top"><img src="https://avatars.githubusercontent.com/u/67301054?v=4?s=100" width="100px;" alt="qyaaaa"/><br /><sub><b>qyaaaa</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=qyaaaa" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://novohit.top"><img src="https://avatars.githubusercontent.com/u/101090395?v=4?s=100" width="100px;" alt="novohit"/><br /><sub><b>novohit</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=novohit" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/rbsrcy"><img src="https://avatars.githubusercontent.com/u/4798540?v=4?s=100" width="100px;" alt="zhuoshangyi"/><br /><sub><b>zhuoshangyi</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=rbsrcy" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ruanliang-hualun"><img src="https://avatars.githubusercontent.com/u/65543716?v=4?s=100" width="100px;" alt="ruanliang"/><br /><sub><b>ruanliang</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=ruanliang-hualun" title="Documentation">📖</a> <a href="https://github.com/dromara/hertzbeat/commits?author=ruanliang-hualun" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Eden4701"><img src="https://avatars.githubusercontent.com/u/68422437?v=4?s=100" width="100px;" alt="Eden4701"/><br /><sub><b>Eden4701</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=Eden4701" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=Eden4701" title="Documentation">📖</a> <a href="#design-Eden4701" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/XiaTian688"><img src="https://avatars.githubusercontent.com/u/111830921?v=4?s=100" width="100px;" alt="XiaTian688"/><br /><sub><b>XiaTian688</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=XiaTian688" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/liyin"><img src="https://avatars.githubusercontent.com/u/863169?v=4?s=100" width="100px;" alt="liyinjiang"/><br /><sub><b>liyinjiang</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=liyin" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jiashu1024"><img src="https://avatars.githubusercontent.com/u/67859663?v=4?s=100" width="100px;" alt="ZhangJiashu"/><br /><sub><b>ZhangJiashu</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=jiashu1024" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://novohit.top"><img src="https://avatars.githubusercontent.com/u/101090395?v=4?s=100" width="100px;" alt="novohit"/><br /><sub><b>novohit</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=novohit" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/rbsrcy"><img src="https://avatars.githubusercontent.com/u/4798540?v=4?s=100" width="100px;" alt="zhuoshangyi"/><br /><sub><b>zhuoshangyi</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=rbsrcy" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ruanliang-hualun"><img src="https://avatars.githubusercontent.com/u/65543716?v=4?s=100" width="100px;" alt="ruanliang"/><br /><sub><b>ruanliang</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ruanliang-hualun" title="Documentation">📖</a> <a href="https://github.com/apache/hertzbeat/commits?author=ruanliang-hualun" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Eden4701"><img src="https://avatars.githubusercontent.com/u/68422437?v=4?s=100" width="100px;" alt="Eden4701"/><br /><sub><b>Eden4701</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Eden4701" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=Eden4701" title="Documentation">📖</a> <a href="#design-Eden4701" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/XiaTian688"><img src="https://avatars.githubusercontent.com/u/111830921?v=4?s=100" width="100px;" alt="XiaTian688"/><br /><sub><b>XiaTian688</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=XiaTian688" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/liyin"><img src="https://avatars.githubusercontent.com/u/863169?v=4?s=100" width="100px;" alt="liyinjiang"/><br /><sub><b>liyinjiang</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=liyin" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jiashu1024"><img src="https://avatars.githubusercontent.com/u/67859663?v=4?s=100" width="100px;" alt="ZhangJiashu"/><br /><sub><b>ZhangJiashu</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=jiashu1024" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/1036664317"><img src="https://avatars.githubusercontent.com/u/7696697?v=4?s=100" width="100px;" alt="moghn"/><br /><sub><b>moghn</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=1036664317" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xiaoguolong"><img src="https://avatars.githubusercontent.com/u/33684988?v=4?s=100" width="100px;" alt="xiaoguolong"/><br /><sub><b>xiaoguolong</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=xiaoguolong" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Clownsw"><img src="https://avatars.githubusercontent.com/u/28394742?v=4?s=100" width="100px;" alt="Smliexx"/><br /><sub><b>Smliexx</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=Clownsw" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Calvin979"><img src="https://avatars.githubusercontent.com/u/131688897?v=4?s=100" width="100px;" alt="Naruse"/><br /><sub><b>Naruse</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=Calvin979" title="Documentation">📖</a> <a href="https://github.com/dromara/hertzbeat/commits?author=Calvin979" title="Code">💻</a> <a href="#design-Calvin979" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bbelide2"><img src="https://avatars.githubusercontent.com/u/26840796?v=4?s=100" width="100px;" alt="Bala Sukesh"/><br /><sub><b>Bala Sukesh</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=bbelide2" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jinyaoMa"><img src="https://avatars.githubusercontent.com/u/25066570?v=4?s=100" width="100px;" alt="Jinyao Ma"/><br /><sub><b>Jinyao Ma</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=jinyaoMa" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://linuxsuren.github.io/open-source-best-practice/"><img src="https://avatars.githubusercontent.com/u/1450685?v=4?s=100" width="100px;" alt="Rick"/><br /><sub><b>Rick</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=LinuxSuRen" title="Code">💻</a> <a href="https://github.com/dromara/hertzbeat/commits?author=LinuxSuRen" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/1036664317"><img src="https://avatars.githubusercontent.com/u/7696697?v=4?s=100" width="100px;" alt="moghn"/><br /><sub><b>moghn</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=1036664317" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xiaoguolong"><img src="https://avatars.githubusercontent.com/u/33684988?v=4?s=100" width="100px;" alt="xiaoguolong"/><br /><sub><b>xiaoguolong</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=xiaoguolong" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Clownsw"><img src="https://avatars.githubusercontent.com/u/28394742?v=4?s=100" width="100px;" alt="Smliexx"/><br /><sub><b>Smliexx</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Clownsw" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Calvin979"><img src="https://avatars.githubusercontent.com/u/131688897?v=4?s=100" width="100px;" alt="Naruse"/><br /><sub><b>Naruse</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Calvin979" title="Documentation">📖</a> <a href="https://github.com/apache/hertzbeat/commits?author=Calvin979" title="Code">💻</a> <a href="#design-Calvin979" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bbelide2"><img src="https://avatars.githubusercontent.com/u/26840796?v=4?s=100" width="100px;" alt="Bala Sukesh"/><br /><sub><b>Bala Sukesh</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=bbelide2" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jinyaoMa"><img src="https://avatars.githubusercontent.com/u/25066570?v=4?s=100" width="100px;" alt="Jinyao Ma"/><br /><sub><b>Jinyao Ma</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=jinyaoMa" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://linuxsuren.github.io/open-source-best-practice/"><img src="https://avatars.githubusercontent.com/u/1450685?v=4?s=100" width="100px;" alt="Rick"/><br /><sub><b>Rick</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=LinuxSuRen" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=LinuxSuRen" title="Tests">⚠️</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ZY945"><img src="https://avatars.githubusercontent.com/u/74083801?v=4?s=100" width="100px;" alt="东风"/><br /><sub><b>东风</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=ZY945" title="Code">💻</a> <a href="#design-ZY945" title="Design">🎨</a> <a href="https://github.com/dromara/hertzbeat/commits?author=ZY945" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/prolevel1"><img src="https://avatars.githubusercontent.com/u/51995525?v=4?s=100" width="100px;" alt="sonam singh"/><br /><sub><b>sonam singh</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=prolevel1" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ZhangZixuan1994"><img src="https://avatars.githubusercontent.com/u/20011653?v=4?s=100" width="100px;" alt="ZhangZixuan1994"/><br /><sub><b>ZhangZixuan1994</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=ZhangZixuan1994" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hurenjie1"><img src="https://avatars.githubusercontent.com/u/40120355?v=4?s=100" width="100px;" alt="SHIG"/><br /><sub><b>SHIG</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=hurenjie1" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://tslj1024.github.io/"><img src="https://avatars.githubusercontent.com/u/155222677?v=4?s=100" width="100px;" alt="泰上老菌"/><br /><sub><b>泰上老菌</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=tslj1024" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ldysdu"><img src="https://avatars.githubusercontent.com/u/15815338?v=4?s=100" width="100px;" alt="ldysdu"/><br /><sub><b>ldysdu</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=ldysdu" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/GEM0816g"><img src="https://avatars.githubusercontent.com/u/85116017?v=4?s=100" width="100px;" alt="梁同学"/><br /><sub><b>梁同学</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=GEM0816g" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ZY945"><img src="https://avatars.githubusercontent.com/u/74083801?v=4?s=100" width="100px;" alt="东风"/><br /><sub><b>东风</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ZY945" title="Code">💻</a> <a href="#design-ZY945" title="Design">🎨</a> <a href="https://github.com/apache/hertzbeat/commits?author=ZY945" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/prolevel1"><img src="https://avatars.githubusercontent.com/u/51995525?v=4?s=100" width="100px;" alt="sonam singh"/><br /><sub><b>sonam singh</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=prolevel1" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ZhangZixuan1994"><img src="https://avatars.githubusercontent.com/u/20011653?v=4?s=100" width="100px;" alt="ZhangZixuan1994"/><br /><sub><b>ZhangZixuan1994</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ZhangZixuan1994" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hurenjie1"><img src="https://avatars.githubusercontent.com/u/40120355?v=4?s=100" width="100px;" alt="SHIG"/><br /><sub><b>SHIG</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=hurenjie1" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://tslj1024.github.io/"><img src="https://avatars.githubusercontent.com/u/155222677?v=4?s=100" width="100px;" alt="泰上老菌"/><br /><sub><b>泰上老菌</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=tslj1024" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ldysdu"><img src="https://avatars.githubusercontent.com/u/15815338?v=4?s=100" width="100px;" alt="ldysdu"/><br /><sub><b>ldysdu</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ldysdu" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/GEM0816g"><img src="https://avatars.githubusercontent.com/u/85116017?v=4?s=100" width="100px;" alt="梁同学"/><br /><sub><b>梁同学</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=GEM0816g" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/avvCode"><img src="https://avatars.githubusercontent.com/u/113538532?v=4?s=100" width="100px;" alt="avv"/><br /><sub><b>avv</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=avvCode" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yqxxgh"><img src="https://avatars.githubusercontent.com/u/42080876?v=4?s=100" width="100px;" alt="yqxxgh"/><br /><sub><b>yqxxgh</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=yqxxgh" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/CharlieShi46"><img src="https://avatars.githubusercontent.com/u/149798885?v=4?s=100" width="100px;" alt="CharlieShi46"/><br /><sub><b>CharlieShi46</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=CharlieShi46" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Nctllnty"><img src="https://avatars.githubusercontent.com/u/33241818?v=4?s=100" width="100px;" alt="Nctllnty"/><br /><sub><b>Nctllnty</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=Nctllnty" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Wang-Yonghao"><img src="https://avatars.githubusercontent.com/u/48146606?v=4?s=100" width="100px;" alt="Wang-Yonghao"/><br /><sub><b>Wang-Yonghao</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=Wang-Yonghao" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.yuque.com/dudiao/yy"><img src="https://avatars.githubusercontent.com/u/38355949?v=4?s=100" width="100px;" alt="读钓"/><br /><sub><b>读钓</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=dudiao" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/starmilkxin"><img src="https://avatars.githubusercontent.com/u/55646681?v=4?s=100" width="100px;" alt="Xin"/><br /><sub><b>Xin</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=starmilkxin" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/avvCode"><img src="https://avatars.githubusercontent.com/u/113538532?v=4?s=100" width="100px;" alt="avv"/><br /><sub><b>avv</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=avvCode" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yqxxgh"><img src="https://avatars.githubusercontent.com/u/42080876?v=4?s=100" width="100px;" alt="yqxxgh"/><br /><sub><b>yqxxgh</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=yqxxgh" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/CharlieShi46"><img src="https://avatars.githubusercontent.com/u/149798885?v=4?s=100" width="100px;" alt="CharlieShi46"/><br /><sub><b>CharlieShi46</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=CharlieShi46" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Nctllnty"><img src="https://avatars.githubusercontent.com/u/33241818?v=4?s=100" width="100px;" alt="Nctllnty"/><br /><sub><b>Nctllnty</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Nctllnty" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Wang-Yonghao"><img src="https://avatars.githubusercontent.com/u/48146606?v=4?s=100" width="100px;" alt="Wang-Yonghao"/><br /><sub><b>Wang-Yonghao</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Wang-Yonghao" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.yuque.com/dudiao/yy"><img src="https://avatars.githubusercontent.com/u/38355949?v=4?s=100" width="100px;" alt="读钓"/><br /><sub><b>读钓</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=dudiao" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/starmilkxin"><img src="https://avatars.githubusercontent.com/u/55646681?v=4?s=100" width="100px;" alt="Xin"/><br /><sub><b>Xin</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=starmilkxin" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/handy-git"><img src="https://avatars.githubusercontent.com/u/32837980?v=4?s=100" width="100px;" alt="handy"/><br /><sub><b>handy</b></sub></a><br /><a href="https://github.com/dromara/hertzbeat/commits?author=handy-git" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/handy-git"><img src="https://avatars.githubusercontent.com/u/32837980?v=4?s=100" width="100px;" alt="handy"/><br /><sub><b>handy</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=handy-git" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/LiuTianyou"><img src="https://avatars.githubusercontent.com/u/30208283?v=4?s=100" width="100px;" alt="LiuTianyou"/><br /><sub><b>LiuTianyou</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=LiuTianyou" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=LiuTianyou" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/WinterKi1ler"><img src="https://avatars.githubusercontent.com/u/160592092?v=4?s=100" width="100px;" alt="WinterKi1ler"/><br /><sub><b>WinterKi1ler</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=WinterKi1ler" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://sharehoo.cn/"><img src="https://avatars.githubusercontent.com/u/45377370?v=4?s=100" width="100px;" alt="miki"/><br /><sub><b>miki</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=miki-hmt" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://codeflex.substack.com/"><img src="https://avatars.githubusercontent.com/u/85513042?v=4?s=100" width="100px;" alt="Keshav Carpenter"/><br /><sub><b>Keshav Carpenter</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=alpha951" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=alpha951" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/makechoicenow"><img src="https://avatars.githubusercontent.com/u/9911918?v=4?s=100" width="100px;" alt="makechoicenow"/><br /><sub><b>makechoicenow</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=makechoicenow" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/gjjjj0101"><img src="https://avatars.githubusercontent.com/u/71874373?v=4?s=100" width="100px;" alt="Gao Jian"/><br /><sub><b>Gao Jian</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=gjjjj0101" title="Code">💻</a> <a href="#design-gjjjj0101" title="Design">🎨</a> <a href="https://github.com/apache/hertzbeat/commits?author=gjjjj0101" title="Tests">⚠️</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://jangto.tistory.com/"><img src="https://avatars.githubusercontent.com/u/37864182?v=4?s=100" width="100px;" alt="Hyeon Sung"/><br /><sub><b>Hyeon Sung</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=dukbong" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://crossoverjie.top/"><img src="https://avatars.githubusercontent.com/u/15684156?v=4?s=100" width="100px;" alt="crossoverJie"/><br /><sub><b>crossoverJie</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=crossoverJie" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=crossoverJie" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/PeixyJ"><img src="https://avatars.githubusercontent.com/u/45998593?v=4?s=100" width="100px;" alt="PeixyJ"/><br /><sub><b>PeixyJ</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=PeixyJ" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Hi-Mr-Wind"><img src="https://avatars.githubusercontent.com/u/85803831?v=4?s=100" width="100px;" alt="风如歌"/><br /><sub><b>风如歌</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Hi-Mr-Wind" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MananPoojara"><img src="https://avatars.githubusercontent.com/u/104253184?v=4?s=100" width="100px;" alt="Manan Pujara"/><br /><sub><b>Manan Pujara</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=MananPoojara" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xuziyang"><img src="https://avatars.githubusercontent.com/u/8465969?v=4?s=100" width="100px;" alt="xuziyang"/><br /><sub><b>xuziyang</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=xuziyang" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lwqzz"><img src="https://avatars.githubusercontent.com/u/62584513?v=4?s=100" width="100px;" alt="lwqzz"/><br /><sub><b>lwqzz</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=lwqzz" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/YxYL6125"><img src="https://avatars.githubusercontent.com/u/91076160?v=4?s=100" width="100px;" alt="YxYL"/><br /><sub><b>YxYL</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=YxYL6125" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/tomorrowshipyltm"><img src="https://avatars.githubusercontent.com/u/61336903?v=4?s=100" width="100px;" alt="tomorrowshipyltm"/><br /><sub><b>tomorrowshipyltm</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=tomorrowshipyltm" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/15613060203"><img src="https://avatars.githubusercontent.com/u/41351615?v=4?s=100" width="100px;" alt="栗磊"/><br /><sub><b>栗磊</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=15613060203" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Alanxtl"><img src="https://avatars.githubusercontent.com/u/25652981?v=4?s=100" width="100px;" alt="Alan"/><br /><sub><b>Alan</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Alanxtl" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.hadoop.wiki/"><img src="https://avatars.githubusercontent.com/u/29418975?v=4?s=100" width="100px;" alt="Jast"/><br /><sub><b>Jast</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=zhangshenghang" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zuobiao-zhou"><img src="https://avatars.githubusercontent.com/u/61108539?v=4?s=100" width="100px;" alt="Zhang Yuxuan"/><br /><sub><b>Zhang Yuxuan</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=zuobiao-zhou" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Pzz-2021"><img src="https://avatars.githubusercontent.com/u/118056735?v=4?s=100" width="100px;" alt="P.P."/><br /><sub><b>P.P.</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Pzz-2021" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/LLP2333"><img src="https://avatars.githubusercontent.com/u/61670545?v=4?s=100" width="100px;" alt="llp2333"/><br /><sub><b>llp2333</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=LLP2333" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/HeartLinked"><img src="https://avatars.githubusercontent.com/u/78212101?v=4?s=100" width="100px;" alt="feiyang li"/><br /><sub><b>feiyang li</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=HeartLinked" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Aias00"><img src="https://avatars.githubusercontent.com/u/25810623?v=4?s=100" width="100px;" alt="aias00"/><br /><sub><b>aias00</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Aias00" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/westboy"><img src="https://avatars.githubusercontent.com/u/6385565?v=4?s=100" width="100px;" alt="Jin"/><br /><sub><b>Jin</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=westboy" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://blog.csdn.net/qq_52397471"><img src="https://avatars.githubusercontent.com/u/77964041?v=4?s=100" width="100px;" alt="YuLuo"/><br /><sub><b>YuLuo</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=yuluo-yx" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Yanshuming1"><img src="https://avatars.githubusercontent.com/u/118667222?v=4?s=100" width="100px;" alt="linDong"/><br /><sub><b>linDong</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Yanshuming1" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lwjxy"><img src="https://avatars.githubusercontent.com/u/52726400?v=4?s=100" width="100px;" alt="lwjxy"/><br /><sub><b>lwjxy</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=lwjxy" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://thespica.github.io/"><img src="https://avatars.githubusercontent.com/u/119573640?v=4?s=100" width="100px;" alt="John"/><br /><sub><b>John</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Thespica" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=Thespica" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/boatrainlsz"><img src="https://avatars.githubusercontent.com/u/18243785?v=4?s=100" width="100px;" alt="boatrainlsz"/><br /><sub><b>boatrainlsz</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=boatrainlsz" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.yitianyigexiangfa.com/"><img src="https://avatars.githubusercontent.com/u/3973419?v=4?s=100" width="100px;" alt="Bill Lau"/><br /><sub><b>Bill Lau</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=JavaProgrammerLB" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lw-yang"><img src="https://avatars.githubusercontent.com/u/23456873?v=4?s=100" width="100px;" alt="lwyang"/><br /><sub><b>lwyang</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=lw-yang" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xfl12345"><img src="https://avatars.githubusercontent.com/u/17960863?v=4?s=100" width="100px;" alt="xfl12345"/><br /><sub><b>xfl12345</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=xfl12345" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yykaue"><img src="https://avatars.githubusercontent.com/u/22905143?v=4?s=100" width="100px;" alt="Limbo"/><br /><sub><b>Limbo</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=yykaue" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/irenhongyan"><img src="https://avatars.githubusercontent.com/u/53438321?v=4?s=100" width="100px;" alt="哈哈哈哈哈哈哈哈哈"/><br /><sub><b>哈哈哈哈哈哈哈哈哈</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=irenhongyan" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ileonli"><img src="https://avatars.githubusercontent.com/u/45332412?v=4?s=100" width="100px;" alt="Leon Li"/><br /><sub><b>Leon Li</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ileonli" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://fnil.net/"><img src="https://avatars.githubusercontent.com/u/14142?v=4?s=100" width="100px;" alt="dennis zhuang"/><br /><sub><b>dennis zhuang</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=killme2008" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/kerwin612"><img src="https://avatars.githubusercontent.com/u/3371163?v=4?s=100" width="100px;" alt="Kerwin Bryant"/><br /><sub><b>Kerwin Bryant</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=kerwin612" title="Code">💻</a> <a href="#design-kerwin612" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ShineDevelopment"><img src="https://avatars.githubusercontent.com/u/59306780?v=4?s=100" width="100px;" alt="daixianglong"/><br /><sub><b>daixianglong</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ShineDevelopment" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mchgood"><img src="https://avatars.githubusercontent.com/u/38482005?v=4?s=100" width="100px;" alt="mchgood"/><br /><sub><b>mchgood</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=mchgood" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/pwallk"><img src="https://avatars.githubusercontent.com/u/69385076?v=4?s=100" width="100px;" alt="kangli"/><br /><sub><b>kangli</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=pwallk" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/cdphantom"><img src="https://avatars.githubusercontent.com/u/12674795?v=4?s=100" width="100px;" alt="cdphantom"/><br /><sub><b>cdphantom</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=cdphantom" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/asd108908382"><img src="https://avatars.githubusercontent.com/u/77717999?v=4?s=100" width="100px;" alt="jiawei.guo"/><br /><sub><b>jiawei.guo</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=asd108908382" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/QBH-insist"><img src="https://avatars.githubusercontent.com/u/39401478?v=4?s=100" width="100px;" alt="QBH-insist"/><br /><sub><b>QBH-insist</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=QBH-insist" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jiangsh-ui"><img src="https://avatars.githubusercontent.com/u/86990361?v=4?s=100" width="100px;" alt="jiangsh"/><br /><sub><b>jiangsh</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=jiangsh-ui" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/keaifafafa"><img src="https://avatars.githubusercontent.com/u/83876361?v=4?s=100" width="100px;" alt="Keaifa"/><br /><sub><b>Keaifa</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=keaifafafa" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/loong95"><img src="https://avatars.githubusercontent.com/u/16333958?v=4?s=100" width="100px;" alt="Loong"/><br /><sub><b>Loong</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=loong95" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ceekay47"><img src="https://avatars.githubusercontent.com/u/104664857?v=4?s=100" width="100px;" alt="Chandrakant Vankayalapati"/><br /><sub><b>Chandrakant Vankayalapati</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ceekay47" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MRgenial"><img src="https://avatars.githubusercontent.com/u/49973336?v=4?s=100" width="100px;" alt="b_mountain"/><br /><sub><b>b_mountain</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=MRgenial" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/TemirlanBasitov"><img src="https://avatars.githubusercontent.com/u/57500808?v=4?s=100" width="100px;" alt="TemirlanBasitov"/><br /><sub><b>TemirlanBasitov</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=TemirlanBasitov" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wyfvsfy"><img src="https://avatars.githubusercontent.com/u/11973517?v=4?s=100" width="100px;" alt="wyfvsfy"/><br /><sub><b>wyfvsfy</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=wyfvsfy" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sherry-peng2333"><img src="https://avatars.githubusercontent.com/u/70619577?v=4?s=100" width="100px;" alt="sherry-peng2333"/><br /><sub><b>sherry-peng2333</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=sherry-peng2333" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lixiaobaivv"><img src="https://avatars.githubusercontent.com/u/39290771?v=4?s=100" width="100px;" alt="Yzzz"/><br /><sub><b>Yzzz</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=lixiaobaivv" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.bckf.cn/"><img src="https://avatars.githubusercontent.com/u/13309008?v=4?s=100" width="100px;" alt="puruidong"/><br /><sub><b>puruidong</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=pruidong" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/shinestare"><img src="https://avatars.githubusercontent.com/u/13570619?v=4?s=100" width="100px;" alt="shinestare"/><br /><sub><b>shinestare</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=shinestare" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/po-168"><img src="https://avatars.githubusercontent.com/u/185745593?v=4?s=100" width="100px;" alt="po-168"/><br /><sub><b>po-168</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=po-168" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/All-The-Best-for"><img src="https://avatars.githubusercontent.com/u/76414672?v=4?s=100" width="100px;" alt="wbs99"/><br /><sub><b>wbs99</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=All-The-Best-for" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/starryCoder"><img src="https://avatars.githubusercontent.com/u/46510059?v=4?s=100" width="100px;" alt="starryCoder"/><br /><sub><b>starryCoder</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=starryCoder" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hasimmollah"><img src="https://avatars.githubusercontent.com/u/32538599?v=4?s=100" width="100px;" alt="hasimmollah"/><br /><sub><b>hasimmollah</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=hasimmollah" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ayu-v0"><img src="https://avatars.githubusercontent.com/u/127600988?v=4?s=100" width="100px;" alt="Ayu"/><br /><sub><b>Ayu</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ayu-v0" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Rancho-7"><img src="https://avatars.githubusercontent.com/u/59016860?v=4?s=100" width="100px;" alt="Nick Guo"/><br /><sub><b>Nick Guo</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Rancho-7" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/doveLin0818"><img src="https://avatars.githubusercontent.com/u/190927907?v=4?s=100" width="100px;" alt="doveLin"/><br /><sub><b>doveLin</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=doveLin0818" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://zzrl.cc/"><img src="https://avatars.githubusercontent.com/u/91836599?v=4?s=100" width="100px;" alt="yunfan24"/><br /><sub><b>yunfan24</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=yunfan24" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lctking"><img src="https://avatars.githubusercontent.com/u/168249998?v=4?s=100" width="100px;" alt="nullwli"/><br /><sub><b>nullwli</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=lctking" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://simonsigre.com/"><img src="https://avatars.githubusercontent.com/u/14932913?v=4?s=100" width="100px;" alt="Simon Sigré"/><br /><sub><b>Simon Sigré</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=simonsigre" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.ponfee.cn/"><img src="https://avatars.githubusercontent.com/u/46117331?v=4?s=100" width="100px;" alt="ponfee"/><br /><sub><b>ponfee</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ponfee" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Vedant7789"><img src="https://avatars.githubusercontent.com/u/147625492?v=4?s=100" width="100px;" alt="Vedant7789"/><br /><sub><b>Vedant7789</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Vedant7789" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Craaaaazy77"><img src="https://avatars.githubusercontent.com/u/23025522?v=4?s=100" width="100px;" alt="Craaaaazy77"/><br /><sub><b>Craaaaazy77</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Craaaaazy77" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Suvrat1629"><img src="https://avatars.githubusercontent.com/u/140749446?v=4?s=100" width="100px;" alt="Suvrat1629"/><br /><sub><b>Suvrat1629</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Suvrat1629" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://ghyghoo8.github.io/"><img src="https://avatars.githubusercontent.com/u/363129?v=4?s=100" width="100px;" alt="ghy"/><br /><sub><b>ghy</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=ghyghoo8" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/helei1030"><img src="https://avatars.githubusercontent.com/u/11839080?v=4?s=100" width="100px;" alt="helei1030"/><br /><sub><b>helei1030</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=helei1030" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://medium.com/@pjfanning"><img src="https://avatars.githubusercontent.com/u/11783444?v=4?s=100" width="100px;" alt="PJ Fanning"/><br /><sub><b>PJ Fanning</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=pjfanning" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MonsterChenzhuo"><img src="https://avatars.githubusercontent.com/u/60029759?v=4?s=100" width="100px;" alt="monster"/><br /><sub><b>monster</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=MonsterChenzhuo" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MasamiYui"><img src="https://avatars.githubusercontent.com/u/22274133?v=4?s=100" width="100px;" alt="Sherlock Yin"/><br /><sub><b>Sherlock Yin</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=MasamiYui" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wanhao23"><img src="https://avatars.githubusercontent.com/u/29560961?v=4?s=100" width="100px;" alt="wanhao"/><br /><sub><b>wanhao</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=wanhao23" title="Code">💻</a> <a href="https://github.com/apache/hertzbeat/commits?author=wanhao23" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jonasHanhan"><img src="https://avatars.githubusercontent.com/u/130035609?v=4?s=100" width="100px;" alt="jonasHanhan"/><br /><sub><b>jonasHanhan</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=jonasHanhan" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/NikhilMurugesan"><img src="https://avatars.githubusercontent.com/u/49281792?v=4?s=100" width="100px;" alt="NikhilMurugesan"/><br /><sub><b>NikhilMurugesan</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=NikhilMurugesan" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/myangle1120"><img src="https://avatars.githubusercontent.com/u/19237013?v=4?s=100" width="100px;" alt="myangle1120"/><br /><sub><b>myangle1120</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=myangle1120" title="Code">💻</a></td>
</tr>
</tbody>
</table>
@@ -420,17 +517,19 @@ Thanks these wonderful people, welcome to join us:
## 💬 社区交流
HertzBeat 赫兹跳动是 [Dromara开源社区](https://dromara.org/) 下顶级项目。Gitee GVP。
##### Channel
**[Chat On Discord](https://discord.gg/Fb6M73htGr)**
[订阅邮件列表](https://lists.apache.org/list.html?dev@hertzbeat.apache.org) : 发送邮件至 `dev-subscribe@hertzbeat.apache.org` 来订阅邮件列表.
**微信交流群** : Add friend `tan-cloud` and will invite you to the group.
[Chat On Discord](https://discord.gg/Fb6M73htGr)
[QQ交流群](https://jq.qq.com/?_wv=1027&k=Bud9OzdI) : Group num `236915833`
微信交流群 : 加 `ahertzbeat` 好友邀请进群.
[Github Discussion](https://github.com/dromara/hertzbeat/discussions)
微信公众号 : 搜索 ID `usthecom`.
[QQ交流群](https://jq.qq.com/?_wv=1027&k=Bud9OzdI) : 群号 `630061200`
[Github Discussion](https://github.com/apache/hertzbeat/discussions)
[Reddit Community](https://www.reddit.com/r/hertzbeat/)
@@ -438,25 +537,12 @@ HertzBeat 赫兹跳动是 [Dromara开源社区](https://dromara.org/) 下顶级
[Subscribe YouTube](https://www.youtube.com/channel/UCri75zfWX0GHqJFPENEbLow)
##### 友情链接
- [Sa-Token](https://gitee.com/dromara/sa-token) : 一个轻量级 java 权限认证框架,让鉴权变得简单、优雅
- [DynamicTp](https://github.com/dromara/dynamic-tp) : 轻量级动态线程池,内置监控告警功能,集成三方中间件线程池管理,基于主流配置中心
- [Hippo4j](https://github.com/opengoofy/hippo4j/) : 强大的动态线程池框架,附带监控报警功能
- [Jpom](https://gitee.com/dromara/Jpom) : 简而轻的低侵入式在线构建、自动部署、日常运维、项目监控软件
- [ArgusDBM](https://github.com/zmops/ArgusDBM) : 开源数据库一体化监控平台,致力于监控所有数据库
- [WangMarket](http://www.wang.market/) : 开源 SAAS 云建站系统
- [API Testing](https://github.com/LinuxSuRen/api-testing):轻量级、可扩展的接口开发、测试工具
##### 赞助
- 感谢 [吉实信息(构建全新的微波+光交易网络)](https://www.flarespeed.com) 赞助服务器采集节点
##### Open-Source Project Build From Open-Source
HertzBeat is built on so many great open source projects, thanks to them!
- `Java Spring SpringBoot Jpa Maven Assembly Netty Lombok Sureness Aviator Protobuf HttpClient Guava SnakeYaml JsonPath ...`
- `Java Spring SpringBoot Jpa Maven Assembly Netty Lombok Sureness Protobuf HttpClient Guava SnakeYaml JsonPath ...`
- `TypeScript Angular NG-ZORRO NG-ALAIN NodeJs Npm Html Less Echarts Rxjs ZoneJs MonacoEditor SlickCarousel Docusaurus ...`
@@ -469,11 +555,5 @@ HertzBeat has been included in the <a href="https://landscape.cncf.io/guide?item
CNCF Observability And Analysis - Monitoring Landscape.</a>
</p>
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=dromara/hertzbeat&type=Date)](https://star-history.com/#dromara/hertzbeat&Date)
## 🛡️ License
[`Apache License, Version 2.0`](https://www.apache.org/licenses/LICENSE-2.0.html)
+9 -6
View File
@@ -1,12 +1,9 @@
# Security Policy
**[Version Releases](https://github.com/dromara/hertzbeat/releases)**
Apache HertzBeat follows the [ASF vulnerability handling process](https://apache.org/security/#vulnerability-handling)
## Supported Versions
Use this section to tell people about which versions of your project are
currently being supported with security updates.
| Version | Supported |
|-------------------|--------------------|
| Latest Version | :white_check_mark: |
@@ -14,6 +11,12 @@ currently being supported with security updates.
## Reporting a Vulnerability
Use this section to tell people how to report a vulnerability.
Please do not file GitHub issues for security vulnerabilities as they are public!
Please submit your security report by this way [reporting-a-security-vulnerability](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing/privately-reporting-a-security-vulnerability#privately-reporting-a-security-vulnerability)
To report a new vulnerability you have discovered please follow the [ASF vulnerability reporting process](https://apache.org/security/#reporting-a-vulnerability).
## Extra Information
- [Apache HertzBeat Security Model](https://hertzbeat.apache.org/docs/help/security_model)
- [ASF Security](https://www.apache.org/security/)
- [Apache HertzBeat Document](https://hertzbeat.apache.org/docs/)
-4
View File
@@ -1,4 +0,0 @@
### Alerter
Processing data according to threshold rules to determine alarms, and alarm distribution functions.
根据告警规则配置信息,处理指标数据判断告警,告警分发。
-104
View File
@@ -1,104 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<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">
<parent>
<artifactId>hertzbeat</artifactId>
<groupId>org.dromara.hertzbeat</groupId>
<version>2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>hertzbeat-alerter</artifactId>
<name>${project.artifactId}</name>
<properties>
</properties>
<dependencies>
<!-- common -->
<dependency>
<groupId>org.dromara.hertzbeat</groupId>
<artifactId>hertzbeat-common</artifactId>
<scope>provided</scope>
</dependency>
<!-- spring -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- data jdbc -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<scope>provided</scope>
</dependency>
<!-- validation -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<scope>provided</scope>
</dependency>
<!-- kafka -->
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
</dependency>
<!--redis-->
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<scope>provided</scope>
</dependency>
<!-- swagger -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
<version>4.3.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.1</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
@@ -1,120 +0,0 @@
/*
* 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.dromara.hertzbeat.alert;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* alerter prop config
*
*/
@Component
@ConfigurationProperties(prefix = "alerter")
@Getter
@Setter
public class AlerterProperties {
/**
* Alarm content console link
*/
private String consoleUrl = "https://console.tancloud.cn";
/**
* WeWork webhook url
*/
private String weWorkWebHookUrl = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=";
/**
* DingDing talk webhook url
*/
private String dingTalkWebHookUrl = "https://oapi.dingtalk.com/robot/send?access_token=";
/**
* FlyBook webhook url
*/
private String flyBookWebHookUrl = "https://open.feishu.cn/open-apis/bot/v2/hook/";
/**
* Telegram Bot api url
*/
private String telegramBotApiUrl = "https://api.telegram.org/bot%s/sendMessage";
/**
* Discord Notify url
*/
private String discordNotifyUrl = "https://discord.com/api/v9/channels/%s/messages";
/**
* ServerChan Notify url
*/
private String serverChanNotifyUrl = "https://sctapi.ftqq.com/%s.send";
/**
* Gotify Notify url
*/
private String gotifyNotifyUrl = "https://push.example.de/message?token=";
/**
* Data entry configuration properties
*/
private EntranceProperties entrance;
/**
* Data entry configuration properties
*/
@Getter
@Setter
public static class EntranceProperties {
/**
* kafka configuration information
*/
private KafkaProperties kafka;
/**
* kafka configuration information
*/
@Getter
@Setter
public static class KafkaProperties {
/**
* Whether the kafka data entry is started
*/
private boolean enabled = true;
/**
* kafka's connection server url
*/
private String servers = "127.0.0.1:9092";
/**
* The name of the topic that receives the data
*/
private String topic;
/**
* Consumer Group ID
*/
private String groupId;
}
}
}
@@ -1,70 +0,0 @@
/*
* 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.dromara.hertzbeat.alert;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* alarm module thread pool
*
*/
@Component
@Slf4j
public class AlerterWorkerPool {
private ThreadPoolExecutor workerExecutor;
public AlerterWorkerPool() {
initWorkExecutor();
}
private void initWorkExecutor() {
ThreadFactory threadFactory = new ThreadFactoryBuilder()
.setUncaughtExceptionHandler((thread, throwable) -> {
log.error("workerExecutor has uncaughtException.");
log.error(throwable.getMessage(), throwable);
})
.setDaemon(true)
.setNameFormat("alerter-worker-%d")
.build();
workerExecutor = new ThreadPoolExecutor(6,
10,
10,
TimeUnit.SECONDS,
new SynchronousQueue<>(),
threadFactory,
new ThreadPoolExecutor.AbortPolicy());
}
/**
* Run the alerter task
* @param runnable task
* @throws RejectedExecutionException when The thread pool is full of
*/
public void executeJob(Runnable runnable) throws RejectedExecutionException {
workerExecutor.execute(runnable);
}
}
@@ -1,479 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.calculate;
import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.Expression;
import com.googlecode.aviator.exception.CompileExpressionErrorException;
import com.googlecode.aviator.exception.ExpressionRuntimeException;
import com.googlecode.aviator.exception.ExpressionSyntaxErrorException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.dromara.hertzbeat.alert.AlerterWorkerPool;
import org.dromara.hertzbeat.alert.dao.AlertMonitorDao;
import org.dromara.hertzbeat.alert.reduce.AlarmCommonReduce;
import org.dromara.hertzbeat.alert.service.AlertDefineService;
import org.dromara.hertzbeat.alert.service.AlertService;
import org.dromara.hertzbeat.alert.util.AlertTemplateUtil;
import org.dromara.hertzbeat.common.constants.CommonConstants;
import org.dromara.hertzbeat.common.entity.alerter.Alert;
import org.dromara.hertzbeat.common.entity.alerter.AlertDefine;
import org.dromara.hertzbeat.common.entity.manager.Monitor;
import org.dromara.hertzbeat.common.entity.manager.TagItem;
import org.dromara.hertzbeat.common.entity.message.CollectRep;
import org.dromara.hertzbeat.common.queue.CommonDataQueue;
import org.dromara.hertzbeat.common.support.event.MonitorDeletedEvent;
import org.dromara.hertzbeat.common.support.event.SystemConfigChangeEvent;
import org.dromara.hertzbeat.common.util.CommonUtil;
import org.dromara.hertzbeat.common.util.ResourceBundleUtil;
import org.springframework.context.event.EventListener;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import jakarta.persistence.criteria.Predicate;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import static org.dromara.hertzbeat.common.constants.CommonConstants.*;
/**
* Calculate alarms based on the alarm definition rules and collected data
*
*/
@Component
@Slf4j
public class CalculateAlarm {
private static final String SYSTEM_VALUE_ROW_COUNT = "system_value_row_count";
/**
* The alarm in the process is triggered
* 触发中告警信息
* key - monitorId+alertDefineId+tags 为普通阈值告警 The alarm is a common threshold alarm
* key - monitorId 为任务状态可用性可达性告警 Indicates the monitoring status availability reachability alarm
*/
private final Map<String, Alert> triggeredAlertMap;
/**
* The not recover alert
* key - monitorId + alertDefineId + tags
*/
private final Map<String, Alert> notRecoveredAlertMap;
private final AlerterWorkerPool workerPool;
private final CommonDataQueue dataQueue;
private final AlertDefineService alertDefineService;
private final AlarmCommonReduce alarmCommonReduce;
private ResourceBundle bundle;
private final AlertService alertService;
public CalculateAlarm(AlerterWorkerPool workerPool, CommonDataQueue dataQueue,
AlertDefineService alertDefineService, AlertMonitorDao monitorDao,
AlarmCommonReduce alarmCommonReduce, AlertService alertService) {
this.workerPool = workerPool;
this.dataQueue = dataQueue;
this.alarmCommonReduce = alarmCommonReduce;
this.alertDefineService = alertDefineService;
this.alertService = alertService;
this.bundle = ResourceBundleUtil.getBundle("alerter");
this.triggeredAlertMap = new ConcurrentHashMap<>(16);
this.notRecoveredAlertMap = new ConcurrentHashMap<>(16);
// Initialize stateAlertMap
List<Monitor> monitors = monitorDao.findMonitorsByStatus(CommonConstants.UN_AVAILABLE_CODE);
if (monitors != null) {
for (Monitor monitor : monitors) {
HashMap<String, String> tags = new HashMap<>(8);
tags.put(TAG_MONITOR_ID, String.valueOf(monitor.getId()));
tags.put(TAG_MONITOR_NAME, monitor.getName());
tags.put(TAG_MONITOR_APP, monitor.getApp());
this.notRecoveredAlertMap.put(monitor.getId() + CommonConstants.AVAILABILITY,
Alert.builder().tags(tags).target(AVAILABILITY).status(ALERT_STATUS_CODE_PENDING).build());
}
}
startCalculate();
}
private void startCalculate() {
Runnable runnable = () -> {
while (!Thread.currentThread().isInterrupted()) {
try {
CollectRep.MetricsData metricsData = dataQueue.pollMetricsDataToAlerter();
if (metricsData != null) {
calculate(metricsData);
}
} catch (InterruptedException ignored) {
} catch (Exception e) {
log.error("calculate alarm error: {}.", e.getMessage(), e);
}
}
};
workerPool.executeJob(runnable);
workerPool.executeJob(runnable);
workerPool.executeJob(runnable);
}
private void calculate(CollectRep.MetricsData metricsData) {
long currentTimeMilli = System.currentTimeMillis();
long monitorId = metricsData.getId();
String app = metricsData.getApp();
if (app.startsWith(CommonConstants.PROMETHEUS_APP_PREFIX)) {
app = CommonConstants.PROMETHEUS;
}
String metrics = metricsData.getMetrics();
// If the metrics whose scheduling priority is 0 has the status of collecting response data UN_REACHABLE/UN_CONNECTABLE,
// the highest severity alarm is generated to monitor the status change
if (metricsData.getPriority() == 0) {
handlerAvailableMetrics(monitorId, app, metricsData);
}
// Query the alarm definitions associated with the metrics of the monitoring type
// field - define[]
Map<String, List<AlertDefine>> defineMap = alertDefineService.getMonitorBindAlertDefines(monitorId, app, metrics);
if (defineMap.isEmpty()) {
return;
}
List<CollectRep.Field> fields = metricsData.getFieldsList();
Map<String, Object> fieldValueMap = new HashMap<>(8);
int valueRowCount = metricsData.getValuesCount();
for (Map.Entry<String, List<AlertDefine>> entry : defineMap.entrySet()) {
List<AlertDefine> defines = entry.getValue();
for (AlertDefine define : defines) {
final String expr = define.getExpr();
if (StringUtils.isBlank(expr)) {
continue;
}
if (expr.contains(SYSTEM_VALUE_ROW_COUNT) && metricsData.getValuesCount() == 0) {
fieldValueMap.put(SYSTEM_VALUE_ROW_COUNT, valueRowCount);
try {
boolean match = execAlertExpression(fieldValueMap, expr);
try {
if (match) {
// If the threshold rule matches, the number of times the threshold has been triggered is determined and an alarm is triggered
// 阈值规则匹配,判断已触发阈值次数,触发告警
afterThresholdRuleMatch(currentTimeMilli, monitorId, app, metrics, "", fieldValueMap, define);
// 若此阈值已被触发,则其它数据行的触发忽略
continue;
} else {
String alarmKey = String.valueOf(monitorId) + define.getId();
triggeredAlertMap.remove(alarmKey);
if (define.isRecoverNotice()) {
handleRecoveredAlert(currentTimeMilli, define, expr, alarmKey);
}
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
} catch (Exception ignored) {}
}
for (CollectRep.ValueRow valueRow : metricsData.getValuesList()) {
if (CollectionUtils.isEmpty(valueRow.getColumnsList())) {
continue;
}
fieldValueMap.clear();
fieldValueMap.put(SYSTEM_VALUE_ROW_COUNT, valueRowCount);
StringBuilder tagBuilder = new StringBuilder();
for (int index = 0; index < valueRow.getColumnsList().size(); index++) {
String valueStr = valueRow.getColumns(index);
if (CommonConstants.NULL_VALUE.equals(valueStr)) {
continue;
}
final CollectRep.Field field = fields.get(index);
final int fieldType = field.getType();
if (fieldType == CommonConstants.TYPE_NUMBER) {
final Double doubleValue;
if ((doubleValue = CommonUtil.parseStrDouble(valueStr)) != null) {
fieldValueMap.put(field.getName(), doubleValue);
}
} else if (fieldType == CommonConstants.TYPE_TIME) {
final Integer integerValue;
if ((integerValue = CommonUtil.parseStrInteger(valueStr)) != null) {
fieldValueMap.put(field.getName(), integerValue);
}
} else {
if (StringUtils.isNotEmpty(valueStr)) {
fieldValueMap.put(field.getName(), valueStr);
}
}
if (field.getLabel()) {
tagBuilder.append("-").append(valueStr);
}
}
try {
boolean match = execAlertExpression(fieldValueMap, expr);
try {
if (match) {
// If the threshold rule matches, the number of times the threshold has been triggered is determined and an alarm is triggered
// 阈值规则匹配,判断已触发阈值次数,触发告警
afterThresholdRuleMatch(currentTimeMilli, monitorId, app, metrics, tagBuilder.toString(), fieldValueMap, define);
// 若此阈值已被触发,则其它数据行的触发忽略
break;
} else {
String alarmKey = String.valueOf(monitorId) + define.getId() + tagBuilder;
triggeredAlertMap.remove(alarmKey);
if (define.isRecoverNotice()) {
handleRecoveredAlert(currentTimeMilli, define, expr, alarmKey);
}
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
} catch (Exception ignored) {}
}
}
}
}
private void handleRecoveredAlert(long currentTimeMilli, AlertDefine define, String expr, String alarmKey) {
Alert notResolvedAlert = notRecoveredAlertMap.remove(alarmKey);
if (notResolvedAlert != null) {
// Sending an alarm Restore
Map<String, String> tags = notResolvedAlert.getTags();
String content = this.bundle.getString("alerter.alarm.recover") + " : " + expr;
Alert resumeAlert = Alert.builder()
.tags(tags)
.target(define.getApp() + "." + define.getMetric() + "." + define.getField())
.content(content)
.priority(CommonConstants.ALERT_PRIORITY_CODE_WARNING)
.status(CommonConstants.ALERT_STATUS_CODE_RESTORED)
.firstAlarmTime(currentTimeMilli)
.lastAlarmTime(notResolvedAlert.getLastAlarmTime())
.triggerTimes(1)
.build();
alarmCommonReduce.reduceAndSendAlarm(resumeAlert);
}
}
private void afterThresholdRuleMatch(long currentTimeMilli, long monitorId, String app, String metrics, String tagStr,
Map<String, Object> fieldValueMap, AlertDefine define) {
String alarmKey = String.valueOf(monitorId) + define.getId() + tagStr;
Alert triggeredAlert = triggeredAlertMap.get(alarmKey);
if (triggeredAlert != null) {
int times = triggeredAlert.getTriggerTimes() + 1;
triggeredAlert.setTriggerTimes(times);
triggeredAlert.setFirstAlarmTime(currentTimeMilli);
triggeredAlert.setLastAlarmTime(currentTimeMilli);
int defineTimes = define.getTimes() == null ? 1 : define.getTimes();
if (times >= defineTimes) {
triggeredAlert.setStatus(ALERT_STATUS_CODE_PENDING);
triggeredAlertMap.remove(alarmKey);
notRecoveredAlertMap.put(alarmKey, triggeredAlert);
alarmCommonReduce.reduceAndSendAlarm(triggeredAlert.clone());
}
} else {
fieldValueMap.put(TAG_MONITOR_APP, app);
fieldValueMap.put(TAG_METRICS, metrics);
fieldValueMap.put(TAG_METRIC, define.getField());
Map<String, String> tags = new HashMap<>(8);
tags.put(CommonConstants.TAG_MONITOR_ID, String.valueOf(monitorId));
tags.put(CommonConstants.TAG_MONITOR_APP, app);
tags.put(CommonConstants.TAG_THRESHOLD_ID, String.valueOf(define.getId()));
if (!CollectionUtils.isEmpty(define.getTags())) {
for (TagItem tagItem : define.getTags()) {
fieldValueMap.put(tagItem.getName(), tagItem.getValue());
tags.put(tagItem.getName(), tagItem.getValue());
}
}
Alert alert = Alert.builder()
.tags(tags)
.priority(define.getPriority())
.status(ALERT_STATUS_CODE_NOT_REACH)
.target(app + "." + metrics + "." + define.getField())
.triggerTimes(1)
.firstAlarmTime(currentTimeMilli)
.lastAlarmTime(currentTimeMilli)
// Keyword matching and substitution in the template
.content(AlertTemplateUtil.render(define.getTemplate(), fieldValueMap))
.build();
int defineTimes = define.getTimes() == null ? 1 : define.getTimes();
if (1 >= defineTimes) {
alert.setStatus(ALERT_STATUS_CODE_PENDING);
notRecoveredAlertMap.put(alarmKey, alert);
alarmCommonReduce.reduceAndSendAlarm(alert.clone());
} else {
triggeredAlertMap.put(alarmKey, alert);
}
}
}
private boolean execAlertExpression(Map<String, Object> fieldValueMap, String expr) {
Boolean match;
try {
Expression expression = AviatorEvaluator.compile(expr, true);
expression.getVariableNames().forEach(variable -> {
if (!fieldValueMap.containsKey(variable)) {
throw new ExpressionRuntimeException("metrics value not contains expr field: " + variable);
}
});
match = (Boolean) expression.execute(fieldValueMap);
} catch (CompileExpressionErrorException |
ExpressionSyntaxErrorException compileException) {
log.error("Alert Define Rule: {} Compile Error: {}.", expr, compileException.getMessage());
throw compileException;
} catch (ExpressionRuntimeException expressionRuntimeException) {
log.error("Alert Define Rule: {} Run Error: {}.", expr, expressionRuntimeException.getMessage());
throw expressionRuntimeException;
} catch (Exception e) {
log.error("Alert Define Rule: {} Unknown Error: {}.", expr, e.getMessage());
throw e;
}
return match != null && match;
}
private void handlerAvailableMetrics(long monitorId, String app, CollectRep.MetricsData metricsData) {
if (metricsData.getCode() == CollectRep.Code.TIMEOUT) {
return;
}
// TODO CACHE getMonitorBindAlertAvaDefine
AlertDefine avaAlertDefine = alertDefineService.getMonitorBindAlertAvaDefine(monitorId, app, CommonConstants.AVAILABILITY);
if (avaAlertDefine == null) {
return;
}
long currentTimeMill = System.currentTimeMillis();
if (metricsData.getCode() != CollectRep.Code.SUCCESS) {
Alert preAlert = triggeredAlertMap.get(String.valueOf(monitorId));
Map<String, String> tags = new HashMap<>(6);
tags.put(CommonConstants.TAG_MONITOR_ID, String.valueOf(monitorId));
tags.put(CommonConstants.TAG_MONITOR_APP, app);
tags.put(CommonConstants.TAG_THRESHOLD_ID, String.valueOf(avaAlertDefine.getId()));
tags.put(TAG_METRICS, CommonConstants.AVAILABILITY);
tags.put(TAG_CODE, metricsData.getCode().name());
Map<String, Object> valueMap = tags.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
if (!CollectionUtils.isEmpty(avaAlertDefine.getTags())) {
for (TagItem tagItem : avaAlertDefine.getTags()) {
valueMap.put(tagItem.getName(), tagItem.getValue());
tags.put(tagItem.getName(), tagItem.getValue());
}
}
if (preAlert == null) {
Alert.AlertBuilder alertBuilder = Alert.builder()
.tags(tags)
.priority(avaAlertDefine.getPriority())
.status(ALERT_STATUS_CODE_NOT_REACH)
.target(CommonConstants.AVAILABILITY)
.content(AlertTemplateUtil.render(avaAlertDefine.getTemplate(), valueMap))
.firstAlarmTime(currentTimeMill)
.lastAlarmTime(currentTimeMill)
.triggerTimes(1);
if (avaAlertDefine.getTimes() == null || avaAlertDefine.getTimes() <= 1) {
String notResolvedAlertKey = monitorId + CommonConstants.AVAILABILITY;
alertBuilder.status(ALERT_STATUS_CODE_PENDING);
notRecoveredAlertMap.put(notResolvedAlertKey, alertBuilder.build());
alarmCommonReduce.reduceAndSendAlarm(alertBuilder.build());
} else {
triggeredAlertMap.put(String.valueOf(monitorId), alertBuilder.build());
}
} else {
int times = preAlert.getTriggerTimes() + 1;
preAlert.setTriggerTimes(times);
preAlert.setFirstAlarmTime(currentTimeMill);
preAlert.setLastAlarmTime(currentTimeMill);
int defineTimes = avaAlertDefine.getTimes() == null ? 1 : avaAlertDefine.getTimes();
if (times >= defineTimes) {
preAlert.setStatus(ALERT_STATUS_CODE_PENDING);
String notResolvedAlertKey = monitorId + CommonConstants.AVAILABILITY;
notRecoveredAlertMap.put(notResolvedAlertKey, preAlert.clone());
alarmCommonReduce.reduceAndSendAlarm(preAlert.clone());
triggeredAlertMap.remove(String.valueOf(monitorId));
}
}
} else {
// Check whether an availability or unreachable alarm is generated before the association monitoring
// and send a clear alarm to clear the monitoring status
// 判断关联监控之前是否有可用性或者不可达告警,发送恢复告警进行任务状态恢复
triggeredAlertMap.remove(String.valueOf(monitorId));
String notResolvedAlertKey = monitorId + CommonConstants.AVAILABILITY;
Alert notResolvedAlert = notRecoveredAlertMap.remove(notResolvedAlertKey);
if (notResolvedAlert != null) {
// Sending an alarm Restore
Map<String, String> tags = notResolvedAlert.getTags();
if (!avaAlertDefine.isRecoverNotice()) {
tags.put(CommonConstants.IGNORE, CommonConstants.IGNORE);
}
String content = this.bundle.getString("alerter.availability.recover");
Alert resumeAlert = Alert.builder()
.tags(tags)
.target(CommonConstants.AVAILABILITY)
.content(content)
.priority(CommonConstants.ALERT_PRIORITY_CODE_WARNING)
.status(CommonConstants.ALERT_STATUS_CODE_RESTORED)
.firstAlarmTime(currentTimeMill)
.lastAlarmTime(notResolvedAlert.getLastAlarmTime())
.triggerTimes(1)
.build();
alarmCommonReduce.reduceAndSendAlarm(resumeAlert);
Runnable updateStatusJob = () -> {
// todo update pre all type alarm status
updateAvailabilityAlertStatus(monitorId, resumeAlert);
};
workerPool.executeJob(updateStatusJob);
}
}
}
private void updateAvailabilityAlertStatus(long monitorId, Alert restoreAlert) {
List<Alert> availabilityAlerts = queryAvailabilityAlerts(monitorId, restoreAlert);
availabilityAlerts.stream().parallel().forEach(alert -> {
log.info("updating alert status solved id: {}", alert.getId());
alertService.editAlertStatus(ALERT_STATUS_CODE_SOLVED, List.of(alert.getId()));
});
}
private List<Alert> queryAvailabilityAlerts(long monitorId, Alert restoreAlert) {
//create query condition
Specification<Alert> specification = (root, query, criteriaBuilder) -> {
List<Predicate> andList = new ArrayList<>();
Predicate predicateTags = criteriaBuilder.like(root.get("tags").as(String.class), "%" + monitorId + "%");
andList.add(predicateTags);
Predicate predicatePriority = criteriaBuilder.equal(root.get("priority"), CommonConstants.ALERT_PRIORITY_CODE_EMERGENCY);
andList.add(predicatePriority);
Predicate predicateStatus = criteriaBuilder.equal(root.get("status"), ALERT_STATUS_CODE_PENDING);
andList.add(predicateStatus);
Predicate predicateAlertTime = criteriaBuilder.lessThanOrEqualTo(root.get("lastAlarmTime"), restoreAlert.getLastAlarmTime());
andList.add(predicateAlertTime);
Predicate[] predicates = new Predicate[andList.size()];
return criteriaBuilder.and(andList.toArray(predicates));
};
//query results
return alertService.getAlerts(specification);
}
@EventListener(SystemConfigChangeEvent.class)
public void onSystemConfigChangeEvent(SystemConfigChangeEvent event) {
log.info("calculate alarm receive system config change event: {}.", event.getSource());
this.bundle = ResourceBundleUtil.getBundle("alerter");
}
@EventListener(MonitorDeletedEvent.class)
public void onMonitorDeletedEvent(MonitorDeletedEvent event) {
log.info("calculate alarm receive monitor {} has been deleted.", event.getMonitorId());
this.triggeredAlertMap.remove(String.valueOf(event.getMonitorId()));
}
}
@@ -1,28 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.config;
import org.springframework.context.annotation.ComponentScan;
/**
* Alert auto configuration.
* @version 2.1
*/
@ComponentScan(basePackages = "org.dromara.hertzbeat.alert")
public class AlerterAutoConfiguration {
}
@@ -1,76 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.dromara.hertzbeat.alert.service.AlertConvergeService;
import org.dromara.hertzbeat.common.entity.alerter.AlertConverge;
import org.dromara.hertzbeat.common.entity.dto.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid;
import static org.dromara.hertzbeat.common.constants.CommonConstants.MONITOR_NOT_EXIST_CODE;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
/**
* Alarm Converge management API
*
*/
@Tag(name = "Alert Converge API | 告警收敛管理API")
@RestController
@RequestMapping(path = "/api/alert/converge", produces = {APPLICATION_JSON_VALUE})
public class AlertConvergeController {
@Autowired
private AlertConvergeService alertConvergeService;
@PostMapping
@Operation(summary = "New Alarm Converge | 新增告警收敛", description = "Added an alarm Converge | 新增一个告警收敛")
public ResponseEntity<Message<Void>> addNewAlertConverge(@Valid @RequestBody AlertConverge alertConverge) {
alertConvergeService.validate(alertConverge, false);
alertConvergeService.addAlertConverge(alertConverge);
return ResponseEntity.ok(Message.success("Add success"));
}
@PutMapping
@Operation(summary = "Modifying an Alarm Converge | 修改告警收敛", description = "Modify an existing alarm Converge | 修改一个已存在告警收敛")
public ResponseEntity<Message<Void>> modifyAlertConverge(@Valid @RequestBody AlertConverge alertConverge) {
alertConvergeService.validate(alertConverge, true);
alertConvergeService.modifyAlertConverge(alertConverge);
return ResponseEntity.ok(Message.success("Modify success"));
}
@GetMapping(path = "/{id}")
@Operation(summary = "Querying Alarm Converge | 查询告警收敛",
description = "You can obtain alarm Converge information based on the alarm Converge ID | 根据告警收敛ID获取告警收敛信息")
public ResponseEntity<Message<AlertConverge>> getAlertConverge(
@Parameter(description = "Alarm Converge ID 告警收敛ID", example = "6565463543") @PathVariable("id") long id) {
AlertConverge alertConverge = alertConvergeService.getAlertConverge(id);
if (alertConverge == null) {
return ResponseEntity.ok(Message.fail(MONITOR_NOT_EXIST_CODE, "AlertConverge not exist."));
} else {
return ResponseEntity.ok(Message.success(alertConverge));
}
}
}
@@ -1,105 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.dromara.hertzbeat.alert.service.AlertConvergeService;
import org.dromara.hertzbeat.common.entity.alerter.AlertConverge;
import org.dromara.hertzbeat.common.entity.dto.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
/**
* Converge the batch API for alarms
*
*/
@Tag(name = "Alert Converge Batch API | 告警收敛管理API")
@RestController
@RequestMapping(path = "/api/alert/converges", produces = {APPLICATION_JSON_VALUE})
public class AlertConvergesController {
@Autowired
private AlertConvergeService alertConvergeService;
@GetMapping
@Operation(summary = "Query the alarm converge list 查询告警收敛列表",
description = "You can obtain the list of alarm converge by querying filter items | 根据查询过滤项获取告警收敛信息列表")
public ResponseEntity<Message<Page<AlertConverge>>> getAlertConverges(
@Parameter(description = "Alarm Converge ID 告警收敛ID", example = "6565463543") @RequestParam(required = false) List<Long> ids,
@Parameter(description = "Search Name 模糊查询-名称", example = "x") @RequestParam(required = false) String search,
@Parameter(description = "Sort field, default id 排序字段,默认id", example = "id") @RequestParam(defaultValue = "id") String sort,
@Parameter(description = "Sort mode: asc: ascending, desc: descending 排序方式,asc:升序,desc:降序", example = "desc") @RequestParam(defaultValue = "desc") String order,
@Parameter(description = "List current page 列表当前分页", example = "0") @RequestParam(defaultValue = "0") int pageIndex,
@Parameter(description = "Number of list pages 列表分页数量", example = "8") @RequestParam(defaultValue = "8") int pageSize) {
Specification<AlertConverge> specification = (root, query, criteriaBuilder) -> {
List<Predicate> andList = new ArrayList<>();
if (ids != null && !ids.isEmpty()) {
CriteriaBuilder.In<Long> inPredicate = criteriaBuilder.in(root.get("id"));
for (long id : ids) {
inPredicate.value(id);
}
andList.add(inPredicate);
}
if (StringUtils.hasText(search)) {
Predicate predicate = criteriaBuilder.or(
criteriaBuilder.like(
criteriaBuilder.lower(root.get("name")),
"%" + search.toLowerCase() + "%"
)
);
andList.add(predicate);
}
Predicate[] predicates = new Predicate[andList.size()];
return criteriaBuilder.and(andList.toArray(predicates));
};
Sort sortExp = Sort.by(new Sort.Order(Sort.Direction.fromString(order), sort));
PageRequest pageRequest = PageRequest.of(pageIndex, pageSize, sortExp);
Page<AlertConverge> alertConvergePage = alertConvergeService.getAlertConverges(specification, pageRequest);
return ResponseEntity.ok(Message.success(alertConvergePage));
}
@DeleteMapping
@Operation(summary = "Delete alarm converge in batches 批量删除告警收敛",
description = "Delete alarm converge in batches based on the alarm converge ID list 根据告警收敛ID列表批量删除告警收敛")
public ResponseEntity<Message<Void>> deleteAlertDefines(
@Parameter(description = "Alarm Converge IDs 告警收敛IDs", example = "6565463543") @RequestParam(required = false) List<Long> ids
) {
if (ids != null && !ids.isEmpty()) {
alertConvergeService.deleteAlertConverges(new HashSet<>(ids));
}
return ResponseEntity.ok(Message.success());
}
}
@@ -1,120 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.controller;
import org.dromara.hertzbeat.common.entity.alerter.AlertDefine;
import org.dromara.hertzbeat.common.entity.alerter.AlertDefineMonitorBind;
import org.dromara.hertzbeat.alert.service.AlertDefineService;
import org.dromara.hertzbeat.common.entity.dto.Message;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import jakarta.validation.Valid;
import java.util.List;
import java.util.stream.Collectors;
import static org.dromara.hertzbeat.common.constants.CommonConstants.MONITOR_NOT_EXIST_CODE;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
/**
* Alarm definition management API
*
*/
@Tag(name = "Alert Define API | 告警定义管理API")
@RestController
@RequestMapping(path = "/api/alert/define", produces = {APPLICATION_JSON_VALUE})
public class AlertDefineController {
@Autowired
private AlertDefineService alertDefineService;
@PostMapping
@Operation(summary = "New Alarm Definition | 新增告警定义", description = "Added an alarm definition | 新增一个告警定义")
public ResponseEntity<Message<Void>> addNewAlertDefine(@Valid @RequestBody AlertDefine alertDefine) {
// Verify request data
alertDefineService.validate(alertDefine, false);
alertDefineService.addAlertDefine(alertDefine);
return ResponseEntity.ok(Message.success("Add success"));
}
@PutMapping
@Operation(summary = "Modifying an Alarm Definition | 修改告警定义", description = "Modify an existing alarm definition | 修改一个已存在告警定义")
public ResponseEntity<Message<Void>> modifyAlertDefine(@Valid @RequestBody AlertDefine alertDefine) {
// Verify request data
alertDefineService.validate(alertDefine, true);
alertDefineService.modifyAlertDefine(alertDefine);
return ResponseEntity.ok(Message.success("Modify success"));
}
@GetMapping(path = "/{id}")
@Operation(summary = "Querying Alarm Definitions | 查询告警定义",
description = "You can obtain alarm definition information based on the alarm definition ID | 根据告警定义ID获取告警定义信息")
public ResponseEntity<Message<AlertDefine>> getAlertDefine(
@Parameter(description = "Alarm Definition ID 告警定义ID", example = "6565463543") @PathVariable("id") long id) {
// Obtaining Monitoring Information
AlertDefine alertDefine = alertDefineService.getAlertDefine(id);
if (alertDefine == null) {
return ResponseEntity.ok(Message.fail(MONITOR_NOT_EXIST_CODE, "AlertDefine not exist."));
} else {
return ResponseEntity.ok(Message.success(alertDefine));
}
}
@DeleteMapping(path = "/{id}")
@Operation(summary = "Deleting an Alarm Definition 删除告警定义",
description = "If the alarm definition does not exist, the alarm is deleted successfully 根据告警定义ID删除告警定义,告警定义不存在也是删除成功")
public ResponseEntity<Message<Void>> deleteAlertDefine(
@Parameter(description = "Alarm Definition ID 告警定义ID", example = "6565463543") @PathVariable("id") long id) {
// If the alarm definition does not exist or is deleted successfully, the deletion succeeds
alertDefineService.deleteAlertDefine(id);
return ResponseEntity.ok(Message.success("Delete success"));
}
@PostMapping(path = "/{alertDefineId}/monitors")
@Operation(summary = "Application alarm definition is associated with monitoring 应用告警定义与监控关联",
description = "Applies the association between specified alarm definitions and monitoring 应用指定告警定义与监控关联关系")
public ResponseEntity<Message<Void>> applyAlertDefineMonitorsBind(
@Parameter(description = "Alarm Definition ID 告警定义ID", example = "6565463543") @PathVariable("alertDefineId") long alertDefineId,
@RequestBody List<AlertDefineMonitorBind> alertDefineMonitorBinds) {
alertDefineService.applyBindAlertDefineMonitors(alertDefineId, alertDefineMonitorBinds);
return ResponseEntity.ok(Message.success("Apply success"));
}
@GetMapping(path = "/{alertDefineId}/monitors")
@Operation(summary = "Application alarm definition is associated with monitoring 应用告警定义与监控关联",
description = "Applies the association between specified alarm definitions and monitoring 应用指定告警定义与监控关联关系")
public ResponseEntity<Message<List<AlertDefineMonitorBind>>> getAlertDefineMonitorsBind(
@Parameter(description = "Alarm Definition ID 告警定义ID", example = "6565463543") @PathVariable("alertDefineId") long alertDefineId) {
List<AlertDefineMonitorBind> defineBinds = alertDefineService.getBindAlertDefineMonitors(alertDefineId);
defineBinds = defineBinds.stream().filter(item -> item.getMonitor() != null).collect(Collectors.toList());
return ResponseEntity.ok(Message.success(defineBinds));
}
}
@@ -1,143 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.controller;
import org.dromara.hertzbeat.common.entity.alerter.AlertDefine;
import org.dromara.hertzbeat.alert.service.AlertDefineService;
import org.dromara.hertzbeat.common.entity.dto.Message;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.Predicate;
import jakarta.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
/**
* Define the batch API for alarms
*
*/
@Tag(name = "Alert Define Batch API | 告警定义管理API")
@RestController
@RequestMapping(path = "/api/alert/defines", produces = {APPLICATION_JSON_VALUE})
public class AlertDefinesController {
@Autowired
private AlertDefineService alertDefineService;
@GetMapping
@Operation(summary = "Example Query the alarm definition list 查询告警定义列表",
description = "You can obtain the list of alarm definitions by querying filter items | 根据查询过滤项获取告警定义信息列表")
public ResponseEntity<Message<Page<AlertDefine>>> getAlertDefines(
@Parameter(description = "Alarm Definition ID 告警定义ID", example = "6565463543") @RequestParam(required = false) List<Long> ids,
@Parameter(description = "Search-Target Expr Template 模糊查询-指标对象 表达式 通知模版", example = "x") @RequestParam(required = false) String search,
@Parameter(description = "Alarm Definition Severity 告警定义级别", example = "6565463543") @RequestParam(required = false) Byte priority,
@Parameter(description = "Sort field, default id 排序字段,默认id", example = "id") @RequestParam(defaultValue = "id") String sort,
@Parameter(description = "Sort mode: asc: ascending, desc: descending 排序方式,asc:升序,desc:降序", example = "desc") @RequestParam(defaultValue = "desc") String order,
@Parameter(description = "List current page 列表当前分页", example = "0") @RequestParam(defaultValue = "0") int pageIndex,
@Parameter(description = "Number of list pages 列表分页数量", example = "8") @RequestParam(defaultValue = "8") int pageSize) {
Specification<AlertDefine> specification = (root, query, criteriaBuilder) -> {
List<Predicate> andList = new ArrayList<>();
if (ids != null && !ids.isEmpty()) {
CriteriaBuilder.In<Long> inPredicate = criteriaBuilder.in(root.get("id"));
for (long id : ids) {
inPredicate.value(id);
}
andList.add(inPredicate);
}
if (StringUtils.hasText(search)) {
Predicate predicate = criteriaBuilder.or(
criteriaBuilder.like(
criteriaBuilder.lower(root.get("app")),
"%" + search.toLowerCase() + "%"
),
criteriaBuilder.like(
criteriaBuilder.lower(root.get("metric")),
"%" + search.toLowerCase() + "%"
),
criteriaBuilder.like(
criteriaBuilder.lower(root.get("field")),
"%" + search.toLowerCase() + "%"
),
criteriaBuilder.like(
criteriaBuilder.lower(root.get("expr")),
"%" + search.toLowerCase() + "%"
),
criteriaBuilder.like(
criteriaBuilder.lower(root.get("template")),
"%" + search.toLowerCase() + "%"
)
);
andList.add(predicate);
}
if (priority != null) {
Predicate predicate = criteriaBuilder.equal(root.get("priority"), priority);
andList.add(predicate);
}
Predicate[] predicates = new Predicate[andList.size()];
return criteriaBuilder.and(andList.toArray(predicates));
};
Sort sortExp = Sort.by(new Sort.Order(Sort.Direction.fromString(order), sort));
PageRequest pageRequest = PageRequest.of(pageIndex, pageSize, sortExp);
Page<AlertDefine> alertDefinePage = alertDefineService.getAlertDefines(specification, pageRequest);
return ResponseEntity.ok(Message.success(alertDefinePage));
}
@DeleteMapping
@Operation(summary = "Delete alarm definitions in batches 批量删除告警定义",
description = "Delete alarm definitions in batches based on the alarm definition ID list 根据告警定义ID列表批量删除告警定义")
public ResponseEntity<Message<Void>> deleteAlertDefines(
@Parameter(description = "Alarm Definition IDs 告警定义IDs", example = "6565463543") @RequestParam(required = false) List<Long> ids
) {
if (ids != null && !ids.isEmpty()) {
alertDefineService.deleteAlertDefines(new HashSet<>(ids));
}
return ResponseEntity.ok(Message.success());
}
@GetMapping("/export")
@Operation(summary = "export alertDefine config", description = "导出告警阀值配置")
public void export(
@Parameter(description = "AlertDefine ID List | 告警阀值ID列表", example = "656937901") @RequestParam List<Long> ids,
@Parameter(description = "Export Type:JSON,EXCEL,YAML") @RequestParam(defaultValue = "JSON") String type,
HttpServletResponse res) throws Exception {
alertDefineService.export(ids, type, res);
}
@PostMapping("/import")
@Operation(summary = "import alertDefine config", description = "导入告警阀值配置")
public ResponseEntity<Message<Void>> importDefines(MultipartFile file) throws Exception {
alertDefineService.importConfig(file);
return ResponseEntity.ok(Message.success("Import success"));
}
}
@@ -1,113 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hertzbeat.alert.dto.CloudAlertReportAbstract;
import org.dromara.hertzbeat.alert.dto.GeneralCloudAlertReport;
import org.dromara.hertzbeat.alert.enums.CloudServiceAlarmInformationEnum;
import org.dromara.hertzbeat.alert.service.AlertService;
import org.dromara.hertzbeat.common.entity.dto.AlertReport;
import org.dromara.hertzbeat.common.entity.dto.Message;
import org.dromara.hertzbeat.common.util.JsonUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.Optional;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
/**
* Extern Alarm Manage API
*
*/
@Tag(name = "Extern Alarm Manage API | 第三方告警管理API")
@RestController
@RequestMapping(path = "/api/alerts/report", produces = {APPLICATION_JSON_VALUE})
@Slf4j
public class AlertReportController {
@Autowired
private AlertService alertService;
@PostMapping("/{cloud}")
@Operation(summary = "Interface for reporting external alarm information of cloud service 对外上报告警信息接口")
public ResponseEntity<Message<Void>> addNewAlertReportFromCloud(@PathVariable("cloud") String cloudServiceName,
@RequestBody String alertReport) {
// 根据枚举获取到对应的枚举对象
CloudServiceAlarmInformationEnum cloudService = CloudServiceAlarmInformationEnum
.getEnumFromCloudServiceName(cloudServiceName);
AlertReport alert = null;
// 校验是否存在对应的对象
if (cloudService != null) {
try {
// 实例化对应的Class
CloudAlertReportAbstract cloudAlertReport = JsonUtil
.fromJson(alertReport, cloudService.getCloudServiceAlarmInformationEntity());
// 模板填充
assert cloudAlertReport != null;
alert = AlertReport.builder()
.content(cloudAlertReport.getContent())
.alertName(cloudAlertReport.getAlertName())
.alertTime(cloudAlertReport.getAlertTime())
.alertDuration(cloudAlertReport.getAlertDuration())
.priority(cloudAlertReport.getPriority())
.reportType(cloudAlertReport.getReportType())
.labels(cloudAlertReport.getLabels())
.annotations(cloudAlertReport.getAnnotations())
.build();
} catch (Exception e) {
log.error("[AlertReportController]:解析云服务告警内容失败!云服务商:" +
cloudService.name() + ";传入JSON字符串:" + alertReport);
}
} else {
// 用户异常使用第三方接入API告警
alert = AlertReport.builder()
.content("第三方告警API接入异常:不存在该API,详情请看文档")
.alertName("/api/alerts/report/" + cloudServiceName)
.alertTime(new Date().getTime())
.priority(1)
.reportType(1)
.build();
}
// 异常判断是否为空
Optional.ofNullable(alert).ifPresent(alertReportPresent ->
alertService.addNewAlertReport(alertReportPresent));
return ResponseEntity.ok(Message.success("Add report success"));
}
@PostMapping
@Operation(summary = "Interface for reporting external and general alarm information 对外上报告警信息 接口",
description = "对外 新增一个云服务通用告警")
public ResponseEntity<Message<Void>> addNewAlertReport(@RequestBody GeneralCloudAlertReport alertReport) {
try {
alertReport.refreshAlertTime();
} catch (Exception e) {
log.error("[AlertReportController]" + e.getMessage() +
",请求实体:" + JsonUtil.toJson(alertReport));
throw e;
}
alertService.addNewAlertReport(alertReport);
return ResponseEntity.ok(Message.success("Add report success"));
}
}
@@ -1,77 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.dromara.hertzbeat.alert.service.AlertSilenceService;
import org.dromara.hertzbeat.common.entity.alerter.AlertSilence;
import org.dromara.hertzbeat.common.entity.dto.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid;
import static org.dromara.hertzbeat.common.constants.CommonConstants.MONITOR_NOT_EXIST_CODE;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
/**
* Alarm Silence management API
*
*/
@Tag(name = "Alert Silence API | 告警静默管理API")
@RestController
@RequestMapping(path = "/api/alert/silence", produces = {APPLICATION_JSON_VALUE})
public class AlertSilenceController {
@Autowired
private AlertSilenceService alertSilenceService;
@PostMapping
@Operation(summary = "New Alarm Silence | 新增告警静默", description = "Added an alarm Silence | 新增一个告警静默")
public ResponseEntity<Message<Void>> addNewAlertSilence(@Valid @RequestBody AlertSilence alertSilence) {
alertSilenceService.validate(alertSilence, false);
alertSilenceService.addAlertSilence(alertSilence);
return ResponseEntity.ok(Message.success("Add success"));
}
@PutMapping
@Operation(summary = "Modifying an Alarm Silence | 修改告警静默", description = "Modify an existing alarm Silence | 修改一个已存在告警静默")
public ResponseEntity<Message<Void>> modifyAlertSilence(@Valid @RequestBody AlertSilence alertSilence) {
alertSilenceService.validate(alertSilence, true);
alertSilenceService.modifyAlertSilence(alertSilence);
return ResponseEntity.ok(Message.success("Modify success"));
}
@GetMapping(path = "/{id}")
@Operation(summary = "Querying Alarm Silence | 查询告警静默",
description = "You can obtain alarm Silence information based on the alarm Silence ID | 根据告警静默ID获取告警静默信息")
public ResponseEntity<Message<AlertSilence>> getAlertSilence(
@Parameter(description = "Alarm Silence ID 告警静默ID", example = "6565463543") @PathVariable("id") long id) {
AlertSilence alertSilence = alertSilenceService.getAlertSilence(id);
if (alertSilence == null) {
return ResponseEntity.ok(Message.fail(MONITOR_NOT_EXIST_CODE, "AlertSilence not exist."));
} else {
return ResponseEntity.ok(Message.success(alertSilence));
}
}
}
@@ -1,107 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.dromara.hertzbeat.alert.service.AlertSilenceService;
import org.dromara.hertzbeat.common.entity.alerter.AlertSilence;
import org.dromara.hertzbeat.common.entity.dto.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
/**
* Silence the batch API for alarms
*
*/
@Tag(name = "Alert Silence Batch API | 告警静默管理API")
@RestController
@RequestMapping(path = "/api/alert/silences", produces = {APPLICATION_JSON_VALUE})
public class AlertSilencesController {
@Autowired
private AlertSilenceService alertSilenceService;
@GetMapping
@Operation(summary = "Query the alarm silence list 查询告警静默列表",
description = "You can obtain the list of alarm silence by querying filter items | 根据查询过滤项获取告警静默信息列表")
public ResponseEntity<Message<Page<AlertSilence>>> getAlertSilences(
@Parameter(description = "Alarm Silence ID 告警静默ID", example = "6565463543") @RequestParam(required = false) List<Long> ids,
@Parameter(description = "Search Name 模糊查询-名称", example = "x") @RequestParam(required = false) String search,
@Parameter(description = "Sort field, default id 排序字段,默认id", example = "id") @RequestParam(defaultValue = "id") String sort,
@Parameter(description = "Sort mode: asc: ascending, desc: descending 排序方式,asc:升序,desc:降序", example = "desc") @RequestParam(defaultValue = "desc") String order,
@Parameter(description = "List current page 列表当前分页", example = "0") @RequestParam(defaultValue = "0") int pageIndex,
@Parameter(description = "Number of list pages 列表分页数量", example = "8") @RequestParam(defaultValue = "8") int pageSize) {
Specification<AlertSilence> specification = (root, query, criteriaBuilder) -> {
List<Predicate> andList = new ArrayList<>();
if (ids != null && !ids.isEmpty()) {
CriteriaBuilder.In<Long> inPredicate= criteriaBuilder.in(root.get("id"));
for (long id : ids) {
inPredicate.value(id);
}
andList.add(inPredicate);
}
if (StringUtils.hasText(search)) {
Predicate predicate = criteriaBuilder.or(
criteriaBuilder.like(
criteriaBuilder.lower(root.get("name")),
"%" + search.toLowerCase() + "%"
)
);
andList.add(predicate);
}
Predicate[] predicates = new Predicate[andList.size()];
return criteriaBuilder.and(andList.toArray(predicates));
};
Sort sortExp = Sort.by(new Sort.Order(Sort.Direction.fromString(order), sort));
PageRequest pageRequest = PageRequest.of(pageIndex, pageSize, sortExp);
Page<AlertSilence> alertSilencePage = alertSilenceService.getAlertSilences(specification, pageRequest);
Message<Page<AlertSilence>> message = Message.success(alertSilencePage);
return ResponseEntity.ok(message);
}
@DeleteMapping
@Operation(summary = "Delete alarm silence in batches 批量删除告警静默",
description = "Delete alarm silence in batches based on the alarm silence ID list 根据告警静默ID列表批量删除告警静默")
public ResponseEntity<Message<Void>> deleteAlertDefines(
@Parameter(description = "Alarm Silence IDs 告警静默IDs", example = "6565463543") @RequestParam(required = false) List<Long> ids
) {
if (ids != null && !ids.isEmpty()) {
alertSilenceService.deleteAlertSilences(new HashSet<>(ids));
}
Message<Void> message = Message.success();
return ResponseEntity.ok(message);
}
}
@@ -1,144 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.controller;
import org.dromara.hertzbeat.alert.dto.AlertSummary;
import org.dromara.hertzbeat.common.entity.alerter.Alert;
import org.dromara.hertzbeat.alert.service.AlertService;
import org.dromara.hertzbeat.common.entity.dto.Message;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
/**
* Alarm Management API
*
*
*/
@Tag(name = "Alarm Manage Batch API | 告警批量管理API")
@RestController
@RequestMapping(path = "/api/alerts", produces = {APPLICATION_JSON_VALUE})
public class AlertsController {
@Autowired
private AlertService alertService;
@GetMapping
@Operation(summary = "Get a list of alarm information based on query filter items", description = "根据查询过滤项获取告警信息列表")
public ResponseEntity<Message<Page<Alert>>> getAlerts(
@Parameter(description = "Alarm ID List | 告警IDS", example = "6565466456") @RequestParam(required = false) List<Long> ids,
@Parameter(description = "Alarm monitor object ID | 告警监控对象ID", example = "6565463543") @RequestParam(required = false) Long monitorId,
@Parameter(description = "Alarm level | 告警级别", example = "6565463543") @RequestParam(required = false) Byte priority,
@Parameter(description = "Alarm Status | 告警状态", example = "6565463543") @RequestParam(required = false) Byte status,
@Parameter(description = "Alarm content fuzzy query | 告警内容模糊查询", example = "linux") @RequestParam(required = false) String content,
@Parameter(description = "Sort field, default id | 排序字段,默认id", example = "name") @RequestParam(defaultValue = "id") String sort,
@Parameter(description = "Sort Type | 排序方式,asc:升序,desc:降序", example = "desc") @RequestParam(defaultValue = "desc") String order,
@Parameter(description = "List current page | 列表当前分页", example = "0") @RequestParam(defaultValue = "0") int pageIndex,
@Parameter(description = "Number of list pagination | 列表分页数量", example = "8") @RequestParam(defaultValue = "8") int pageSize) {
Specification<Alert> specification = (root, query, criteriaBuilder) -> {
List<Predicate> andList = new ArrayList<>();
if (ids != null && !ids.isEmpty()) {
CriteriaBuilder.In<Long> inPredicate = criteriaBuilder.in(root.get("id"));
for (long id : ids) {
inPredicate.value(id);
}
andList.add(inPredicate);
}
if (monitorId != null) {
Predicate predicate = criteriaBuilder.like(root.get("tags").as(String.class), "%" + monitorId + "%");
andList.add(predicate);
}
if (priority != null) {
Predicate predicate = criteriaBuilder.equal(root.get("priority"), priority);
andList.add(predicate);
}
if (status != null) {
Predicate predicate = criteriaBuilder.equal(root.get("status"), status);
andList.add(predicate);
}
if (content != null && !content.isEmpty()) {
Predicate predicateContent = criteriaBuilder.like(root.get("content"), "%" + content + "%");
andList.add(predicateContent);
}
Predicate[] predicates = new Predicate[andList.size()];
return criteriaBuilder.and(andList.toArray(predicates));
};
Sort sortExp = Sort.by(new Sort.Order(Sort.Direction.fromString(order), sort));
PageRequest pageRequest = PageRequest.of(pageIndex, pageSize, sortExp);
Page<Alert> alertPage = alertService.getAlerts(specification, pageRequest);
Message<Page<Alert>> message = Message.success(alertPage);
return ResponseEntity.ok(message);
}
@DeleteMapping
@Operation(summary = "Delete alarms in batches", description = "根据告警ID列表批量删除告警")
public ResponseEntity<Message<Void>> deleteAlerts(
@Parameter(description = "Alarm List ID | 告警IDs", example = "6565463543") @RequestParam(required = false) List<Long> ids) {
if (ids != null && !ids.isEmpty()) {
alertService.deleteAlerts(new HashSet<>(ids));
}
Message<Void> message = Message.success();
return ResponseEntity.ok(message);
}
@DeleteMapping("/clear")
@Operation(summary = "Delete alarms in batches", description = "清空所有告警信息")
public ResponseEntity<Message<Void>> clearAllAlerts() {
alertService.clearAlerts();
Message<Void> message = Message.success();
return ResponseEntity.ok(message);
}
@PutMapping(path = "/status/{status}")
@Operation(summary = "Batch modify alarm status, set read and unread", description = "批量修改告警状态,设置已读未读")
public ResponseEntity<Message<Void>> applyAlertDefinesStatus(
@Parameter(description = "Alarm status value | 告警状态值", example = "0") @PathVariable Byte status,
@Parameter(description = "Alarm List IDS | 告警IDS", example = "6565463543") @RequestParam(required = false) List<Long> ids) {
if (ids != null && status != null && !ids.isEmpty()) {
alertService.editAlertStatus(status, ids);
}
Message<Void> message = Message.success();
return ResponseEntity.ok(message);
}
@GetMapping(path = "/summary")
@Operation(summary = "Get alarm statistics", description = "获取告警统计信息")
public ResponseEntity<Message<AlertSummary>> getAlertsSummary() {
AlertSummary alertSummary = alertService.getAlertsSummary();
Message<AlertSummary> message = Message.success(alertSummary);
return ResponseEntity.ok(message);
}
}
@@ -1,41 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.dao;
import org.dromara.hertzbeat.common.entity.alerter.AlertConverge;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import java.util.Set;
/**
* AlertConverge Dao
*
*
*/
public interface AlertConvergeDao extends JpaRepository<AlertConverge, Long>, JpaSpecificationExecutor<AlertConverge> {
/**
* Delete alarm converge based on the ID list
*
* @param convergeIds alert converge id list
*/
@Modifying
void deleteAlertConvergesByIdIn(Set<Long> convergeIds);
}
@@ -1,59 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.dao;
import org.dromara.hertzbeat.alert.dto.AlertPriorityNum;
import org.dromara.hertzbeat.common.entity.alerter.Alert;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;
import java.util.Set;
/**
* Alert Database Operations
*
*/
public interface AlertDao extends JpaRepository<Alert, Long>, JpaSpecificationExecutor<Alert> {
/**
* Delete alerts based on ID list
* @param alertIds Alert ID List
*/
void deleteAlertsByIdIn(Set<Long> alertIds);
/**
* Updates the alarm status based on the alarm ID-status value
* @param status status value
* @param ids alarm ids
*/
@Modifying
@Query("update Alert set status = :status where id in :ids")
void updateAlertsStatus(@Param(value = "status") Byte status, @Param(value = "ids") List<Long> ids);
/**
* Query the number of unhandled alarms of each alarm severity
* 查询各个告警级别的未处理告警数量
* @return List of alerts num
*/
@Query("select new org.dromara.hertzbeat.alert.dto.AlertPriorityNum(mo.priority, count(mo.id)) from Alert mo where mo.status = 0 group by mo.priority")
List<AlertPriorityNum> findAlertPriorityNum();
}
@@ -1,71 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.dao;
import org.dromara.hertzbeat.common.entity.alerter.AlertDefine;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;
import java.util.Set;
/**
* AlertDefine Dao
*
*/
public interface AlertDefineDao extends JpaRepository<AlertDefine, Long>, JpaSpecificationExecutor<AlertDefine> {
/**
* Delete alarm definitions based on the ID list
* @param alertDefineIds alarm define ids
*/
void deleteAlertDefinesByIdIn(Set<Long> alertDefineIds);
/**
* Query the default alarm thresholds based on the monitoring metrics type
* 根据监控指标类型查询对应默认告警定义阈值
* @param app monitoring type
* @param metric metrics
* @return alarm defines
*/
List<AlertDefine> queryAlertDefinesByAppAndMetricAndPresetTrueAndEnableTrue(String app, String metric);
/**
* Query app metric alert define
* @param app app
* @param metric metric
* @return alert define
*/
List<AlertDefine> queryAlertDefineByAppAndMetric(String app, String metric);
/**
* Query the alarm definition list associated with the monitoring ID
* 根据监控任务ID查询与之关联的告警定义列表
* @param monitorId monitor id
* @param app monitor type
* @param metrics metrics
* @return Alarm Definition List
*/
@Query("select define from AlertDefine define join AlertDefineMonitorBind bind on bind.alertDefineId = define.id " +
"where bind.monitorId = :monitorId and define.app = :app and define.metric = :metrics and define.enable = true and define.preset = false")
List<AlertDefine> queryAlertDefinesByMonitor(@Param(value = "monitorId") Long monitorId,
@Param(value = "app") String app,
@Param(value = "metrics") String metrics);
}
@@ -1,78 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.dto;
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.util.Map;
/**
* Abstract parent of cloud service alarm information
* {@link org.dromara.hertzbeat.common.entity.dto.AlertReport} - The method corresponds to the parameter of this class one by one. For details about the method, see this class
*/
public abstract class CloudAlertReportAbstract {
/**
* This parameter specifies the alarm name when a cloud alarm is converted to an internal alarm
*/
@JsonIgnore
public abstract String getAlertName();
/**
* Interval when a cloud alarm is converted to an internal alarm
*/
@JsonIgnore
public abstract Integer getAlertDuration();
/**
* Specifies the alarm time when a cloud alarm is converted to an internal alarm
*/
@JsonIgnore
public abstract long getAlertTime();
/**
* Severity of an alarm when a cloud alarm is converted to an internal alarm
*/
@JsonIgnore
public abstract Integer getPriority();
/**
* This parameter specifies the alarm type when a cloud alarm is converted to an internal alarm
*/
@JsonIgnore
public abstract Integer getReportType();
/**
* Alarm label information about a cloud alarm that is converted to an internal alarm
*/
@JsonIgnore
public abstract Map<String, String> getLabels();
/**
* Alarm labels when a cloud alarm is converted to an internal alarm
*/
@JsonIgnore
public abstract Map<String, String> getAnnotations();
/**
* This topic describes the alarm content when a cloud alarm is converted to an internal alarm
*/
@JsonIgnore
public abstract String getContent();
}
@@ -1,72 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.dto;
import lombok.*;
import org.apache.commons.lang3.StringUtils;
import org.dromara.hertzbeat.alert.util.DateUtil;
import org.dromara.hertzbeat.common.entity.dto.AlertReport;
/**
* Generic cloud alarm entity class
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class GeneralCloudAlertReport extends AlertReport {
/**
* Alarm date and time
*/
private String alertDateTime;
/**
* DATE TIME FORMAT
*/
private String dateTimeFormat;
/**
* You can refresh the timestamp of the alarm time with enhanced properties
*/
public void refreshAlertTime() {
// 有时间戳,取时间戳
if (getAlertTime() != 0L) {
return;
}
// 没有时间戳,判断是否有字符串配置
if (StringUtils.isNotBlank(alertDateTime)) {
Long timeStamp = null;
// 优先用户配置
if (StringUtils.isNotBlank(dateTimeFormat)) {
timeStamp = DateUtil.getTimeStampFromFormat(alertDateTime, dateTimeFormat);
}
// 默认支持日期格式
if (timeStamp == null) {
timeStamp = DateUtil.getTimeStampFromSomeFormats(alertDateTime);
}
// 解析成功
if (timeStamp != null) {
setAlertTime(timeStamp);
return;
}
}
throw new RuntimeException("告警时间解析异常");
}
}
@@ -1,228 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.dromara.hertzbeat.alert.util.DateUtil;
import java.io.Serializable;
import java.util.Map;
/**
*
* Tencent cloud alarm entity class
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@Builder
public class TenCloudAlertReport extends CloudAlertReportAbstract implements Serializable {
@JsonProperty("sessionID")
private String sessionId;
private String alarmStatus;
private String alarmType;
private AlarmObjInfo alarmObjInfo;
private AlarmPolicyInfo alarmPolicyInfo;
private String firstOccurTime;
private int durationTime;
private String recoverTime;
/**
* Alarm Object information
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class AlarmObjInfo {
private String region;
private String namespace;
@JsonProperty("appID")
private String appId;
private String uin;
private Dimensions dimensions;
}
/**
* Uniform Resource ID information
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class Dimensions {
@JsonProperty("unInstanceID")
private String unInstanceId;
@JsonProperty("objID")
private String objId;
}
/**
* Alarm policy information
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class AlarmPolicyInfo {
@JsonProperty("policyID")
private String policyId;
private String policyType;
private String policyName;
@JsonProperty("policyTypeCName")
private String policyTypeCname;
private Conditions conditions;
}
/**
* Parameters of indicator alarms
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class Conditions {
// 指标告警的参数
private String metricName;
private String metricShowName;
private String calcType;
private String calcValue;
private String calcUnit;
private String currentValue;
private String historyValue;
private String unit;
private String period;
private String periodNum;
private String alarmNotifyType;
private long alarmNotifyPeriod;
// 事件告警的参数
private String productName;
private String productShowName;
private String eventName;
private String eventShowName;
}
@Override
public String getAlertName() {
return "TenCloud|腾讯云";
}
@Override
public Integer getAlertDuration() {
return this.durationTime;
}
@Override
public long getAlertTime() {
return DateUtil.getTimeStampFromFormat(getFirstOccurTime(), "yyyy-MM-dd HH:mm:ss");
}
@Override
public Integer getPriority() {
return 1;
}
@Override
public Integer getReportType() {
return 1;
}
@Override
public Map<String, String> getLabels() {
return Map.of("app", "TenCloud");
}
@Override
public Map<String, String> getAnnotations() {
return Map.of("app", "TenCloud");
}
/**
* Transaction alarm
*/
private static final String EVENT = "event";
/**
* Indicator alarm
*/
private static final String METRIC = "metric";
/**
* If the following alarm types increase, the entity class can be divided into a parent class and multiple subclasses, and then the method can be implemented in the subclass
* Since there are only two, it will not be split for the time being
*/
@Override
public String getContent() {
StringBuilder contentBuilder = new StringBuilder();
// 判断类型
if (EVENT.equals(getAlarmType())) {
contentBuilder
.append("[")
.append("告警状态 | ")
.append("0".equals(alarmStatus) ? "恢复" : "告警")
.append("]\n")
.append("[")
.append("告警对象信息 | ")
.append(getAlarmObjInfo().getRegion() == null ? "" : "region:" + getAlarmObjInfo().getRegion())
.append(";").append("appId:").append(getAlarmObjInfo().getAppId())
.append(";").append("uni:").append(getAlarmObjInfo().getUin())
.append(";").append("unInstanceId:").append(getAlarmObjInfo().getDimensions().getUnInstanceId())
.append("]\n")
.append("[")
.append("告警策略组信息 | ")
.append("名称:").append(getAlarmPolicyInfo().getPolicyName())
.append(";")
.append("策略类型展示名称:").append(getAlarmPolicyInfo().getConditions().getProductName())
.append(",").append(getAlarmPolicyInfo().getConditions().getProductShowName())
.append(";")
.append("事件告警名称:").append(getAlarmPolicyInfo().getConditions().getEventName())
.append(",").append(getAlarmPolicyInfo().getConditions().getEventShowName())
.append("]");
} else if (METRIC.equals(getAlarmType())) {
contentBuilder
.append("[")
.append("告警对象:")
.append(getAlarmObjInfo().getRegion() == null ? "" : getAlarmObjInfo().getRegion())
.append(getAlarmObjInfo().getRegion() == null ? "" : "|")
.append(getAlarmObjInfo().getNamespace())
.append("]")
.append("[")
.append("告警内容:")
.append(getAlarmPolicyInfo().getPolicyTypeCname()).append("|")
.append(getAlarmPolicyInfo().getConditions().getMetricShowName()).append("|")
.append(getAlarmPolicyInfo().getConditions().getMetricName())
.append(getAlarmPolicyInfo().getConditions().getCalcType())
.append(getAlarmPolicyInfo().getConditions().getCalcValue())
.append(getAlarmPolicyInfo().getConditions().getCalcUnit())
.append("]")
.append("[")
.append("当前数据")
.append(getAlarmPolicyInfo().getConditions().getCurrentValue())
.append(getAlarmPolicyInfo().getConditions().getCalcUnit())
.append("]");
}
return contentBuilder.toString();
}
}
@@ -1,53 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.dromara.hertzbeat.alert.dto.CloudAlertReportAbstract;
import org.dromara.hertzbeat.alert.dto.TenCloudAlertReport;
import java.util.Arrays;
/**
* Cloud server alarm enum
*/
@AllArgsConstructor
@Getter
public enum CloudServiceAlarmInformationEnum {
TencentCloud("tencloud", TenCloudAlertReport.class);
/**
* cloud service name
*/
private final String cloudServiceName;
/**
* cloud service body
*/
private final Class<? extends CloudAlertReportAbstract> cloudServiceAlarmInformationEntity;
public static CloudServiceAlarmInformationEnum getEnumFromCloudServiceName(String name) {
return Arrays.stream(CloudServiceAlarmInformationEnum.values())
.filter(cloudService -> cloudService.cloudServiceName.equals(name))
.findFirst()
.orElse(null);
}
}
@@ -1,76 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.reduce;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hertzbeat.alert.dao.AlertMonitorDao;
import org.dromara.hertzbeat.common.constants.CommonConstants;
import org.dromara.hertzbeat.common.entity.alerter.Alert;
import org.dromara.hertzbeat.common.entity.manager.Tag;
import org.dromara.hertzbeat.common.queue.CommonDataQueue;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* reduce alarm and send alert data
*
*
*/
@Service
@RequiredArgsConstructor
@Slf4j
public class AlarmCommonReduce {
private final AlarmSilenceReduce alarmSilenceReduce;
private final AlarmConvergeReduce alarmConvergeReduce;
private final CommonDataQueue dataQueue;
private final AlertMonitorDao alertMonitorDao;
public void reduceAndSendAlarm(Alert alert) {
alert.setTimes(1);
Map<String, String> tags = alert.getTags();
if (tags == null) {
tags = new HashMap<>(8);
alert.setTags(tags);
}
String monitorIdStr = tags.get(CommonConstants.TAG_MONITOR_ID);
if (monitorIdStr == null) {
log.debug("receiver extern alarm message: {}", alert);
} else {
long monitorId = Long.parseLong(monitorIdStr);
List<Tag> tagList = alertMonitorDao.findMonitorIdBindTags(monitorId);
for (Tag tag : tagList) {
if (!tags.containsKey(tag.getName())) {
tags.put(tag.getName(), tag.getValue());
}
}
}
// converge -> silence
if (alarmConvergeReduce.filterConverge(alert) && alarmSilenceReduce.filterSilence(alert)) {
dataQueue.sendAlertsData(alert);
}
}
}
@@ -1,163 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.reduce;
import org.dromara.hertzbeat.alert.dao.AlertConvergeDao;
import org.dromara.hertzbeat.common.cache.CacheFactory;
import org.dromara.hertzbeat.common.cache.CommonCacheService;
import org.dromara.hertzbeat.common.constants.CommonConstants;
import org.dromara.hertzbeat.common.entity.alerter.Alert;
import org.dromara.hertzbeat.common.entity.alerter.AlertConverge;
import org.dromara.hertzbeat.common.entity.manager.TagItem;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
/**
* alarm converge
*
*
*/
@Service
public class AlarmConvergeReduce {
private final AlertConvergeDao alertConvergeDao;
private final Map<Integer, Alert> converageAlertMap;
public AlarmConvergeReduce(AlertConvergeDao alertConvergeDao) {
this.alertConvergeDao = alertConvergeDao;
this.converageAlertMap = new ConcurrentHashMap<>(16);
}
/**
* currentAlert converge filter data
*
* @param currentAlert currentAlert
* @return true when not filter
*/
@SuppressWarnings("unchecked")
public boolean filterConverge(Alert currentAlert) {
// ignore monitor status auto recover notice
if (currentAlert.getTags() != null && currentAlert.getTags().containsKey(CommonConstants.IGNORE)) {
return true;
}
if (currentAlert.getStatus() == CommonConstants.ALERT_STATUS_CODE_RESTORED) {
// restored alert
int alertHash = Objects.hash(CommonConstants.ALERT_PRIORITY_CODE_CRITICAL)
+ Arrays.hashCode(currentAlert.getTags().keySet().toArray(new String[0]))
+ Arrays.hashCode(currentAlert.getTags().values().toArray(new String[0]));
converageAlertMap.remove(alertHash);
alertHash = Objects.hash(CommonConstants.ALERT_PRIORITY_CODE_EMERGENCY)
+ Arrays.hashCode(currentAlert.getTags().keySet().toArray(new String[0]))
+ Arrays.hashCode(currentAlert.getTags().values().toArray(new String[0]));
converageAlertMap.remove(alertHash);
alertHash = Objects.hash(CommonConstants.ALERT_PRIORITY_CODE_WARNING)
+ Arrays.hashCode(currentAlert.getTags().keySet().toArray(new String[0]))
+ Arrays.hashCode(currentAlert.getTags().values().toArray(new String[0]));
converageAlertMap.remove(alertHash);
return true;
}
CommonCacheService<String, Object> convergeCache = CacheFactory.getAlertConvergeCache();
List<AlertConverge> alertConvergeList = (List<AlertConverge>) convergeCache.get(CommonConstants.CACHE_ALERT_CONVERGE);
if (alertConvergeList == null) {
alertConvergeList = alertConvergeDao.findAll();
// matchAll is in the last
alertConvergeList.sort((item1, item2) -> {
if (item1.isMatchAll()) {
return 1;
} else if (item2.isMatchAll()) {
return -1;
} else {
return 0;
}
});
convergeCache.put(CommonConstants.CACHE_ALERT_CONVERGE, alertConvergeList);
}
for (AlertConverge alertConverge : alertConvergeList) {
if (!alertConverge.isEnable()) {
continue;
}
boolean match = alertConverge.isMatchAll();
if (!match) {
List<TagItem> tags = alertConverge.getTags();
if (currentAlert.getTags() != null && !currentAlert.getTags().isEmpty()) {
Map<String, String> alertTagMap = currentAlert.getTags();
match = tags.stream().anyMatch(item -> {
if (alertTagMap.containsKey(item.getName())) {
String tagValue = alertTagMap.get(item.getName());
if (tagValue == null && item.getValue() == null) {
return true;
} else {
return tagValue != null && tagValue.equals(item.getValue());
}
} else {
return false;
}
});
} else {
match = true;
}
if (match && alertConverge.getPriorities() != null && !alertConverge.getPriorities().isEmpty()) {
match = alertConverge.getPriorities().stream().anyMatch(item -> item != null && item == currentAlert.getPriority());
}
}
if (match) {
long evalInterval = alertConverge.getEvalInterval() * 1000;
long now = System.currentTimeMillis();
if (evalInterval <= 0) {
return true;
}
int alertHash = Objects.hash(currentAlert.getPriority())
+ Arrays.hashCode(currentAlert.getTags().keySet().toArray(new String[0]))
+ Arrays.hashCode(currentAlert.getTags().values().toArray(new String[0]));
Alert preAlert = converageAlertMap.get(alertHash);
if (preAlert == null) {
currentAlert.setTimes(1);
currentAlert.setFirstAlarmTime(now);
currentAlert.setLastAlarmTime(now);
converageAlertMap.put(alertHash, currentAlert.clone());
return true;
} else {
if (now - preAlert.getFirstAlarmTime() < evalInterval) {
preAlert.setTimes(preAlert.getTimes() + 1);
preAlert.setLastAlarmTime(now);
return false;
} else {
currentAlert.setTimes(preAlert.getTimes());
if (preAlert.getTimes() == 1) {
currentAlert.setFirstAlarmTime(now);
} else {
currentAlert.setFirstAlarmTime(preAlert.getFirstAlarmTime());
}
currentAlert.setLastAlarmTime(now);
preAlert.setFirstAlarmTime(now);
preAlert.setLastAlarmTime(now);
preAlert.setTimes(1);
return true;
}
}
}
}
return true;
}
}
@@ -1,128 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.reduce;
import lombok.RequiredArgsConstructor;
import org.dromara.hertzbeat.alert.dao.AlertSilenceDao;
import org.dromara.hertzbeat.common.cache.CacheFactory;
import org.dromara.hertzbeat.common.cache.CommonCacheService;
import org.dromara.hertzbeat.common.constants.CommonConstants;
import org.dromara.hertzbeat.common.entity.alerter.Alert;
import org.dromara.hertzbeat.common.entity.alerter.AlertSilence;
import org.dromara.hertzbeat.common.entity.manager.TagItem;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.Map;
import java.util.Optional;
/**
* silence alarm
*
*
*/
@Service
@RequiredArgsConstructor
public class AlarmSilenceReduce {
private final AlertSilenceDao alertSilenceDao;
/**
* alert silence filter data
*
* @param alert alert
* @return true when not filter
*/
@SuppressWarnings("unchecked")
public boolean filterSilence(Alert alert) {
CommonCacheService<String, Object> silenceCache = CacheFactory.getAlertSilenceCache();
List<AlertSilence> alertSilenceList = (List<AlertSilence>) silenceCache.get(CommonConstants.CACHE_ALERT_SILENCE);
if (alertSilenceList == null) {
alertSilenceList = alertSilenceDao.findAll();
silenceCache.put(CommonConstants.CACHE_ALERT_SILENCE, alertSilenceList);
}
for (AlertSilence alertSilence : alertSilenceList) {
if (!alertSilence.isEnable()) {
continue;
}
// if match the silence rule, return
boolean match = alertSilence.isMatchAll();
if (!match) {
List<TagItem> tags = alertSilence.getTags();
if (alert.getTags() != null && !alert.getTags().isEmpty()) {
Map<String, String> alertTagMap = alert.getTags();
match = tags.stream().anyMatch(item -> {
if (alertTagMap.containsKey(item.getName())) {
String tagValue = alertTagMap.get(item.getName());
if (tagValue == null && item.getValue() == null) {
return true;
} else {
return tagValue != null && tagValue.equals(item.getValue());
}
} else {
return false;
}
});
} else {
match = true;
}
if (match && alertSilence.getPriorities() != null && !alertSilence.getPriorities().isEmpty()) {
match = alertSilence.getPriorities().stream().anyMatch(item -> item != null && item == alert.getPriority());
}
}
if (match) {
LocalDateTime nowDate = LocalDateTime.now();
if (alertSilence.getType() == 0) {
// once time
boolean startMatch = alertSilence.getPeriodStart() == null ||
nowDate.isAfter(alertSilence.getPeriodStart().toLocalDateTime());
boolean endMatch = alertSilence.getPeriodEnd() == null ||
nowDate.isBefore(alertSilence.getPeriodEnd().toLocalDateTime());
if (startMatch && endMatch) {
int times = Optional.ofNullable(alertSilence.getTimes()).orElse(0);
alertSilence.setTimes(times + 1);
alertSilenceDao.save(alertSilence);
return false;
}
} else if (alertSilence.getType() == 1) {
// cyc time
int currentDayOfWeek = nowDate.toLocalDate().getDayOfWeek().getValue();
if (alertSilence.getDays() != null && !alertSilence.getDays().isEmpty()) {
boolean dayMatch = alertSilence.getDays().stream().anyMatch(item -> item == currentDayOfWeek);
if (dayMatch) {
LocalTime nowTime = nowDate.toLocalTime();
boolean startMatch = alertSilence.getPeriodStart() == null ||
nowTime.isAfter(alertSilence.getPeriodStart().toLocalTime());
boolean endMatch = alertSilence.getPeriodEnd() == null ||
nowTime.isBefore(alertSilence.getPeriodEnd().toLocalTime());
if (startMatch && endMatch) {
int times = Optional.ofNullable(alertSilence.getTimes()).orElse(0);
alertSilence.setTimes(times + 1);
alertSilenceDao.save(alertSilence);
return false;
}
}
}
}
}
}
return true;
}
}
@@ -1,84 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.service;
import org.dromara.hertzbeat.common.entity.alerter.AlertConverge;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import java.util.Set;
/**
* management interface service for alert converge
*
*
*/
public interface AlertConvergeService {
/**
* Verify the correctness of the request data parameters
*
* @param alertConverge AlertConverge
* @param isModify whether modify
* @throws IllegalArgumentException A checksum parameter error is thrown
*/
void validate(AlertConverge alertConverge, boolean isModify) throws IllegalArgumentException;
/**
* New AlertConverge
*
* @param alertConverge AlertConverge Entity
* @throws RuntimeException Added procedure exception throwing
*/
void addAlertConverge(AlertConverge alertConverge) throws RuntimeException;
/**
* Modifying an AlertConverge
*
* @param alertConverge Alarm definition Entity
* @throws RuntimeException Exception thrown during modification
*/
void modifyAlertConverge(AlertConverge alertConverge) throws RuntimeException;
/**
* Obtain AlertConverge information
*
* @param convergeId AlertConverge ID
* @return AlertConverge
* @throws RuntimeException An exception was thrown during the query
*/
AlertConverge getAlertConverge(long convergeId) throws RuntimeException;
/**
* Delete AlertConverge in batches
*
* @param convergeIds AlertConverge IDs
* @throws RuntimeException Exception thrown during deletion
*/
void deleteAlertConverges(Set<Long> convergeIds) throws RuntimeException;
/**
* Dynamic conditional query
*
* @param specification Query conditions
* @param pageRequest Paging parameters
* @return The query results
*/
Page<AlertConverge> getAlertConverges(Specification<AlertConverge> specification, PageRequest pageRequest);
}
@@ -1,151 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.service;
import org.dromara.hertzbeat.common.entity.alerter.AlertDefine;
import org.dromara.hertzbeat.common.entity.alerter.AlertDefineMonitorBind;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.multipart.MultipartFile;
import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Alarm define manager service
*
*/
public interface AlertDefineService {
/**
* Verify the correctness of the request data parameters
* @param alertDefine alertDefine
* @param isModify whether modify
* @throws IllegalArgumentException A checksum parameter error is thrown
*/
void validate(AlertDefine alertDefine, boolean isModify) throws IllegalArgumentException;
/**
* New Alarm Definition
* @param alertDefine Alarm definition Entity
* @throws RuntimeException Added procedure exception throwing
*/
void addAlertDefine(AlertDefine alertDefine) throws RuntimeException;
/**
* Modifying an Alarm Definition
* @param alertDefine Alarm definition Entity
* @throws RuntimeException Exception thrown during modification
*/
void modifyAlertDefine(AlertDefine alertDefine) throws RuntimeException;
/**
* Deleting an Alarm Definition
* @param alertId Alarm Definition ID
* @throws RuntimeException Exception thrown during deletion
*/
void deleteAlertDefine(long alertId) throws RuntimeException;
/**
* Obtain alarm definition information
* @param alertId Monitor the ID
* @return AlertDefine
* @throws RuntimeException An exception was thrown during the query
*/
AlertDefine getAlertDefine(long alertId) throws RuntimeException;
/**
* Delete alarm definitions in batches
* @param alertIds Alarm Definition IDs
* @throws RuntimeException Exception thrown during deletion
*/
void deleteAlertDefines(Set<Long> alertIds) throws RuntimeException;
/**
* Dynamic conditional query
* @param specification Query conditions
* @param pageRequest Paging parameters
* @return The query results
*/
Page<AlertDefine> getMonitorBindAlertDefines(Specification<AlertDefine> specification, PageRequest pageRequest);
/**
* Association between application alarm schedule and monitoring
* @param alertId Alarm Definition ID
* @param alertDefineBinds correlation
*/
void applyBindAlertDefineMonitors(Long alertId, List<AlertDefineMonitorBind> alertDefineBinds);
/**
* Query the alarm definitions that match the specified metrics associated with the monitoring ID
* 查询与此监控任务ID关联的指定指标匹配的告警定义
* @param monitorId Monitor the ID
* @param app Monitoring type
* @param metrics metrics
* @return field - define[]
*/
Map<String, List<AlertDefine>> getMonitorBindAlertDefines(long monitorId, String app, String metrics);
/**
* Query the alarm definitions that match the specified metrics associated with the monitoring ID
* 查询与此监控任务ID关联的可用性告警定义
* @param monitorId Monitor the ID
* @param app Monitoring type
* @param metrics metrics
* @return field - define[]
*/
AlertDefine getMonitorBindAlertAvaDefine(long monitorId, String app, String metrics);
/**
* Dynamic conditional query
* @param specification Query conditions
* @param pageRequest Paging parameters
* @return The query results
*/
Page<AlertDefine> getAlertDefines(Specification<AlertDefine> specification, PageRequest pageRequest);
/**
* Query the associated monitoring list information based on the alarm definition ID
* 根据告警定义ID查询其关联的监控列表关联信息
* @param alertDefineId Alarm Definition ID
* @return Associated information about the monitoring list
*/
List<AlertDefineMonitorBind> getBindAlertDefineMonitors(long alertDefineId);
/**
* Export file configuration of specified type based on ID list and export file type
* 根据ID列表、导出文件类型导出指定类型文件配置
* @param ids AlertDefine ID
* @param type File Type
* @param res Response
* @throws Exception An exception was thrown during the export
*/
void export(List<Long> ids, String type, HttpServletResponse res) throws Exception;
/**
* Add alarm threshold rules based on the uploaded alarm threshold file
* 根据上传的告警阀值文件,增加告警阀值规则
* @param file Upload File
* @throws Exception An exception was thrown during the importConfig
*/
void importConfig(MultipartFile file) throws Exception;
}
@@ -1,89 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.service;
import org.dromara.hertzbeat.alert.dto.AlertSummary;
import org.dromara.hertzbeat.common.entity.alerter.Alert;
import org.dromara.hertzbeat.common.entity.dto.AlertReport;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import java.util.HashSet;
import java.util.List;
/**
* Alarm information management interface
*
*/
public interface AlertService {
/**
* Add alarm record
* @param alert Alert entity
* @throws RuntimeException Add process exception throw
*/
void addAlert(Alert alert) throws RuntimeException;
/**
* Dynamic conditional query
* @param specification Query conditions
* @param pageRequest pagination parameters
* @return search result
*/
Page<Alert> getAlerts(Specification<Alert> specification, PageRequest pageRequest);
/**
* Delete alarms in batches according to the alarm ID list
* 根据告警ID列表批量删除告警
* @param ids Alarm ID List
*/
void deleteAlerts(HashSet<Long> ids);
/**
* Clear all alerts
*/
void clearAlerts();
/**
* Update the alarm status according to the alarm ID-status value
* 根据告警ID-状态值 更新告警状态
* @param status Alarm status to be modified
* @param ids Alarm ID List to be modified
*/
void editAlertStatus(Byte status, List<Long> ids);
/**
* Get alarm statistics information
* @return Alarm statistics information
*/
AlertSummary getAlertsSummary();
/**
* A third party reports an alarm
* @param alertReport The alarm information
*/
void addNewAlertReport(AlertReport alertReport);
/**
* Dynamic conditional query
* @param specification Query conditions
* @return search result
*/
List<Alert> getAlerts(Specification<Alert> specification);
}
@@ -1,85 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.service.impl;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hertzbeat.alert.dao.AlertConvergeDao;
import org.dromara.hertzbeat.alert.service.AlertConvergeService;
import org.dromara.hertzbeat.common.cache.CacheFactory;
import org.dromara.hertzbeat.common.cache.CommonCacheService;
import org.dromara.hertzbeat.common.constants.CommonConstants;
import org.dromara.hertzbeat.common.entity.alerter.AlertConverge;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Set;
/**
* implement for alert converge service
*
*/
@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class AlertConvergeServiceImpl implements AlertConvergeService {
@Autowired
private AlertConvergeDao alertConvergeDao;
@Override
public void validate(AlertConverge alertConverge, boolean isModify) throws IllegalArgumentException {
// todo
}
@Override
public void addAlertConverge(AlertConverge alertConverge) throws RuntimeException {
alertConvergeDao.save(alertConverge);
clearAlertConvergesCache();
}
@Override
public void modifyAlertConverge(AlertConverge alertConverge) throws RuntimeException {
alertConvergeDao.save(alertConverge);
clearAlertConvergesCache();
}
@Override
public AlertConverge getAlertConverge(long convergeId) throws RuntimeException {
return alertConvergeDao.findById(convergeId).orElse(null);
}
@Override
public void deleteAlertConverges(Set<Long> convergeIds) throws RuntimeException {
alertConvergeDao.deleteAlertConvergesByIdIn(convergeIds);
clearAlertConvergesCache();
}
@Override
public Page<AlertConverge> getAlertConverges(Specification<AlertConverge> specification, PageRequest pageRequest) {
return alertConvergeDao.findAll(specification, pageRequest);
}
private void clearAlertConvergesCache() {
CommonCacheService<String, Object> convergeCache = CacheFactory.getAlertConvergeCache();
convergeCache.remove(CommonConstants.CACHE_ALERT_CONVERGE);
}
}
@@ -1,160 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.service.impl;
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelTarget;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hertzbeat.alert.service.AlertDefineImExportService;
import org.dromara.hertzbeat.alert.service.AlertDefineService;
import org.dromara.hertzbeat.common.entity.alerter.AlertDefine;
import org.dromara.hertzbeat.common.entity.manager.TagItem;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.util.CollectionUtils;
import jakarta.annotation.Resource;
import java.io.InputStream;
import java.io.OutputStream;
import java.time.LocalDate;
import java.util.List;
import java.util.stream.Collectors;
/**
* Configuration Import Export
* 配置导入导出
*
*
* Created by a-little-fool on 2023/12/25
*/
@Slf4j
public abstract class AlertDefineAbstractImExportServiceImpl implements AlertDefineImExportService {
@Resource
@Lazy
private AlertDefineService alertDefineService;
@Override
public void importConfig(InputStream is) {
var formList = parseImport(is)
.stream()
.map(this::convert)
.collect(Collectors.toUnmodifiableList());
if (!CollectionUtils.isEmpty(formList)) {
formList.forEach(alertDefine -> {
alertDefineService.validate(alertDefine, false);
alertDefineService.addAlertDefine(alertDefine);
});
}
}
@Override
public void exportConfig(OutputStream os, List<Long> configList) {
var monitorList = configList.stream()
.map(it -> alertDefineService.getAlertDefine(it))
.map(this::convert)
.collect(Collectors.toUnmodifiableList());
writeOs(monitorList, os);
}
/**
* Parsing an input stream into a form
* 将输入流解析为表单
*
* @param is 输入流
* @return 表单
*/
abstract List<ExportAlertDefineDTO> parseImport(InputStream is);
/**
* Export Configuration to Output Stream
* 导出配置到输出流
*
* @param exportAlertDefineList 配置列表
* @param os 输出流
*/
abstract void writeOs(List<ExportAlertDefineDTO> exportAlertDefineList, OutputStream os);
private ExportAlertDefineDTO convert(AlertDefine alertDefine) {
var exportAlertDefine = new ExportAlertDefineDTO();
var alertDefineDTO = new AlertDefineDTO();
BeanUtils.copyProperties(alertDefine, alertDefineDTO);
exportAlertDefine.setAlertDefine(alertDefineDTO);
return exportAlertDefine;
}
private AlertDefine convert(ExportAlertDefineDTO exportAlertDefineDTO) {
var alertDefine = new AlertDefine();
var alertDefineDTO = exportAlertDefineDTO.getAlertDefine();
BeanUtils.copyProperties(alertDefineDTO, alertDefine);
return alertDefine;
}
protected String fileNamePrefix() {
return "hertzbeat_alertDefine_" + LocalDate.now();
}
/**
* Export data transfer objects for alert configurations
*/
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
@ExcelTarget(value = "ExportAlertDefineDTO")
protected static class ExportAlertDefineDTO {
@Excel(name = "AlertDefine")
private AlertDefineDTO alertDefine;
}
/**
* Data transfer object for alert configuration
*/
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
@ExcelTarget(value = "AlertDefineDTO")
protected static class AlertDefineDTO {
@Excel(name = "App")
private String app;
@Excel(name = "Metric")
private String metric;
@Excel(name = "Field")
private String field;
@Excel(name = "Preset")
private Boolean preset;
@Excel(name = "Expr")
private String expr;
@Excel(name = "Priority")
private Byte priority;
@Excel(name = "Times")
private Integer times;
@Excel(name = "Tags")
private List<TagItem> tags;
@Excel(name = "Enable")
private Boolean enable;
@Excel(name = "RecoverNotice")
private Boolean recoverNotice;
@Excel(name = "Template")
private String template;
}
}
@@ -1,275 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.service.impl;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.dromara.hertzbeat.common.entity.manager.TagItem;
import org.dromara.hertzbeat.common.util.JsonUtil;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;
/**
* Configure the import and export EXCEL format
* 配置导入导出 EXCEL格式
*
*
* Created by a-little-fool on 2023/12/25
*/
@Slf4j
@Service
public class AlertDefineExcelImExportServiceImpl extends AlertDefineAbstractImExportServiceImpl {
public static final String TYPE = "EXCEL";
public static final String FILE_SUFFIX = ".xlsx";
/**
* Export file type
* 导出文件类型
*
* @return 文件类型
*/
@Override
public String type() {
return TYPE;
}
/**
* Get Export File Name
* 获取导出文件名
*
* @return 文件名
*/
@Override
public String getFileName() {
return fileNamePrefix() + FILE_SUFFIX;
}
/**
* Parsing an input stream into a form
* 将输入流解析为表单
*
* @param is 输入流
* @return 表单
*/
@Override
List<ExportAlertDefineDTO> parseImport(InputStream is) {
try (Workbook workbook = WorkbookFactory.create(is)) {
Sheet sheet = workbook.getSheetAt(0);
List<ExportAlertDefineDTO> alertDefines = new ArrayList<>();
for (Row row : sheet) {
if (row.getRowNum() == 0) {
continue;
}
String app = getCellValueAsString(row.getCell(0));
if (StringUtils.hasText(app)) {
AlertDefineDTO alertDefineDTO = extractAlertDefineDataFromRow(row);
ExportAlertDefineDTO exportAlertDefineDTO = new ExportAlertDefineDTO();
exportAlertDefineDTO.setAlertDefine(alertDefineDTO);
alertDefines.add(exportAlertDefineDTO);
}
}
return alertDefines;
} catch (IOException e) {
throw new RuntimeException("Failed to parse alertDefine data", e);
}
}
private TagItem extractTagDataFromRow(Row row) {
String name = getCellValueAsString(row.getCell(7));
if (StringUtils.hasText(name)) {
TagItem tagItem = new TagItem();
tagItem.setName(name);
tagItem.setValue(getCellValueAsString(row.getCell(8)));
return tagItem;
}
return null;
}
private List<TagItem> extractTagDataFromRow(Cell cell) {
String jsonStr = getCellValueAsString(cell);
if (StringUtils.hasText(jsonStr)) {
return JsonUtil.fromJson(jsonStr, new TypeReference<List<TagItem>>() {});
}
return null;
}
private String getCellValueAsString(Cell cell) {
if (cell == null) {
return null;
}
switch (cell.getCellType()) {
case STRING:
return cell.getStringCellValue();
case NUMERIC:
return String.valueOf(cell.getNumericCellValue());
default:
return null;
}
}
private boolean getCellValueAsBoolean(Cell cell) {
if (cell == null) {
return false;
}
if (Objects.requireNonNull(cell.getCellType()) == CellType.BOOLEAN) {
return cell.getBooleanCellValue();
}
return false;
}
private Integer getCellValueAsInteger(Cell cell) {
if (cell == null) {
return null;
}
if (Objects.requireNonNull(cell.getCellType()) == CellType.NUMERIC) {
return (int) cell.getNumericCellValue();
}
return null;
}
private Byte getCellValueAsByte(Cell cell) {
if (cell == null) {
return null;
}
if (Objects.requireNonNull(cell.getCellType()) == CellType.NUMERIC) {
return (byte) cell.getNumericCellValue();
}
return null;
}
private AlertDefineDTO extractAlertDefineDataFromRow(Row row) {
AlertDefineDTO alertDefineDTO = new AlertDefineDTO();
alertDefineDTO.setApp(getCellValueAsString(row.getCell(0)));
alertDefineDTO.setMetric(getCellValueAsString(row.getCell(1)));
alertDefineDTO.setField(getCellValueAsString(row.getCell(2)));
alertDefineDTO.setPreset(getCellValueAsBoolean(row.getCell(3)));
alertDefineDTO.setExpr(getCellValueAsString(row.getCell(4)));
alertDefineDTO.setPriority(getCellValueAsByte(row.getCell(5)));
alertDefineDTO.setTimes(getCellValueAsInteger(row.getCell(6)));
alertDefineDTO.setTags(extractTagDataFromRow(row.getCell(7)));
alertDefineDTO.setEnable(getCellValueAsBoolean(row.getCell(8)));
alertDefineDTO.setRecoverNotice(getCellValueAsBoolean(row.getCell(9)));
alertDefineDTO.setTemplate(getCellValueAsString(row.getCell(10)));
return alertDefineDTO;
}
/**
* Export Configuration to Output Stream
* 导出配置到输出流
*
* @param exportAlertDefineList 配置列表
* @param os 输出流
*/
@Override
void writeOs(List<ExportAlertDefineDTO> exportAlertDefineList, OutputStream os) {
try {
Workbook workbook = WorkbookFactory.create(true);
String sheetName = "Export AlertDefine";
Sheet sheet = workbook.createSheet(sheetName);
sheet.setDefaultColumnWidth(20);
sheet.setColumnWidth(9, 40 * 256);
sheet.setColumnWidth(10, 40 * 256);
// 设置表头样式
CellStyle headerCellStyle = workbook.createCellStyle();
Font headerFont = workbook.createFont();
headerFont.setBold(true);
headerCellStyle.setFont(headerFont);
headerCellStyle.setAlignment(HorizontalAlignment.CENTER);
// 设置表格内容样式
CellStyle cellStyle = workbook.createCellStyle();
cellStyle.setAlignment(HorizontalAlignment.CENTER);
// 设置表头
String[] headers = {"app", "metric", "field", "preset", "expr", "priority", "times", "tags",
"enable", "recoverNotice", "template"};
Row headerRow = sheet.createRow(0);
for (int i = 0; i < headers.length; i++) {
Cell cell = headerRow.createCell(i);
cell.setCellValue(headers[i]);
cell.setCellStyle(headerCellStyle);
}
// 遍历阀值规则列表,每个阀值规则对象对应一行数据
int rowIndex = 1;
for (ExportAlertDefineDTO alertDefine : exportAlertDefineList) {
// 获取阀值规则信息
AlertDefineDTO alertDefineDTO = alertDefine.getAlertDefine();
// 阀值规则信息一行中
Row row = sheet.createRow(rowIndex++);
// 阀值规则信息只需要写一次
Cell appCell = row.createCell(0);
appCell.setCellValue(alertDefineDTO.getApp());
appCell.setCellStyle(cellStyle);
Cell metricCell = row.createCell(1);
metricCell.setCellValue(alertDefineDTO.getMetric());
metricCell.setCellStyle(cellStyle);
Cell fieldCell = row.createCell(2);
fieldCell.setCellValue(alertDefineDTO.getField());
fieldCell.setCellStyle(cellStyle);
Cell presetCell = row.createCell(3);
presetCell.setCellValue(alertDefineDTO.getPreset() != null
&& alertDefineDTO.getPreset());
presetCell.setCellStyle(cellStyle);
Cell exprCell = row.createCell(4);
exprCell.setCellValue(alertDefineDTO.getExpr());
exprCell.setCellStyle(cellStyle);
Cell priorityCell = row.createCell(5);
priorityCell.setCellValue(alertDefineDTO.getPriority());
priorityCell.setCellStyle(cellStyle);
Cell timesCell = row.createCell(6);
timesCell.setCellValue(alertDefineDTO.getTimes());
Cell tagCell = row.createCell(7);
// 获取标签信息
List<TagItem> tagList = alertDefineDTO.getTags();
String tagValue = tagList == null || tagList.size() == 0 ? "" : JsonUtil.toJson(tagList);
tagCell.setCellValue(tagValue);
tagCell.setCellStyle(cellStyle);
Cell enableCell = row.createCell(8);
enableCell.setCellValue(alertDefineDTO.getEnable() != null
&& alertDefineDTO.getEnable());
enableCell.setCellStyle(cellStyle);
Cell recoverNoticeCell = row.createCell(9);
recoverNoticeCell.setCellValue(alertDefineDTO.getRecoverNotice() != null
&& alertDefineDTO.getRecoverNotice());
recoverNoticeCell.setCellStyle(cellStyle);
Cell templateCell = row.createCell(10);
templateCell.setCellValue(alertDefineDTO.getTemplate());
recoverNoticeCell.setCellStyle(cellStyle);
}
workbook.write(os);
os.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
@@ -1,188 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.service.impl;
import com.googlecode.aviator.AviatorEvaluator;
import org.dromara.hertzbeat.alert.dao.AlertDefineBindDao;
import org.dromara.hertzbeat.alert.dao.AlertDefineDao;
import org.dromara.hertzbeat.alert.service.AlertDefineImExportService;
import org.dromara.hertzbeat.common.entity.alerter.AlertDefine;
import org.dromara.hertzbeat.common.entity.alerter.AlertDefineMonitorBind;
import org.dromara.hertzbeat.alert.service.AlertDefineService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import jakarta.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;
/**
* Alarm definition management interface implementation
*
*/
@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class AlertDefineServiceImpl implements AlertDefineService {
@Autowired
private AlertDefineDao alertDefineDao;
@Autowired
private AlertDefineBindDao alertDefineBindDao;
private final Map<String, AlertDefineImExportService> alertDefineImExportServiceMap = new HashMap<>();
public AlertDefineServiceImpl(List<AlertDefineImExportService> alertDefineImExportServiceList) {
alertDefineImExportServiceList.forEach(it -> alertDefineImExportServiceMap.put(it.type(), it));
}
@Override
public void validate(AlertDefine alertDefine, boolean isModify) throws IllegalArgumentException {
// todo
if (StringUtils.hasText(alertDefine.getExpr())) {
try {
AviatorEvaluator.compile(alertDefine.getExpr(), false);
} catch (Exception e) {
throw new IllegalArgumentException("alert expr error: " + e.getMessage());
}
}
}
@Override
public void addAlertDefine(AlertDefine alertDefine) throws RuntimeException {
alertDefineDao.save(alertDefine);
}
@Override
public void modifyAlertDefine(AlertDefine alertDefine) throws RuntimeException {
alertDefineDao.save(alertDefine);
}
@Override
public void deleteAlertDefine(long alertId) throws RuntimeException {
alertDefineDao.deleteById(alertId);
}
@Override
public AlertDefine getAlertDefine(long alertId) throws RuntimeException {
Optional<AlertDefine> optional = alertDefineDao.findById(alertId);
return optional.orElse(null);
}
@Override
public void deleteAlertDefines(Set<Long> alertIds) throws RuntimeException {
alertDefineDao.deleteAlertDefinesByIdIn(alertIds);
}
@Override
public Page<AlertDefine> getMonitorBindAlertDefines(Specification<AlertDefine> specification, PageRequest pageRequest) {
return alertDefineDao.findAll(specification, pageRequest);
}
@Override
public void applyBindAlertDefineMonitors(Long alertId, List<AlertDefineMonitorBind> alertDefineBinds) {
// todo checks whether the alarm definition and monitoring exist
// todo 校验此告警定义和监控是否存在
if (!alertDefineBindDao.existsById(alertId)){
alertDefineBindDao.deleteAlertDefineBindsByAlertDefineIdEquals(alertId);
}
// Delete all associations of this alarm
alertDefineBindDao.deleteAlertDefineBindsByAlertDefineIdEquals(alertId);
// Save the associated
alertDefineBindDao.saveAll(alertDefineBinds);
}
@Override
public Map<String, List<AlertDefine>> getMonitorBindAlertDefines(long monitorId, String app, String metrics) {
List<AlertDefine> defines = alertDefineDao.queryAlertDefinesByMonitor(monitorId, app, metrics);
List<AlertDefine> defaultDefines = alertDefineDao.queryAlertDefinesByAppAndMetricAndPresetTrueAndEnableTrue(app, metrics);
defines.addAll(defaultDefines);
Set<AlertDefine> defineSet = defines.stream().filter(item -> item.getField() != null).collect(Collectors.toSet());
// The alarm thresholds are defined in ascending order of the alarm severity from 0 to 3.
// The lower the number, the higher the alarm is. That is, the alarm is calculated from the highest alarm threshold
// 将告警阈值定义从告警级别0-3数字升序排序,数字越小告警基本越高,即从最高的告警阈值开始匹配计算
return defineSet.stream().sorted(Comparator.comparing(AlertDefine::getPriority))
.collect(Collectors.groupingBy(AlertDefine::getField));
}
@Override
public AlertDefine getMonitorBindAlertAvaDefine(long monitorId, String app, String metrics) {
List<AlertDefine> defines = alertDefineDao.queryAlertDefinesByMonitor(monitorId, app, metrics);
List<AlertDefine> defaultDefines = alertDefineDao.queryAlertDefinesByAppAndMetricAndPresetTrueAndEnableTrue(app, metrics);
defines.addAll(defaultDefines);
return defines.stream().findFirst().orElse(null);
}
@Override
public Page<AlertDefine> getAlertDefines(Specification<AlertDefine> specification, PageRequest pageRequest) {
return alertDefineDao.findAll(specification, pageRequest);
}
@Override
public List<AlertDefineMonitorBind> getBindAlertDefineMonitors(long alertDefineId) {
return alertDefineBindDao.getAlertDefineBindsByAlertDefineIdEquals(alertDefineId);
}
@Override
public void export(List<Long> ids, String type, HttpServletResponse res) throws Exception {
var imExportService = alertDefineImExportServiceMap.get(type);
if (imExportService == null) {
throw new IllegalArgumentException("not support export type: " + type);
}
var fileName = imExportService.getFileName();
res.setHeader("content-type", "application/octet-stream;charset=UTF-8");
res.setContentType("application/octet-stream;charset=UTF-8");
res.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8));
res.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
imExportService.exportConfig(res.getOutputStream(), ids);
}
@Override
public void importConfig(MultipartFile file) throws Exception {
var fileName = file.getOriginalFilename();
if (!StringUtils.hasText(fileName)) {
return;
}
var type = "";
if (fileName.toLowerCase().endsWith(AlertDefineJsonImExportServiceImpl.FILE_SUFFIX)) {
type = AlertDefineJsonImExportServiceImpl.TYPE;
}
if (fileName.toLowerCase().endsWith(AlertDefineExcelImExportServiceImpl.FILE_SUFFIX)) {
type = AlertDefineExcelImExportServiceImpl.TYPE;
}
if (fileName.toLowerCase().endsWith(AlertDefineYamlImExportServiceImpl.FILE_SUFFIX)) {
type = AlertDefineYamlImExportServiceImpl.TYPE;
}
if (!alertDefineImExportServiceMap.containsKey(type)) {
throw new RuntimeException("file " + fileName + " is not supported.");
}
var imExportService = alertDefineImExportServiceMap.get(type);
imExportService.importConfig(file.getInputStream());
}
}
@@ -1,73 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.service.impl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.List;
/**
* Configure the import and export Yaml format
* 配置导入导出 Yaml格式
*
*
* Created by a-little-fool on 2023/12/25
*/
@Slf4j
@Service
public class AlertDefineYamlImExportServiceImpl extends AlertDefineAbstractImExportServiceImpl {
public static final String TYPE = "YAML";
public static final String FILE_SUFFIX = ".yaml";
@Override
public String type() {
return TYPE;
}
@Override
public String getFileName() {
return fileNamePrefix() + FILE_SUFFIX;
}
@Override
List<ExportAlertDefineDTO> parseImport(InputStream is) {
Yaml yaml = new Yaml();
return yaml.load(is);
}
@Override
void writeOs(List<ExportAlertDefineDTO> exportAlertDefineList, OutputStream os) {
DumperOptions options = new DumperOptions();
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
options.setIndent(2);
options.setPrettyFlow(true);
Yaml yaml = new Yaml(options);
yaml.dump(exportAlertDefineList, new OutputStreamWriter(os, StandardCharsets.UTF_8));
}
}
@@ -1,173 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.service.impl;
import org.dromara.hertzbeat.alert.reduce.AlarmCommonReduce;
import org.dromara.hertzbeat.alert.dao.AlertDao;
import org.dromara.hertzbeat.alert.dto.AlertPriorityNum;
import org.dromara.hertzbeat.alert.dto.AlertSummary;
import org.dromara.hertzbeat.common.entity.alerter.Alert;
import org.dromara.hertzbeat.alert.service.AlertService;
import org.dromara.hertzbeat.common.entity.dto.AlertReport;
import org.dromara.hertzbeat.common.constants.CommonConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
/**
* Realization of Alarm Information Service
*
*/
@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class AlertServiceImpl implements AlertService {
@Autowired
private AlertDao alertDao;
@Autowired
private AlarmCommonReduce alarmCommonReduce;
@Override
public void addAlert(Alert alert) throws RuntimeException {
alertDao.save(alert);
}
@Override
public Page<Alert> getAlerts(Specification<Alert> specification, PageRequest pageRequest) {
return alertDao.findAll(specification, pageRequest);
}
@Override
public void deleteAlerts(HashSet<Long> ids) {
alertDao.deleteAlertsByIdIn(ids);
}
@Override
public void clearAlerts() {
alertDao.deleteAll();
}
@Override
public void editAlertStatus(Byte status, List<Long> ids) {
alertDao.updateAlertsStatus(status, ids);
}
@Override
public AlertSummary getAlertsSummary() {
AlertSummary alertSummary = new AlertSummary();
// Statistics on the alarm information in the alarm state
List<AlertPriorityNum> priorityNums = alertDao.findAlertPriorityNum();
if (priorityNums != null) {
for (AlertPriorityNum priorityNum : priorityNums) {
switch (priorityNum.getPriority()) {
case CommonConstants
.ALERT_PRIORITY_CODE_WARNING:
alertSummary.setPriorityWarningNum(priorityNum.getNum());
break;
case CommonConstants.ALERT_PRIORITY_CODE_CRITICAL:
alertSummary.setPriorityCriticalNum(priorityNum.getNum());
break;
case CommonConstants.ALERT_PRIORITY_CODE_EMERGENCY:
alertSummary.setPriorityEmergencyNum(priorityNum.getNum());
break;
default:
break;
}
}
}
long total = alertDao.count();
alertSummary.setTotal(total);
long dealNum = total - alertSummary.getPriorityCriticalNum()
- alertSummary.getPriorityEmergencyNum() - alertSummary.getPriorityWarningNum();
alertSummary.setDealNum(dealNum);
try {
if (total == 0) {
alertSummary.setRate(100);
} else {
float rate = BigDecimal.valueOf(100 * (float) dealNum / total)
.setScale(2, RoundingMode.HALF_UP)
.floatValue();
alertSummary.setRate(rate);
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return alertSummary;
}
@Override
public void addNewAlertReport(AlertReport alertReport) {
alarmCommonReduce.reduceAndSendAlarm(buildAlertData(alertReport));
}
@Override
public List<Alert> getAlerts(Specification<Alert> specification) {
return alertDao.findAll(specification);
}
/**
* The external alarm information is converted to Alert
* @param alertReport alarm body
* @return Alert entity
*/
private Alert buildAlertData(AlertReport alertReport){
Map<String, String> annotations = alertReport.getAnnotations();
StringBuilder sb = new StringBuilder();
if (alertReport.getContent() == null || alertReport.getContent().length() <= 0){
StringBuilder finalSb = sb;
annotations.forEach((k, v) -> {
finalSb.append(k).append(":").append(v).append("\n");
});
}else {
sb = new StringBuilder(alertReport.getContent());
}
LocalDateTime dateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(alertReport.getAlertTime()),
ZoneId.systemDefault());
return Alert.builder()
.content("Alert Center\n" + sb)
.priority(alertReport.getPriority().byteValue())
.status(CommonConstants.ALERT_STATUS_CODE_PENDING)
.tags(alertReport.getLabels())
.target(alertReport.getAlertName())
.triggerTimes(1)
.firstAlarmTime(alertReport.getAlertTime())
.lastAlarmTime(alertReport.getAlertTime())
.gmtCreate(dateTime)
.gmtUpdate(dateTime)
.build();
}
}
@@ -1,91 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.service.impl;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hertzbeat.alert.dao.AlertSilenceDao;
import org.dromara.hertzbeat.alert.service.AlertSilenceService;
import org.dromara.hertzbeat.common.cache.CacheFactory;
import org.dromara.hertzbeat.common.cache.CommonCacheService;
import org.dromara.hertzbeat.common.constants.CommonConstants;
import org.dromara.hertzbeat.common.entity.alerter.AlertSilence;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.Set;
/**
* management interface service implement for alert silence
*
*
*/
@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class AlertSilenceServiceImpl implements AlertSilenceService {
@Autowired
private AlertSilenceDao alertSilenceDao;
@Override
public void validate(AlertSilence alertSilence, boolean isModify) throws IllegalArgumentException {
// todo
// 兜底策略, 如果周期性情况下设置的告警静默选择日期为空, 视为全部勾选
if (alertSilence.getType() == 1 && alertSilence.getDays() == null) {
alertSilence.setDays(Arrays.asList((byte) 7, (byte) 1, (byte) 2, (byte) 3, (byte) 4, (byte) 5, (byte) 6));
}
}
@Override
public void addAlertSilence(AlertSilence alertSilence) throws RuntimeException {
alertSilenceDao.save(alertSilence);
clearAlertSilencesCache();
}
@Override
public void modifyAlertSilence(AlertSilence alertSilence) throws RuntimeException {
alertSilenceDao.save(alertSilence);
clearAlertSilencesCache();
}
@Override
public AlertSilence getAlertSilence(long silenceId) throws RuntimeException {
return alertSilenceDao.findById(silenceId).orElse(null);
}
@Override
public void deleteAlertSilences(Set<Long> silenceIds) throws RuntimeException {
alertSilenceDao.deleteAlertSilencesByIdIn(silenceIds);
clearAlertSilencesCache();
}
@Override
public Page<AlertSilence> getAlertSilences(Specification<AlertSilence> specification, PageRequest pageRequest) {
return alertSilenceDao.findAll(specification, pageRequest);
}
private void clearAlertSilencesCache() {
CommonCacheService<String, Object> silenceCache = CacheFactory.getAlertSilenceCache();
silenceCache.remove(CommonConstants.CACHE_ALERT_SILENCE);
}
}
@@ -1,65 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.util;
import lombok.extern.slf4j.Slf4j;
import java.text.ParseException;
import java.text.SimpleDateFormat;
/**
* date time common util
*/
@Slf4j
public class DateUtil {
private static final String[] DATE_FORMATS = {
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
"yyyy-MM-dd HH:mm:ss"};
/**
* convert date to timestamp
* @param date date
*/
public static Long getTimeStampFromSomeFormats(String date) {
SimpleDateFormat sdf;
for (String dateFormat : DATE_FORMATS) {
try {
sdf = new SimpleDateFormat(dateFormat);
return sdf.parse(date).getTime();
} catch (ParseException e) {
log.error(e.getMessage());
}
}
return null;
}
/**
* convert format data to timestamp
*/
public static Long getTimeStampFromFormat(String date, String format) {
SimpleDateFormat sdf = new SimpleDateFormat(format);
try {
return sdf.parse(date).getTime();
} catch (Exception e) {
log.error(e.getMessage());
}
return null;
}
}
@@ -1,17 +0,0 @@
# 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.
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.dromara.hertzbeat.alert.config.AlerterAutoConfiguration
@@ -1,175 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.controller;
import org.dromara.hertzbeat.alert.service.impl.AlertDefineServiceImpl;
import org.dromara.hertzbeat.common.entity.alerter.AlertDefine;
import org.dromara.hertzbeat.common.entity.alerter.AlertDefineMonitorBind;
import org.dromara.hertzbeat.common.entity.manager.Monitor;
import org.dromara.hertzbeat.common.constants.CommonConstants;
import org.dromara.hertzbeat.common.util.JsonUtil;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
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;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import java.util.Collections;
import java.util.List;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
* Test case for {@link AlertDefineController}
*
*
*/
@ExtendWith(MockitoExtension.class)
class AlertDefineControllerTest {
private MockMvc mockMvc;
private AlertDefine alertDefine;
private List<AlertDefineMonitorBind> alertDefineMonitorBinds;
@Mock
private AlertDefineServiceImpl alertDefineService;
@InjectMocks
private AlertDefineController alertDefineController;
@BeforeEach
void setUp() {
// standaloneSetup: 独立安装, 不集成web环境测试
this.mockMvc = MockMvcBuilders.standaloneSetup(alertDefineController).build();
this.alertDefine = AlertDefine.builder()
.id(1L)
.app("app")
.metric("test")
.field("test")
.preset(false)
.expr("1 > 0")
.priority((byte) 1)
.times(1)
.template("template")
.creator("tom")
.modifier("tom")
.build();
this.alertDefineMonitorBinds = Collections.singletonList(
AlertDefineMonitorBind.builder()
.id(1L)
.alertDefineId(this.alertDefine.getId())
.monitorId(1L)
.monitor(
Monitor.builder()
.id(1L)
.app("app")
.host("localhost")
.name("monitor")
.build()
)
.build()
);
}
@Test
void addNewAlertDefine() throws Exception {
// 模拟客户端往服务端发送请求
mockMvc.perform(MockMvcRequestBuilders.post("/api/alert/define")
.contentType(MediaType.APPLICATION_JSON)
.content(JsonUtil.toJson(this.alertDefine)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE))
.andReturn();
}
@Test
void modifyAlertDefine() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.put("/api/alert/define")
.contentType(MediaType.APPLICATION_JSON)
.content(JsonUtil.toJson(this.alertDefine)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE))
.andReturn();
}
@Test
void getAlertDefine() throws Exception {
// 模拟getAlertDefine返回数据
Mockito.when(alertDefineService.getAlertDefine(this.alertDefine.getId()))
.thenReturn(this.alertDefine);
mockMvc.perform(MockMvcRequestBuilders.get("/api/alert/define/" + this.alertDefine.getId())
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE))
.andExpect(jsonPath("$.data.id").value(alertDefine.getId()))
.andExpect(jsonPath("$.data.app").value(alertDefine.getApp()))
.andExpect(jsonPath("$.data.metric").value(alertDefine.getMetric()))
.andExpect(jsonPath("$.data.field").value(alertDefine.getField()))
.andExpect(jsonPath("$.data.expr").value(alertDefine.getExpr()))
.andExpect(jsonPath("$.data.template").value(alertDefine.getTemplate()))
.andExpect(jsonPath("$.data.gmtCreate").value(alertDefine.getGmtCreate()))
.andExpect(jsonPath("$.data.gmtUpdate").value(alertDefine.getGmtUpdate()))
.andReturn();
}
@Test
void deleteAlertDefine() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.delete("/api/alert/define/" + this.alertDefine.getId())
.contentType(MediaType.APPLICATION_JSON)
.content(JsonUtil.toJson(this.alertDefine)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE))
.andReturn();
}
@Test
void applyAlertDefineMonitorsBind() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/api/alert/define/" + this.alertDefine.getId() + "/monitors")
.contentType(MediaType.APPLICATION_JSON)
.content(JsonUtil.toJson(this.alertDefineMonitorBinds)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE))
.andReturn();
}
@Test
void getAlertDefineMonitorsBind() throws Exception {
Mockito.when(alertDefineService.getBindAlertDefineMonitors(this.alertDefine.getId()))
.thenReturn(this.alertDefineMonitorBinds);
mockMvc.perform(MockMvcRequestBuilders.get("/api/alert/define/" + this.alertDefine.getId() + "/monitors")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE))
.andExpect(jsonPath("$.data[0].id").value(alertDefineMonitorBinds.get(0).getId()))
.andExpect(jsonPath("$.data[0].monitor.id").value(alertDefineMonitorBinds.get(0).getMonitor().getId()))
.andReturn();
}
}
@@ -1,155 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.controller;
import org.dromara.hertzbeat.alert.service.AlertDefineService;
import org.dromara.hertzbeat.common.entity.alerter.AlertDefine;
import org.dromara.hertzbeat.common.constants.CommonConstants;
import org.dromara.hertzbeat.common.util.JsonUtil;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentMatcher;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
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;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
/**
* Test case for {@link AlertDefinesController}
* 测试mock处的数据是否正确,测试返回的数据格式是否正确
*
*
*/
@ExtendWith(MockitoExtension.class)
class AlertDefinesControllerTest {
private MockMvc mockMvc;
@InjectMocks
private AlertDefinesController alertDefinesController;
@Mock
AlertDefineService alertDefineService;
// 参数如下,为了避免默认值干扰,默认值已经被替换
List<Long> ids = Stream.of(6565463543L, 6565463544L).collect(Collectors.toList());
Byte priority = Byte.parseByte("1");
String sort = "gmtCreate";
String order = "asc";
Integer pageIndex = 1;
Integer pageSize = 7;
// 参数集合
Map<String, Object> content = new HashMap<String, Object>();
// 用于mock的对象
PageRequest pageRequest;
// 由于specification被使用于动态代理,所以无法mock
// 缺失的调试参数是ids、priority
// 缺失部分已经通过手动输出测试
@BeforeEach
void setUp() {
this.mockMvc = MockMvcBuilders.standaloneSetup(alertDefinesController).build();
// 配置测试内容
content.put("ids", ids);
content.put("priority", priority);
content.put("sort", sort);
content.put("order", order);
content.put("pageIndex", pageIndex);
content.put("pageSize", pageSize);
// mock的pageRequest
Sort sortExp = Sort.by(new Sort.Order(Sort.Direction.fromString(content.get("order").toString()), content.get("sort").toString()));
pageRequest = PageRequest.of(((Integer) content.get("pageIndex")).intValue(), ((Integer) content.get("pageSize")).intValue(), sortExp);
}
// @Test
// todo: fix this test
void getAlertDefines() throws Exception {
// 测试mock正确性
// 虽然无法mock对象,但是可以用class文件去存根
// Mockito.when(alertDefineService.getAlertDefines(Mockito.any(Specification.class), Mockito.argThat(new ArgumentMatcher<PageRequest>() {
// @Override
// public boolean matches(PageRequest pageRequestMidden) {
// // 看源码有三个方法要对比,分别是getPageNumber()、getPageSize()、getSort()
// if(pageRequestMidden.getPageSize() == pageRequest.getPageSize() &&
// pageRequestMidden.getPageNumber() == pageRequest.getPageNumber() &&
// pageRequestMidden.getSort().equals(pageRequest.getSort())) {
// return true;
// }
// return false;
// }
// }))).thenReturn(new PageImpl<AlertDefine>(new ArrayList<AlertDefine>()));
AlertDefine define = AlertDefine.builder().id(9L).app("linux").metric("disk").field("usage").expr("x").times(1).tags(new LinkedList<>()).build();
Mockito.when(alertDefineService.getAlertDefines(Mockito.any(), Mockito.any())).thenReturn(new PageImpl<>(Collections.singletonList(define)));
mockMvc.perform(MockMvcRequestBuilders.get(
"/api/alert/defines")
.param("ids", ids.toString().substring(1, ids.toString().length() - 1))
.param("priority", priority.toString())
.param("sort", sort)
.param("order", order)
.param("pageIndex", pageIndex.toString())
.param("pageSize", pageSize.toString()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE))
.andExpect(jsonPath("$.data.content").value(new ArrayList<>()))
.andExpect(jsonPath("$.data.pageable").value("INSTANCE"))
.andExpect(jsonPath("$.data.totalPages").value(1))
.andExpect(jsonPath("$.data.totalElements").value(0))
.andExpect(jsonPath("$.data.last").value(true))
.andExpect(jsonPath("$.data.number").value(0))
.andExpect(jsonPath("$.data.size").value(0))
.andExpect(jsonPath("$.data.first").value(true))
.andExpect(jsonPath("$.data.numberOfElements").value(0))
.andExpect(jsonPath("$.data.empty").value(true))
.andExpect(jsonPath("$.data.sort.empty").value(true))
.andExpect(jsonPath("$.data.sort.sorted").value(false))
.andExpect(jsonPath("$.data.sort.unsorted").value(true))
.andReturn();
}
@Test
void deleteAlertDefines() throws Exception {
this.mockMvc.perform(MockMvcRequestBuilders.delete("/api/alert/defines")
.contentType(MediaType.APPLICATION_JSON)
.content(JsonUtil.toJson(ids)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE))
.andReturn();
}
}
@@ -1,126 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.controller;
import org.dromara.hertzbeat.alert.dto.GeneralCloudAlertReport;
import org.dromara.hertzbeat.alert.dto.TenCloudAlertReport;
import org.dromara.hertzbeat.alert.service.AlertService;
import org.dromara.hertzbeat.common.constants.CommonConstants;
import org.dromara.hertzbeat.common.util.JsonUtil;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
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;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
* unit test for {@link AlertReportController }
*
*/
@ExtendWith(MockitoExtension.class)
class AlertReportControllerTest {
private MockMvc mockMvc;
@Mock
private AlertService alertService;
@InjectMocks
private AlertReportController alertReportController;
@BeforeEach
void setUp() {
this.mockMvc = MockMvcBuilders.standaloneSetup(alertReportController).build();
}
@Test
void addNewAlertReportTencent() throws Exception {
TenCloudAlertReport.Dimensions dimensions = new TenCloudAlertReport.Dimensions();
dimensions.setUnInstanceId("3333");
TenCloudAlertReport.AlarmObjInfo alarmObjInfo = new TenCloudAlertReport.AlarmObjInfo();
alarmObjInfo.setRegion("广东");
alarmObjInfo.setNamespace("广州节点1");
alarmObjInfo.setAppId("1111");
alarmObjInfo.setUin("2222");
alarmObjInfo.setDimensions(dimensions);
TenCloudAlertReport.Conditions conditions = new TenCloudAlertReport.Conditions();
conditions.setMetricName("xx");
conditions.setMetricShowName("xxx");
conditions.setCalcType("a");
conditions.setCalcValue("aa");
conditions.setCalcUnit("aaa");
conditions.setCurrentValue("b");
conditions.setCalcUnit("bb");
conditions.setProductName("guangzhou");
conditions.setProductShowName("广州");
conditions.setEventName("CVS");
conditions.setEventShowName("内核异常");
TenCloudAlertReport.AlarmPolicyInfo alarmPolicyInfo = new TenCloudAlertReport.AlarmPolicyInfo();
alarmPolicyInfo.setPolicyTypeCname("x");
alarmPolicyInfo.setPolicyName("测试1");
alarmPolicyInfo.setConditions(conditions);
TenCloudAlertReport report = TenCloudAlertReport.builder()
.sessionId("123")
.alarmStatus("1")
.alarmType("event")
.durationTime(2)
.firstOccurTime("2023-08-14 11:11:11")
.alarmObjInfo(alarmObjInfo)
.alarmPolicyInfo(alarmPolicyInfo)
.build();
mockMvc.perform(
MockMvcRequestBuilders
.post("/api/alerts/report/tencloud")
.contentType(MediaType.APPLICATION_JSON)
.content(JsonUtil.toJson(report))
)
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE))
.andExpect(content().json("{\"data\":null,\"msg\":\"Add report success\",\"code\":0}"))
.andReturn();
}
@Test
void addNewAlertReport() throws Exception {
GeneralCloudAlertReport generalCloudAlertReport = new GeneralCloudAlertReport();
generalCloudAlertReport.setAlertDateTime("2023-02-22T07:27:15.404000000Z");
mockMvc.perform(MockMvcRequestBuilders
.post("/api/alerts/report")
.contentType(MediaType.APPLICATION_JSON)
.content(JsonUtil.toJson(generalCloudAlertReport))
)
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE))
.andExpect(content().json("{\"data\":null,\"msg\":\"Add report success\",\"code\":0}"))
.andReturn();
}
}
@@ -1,171 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.controller;
import org.dromara.hertzbeat.alert.dto.AlertSummary;
import org.dromara.hertzbeat.alert.service.AlertService;
import org.dromara.hertzbeat.common.entity.alerter.Alert;
import org.dromara.hertzbeat.common.entity.dto.AlertReport;
import org.dromara.hertzbeat.common.constants.CommonConstants;
import org.dromara.hertzbeat.common.util.JsonUtil;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
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;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.LongStream;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
/**
* Test case for {@link AlertsController}
*/
@ExtendWith(MockitoExtension.class)
class AlertsControllerTest {
private MockMvc mockMvc;
@InjectMocks
private AlertsController alertsController;
@Mock
private AlertService alertService;
private List<Long> ids;
@BeforeEach
void setUp() {
this.mockMvc = MockMvcBuilders.standaloneSetup(alertsController).build();
ids = LongStream.rangeClosed(1, 10).boxed().collect(Collectors.toList());
}
// @Test
// todo: fix this test
void getAlerts() throws Exception {
//定义要用到的测试值
String sortField = "id";
String orderType = "asc";
int pageIndex = 0;
int pageSize = 10;
PageRequest pageRequest = PageRequest.of(pageIndex, pageSize, Sort.by(new Sort.Order(Sort.Direction.fromString(orderType), sortField)));
Page<Alert> alertPage = new PageImpl<>(Collections.singletonList(Alert.builder().build()));
//打桩
Mockito.when(
alertService.getAlerts(
Mockito.any(Specification.class)
, Mockito.argThat(
argument ->
argument.getPageNumber() == pageRequest.getPageNumber()
&& argument.getPageSize() == pageRequest.getPageSize()
&& argument.getSort().equals(pageRequest.getSort())
)
)
)
.thenReturn(alertPage);
mockMvc.perform(
MockMvcRequestBuilders
.get("/api/alerts")
.param("ids", ids.stream().map(String::valueOf).collect(Collectors.joining(",")))
.param("monitorId", "1")
.param("priority", "1")
.param("status", "1")
.param("content", "test")
.param("sort", sortField)
.param("order", orderType)
.param("pageIndex", String.valueOf(pageIndex))
.param("pageSize", String.valueOf(pageSize))
)
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE))
.andExpect(jsonPath("$.data.content.length()").value(1))
.andReturn();
}
@Test
void deleteAlerts() throws Exception {
mockMvc.perform(
MockMvcRequestBuilders
.delete("/api/alerts")
.param("ids", ids.stream().map(String::valueOf).collect(Collectors.joining(",")))
)
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE))
.andExpect(content().json("{\"data\":null,\"msg\":null,\"code\":0}"))
.andReturn();
}
@Test
void clearAllAlerts() throws Exception {
mockMvc.perform(
MockMvcRequestBuilders
.delete("/api/alerts/clear")
)
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE))
.andExpect(content().json("{\"data\":null,\"msg\":null,\"code\":0}"))
.andReturn();
}
@Test
void applyAlertDefinesStatus() throws Exception {
mockMvc.perform(
MockMvcRequestBuilders
.put("/api/alerts/status/1")
.param("ids", ids.stream().map(String::valueOf).collect(Collectors.joining(",")))
)
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE))
.andExpect(content().json("{\"data\":null,\"msg\":null,\"code\":0}"))
.andReturn();
}
@Test
void getAlertsSummary() throws Exception {
//打桩
Mockito.when(alertService.getAlertsSummary()).thenReturn(new AlertSummary());
mockMvc.perform(
MockMvcRequestBuilders
.get("/api/alerts/summary")
)
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE))
.andExpect(content().json("{\"data\":{\"total\":0,\"dealNum\":0,\"rate\":0.0,\"priorityWarningNum\":0,\"priorityCriticalNum\":0,\"priorityEmergencyNum\":0},\"msg\":null,\"code\":0}"))
.andReturn();
}
}
@@ -1,181 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.service;
import org.dromara.hertzbeat.alert.dao.AlertDefineBindDao;
import org.dromara.hertzbeat.alert.dao.AlertDefineDao;
import org.dromara.hertzbeat.alert.service.impl.AlertDefineServiceImpl;
import org.dromara.hertzbeat.common.entity.alerter.AlertDefine;
import org.dromara.hertzbeat.common.entity.alerter.AlertDefineMonitorBind;
import org.dromara.hertzbeat.common.entity.manager.Monitor;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.*;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.test.util.ReflectionTestUtils;
import java.util.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
/**
* Test case for {@link AlertDefineService}
*/
@ExtendWith(MockitoExtension.class)
class AlertDefineServiceTest {
private AlertDefine alertDefine;
private List<AlertDefineMonitorBind> alertDefineMonitorBinds;
@Mock
private AlertDefineDao alertDefineDao;
@Mock
private AlertDefineBindDao alertDefineBindDao;
@Mock
private List<AlertDefineImExportService> alertDefineImExportServiceList;
@InjectMocks
private AlertDefineServiceImpl alertDefineService;
@BeforeEach
void setUp() {
ReflectionTestUtils.setField(this.alertDefineService, "alertDefineDao", alertDefineDao);
ReflectionTestUtils.setField(this.alertDefineService, "alertDefineBindDao", alertDefineBindDao);
this.alertDefine = AlertDefine.builder()
.id(1L)
.app("app")
.metric("test")
.field("test")
.preset(false)
.expr("1 > 0")
.priority((byte) 1)
.times(1)
.template("template")
.creator("tom")
.modifier("tom")
.build();
this.alertDefineMonitorBinds = Collections.singletonList(
AlertDefineMonitorBind.builder()
.id(1L)
.alertDefineId(this.alertDefine.getId())
.monitorId(1L)
.monitor(
Monitor.builder()
.id(1L)
.app("app")
.host("localhost")
.name("monitor")
.build()
)
.build()
);
}
@Test
void validate() {
assertDoesNotThrow(() -> alertDefineService.validate(alertDefine, true));
assertDoesNotThrow(() -> alertDefineService.validate(alertDefine, false));
}
@Test
void addAlertDefine() {
assertDoesNotThrow(() -> alertDefineService.addAlertDefine(alertDefine));
when(alertDefineDao.save(alertDefine)).thenThrow(new RuntimeException());
assertThrows(RuntimeException.class, () -> alertDefineService.addAlertDefine(alertDefine));
}
@Test
void modifyAlertDefine() {
AlertDefine alertDefine = AlertDefine.builder().id(1L).build();
when(alertDefineDao.save(alertDefine)).thenReturn(alertDefine);
assertDoesNotThrow(() -> alertDefineService.modifyAlertDefine(alertDefine));
reset();
when(alertDefineDao.save(alertDefine)).thenThrow(new RuntimeException());
assertThrows(RuntimeException.class, () -> alertDefineService.modifyAlertDefine(alertDefine));
}
@Test
void deleteAlertDefine() {
long id = 1L;
doNothing().doThrow(new RuntimeException()).when(alertDefineDao).deleteById(id);
assertDoesNotThrow(() -> alertDefineService.deleteAlertDefine(id));
assertThrows(RuntimeException.class, () -> alertDefineService.deleteAlertDefine(id));
}
@Test
void getAlertDefine() {
long id = 1L;
AlertDefine alertDefine = AlertDefine.builder().id(id).build();
when(alertDefineDao.findById(id)).thenReturn(Optional.of(alertDefine));
assertDoesNotThrow(() -> alertDefineService.getAlertDefine(id));
}
@Test
void deleteAlertDefines() {
doNothing().when(alertDefineDao).deleteAlertDefinesByIdIn(anySet());
assertDoesNotThrow(() -> alertDefineService.deleteAlertDefines(new HashSet<>(1)));
}
@Test
void getMonitorBindAlertDefines() {
Specification<AlertDefine> specification = mock(Specification.class);
when(alertDefineDao.findAll(specification, PageRequest.of(1, 1))).thenReturn(Page.empty());
assertNotNull(alertDefineService.getMonitorBindAlertDefines(specification, PageRequest.of(1, 1)));
}
@Test
void applyBindAlertDefineMonitors() {
long id = 1L;
doNothing().when(alertDefineBindDao).deleteAlertDefineBindsByAlertDefineIdEquals(id);
when(alertDefineBindDao.saveAll(alertDefineMonitorBinds)).thenReturn(alertDefineMonitorBinds);
assertDoesNotThrow(() -> alertDefineService.applyBindAlertDefineMonitors(id, alertDefineMonitorBinds));
}
@Test
void testGetMonitorBindAlertDefines() {
List<AlertDefine> alertDefineList = new ArrayList<>();
alertDefineList.add(this.alertDefine);
when(alertDefineDao.queryAlertDefinesByMonitor(1L, "app", "test")).thenReturn(alertDefineList);
when(alertDefineDao.queryAlertDefinesByAppAndMetricAndPresetTrueAndEnableTrue("app", "test")).thenReturn(alertDefineList);
assertNotNull(alertDefineService.getMonitorBindAlertDefines(1L, "app", "test"));
}
@Test
void getAlertDefines() {
Specification<AlertDefine> specification = mock(Specification.class);
when(alertDefineDao.findAll(specification, PageRequest.of(1, 1))).thenReturn(Page.empty());
assertNotNull(alertDefineService.getAlertDefines(specification, PageRequest.of(1, 1)));
}
@Test
void getBindAlertDefineMonitors() {
long id = 1L;
when(alertDefineBindDao.getAlertDefineBindsByAlertDefineIdEquals(id)).thenReturn(alertDefineMonitorBinds);
assertDoesNotThrow(() -> alertDefineService.getBindAlertDefineMonitors(id));
}
}
@@ -1,59 +0,0 @@
/*
* 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.dromara.hertzbeat.alert.service;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
/**
* Test case for {@link AlertService}
*/
class AlertServiceTest {
@BeforeEach
void setUp() {
}
@Test
void addAlert() {
}
@Test
void getAlerts() {
}
@Test
void deleteAlerts() {
}
@Test
void clearAlerts() {
}
@Test
void editAlertStatus() {
}
@Test
void getAlertsSummary() {
}
@Test
void addNewAlertReport() {
}
}
-56
View File
@@ -1,56 +0,0 @@
### Collector
Collect Metrics Data from peer-to-peer machine by common protocols.
使用通用协议远程采集获取对端指标数据。
support protocolshttp/https, jdbc, ssh, telnet, jmx, ping, prometheus...
## Supported
> We define all monitoring collection types such as `mysql`, `jvm`, and `k8s` as `YML` monitoring templates, allowing users to import them to support corresponding types of monitoring.
> Welcome everyone to contribute your customized general monitoring type YML template during use.
- [Website](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-website.yml), [Port Telnet](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-port.yml),
[Http Api](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-api.yml), [Ping Connect](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-ping.yml),
[Jvm](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-jvm.yml), [SiteMap](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-fullsite.yml),
[Ssl Certificate](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-ssl_cert.yml), [SpringBoot2](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-springboot2.yml),
[FTP Server](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-ftp.yml), [SpringBoot3](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-springboot3.yml)
- [Mysql](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-mysql.yml), [PostgreSQL](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-postgresql.yml),
[MariaDB](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-mariadb.yml), [Redis](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-redis.yml),
[ElasticSearch](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-elasticsearch.yml), [SqlServer](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-sqlserver.yml),
[Oracle](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-oracle.yml), [MongoDB](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-mongodb.yml),
[DM](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-dm.yml), [OpenGauss](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-opengauss.yml),
[ClickHouse](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-clickhouse.yml), [IoTDB](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-iotdb.yml),
[Redis Cluster](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-redis_cluster.yml), [Redis Sentinel](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-redis_sentinel.yml)
- [Linux](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-linux.yml), [Ubuntu](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-ubuntu.yml),
[CentOS](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-centos.yml), [Windows](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-windows.yml),
[EulerOS](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-euleros.yml), [Fedora CoreOS](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-coreos.yml),
[OpenSUSE](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-opensuse.yml), [Rocky Linux](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-rockylinux.yml),
[Red Hat](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-redhat.yml), [FreeBSD](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-freebsd.yml),
[AlmaLinux](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-almalinux.yml), [Debian Linux](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-debian.yml)
- [Tomcat](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-tomcat.yml), [Nacos](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-nacos.yml),
[Zookeeper](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-zookeeper.yml), [RabbitMQ](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-rabbitmq.yml),
[Flink](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-flink.yml), [Kafka](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-kafka.yml),
[ShenYu](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-shenyu.yml), [DynamicTp](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-dynamic_tp.yml),
[Jetty](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-jetty.yml), [ActiveMQ](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-activemq.yml)
- [Kubernetes](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-kubernetes.yml), [Docker](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-docker.yml)
- [CiscoSwitch](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-cisco_switch.yml), [HpeSwitch](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-hpe_switch.yml),
[HuaweiSwitch](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-huawei_switch.yml), [TpLinkSwitch](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-tplink_switch.yml),
[H3cSwitch](https://raw.githubusercontent.com/dromara/hertzbeat/master/manager/src/main/resources/define/app-h3c_switch.yml)
- And More Your Custom Template.
- Notified Support `Discord` `Slack` `Telegram` `Email` `DingDing` `WeChat` `FeiShu` `Webhook` `SMS`.
## Build HertzBeat Collector Install Package
1. Execute command in root
```mvn clean install```
2. Execute command in collector module
```shell
cd collector
mvn clean package -Pcluster
```
-375
View File
@@ -1,375 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<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">
<parent>
<artifactId>hertzbeat</artifactId>
<groupId>org.dromara.hertzbeat</groupId>
<version>2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>hertzbeat-collector</artifactId>
<name>${project.artifactId}</name>
<properties>
<java.version>17</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<maven-jar-plugin.version>3.2.0</maven-jar-plugin.version>
<maven-assembly-plugin.version>3.3.0</maven-assembly-plugin.version>
</properties>
<dependencies>
<!-- spring -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- common -->
<dependency>
<groupId>org.dromara.hertzbeat</groupId>
<artifactId>hertzbeat-common</artifactId>
</dependency>
<!-- remoting -->
<dependency>
<groupId>org.dromara.hertzbeat</groupId>
<artifactId>hertzbeat-remoting</artifactId>
</dependency>
<!-- validation -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- run sql script-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.23</version>
</dependency>
<!-- kafka -->
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
</dependency>
<!-- http -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<!--network-->
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.8.0</version>
</dependency>
<!--json path parser-->
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
</dependency>
<!-- lru hashmap -->
<dependency>
<groupId>com.googlecode.concurrentlinkedhashmap</groupId>
<artifactId>concurrentlinkedhashmap-lru</artifactId>
<version>1.4.2</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<!--collect-->
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>provided</scope>
</dependency>
<!-- clickhouse -->
<dependency>
<groupId>com.clickhouse</groupId>
<artifactId>clickhouse-jdbc</artifactId>
</dependency>
<!-- dm -->
<dependency>
<groupId>com.dameng</groupId>
<artifactId>DmJdbcDriver18</artifactId>
</dependency>
<!-- postgresql -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<!-- linux ssh -->
<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-core</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>net.i2p.crypto</groupId>
<artifactId>eddsa</artifactId>
<version>0.3.0</version>
</dependency>
<!-- sql server -->
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
</dependency>
<!-- oracle -->
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.oracle.database.nls</groupId>
<artifactId>orai18n</artifactId>
<scope>provided</scope>
</dependency>
<!--redis-->
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</dependency>
<!-- mongodb -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
</dependency>
<!--snmp-->
<dependency>
<groupId>org.snmp4j</groupId>
<artifactId>snmp4j</artifactId>
<version>3.6.7</version>
</dependency>
<!-- rocketmq -->
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-tools</artifactId>
<version>4.9.4</version>
</dependency>
<!--dns-->
<dependency>
<groupId>dnsjava</groupId>
<artifactId>dnsjava</artifactId>
<version>3.5.2</version>
</dependency>
<!-- consul -->
<dependency>
<groupId>com.ecwid.consul</groupId>
<artifactId>consul-api</artifactId>
<version>1.4.5</version>
</dependency>
<!-- nacos -->
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>2.2.1</version>
</dependency>
</dependencies>
<profiles>
<profile>
<id>inner</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<finalName>hertzbeat-collector</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>${maven-jar-plugin.version}</version>
<executions>
<execution>
<phase>package</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>cluster</id>
<build>
<finalName>hertzbeat-collector</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>*.yml</include>
<include>*.properties</include>
<include>*.xml</include>
<include>banner.txt</include>
<include>META-INF/**</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>${maven-jar-plugin.version}</version>
<configuration>
<classesDirectory>target/classes/</classesDirectory>
<archive>
<!--生成的jar包不包含maven描述相关文件-->
<addMavenDescriptor>false</addMavenDescriptor>
<manifest>
<!--项目启动类-->
<mainClass>org.dromara.hertzbeat.collector.Collector</mainClass>
<useUniqueVersions>false</useUniqueVersions>
<!--第三方JAR加入类构建的路径maven-dependency-plugin-->
<addClasspath>true</addClasspath>
<!--外部依赖jar包的位置-->
<classpathPrefix>lib/</classpathPrefix>
</manifest>
<manifestEntries>
<Class-Path>. config</Class-Path>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>${maven-assembly-plugin.version}</version>
<executions>
<execution>
<id>without-jdk</id>
<!--绑定的maven操作-->
<phase>package</phase>
<!--运行一次-->
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>../script/assembly/collector/assembly.xml</descriptor>
</descriptors>
</configuration>
</execution>
<execution>
<id>make-macos-arm64</id>
<!--绑定的maven操作-->
<phase>package</phase>
<!--运行一次-->
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>../script/assembly/collector/assembly-macos-arm64.xml</descriptor>
</descriptors>
</configuration>
</execution>
<execution>
<id>make-macos-amd64</id>
<!--绑定的maven操作-->
<phase>package</phase>
<!--运行一次-->
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>../script/assembly/collector/assembly-macos-amd64.xml</descriptor>
</descriptors>
</configuration>
</execution>
<execution>
<id>make-linux-arm64</id>
<!--绑定的maven操作-->
<phase>package</phase>
<!--运行一次-->
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>../script/assembly/collector/assembly-linux-arm64.xml</descriptor>
</descriptors>
</configuration>
</execution>
<execution>
<id>make-linux-amd64</id>
<!--绑定的maven操作-->
<phase>package</phase>
<!--运行一次-->
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>../script/assembly/collector/assembly-linux-amd64.xml</descriptor>
</descriptors>
</configuration>
</execution>
<execution>
<id>make-windows-64</id>
<!--绑定的maven操作-->
<phase>package</phase>
<!--运行一次-->
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>../script/assembly/collector/assembly-windows-64.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
@@ -1,43 +0,0 @@
/*
* 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.dromara.hertzbeat.collector;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import jakarta.annotation.PostConstruct;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.context.annotation.ComponentScan;
/**
* collector startup
*
*/
@ComponentScan(basePackages = {"org.dromara.hertzbeat"})
@ConfigurationPropertiesScan(basePackages = {"org.dromara.hertzbeat"})
@SpringBootApplication
public class Collector {
public static void main(String[] args) {
SpringApplication.run(Collector.class, args);
}
@PostConstruct
public void init() {
System.setProperty("jdk.jndi.object.factoriesFilter", "!com.zaxxer.hikari.HikariJNDIFactory");
}
}
@@ -1,44 +0,0 @@
/*
* 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.dromara.hertzbeat.collector.collect;
import org.dromara.hertzbeat.common.entity.job.Metrics;
import org.dromara.hertzbeat.common.entity.message.CollectRep;
/**
* Specific metrics collection implementation abstract class
*
*/
public abstract class AbstractCollect {
/**
* Real acquisition implementation interface
* @param builder response builder
* @param monitorId monitor id
* @param app monitor type
* @param metrics metric configuration
*/
public abstract void collect(CollectRep.MetricsData.Builder builder, long monitorId, String app, Metrics metrics);
/**
* the protocol this collect instance support
* @return protocol str
*/
public abstract String supportProtocol();
}
@@ -1,30 +0,0 @@
/*
* 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.dromara.hertzbeat.collector.collect.common.cache;
/**
* resource in cache remove callback
*
*/
public interface CacheCloseable {
/**
* when the resource in cache want to be removed, callback this
*/
void close();
}
@@ -1,49 +0,0 @@
/*
* 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.dromara.hertzbeat.collector.collect.common.cache;
import lombok.Builder;
import lombok.Data;
import java.util.Objects;
/**
* resource identifier in cache
*
*/
@Data
@Builder
public class CacheIdentifier {
private String ip;
private String port;
private String username;
private String password;
@Override
public String toString() {
return "CacheIdentifier {" +
"ip='" + ip + '\'' +
", port='" + port + '\'' +
", username+password=>hash='" + Objects.hash(username, password) + '\'' +
'}';
}
}
@@ -1,234 +0,0 @@
/*
* 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.dromara.hertzbeat.collector.collect.common.cache;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.*;
/**
* lru common resource cache for client-server connection
*
*
*/
@Slf4j
public class ConnectionCommonCache {
/**
* default cache time 200s
*/
private static final long DEFAULT_CACHE_TIMEOUT = 200 * 1000L;
/**
* default max cache num
*/
private static final int DEFAULT_MAX_CAPACITY = 10000;
/**
* cacheTime length
*/
private static final int CACHE_TIME_LENGTH = 2;
/**
* cache timeout map
*/
private Map<Object, Long[]> timeoutMap;
/**
* object cache
*/
private ConcurrentLinkedHashMap<Object, Object> cacheMap;
/**
* the executor who clean cache when timeout
*/
private ThreadPoolExecutor timeoutCleanerExecutor;
private ConnectionCommonCache() {
init();
}
private void init() {
cacheMap = new ConcurrentLinkedHashMap
.Builder<>()
.maximumWeightedCapacity(DEFAULT_MAX_CAPACITY)
.listener((key, value) -> {
timeoutMap.remove(key);
if (value instanceof CacheCloseable) {
((CacheCloseable) value).close();
}
log.info("connection common cache discard key: {}, value: {}.", key, value);
}).build();
timeoutMap = new ConcurrentHashMap<>(DEFAULT_MAX_CAPACITY >> 6);
// last-first-coverage algorithm, run the first and last thread, discard mid
timeoutCleanerExecutor = new ThreadPoolExecutor(1, 1, 1, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(1),
r -> new Thread(r, "connection-cache-timeout-cleaner"),
new ThreadPoolExecutor.DiscardOldestPolicy());
// init monitor available detector cyc task
ThreadFactory threadFactory = new ThreadFactoryBuilder()
.setNameFormat("connection-cache-ava-detector-%d")
.setDaemon(true)
.build();
ScheduledThreadPoolExecutor scheduledExecutor = new ScheduledThreadPoolExecutor(1, threadFactory);
scheduledExecutor.scheduleWithFixedDelay(this::detectCacheAvailable, 2, 20, TimeUnit.MINUTES);
}
/**
* detect all cache available, cleanup not ava connection
*/
private void detectCacheAvailable() {
try {
cacheMap.forEach((key, value) -> {
Long[] cacheTime = timeoutMap.get(key);
long currentTime = System.currentTimeMillis();
if (cacheTime == null || cacheTime.length != CACHE_TIME_LENGTH
|| cacheTime[0] + cacheTime[1] < currentTime) {
cacheMap.remove(key);
timeoutMap.remove(key);
if (value instanceof CacheCloseable) {
((CacheCloseable) value).close();
}
}
});
} catch (Exception e) {
log.error("connection common cache detect cache available error: {}.", e.getMessage(), e);
}
}
/**
* clean timeout cache
*/
private void cleanTimeoutCache() {
try {
cacheMap.forEach((key, value) -> {
// index 0 is startTime, 1 is timeDiff
Long[] cacheTime = timeoutMap.get(key);
long currentTime = System.currentTimeMillis();
if (cacheTime == null || cacheTime.length != CACHE_TIME_LENGTH) {
timeoutMap.put(key, new Long[]{currentTime, DEFAULT_CACHE_TIMEOUT});
} else if (cacheTime[0] + cacheTime[1] < currentTime) {
// timeout, remove this object cache
log.warn("[connection common cache] clean the timeout cache, key {}", key);
timeoutMap.remove(key);
cacheMap.remove(key);
if (value instanceof CacheCloseable) {
log.warn("[connection common cache] close the timeout cache, key {}", key);
((CacheCloseable) value).close();
}
}
});
Thread.sleep(20 * 1000);
} catch (Exception e) {
log.error("[connection common cache] clean timeout cache error: {}.", e.getMessage(), e);
}
}
/**
* add update cache
*
* @param key cache key
* @param value cache value
* @param timeDiff cache time millis
*/
public void addCache(Object key, Object value, Long timeDiff) {
removeCache(key);
if (timeDiff == null) {
timeDiff = DEFAULT_CACHE_TIMEOUT;
}
cacheMap.put(key, value);
timeoutMap.put(key, new Long[]{System.currentTimeMillis(), timeDiff});
timeoutCleanerExecutor.execute(this::cleanTimeoutCache);
}
/**
* add update cache
*
* @param key cache key
* @param value cache value
*/
public void addCache(Object key, Object value) {
addCache(key, value, DEFAULT_CACHE_TIMEOUT);
}
/**
* get cache by key
*
* @param key cache key
* @param refreshCache is refresh cache
* @return cache object
*/
public Optional<Object> getCache(Object key, boolean refreshCache) {
Long[] cacheTime = timeoutMap.get(key);
if (cacheTime == null || cacheTime.length != CACHE_TIME_LENGTH) {
log.info("[connection common cache] not hit the cache, key {}.", key);
return Optional.empty();
}
if (cacheTime[0] + cacheTime[1] < System.currentTimeMillis()) {
log.warn("[connection common cache] is timeout, remove it, key {}.", key);
timeoutMap.remove(key);
cacheMap.remove(key);
return Optional.empty();
}
Object value = cacheMap.get(key);
if (value == null) {
log.error("[connection common cache] value is null, remove it, key {}.", key);
cacheMap.remove(key);
timeoutMap.remove(key);
} else if (refreshCache) {
cacheTime[0] = System.currentTimeMillis();
timeoutMap.put(key, cacheTime);
}
return Optional.ofNullable(value);
}
/**
* remove cache by key
*
* @param key key
*/
public void removeCache(Object key) {
timeoutMap.remove(key);
Object value = cacheMap.remove(key);
if (value instanceof CacheCloseable) {
((CacheCloseable) value).close();
}
}
/**
* get common cache instance
*
* @return connection common cache
*/
public static ConnectionCommonCache getInstance() {
return SingleInstance.INSTANCE;
}
/**
* static single instance
*/
private static class SingleInstance {
private static final ConnectionCommonCache INSTANCE = new ConnectionCommonCache();
}
}
@@ -1,49 +0,0 @@
/*
* 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.dromara.hertzbeat.collector.collect.common.cache;
import com.mongodb.client.MongoClient;
import lombok.extern.slf4j.Slf4j;
/**
* mongodb connect client
*
*/
@Slf4j
public class MongodbConnect implements CacheCloseable {
private final MongoClient mongoClient;
public MongodbConnect(MongoClient mongoClient) {
this.mongoClient = mongoClient;
}
@Override
public void close() {
try {
if (this.mongoClient != null) {
this.mongoClient.close();
}
} catch (Exception e) {
log.error("[connection common cache] close mongodb connect error: {}", e.getMessage());
}
}
public MongoClient getMongoClient() {
return mongoClient;
}
}
@@ -1,347 +0,0 @@
/*
* 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.dromara.hertzbeat.collector.collect.database;
import com.mysql.cj.jdbc.exceptions.CommunicationsException;
import org.dromara.hertzbeat.collector.collect.AbstractCollect;
import org.dromara.hertzbeat.collector.collect.common.cache.CacheIdentifier;
import org.dromara.hertzbeat.collector.collect.common.cache.ConnectionCommonCache;
import org.dromara.hertzbeat.collector.collect.common.cache.JdbcConnect;
import org.dromara.hertzbeat.collector.dispatch.DispatchConstants;
import org.dromara.hertzbeat.collector.util.CollectUtil;
import org.dromara.hertzbeat.common.constants.CollectorConstants;
import org.dromara.hertzbeat.common.entity.job.Metrics;
import org.dromara.hertzbeat.common.entity.job.protocol.JdbcProtocol;
import org.dromara.hertzbeat.common.entity.message.CollectRep;
import org.dromara.hertzbeat.common.constants.CommonConstants;
import org.dromara.hertzbeat.common.util.CommonUtil;
import lombok.extern.slf4j.Slf4j;
import org.postgresql.util.PSQLException;
import org.springframework.core.io.FileSystemResource;
import org.springframework.jdbc.datasource.init.ScriptUtils;
import org.springframework.util.StringUtils;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
/**
* common query for database query
*
*/
@Slf4j
public class JdbcCommonCollect extends AbstractCollect {
private static final String QUERY_TYPE_ONE_ROW = "oneRow";
private static final String QUERY_TYPE_MULTI_ROW = "multiRow";
private static final String QUERY_TYPE_COLUMNS = "columns";
private static final String RUN_SCRIPT = "runScript";
private static final String[] VULNERABLE_KEYWORDS = {"allowLoadLocalInfile", "allowLoadLocalInfileInPath", "useLocalInfile"};
public JdbcCommonCollect(){}
@Override
public void collect(CollectRep.MetricsData.Builder builder, long monitorId, String app, Metrics metrics) {
long startTime = System.currentTimeMillis();
// check the params
try {
validateParams(metrics);
} catch (Exception e) {
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg(e.getMessage());
return;
}
JdbcProtocol jdbcProtocol = metrics.getJdbc();
String databaseUrl = constructDatabaseUrl(jdbcProtocol);
int timeout = CollectUtil.getTimeout(jdbcProtocol.getTimeout());
Statement statement = null;
try {
statement = getConnection(jdbcProtocol.getUsername(),
jdbcProtocol.getPassword(), databaseUrl, timeout);
switch (jdbcProtocol.getQueryType()) {
case QUERY_TYPE_ONE_ROW:
queryOneRow(statement, jdbcProtocol.getSql(), metrics.getAliasFields(), builder, startTime);
break;
case QUERY_TYPE_MULTI_ROW:
queryMultiRow(statement, jdbcProtocol.getSql(), metrics.getAliasFields(), builder, startTime);
break;
case QUERY_TYPE_COLUMNS:
queryOneRowByMatchTwoColumns(statement, jdbcProtocol.getSql(), metrics.getAliasFields(), builder, startTime);
break;
case RUN_SCRIPT:
Connection connection = statement.getConnection();
FileSystemResource rc = new FileSystemResource(jdbcProtocol.getSql());
ScriptUtils.executeSqlScript(connection, rc);
break;
default:
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg("Not support database query type: " + jdbcProtocol.getQueryType());
break;
}
} catch (CommunicationsException communicationsException) {
log.warn("Jdbc sql error: {}, code: {}.", communicationsException.getMessage(), communicationsException.getErrorCode());
builder.setCode(CollectRep.Code.UN_REACHABLE);
builder.setMsg("Error: " + communicationsException.getMessage() + " Code: " + communicationsException.getErrorCode());
} catch (PSQLException psqlException) {
// for PostgreSQL 08001
if (CollectorConstants.POSTGRESQL_UN_REACHABLE_CODE.equals(psqlException.getSQLState())) {
// 对端链接失败 不可达
builder.setCode(CollectRep.Code.UN_REACHABLE);
} else {
builder.setCode(CollectRep.Code.FAIL);
}
builder.setMsg("Error: " + psqlException.getMessage() + " Code: " + psqlException.getSQLState());
} catch (SQLException sqlException) {
log.warn("Jdbc sql error: {}, code: {}.", sqlException.getMessage(), sqlException.getErrorCode());
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg("Query Error: " + sqlException.getMessage() + " Code: " + sqlException.getErrorCode());
} catch (Exception e) {
String errorMessage = CommonUtil.getMessageFromThrowable(e);
log.error("Jdbc error: {}.", errorMessage, e);
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg("Query Error: " + errorMessage);
} finally {
if (statement != null) {
try {
statement.close();
} catch (Exception e) {
log.error("Jdbc close statement error: {}", e.getMessage());
}
}
}
}
@Override
public String supportProtocol() {
return DispatchConstants.PROTOCOL_JDBC;
}
private Statement getConnection(String username, String password, String url, Integer timeout) throws Exception {
CacheIdentifier identifier = CacheIdentifier.builder()
.ip(url)
.username(username).password(password).build();
Optional<Object> cacheOption = ConnectionCommonCache.getInstance().getCache(identifier, true);
Statement statement = null;
if (cacheOption.isPresent()) {
JdbcConnect jdbcConnect = (JdbcConnect) cacheOption.get();
try {
statement = jdbcConnect.getConnection().createStatement();
// set query timeout
int timeoutSecond = timeout / 1000;
timeoutSecond = timeoutSecond <= 0 ? 1 : timeoutSecond;
statement.setQueryTimeout(timeoutSecond);
// set query max row number
statement.setMaxRows(1000);
} catch (Exception e) {
log.info("The jdbc connect from cache, create statement error: {}", e.getMessage());
try {
if (statement != null) {
statement.close();
}
jdbcConnect.close();
} catch (Exception e2) {
log.error(e2.getMessage());
}
statement = null;
ConnectionCommonCache.getInstance().removeCache(identifier);
}
}
if (statement != null) {
return statement;
}
// renew connection when failed
Connection connection = DriverManager.getConnection(url, username, password);
statement = connection.createStatement();
int timeoutSecond = timeout / 1000;
timeoutSecond = timeoutSecond <= 0 ? 1 : timeoutSecond;
statement.setQueryTimeout(timeoutSecond);
statement.setMaxRows(1000);
JdbcConnect jdbcConnect = new JdbcConnect(connection);
ConnectionCommonCache.getInstance().addCache(identifier, jdbcConnect);
return statement;
}
/**
* query one row record, response metrics header and one value row
* eg:
* query metricsone tow three four
* query sqlselect one, tow, three, four from book limit 1;
* @param statement statement
* @param sql sql
* @param columns query metrics field list
* @throws Exception when error happen
*/
private void queryOneRow(Statement statement, String sql, List<String> columns,
CollectRep.MetricsData.Builder builder, long startTime) throws Exception {
statement.setMaxRows(1);
try (ResultSet resultSet = statement.executeQuery(sql)) {
if (resultSet.next()) {
CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder();
for (String column : columns) {
if (CollectorConstants.RESPONSE_TIME.equals(column)) {
long time = System.currentTimeMillis() - startTime;
valueRowBuilder.addColumns(String.valueOf(time));
} else {
String value = resultSet.getString(column);
value = value == null ? CommonConstants.NULL_VALUE : value;
valueRowBuilder.addColumns(value);
}
}
builder.addValues(valueRowBuilder.build());
}
}
}
/**
* query two columns to mapping one row
* eg:
* query metricsone two three four
* query sqlselect key, value from book; the key is the query metrics fields
* select key, value from book;
* one - value1
* two - value2
* three - value3
* four - value4
* @param statement statement
* @param sql sql
* @param columns query metrics field list
* @throws Exception when error happen
*/
private void queryOneRowByMatchTwoColumns(Statement statement, String sql, List<String> columns,
CollectRep.MetricsData.Builder builder, long startTime) throws Exception {
try (ResultSet resultSet = statement.executeQuery(sql)) {
HashMap<String, String> values = new HashMap<>(columns.size());
while (resultSet.next()) {
if (resultSet.getString(1) != null) {
values.put(resultSet.getString(1).toLowerCase().trim(), resultSet.getString(2));
}
}
CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder();
for (String column : columns) {
if (CollectorConstants.RESPONSE_TIME.equals(column)) {
long time = System.currentTimeMillis() - startTime;
valueRowBuilder.addColumns(String.valueOf(time));
} else {
String value = values.get(column.toLowerCase());
value = value == null ? CommonConstants.NULL_VALUE : value;
valueRowBuilder.addColumns(value);
}
}
builder.addValues(valueRowBuilder.build());
}
}
/**
* query multi row record, response metrics header and multi value row
* eg:
* query metricsone tow three four
* query sqlselect one, tow, three, four from book;
* and return multi row record mapping with the metrics
* @param statement statement
* @param sql sql
* @param columns query metrics field list
* @throws Exception when error happen
*/
private void queryMultiRow(Statement statement, String sql, List<String> columns,
CollectRep.MetricsData.Builder builder, long startTime) throws Exception {
try (ResultSet resultSet = statement.executeQuery(sql)) {
while (resultSet.next()) {
CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder();
for (String column : columns) {
if (CollectorConstants.RESPONSE_TIME.equals(column)) {
long time = System.currentTimeMillis() - startTime;
valueRowBuilder.addColumns(String.valueOf(time));
} else {
String value = resultSet.getString(column);
value = value == null ? CommonConstants.NULL_VALUE : value;
valueRowBuilder.addColumns(value);
}
}
builder.addValues(valueRowBuilder.build());
}
}
}
/**
* construct jdbc url due the jdbc protocol
* @param jdbcProtocol jdbc
* @return URL
*/
private String constructDatabaseUrl(JdbcProtocol jdbcProtocol) {
if (Objects.nonNull(jdbcProtocol.getUrl())
&& !Objects.equals("", jdbcProtocol.getUrl())
&& jdbcProtocol.getUrl().startsWith("jdbc")) {
// when has config jdbc url, use it
return jdbcProtocol.getUrl();
}
String url;
switch (jdbcProtocol.getPlatform()) {
case "mysql":
case "mariadb":
url = "jdbc:mysql://" + jdbcProtocol.getHost() + ":" + jdbcProtocol.getPort()
+ "/" + (jdbcProtocol.getDatabase() == null ? "" : jdbcProtocol.getDatabase())
+ "?useUnicode=true&characterEncoding=utf-8&useSSL=false";
break;
case "postgresql":
url = "jdbc:postgresql://" + jdbcProtocol.getHost() + ":" + jdbcProtocol.getPort()
+ "/" + (jdbcProtocol.getDatabase() == null ? "" : jdbcProtocol.getDatabase());
break;
case "clickhouse":
url = "jdbc:clickhouse://" + jdbcProtocol.getHost() + ":" + jdbcProtocol.getPort()
+ "/" + (jdbcProtocol.getDatabase() == null ? "" : jdbcProtocol.getDatabase());
break;
case "sqlserver":
url = "jdbc:sqlserver://" + jdbcProtocol.getHost() + ":" + jdbcProtocol.getPort()
+ ";" + (jdbcProtocol.getDatabase() == null ? "" : "DatabaseName=" + jdbcProtocol.getDatabase())
+ ";trustServerCertificate=true;";
break;
case "oracle":
url = "jdbc:oracle:thin:@" + jdbcProtocol.getHost() + ":" + jdbcProtocol.getPort()
+ "/" + (jdbcProtocol.getDatabase() == null ? "" : jdbcProtocol.getDatabase());
break;
case "dm":
url = "jdbc:dm://" + jdbcProtocol.getHost() + ":" +jdbcProtocol.getPort();
break;
default:
throw new IllegalArgumentException("Not support database platform: " + jdbcProtocol.getPlatform());
}
return url;
}
private void validateParams(Metrics metrics) throws IllegalArgumentException {
if (metrics == null || metrics.getJdbc() == null) {
throw new IllegalArgumentException("Database collect must has jdbc params");
}
if (StringUtils.hasText(metrics.getJdbc().getUrl())) {
for (String keyword : VULNERABLE_KEYWORDS) {
if (metrics.getJdbc().getUrl().contains(keyword)) {
throw new IllegalArgumentException("Jdbc url prohibit contains vulnerable param " + keyword);
}
}
}
}
}
@@ -1,161 +0,0 @@
/*
* 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.dromara.hertzbeat.collector.collect.ftp;
import org.dromara.hertzbeat.collector.collect.AbstractCollect;
import org.dromara.hertzbeat.collector.dispatch.DispatchConstants;
import org.dromara.hertzbeat.common.entity.job.Metrics;
import org.dromara.hertzbeat.common.entity.job.protocol.FtpProtocol;
import org.dromara.hertzbeat.common.entity.message.CollectRep;
import org.dromara.hertzbeat.common.constants.CommonConstants;
import org.dromara.hertzbeat.common.util.CommonUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTPClient;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* ftp protocol collection implementation
*
*/
@Slf4j
public class FtpCollectImpl extends AbstractCollect {
private static final String ANONYMOUS = "anonymous";
private static final String PASSWORD = "password";
@Override
public void collect(CollectRep.MetricsData.Builder builder, long monitorId, String app, Metrics metrics) {
FTPClient ftpClient = new FTPClient();
FtpProtocol ftpProtocol = metrics.getFtp();
// Set timeout
ftpClient.setControlKeepAliveReplyTimeout(Integer.parseInt(ftpProtocol.getTimeout()));
// Judge whether the basic information is wrong
try {
preCheck(metrics);
} catch (Exception e) {
log.info("[FtpProtocol] error: {}", CommonUtil.getMessageFromThrowable(e), e);
builder.setCode(CollectRep.Code.UN_CONNECTABLE);
builder.setMsg(e.getMessage());
return;
}
// Collect data to load in CollectRep.ValueRow.Builder's object
CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder();
Map<String, String> valueMap;
try {
valueMap = collectValue(ftpClient, ftpProtocol);
metrics.getAliasFields().forEach(it -> {
if (valueMap.containsKey(it)) {
String fieldValue = valueMap.get(it);
valueRowBuilder.addColumns(Objects.requireNonNullElse(fieldValue, CommonConstants.NULL_VALUE));
} else {
valueRowBuilder.addColumns(CommonConstants.NULL_VALUE);
}
});
} catch (Exception e) {
builder.setCode(CollectRep.Code.UN_CONNECTABLE);
builder.setMsg(e.getMessage());
return;
}
builder.addValues(valueRowBuilder.build());
}
/**
* collect data: key-value
* Please modify this, if you want to add some metrics.
*/
private Map<String, String> collectValue(FTPClient ftpClient, FtpProtocol ftpProtocol) {
boolean isActive;
String responseTime;
try {
long startTime = System.currentTimeMillis();
connect(ftpClient, ftpProtocol);
login(ftpClient, ftpProtocol);
// In here, we can do some extended operation without changing the architecture
isActive = ftpClient.changeWorkingDirectory(ftpProtocol.getDirection());
long endTime = System.currentTimeMillis();
responseTime = String.valueOf(endTime - startTime);
ftpClient.disconnect();
} catch (Exception e) {
log.info("[FTPClient] error: {}", CommonUtil.getMessageFromThrowable(e), e);
throw new IllegalArgumentException(e.getMessage());
}
return new HashMap<>(8) {
{
put("isActive", Boolean.toString(isActive));
put("responseTime", responseTime);
}
};
}
/**
* login
*/
private void login(FTPClient ftpClient, FtpProtocol ftpProtocol) {
try {
// username: not empty, password: not empty
if (StringUtils.hasText(ftpProtocol.getUsername()) && StringUtils.hasText(ftpProtocol.getPassword())) {
if (!ftpClient.login(ftpProtocol.getUsername(), ftpProtocol.getPassword())) {
throw new IllegalArgumentException("The username or password may be wrong.");
}
return;
}
// anonymous access
if (!ftpClient.login(ANONYMOUS, PASSWORD)) {
throw new IllegalArgumentException("The server may not allow anonymous access, we need to username and password.");
}
} catch (Exception e) {
log.info("[ftp login] error: {}", CommonUtil.getMessageFromThrowable(e), e);
throw new IllegalArgumentException(e.getMessage());
}
}
/**
* connect
*/
private void connect(FTPClient ftpClient, FtpProtocol ftpProtocol) {
try {
ftpClient.connect(ftpProtocol.getHost(), Integer.parseInt(ftpProtocol.getPort()));
} catch (Exception e) {
log.info("[ftp connection] error: {}", CommonUtil.getMessageFromThrowable(e), e);
throw new IllegalArgumentException("The host or port may be wrong.");
}
}
/**
* preCheck params
*/
private void preCheck(Metrics metrics) {
if (metrics == null || metrics.getFtp() == null) {
throw new IllegalArgumentException("Ftp collect must has ftp params.");
}
FtpProtocol ftpProtocol = metrics.getFtp();
Assert.hasText(ftpProtocol.getHost(), "Ftp Protocol host is required.");
Assert.hasText(ftpProtocol.getPort(), "Ftp Protocol port is required.");
Assert.hasText(ftpProtocol.getDirection(), "Ftp Protocol direction is required.");
}
@Override
public String supportProtocol() {
return DispatchConstants.PROTOCOL_FTP;
}
}
@@ -1,590 +0,0 @@
/*
* 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.dromara.hertzbeat.collector.collect.http;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.dromara.hertzbeat.collector.collect.AbstractCollect;
import org.dromara.hertzbeat.collector.collect.common.http.CommonHttpClient;
import org.dromara.hertzbeat.collector.collect.http.promethus.exporter.ExporterParser;
import org.dromara.hertzbeat.collector.collect.http.promethus.exporter.MetricFamily;
import org.dromara.hertzbeat.collector.dispatch.DispatchConstants;
import org.dromara.hertzbeat.collector.util.CollectUtil;
import org.dromara.hertzbeat.common.constants.CollectorConstants;
import org.dromara.hertzbeat.collector.util.JsonPathParser;
import org.dromara.hertzbeat.common.entity.job.Metrics;
import org.dromara.hertzbeat.common.entity.job.protocol.HttpProtocol;
import org.dromara.hertzbeat.common.entity.message.CollectRep;
import org.dromara.hertzbeat.common.constants.CommonConstants;
import org.dromara.hertzbeat.common.util.CommonUtil;
import org.dromara.hertzbeat.common.util.IpDomainUtil;
import org.dromara.hertzbeat.collector.collect.http.promethus.AbstractPrometheusParse;
import org.dromara.hertzbeat.collector.collect.http.promethus.PrometheusParseCreater;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.util.Base64;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpHost;
import org.apache.http.HttpStatus;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.AuthCache;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.auth.DigestScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.springframework.http.HttpMethod;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.net.ssl.SSLException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.ConnectException;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.dromara.hertzbeat.common.constants.SignConstants.RIGHT_DASH;
/**
* http https collect
*
*
*/
@Slf4j
public class HttpCollectImpl extends AbstractCollect {
private final Set<Integer> defaultSuccessStatusCodes = Stream.of(HttpStatus.SC_OK, HttpStatus.SC_CREATED,
HttpStatus.SC_ACCEPTED, HttpStatus.SC_MULTIPLE_CHOICES, HttpStatus.SC_MOVED_PERMANENTLY,
HttpStatus.SC_MOVED_TEMPORARILY).collect(Collectors.toSet());
public HttpCollectImpl() {
}
@Override
public void collect(CollectRep.MetricsData.Builder builder,
long monitorId, String app, Metrics metrics) {
long startTime = System.currentTimeMillis();
try {
validateParams(metrics);
} catch (Exception e) {
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg(e.getMessage());
return;
}
HttpContext httpContext = createHttpContext(metrics.getHttp());
HttpUriRequest request = createHttpRequest(metrics.getHttp());
try (CloseableHttpResponse response = CommonHttpClient.getHttpClient().execute(request, httpContext)) {
int statusCode = response.getStatusLine().getStatusCode();
boolean isSuccessInvoke = checkSuccessInvoke(metrics, statusCode);
log.debug("http response status: {}", statusCode);
if (!isSuccessInvoke) {
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg("StatusCode " + statusCode);
return;
}
// todo 这里直接将InputStream转为了String, 对于prometheus exporter大数据来说, 会生成大对象, 可能会严重影响JVM内存空间
// todo 方法一、使用InputStream进行解析, 代码改动大; 方法二、手动触发gc, 可以参考dubbo for long i
String resp = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
if (resp == null || "".equals(resp)) {
log.info("http response entity is empty, status: {}.", statusCode);
}
Long responseTime = System.currentTimeMillis() - startTime;
String parseType = metrics.getHttp().getParseType();
try {
if (DispatchConstants.PARSE_DEFAULT.equals(parseType)) {
parseResponseByDefault(resp, metrics.getAliasFields(), metrics.getHttp(), builder, responseTime);
} else if (DispatchConstants.PARSE_JSON_PATH.equals(parseType)) {
parseResponseByJsonPath(resp, metrics.getAliasFields(), metrics.getHttp(), builder, responseTime);
} else if (DispatchConstants.PARSE_PROM_QL.equalsIgnoreCase(parseType)) {
parseResponseByPromQl(resp, metrics.getAliasFields(), metrics.getHttp(), builder);
} else if (DispatchConstants.PARSE_PROMETHEUS.equals(parseType)) {
parseResponseByPrometheusExporter(resp, metrics.getAliasFields(), builder);
} else if (DispatchConstants.PARSE_XML_PATH.equals(parseType)) {
parseResponseByXmlPath(resp, metrics.getAliasFields(), metrics.getHttp(), builder);
} else if (DispatchConstants.PARSE_WEBSITE.equals(parseType)) {
parseResponseByWebsite(resp, metrics.getAliasFields(), metrics.getHttp(), builder, responseTime);
} else if (DispatchConstants.PARSE_SITE_MAP.equals(parseType)) {
parseResponseBySiteMap(resp, metrics.getAliasFields(), builder);
} else {
parseResponseByDefault(resp, metrics.getAliasFields(), metrics.getHttp(), builder, responseTime);
}
} catch (Exception e) {
log.info("parse error: {}.", e.getMessage(), e);
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg("parse response data error:" + e.getMessage());
}
} catch (ClientProtocolException e1) {
String errorMsg = CommonUtil.getMessageFromThrowable(e1);
log.error(errorMsg);
builder.setCode(CollectRep.Code.UN_CONNECTABLE);
builder.setMsg(errorMsg);
} catch (UnknownHostException e2) {
String errorMsg = CommonUtil.getMessageFromThrowable(e2);
log.info(errorMsg);
builder.setCode(CollectRep.Code.UN_REACHABLE);
builder.setMsg("unknown host:" + errorMsg);
} catch (InterruptedIOException | ConnectException | SSLException e3) {
String errorMsg = CommonUtil.getMessageFromThrowable(e3);
log.info(errorMsg);
builder.setCode(CollectRep.Code.UN_CONNECTABLE);
builder.setMsg(errorMsg);
} catch (IOException e4) {
String errorMsg = CommonUtil.getMessageFromThrowable(e4);
log.info(errorMsg);
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg(errorMsg);
} catch (Exception e) {
String errorMsg = CommonUtil.getMessageFromThrowable(e);
log.error(errorMsg, e);
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg(errorMsg);
} finally {
if (request != null) {
request.abort();
}
}
}
@Override
public String supportProtocol() {
return DispatchConstants.PROTOCOL_HTTP;
}
private void validateParams(Metrics metrics) throws Exception {
if (metrics == null || metrics.getHttp() == null) {
throw new Exception("Http/Https collect must has http params");
}
HttpProtocol httpProtocol = metrics.getHttp();
if (httpProtocol.getUrl() == null
|| "".equals(httpProtocol.getUrl())
|| !httpProtocol.getUrl().startsWith(RIGHT_DASH)) {
httpProtocol.setUrl(httpProtocol.getUrl() == null ? RIGHT_DASH : RIGHT_DASH + httpProtocol.getUrl().trim());
}
if (CollectionUtils.isEmpty(httpProtocol.getSuccessCodes())) {
httpProtocol.setSuccessCodes(List.of("200"));
}
}
private void parseResponseByWebsite(String resp, List<String> aliasFields, HttpProtocol http,
CollectRep.MetricsData.Builder builder, Long responseTime) {
CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder();
int keywordNum = CollectUtil.countMatchKeyword(resp, http.getKeyword());
for (String alias : aliasFields) {
if (CollectorConstants.RESPONSE_TIME.equalsIgnoreCase(alias)) {
valueRowBuilder.addColumns(responseTime.toString());
} else if (CollectorConstants.KEYWORD.equalsIgnoreCase(alias)) {
valueRowBuilder.addColumns(Integer.toString(keywordNum));
} else {
valueRowBuilder.addColumns(CommonConstants.NULL_VALUE);
}
}
builder.addValues(valueRowBuilder.build());
}
private void parseResponseBySiteMap(String resp, List<String> aliasFields,
CollectRep.MetricsData.Builder builder) {
List<String> siteUrls = new LinkedList<>();
boolean isXmlFormat = true;
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.parse(new ByteArrayInputStream(resp.getBytes(StandardCharsets.UTF_8)));
NodeList urlList = document.getElementsByTagName("url");
for (int i = 0; i < urlList.getLength(); i++) {
Node urlNode = urlList.item(i);
NodeList childNodes = urlNode.getChildNodes();
for (int k = 0; k < childNodes.getLength(); k++) {
Node currentNode = childNodes.item(k);
// 区分出text类型的node以及element类型的node
if (currentNode.getNodeType() == Node.ELEMENT_NODE && "loc".equals(currentNode.getNodeName())) {
//获取了loc节点的值
siteUrls.add(currentNode.getFirstChild().getNodeValue());
break;
}
}
}
} catch (Exception e) {
log.warn(e.getMessage());
isXmlFormat = false;
}
// 若xml解析失败 用txt格式解析
if (!isXmlFormat) {
try {
String[] urls = resp.split("\n");
// 校验是否是URL
if (IpDomainUtil.isHasSchema(urls[0])) {
siteUrls.addAll(Arrays.asList(urls));
}
} catch (Exception e) {
log.warn(e.getMessage(), e);
}
}
// 开始循环访问每个site url 采集其 http status code, responseTime, 异常信息
for (String siteUrl : siteUrls) {
String errorMsg = "";
Integer statusCode = null;
long startTime = System.currentTimeMillis();
try {
HttpGet httpGet = new HttpGet(siteUrl);
CloseableHttpResponse response = CommonHttpClient.getHttpClient().execute(httpGet);
statusCode = response.getStatusLine().getStatusCode();
EntityUtils.consume(response.getEntity());
} catch (ClientProtocolException e1) {
if (e1.getCause() != null) {
errorMsg = e1.getCause().getMessage();
} else {
errorMsg = e1.getMessage();
}
} catch (UnknownHostException e2) {
errorMsg = "unknown host";
} catch (InterruptedIOException | ConnectException | SSLException e3) {
errorMsg = "connect error: " + e3.getMessage();
} catch (IOException e4) {
errorMsg = "io error: " + e4.getMessage();
} catch (Exception e) {
errorMsg = "error: " + e.getMessage();
}
long responseTime = System.currentTimeMillis() - startTime;
CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder();
for (String alias : aliasFields) {
if (CollectorConstants.URL.equalsIgnoreCase(alias)) {
valueRowBuilder.addColumns(siteUrl);
} else if (CollectorConstants.STATUS_CODE.equalsIgnoreCase(alias)) {
valueRowBuilder.addColumns(statusCode == null ?
CommonConstants.NULL_VALUE : String.valueOf(statusCode));
} else if (CollectorConstants.RESPONSE_TIME.equalsIgnoreCase(alias)) {
valueRowBuilder.addColumns(String.valueOf(responseTime));
} else if (CollectorConstants.ERROR_MSG.equalsIgnoreCase(alias)) {
valueRowBuilder.addColumns(errorMsg);
} else {
valueRowBuilder.addColumns(CommonConstants.NULL_VALUE);
}
}
builder.addValues(valueRowBuilder.build());
}
}
private void parseResponseByXmlPath(String resp, List<String> aliasFields, HttpProtocol http,
CollectRep.MetricsData.Builder builder) {
}
private void parseResponseByJsonPath(String resp, List<String> aliasFields, HttpProtocol http,
CollectRep.MetricsData.Builder builder, Long responseTime) {
List<Object> results = JsonPathParser.parseContentWithJsonPath(resp, http.getParseScript());
int keywordNum = CollectUtil.countMatchKeyword(resp, http.getKeyword());
for (int i = 0; i < results.size(); i++) {
Object objectValue = results.get(i);
// 监控目标版本问题可能出现属性不存在,为空时过滤。参考app-elasticsearch.yml的name: nodes
if (objectValue == null) {
continue;
}
if (objectValue instanceof Map) {
Map<String, Object> stringMap = (Map<String, Object>) objectValue;
CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder();
for (String alias : aliasFields) {
Object value = stringMap.get(alias);
if (value != null) {
valueRowBuilder.addColumns(String.valueOf(value));
} else {
if (alias.startsWith("$.")) {
List<Object> subResults = JsonPathParser.parseContentWithJsonPath(resp, http.getParseScript() + alias.substring(1));
if (subResults != null && subResults.size() > i) {
Object resultValue = subResults.get(i);
valueRowBuilder.addColumns(resultValue == null ? CommonConstants.NULL_VALUE : String.valueOf(resultValue));
} else {
valueRowBuilder.addColumns(CommonConstants.NULL_VALUE);
}
} else if (CollectorConstants.RESPONSE_TIME.equalsIgnoreCase(alias)) {
valueRowBuilder.addColumns(responseTime.toString());
} else if (CollectorConstants.KEYWORD.equalsIgnoreCase(alias)) {
valueRowBuilder.addColumns(Integer.toString(keywordNum));
} else {
valueRowBuilder.addColumns(CommonConstants.NULL_VALUE);
}
}
}
builder.addValues(valueRowBuilder.build());
} else if (objectValue instanceof String) {
String stringValue = (String) objectValue;
CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder();
for (String alias : aliasFields) {
if (CollectorConstants.RESPONSE_TIME.equalsIgnoreCase(alias)) {
valueRowBuilder.addColumns(responseTime.toString());
} else if (CollectorConstants.KEYWORD.equalsIgnoreCase(alias)) {
valueRowBuilder.addColumns(Integer.toString(keywordNum));
} else {
valueRowBuilder.addColumns(stringValue);
}
}
builder.addValues(valueRowBuilder.build());
}
}
}
private void parseResponseByPromQl(String resp, List<String> aliasFields, HttpProtocol http,
CollectRep.MetricsData.Builder builder) {
AbstractPrometheusParse prometheusParser = PrometheusParseCreater.getPrometheusParse();
prometheusParser.handle(resp, aliasFields, http, builder);
}
private static final Map<Long, ExporterParser> EXPORTER_PARSER_TABLE = new ConcurrentHashMap<>();
private void parseResponseByPrometheusExporter(String resp, List<String> aliasFields,
CollectRep.MetricsData.Builder builder) {
if (!EXPORTER_PARSER_TABLE.containsKey(builder.getId())) {
EXPORTER_PARSER_TABLE.put(builder.getId(), new ExporterParser());
}
ExporterParser parser = EXPORTER_PARSER_TABLE.get(builder.getId());
Map<String, MetricFamily> metricFamilyMap = parser.textToMetric(resp);
String metrics = builder.getMetrics();
if (metricFamilyMap.containsKey(metrics)) {
MetricFamily metricFamily = metricFamilyMap.get(metrics);
for (MetricFamily.Metric metric : metricFamily.getMetricList()) {
Map<String, String> labelMap = metric.getLabelPair()
.stream()
.collect(Collectors.toMap(MetricFamily.Label::getName, MetricFamily.Label::getValue));
CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder();
for (String aliasField : aliasFields) {
if ("value".equals(aliasField)) {
if (metric.getCounter() != null) {
valueRowBuilder.addColumns(String.valueOf(metric.getCounter().getValue()));
} else if (metric.getGauge() != null) {
valueRowBuilder.addColumns(String.valueOf(metric.getGauge().getValue()));
} else if (metric.getUntyped() != null) {
valueRowBuilder.addColumns(String.valueOf(metric.getUntyped().getValue()));
} else if (metric.getInfo() != null) {
valueRowBuilder.addColumns(String.valueOf(metric.getInfo().getValue()));
}
} else {
valueRowBuilder.addColumns(labelMap.get(aliasField));
}
}
builder.addValues(valueRowBuilder.build());
}
}
}
private void parseResponseByDefault(String resp, List<String> aliasFields, HttpProtocol http,
CollectRep.MetricsData.Builder builder, Long responseTime) {
JsonElement element = JsonParser.parseString(resp);
int keywordNum = CollectUtil.countMatchKeyword(resp, http.getKeyword());
if (element.isJsonArray()) {
JsonArray array = element.getAsJsonArray();
for (JsonElement jsonElement : array) {
getValueFromJson(aliasFields, builder, responseTime, jsonElement, keywordNum);
}
} else {
getValueFromJson(aliasFields, builder, responseTime, element, keywordNum);
}
}
private void getValueFromJson(List<String> aliasFields, CollectRep.MetricsData.Builder builder, Long responseTime, JsonElement element, int keywordNum) {
if (element.isJsonObject()) {
JsonObject object = element.getAsJsonObject();
CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder();
for (String alias : aliasFields) {
JsonElement valueElement = object.get(alias);
if (valueElement != null) {
String value = valueElement.getAsString();
valueRowBuilder.addColumns(value);
} else {
if (CollectorConstants.RESPONSE_TIME.equalsIgnoreCase(alias)) {
valueRowBuilder.addColumns(responseTime.toString());
} else if (CollectorConstants.KEYWORD.equalsIgnoreCase(alias)) {
valueRowBuilder.addColumns(Integer.toString(keywordNum));
} else {
valueRowBuilder.addColumns(CommonConstants.NULL_VALUE);
}
}
}
builder.addValues(valueRowBuilder.build());
}
}
/**
* create httpContext
* @param httpProtocol http protocol
* @return context
*/
public HttpContext createHttpContext(HttpProtocol httpProtocol) {
HttpProtocol.Authorization auth = httpProtocol.getAuthorization();
if (auth != null && DispatchConstants.DIGEST_AUTH.equals(auth.getType())) {
HttpClientContext clientContext = new HttpClientContext();
if (StringUtils.hasText(auth.getDigestAuthUsername())
&& StringUtils.hasText(auth.getDigestAuthPassword())) {
CredentialsProvider provider = new BasicCredentialsProvider();
UsernamePasswordCredentials credentials
= new UsernamePasswordCredentials(auth.getDigestAuthUsername(), auth.getDigestAuthPassword());
provider.setCredentials(AuthScope.ANY, credentials);
AuthCache authCache = new BasicAuthCache();
authCache.put(new HttpHost(httpProtocol.getHost(), Integer.parseInt(httpProtocol.getPort())), new DigestScheme());
clientContext.setCredentialsProvider(provider);
clientContext.setAuthCache(authCache);
return clientContext;
}
}
return null;
}
/**
* create http request
* @param httpProtocol http params
* @return http uri request
*/
public HttpUriRequest createHttpRequest(HttpProtocol httpProtocol) {
RequestBuilder requestBuilder;
String httpMethod = httpProtocol.getMethod().toUpperCase();
if (HttpMethod.GET.matches(httpMethod)) {
requestBuilder = RequestBuilder.get();
} else if (HttpMethod.POST.matches(httpMethod)) {
requestBuilder = RequestBuilder.post();
} else if (HttpMethod.PUT.matches(httpMethod)) {
requestBuilder = RequestBuilder.put();
} else if (HttpMethod.DELETE.matches(httpMethod)) {
requestBuilder = RequestBuilder.delete();
} else if (HttpMethod.PATCH.matches(httpMethod)) {
requestBuilder = RequestBuilder.patch();
} else {
// not support the method
log.error("not support the http method: {}.", httpProtocol.getMethod());
return null;
}
// params
Map<String, String> params = httpProtocol.getParams();
if (params != null && !params.isEmpty()) {
for (Map.Entry<String, String> param : params.entrySet()) {
if (StringUtils.hasText(param.getValue())) {
requestBuilder.addParameter(param.getKey(), param.getValue());
}
}
}
// The default request header can be overridden if customized
// keep-alive
requestBuilder.addHeader(HttpHeaders.CONNECTION, "keep-alive");
requestBuilder.addHeader(HttpHeaders.USER_AGENT, "Mozilla/5.0 (Windows NT 6.1; WOW64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.76 Safari/537.36");
// headers The custom request header is overwritten here
Map<String, String> headers = httpProtocol.getHeaders();
if (headers != null && !headers.isEmpty()) {
for (Map.Entry<String, String> header : headers.entrySet()) {
if (StringUtils.hasText(header.getValue())) {
requestBuilder.addHeader(CollectUtil.replaceUriSpecialChar(header.getKey()),
CollectUtil.replaceUriSpecialChar(header.getValue()));
}
}
}
// add accept
if (DispatchConstants.PARSE_DEFAULT.equals(httpProtocol.getParseType())
|| DispatchConstants.PARSE_JSON_PATH.equals(httpProtocol.getParseType())) {
requestBuilder.addHeader(HttpHeaders.ACCEPT, "application/json");
} else if (DispatchConstants.PARSE_XML_PATH.equals(httpProtocol.getParseType())) {
requestBuilder.addHeader(HttpHeaders.ACCEPT, "text/xml,application/xml");
} else {
requestBuilder.addHeader(HttpHeaders.ACCEPT, "*/*");
}
if (httpProtocol.getAuthorization() != null) {
HttpProtocol.Authorization authorization = httpProtocol.getAuthorization();
if (DispatchConstants.BEARER_TOKEN.equalsIgnoreCase(authorization.getType())) {
String value = DispatchConstants.BEARER + " " + authorization.getBearerTokenToken();
requestBuilder.addHeader(HttpHeaders.AUTHORIZATION, value);
} else if (DispatchConstants.BASIC_AUTH.equals(authorization.getType())) {
if (StringUtils.hasText(authorization.getBasicAuthUsername())
&& StringUtils.hasText(authorization.getBasicAuthPassword())) {
String authStr = authorization.getBasicAuthUsername() + ":" + authorization.getBasicAuthPassword();
String encodedAuth = new String(Base64.encodeBase64(authStr.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8);
requestBuilder.addHeader(HttpHeaders.AUTHORIZATION, DispatchConstants.BASIC + " " + encodedAuth);
}
}
}
// if it has payload, would override post params
if (StringUtils.hasLength(httpProtocol.getPayload())) {
requestBuilder.setEntity(new StringEntity(httpProtocol.getPayload(), StandardCharsets.UTF_8));
}
// uri
String uri = CollectUtil.replaceUriSpecialChar(httpProtocol.getUrl());
if (IpDomainUtil.isHasSchema(httpProtocol.getHost())) {
requestBuilder.setUri(httpProtocol.getHost() + ":" + httpProtocol.getPort() + uri);
} else {
String ipAddressType = IpDomainUtil.checkIpAddressType(httpProtocol.getHost());
String baseUri = CollectorConstants.IPV6.equals(ipAddressType)
? String.format("[%s]:%s%s", httpProtocol.getHost(), httpProtocol.getPort(), uri)
: String.format("%s:%s%s", httpProtocol.getHost(), httpProtocol.getPort(), uri);
boolean ssl = Boolean.parseBoolean(httpProtocol.getSsl());
if (ssl) {
requestBuilder.setUri(CollectorConstants.HTTPS_HEADER + baseUri);
} else {
requestBuilder.setUri(CollectorConstants.HTTP_HEADER + baseUri);
}
}
// custom timeout
int timeout = CollectUtil.getTimeout(httpProtocol.getTimeout(), 0);
if (timeout > 0) {
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(timeout)
.setSocketTimeout(timeout)
.setRedirectsEnabled(true)
.build();
requestBuilder.setConfig(requestConfig);
}
return requestBuilder.build();
}
private boolean checkSuccessInvoke(Metrics metrics, int statusCode) {
List<String> successCodes = metrics.getHttp().getSuccessCodes();
Set<Integer> successCodeSet = successCodes != null ? successCodes.stream().map(code -> {
try {
return Integer.valueOf(code);
} catch (Exception ignored) {
return null;
}
}).filter(Objects::nonNull).collect(Collectors.toSet()) : defaultSuccessStatusCodes;
if (successCodeSet.isEmpty()) {
successCodeSet = defaultSuccessStatusCodes;
}
return successCodeSet.contains(statusCode);
}
}
@@ -1,170 +0,0 @@
/*
* 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.dromara.hertzbeat.collector.collect.http;
import org.dromara.hertzbeat.collector.collect.AbstractCollect;
import org.dromara.hertzbeat.collector.dispatch.DispatchConstants;
import org.dromara.hertzbeat.common.constants.CollectorConstants;
import org.dromara.hertzbeat.common.entity.job.Metrics;
import org.dromara.hertzbeat.common.entity.job.protocol.HttpProtocol;
import org.dromara.hertzbeat.common.entity.message.CollectRep;
import org.dromara.hertzbeat.common.constants.CommonConstants;
import org.dromara.hertzbeat.common.util.CommonUtil;
import org.dromara.hertzbeat.common.util.IpDomainUtil;
import lombok.extern.slf4j.Slf4j;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLPeerUnverifiedException;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.ConnectException;
import java.net.URL;
import java.net.UnknownHostException;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Date;
import static org.dromara.hertzbeat.common.constants.SignConstants.RIGHT_DASH;
/**
* ssl Certificate
*
*/
@Slf4j
public class SslCertificateCollectImpl extends AbstractCollect {
private static final String NAME_SUBJECT = "subject";
private static final String NAME_EXPIRED = "expired";
private static final String NAME_START_TIME = "start_time";
private static final String NAME_START_TIMESTAMP = "start_timestamp";
private static final String NAME_END_TIME = "end_time";
private static final String NAME_END_TIMESTAMP = "end_timestamp";
public SslCertificateCollectImpl() {}
@Override
public void collect(CollectRep.MetricsData.Builder builder,
long monitorId, String app, Metrics metrics) {
long startTime = System.currentTimeMillis();
try {
validateParams(metrics);
} catch (Exception e) {
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg(e.getMessage());
return;
}
HttpProtocol httpProtocol = metrics.getHttp();
HttpsURLConnection urlConnection = null;
try {
String uri = "";
if (IpDomainUtil.isHasSchema(httpProtocol.getHost())) {
uri = httpProtocol.getHost() + ":" + httpProtocol.getPort();
} else {
uri = "https://" + httpProtocol.getHost() + ":" + httpProtocol.getPort();
}
urlConnection = (HttpsURLConnection) new URL(uri).openConnection();
urlConnection.connect();
Certificate[] certificates = urlConnection.getServerCertificates();
if (certificates == null || certificates.length == 0) {
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg("Ssl certificate does not exist.");
return;
}
long responseTime = System.currentTimeMillis() - startTime;
for (Certificate certificate : urlConnection.getServerCertificates()) {
X509Certificate x509Certificate = (X509Certificate) certificate;
Date now = new Date();
Date deadline = x509Certificate.getNotAfter();
boolean expired = deadline != null && now.after(deadline);
CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder();
for (String alias : metrics.getAliasFields()) {
if (CollectorConstants.RESPONSE_TIME.equalsIgnoreCase(alias)) {
valueRowBuilder.addColumns(Long.toString(responseTime));
} else if (NAME_SUBJECT.equalsIgnoreCase(alias)) {
valueRowBuilder.addColumns(x509Certificate.getSubjectDN().getName());
} else if (NAME_EXPIRED.equalsIgnoreCase(alias)) {
valueRowBuilder.addColumns(Boolean.toString(expired));
} else if (NAME_START_TIME.equalsIgnoreCase(alias)) {
valueRowBuilder.addColumns(x509Certificate.getNotBefore().toLocaleString());
} else if (NAME_START_TIMESTAMP.equalsIgnoreCase(alias)) {
valueRowBuilder.addColumns(String.valueOf(x509Certificate.getNotBefore().getTime()));
} else if (NAME_END_TIME.equalsIgnoreCase(alias)) {
valueRowBuilder.addColumns(x509Certificate.getNotAfter().toLocaleString());
} else if (NAME_END_TIMESTAMP.equalsIgnoreCase(alias)) {
valueRowBuilder.addColumns(String.valueOf(x509Certificate.getNotAfter().getTime()));
} else {
valueRowBuilder.addColumns(CommonConstants.NULL_VALUE);
}
}
builder.addValues(valueRowBuilder.build());
}
} catch (SSLPeerUnverifiedException e1) {
String errorMsg = "Ssl certificate does not exist.";
if (e1.getMessage() != null) {
errorMsg = e1.getMessage();
log.error(errorMsg);
}
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg(errorMsg);
} catch (UnknownHostException e2) {
String errorMsg = CommonUtil.getMessageFromThrowable(e2);
log.info(errorMsg);
builder.setCode(CollectRep.Code.UN_REACHABLE);
builder.setMsg("unknown host:" + errorMsg);
} catch (InterruptedIOException | ConnectException | SSLException e3) {
String errorMsg = CommonUtil.getMessageFromThrowable(e3);
log.info(errorMsg);
builder.setCode(CollectRep.Code.UN_CONNECTABLE);
builder.setMsg(errorMsg);
} catch (IOException e4) {
String errorMsg = CommonUtil.getMessageFromThrowable(e4);
log.info(errorMsg);
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg(errorMsg);
} catch (Exception e) {
String errorMsg = CommonUtil.getMessageFromThrowable(e);
log.error(errorMsg, e);
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg(errorMsg);
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
}
@Override
public String supportProtocol() {
return DispatchConstants.PROTOCOL_SSL_CERT;
}
private void validateParams(Metrics metrics) throws Exception {
if (metrics == null || metrics.getHttp() == null) {
throw new Exception("Http/Https collect must has http params");
}
HttpProtocol httpProtocol = metrics.getHttp();
if (httpProtocol.getUrl() == null
|| "".equals(httpProtocol.getUrl())
|| !httpProtocol.getUrl().startsWith(RIGHT_DASH)) {
httpProtocol.setUrl(httpProtocol.getUrl() == null ? RIGHT_DASH : RIGHT_DASH + httpProtocol.getUrl().trim());
}
}
}
@@ -1,102 +0,0 @@
/*
* 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.dromara.hertzbeat.collector.collect.http.promethus;
import com.google.gson.JsonElement;
import org.dromara.hertzbeat.collector.dispatch.DispatchConstants;
import org.dromara.hertzbeat.collector.util.CollectUtil;
import org.dromara.hertzbeat.common.entity.dto.PromVectorOrMatrix;
import org.dromara.hertzbeat.common.entity.job.protocol.HttpProtocol;
import org.dromara.hertzbeat.common.entity.message.CollectRep;
import org.dromara.hertzbeat.common.constants.CommonConstants;
import org.dromara.hertzbeat.common.util.JsonUtil;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.util.List;
/**
*
*
* Processing prometheus returns a response format of type "matrix"
*/
@NoArgsConstructor
public class PrometheusMatrixParser extends AbstractPrometheusParse {
@Override
public Boolean checkType(String responseStr) {
try {
PromVectorOrMatrix promVectorOrMatrix = JsonUtil.fromJson(responseStr, PromVectorOrMatrix.class);
if (promVectorOrMatrix != null && promVectorOrMatrix.getData() != null) {
return DispatchConstants.PARSE_PROM_QL_MATRIX.equals(promVectorOrMatrix.getData().getResultType());
}
return false;
} catch (Exception e) {
return false;
}
}
@Override
public void parse(String resp, List<String> aliasFields, HttpProtocol http, CollectRep.MetricsData.Builder builder) {
PromVectorOrMatrix promVectorOrMatrix = JsonUtil.fromJson(resp, PromVectorOrMatrix.class);
if (promVectorOrMatrix == null){
return;
}
List<PromVectorOrMatrix.Result> result = promVectorOrMatrix.getData().getResult();
for (PromVectorOrMatrix.Result r : result) {
for (List<Object> value : r.getValues()) {
boolean setTimeFlag = false;
boolean setValueFlag = false;
CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder();
for (String aliasField : aliasFields) {
if (!CollectUtil.assertPromRequireField(aliasField)) {
JsonElement jsonElement = r.getMetric().get(aliasField);
if (jsonElement != null) {
valueRowBuilder.addColumns(jsonElement.getAsString());
} else {
valueRowBuilder.addColumns(CommonConstants.NULL_VALUE);
}
} else {
if (CommonConstants.PROM_TIME.equals(aliasField)) {
for (Object o : value) {
if (o instanceof Double) {
valueRowBuilder.addColumns(String.valueOf(BigDecimal.valueOf((Double) o * 1000)));
setTimeFlag = true;
}
}
if (!setTimeFlag) {
valueRowBuilder.addColumns(CommonConstants.NULL_VALUE);
}
} else {
for (Object o : value) {
if (o instanceof String) {
valueRowBuilder.addColumns((String) o);
setValueFlag = true;
}
}
if (!setValueFlag) {
valueRowBuilder.addColumns(CommonConstants.NULL_VALUE);
}
}
}
}
builder.addValues(valueRowBuilder);
}
}
}
}
@@ -1,45 +0,0 @@
/*
* 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.dromara.hertzbeat.collector.collect.http.promethus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
/**
* prometheus parse creater
*
*/
@Slf4j
@Component
public class PrometheusParseCreater implements InitializingBean {
private static AbstractPrometheusParse PROMETHEUSPARSE = new PrometheusVectorParser();
private static void create() {
PROMETHEUSPARSE.setInstance(new PrometheusMatrixParser().setInstance(new PrometheusLastParser()));
}
public static AbstractPrometheusParse getPrometheusParse(){
return PROMETHEUSPARSE;
}
@Override
public void afterPropertiesSet() throws Exception {
create();
}
}
@@ -1,99 +0,0 @@
/*
* 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.dromara.hertzbeat.collector.collect.http.promethus;
import com.google.gson.JsonElement;
import org.dromara.hertzbeat.collector.dispatch.DispatchConstants;
import org.dromara.hertzbeat.collector.util.CollectUtil;
import org.dromara.hertzbeat.common.entity.dto.PromVectorOrMatrix;
import org.dromara.hertzbeat.common.entity.job.protocol.HttpProtocol;
import org.dromara.hertzbeat.common.entity.message.CollectRep;
import org.dromara.hertzbeat.common.constants.CommonConstants;
import org.dromara.hertzbeat.common.util.JsonUtil;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.util.List;
/**
*
*
* Processing prometheus returns a response format of type "vector"
*/
@NoArgsConstructor
public class PrometheusVectorParser extends AbstractPrometheusParse {
@Override
public Boolean checkType(String responseStr) {
try {
PromVectorOrMatrix promVectorOrMatrix = JsonUtil.fromJson(responseStr, PromVectorOrMatrix.class);
if (promVectorOrMatrix != null && promVectorOrMatrix.getData() != null) {
return DispatchConstants.PARSE_PROM_QL_VECTOR.equals(promVectorOrMatrix.getData().getResultType());
}
return false;
} catch (Exception e) {
return false;
}
}
@Override
public void parse(String resp, List<String> aliasFields, HttpProtocol http, CollectRep.MetricsData.Builder builder) {
boolean setTimeFlag = false;
boolean setValueFlag = false;
PromVectorOrMatrix promVectorOrMatrix = JsonUtil.fromJson(resp, PromVectorOrMatrix.class);
if (promVectorOrMatrix == null){
return;
}
List<PromVectorOrMatrix.Result> result = promVectorOrMatrix.getData().getResult();
for (PromVectorOrMatrix.Result r : result) {
CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder();
for (String aliasField : aliasFields) {
if (!CollectUtil.assertPromRequireField(aliasField)) {
JsonElement jsonElement = r.getMetric().get(aliasField);
if (jsonElement != null) {
valueRowBuilder.addColumns(jsonElement.getAsString());
} else {
valueRowBuilder.addColumns(CommonConstants.NULL_VALUE);
}
} else {
if (CommonConstants.PROM_TIME.equals(aliasField)) {
for (Object o : r.getValue()) {
if (o instanceof Double) {
valueRowBuilder.addColumns(String.valueOf(BigDecimal.valueOf((Double) o * 1000)));
setTimeFlag = true;
}
}
if (!setTimeFlag) {
valueRowBuilder.addColumns(CommonConstants.NULL_VALUE);
}
} else {
for (Object o : r.getValue()) {
if (o instanceof String) {
valueRowBuilder.addColumns((String) o);
setValueFlag = true;
}
}
if (!setValueFlag) {
valueRowBuilder.addColumns(CommonConstants.NULL_VALUE);
}
}
}
}
builder.addValues(valueRowBuilder);
}
}
}
@@ -1,472 +0,0 @@
/*
* 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.dromara.hertzbeat.collector.collect.http.promethus.exporter;
import org.dromara.hertzbeat.collector.collect.http.promethus.ParseException;
import org.dromara.hertzbeat.common.util.StrBuffer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
*
*
* Resolves the data passed by prometheus's exporter interface http:xxx/metrics
* Reference: prometheus text_parse.go code, entry: TextToMetricFamilies
*/
@Slf4j
public class ExporterParser {
private static final String HELP = "HELP";
private static final String TYPE = "TYPE";
private static final String EOF = "EOF";
private static final String QUANTILE_LABEL = "quantile";
private static final String BUCKET_LABEL = "le";
private static final String NAME_LABEL = "__name__";
private static final String SUM_SUFFIX = "_sum";
private static final String COUNT_SUFFIX = "_count";
private static final char LEFT_CURLY_BRACKET = '{';
private static final char RIGHT_CURLY_BRACKET = '}';
private static final char EQUALS = '=';
private static final char QUOTES = '"';
private static final char ENTER = '\n';
private static final char SPACE = ' ';
private static final char COMMA = ',';
private MetricFamily currentMetricFamily;
private String currentQuantile;
private String currentBucket;
private final Lock lock = new ReentrantLock();
public Map<String, MetricFamily> textToMetric(String resp) {
// key: metric name, value: metric family
Map<String, MetricFamily> metricMap = new ConcurrentHashMap<>(10);
lock.lock();
try {
String[] lines = resp.split("\n");
for (String line : lines) {
this.parseLine(metricMap, new StrBuffer(line));
}
return metricMap;
} catch (Exception e) {
log.error("parse prometheus exporter data error, msg: {}", e.getMessage());
} finally {
lock.unlock();
}
return metricMap;
}
private void parseLine(Map<String, MetricFamily> metricMap, StrBuffer buffer) {
buffer.skipBlankTabs();
if (buffer.isEmpty()) return;
switch (buffer.charAt(0)) {
case '#':
buffer.read();
this.currentMetricFamily = null;
this.parseComment(metricMap, buffer);
break;
case ENTER:
break;
default:
this.currentBucket = null;
this.currentQuantile = null;
this.parseMetric(buffer);
}
}
private void parseComment(Map<String, MetricFamily> metricMap, StrBuffer buffer) {
buffer.skipBlankTabs();
if (buffer.isEmpty()) return;
String token = this.readTokenUnitWhitespace(buffer);
if (EOF.equals(token)) {
return;
}
if (!HELP.equals(token) && !TYPE.equals(token)) {
log.error("parse comment error {}, start without {} or {}", buffer.toStr(), HELP, TYPE);
return;
}
String metricName = this.readTokenAsMetricName(buffer);
this.currentMetricFamily = metricMap.computeIfAbsent(metricName, key -> new MetricFamily());
this.currentMetricFamily.setName(metricName);
switch (token) {
case HELP:
this.parseHelp(buffer);
break;
case TYPE:
this.parseType(buffer);
break;
default:
}
}
private void parseHelp(StrBuffer line) {
line.skipBlankTabs();
this.currentMetricFamily.setHelp(line.toStr());
}
private void parseType(StrBuffer line) {
line.skipBlankTabs();
String type = line.toStr().toLowerCase();
MetricType metricType = MetricType.getType(type);
if (metricType == null) {
throw new ParseException("pare type error");
}
this.currentMetricFamily.setMetricType(metricType);
}
private void parseMetric(StrBuffer buffer) {
String metricName = this.readTokenAsMetricName(buffer);
if (metricName.isEmpty()) {
log.error("error parse metric, metric name is null, line: {}", buffer.toStr());
return;
}
List<MetricFamily.Metric> metricList = this.currentMetricFamily.getMetricList();
if (metricList == null) {
metricList = new ArrayList<>();
this.currentMetricFamily.setMetricList(metricList);
}
// todo 这里可能存在问题, 目前逻辑是HISTOGRAM和SUMMARY只创建一个metric
// 相比源码有所改动: 源码通过属性存储解析结果; 这边通过参数传递
MetricFamily.Metric metric;
if (!metricList.isEmpty() &&
(this.currentMetricFamily.getMetricType().equals(MetricType.HISTOGRAM) ||
this.currentMetricFamily.getMetricType().equals(MetricType.SUMMARY))) {
metric = metricList.get(0);
} else {
metric = new MetricFamily.Metric();
metricList.add(metric);
}
this.readLabels(metric, buffer);
}
private void readLabels(MetricFamily.Metric metric, StrBuffer buffer) {
buffer.skipBlankTabs();
if (buffer.isEmpty()) return;
metric.setLabelPair(new ArrayList<>());
if (buffer.charAt(0) == LEFT_CURLY_BRACKET) {
buffer.read();
this.startReadLabelName(metric, buffer);
} else {
this.readLabelValue(metric, null, buffer);
}
}
private void startReadLabelName(MetricFamily.Metric metric, StrBuffer buffer) {
buffer.skipBlankTabs();
if (buffer.isEmpty()) return;
if (buffer.charAt(0) == RIGHT_CURLY_BRACKET) {
buffer.read();
buffer.skipBlankTabs();
if (buffer.isEmpty()) return;
this.readLabelValue(metric, new MetricFamily.Label(), buffer);
return;
}
String labelName = this.readTokenAsLabelName(buffer);
if (labelName.isEmpty() || labelName.equals(NAME_LABEL)) {
throw new ParseException("invalid label name" + labelName + ", label name size = 0 or label name equals " + NAME_LABEL);
}
MetricFamily.Label label = new MetricFamily.Label();
label.setName(labelName);
if (buffer.read() != EQUALS) {
throw new ParseException("parse error, not match the format of labelName=labelValue");
}
this.startReadLabelValue(metric, label, buffer);
}
private void startReadLabelValue(MetricFamily.Metric metric, MetricFamily.Label label, StrBuffer buffer) {
buffer.skipBlankTabs();
if (buffer.isEmpty()) return;
char c = buffer.read();
if (c != QUOTES) {
throw new ParseException("expected '\"' at start of label value, line: " + buffer.toStr());
}
String labelValue = this.readTokenAsLabelValue(buffer);
label.setValue(labelValue);
if (!this.isValidLabelValue(labelValue)) {
throw new ParseException("no valid label value: " + labelValue);
}
if (this.currentMetricFamily.getMetricType().equals(MetricType.SUMMARY) && label.getName().equals(QUANTILE_LABEL)) {
this.currentQuantile = labelValue;
} else if (this.currentMetricFamily.getMetricType().equals(MetricType.HISTOGRAM) && label.getName().equals(BUCKET_LABEL)) {
this.currentBucket = labelValue;
} else {
metric.getLabelPair().add(label);
}
if (buffer.isEmpty()) return;
c = buffer.read();
switch (c) {
case COMMA:
this.startReadLabelName(metric, buffer);
break;
case RIGHT_CURLY_BRACKET:
this.readLabelValue(metric, label, buffer);
break;
default:
throw new ParseException("expected '}' or ',' at end of label value, line: " + buffer.toStr());
}
}
private void readLabelValue(MetricFamily.Metric metric, MetricFamily.Label label, StrBuffer buffer) {
buffer.skipBlankTabs();
if (buffer.isEmpty()) return;
switch (this.currentMetricFamily.getMetricType()) {
case INFO:
MetricFamily.Info info = new MetricFamily.Info();
info.setValue(buffer.toDouble());
metric.setInfo(info);
break;
case COUNTER:
MetricFamily.Counter counter = new MetricFamily.Counter();
counter.setValue(buffer.toDouble());
metric.setCounter(counter);
break;
case GAUGE:
MetricFamily.Gauge gauge = new MetricFamily.Gauge();
gauge.setValue(buffer.toDouble());
metric.setGauge(gauge);
break;
case UNTYPED:
MetricFamily.Untyped untyped = new MetricFamily.Untyped();
untyped.setValue(buffer.toDouble());
metric.setUntyped(untyped);
break;
case SUMMARY:
MetricFamily.Summary summary = metric.getSummary();
if (summary == null) {
summary = new MetricFamily.Summary();
metric.setSummary(summary);
}
// 处理 xxx_sum 的数据
if (label != null && this.isSum(label.getName())) {
summary.setSum(buffer.toDouble());
}
// 处理 xxx_count 的数据
else if (label != null && this.isCount(label.getName())) {
summary.setCount(buffer.toLong());
}
// 处理 "xxx{quantile=\"0\"} 0" 的格式
else if (StringUtils.hasText(this.currentQuantile)) {
List<MetricFamily.Quantile> quantileList = summary.getQuantileList();
MetricFamily.Quantile quantile = new MetricFamily.Quantile();
quantile.setXLabel(StrBuffer.parseDouble(this.currentQuantile));
quantile.setValue(buffer.toDouble());
quantileList.add(quantile);
}
break;
case HISTOGRAM:
MetricFamily.Histogram histogram = metric.getHistogram();
if (histogram == null) {
histogram = new MetricFamily.Histogram();
metric.setHistogram(histogram);
}
if (label != null && this.isSum(label.getName())) {
histogram.setSum(buffer.toDouble());
} else if (label != null && this.isCount(label.getName())) {
histogram.setCount(buffer.toLong());
}
// 处理 "xxx{quantile=\"0\"} 0" 的格式
else if (StringUtils.hasText(this.currentBucket)) {
List<MetricFamily.Bucket> bucketList = histogram.getBucketList();
MetricFamily.Bucket bucket = new MetricFamily.Bucket();
bucket.setUpperBound(StrBuffer.parseDouble(this.currentBucket));
bucket.setCumulativeCount(buffer.toLong());
bucketList.add(bucket);
}
break;
default:
throw new ParseException("no such type in metricFamily");
}
}
/**
* 读取第一个空格符前的token
*
* @param buffer 行数据对象
* @return token unit
*/
private String readTokenUnitWhitespace(StrBuffer buffer) {
StringBuilder builder = new StringBuilder();
while (!buffer.isEmpty()) {
char c = buffer.read();
if (c == SPACE) {
break;
}
builder.append(c);
}
return builder.toString();
}
/**
* 获取指标的名称
*
* @param buffer 行数据对象
* @return token name
*/
private String readTokenAsMetricName(StrBuffer buffer) {
buffer.skipBlankTabs();
StringBuilder builder = new StringBuilder();
if (this.isValidMetricNameStart(buffer.charAt(0))) {
while (!buffer.isEmpty()) {
char c = buffer.read();
if (!this.isValidMetricNameContinuation(c)) {
buffer.rollback();
break;
}
builder.append(c);
}
return builder.toString();
}
throw new ParseException("parse metric name error");
}
/**
* 获取label的名称
*
* @param buffer 行数据对象
* @return label name
*/
private String readTokenAsLabelName(StrBuffer buffer) {
buffer.skipBlankTabs();
StringBuilder builder = new StringBuilder();
char c = buffer.read();
if (this.isValidLabelNameStart(c)) {
builder.append(c);
while (!buffer.isEmpty()) {
c = buffer.read();
if (!this.isValidLabelNameContinuation(c)) {
buffer.rollback();
break;
}
builder.append(c);
}
return builder.toString();
}
throw new ParseException("parse label name error");
}
/**
* 获取Label的值
*
* @param buffer 行数据对象
* @return label value
*/
private String readTokenAsLabelValue(StrBuffer buffer) {
StringBuilder builder = new StringBuilder();
boolean escaped = false;
while (!buffer.isEmpty()) {
char c = buffer.read();
// 处理 '\\' 转义
if (escaped) {
switch (c) {
case QUOTES:
case '\\':
builder.append(c);
break;
case 'n':
builder.append('\n');
break;
default:
throw new ParseException("parse label value error");
}
escaped = false;
} else {
switch (c) {
case QUOTES:
return builder.toString();
case ENTER:
throw new ParseException("parse label value error, next line");
case '\\':
escaped = true;
break;
default:
builder.append(c);
}
}
}
return builder.toString();
}
/**
* 是否符合metric name首字符规则
*
* @param c metric字符
* @return true/false
*/
private boolean isValidMetricNameStart(char c) {
return isValidLabelNameStart(c) || c == ':';
}
/**
* 是否符合metric name除首字符其他字符规则
*
* @param c metric字符
* @return true/false
*/
private boolean isValidMetricNameContinuation(char c) {
return isValidLabelNameContinuation(c) || c == ':';
}
/**
* 是否符合label name首字符规则
*
* @param c metric字符
* @return true/false
*/
private boolean isValidLabelNameStart(char c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
}
/**
* 是否符合label name除首字符其他字符规则
*
* @param c metric字符
* @return true/false
*/
private boolean isValidLabelNameContinuation(char c) {
return isValidLabelNameStart(c) || (c >= '0' && c <= '9');
}
/**
* 检测是否是有效的utf8编码的字符串
*
* @param s label value
* @return true/false
*/
private boolean isValidLabelValue(String s) {
return s != null && s.equals(new String(s.getBytes(StandardCharsets.UTF_8)));
}
private boolean isSum(String s) {
return s != null && s.endsWith(SUM_SUFFIX);
}
private boolean isCount(String s) {
return s != null && s.endsWith(COUNT_SUFFIX);
}
}
@@ -1,247 +0,0 @@
/*
* 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.dromara.hertzbeat.collector.collect.http.promethus.exporter;
import lombok.Data;
import lombok.ToString;
import java.util.ArrayList;
import java.util.List;
/**
*
*
*/
@Data
@ToString
public class MetricFamily {
/**
* 指标名称
* metric name
*/
private String name;
/**
* 指标描述
* metric help
*/
private String help;
/**
* 指标类型
* metric type
*/
private MetricType metricType;
/**
* 具体的指标
*/
private List<Metric> metricList;
/**
* Metric
*/
@Data
public static class Metric {
/**
* 标签数据, 主要对应{}内容
*/
private List<Label> labelPair;
/**
* info
*/
private Info info;
/**
* gauge
*/
private Gauge gauge;
/**
* counter
*/
private Counter counter;
/**
* summary
*/
private Summary summary;
/**
* untyped
*/
private Untyped untyped;
/**
* histogram
*/
private Histogram histogram;
/**
* timestampMs
*/
private Long timestampMs;
}
/**
* Label
*/
@Data
public static class Label {
/**
* name
*/
private String name;
/**
* value
*/
private String value;
}
/**
* Info
*/
@Data
public static class Info {
/**
* value
*/
private double value;
}
/**
* Counter
*/
@Data
public static class Counter {
/**
* value
*/
private double value;
// Exemplar
}
/**
* Gauge
*/
@Data
public static class Gauge {
/**
* value
*/
private double value;
}
/**
* untyped
*/
@Data
public static class Untyped {
/**
* value
*/
private double value;
}
/**
* Summary
*/
@Data
public static class Summary {
/**
* count
*/
private long count;
/**
* sum
*/
private double sum;
/**
* quantileList
*/
private List<Quantile> quantileList = new ArrayList<>();
}
/**
* Quantile
*/
@Data
public static class Quantile {
/**
* 对应 prometheus 的 quantile 字段
*/
private double xLabel;
/**
* value
*/
private double value;
}
/**
* Histogram
*/
@Data
public static class Histogram {
/**
* count
*/
private long count;
/**
* sum
*/
private double sum;
/**
* bucketList
*/
private List<Bucket> bucketList = new ArrayList<>();
}
/**
* Bucket
*/
@Data
public static class Bucket {
/**
* cumulativeCount
*/
private long cumulativeCount;
/**
* upperBound
*/
private double upperBound;
}
}
@@ -1,103 +0,0 @@
package org.dromara.hertzbeat.collector.collect.httpsd;
import com.ecwid.consul.transport.TransportException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.dromara.hertzbeat.collector.collect.AbstractCollect;
import org.dromara.hertzbeat.collector.collect.httpsd.discovery.DiscoveryClient;
import org.dromara.hertzbeat.collector.collect.httpsd.discovery.DiscoveryClientManagement;
import org.dromara.hertzbeat.collector.collect.httpsd.discovery.ServerInfo;
import org.dromara.hertzbeat.collector.dispatch.DispatchConstants;
import org.dromara.hertzbeat.common.constants.CollectorConstants;
import org.dromara.hertzbeat.common.constants.CommonConstants;
import org.dromara.hertzbeat.common.entity.job.Metrics;
import org.dromara.hertzbeat.common.entity.job.protocol.HttpsdProtocol;
import org.dromara.hertzbeat.common.entity.message.CollectRep;
import org.dromara.hertzbeat.common.util.CommonUtil;
import java.lang.reflect.Field;
import java.util.Objects;
/**
* http_sd protocol collection implementation
*
*/
@Slf4j
public class HttpsdImpl extends AbstractCollect {
private final static String SERVER = "server";
private final DiscoveryClientManagement discoveryClientManagement = new DiscoveryClientManagement();
@Override
public void collect(CollectRep.MetricsData.Builder builder, long monitorId, String app, Metrics metrics) {
HttpsdProtocol httpsdProtocol = metrics.getHttpsd();
// check params
if (checkParamsFailed(httpsdProtocol)) {
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg("http_sd collect must have a valid http_sd protocol param! ");
return;
}
try (DiscoveryClient discoveryClient = discoveryClientManagement.getClient(httpsdProtocol)) {
collectMetrics(builder, metrics, discoveryClient);
} catch (TransportException e1) {
String errorMsg = "Consul " + CommonUtil.getMessageFromThrowable(e1);
log.error(errorMsg);
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg(errorMsg);
} catch (Exception e) {
String errorMsg = CommonUtil.getMessageFromThrowable(e);
log.error(errorMsg, e);
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg(errorMsg);
}
}
private void collectMetrics(CollectRep.MetricsData.Builder builder, Metrics metrics, DiscoveryClient discoveryClient) {
long beginTime = System.currentTimeMillis();
// Available and Server monitor
if (StringUtils.equals(metrics.getName(), SERVER)) {
CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder();
ServerInfo serverInfo = discoveryClient.getServerInfo();
metrics.getAliasFields().forEach(fieldName -> {
if (StringUtils.equalsAnyIgnoreCase(CollectorConstants.RESPONSE_TIME, fieldName)) {
valueRowBuilder.addColumns(String.valueOf(System.currentTimeMillis() - beginTime));
}else {
addColumnIfMatched(fieldName, serverInfo, valueRowBuilder);
}
});
builder.addValues(valueRowBuilder.build());
}else {
// Service instances monitor
discoveryClient.getServices().forEach(serviceInstance -> {
CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder();
metrics.getAliasFields().forEach(fieldName -> addColumnIfMatched(fieldName, serviceInstance, valueRowBuilder));
builder.addValues(valueRowBuilder.build());
});
}
}
@Override
public String supportProtocol() {
return DispatchConstants.PROTOCOL_HTTP_SD;
}
private boolean checkParamsFailed(HttpsdProtocol httpsd) {
return Objects.isNull(httpsd) || httpsd.isInvalid();
}
private void addColumnIfMatched(String fieldName, Object sourceObj, CollectRep.ValueRow.Builder valueRowBuilder) {
String columnValue = null;
try {
Field declaredField = sourceObj.getClass().getDeclaredField(fieldName);
declaredField.setAccessible(Boolean.TRUE);
columnValue = (String) declaredField.get(sourceObj);
} catch (NoSuchFieldException | IllegalAccessException e) {
log.warn("No such field for {}", fieldName);
}
valueRowBuilder.addColumns(StringUtils.isBlank(columnValue)
? CommonConstants.NULL_VALUE
: columnValue);
}
}
@@ -1,29 +0,0 @@
package org.dromara.hertzbeat.collector.collect.httpsd.constant;
import org.apache.commons.lang3.StringUtils;
import java.util.Arrays;
/**
* Discovery Client Instance Name For Httpsd monitor
*
*/
public enum DiscoveryClientInstance {
CONSUL("Consul"),
NACOS("Nacos"),
NOT_SUPPORT("Not support discovery client instance! "),
;
private final String name;
DiscoveryClientInstance(String name) {
this.name = name;
}
public static DiscoveryClientInstance getByName(String clientInstanceName) {
return Arrays.stream(DiscoveryClientInstance.values())
.filter(instance -> StringUtils.equalsIgnoreCase(instance.name, clientInstanceName))
.findFirst()
.orElse(DiscoveryClientInstance.NOT_SUPPORT);
}
}
@@ -1,17 +0,0 @@
package org.dromara.hertzbeat.collector.collect.httpsd.discovery;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
/**
* Discovery Client Connect Config
*
*/
@Data
@Builder
@AllArgsConstructor
public class ConnectConfig {
private String host;
private int port;
}
@@ -1,18 +0,0 @@
package org.dromara.hertzbeat.collector.collect.httpsd.discovery;
import org.dromara.hertzbeat.common.entity.job.protocol.HttpsdProtocol;
import java.util.List;
/**
* DiscoveryClient interface
*/
public interface DiscoveryClient extends AutoCloseable {
ConnectConfig buildConnectConfig(HttpsdProtocol httpsdProtocol);
void initClient(ConnectConfig connectConfig);
ServerInfo getServerInfo();
List<ServiceInstance> getServices();
}
@@ -1,43 +0,0 @@
package org.dromara.hertzbeat.collector.collect.httpsd.discovery;
import org.dromara.hertzbeat.collector.collect.httpsd.constant.DiscoveryClientInstance;
import org.dromara.hertzbeat.collector.collect.httpsd.discovery.impl.ConsulDiscoveryClient;
import org.dromara.hertzbeat.collector.collect.httpsd.discovery.impl.NacosDiscoveryClient;
import org.dromara.hertzbeat.common.entity.job.protocol.HttpsdProtocol;
import java.util.Objects;
/**
* Discovery Client Management
*/
public class DiscoveryClientManagement {
public DiscoveryClient getClient(HttpsdProtocol httpsdProtocol) {
return createClient(httpsdProtocol, DiscoveryClientInstance.getByName(httpsdProtocol.getDiscoveryClientTypeName()));
}
private DiscoveryClient createClient(HttpsdProtocol httpsdProtocol, DiscoveryClientInstance discoveryClientInstance) {
if (Objects.equals(discoveryClientInstance, DiscoveryClientInstance.NOT_SUPPORT)) {
return null;
}
return doCreateClient(httpsdProtocol, discoveryClientInstance);
}
private DiscoveryClient doCreateClient(HttpsdProtocol httpsdProtocol, DiscoveryClientInstance discoveryClientInstance) {
DiscoveryClient discoveryClient;
switch (discoveryClientInstance) {
case CONSUL:
discoveryClient = new ConsulDiscoveryClient();
break;
case NACOS:
discoveryClient = new NacosDiscoveryClient();
break;
default:
return null;
}
discoveryClient.initClient(discoveryClient.buildConnectConfig(httpsdProtocol));
return discoveryClient;
}
}

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