mirror of
https://github.com/dromara/hertzbeat.git
synced 2026-09-17 18:19:02 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
abdf3df92c | ||
|
|
58360442ca | ||
|
|
0211a80f6b | ||
|
|
4d76c0abf4 | ||
|
|
f761e18739 | ||
|
|
6ac073a54e | ||
|
|
65a8d19c5d | ||
|
|
060b4d875d | ||
|
|
6c88c1ba03 | ||
|
|
8c58a35476 | ||
|
|
2ab05a5669 | ||
|
|
f3bc7f55c5 | ||
|
|
7effbc1f0d | ||
|
|
05e42182d9 | ||
|
|
5e69f4dfd0 | ||
|
|
aeb0083394 | ||
|
|
02f635bdd3 | ||
|
|
7dbcaaeda8 | ||
|
|
4ddf0a9f3f | ||
|
|
f1b1e3f7d6 | ||
|
|
921b8e5713 | ||
|
|
4009525f81 | ||
|
|
e0c7b4e111 | ||
|
|
5e01482caa | ||
|
|
028e2fbcbe | ||
|
|
d00cc6dcf4 | ||
|
|
4b7fdd6985 | ||
|
|
e45ec431aa | ||
|
|
8fa52fbca1 | ||
|
|
132fd00ab1 | ||
|
|
12ba2faa19 | ||
|
|
2f3abfbad4 | ||
|
|
95739d9114 | ||
|
|
428ae1f7d5 | ||
|
|
6509b8bfc6 | ||
|
|
783bd8de89 | ||
|
|
d1115b44d1 | ||
|
|
68e37d613a | ||
|
|
7db0df11ba | ||
|
|
e244bdc5a7 | ||
|
|
0b7aa487f0 | ||
|
|
59d8764dfb | ||
|
|
8a38a34965 | ||
|
|
fd7e1b0e05 | ||
|
|
5441838888 | ||
|
|
56b1dcb502 | ||
|
|
efbaf7feac | ||
|
|
7003b8a150 | ||
|
|
aed524a88b | ||
|
|
9b20ab8434 | ||
|
|
5c39b98eaa | ||
|
|
43ac859939 | ||
|
|
b5c2eca819 | ||
|
|
cd57f51892 | ||
|
|
a33966de9f | ||
|
|
4ff9452926 | ||
|
|
67da9bdbba | ||
|
|
8bb4493b43 | ||
|
|
92edd53f8c | ||
|
|
d70ad75dcc | ||
|
|
2e76c12fe1 | ||
|
|
7e158eb778 | ||
|
|
db23c94882 | ||
|
|
e905f36de2 | ||
|
|
037957dbe6 | ||
|
|
01d18f7935 | ||
|
|
88e350de1c | ||
|
|
07d22a8712 | ||
|
|
7847fd78b7 | ||
|
|
f7676ac8ca | ||
|
|
dd1cc700d9 | ||
|
|
d8dabe251a | ||
|
|
f2e647d777 | ||
|
|
7bac0245a2 | ||
|
|
d6e5399121 | ||
|
|
00076fc704 | ||
|
|
4a3d61bd9e | ||
|
|
af59b487e4 | ||
|
|
4cd3c3c97f | ||
|
|
69a21ffaa1 | ||
|
|
8ab71e672f | ||
|
|
7625a0b508 | ||
|
|
dc963833e8 | ||
|
|
87d4379efb | ||
|
|
bffd7c1d4f | ||
|
|
ba21ef5cdb | ||
|
|
3bf237a4eb | ||
|
|
19e7f128a3 | ||
|
|
5c409d7512 | ||
|
|
6bf20ba21a | ||
|
|
8c9b1f3f92 | ||
|
|
b3eb0083df | ||
|
|
e51accb3e6 | ||
|
|
a9e219811a | ||
|
|
51bdb56592 | ||
|
|
3562e870d8 | ||
|
|
6f9ee2f4e6 | ||
|
|
917c11f298 | ||
|
|
bf8d5b79bb | ||
|
|
7178c444f2 | ||
|
|
bc2dc1d567 | ||
|
|
9714123c98 | ||
|
|
8ca2f70153 | ||
|
|
126268f7ec | ||
|
|
12d1f4990d | ||
|
|
4b21df556c | ||
|
|
893d91c4f0 | ||
|
|
4236c438be | ||
|
|
6a64752af0 | ||
|
|
c5cce27cb4 | ||
|
|
364de609bf | ||
|
|
5d81c32f9d | ||
|
|
6aff6ed053 | ||
|
|
5ba09cf5c1 | ||
|
|
a746e35dcf | ||
|
|
a27777adcb | ||
|
|
4b7dfb4c8e | ||
|
|
ceda4a65f9 | ||
|
|
d4f6fc1ae8 | ||
|
|
e999360da8 | ||
|
|
948fcb739a | ||
|
|
cdf060e9ac | ||
|
|
1280c61af1 | ||
|
|
86ad10ad7b | ||
|
|
8961cf70a3 | ||
|
|
f31909a30d | ||
|
|
2df7e1d269 | ||
|
|
c10ebf0b60 | ||
|
|
1fe70a60cc | ||
|
|
3ea4c0e7da | ||
|
|
8228938bd1 | ||
|
|
5acaf4844a | ||
|
|
fc8be06ad5 | ||
|
|
509a9c9651 | ||
|
|
754b18c9ba | ||
|
|
8cdc92ab56 | ||
|
|
f0cb2af031 | ||
|
|
bd937bf7b8 | ||
|
|
8852713e4d | ||
|
|
12f4ecce01 | ||
|
|
ca9934ec81 | ||
|
|
eaaf589083 | ||
|
|
be84a0abae | ||
|
|
9a00f5a776 | ||
|
|
fb4626dd07 | ||
|
|
f28996255a | ||
|
|
0b79222bd0 | ||
|
|
120f3a12fe | ||
|
|
b8b1885657 | ||
|
|
caf13c09bd | ||
|
|
dca3e351ed | ||
|
|
6298e7ae90 | ||
|
|
4b2c3756b1 | ||
|
|
d32ec249b4 | ||
|
|
611ddc22e3 | ||
|
|
4373ab23f3 | ||
|
|
bff75757db | ||
|
|
50dd262fbf | ||
|
|
dc9743b7a5 | ||
|
|
8dc0fdee27 | ||
|
|
1267fcae5a | ||
|
|
afe68ba4f8 | ||
|
|
4da00d445b | ||
|
|
e3d09ef427 | ||
|
|
bb0a22c42f | ||
|
|
291f7cb351 | ||
|
|
ba4f1e35f8 | ||
|
|
32f8cd5188 | ||
|
|
1f22a610ce | ||
|
|
fac3f5b927 | ||
|
|
efa2dc3969 | ||
|
|
a0995d26ec | ||
|
|
4f18c2c930 | ||
|
|
739e678dd5 | ||
|
|
2856c3fe65 | ||
|
|
bad49ce17e | ||
|
|
64c68a4593 | ||
|
|
cc47db793f | ||
|
|
108cc4db5a | ||
|
|
7e3d009536 | ||
|
|
5dabc7b7fd | ||
|
|
f2eb663e02 | ||
|
|
ebe7a6f8fe | ||
|
|
163a5a05ed | ||
|
|
ec195c1dbf | ||
|
|
5fa88ec577 | ||
|
|
1e4dd6793e | ||
|
|
a811b9f6cb | ||
|
|
a8790c856b | ||
|
|
b9fdfbd50e | ||
|
|
85b4a4ef0c | ||
|
|
febc911639 | ||
|
|
001e76db4b | ||
|
|
ca27605640 | ||
|
|
06ce10ec3a | ||
|
|
1c17c7cb44 | ||
|
|
a34ccdd769 | ||
|
|
f5a8ebeeca | ||
|
|
6c36d1d60a | ||
|
|
90c027d6cc | ||
|
|
c30295cf9c | ||
|
|
bb0e2ea41c | ||
|
|
16f52d1b6e | ||
|
|
ff3139e1de | ||
|
|
65639da9c4 | ||
|
|
af0dc23b45 | ||
|
|
4b81ae4abf | ||
|
|
d5fdccf1d2 | ||
|
|
4d9900b56b | ||
|
|
dab66d4f16 | ||
|
|
cd028d8464 | ||
|
|
c4c56c6f85 | ||
|
|
6a852b2b8d | ||
|
|
c153433165 | ||
|
|
27175ef3ef | ||
|
|
c507f952de | ||
|
|
b00a50a469 | ||
|
|
98354f267e | ||
|
|
9080ccd2ba | ||
|
|
bd3420c4a7 | ||
|
|
7506429fc4 | ||
|
|
e9bfee6e7e | ||
|
|
b8a2e865cd | ||
|
|
83c5a3a08a | ||
|
|
4b7178af02 | ||
|
|
1841ed59d8 | ||
|
|
4080f5f068 | ||
|
|
25ee822c5f | ||
|
|
969c4a95c5 | ||
|
|
a15a106a46 | ||
|
|
74ed750860 | ||
|
|
ef377912ef | ||
|
|
cb11f11ace | ||
|
|
589b0d915d | ||
|
|
50a18f2813 | ||
|
|
86ca715a64 | ||
|
|
7b886fe72d | ||
|
|
9024b2aca2 | ||
|
|
5cd9590907 | ||
|
|
8e38b8ba9b | ||
|
|
47e632a088 | ||
|
|
4a691777aa | ||
|
|
ec92f4ee97 | ||
|
|
714f216470 | ||
|
|
16cb8f681c | ||
|
|
3ec150c586 | ||
|
|
31fcb0d839 | ||
|
|
3e1d87b59f | ||
|
|
2076693a16 | ||
|
|
7bb049f2df | ||
|
|
19955fa59a | ||
|
|
049c0937bc | ||
|
|
2763ee4dc4 | ||
|
|
497fc915c3 | ||
|
|
e945c42632 | ||
|
|
59398bd7c6 | ||
|
|
d49cb37c6f | ||
|
|
89be682a88 | ||
|
|
0d73ac6fc4 | ||
|
|
17636ed582 | ||
|
|
9cb50b7190 | ||
|
|
0e49e100d8 | ||
|
|
24678c2ca0 | ||
|
|
6074c08e1a | ||
|
|
3eb6fb35f4 | ||
|
|
466ac37e66 | ||
|
|
a5bc6327f9 | ||
|
|
2e9021a12d | ||
|
|
1dd08b8b19 | ||
|
|
6117396377 | ||
|
|
d71b9aa048 | ||
|
|
525980f919 | ||
|
|
6e430bcab6 | ||
|
|
12a53c69da | ||
|
|
1799e00ec9 | ||
|
|
5d416e855b | ||
|
|
5eef247a5b | ||
|
|
77f725cf42 | ||
|
|
b7969e78c9 | ||
|
|
2f4343c453 | ||
|
|
857e4118f0 | ||
|
|
c3ffad76ca | ||
|
|
102c72bcc6 | ||
|
|
88aeb9fc21 | ||
|
|
20f89f3b3b | ||
|
|
7facbe827c | ||
|
|
e3a1b8345f | ||
|
|
0f0f00c700 | ||
|
|
51699e34cd | ||
|
|
343afd517d | ||
|
|
b602d8ceb6 | ||
|
|
bad28bccdb | ||
|
|
eea68d2a27 | ||
|
|
fff291da82 | ||
|
|
97aada9956 | ||
|
|
d056ce2aa6 | ||
|
|
c2d92eb57d | ||
|
|
4dceb42dc7 | ||
|
|
1fac6ab2fa | ||
|
|
235df8bca1 | ||
|
|
603bc3222a | ||
|
|
a1d73a292c | ||
|
|
bdfffeec4c | ||
|
|
bc47768bfb | ||
|
|
98b03b62c7 | ||
|
|
ceab3023b1 | ||
|
|
a49fa3d91b | ||
|
|
5d87275206 | ||
|
|
a2bd61947b | ||
|
|
7ac21d3171 | ||
|
|
4fdc048287 | ||
|
|
e10e4b2d8d | ||
|
|
27d66a11c1 | ||
|
|
19c7d84e53 | ||
|
|
031e83d701 | ||
|
|
5b50307e8c | ||
|
|
4f7ba7355f | ||
|
|
4733ac2eba | ||
|
|
e157d82a18 | ||
|
|
f1a123ee76 | ||
|
|
584b70a726 | ||
|
|
9d62270131 | ||
|
|
53a506569a | ||
|
|
0ec6a3b6ba | ||
|
|
c8560e6b16 | ||
|
|
361e573d8e | ||
|
|
c12b4c0d84 | ||
|
|
9b065f7ec0 | ||
|
|
ffa81a68f7 | ||
|
|
ed21cc3a94 | ||
|
|
35616d2763 | ||
|
|
fbb74199c9 | ||
|
|
3a2350b86d | ||
|
|
b39602f15d | ||
|
|
86c7c2dadf | ||
|
|
ddfa60e597 | ||
|
|
e34b64062e | ||
|
|
0634e7bb2e | ||
|
|
0920910738 | ||
|
|
8ae4d0e2d3 | ||
|
|
1c5b3f9c3f | ||
|
|
a55a098983 | ||
|
|
a8c1c48390 | ||
|
|
9f7be0292a | ||
|
|
3250bc714d | ||
|
|
3d3d881722 | ||
|
|
3c01298e86 | ||
|
|
c650972f3d | ||
|
|
df4272a2f8 | ||
|
|
23d16ae921 | ||
|
|
aeac1ffed4 | ||
|
|
bac607f6dd | ||
|
|
8faa13e7b4 | ||
|
|
3113487192 | ||
|
|
7a7d4792cd | ||
|
|
ec8cc517d1 | ||
|
|
12fee7fb01 | ||
|
|
339a33a0bd | ||
|
|
e3a0fb4537 | ||
|
|
9b328ce34c | ||
|
|
e8dc6482ff | ||
|
|
c4fa738d65 | ||
|
|
6ac092dcd5 | ||
|
|
fe403ed880 | ||
|
|
d6b19691fb | ||
|
|
c2c00d44c7 | ||
|
|
e9da2d2925 | ||
|
|
58e6e1a2a7 | ||
|
|
0c2cc59b55 | ||
|
|
111f0f6b99 | ||
|
|
e560502d8e | ||
|
|
67983c2702 | ||
|
|
033240341b | ||
|
|
35a8ec4275 | ||
|
|
9ac45ab343 | ||
|
|
4b5a97044c | ||
|
|
477af0959f | ||
|
|
a5b8f59242 | ||
|
|
98b8d95b92 | ||
|
|
c0ef4a436e | ||
|
|
254421bc46 | ||
|
|
deb827a572 | ||
|
|
7eef0c21f1 | ||
|
|
58920978c3 | ||
|
|
a4c6a6045f | ||
|
|
6e47da758e | ||
|
|
ae03111a75 | ||
|
|
69b8db7048 | ||
|
|
de657f9144 | ||
|
|
822825b614 | ||
|
|
7672502c3d | ||
|
|
598ed2ea16 | ||
|
|
aee969a18a | ||
|
|
b0438da537 | ||
|
|
c85e182119 | ||
|
|
7446d3ebbf | ||
|
|
f6e8e64e23 | ||
|
|
2a3f4dfa80 | ||
|
|
3d99835487 | ||
|
|
3a7d5829ad | ||
|
|
51b1a9bdc7 | ||
|
|
181ca5aa5e | ||
|
|
a5c444a49a | ||
|
|
2784c8fa6b | ||
|
|
ae4a5b1c63 | ||
|
|
c7f4390638 | ||
|
|
c998d3b850 | ||
|
|
861e9d377f | ||
|
|
c1252fbe2b | ||
|
|
dce9a4b15e | ||
|
|
15768d8077 | ||
|
|
2824542037 | ||
|
|
f9bce29523 | ||
|
|
6b7dbd53f4 | ||
|
|
f5e88db841 | ||
|
|
82219d14df | ||
|
|
05bce69b84 | ||
|
|
bc49280c3c | ||
|
|
90035cac5d | ||
|
|
3487e4a16b | ||
|
|
974b27e878 | ||
|
|
22459c5b6f | ||
|
|
64e156be2a | ||
|
|
a9827bbcef | ||
|
|
0ed1355d76 | ||
|
|
0b81717a9e | ||
|
|
86ca62c67a | ||
|
|
7488dfadc9 | ||
|
|
50fe51bd95 | ||
|
|
8233a62aea | ||
|
|
7367b7315b | ||
|
|
9e305f7a59 | ||
|
|
3d9be220e6 | ||
|
|
659346ddd7 | ||
|
|
7f0b340663 | ||
|
|
a427099db7 | ||
|
|
d1d28e6763 | ||
|
|
ba70b2f269 | ||
|
|
2352ceef3d | ||
|
|
927625a79f | ||
|
|
16a6620ff6 | ||
|
|
a1d016e5d5 | ||
|
|
40aa5a4d73 | ||
|
|
aef7ac23c4 | ||
|
|
348b50c4c6 | ||
|
|
88538890b4 | ||
|
|
fa4a3fd9e1 | ||
|
|
3a24edb309 | ||
|
|
e142a498e2 | ||
|
|
f4685aa75a | ||
|
|
f038ec5326 | ||
|
|
06186c5ccc | ||
|
|
6c931956fa | ||
|
|
809f679375 | ||
|
|
b31d8b1380 | ||
|
|
1bba56bfbc | ||
|
|
357068cc8f | ||
|
|
8a88607be9 | ||
|
|
15e9bd0656 | ||
|
|
aa58f0af7f | ||
|
|
115f7b40c5 | ||
|
|
d2c19cbf95 | ||
|
|
173733784b | ||
|
|
df4115a64c | ||
|
|
8d34de4422 | ||
|
|
a482d24770 | ||
|
|
aee8481204 | ||
|
|
497338e00f | ||
|
|
e5236259ff | ||
|
|
712c54186e | ||
|
|
7aa3be8f7d | ||
|
|
f84e1fc5bf | ||
|
|
a8c1921fa3 | ||
|
|
43afb0bc63 | ||
|
|
ee9bdf6773 | ||
|
|
229b4158cc | ||
|
|
3d49b288bb | ||
|
|
e0caceda92 | ||
|
|
0b73e0900b | ||
|
|
1a09611ad6 | ||
|
|
be0de49646 | ||
|
|
061423d301 | ||
|
|
6421fef548 | ||
|
|
70af0669c6 | ||
|
|
55b3dd7f0c | ||
|
|
91111e5555 | ||
|
|
07913e7d51 | ||
|
|
38d466b7f8 | ||
|
|
9770c9321e | ||
|
|
7e5283ea0d | ||
|
|
8f659f0fd1 | ||
|
|
7a4ee880c3 | ||
|
|
3b323e1882 | ||
|
|
acc617f9bd | ||
|
|
5585993503 | ||
|
|
fd0e216818 | ||
|
|
999b37ec4f | ||
|
|
823430bca9 | ||
|
|
9a7e0411a1 | ||
|
|
3a2e0b3dd2 | ||
|
|
25d27880aa | ||
|
|
8a11dacdba | ||
|
|
467c595802 | ||
|
|
c70cc5d9b7 | ||
|
|
8f9143001f | ||
|
|
3e50b96322 | ||
|
|
9cf0e6f4ee | ||
|
|
d47d3be6b4 | ||
|
|
6cabe3ca0c | ||
|
|
874f7bdab3 | ||
|
|
f90d1e6242 | ||
|
|
afcb0c19fb | ||
|
|
0e7323fc04 | ||
|
|
feb60a7da9 | ||
|
|
2e7616cd56 | ||
|
|
2d53abdaab | ||
|
|
9fed2c8a36 | ||
|
|
a4db859eee | ||
|
|
9a3a2f0a54 | ||
|
|
da05b6a151 | ||
|
|
78621f2f14 | ||
|
|
a618ff00ea | ||
|
|
044c6d4bad | ||
|
|
53787cc215 | ||
|
|
d884278fed | ||
|
|
21a7788522 | ||
|
|
c7d192996a | ||
|
|
78ce1cdc1f | ||
|
|
12230b47ca | ||
|
|
753ea44d2b | ||
|
|
c3faea07c2 | ||
|
|
4149a027a7 | ||
|
|
65d69eb191 | ||
|
|
5e2e78fe95 | ||
|
|
e992da78cd | ||
|
|
2fd0090e83 | ||
|
|
a86fc85ffc | ||
|
|
f3cecea307 | ||
|
|
cbf6536923 | ||
|
|
336eaffd27 | ||
|
|
b9f8b7de72 | ||
|
|
5b44a95298 | ||
|
|
97e5435296 | ||
|
|
9b31fe785f | ||
|
|
f6fcd52a50 | ||
|
|
19a59004de | ||
|
|
f9b04ceb0c | ||
|
|
7ee227196d | ||
|
|
20f3b01251 | ||
|
|
9260bca057 | ||
|
|
6cdffbefac | ||
|
|
0699e89346 | ||
|
|
6222c51f41 | ||
|
|
ccbc7c698e | ||
|
|
b5c7705f4a | ||
|
|
eeba46af9f | ||
|
|
b4d0e77c99 | ||
|
|
1cb293ac03 | ||
|
|
2ffdda8f26 | ||
|
|
4f1c62fa3a | ||
|
|
bfe68d8a06 | ||
|
|
215271716d | ||
|
|
fafc6a8212 | ||
|
|
e860e63f62 | ||
|
|
702446190d | ||
|
|
7251fb4185 | ||
|
|
12bb21cb8d | ||
|
|
a7f30fc1f6 | ||
|
|
2cc779ce1c | ||
|
|
27c394d9f7 | ||
|
|
b25f1834e8 | ||
|
|
c878ac8fad | ||
|
|
0ebcffa408 | ||
|
|
5ef96061c9 | ||
|
|
c06f53c926 | ||
|
|
51765d8f9a | ||
|
|
1fe37d3789 | ||
|
|
baf2d5f536 | ||
|
|
5757d7427d | ||
|
|
cbb4b8c736 | ||
|
|
dbac0dfe63 | ||
|
|
8c0b39f69b | ||
|
|
a54d8cdd11 | ||
|
|
ec1c41cf68 | ||
|
|
93635a0482 | ||
|
|
59266ccb8a | ||
|
|
bc4b399a21 | ||
|
|
87756f16d9 | ||
|
|
e1cda5066e | ||
|
|
fa0e9ef50a | ||
|
|
a10c2bfbd8 | ||
|
|
33877615c5 | ||
|
|
13411105ed | ||
|
|
e2faa44f18 | ||
|
|
657de4f5b6 | ||
|
|
dfa6895a7e | ||
|
|
a9de486744 | ||
|
|
31d8712299 | ||
|
|
c4a6e36977 | ||
|
|
41c3bf50ee | ||
|
|
957cce93d9 | ||
|
|
9b7b00e09c | ||
|
|
b3976295f5 | ||
|
|
1be2631af7 | ||
|
|
5f5f4d0346 | ||
|
|
95c30f54cd | ||
|
|
855abf6ada | ||
|
|
bdf82751a5 | ||
|
|
f49e20535c | ||
|
|
a32757ea7a | ||
|
|
bd52e0527e | ||
|
|
1bac42b094 | ||
|
|
a71c61a0d8 | ||
|
|
56db540721 | ||
|
|
bc104dfe9f | ||
|
|
fc6ea4a2e0 | ||
|
|
55c48d167c | ||
|
|
393bb95878 | ||
|
|
915fcbf1d9 | ||
|
|
26b982a59b | ||
|
|
3186aa5eb6 | ||
|
|
a6ac326581 | ||
|
|
53b796ff57 | ||
|
|
b7217b5d48 | ||
|
|
b8f2bf30fd | ||
|
|
bc4ddefc76 | ||
|
|
2fcd100fec | ||
|
|
365de4657e | ||
|
|
d4e6317a30 | ||
|
|
cc19831f7c | ||
|
|
f10e5dbd06 | ||
|
|
af1f59e009 | ||
|
|
009a512ba0 | ||
|
|
dc381ea338 | ||
|
|
3ed52c54af | ||
|
|
c5808a0430 | ||
|
|
ed390a50c9 | ||
|
|
cfe93bf19d |
+412
-3
@@ -1652,7 +1652,8 @@
|
||||
"profile": "https://github.com/gjjjj0101",
|
||||
"contributions": [
|
||||
"code",
|
||||
"design"
|
||||
"design",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1829,7 +1830,7 @@
|
||||
},
|
||||
{
|
||||
"login": "Yanshuming1",
|
||||
"name": "xiaoming student",
|
||||
"name": "linDong",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/118667222?v=4",
|
||||
"profile": "https://github.com/Yanshuming1",
|
||||
"contributions": [
|
||||
@@ -1851,7 +1852,8 @@
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/119573640?v=4",
|
||||
"profile": "https://thespica.github.io/",
|
||||
"contributions": [
|
||||
"code"
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1889,6 +1891,413 @@
|
||||
"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,
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
@@ -20,6 +20,3 @@ contact_links:
|
||||
- name: Community Support
|
||||
url: https://github.com/apache/hertzbeat/discussions
|
||||
about: Please ask and answer questions here.
|
||||
- name: Security Bug Bounty
|
||||
url: https://github.com/apache/hertzbeat/issues
|
||||
about: Please report security vulnerabilities here.
|
||||
|
||||
@@ -53,4 +53,4 @@ body:
|
||||
validations:
|
||||
required: false
|
||||
- type: markdown
|
||||
value: "Please read the [Contribution Guideline](https://hertzbeat.apache.org/docs/others/contributing) before submitting the PR"
|
||||
value: "Please read the [Contribution Guideline](https://hertzbeat.apache.org/docs/community/contribution) before submitting the PR"
|
||||
|
||||
@@ -39,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
|
||||
|
||||
@@ -30,5 +30,5 @@ body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Please read the [Contribution Guideline](https://hertzbeat.apache.org/docs/others/contributing/) before submitting the PR
|
||||
Please read the [Contribution Guideline](https://hertzbeat.apache.org/docs/community/contribution) before submitting the PR
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ name: Backend CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master, dev ]
|
||||
branches: [ master, dev, action* ]
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- 'home/**'
|
||||
@@ -39,29 +39,45 @@ on:
|
||||
- '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 -Prelease --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
|
||||
|
||||
@@ -47,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
|
||||
|
||||
@@ -28,91 +28,37 @@ on:
|
||||
- 'home/**'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
docs-build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Check filename in home/blog
|
||||
- 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: |
|
||||
TARGET_DIR="./home/blog"
|
||||
invalid_files=()
|
||||
while IFS= read -r -d '' file; do
|
||||
filename=$(basename "$file")
|
||||
if [[ ! "$filename" =~ ^[_a-z0-9-]+(\.[_a-z0-9-]+)*$ ]]; then
|
||||
invalid_files+=("$file")
|
||||
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 < <(find "$TARGET_DIR" -type f -print0)
|
||||
if [ ${#invalid_files[@]} -ne 0 ]; then
|
||||
echo "Error: The following files have invalid names:(File name should only contain lowercase letters, numbers, and hyphens.)"
|
||||
for invalid_file in "${invalid_files[@]}"; do
|
||||
echo "$invalid_file"
|
||||
done
|
||||
exit 1
|
||||
else
|
||||
echo "All file names are valid."
|
||||
fi
|
||||
- name: Check filename in home/docs
|
||||
run: |
|
||||
TARGET_DIR="./home/docs"
|
||||
invalid_files=()
|
||||
while IFS= read -r -d '' file; do
|
||||
filename=$(basename "$file")
|
||||
if [[ ! "$filename" =~ ^[_a-z0-9-]+(\.[_a-z0-9-]+)*$ ]]; then
|
||||
invalid_files+=("$file")
|
||||
fi
|
||||
done < <(find "$TARGET_DIR" -type f -print0)
|
||||
if [ ${#invalid_files[@]} -ne 0 ]; then
|
||||
echo "Error: The following files have invalid names:(File name should only contain lowercase letters, numbers, and hyphens.)"
|
||||
for invalid_file in "${invalid_files[@]}"; do
|
||||
echo "$invalid_file"
|
||||
done
|
||||
exit 1
|
||||
else
|
||||
echo "All file names are valid."
|
||||
fi
|
||||
- name: Check filename in /zh-cn/docusaurus-plugin-content-blog
|
||||
run: |
|
||||
TARGET_DIR="./home/i18n/zh-cn/docusaurus-plugin-content-blog"
|
||||
invalid_files=()
|
||||
while IFS= read -r -d '' file; do
|
||||
filename=$(basename "$file")
|
||||
if [[ ! "$filename" =~ ^[_a-z0-9-]+(\.[_a-z0-9-]+)*$ ]]; then
|
||||
invalid_files+=("$file")
|
||||
fi
|
||||
done < <(find "$TARGET_DIR" -type f -print0)
|
||||
if [ ${#invalid_files[@]} -ne 0 ]; then
|
||||
echo "Error: The following files have invalid names:(File name should only contain lowercase letters, numbers, and hyphens.)"
|
||||
for invalid_file in "${invalid_files[@]}"; do
|
||||
echo "$invalid_file"
|
||||
done
|
||||
exit 1
|
||||
else
|
||||
echo "All file names are valid."
|
||||
fi
|
||||
- name: Check filename in /home/i18n/zh-cn/docusaurus-plugin-content-docs/current
|
||||
run: |
|
||||
TARGET_DIR="./home/i18n/zh-cn/docusaurus-plugin-content-docs/current"
|
||||
invalid_files=()
|
||||
while IFS= read -r -d '' file; do
|
||||
filename=$(basename "$file")
|
||||
if [[ ! "$filename" =~ ^[_a-z0-9-]+(\.[_a-z0-9-]+)*$ ]]; then
|
||||
invalid_files+=("$file")
|
||||
fi
|
||||
done < <(find "$TARGET_DIR" -type f -print0)
|
||||
if [ ${#invalid_files[@]} -ne 0 ]; then
|
||||
echo "Error: The following files have invalid names:(File name should only contain lowercase letters, numbers, and hyphens.)"
|
||||
for invalid_file in "${invalid_files[@]}"; do
|
||||
echo "$invalid_file"
|
||||
done
|
||||
exit 1
|
||||
else
|
||||
echo "All file names are valid."
|
||||
fi
|
||||
done
|
||||
|
||||
- name: NPM INSTALL
|
||||
working-directory: home
|
||||
run: npm install
|
||||
|
||||
- name: NPM BUILD
|
||||
working-directory: home
|
||||
run: npm run build
|
||||
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
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
|
||||
@@ -47,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
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- name: Yarn Install
|
||||
working-directory: web-app
|
||||
run: yarn
|
||||
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- name: Check license header
|
||||
|
||||
@@ -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
|
||||
+21
@@ -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
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
tasks:
|
||||
|
||||
- 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
|
||||
+4
-2
@@ -62,6 +62,8 @@ header:
|
||||
- '.stylelintrc'
|
||||
- '.prettierignore'
|
||||
- '.prettierrc.js'
|
||||
- '.gitpod.Dockerfile'
|
||||
- '.gitpod.yml'
|
||||
- 'karma.conf.js'
|
||||
- 'proxy.conf.js'
|
||||
- '.helmignore'
|
||||
@@ -92,12 +94,12 @@ header:
|
||||
- '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
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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/"
|
||||
]
|
||||
}
|
||||
+39
-34
@@ -38,7 +38,9 @@ Even small corrections to typos are very welcome :)
|
||||
|
||||
3. Execute under the project root directory: `mvn clean install -DskipTests`
|
||||
|
||||
4. Start `springboot manager` service: `manager/src/main/java/org/apache/hertzbeat/manager/Manager.java`
|
||||
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
|
||||
|
||||
@@ -68,23 +70,23 @@ Of course, if you have a good idea, you can also propose it directly on GitHub D
|
||||
|
||||
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.
|
||||
@@ -127,17 +129,17 @@ With the above steps, you are a contributor to HertzBeat. Repeat the previous st
|
||||
|
||||
[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.
|
||||
|
||||
Add WeChat account `tan-cloud` to pull you into the WeChat group.
|
||||
Add WeChat account `ahertzbeat` to pull you into the WeChat group.
|
||||
|
||||
## 🥐 Architecture
|
||||
|
||||
- **[manager](https://github.com/apache/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/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/apache/hertzbeat/tree/master/warehouse)** Provide monitoring data warehousing services.
|
||||
> Metrics data management, data query, calculation and statistics.
|
||||
- **[alerter](https://github.com/apache/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/apache/hertzbeat/tree/master/web-app)** Provide web ui.
|
||||
> Angular Web UI.
|
||||
@@ -189,7 +191,10 @@ Add WeChat account `tan-cloud` to pull you into the WeChat group.
|
||||
|
||||
3. 在项目根目录运行编译: `mvn clean install -DskipTests`
|
||||
|
||||
4. 启动`springboot manager`服务 `manager/src/main/java/org/apache/hertzbeat/manager/Manager.java`
|
||||
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`
|
||||
|
||||
|
||||
#### 前端启动
|
||||
|
||||
@@ -218,23 +223,23 @@ Add WeChat account `tan-cloud` to pull you into the WeChat group.
|
||||
|
||||
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 和其他贡献者进行代码审查。
|
||||
@@ -277,17 +282,17 @@ git pull upstream master
|
||||
|
||||
[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.
|
||||
|
||||
Add WeChat account `tan-cloud` to pull you into the WeChat group.
|
||||
Add WeChat account `ahertzbeat` to pull you into the WeChat group.
|
||||
|
||||
### 模块
|
||||
|
||||
- **[manager](https://github.com/apache/hertzbeat/tree/master/manager)** 提供监控管理,系统管理基础服务
|
||||
- **[manager](https://github.com/apache/hertzbeat/tree/master/hertzbeat-manager)** 提供监控管理,系统管理基础服务
|
||||
> 提供对监控的管理,监控应用配置的管理,系统用户租户后台管理等。
|
||||
- **[collector](https://github.com/apache/hertzbeat/tree/master/collector)** 提供监控数据采集服务
|
||||
> 使用通用协议远程采集获取对端指标数据。
|
||||
- **[warehouse](https://github.com/apache/hertzbeat/tree/master/warehouse)** 提供监控数据仓储服务
|
||||
> 采集指标结果数据管理,数据落盘,查询,计算统计。
|
||||
- **[alerter](https://github.com/apache/hertzbeat/tree/master/alerter)** 提供告警服务
|
||||
- **[alerter](https://github.com/apache/hertzbeat/tree/master/hertzbeat-alerter)** 提供告警服务
|
||||
> 告警计算触发,任务状态联动,告警配置,告警通知。
|
||||
- **[web-app](https://github.com/apache/hertzbeat/tree/master/web-app)** 提供可视化控制台页面
|
||||
> 监控告警系统可视化控制台前端
|
||||
|
||||
@@ -14,9 +14,11 @@
|
||||
[](https://www.reddit.com/r/hertzbeat/)
|
||||
[](https://twitter.com/hertzbeat1024)
|
||||
[](https://www.bestpractices.dev/projects/8139)
|
||||
[](https://hub.docker.com/repository/docker/apache/hertzbeat/general)
|
||||
[](https://app.codecov.io/gh/apache/hertzbeat)
|
||||
[](https://hub.docker.com/r/apache/hertzbeat)
|
||||
[](https://artifacthub.io/packages/search?repo=hertzbeat)
|
||||
[](https://www.youtube.com/channel/UCri75zfWX0GHqJFPENEbLow)
|
||||
[](https://gitpod.io/#https://github.com/apache/hertzbeat)
|
||||
|
||||
**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**
|
||||
@@ -58,42 +60,42 @@
|
||||
> Welcome everyone to contribute your customized general monitoring type YML template during use.
|
||||
|
||||
|
||||
- [Website](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-website.yml), [Port Telnet](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-port.yml),
|
||||
[Http Api](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-api.yml), [Ping Connect](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-ping.yml),
|
||||
[Jvm](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-jvm.yml), [SiteMap](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-fullsite.yml),
|
||||
[Ssl Certificate](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-ssl_cert.yml), [SpringBoot2](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-springboot2.yml),
|
||||
[FTP Server](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-ftp.yml), [SpringBoot3](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-springboot3.yml),
|
||||
[Udp Port](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-udp.yml), [Dns](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-dns.yml),
|
||||
[Pop3](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-pop3.yml), [Ntp](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-ntp.yml),
|
||||
[Api Code](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-api_code.yml), [Smtp](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-smtp.yml),
|
||||
[Nginx](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-nginx.yml)
|
||||
- [Mysql](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-mysql.yml), [PostgreSQL](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-postgresql.yml),
|
||||
[MariaDB](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-mariadb.yml), [Redis](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-redis.yml),
|
||||
[ElasticSearch](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-elasticsearch.yml), [SqlServer](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-sqlserver.yml),
|
||||
[Oracle](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-oracle.yml), [MongoDB](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-mongodb.yml),
|
||||
[DM](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-dm.yml), [OpenGauss](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-opengauss.yml),
|
||||
[ClickHouse](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-clickhouse.yml), [IoTDB](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-iotdb.yml),
|
||||
[Redis Cluster](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-redis_cluster.yml), [Redis Sentinel](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-redis_sentinel.yml)
|
||||
[Doris BE](https://github.com/apache/hertzbeat/blob/master/manager/src/main/resources/define/app-doris_be.yml), [Doris FE](https://github.com/apache/hertzbeat/blob/master/manager/src/main/resources/define/app-doris_fe.yml),
|
||||
[Memcached](https://github.com/apache/hertzbeat/blob/master/manager/src/main/resources/define/app-memcached.yml), [NebulaGraph](https://github.com/apache/hertzbeat/blob/master/manager/src/main/resources/define/app-nebulaGraph.yml)
|
||||
- [Linux](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-linux.yml), [Ubuntu](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-ubuntu.yml),
|
||||
[CentOS](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-centos.yml), [Windows](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-windows.yml),
|
||||
[EulerOS](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-euleros.yml), [Fedora CoreOS](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-coreos.yml),
|
||||
[OpenSUSE](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-opensuse.yml), [Rocky Linux](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-rockylinux.yml),
|
||||
[Red Hat](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-redhat.yml), [FreeBSD](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-freebsd.yml),
|
||||
[AlmaLinux](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-almalinux.yml), [Debian Linux](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-debian.yml)
|
||||
- [Tomcat](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-tomcat.yml), [Nacos](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-nacos.yml),
|
||||
[Zookeeper](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-zookeeper.yml), [RabbitMQ](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-rabbitmq.yml),
|
||||
[Flink](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-flink.yml), [Kafka](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-kafka.yml),
|
||||
[ShenYu](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-shenyu.yml), [DynamicTp](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-dynamic_tp.yml),
|
||||
[Jetty](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-jetty.yml), [ActiveMQ](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-activemq.yml),
|
||||
[Spring Gateway](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-spring_gateway.yml), [EMQX MQTT](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-emqx.yml),
|
||||
[AirFlow](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-airflow.yml), [Hive](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-hive.yml),
|
||||
[Spark](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-spark.yml), [Hadoop](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-hadoop.yml)
|
||||
- [Kubernetes](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-kubernetes.yml), [Docker](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-docker.yml)
|
||||
- [CiscoSwitch](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-cisco_switch.yml), [HpeSwitch](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-hpe_switch.yml),
|
||||
[HuaweiSwitch](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-huawei_switch.yml), [TpLinkSwitch](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-tplink_switch.yml),
|
||||
[H3cSwitch](https://raw.githubusercontent.com/apache/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`.
|
||||
|
||||
@@ -108,32 +110,36 @@
|
||||
|
||||
##### 1:Install 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 apache/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 apache/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
|
||||
```
|
||||
|
||||
- `-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)
|
||||
|
||||
##### 2:Install via package
|
||||
|
||||
1. Download the release package `hertzbeat-xx.tar.gz` [GITHUB Release](https://github.com/apache/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 [GITHUB Release](https://github.com/apache/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,19 +160,19 @@ Detailed config refer to [Install HertzBeat via Package](https://hertzbeat.apach
|
||||
##### 3:Start via source code
|
||||
|
||||
1. Local source code debugging needs to start the back-end project `manager` and the front-end project `web-app`.
|
||||
2. Backend:need `maven3+`, `java17`, `lombok`, start the `manager` service.
|
||||
2. Backend:need `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. Web:need `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)
|
||||
|
||||
##### 4:Install All(hertzbeat+mysql+tsdb) via Docker-compose
|
||||
##### 4:Install 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.
|
||||
|
||||
@@ -174,10 +180,6 @@ Detailed steps refer to [Artifact Hub](https://artifacthub.io/packages/helm/hert
|
||||
|
||||
**HAVE FUN**
|
||||
|
||||
## 🥐 Roadmap
|
||||
|
||||

|
||||
|
||||
## ✨ Contributors
|
||||
|
||||
Thanks to these wonderful people, welcome to join us:
|
||||
@@ -411,7 +413,7 @@ Thanks to these wonderful people, welcome to join us:
|
||||
<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></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>
|
||||
@@ -437,15 +439,74 @@ Thanks to these wonderful people, welcome to join us:
|
||||
<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="xiaoming student"/><br /><sub><b>xiaoming student</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/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></td>
|
||||
<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>
|
||||
@@ -463,7 +524,7 @@ Thanks to these wonderful people, welcome to join us:
|
||||
|
||||
[Chat On Discord](https://discord.gg/Fb6M73htGr)
|
||||
|
||||
WeChat Group : Add friend `tan-cloud` and invite to the group.
|
||||
WeChat Group : Add friend `ahertzbeat` and invite to the group.
|
||||
|
||||
WeChat Public : Search ID `usthecom`.
|
||||
|
||||
@@ -493,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
|
||||
|
||||
[](https://star-history.com/#apache/hertzbeat&Date)
|
||||
|
||||
|
||||
## 🛡️ License
|
||||
[`Apache License, Version 2.0`](https://www.apache.org/licenses/LICENSE-2.0.html)
|
||||
|
||||
+125
-70
@@ -14,9 +14,11 @@
|
||||
[](https://www.reddit.com/r/hertzbeat/)
|
||||
[](https://twitter.com/hertzbeat1024)
|
||||
[](https://www.bestpractices.dev/projects/8139)
|
||||
[](https://hub.docker.com/repository/docker/apache/hertzbeat/general)
|
||||
[](https://app.codecov.io/gh/apache/hertzbeat)
|
||||
[](https://hub.docker.com/r/apache/hertzbeat)
|
||||
[](https://artifacthub.io/packages/search?repo=hertzbeat)
|
||||
[](https://www.youtube.com/channel/UCri75zfWX0GHqJFPENEbLow)
|
||||
[](https://gitpod.io/#https://github.com/apache/hertzbeat)
|
||||
|
||||
|
||||
**官网: [hertzbeat.apache.org](https://hertzbeat.apache.org)**
|
||||
@@ -40,7 +42,7 @@
|
||||
|
||||
> `HertzBeat`的强大自定义,多类型支持,高性能,易扩展,低耦合,希望能帮助用户快速搭建自有监控系统。
|
||||
|
||||
----
|
||||
----
|
||||
|
||||

|
||||
|
||||
@@ -48,7 +50,7 @@
|
||||
|
||||

|
||||
|
||||
----
|
||||
----
|
||||
|
||||
## 🥐 模块
|
||||
|
||||
@@ -59,42 +61,42 @@
|
||||
> 我们将监控采集类型(mysql,jvm,k8s)都定义为 `yml` 监控模版,用户可以导入这些模版来支持对应类型的监控!
|
||||
> 欢迎大家一起贡献你使用过程中自定义的通用监控类型监控模版。
|
||||
|
||||
- [Website](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-website.yml), [Port Telnet](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-port.yml),
|
||||
[Http Api](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-api.yml), [Ping Connect](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-ping.yml),
|
||||
[Jvm](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-jvm.yml), [SiteMap](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-fullsite.yml),
|
||||
[Ssl Certificate](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-ssl_cert.yml), [SpringBoot2](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-springboot2.yml),
|
||||
[FTP Server](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-ftp.yml), [SpringBoot3](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-springboot3.yml),
|
||||
[Udp Port](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-udp.yml), [Dns](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-dns.yml),
|
||||
[Pop3](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-pop3.yml), [Ntp](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-ntp.yml),
|
||||
[Api Code](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-api_code.yml), [Smtp](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-smtp.yml),
|
||||
[Nginx](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-nginx.yml)
|
||||
- [Mysql](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-mysql.yml), [PostgreSQL](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-postgresql.yml),
|
||||
[MariaDB](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-mariadb.yml), [Redis](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-redis.yml),
|
||||
[ElasticSearch](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-elasticsearch.yml), [SqlServer](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-sqlserver.yml),
|
||||
[Oracle](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-oracle.yml), [MongoDB](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-mongodb.yml),
|
||||
[DM](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-dm.yml), [OpenGauss](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-opengauss.yml),
|
||||
[ClickHouse](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-clickhouse.yml), [IoTDB](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-iotdb.yml),
|
||||
[Redis Cluster](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-redis_cluster.yml), [Redis Sentinel](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-redis_sentinel.yml)
|
||||
[Doris BE](https://github.com/apache/hertzbeat/blob/master/manager/src/main/resources/define/app-doris_be.yml), [Doris FE](https://github.com/apache/hertzbeat/blob/master/manager/src/main/resources/define/app-doris_fe.yml),
|
||||
[Memcached](https://github.com/apache/hertzbeat/blob/master/manager/src/main/resources/define/app-memcached.yml), [NebulaGraph](https://github.com/apache/hertzbeat/blob/master/manager/src/main/resources/define/app-nebulaGraph.yml)
|
||||
- [Linux](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-linux.yml), [Ubuntu](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-ubuntu.yml),
|
||||
[CentOS](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-centos.yml), [Windows](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-windows.yml),
|
||||
[EulerOS](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-euleros.yml), [Fedora CoreOS](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-coreos.yml),
|
||||
[OpenSUSE](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-opensuse.yml), [Rocky Linux](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-rockylinux.yml),
|
||||
[Red Hat](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-redhat.yml), [FreeBSD](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-freebsd.yml),
|
||||
[AlmaLinux](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-almalinux.yml), [Debian Linux](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-debian.yml)
|
||||
- [Tomcat](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-tomcat.yml), [Nacos](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-nacos.yml),
|
||||
[Zookeeper](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-zookeeper.yml), [RabbitMQ](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-rabbitmq.yml),
|
||||
[Flink](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-flink.yml), [Kafka](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-kafka.yml),
|
||||
[ShenYu](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-shenyu.yml), [DynamicTp](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-dynamic_tp.yml),
|
||||
[Jetty](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-jetty.yml), [ActiveMQ](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-activemq.yml),
|
||||
[Spring Gateway](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-spring_gateway.yml), [EMQX MQTT](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-emqx.yml),
|
||||
[AirFlow](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-airflow.yml), [Hive](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-hive.yml),
|
||||
[Spark](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-spark.yml), [Hadoop](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-hadoop.yml)
|
||||
- [Kubernetes](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-kubernetes.yml), [Docker](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-docker.yml)
|
||||
- [CiscoSwitch](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-cisco_switch.yml), [HpeSwitch](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-hpe_switch.yml),
|
||||
[HuaweiSwitch](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-huawei_switch.yml), [TpLinkSwitch](https://raw.githubusercontent.com/apache/hertzbeat/master/manager/src/main/resources/define/app-tplink_switch.yml),
|
||||
[H3cSwitch](https://raw.githubusercontent.com/apache/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酱`。
|
||||
|
||||
@@ -109,30 +111,34 @@
|
||||
|
||||
1. `docker` 环境仅需一条命令即可开始
|
||||
|
||||
```docker run -d -p 1157:1157 -p 1158:1158 --name hertzbeat apache/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 apache/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.apache.org/docs/start/docker-deploy)
|
||||
|
||||
更多配置详细步骤参考 [通过 Docker 方式安装 HertzBeat](https://hertzbeat.apache.org/docs/start/docker-deploy)
|
||||
|
||||
##### 方式二:通过安装包安装
|
||||
|
||||
1. 下载您系统环境对应的安装包 `hertzbeat-xx.tar.gz` [GITHUB Release](https://github.com/apache/hertzbeat/releases)
|
||||
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` 到规划的另一台部署主机上 [GITHUB Release](https://github.com/apache/hertzbeat/releases)
|
||||
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:
|
||||
@@ -153,19 +159,19 @@ docker run -d -e IDENTITY=custom-collector-name -e MANAGER_HOST=127.0.0.1 -e MAN
|
||||
##### 方式三:本地代码启动
|
||||
|
||||
1. 此为前后端分离项目,本地代码调试需要分别启动后端工程 `manager` 和前端工程 `web-app`
|
||||
2. 后端:需要 `maven3+`, `java17` 和 `lombok` 环境,修改 `YML` 配置信息并启动 `manager` 服务
|
||||
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 集群中。
|
||||
|
||||
@@ -173,10 +179,6 @@ docker run -d -e IDENTITY=custom-collector-name -e MANAGER_HOST=127.0.0.1 -e MAN
|
||||
|
||||
**HAVE FUN**
|
||||
|
||||
## 🥐 路线图
|
||||
|
||||

|
||||
|
||||
## ✨ Contributors
|
||||
|
||||
Thanks these wonderful people, welcome to join us:
|
||||
@@ -410,7 +412,7 @@ Thanks these wonderful people, welcome to join us:
|
||||
<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></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>
|
||||
@@ -436,15 +438,74 @@ Thanks these wonderful people, welcome to join us:
|
||||
<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="xiaoming student"/><br /><sub><b>xiaoming student</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/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></td>
|
||||
<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>
|
||||
@@ -462,7 +523,7 @@ Thanks these wonderful people, welcome to join us:
|
||||
|
||||
[Chat On Discord](https://discord.gg/Fb6M73htGr)
|
||||
|
||||
微信交流群 : 加 `tan-cloud` 好友邀请进群.
|
||||
微信交流群 : 加 `ahertzbeat` 好友邀请进群.
|
||||
|
||||
微信公众号 : 搜索 ID `usthecom`.
|
||||
|
||||
@@ -494,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
|
||||
|
||||
[](https://star-history.com/#apache/hertzbeat&Date)
|
||||
|
||||
|
||||
## 🛡️ License
|
||||
[`Apache License, Version 2.0`](https://www.apache.org/licenses/LICENSE-2.0.html)
|
||||
|
||||
+9
-6
@@ -1,12 +1,9 @@
|
||||
# Security Policy
|
||||
|
||||
**[Version Releases](https://github.com/apache/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 report vulnerability disclosures to `security@apache.org`.
|
||||
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/)
|
||||
|
||||
@@ -1,87 +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.apache.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.apache.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>
|
||||
<!-- 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,68 +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.apache.hertzbeat.alert;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
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;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 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,482 +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.apache.hertzbeat.alert.calculate;
|
||||
|
||||
import static org.apache.hertzbeat.common.constants.CommonConstants.ALERT_STATUS_CODE_NOT_REACH;
|
||||
import static org.apache.hertzbeat.common.constants.CommonConstants.ALERT_STATUS_CODE_PENDING;
|
||||
import static org.apache.hertzbeat.common.constants.CommonConstants.ALERT_STATUS_CODE_SOLVED;
|
||||
import static org.apache.hertzbeat.common.constants.CommonConstants.TAG_CODE;
|
||||
import static org.apache.hertzbeat.common.constants.CommonConstants.TAG_METRIC;
|
||||
import static org.apache.hertzbeat.common.constants.CommonConstants.TAG_METRICS;
|
||||
import static org.apache.hertzbeat.common.constants.CommonConstants.TAG_MONITOR_APP;
|
||||
import static org.apache.hertzbeat.common.constants.CommonConstants.TAG_MONITOR_ID;
|
||||
import static org.apache.hertzbeat.common.constants.CommonConstants.TAG_MONITOR_NAME;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.jexl3.JexlException;
|
||||
import org.apache.commons.jexl3.JexlExpression;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.hertzbeat.alert.AlerterWorkerPool;
|
||||
import org.apache.hertzbeat.alert.dao.AlertMonitorDao;
|
||||
import org.apache.hertzbeat.alert.reduce.AlarmCommonReduce;
|
||||
import org.apache.hertzbeat.alert.service.AlertDefineService;
|
||||
import org.apache.hertzbeat.alert.service.AlertService;
|
||||
import org.apache.hertzbeat.alert.util.AlertTemplateUtil;
|
||||
import org.apache.hertzbeat.common.constants.CommonConstants;
|
||||
import org.apache.hertzbeat.common.entity.alerter.Alert;
|
||||
import org.apache.hertzbeat.common.entity.alerter.AlertDefine;
|
||||
import org.apache.hertzbeat.common.entity.manager.Monitor;
|
||||
import org.apache.hertzbeat.common.entity.manager.TagItem;
|
||||
import org.apache.hertzbeat.common.entity.message.CollectRep;
|
||||
import org.apache.hertzbeat.common.queue.CommonDataQueue;
|
||||
import org.apache.hertzbeat.common.support.event.MonitorDeletedEvent;
|
||||
import org.apache.hertzbeat.common.support.event.SystemConfigChangeEvent;
|
||||
import org.apache.hertzbeat.common.util.CommonUtil;
|
||||
import org.apache.hertzbeat.common.util.JexlExpressionRunner;
|
||||
import org.apache.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;
|
||||
|
||||
|
||||
/**
|
||||
* 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.MONITOR_DOWN_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(CommonConstants.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);
|
||||
// if the threshold is triggered, ignore other data rows
|
||||
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);
|
||||
} 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(TAG_MONITOR_ID, String.valueOf(monitorId));
|
||||
tags.put(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;
|
||||
JexlExpression expression;
|
||||
try {
|
||||
expression = JexlExpressionRunner.compile(expr);
|
||||
} catch (JexlException jexlException) {
|
||||
log.error("Alarm Rule: {} Compile Error: {}.", expr, jexlException.getMessage());
|
||||
throw jexlException;
|
||||
} catch (Exception e) {
|
||||
log.error("Alarm Rule: {} Unknown Error: {}.", expr, e.getMessage());
|
||||
throw e;
|
||||
}
|
||||
|
||||
try {
|
||||
match = (Boolean) JexlExpressionRunner.evaluate(expression, fieldValueMap);
|
||||
} catch (JexlException jexlException) {
|
||||
log.error("Alarm Rule: {} Run Error: {}.", expr, jexlException.getMessage());
|
||||
throw jexlException;
|
||||
} catch (Exception e) {
|
||||
log.error("Alarm 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(TAG_MONITOR_ID, String.valueOf(monitorId));
|
||||
tags.put(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,27 +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.apache.hertzbeat.alert.config;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
/**
|
||||
* Alert auto configuration.
|
||||
*/
|
||||
@ComponentScan(basePackages = "org.apache.hertzbeat.alert")
|
||||
public class AlerterAutoConfiguration {
|
||||
}
|
||||
-79
@@ -1,79 +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.apache.hertzbeat.alert.controller;
|
||||
|
||||
import static org.apache.hertzbeat.common.constants.CommonConstants.MONITOR_NOT_EXIST_CODE;
|
||||
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import org.apache.hertzbeat.alert.service.AlertConvergeService;
|
||||
import org.apache.hertzbeat.common.entity.alerter.AlertConverge;
|
||||
import org.apache.hertzbeat.common.entity.dto.Message;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Alarm Converge management API
|
||||
*/
|
||||
@Tag(name = "Alert Converge 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")
|
||||
public ResponseEntity<Message<AlertConverge>> getAlertConverge(
|
||||
@Parameter(description = "Alarm Converge 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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-106
@@ -1,106 +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.apache.hertzbeat.alert.controller;
|
||||
|
||||
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import org.apache.hertzbeat.alert.service.AlertConvergeService;
|
||||
import org.apache.hertzbeat.common.entity.alerter.AlertConverge;
|
||||
import org.apache.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.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* Converge the batch API for alarms
|
||||
*/
|
||||
@Tag(name = "Alert Converge Batch 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", 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", example = "id") @RequestParam(defaultValue = "id") String sort,
|
||||
@Parameter(description = "Sort mode: asc: ascending, desc: descending", 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")
|
||||
public ResponseEntity<Message<Void>> deleteAlertDefines(
|
||||
@Parameter(description = "Alarm Converge IDs", example = "6565463543") @RequestParam(required = false) List<Long> ids
|
||||
) {
|
||||
if (ids != null && !ids.isEmpty()) {
|
||||
alertConvergeService.deleteAlertConverges(new HashSet<>(ids));
|
||||
}
|
||||
return ResponseEntity.ok(Message.success());
|
||||
}
|
||||
|
||||
}
|
||||
-116
@@ -1,116 +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.apache.hertzbeat.alert.controller;
|
||||
|
||||
import static org.apache.hertzbeat.common.constants.CommonConstants.MONITOR_NOT_EXIST_CODE;
|
||||
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import org.apache.hertzbeat.alert.service.AlertDefineService;
|
||||
import org.apache.hertzbeat.common.entity.alerter.AlertDefine;
|
||||
import org.apache.hertzbeat.common.entity.alerter.AlertDefineMonitorBind;
|
||||
import org.apache.hertzbeat.common.entity.dto.Message;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Alarm definition management API
|
||||
*/
|
||||
@Tag(name = "Alert Define 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")
|
||||
public ResponseEntity<Message<AlertDefine>> getAlertDefine(
|
||||
@Parameter(description = "Alarm Definition 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")
|
||||
public ResponseEntity<Message<Void>> deleteAlertDefine(
|
||||
@Parameter(description = "Alarm Definition 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", 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", 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));
|
||||
}
|
||||
|
||||
}
|
||||
-145
@@ -1,145 +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.apache.hertzbeat.alert.controller;
|
||||
|
||||
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
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 org.apache.hertzbeat.alert.service.AlertDefineService;
|
||||
import org.apache.hertzbeat.common.entity.alerter.AlertDefine;
|
||||
import org.apache.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.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* Define the batch API for alarms
|
||||
*/
|
||||
@Tag(name = "Alert Define Batch 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", 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", example = "id") @RequestParam(defaultValue = "id") String sort,
|
||||
@Parameter(description = "Sort mode: asc: ascending, desc: descending", 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")
|
||||
public ResponseEntity<Message<Void>> deleteAlertDefines(
|
||||
@Parameter(description = "Alarm Definition 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 = "export alarm definition configuration")
|
||||
public void export(
|
||||
@Parameter(description = "AlertDefine ID List", 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 = "import alarm definition configuration")
|
||||
public ResponseEntity<Message<Void>> importDefines(MultipartFile file) throws Exception {
|
||||
alertDefineService.importConfig(file);
|
||||
return ResponseEntity.ok(Message.success("Import success"));
|
||||
}
|
||||
}
|
||||
-102
@@ -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.apache.hertzbeat.alert.controller;
|
||||
|
||||
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import java.util.Date;
|
||||
import java.util.Optional;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.alert.dto.CloudAlertReportAbstract;
|
||||
import org.apache.hertzbeat.alert.dto.GeneralCloudAlertReport;
|
||||
import org.apache.hertzbeat.alert.enums.CloudServiceAlarmInformationEnum;
|
||||
import org.apache.hertzbeat.alert.service.AlertService;
|
||||
import org.apache.hertzbeat.common.entity.dto.AlertReport;
|
||||
import org.apache.hertzbeat.common.entity.dto.Message;
|
||||
import org.apache.hertzbeat.common.util.JsonUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* Extern Alarm Manage API
|
||||
*/
|
||||
@Tag(name = "Extern Alarm Manage 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 {
|
||||
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("[alert report] parse cloud service alarm content failed! cloud service: {} conrent: {}",
|
||||
cloudService.name(), alertReport);
|
||||
}
|
||||
} else {
|
||||
alert = AlertReport.builder()
|
||||
.content("error do not has cloud service 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 = "The interface is used to report external and general alarm information")
|
||||
public ResponseEntity<Message<Void>> addNewAlertReport(@RequestBody GeneralCloudAlertReport alertReport) {
|
||||
alertReport.refreshAlertTime();
|
||||
alertService.addNewAlertReport(alertReport);
|
||||
return ResponseEntity.ok(Message.success("Add report success"));
|
||||
}
|
||||
}
|
||||
-108
@@ -1,108 +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.apache.hertzbeat.alert.controller;
|
||||
|
||||
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import org.apache.hertzbeat.alert.service.AlertSilenceService;
|
||||
import org.apache.hertzbeat.common.entity.alerter.AlertSilence;
|
||||
import org.apache.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.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* Silence the batch API for alarms
|
||||
*/
|
||||
@Tag(name = "Alert Silence Batch 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", 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", example = "id") @RequestParam(defaultValue = "id") String sort,
|
||||
@Parameter(description = "Sort mode: asc: ascending, desc: descending", 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")
|
||||
public ResponseEntity<Message<Void>> deleteAlertDefines(
|
||||
@Parameter(description = "Alarm Silence 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,146 +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.apache.hertzbeat.alert.controller;
|
||||
|
||||
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import org.apache.hertzbeat.alert.dto.AlertSummary;
|
||||
import org.apache.hertzbeat.alert.service.AlertService;
|
||||
import org.apache.hertzbeat.common.entity.alerter.Alert;
|
||||
import org.apache.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.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* Alarm Management API
|
||||
*/
|
||||
@Tag(name = "Alarm Manage Batch 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 = "according to the query filter items to obtain a list of alarm information")
|
||||
public ResponseEntity<Message<Page<Alert>>> getAlerts(
|
||||
@Parameter(description = "Alarm ID List", example = "6565466456") @RequestParam(required = false) List<Long> ids,
|
||||
@Parameter(description = "Alarm monitor object 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", example = "name") @RequestParam(defaultValue = "id") String sort,
|
||||
@Parameter(description = "Sort Type", 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 = "according to the alarm ID list to delete the alarm information in batches")
|
||||
public ResponseEntity<Message<Void>> deleteAlerts(
|
||||
@Parameter(description = "Alarm List ID", 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 = "delete all alarm information")
|
||||
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 = "Batch modify alarm status, set read and unread")
|
||||
public ResponseEntity<Message<Void>> applyAlertDefinesStatus(
|
||||
@Parameter(description = "Alarm status value", example = "0") @PathVariable Byte status,
|
||||
@Parameter(description = "Alarm List 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 = "Get alarm statistics information")
|
||||
public ResponseEntity<Message<AlertSummary>> getAlertsSummary() {
|
||||
AlertSummary alertSummary = alertService.getAlertsSummary();
|
||||
Message<AlertSummary> message = Message.success(alertSummary);
|
||||
return ResponseEntity.ok(message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,37 +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.apache.hertzbeat.alert.dao;
|
||||
|
||||
import java.util.Set;
|
||||
import org.apache.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;
|
||||
|
||||
/**
|
||||
* 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,56 +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.apache.hertzbeat.alert.dao;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.apache.hertzbeat.alert.dto.AlertPriorityNum;
|
||||
import org.apache.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;
|
||||
|
||||
/**
|
||||
* 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.apache.hertzbeat.alert.dto.AlertPriorityNum(mo.priority, count(mo.id)) from Alert mo where mo.status = 0 group by mo.priority")
|
||||
List<AlertPriorityNum> findAlertPriorityNum();
|
||||
}
|
||||
@@ -1,67 +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.apache.hertzbeat.alert.dao;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.apache.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;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @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.apache.hertzbeat.alert.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import java.util.Map;
|
||||
import org.apache.hertzbeat.common.entity.dto.AlertReport;
|
||||
|
||||
/**
|
||||
* Abstract parent of cloud service alarm information
|
||||
* {@link 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,79 +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.apache.hertzbeat.alert.dto;
|
||||
|
||||
import java.util.Optional;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.hertzbeat.alert.util.DateUtil;
|
||||
import org.apache.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)) {
|
||||
Optional<Long> tsf = DateUtil.getTimeStampFromFormat(alertDateTime, dateTimeFormat);
|
||||
boolean present = tsf.isPresent();
|
||||
if (present) {
|
||||
timeStamp = tsf.get();
|
||||
}
|
||||
}
|
||||
if (timeStamp == null) {
|
||||
Optional<Long> tsf = DateUtil.getTimeStampFromSomeFormats(alertDateTime);
|
||||
boolean present = tsf.isPresent();
|
||||
if (present) {
|
||||
timeStamp = tsf.get();
|
||||
}
|
||||
}
|
||||
if (timeStamp != null) {
|
||||
setAlertTime(timeStamp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("parse alarm time error");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,229 +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.apache.hertzbeat.alert.dto;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.apache.hertzbeat.alert.util.DateUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
* 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 {
|
||||
// alarm metrics parameters
|
||||
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;
|
||||
|
||||
// alarm event parameters
|
||||
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")
|
||||
.orElse(0L);
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
-52
@@ -1,52 +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.apache.hertzbeat.alert.enums;
|
||||
|
||||
import java.util.Arrays;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.apache.hertzbeat.alert.dto.CloudAlertReportAbstract;
|
||||
import org.apache.hertzbeat.alert.dto.TenCloudAlertReport;
|
||||
|
||||
/**
|
||||
* 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,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.apache.hertzbeat.alert.reduce;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.alert.dao.AlertMonitorDao;
|
||||
import org.apache.hertzbeat.common.constants.CommonConstants;
|
||||
import org.apache.hertzbeat.common.entity.alerter.Alert;
|
||||
import org.apache.hertzbeat.common.entity.manager.Tag;
|
||||
import org.apache.hertzbeat.common.queue.CommonDataQueue;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 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.getTagValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
// converge -> silence
|
||||
if (alarmConvergeReduce.filterConverge(alert) && alarmSilenceReduce.filterSilence(alert)) {
|
||||
dataQueue.sendAlertsData(alert);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.apache.hertzbeat.alert.reduce;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import org.apache.hertzbeat.alert.dao.AlertConvergeDao;
|
||||
import org.apache.hertzbeat.common.cache.CacheFactory;
|
||||
import org.apache.hertzbeat.common.cache.CommonCacheService;
|
||||
import org.apache.hertzbeat.common.constants.CommonConstants;
|
||||
import org.apache.hertzbeat.common.entity.alerter.Alert;
|
||||
import org.apache.hertzbeat.common.entity.alerter.AlertConverge;
|
||||
import org.apache.hertzbeat.common.entity.manager.TagItem;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 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() * 1000L;
|
||||
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,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.apache.hertzbeat.alert.reduce;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.hertzbeat.alert.dao.AlertSilenceDao;
|
||||
import org.apache.hertzbeat.common.cache.CacheFactory;
|
||||
import org.apache.hertzbeat.common.cache.CommonCacheService;
|
||||
import org.apache.hertzbeat.common.constants.CommonConstants;
|
||||
import org.apache.hertzbeat.common.entity.alerter.Alert;
|
||||
import org.apache.hertzbeat.common.entity.alerter.AlertSilence;
|
||||
import org.apache.hertzbeat.common.entity.manager.TagItem;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 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,75 +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.apache.hertzbeat.alert.service;
|
||||
|
||||
import java.util.Set;
|
||||
import org.apache.hertzbeat.common.entity.alerter.AlertConverge;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
|
||||
/**
|
||||
* 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,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.apache.hertzbeat.alert.service;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.apache.hertzbeat.common.entity.alerter.AlertDefine;
|
||||
import org.apache.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;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @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
|
||||
* @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
|
||||
* @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
|
||||
* @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,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.apache.hertzbeat.alert.service;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import org.apache.hertzbeat.alert.dto.AlertSummary;
|
||||
import org.apache.hertzbeat.common.entity.alerter.Alert;
|
||||
import org.apache.hertzbeat.common.entity.dto.AlertReport;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @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
|
||||
* @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);
|
||||
}
|
||||
-83
@@ -1,83 +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.apache.hertzbeat.alert.service.impl;
|
||||
|
||||
import java.util.Set;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.alert.dao.AlertConvergeDao;
|
||||
import org.apache.hertzbeat.alert.service.AlertConvergeService;
|
||||
import org.apache.hertzbeat.common.cache.CacheFactory;
|
||||
import org.apache.hertzbeat.common.cache.CommonCacheService;
|
||||
import org.apache.hertzbeat.common.constants.CommonConstants;
|
||||
import org.apache.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;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
-151
@@ -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.apache.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 jakarta.annotation.Resource;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.alert.service.AlertDefineImExportService;
|
||||
import org.apache.hertzbeat.alert.service.AlertDefineService;
|
||||
import org.apache.hertzbeat.common.entity.alerter.AlertDefine;
|
||||
import org.apache.hertzbeat.common.entity.manager.TagItem;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* Configuration Import Export
|
||||
*/
|
||||
@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 input stream
|
||||
* @return form list
|
||||
*/
|
||||
abstract List<ExportAlertDefineDTO> parseImport(InputStream is);
|
||||
|
||||
/**
|
||||
* Export Configuration to Output Stream
|
||||
* @param exportAlertDefineList configuration list
|
||||
* @param os output stream
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
-265
@@ -1,265 +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.apache.hertzbeat.alert.service.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.common.entity.manager.TagItem;
|
||||
import org.apache.hertzbeat.common.util.JsonUtil;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.CellType;
|
||||
import org.apache.poi.ss.usermodel.Font;
|
||||
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Configure the import and export EXCEL format
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class AlertDefineExcelImExportServiceImpl extends AlertDefineAbstractImExportServiceImpl {
|
||||
public static final String TYPE = "EXCEL";
|
||||
public static final String FILE_SUFFIX = ".xlsx";
|
||||
|
||||
/**
|
||||
* Export file type
|
||||
* @return file type
|
||||
*/
|
||||
@Override
|
||||
public String type() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Export File Name
|
||||
* @return file name
|
||||
*/
|
||||
@Override
|
||||
public String getFileName() {
|
||||
return fileNamePrefix() + FILE_SUFFIX;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parsing an input stream into a form
|
||||
* @param is input stream
|
||||
* @return form list
|
||||
*/
|
||||
@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<>() {
|
||||
});
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private String getCellValueAsString(Cell cell) {
|
||||
if (cell == null) {
|
||||
return null;
|
||||
}
|
||||
return switch (cell.getCellType()) {
|
||||
case STRING -> cell.getStringCellValue();
|
||||
case NUMERIC -> String.valueOf(cell.getNumericCellValue());
|
||||
default -> 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 exportAlertDefineList
|
||||
* @param os output stream
|
||||
*/
|
||||
@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);
|
||||
// set header style
|
||||
CellStyle headerCellStyle = workbook.createCellStyle();
|
||||
Font headerFont = workbook.createFont();
|
||||
headerFont.setBold(true);
|
||||
headerCellStyle.setFont(headerFont);
|
||||
headerCellStyle.setAlignment(HorizontalAlignment.CENTER);
|
||||
// set cell style
|
||||
CellStyle cellStyle = workbook.createCellStyle();
|
||||
cellStyle.setAlignment(HorizontalAlignment.CENTER);
|
||||
// set header
|
||||
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);
|
||||
}
|
||||
|
||||
// Traverse the threshold rule list, each threshold rule object corresponds to a row of data
|
||||
int rowIndex = 1;
|
||||
for (ExportAlertDefineDTO alertDefine : exportAlertDefineList) {
|
||||
AlertDefineDTO alertDefineDTO = alertDefine.getAlertDefine();
|
||||
Row row = sheet.createRow(rowIndex++);
|
||||
// Threshold rule information only needs to be written once
|
||||
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);
|
||||
// get tags
|
||||
List<TagItem> tagList = alertDefineDTO.getTags();
|
||||
String tagValue = tagList == null || tagList.isEmpty() ? "" : 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
-189
@@ -1,189 +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.apache.hertzbeat.alert.service.impl;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.alert.dao.AlertDefineBindDao;
|
||||
import org.apache.hertzbeat.alert.dao.AlertDefineDao;
|
||||
import org.apache.hertzbeat.alert.service.AlertDefineImExportService;
|
||||
import org.apache.hertzbeat.alert.service.AlertDefineService;
|
||||
import org.apache.hertzbeat.common.entity.alerter.AlertDefine;
|
||||
import org.apache.hertzbeat.common.entity.alerter.AlertDefineMonitorBind;
|
||||
import org.apache.hertzbeat.common.util.JexlExpressionRunner;
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
JexlExpressionRunner.compile(alertDefine.getExpr());
|
||||
} 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
|
||||
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
|
||||
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());
|
||||
}
|
||||
}
|
||||
-65
@@ -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.apache.hertzbeat.alert.service.impl;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.yaml.snakeyaml.DumperOptions;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
/**
|
||||
* Configure the import and export Yaml format
|
||||
*/
|
||||
@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,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.apache.hertzbeat.alert.service.impl;
|
||||
|
||||
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;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.alert.dao.AlertDao;
|
||||
import org.apache.hertzbeat.alert.dto.AlertPriorityNum;
|
||||
import org.apache.hertzbeat.alert.dto.AlertSummary;
|
||||
import org.apache.hertzbeat.alert.reduce.AlarmCommonReduce;
|
||||
import org.apache.hertzbeat.alert.service.AlertService;
|
||||
import org.apache.hertzbeat.common.constants.CommonConstants;
|
||||
import org.apache.hertzbeat.common.entity.alerter.Alert;
|
||||
import org.apache.hertzbeat.common.entity.dto.AlertReport;
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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());
|
||||
case CommonConstants.ALERT_PRIORITY_CODE_CRITICAL -> alertSummary.setPriorityCriticalNum(priorityNum.getNum());
|
||||
case CommonConstants.ALERT_PRIORITY_CODE_EMERGENCY -> alertSummary.setPriorityEmergencyNum(priorityNum.getNum());
|
||||
default -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
-88
@@ -1,88 +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.apache.hertzbeat.alert.service.impl;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.alert.dao.AlertSilenceDao;
|
||||
import org.apache.hertzbeat.alert.service.AlertSilenceService;
|
||||
import org.apache.hertzbeat.common.cache.CacheFactory;
|
||||
import org.apache.hertzbeat.common.cache.CommonCacheService;
|
||||
import org.apache.hertzbeat.common.constants.CommonConstants;
|
||||
import org.apache.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;
|
||||
|
||||
/**
|
||||
* 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 the alarm silent selection date set in periodic situations is empty, it will be deemed to be all checked.
|
||||
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,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.apache.hertzbeat.alert.config.AlerterAutoConfiguration
|
||||
-171
@@ -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.apache.hertzbeat.alert.controller;
|
||||
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.apache.hertzbeat.alert.service.impl.AlertDefineServiceImpl;
|
||||
import org.apache.hertzbeat.common.constants.CommonConstants;
|
||||
import org.apache.hertzbeat.common.entity.alerter.AlertDefine;
|
||||
import org.apache.hertzbeat.common.entity.alerter.AlertDefineMonitorBind;
|
||||
import org.apache.hertzbeat.common.entity.manager.Monitor;
|
||||
import org.apache.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;
|
||||
|
||||
/**
|
||||
* 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: Standalone setup, not integrated with a web environment for testing
|
||||
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 {
|
||||
// Simulate the client sending a request to the server
|
||||
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 {
|
||||
// Simulate returning data from 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();
|
||||
}
|
||||
}
|
||||
-151
@@ -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.apache.hertzbeat.alert.controller;
|
||||
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import org.apache.hertzbeat.alert.service.AlertDefineService;
|
||||
import org.apache.hertzbeat.common.constants.CommonConstants;
|
||||
import org.apache.hertzbeat.common.entity.alerter.AlertDefine;
|
||||
import org.apache.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.PageImpl;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Test case for {@link AlertDefinesController}
|
||||
* Test whether the data mocked at the mock is correct, and test whether the format of the returned data is correct
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class AlertDefinesControllerTest {
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@InjectMocks
|
||||
private AlertDefinesController alertDefinesController;
|
||||
|
||||
@Mock
|
||||
AlertDefineService alertDefineService;
|
||||
|
||||
// Parameters to avoid default values interference, default values have been replaced
|
||||
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;
|
||||
|
||||
// Parameter collection
|
||||
Map<String, Object> content = new HashMap<>();
|
||||
|
||||
// Object for mock
|
||||
PageRequest pageRequest;
|
||||
|
||||
// Since the specification is used in dynamic proxy, it cannot be mocked
|
||||
// Missing debugging parameters are ids, priority
|
||||
// The missing part has been manually output for testing
|
||||
|
||||
@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);
|
||||
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"), (Integer) content.get("pageSize"), sortExp);
|
||||
}
|
||||
|
||||
// @Test
|
||||
// todo: fix this test
|
||||
void getAlertDefines() throws Exception {
|
||||
|
||||
// Test the correctness of the mock
|
||||
// Although objects cannot be mocked, stubs can be stored using class files
|
||||
// Mockito.when(alertDefineService.getAlertDefines(Mockito.any(Specification.class), Mockito.argThat(new ArgumentMatcher<PageRequest>() {
|
||||
// @Override
|
||||
// public boolean matches(PageRequest pageRequestMidden) {
|
||||
// // There are three methods in the source code that need to be compared, namely 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();
|
||||
}
|
||||
}
|
||||
-124
@@ -1,124 +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.apache.hertzbeat.alert.controller;
|
||||
|
||||
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;
|
||||
import org.apache.hertzbeat.alert.dto.GeneralCloudAlertReport;
|
||||
import org.apache.hertzbeat.alert.dto.TenCloudAlertReport;
|
||||
import org.apache.hertzbeat.alert.service.AlertService;
|
||||
import org.apache.hertzbeat.common.constants.CommonConstants;
|
||||
import org.apache.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;
|
||||
|
||||
/**
|
||||
* 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("Guangzhou");
|
||||
alarmObjInfo.setNamespace("Guangzhou1");
|
||||
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("Guangzhou1");
|
||||
conditions.setEventName("CVS");
|
||||
conditions.setEventShowName("Core error");
|
||||
|
||||
TenCloudAlertReport.AlarmPolicyInfo alarmPolicyInfo = new TenCloudAlertReport.AlarmPolicyInfo();
|
||||
alarmPolicyInfo.setPolicyTypeCname("x");
|
||||
alarmPolicyInfo.setPolicyName("Test1");
|
||||
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();
|
||||
}
|
||||
}
|
||||
-161
@@ -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.apache.hertzbeat.alert.controller;
|
||||
|
||||
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;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.LongStream;
|
||||
import org.apache.hertzbeat.alert.dto.AlertSummary;
|
||||
import org.apache.hertzbeat.alert.service.AlertService;
|
||||
import org.apache.hertzbeat.common.constants.CommonConstants;
|
||||
import org.apache.hertzbeat.common.entity.alerter.Alert;
|
||||
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.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
|
||||
/**
|
||||
* 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());
|
||||
}
|
||||
|
||||
// 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,190 +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.apache.hertzbeat.alert.service;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.Mockito.anySet;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.when;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import org.apache.hertzbeat.alert.dao.AlertDefineBindDao;
|
||||
import org.apache.hertzbeat.alert.dao.AlertDefineDao;
|
||||
import org.apache.hertzbeat.alert.service.impl.AlertDefineServiceImpl;
|
||||
import org.apache.hertzbeat.common.entity.alerter.AlertDefine;
|
||||
import org.apache.hertzbeat.common.entity.alerter.AlertDefineMonitorBind;
|
||||
import org.apache.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.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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.apache.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() {
|
||||
}
|
||||
}
|
||||
@@ -1,464 +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.apache.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.apache.hertzbeat</groupId>
|
||||
<artifactId>hertzbeat-common</artifactId>
|
||||
</dependency>
|
||||
<!-- remoting -->
|
||||
<dependency>
|
||||
<groupId>org.apache.hertzbeat</groupId>
|
||||
<artifactId>hertzbeat-remoting</artifactId>
|
||||
</dependency>
|
||||
<!-- run sql script-->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
</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>
|
||||
<!-- nebula graph client -->
|
||||
<dependency>
|
||||
<groupId>com.vesoft</groupId>
|
||||
<artifactId>client</artifactId>
|
||||
<version>3.6.0</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>apache-hertzbeat-collector-${hzb.version}</finalName>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>inner</id>
|
||||
<build>
|
||||
<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>
|
||||
<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>17</source>
|
||||
<target>17</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>
|
||||
<!--Generated JAR does not include Maven descriptor-related files-->
|
||||
<addMavenDescriptor>false</addMavenDescriptor>
|
||||
<manifest>
|
||||
<!--Project startup class-->
|
||||
<mainClass>org.apache.hertzbeat.collector.Collector</mainClass>
|
||||
<useUniqueVersions>false</useUniqueVersions>
|
||||
<!--Third-party JARs are added to the classpath using maven-dependency-plugin-->
|
||||
<addClasspath>true</addClasspath>
|
||||
<!--Location of external dependency JARs-->
|
||||
<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>
|
||||
<!--Bound Maven operation-->
|
||||
<phase>package</phase>
|
||||
<!--Run once-->
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>../script/assembly/collector/assembly.xml</descriptor>
|
||||
</descriptors>
|
||||
<outputDirectory>../dist</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>runtime</id>
|
||||
<build>
|
||||
<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>17</source>
|
||||
<target>17</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>
|
||||
<!--Generated JAR does not include Maven descriptor-related files-->
|
||||
<addMavenDescriptor>false</addMavenDescriptor>
|
||||
<manifest>
|
||||
<!--Project startup class-->
|
||||
<mainClass>org.apache.hertzbeat.collector.Collector</mainClass>
|
||||
<useUniqueVersions>false</useUniqueVersions>
|
||||
<!--Third-party JARs are added to the classpath using maven-dependency-plugin-->
|
||||
<addClasspath>true</addClasspath>
|
||||
<!--Location of external dependency JARs-->
|
||||
<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>
|
||||
<!--Bound Maven operation-->
|
||||
<phase>package</phase>
|
||||
<!--Run once-->
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>../script/assembly/collector/assembly.xml</descriptor>
|
||||
</descriptors>
|
||||
<outputDirectory>../dist</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>make-macos-arm64</id>
|
||||
<!--Bound Maven operation-->
|
||||
<phase>package</phase>
|
||||
<!--Run once-->
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>../script/assembly/collector/assembly-macos-arm64.xml</descriptor>
|
||||
</descriptors>
|
||||
<outputDirectory>../dist</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>make-macos-amd64</id>
|
||||
<!--Bound Maven operation-->
|
||||
<phase>package</phase>
|
||||
<!--Run once-->
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>../script/assembly/collector/assembly-macos-amd64.xml</descriptor>
|
||||
</descriptors>
|
||||
<outputDirectory>../dist</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>make-linux-arm64</id>
|
||||
<!--Bound Maven operation-->
|
||||
<phase>package</phase>
|
||||
<!--Run once-->
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>../script/assembly/collector/assembly-linux-arm64.xml</descriptor>
|
||||
</descriptors>
|
||||
<outputDirectory>../dist</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>make-linux-amd64</id>
|
||||
<!--Bound Maven operation-->
|
||||
<phase>package</phase>
|
||||
<!--Run once-->
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>../script/assembly/collector/assembly-linux-amd64.xml</descriptor>
|
||||
</descriptors>
|
||||
<outputDirectory>../dist</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>make-windows-64</id>
|
||||
<!--Bound Maven operation-->
|
||||
<phase>package</phase>
|
||||
<!--Run once-->
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>../script/assembly/collector/assembly-windows-64.xml</descriptor>
|
||||
</descriptors>
|
||||
<outputDirectory>../dist</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
</project>
|
||||
-233
@@ -1,233 +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.apache.hertzbeat.collector.collect.common.cache;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* lru common resource cache for client-server connection
|
||||
*/
|
||||
@Slf4j
|
||||
public class ConnectionCommonCache<T, C extends AbstractConnection<?>> {
|
||||
|
||||
/**
|
||||
* 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<T, Long[]> timeoutMap;
|
||||
|
||||
/**
|
||||
* object cache
|
||||
*/
|
||||
private ConcurrentLinkedHashMap<T, C> cacheMap;
|
||||
|
||||
/**
|
||||
* the executor who clean cache when timeout
|
||||
*/
|
||||
private ThreadPoolExecutor timeoutCleanerExecutor;
|
||||
|
||||
public ConnectionCommonCache() {
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
cacheMap = new ConcurrentLinkedHashMap
|
||||
.Builder<T, C>()
|
||||
.maximumWeightedCapacity(DEFAULT_MAX_CAPACITY)
|
||||
.listener((key, value) -> {
|
||||
timeoutMap.remove(key);
|
||||
try {
|
||||
value.close();
|
||||
} catch (Exception e) {
|
||||
log.error("connection close error: {}.", e.getMessage(), e);
|
||||
}
|
||||
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);
|
||||
try {
|
||||
value.close();
|
||||
} catch (Exception e) {
|
||||
log.error("connection close error: {}.", e.getMessage(), e);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
} 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);
|
||||
try {
|
||||
value.close();
|
||||
} catch (Exception e) {
|
||||
log.error("connection close error: {}.", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
});
|
||||
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(T key, C 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(T key, C 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<C> getCache(T 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();
|
||||
}
|
||||
C value = cacheMap.compute(key, (k, v) -> {
|
||||
if (v == null) {
|
||||
log.error("[connection common cache] value is null, remove it, key {}.", key);
|
||||
timeoutMap.remove(key);
|
||||
return null;
|
||||
}
|
||||
if (refreshCache) {
|
||||
cacheTime[0] = System.currentTimeMillis();
|
||||
timeoutMap.put(key, cacheTime);
|
||||
}
|
||||
return v;
|
||||
});
|
||||
return Optional.ofNullable(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* remove cache by key
|
||||
*
|
||||
* @param key key
|
||||
*/
|
||||
public void removeCache(T key) {
|
||||
timeoutMap.remove(key);
|
||||
C value = cacheMap.remove(key);
|
||||
try {
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
value.close();
|
||||
} catch (Exception e) {
|
||||
log.error("connection close error: {}.", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-153
@@ -1,153 +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.apache.hertzbeat.collector.collect.ftp;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.net.ftp.FTPClient;
|
||||
import org.apache.hertzbeat.collector.collect.AbstractCollect;
|
||||
import org.apache.hertzbeat.collector.dispatch.DispatchConstants;
|
||||
import org.apache.hertzbeat.common.constants.CommonConstants;
|
||||
import org.apache.hertzbeat.common.entity.job.Metrics;
|
||||
import org.apache.hertzbeat.common.entity.job.protocol.FtpProtocol;
|
||||
import org.apache.hertzbeat.common.entity.message.CollectRep;
|
||||
import org.apache.hertzbeat.common.util.CommonUtil;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* ftp protocol collection implementation
|
||||
*/
|
||||
@Slf4j
|
||||
public class FtpCollectImpl extends AbstractCollect {
|
||||
|
||||
private static final String ANONYMOUS = "anonymous";
|
||||
private static final String PASSWORD = "password";
|
||||
|
||||
/**
|
||||
* preCheck params
|
||||
*/
|
||||
public void preCheck(Metrics metrics) throws IllegalArgumentException{
|
||||
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.");
|
||||
Assert.hasText(ftpProtocol.getTimeout(), "Ftp Protocol timeout is required.");
|
||||
}
|
||||
|
||||
|
||||
@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()));
|
||||
|
||||
// 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.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String supportProtocol() {
|
||||
return DispatchConstants.PROTOCOL_FTP;
|
||||
}
|
||||
}
|
||||
-163
@@ -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.apache.hertzbeat.collector.collect.http;
|
||||
|
||||
import static org.apache.hertzbeat.common.constants.SignConstants.RIGHT_DASH;
|
||||
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 javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.SSLPeerUnverifiedException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.collector.collect.AbstractCollect;
|
||||
import org.apache.hertzbeat.collector.dispatch.DispatchConstants;
|
||||
import org.apache.hertzbeat.common.constants.CollectorConstants;
|
||||
import org.apache.hertzbeat.common.constants.CommonConstants;
|
||||
import org.apache.hertzbeat.common.entity.job.Metrics;
|
||||
import org.apache.hertzbeat.common.entity.job.protocol.HttpProtocol;
|
||||
import org.apache.hertzbeat.common.entity.message.CollectRep;
|
||||
import org.apache.hertzbeat.common.util.CommonUtil;
|
||||
import org.apache.hertzbeat.common.util.IpDomainUtil;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* 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";
|
||||
|
||||
@Override
|
||||
public void preCheck(Metrics metrics) throws IllegalArgumentException {
|
||||
if (metrics == null || metrics.getHttp() == null) {
|
||||
throw new IllegalArgumentException("Http/Https collect must has http params");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collect(CollectRep.MetricsData.Builder builder,
|
||||
long monitorId, String app, Metrics metrics) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
HttpProtocol httpProtocol = metrics.getHttp();
|
||||
String url = httpProtocol.getUrl();
|
||||
if (!StringUtils.hasText(url) || !url.startsWith(RIGHT_DASH)) {
|
||||
httpProtocol.setUrl(StringUtils.hasText(url) ? RIGHT_DASH + url.trim() : RIGHT_DASH);
|
||||
}
|
||||
|
||||
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.getSubjectX500Principal().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) {
|
||||
|
||||
}
|
||||
}
|
||||
-44
@@ -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.apache.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();
|
||||
}
|
||||
}
|
||||
-127
@@ -1,127 +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.apache.hertzbeat.collector.collect.httpsd;
|
||||
|
||||
import com.ecwid.consul.transport.TransportException;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Objects;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.hertzbeat.collector.collect.AbstractCollect;
|
||||
import org.apache.hertzbeat.collector.collect.httpsd.discovery.DiscoveryClient;
|
||||
import org.apache.hertzbeat.collector.collect.httpsd.discovery.DiscoveryClientManagement;
|
||||
import org.apache.hertzbeat.collector.collect.httpsd.discovery.entity.ServerInfo;
|
||||
import org.apache.hertzbeat.collector.dispatch.DispatchConstants;
|
||||
import org.apache.hertzbeat.common.constants.CollectorConstants;
|
||||
import org.apache.hertzbeat.common.constants.CommonConstants;
|
||||
import org.apache.hertzbeat.common.entity.job.Metrics;
|
||||
import org.apache.hertzbeat.common.entity.job.protocol.HttpsdProtocol;
|
||||
import org.apache.hertzbeat.common.entity.message.CollectRep;
|
||||
import org.apache.hertzbeat.common.util.CommonUtil;
|
||||
|
||||
/**
|
||||
* http_sd protocol collection implementation
|
||||
*/
|
||||
@Slf4j
|
||||
public class HttpsdImpl extends AbstractCollect {
|
||||
private static final String SERVER = "server";
|
||||
|
||||
@Setter
|
||||
@VisibleForTesting
|
||||
private DiscoveryClientManagement discoveryClientManagement = new DiscoveryClientManagement();
|
||||
|
||||
@Override
|
||||
public void preCheck(Metrics metrics) throws IllegalArgumentException {
|
||||
HttpsdProtocol httpsdProtocol = metrics.getHttpsd();
|
||||
if (Objects.isNull(httpsdProtocol) || httpsdProtocol.isInvalid()){
|
||||
throw new IllegalArgumentException("http_sd collect must have a valid http_sd protocol param! ");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collect(CollectRep.MetricsData.Builder builder, long monitorId, String app, Metrics metrics) {
|
||||
HttpsdProtocol httpsdProtocol = metrics.getHttpsd();
|
||||
|
||||
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.valueOf(declaredField.get(sourceObj));
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
log.warn("No such field for {}", fieldName);
|
||||
}
|
||||
|
||||
valueRowBuilder.addColumns(StringUtils.isBlank(columnValue)
|
||||
? CommonConstants.NULL_VALUE
|
||||
: columnValue);
|
||||
}
|
||||
}
|
||||
-64
@@ -1,64 +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.apache.hertzbeat.collector.collect.httpsd.discovery;
|
||||
|
||||
import java.util.List;
|
||||
import org.apache.hertzbeat.collector.collect.httpsd.discovery.entity.ConnectConfig;
|
||||
import org.apache.hertzbeat.collector.collect.httpsd.discovery.entity.ServerInfo;
|
||||
import org.apache.hertzbeat.collector.collect.httpsd.discovery.entity.ServiceInstance;
|
||||
import org.apache.hertzbeat.common.entity.job.protocol.HttpsdProtocol;
|
||||
|
||||
/**
|
||||
* DiscoveryClient interface.
|
||||
*/
|
||||
public interface DiscoveryClient extends AutoCloseable {
|
||||
|
||||
/**
|
||||
* Build connect config.
|
||||
* @param httpsdProtocol httpsd protocol.
|
||||
* @return connect config object.
|
||||
*/
|
||||
ConnectConfig buildConnectConfig(HttpsdProtocol httpsdProtocol);
|
||||
|
||||
/**
|
||||
* Initialize client.
|
||||
* @param connectConfig connect config.
|
||||
*/
|
||||
void initClient(ConnectConfig connectConfig);
|
||||
|
||||
/**
|
||||
* Get server info.
|
||||
* @return server info object.
|
||||
*/
|
||||
ServerInfo getServerInfo();
|
||||
|
||||
/**
|
||||
* Get services.
|
||||
* @return service instance list.
|
||||
*/
|
||||
List<ServiceInstance> getServices();
|
||||
|
||||
/**
|
||||
* Discovery client Health check.
|
||||
* @return true if health check pass, otherwise false
|
||||
*/
|
||||
boolean healthCheck();
|
||||
|
||||
}
|
||||
-55
@@ -1,55 +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.apache.hertzbeat.collector.collect.httpsd.discovery;
|
||||
|
||||
import java.util.Objects;
|
||||
import org.apache.hertzbeat.collector.collect.httpsd.constant.DiscoveryClientInstance;
|
||||
import org.apache.hertzbeat.collector.collect.httpsd.discovery.impl.ConsulDiscoveryClient;
|
||||
import org.apache.hertzbeat.collector.collect.httpsd.discovery.impl.NacosDiscoveryClient;
|
||||
import org.apache.hertzbeat.common.entity.job.protocol.HttpsdProtocol;
|
||||
|
||||
/**
|
||||
* 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();
|
||||
case NACOS -> discoveryClient = new NacosDiscoveryClient();
|
||||
default -> { return null; }
|
||||
}
|
||||
discoveryClient.initClient(discoveryClient.buildConnectConfig(httpsdProtocol));
|
||||
return discoveryClient;
|
||||
}
|
||||
}
|
||||
-330
@@ -1,330 +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.apache.hertzbeat.collector.collect.ssh;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.ConnectException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.collector.collect.AbstractCollect;
|
||||
import org.apache.hertzbeat.collector.collect.common.cache.CacheIdentifier;
|
||||
import org.apache.hertzbeat.collector.collect.common.cache.ConnectionCommonCache;
|
||||
import org.apache.hertzbeat.collector.collect.common.cache.SshConnect;
|
||||
import org.apache.hertzbeat.collector.collect.common.ssh.CommonSshClient;
|
||||
import org.apache.hertzbeat.collector.dispatch.DispatchConstants;
|
||||
import org.apache.hertzbeat.collector.util.CollectUtil;
|
||||
import org.apache.hertzbeat.collector.util.PrivateKeyUtils;
|
||||
import org.apache.hertzbeat.common.constants.CollectorConstants;
|
||||
import org.apache.hertzbeat.common.constants.CommonConstants;
|
||||
import org.apache.hertzbeat.common.entity.job.Metrics;
|
||||
import org.apache.hertzbeat.common.entity.job.protocol.SshProtocol;
|
||||
import org.apache.hertzbeat.common.entity.message.CollectRep;
|
||||
import org.apache.hertzbeat.common.util.CommonUtil;
|
||||
import org.apache.sshd.client.SshClient;
|
||||
import org.apache.sshd.client.channel.ClientChannel;
|
||||
import org.apache.sshd.client.channel.ClientChannelEvent;
|
||||
import org.apache.sshd.client.session.ClientSession;
|
||||
import org.apache.sshd.common.SshException;
|
||||
import org.apache.sshd.common.channel.exception.SshChannelOpenException;
|
||||
import org.apache.sshd.common.util.io.output.NoCloseOutputStream;
|
||||
import org.apache.sshd.common.util.security.SecurityUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Ssh protocol collection implementation
|
||||
*/
|
||||
@Slf4j
|
||||
public class SshCollectImpl extends AbstractCollect {
|
||||
|
||||
private static final String PARSE_TYPE_ONE_ROW = "oneRow";
|
||||
private static final String PARSE_TYPE_MULTI_ROW = "multiRow";
|
||||
private static final String PARSE_TYPE_NETCAT = "netcat";
|
||||
private static final String PARSE_TYPE_LOG = "log";
|
||||
|
||||
private static final int DEFAULT_TIMEOUT = 10_000;
|
||||
private final ConnectionCommonCache<CacheIdentifier, SshConnect> connectionCommonCache;
|
||||
|
||||
public SshCollectImpl() {
|
||||
connectionCommonCache = new ConnectionCommonCache<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preCheck(Metrics metrics) throws IllegalArgumentException {
|
||||
if (metrics == null || metrics.getSsh() == null) {
|
||||
throw new IllegalArgumentException("ssh collect must has ssh params");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collect(CollectRep.MetricsData.Builder builder, long monitorId, String app, Metrics metrics) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
SshProtocol sshProtocol = metrics.getSsh();
|
||||
boolean reuseConnection = Boolean.parseBoolean(sshProtocol.getReuseConnection());
|
||||
int timeout = CollectUtil.getTimeout(sshProtocol.getTimeout(), DEFAULT_TIMEOUT);
|
||||
ClientChannel channel = null;
|
||||
ClientSession clientSession = null;
|
||||
try {
|
||||
clientSession = getConnectSession(sshProtocol, timeout, reuseConnection);
|
||||
channel = clientSession.createExecChannel(sshProtocol.getScript());
|
||||
ByteArrayOutputStream response = new ByteArrayOutputStream();
|
||||
channel.setOut(response);
|
||||
channel.setErr(new NoCloseOutputStream(System.err));
|
||||
channel.open().verify(timeout);
|
||||
List<ClientChannelEvent> list = new ArrayList<>();
|
||||
list.add(ClientChannelEvent.CLOSED);
|
||||
Collection<ClientChannelEvent> waitEvents = channel.waitFor(list, timeout);
|
||||
if (waitEvents.contains(ClientChannelEvent.TIMEOUT)) {
|
||||
throw new SocketTimeoutException("Failed to retrieve command result in time: " + sshProtocol.getScript());
|
||||
}
|
||||
Long responseTime = System.currentTimeMillis() - startTime;
|
||||
String result = response.toString();
|
||||
if (!StringUtils.hasText(result)) {
|
||||
builder.setCode(CollectRep.Code.FAIL);
|
||||
builder.setMsg("ssh shell response data is null");
|
||||
return;
|
||||
}
|
||||
switch (sshProtocol.getParseType()) {
|
||||
case PARSE_TYPE_LOG -> parseResponseDataByLog(result, metrics.getAliasFields(), builder, responseTime);
|
||||
case PARSE_TYPE_NETCAT -> parseResponseDataByNetcat(result, metrics.getAliasFields(), builder, responseTime);
|
||||
case PARSE_TYPE_ONE_ROW -> parseResponseDataByOne(result, metrics.getAliasFields(), builder, responseTime);
|
||||
case PARSE_TYPE_MULTI_ROW -> parseResponseDataByMulti(result, metrics.getAliasFields(), builder, responseTime);
|
||||
default -> {
|
||||
builder.setCode(CollectRep.Code.FAIL);
|
||||
builder.setMsg("Ssh collect not support this parse type: " + sshProtocol.getParseType());
|
||||
}
|
||||
}
|
||||
} catch (ConnectException connectException) {
|
||||
String errorMsg = CommonUtil.getMessageFromThrowable(connectException);
|
||||
log.info(errorMsg);
|
||||
builder.setCode(CollectRep.Code.UN_CONNECTABLE);
|
||||
builder.setMsg("The peer refused to connect: service port does not listening or firewall: " + errorMsg);
|
||||
} catch (SshException sshException) {
|
||||
Throwable throwable = sshException.getCause();
|
||||
if (throwable instanceof SshChannelOpenException) {
|
||||
log.warn("Remote ssh server no more session channel, please increase sshd_config MaxSessions.");
|
||||
}
|
||||
String errorMsg = CommonUtil.getMessageFromThrowable(sshException);
|
||||
builder.setCode(CollectRep.Code.UN_CONNECTABLE);
|
||||
builder.setMsg("Peer ssh connection failed: " + errorMsg);
|
||||
} catch (IOException ioException) {
|
||||
String errorMsg = CommonUtil.getMessageFromThrowable(ioException);
|
||||
log.info(errorMsg);
|
||||
builder.setCode(CollectRep.Code.UN_CONNECTABLE);
|
||||
builder.setMsg("Peer io connection failed: " + errorMsg);
|
||||
} catch (Exception exception) {
|
||||
String errorMsg = CommonUtil.getMessageFromThrowable(exception);
|
||||
log.warn(errorMsg, exception);
|
||||
builder.setCode(CollectRep.Code.FAIL);
|
||||
builder.setMsg(errorMsg);
|
||||
} finally {
|
||||
if (channel != null && channel.isOpen()) {
|
||||
try {
|
||||
channel.close();
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
if (clientSession != null && !reuseConnection) {
|
||||
try {
|
||||
clientSession.close();
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String supportProtocol() {
|
||||
return DispatchConstants.PROTOCOL_SSH;
|
||||
}
|
||||
|
||||
private void parseResponseDataByLog(String result, List<String> aliasFields, CollectRep.MetricsData.Builder builder, Long responseTime) {
|
||||
String[] lines = result.split("\n");
|
||||
if (lines.length + 1 < aliasFields.size()) {
|
||||
log.error("ssh response data not enough: {}", result);
|
||||
return;
|
||||
}
|
||||
for (String line : lines) {
|
||||
CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder();
|
||||
for (String alias : aliasFields) {
|
||||
if (CollectorConstants.RESPONSE_TIME.equalsIgnoreCase(alias)) {
|
||||
valueRowBuilder.addColumns(responseTime.toString());
|
||||
} else {
|
||||
valueRowBuilder.addColumns(line);
|
||||
}
|
||||
}
|
||||
builder.addValues(valueRowBuilder.build());
|
||||
}
|
||||
}
|
||||
|
||||
private void parseResponseDataByNetcat(String result, List<String> aliasFields, CollectRep.MetricsData.Builder builder, Long responseTime) {
|
||||
String[] lines = result.split("\n");
|
||||
if (lines.length + 1 < aliasFields.size()) {
|
||||
log.error("ssh response data not enough: {}", result);
|
||||
return;
|
||||
}
|
||||
boolean contains = lines[0].contains("=");
|
||||
Map<String, String> mapValue = Arrays.stream(lines)
|
||||
.map(item -> {
|
||||
if (contains) {
|
||||
return item.split("=");
|
||||
} else {
|
||||
return item.split("\t");
|
||||
}
|
||||
})
|
||||
.filter(item -> item.length == 2)
|
||||
.collect(Collectors.toMap(x -> x[0], x -> x[1]));
|
||||
|
||||
CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder();
|
||||
for (String field : aliasFields) {
|
||||
String fieldValue = mapValue.get(field);
|
||||
if (fieldValue == null) {
|
||||
valueRowBuilder.addColumns(CommonConstants.NULL_VALUE);
|
||||
} else {
|
||||
valueRowBuilder.addColumns(fieldValue);
|
||||
}
|
||||
}
|
||||
builder.addValues(valueRowBuilder.build());
|
||||
}
|
||||
|
||||
private void parseResponseDataByOne(String result, List<String> aliasFields, CollectRep.MetricsData.Builder builder, Long responseTime) {
|
||||
String[] lines = result.split("\n");
|
||||
if (lines.length + 1 < aliasFields.size()) {
|
||||
log.error("ssh response data not enough: {}", result);
|
||||
return;
|
||||
}
|
||||
CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder();
|
||||
int aliasIndex = 0;
|
||||
int lineIndex = 0;
|
||||
while (aliasIndex < aliasFields.size()) {
|
||||
if (CollectorConstants.RESPONSE_TIME.equalsIgnoreCase(aliasFields.get(aliasIndex))) {
|
||||
valueRowBuilder.addColumns(responseTime.toString());
|
||||
} else {
|
||||
if (lineIndex < lines.length) {
|
||||
valueRowBuilder.addColumns(lines[lineIndex].trim());
|
||||
} else {
|
||||
valueRowBuilder.addColumns(CommonConstants.NULL_VALUE);
|
||||
}
|
||||
lineIndex++;
|
||||
}
|
||||
aliasIndex++;
|
||||
}
|
||||
builder.addValues(valueRowBuilder.build());
|
||||
}
|
||||
|
||||
private void parseResponseDataByMulti(String result, List<String> aliasFields,
|
||||
CollectRep.MetricsData.Builder builder, Long responseTime) {
|
||||
String[] lines = result.split("\n");
|
||||
if (lines.length <= 1) {
|
||||
log.error("ssh response data only has header: {}", result);
|
||||
return;
|
||||
}
|
||||
String[] fields = lines[0].split(" ");
|
||||
Map<String, Integer> fieldMapping = new HashMap<>(fields.length);
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
fieldMapping.put(fields[i].trim().toLowerCase(), i);
|
||||
}
|
||||
for (int i = 1; i < lines.length; i++) {
|
||||
String[] values = lines[i].split(" ");
|
||||
CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder();
|
||||
for (String alias : aliasFields) {
|
||||
if (CollectorConstants.RESPONSE_TIME.equalsIgnoreCase(alias)) {
|
||||
valueRowBuilder.addColumns(responseTime.toString());
|
||||
} else {
|
||||
Integer index = fieldMapping.get(alias.toLowerCase());
|
||||
if (index != null && index < values.length) {
|
||||
valueRowBuilder.addColumns(values[index]);
|
||||
} else {
|
||||
valueRowBuilder.addColumns(CommonConstants.NULL_VALUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
builder.addValues(valueRowBuilder.build());
|
||||
}
|
||||
}
|
||||
|
||||
private void removeConnectSessionCache(SshProtocol sshProtocol) {
|
||||
CacheIdentifier identifier = CacheIdentifier.builder()
|
||||
.ip(sshProtocol.getHost()).port(sshProtocol.getPort())
|
||||
.username(sshProtocol.getUsername()).password(sshProtocol.getPassword())
|
||||
.build();
|
||||
connectionCommonCache.removeCache(identifier);
|
||||
}
|
||||
|
||||
private ClientSession getConnectSession(SshProtocol sshProtocol, int timeout, boolean reuseConnection)
|
||||
throws IOException, GeneralSecurityException {
|
||||
CacheIdentifier identifier = CacheIdentifier.builder()
|
||||
.ip(sshProtocol.getHost()).port(sshProtocol.getPort())
|
||||
.username(sshProtocol.getUsername()).password(sshProtocol.getPassword())
|
||||
.build();
|
||||
ClientSession clientSession = null;
|
||||
if (reuseConnection) {
|
||||
Optional<SshConnect> cacheOption = connectionCommonCache.getCache(identifier, true);
|
||||
if (cacheOption.isPresent()) {
|
||||
clientSession = cacheOption.get().getConnection();
|
||||
try {
|
||||
if (clientSession == null || clientSession.isClosed() || clientSession.isClosing()) {
|
||||
clientSession = null;
|
||||
connectionCommonCache.removeCache(identifier);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn(e.getMessage());
|
||||
clientSession = null;
|
||||
connectionCommonCache.removeCache(identifier);
|
||||
}
|
||||
}
|
||||
if (clientSession != null) {
|
||||
return clientSession;
|
||||
}
|
||||
}
|
||||
SshClient sshClient = CommonSshClient.getSshClient();
|
||||
clientSession = sshClient.connect(sshProtocol.getUsername(), sshProtocol.getHost(), Integer.parseInt(sshProtocol.getPort()))
|
||||
.verify(timeout, TimeUnit.MILLISECONDS).getSession();
|
||||
if (StringUtils.hasText(sshProtocol.getPassword())) {
|
||||
clientSession.addPasswordIdentity(sshProtocol.getPassword());
|
||||
} else if (StringUtils.hasText(sshProtocol.getPrivateKey())) {
|
||||
var resourceKey = PrivateKeyUtils.writePrivateKey(sshProtocol.getHost(), sshProtocol.getPrivateKey());
|
||||
SecurityUtils.loadKeyPairIdentities(null, () -> resourceKey, new FileInputStream(resourceKey), null)
|
||||
.forEach(clientSession::addPublicKeyIdentity);
|
||||
} // else auth with localhost private public key certificates
|
||||
|
||||
// auth
|
||||
if (!clientSession.auth().verify(timeout, TimeUnit.MILLISECONDS).isSuccess()) {
|
||||
clientSession.close();
|
||||
throw new IllegalArgumentException("ssh auth failed.");
|
||||
}
|
||||
if (reuseConnection) {
|
||||
SshConnect sshConnect = new SshConnect(clientSession);
|
||||
connectionCommonCache.addCache(identifier, sshConnect);
|
||||
}
|
||||
return clientSession;
|
||||
}
|
||||
}
|
||||
-28
@@ -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.apache.hertzbeat.collector.config;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
/**
|
||||
* Collector Auto Configuration
|
||||
* @version 2.1
|
||||
*/
|
||||
@ComponentScan(basePackages = "org.apache.hertzbeat.collector")
|
||||
public class CollectorAutoConfiguration {
|
||||
}
|
||||
-176
@@ -1,176 +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.apache.hertzbeat.collector.dispatch.entrance.internal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.collector.dispatch.DispatchProperties;
|
||||
import org.apache.hertzbeat.collector.dispatch.WorkerPool;
|
||||
import org.apache.hertzbeat.collector.dispatch.entrance.CollectServer;
|
||||
import org.apache.hertzbeat.collector.dispatch.timer.TimerDispatch;
|
||||
import org.apache.hertzbeat.common.constants.CommonConstants;
|
||||
import org.apache.hertzbeat.common.entity.job.Job;
|
||||
import org.apache.hertzbeat.common.entity.message.ClusterMsg;
|
||||
import org.apache.hertzbeat.common.entity.message.CollectRep;
|
||||
import org.apache.hertzbeat.common.util.IpDomainUtil;
|
||||
import org.apache.hertzbeat.common.util.JsonUtil;
|
||||
import org.apache.hertzbeat.common.util.ProtoJsonUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Collection job management provides api interface
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class CollectJobService {
|
||||
|
||||
private static final String COLLECTOR_STR = "-collector";
|
||||
|
||||
private final TimerDispatch timerDispatch;
|
||||
|
||||
private final WorkerPool workerPool;
|
||||
|
||||
private final String collectorIdentity;
|
||||
|
||||
private String mode = null;
|
||||
|
||||
private CollectServer collectServer;
|
||||
|
||||
public CollectJobService(TimerDispatch timerDispatch, DispatchProperties properties, WorkerPool workerPool) {
|
||||
this.timerDispatch = timerDispatch;
|
||||
this.workerPool = workerPool;
|
||||
if (properties != null && properties.getEntrance() != null && properties.getEntrance().getNetty() != null
|
||||
&& properties.getEntrance().getNetty().isEnabled()) {
|
||||
mode = properties.getEntrance().getNetty().getMode();
|
||||
String collectorName = properties.getEntrance().getNetty().getIdentity();
|
||||
if (StringUtils.hasText(collectorName)) {
|
||||
collectorIdentity = collectorName;
|
||||
} else {
|
||||
collectorIdentity = IpDomainUtil.getCurrentHostName() + COLLECTOR_STR;
|
||||
log.info("user not config this collector identity, use [host name - host ip] default: {}.", collectorIdentity);
|
||||
}
|
||||
} else {
|
||||
collectorIdentity = CommonConstants.MAIN_COLLECTOR_NODE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a one-time collection task and get the collected data response
|
||||
*
|
||||
* @param job Collect task details
|
||||
* @return Collection results
|
||||
*/
|
||||
public List<CollectRep.MetricsData> collectSyncJobData(Job job) {
|
||||
final List<CollectRep.MetricsData> metricsData = new LinkedList<>();
|
||||
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||
CollectResponseEventListener listener = new CollectResponseEventListener() {
|
||||
@Override
|
||||
public void response(List<CollectRep.MetricsData> responseMetrics) {
|
||||
if (responseMetrics != null) {
|
||||
metricsData.addAll(responseMetrics);
|
||||
}
|
||||
countDownLatch.countDown();
|
||||
}
|
||||
};
|
||||
timerDispatch.addJob(job, listener);
|
||||
try {
|
||||
countDownLatch.await(120, TimeUnit.SECONDS);
|
||||
} catch (Exception e) {
|
||||
log.info("The sync task runs for 120 seconds with no response and returns");
|
||||
}
|
||||
return metricsData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a one-time collection task and send the collected data response
|
||||
*
|
||||
* @param oneTimeJob Collect task details
|
||||
*/
|
||||
public void collectSyncOneTimeJobData(Job oneTimeJob) {
|
||||
workerPool.executeJob(() -> {
|
||||
List<CollectRep.MetricsData> metricsDataList = this.collectSyncJobData(oneTimeJob);
|
||||
List<String> jsons = new ArrayList<>(metricsDataList.size());
|
||||
for (CollectRep.MetricsData metricsData : metricsDataList) {
|
||||
String json = ProtoJsonUtil.toJsonStr(metricsData);
|
||||
if (json != null) {
|
||||
jsons.add(json);
|
||||
}
|
||||
}
|
||||
String response = JsonUtil.toJson(jsons);
|
||||
ClusterMsg.Message message = ClusterMsg.Message.newBuilder()
|
||||
.setMsg(response)
|
||||
.setDirection(ClusterMsg.Direction.REQUEST)
|
||||
.setType(ClusterMsg.MessageType.RESPONSE_ONE_TIME_TASK_DATA)
|
||||
.build();
|
||||
this.collectServer.sendMsg(message);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue periodic asynchronous collection tasks
|
||||
*
|
||||
* @param job Collect task details
|
||||
*/
|
||||
public void addAsyncCollectJob(Job job) {
|
||||
timerDispatch.addJob(job.clone(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel periodic asynchronous collection tasks
|
||||
*
|
||||
* @param jobId Job ID
|
||||
*/
|
||||
public void cancelAsyncCollectJob(Long jobId) {
|
||||
if (jobId != null) {
|
||||
timerDispatch.deleteJob(jobId, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* send async collect response data
|
||||
*
|
||||
* @param metricsData collect data
|
||||
*/
|
||||
public void sendAsyncCollectData(CollectRep.MetricsData metricsData) {
|
||||
String data = ProtoJsonUtil.toJsonStr(metricsData);
|
||||
ClusterMsg.Message message = ClusterMsg.Message.newBuilder()
|
||||
.setIdentity(collectorIdentity)
|
||||
.setMsg(data)
|
||||
.setDirection(ClusterMsg.Direction.REQUEST)
|
||||
.setType(ClusterMsg.MessageType.RESPONSE_CYCLIC_TASK_DATA)
|
||||
.build();
|
||||
this.collectServer.sendMsg(message);
|
||||
}
|
||||
|
||||
public String getCollectorIdentity() {
|
||||
return collectorIdentity;
|
||||
}
|
||||
|
||||
public String getCollectorMode() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
public void setCollectServer(CollectServer collectServer) {
|
||||
this.collectServer = collectServer;
|
||||
}
|
||||
}
|
||||
-73
@@ -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.apache.hertzbeat.collector.dispatch.unit.impl;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.collector.dispatch.unit.DataUnit;
|
||||
import org.apache.hertzbeat.collector.dispatch.unit.UnitConvert;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* the convert of data size
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public final class DataSizeConvert implements UnitConvert {
|
||||
|
||||
@Override
|
||||
public String convert(String value, String originUnit, String newUnit) {
|
||||
if (value == null || value.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
if (!checkUnit(originUnit) || !checkUnit(newUnit)) {
|
||||
return null;
|
||||
}
|
||||
if (originUnit.equalsIgnoreCase(newUnit)) {
|
||||
log.warn("The origin unit is the same as the new unit, no need to convert");
|
||||
return value;
|
||||
}
|
||||
BigDecimal size = new BigDecimal(value);
|
||||
// Idea: Value is converted to bytes through origin unit,
|
||||
// and then converted to the value corresponding to the new unit unit
|
||||
for (DataUnit dataUnit : DataUnit.values()) {
|
||||
if (dataUnit.getUnit().equals(originUnit.toUpperCase())) {
|
||||
size = size.multiply(new BigDecimal(dataUnit.getScale()));
|
||||
}
|
||||
if (dataUnit.getUnit().equals(newUnit.toUpperCase())) {
|
||||
size = size.divide(new BigDecimal(dataUnit.getScale()), 12, RoundingMode.HALF_UP);
|
||||
}
|
||||
}
|
||||
return size.setScale(4, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkUnit(String unit) {
|
||||
if (unit == null || unit.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
for (DataUnit dataUnit : DataUnit.values()) {
|
||||
// not case-sensitive
|
||||
if (dataUnit.getUnit().equals(unit.toUpperCase())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
-65
@@ -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.apache.hertzbeat.collector.dispatch.unit.impl;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import org.apache.hertzbeat.collector.dispatch.unit.TimeLengthUnit;
|
||||
import org.apache.hertzbeat.collector.dispatch.unit.UnitConvert;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* the convert of time length
|
||||
*/
|
||||
@Component
|
||||
public final class TimeLengthConvert implements UnitConvert {
|
||||
|
||||
|
||||
@Override
|
||||
public String convert(String value, String originUnit, String newUnit) {
|
||||
if (value == null || value.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
BigDecimal length = new BigDecimal(value);
|
||||
// Idea: Value is converted to nanoseconds through origin unit,
|
||||
// and then converted to the value corresponding to the new unit unit
|
||||
for (TimeLengthUnit timeLengthUnit : TimeLengthUnit.values()) {
|
||||
if (timeLengthUnit.getUnit().equals(originUnit.toUpperCase())) {
|
||||
length = length.multiply(new BigDecimal(timeLengthUnit.getScale()));
|
||||
}
|
||||
if (timeLengthUnit.getUnit().equals(newUnit.toUpperCase())) {
|
||||
length = length.divide(new BigDecimal(timeLengthUnit.getScale()), 12, RoundingMode.HALF_UP);
|
||||
}
|
||||
}
|
||||
return length.setScale(4, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkUnit(String unit) {
|
||||
if (unit == null || unit.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
for (TimeLengthUnit timeUnit : TimeLengthUnit.values()) {
|
||||
// not case-sensitive
|
||||
if (timeUnit.getUnit().equals(unit.toUpperCase())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,458 +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.apache.hertzbeat.collector.util;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonNull;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.hertzbeat.common.constants.CommonConstants;
|
||||
import org.apache.hertzbeat.common.entity.job.Configmap;
|
||||
import org.apache.hertzbeat.common.entity.job.Metrics;
|
||||
import org.apache.hertzbeat.common.util.JsonUtil;
|
||||
|
||||
/**
|
||||
* util for collector
|
||||
*/
|
||||
@Slf4j
|
||||
public final class CollectUtil {
|
||||
|
||||
private static final int DEFAULT_TIMEOUT = 60000;
|
||||
private static final int HEX_STR_WIDTH = 2;
|
||||
private static final String SMILING_PLACEHOLDER = "^_^";
|
||||
private static final String SMILING_PLACEHOLDER_REX = "\\^_\\^";
|
||||
private static final String SMILING_PLACEHOLDER_REGEX = "(\\^_\\^)(\\w|-|$|\\.)+(\\^_\\^)";
|
||||
private static final Pattern SMILING_PLACEHOLDER_REGEX_PATTERN = Pattern.compile(SMILING_PLACEHOLDER_REGEX);
|
||||
private static final String CRYING_PLACEHOLDER_REX = "\\^o\\^";
|
||||
private static final String CRYING_PLACEHOLDER_REGEX = "(\\^o\\^)(\\w|-|$|\\.)+(\\^o\\^)";
|
||||
private static final Pattern CRYING_PLACEHOLDER_REGEX_PATTERN = Pattern.compile(CRYING_PLACEHOLDER_REGEX);
|
||||
private static final List<String> UNIT_SYMBOLS = Arrays.asList("%", "G", "g", "M", "m", "K", "k", "B", "b");
|
||||
|
||||
/**
|
||||
* private constructor, not allow to create instance.
|
||||
*/
|
||||
private CollectUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Regularly verifying whether a string is a combination of numbers and units
|
||||
*/
|
||||
private static final String DOUBLE_AND_UNIT_CHECK_REGEX = "^[.\\d+" + String.join("", UNIT_SYMBOLS) + "]+$";
|
||||
|
||||
/**
|
||||
* count match keyword number
|
||||
* @param content content
|
||||
* @param keyword keyword
|
||||
* @return match num
|
||||
*/
|
||||
public static int countMatchKeyword(String content, String keyword) {
|
||||
if (StringUtils.isAnyEmpty(content, keyword)) {
|
||||
return 0;
|
||||
}
|
||||
try {
|
||||
Pattern pattern = Pattern.compile(keyword);
|
||||
Matcher matcher = pattern.matcher(content);
|
||||
int count = 0;
|
||||
while (matcher.find()) {
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
} catch (Exception e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static DoubleAndUnit extractDoubleAndUnitFromStr(String str) {
|
||||
if (StringUtils.isEmpty(str)) {
|
||||
return null;
|
||||
}
|
||||
DoubleAndUnit doubleAndUnit = new DoubleAndUnit();
|
||||
try {
|
||||
Double doubleValue = Double.parseDouble(str);
|
||||
doubleAndUnit.setValue(doubleValue);
|
||||
return doubleAndUnit;
|
||||
} catch (Exception e) {
|
||||
log.debug(e.getMessage());
|
||||
}
|
||||
|
||||
if (!str.matches(DOUBLE_AND_UNIT_CHECK_REGEX)){
|
||||
return doubleAndUnit;
|
||||
}
|
||||
// extract unit from str value, eg: 23.43GB, 33KB, 44.22G
|
||||
try {
|
||||
// B KB MB GB % ....
|
||||
for (String unitSymbol : UNIT_SYMBOLS) {
|
||||
int index = str.indexOf(unitSymbol);
|
||||
if (index == 0) {
|
||||
Double doubleValue = 0d;
|
||||
String unit = str.trim();
|
||||
doubleAndUnit.setValue(doubleValue);
|
||||
doubleAndUnit.setUnit(unit);
|
||||
return doubleAndUnit;
|
||||
}
|
||||
if (index > 0) {
|
||||
Double doubleValue = Double.parseDouble(str.substring(0, index));
|
||||
String unit = str.substring(index).trim();
|
||||
doubleAndUnit.setValue(doubleValue);
|
||||
doubleAndUnit.setUnit(unit);
|
||||
return doubleAndUnit;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.debug(e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* double and unit
|
||||
*/
|
||||
public static final class DoubleAndUnit {
|
||||
|
||||
private Double value;
|
||||
private String unit;
|
||||
|
||||
public Double getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(Double value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getUnit() {
|
||||
return unit;
|
||||
}
|
||||
|
||||
public void setUnit(String unit) {
|
||||
this.unit = unit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get timeout integer
|
||||
*
|
||||
* @param timeout timeout str
|
||||
* @return timeout
|
||||
*/
|
||||
public static int getTimeout(String timeout) {
|
||||
return getTimeout(timeout, DEFAULT_TIMEOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* get timeout integer or default value
|
||||
*
|
||||
* @param timeout timeout str
|
||||
* @param defaultTimeout default timeout
|
||||
* @return timeout
|
||||
*/
|
||||
public static int getTimeout(String timeout, int defaultTimeout) {
|
||||
if (StringUtils.isEmpty(timeout)) {
|
||||
return defaultTimeout;
|
||||
}
|
||||
try {
|
||||
return Double.valueOf(timeout).intValue();
|
||||
} catch (Exception e) {
|
||||
return defaultTimeout;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* assert prom field
|
||||
*/
|
||||
public static Boolean assertPromRequireField(String aliasField) {
|
||||
return CommonConstants.PROM_TIME.equals(aliasField) || CommonConstants.PROM_VALUE.equals(aliasField);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* is contains cryPlaceholder ^o^xxx^o^
|
||||
*
|
||||
* @param jsonElement json element
|
||||
* @return return true when contains
|
||||
*/
|
||||
public static boolean containCryPlaceholder(JsonElement jsonElement) {
|
||||
String jsonStr = jsonElement.toString();
|
||||
return CRYING_PLACEHOLDER_REGEX_PATTERN.matcher(jsonStr).find();
|
||||
}
|
||||
|
||||
public static boolean notContainCryPlaceholder(JsonElement jsonElement) {
|
||||
return !containCryPlaceholder(jsonElement);
|
||||
}
|
||||
|
||||
/**
|
||||
* match existed cry placeholder fields ^o^field^o^
|
||||
* @param jsonElement json element
|
||||
* @return match field str
|
||||
*/
|
||||
public static Set<String> matchCryPlaceholderField(JsonElement jsonElement) {
|
||||
String jsonStr = jsonElement.toString();
|
||||
return CRYING_PLACEHOLDER_REGEX_PATTERN.matcher(jsonStr).results()
|
||||
.map(item -> item.group().replaceAll(CRYING_PLACEHOLDER_REX, ""))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
/**
|
||||
* json parameter replacement
|
||||
*
|
||||
* @param jsonElement json
|
||||
* @param configmap parameter map
|
||||
* @return json
|
||||
*/
|
||||
public static JsonElement replaceCryPlaceholder(JsonElement jsonElement, Map<String, Configmap> configmap) {
|
||||
if (jsonElement.isJsonObject()) {
|
||||
JsonObject jsonObject = jsonElement.getAsJsonObject();
|
||||
Iterator<Map.Entry<String, JsonElement>> iterator = jsonObject.entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<String, JsonElement> entry = iterator.next();
|
||||
JsonElement element = entry.getValue();
|
||||
// Replace normal VALUE value
|
||||
if (element.isJsonPrimitive()) {
|
||||
// Check if there are special characters Replace
|
||||
String value = element.getAsString();
|
||||
Matcher cryingMatcher = CRYING_PLACEHOLDER_REGEX_PATTERN.matcher(value);
|
||||
if (cryingMatcher.find()) {
|
||||
cryingMatcher.reset();
|
||||
while (cryingMatcher.find()) {
|
||||
String group = cryingMatcher.group();
|
||||
String replaceField = group.replaceAll(CRYING_PLACEHOLDER_REX, "");
|
||||
Configmap param = configmap.get(replaceField);
|
||||
if (param != null) {
|
||||
if (param.getValue() == null) {
|
||||
if (group.length() == value.length()) {
|
||||
value = null;
|
||||
break;
|
||||
} else {
|
||||
value = value.replace(group, "");
|
||||
}
|
||||
} else {
|
||||
value = value.replace(group, (String) param.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
jsonObject.addProperty(entry.getKey(), value);
|
||||
}
|
||||
} else {
|
||||
jsonObject.add(entry.getKey(), replaceCryPlaceholder(entry.getValue(), configmap));
|
||||
}
|
||||
}
|
||||
} else if (jsonElement.isJsonArray()) {
|
||||
JsonArray jsonArray = jsonElement.getAsJsonArray();
|
||||
Iterator<JsonElement> iterator = jsonArray.iterator();
|
||||
int index = 0;
|
||||
while (iterator.hasNext()) {
|
||||
JsonElement element = iterator.next();
|
||||
if (element.isJsonPrimitive()) {
|
||||
// Check if there are special characters Replace
|
||||
String value = element.getAsString();
|
||||
Matcher cryingMatcher = CRYING_PLACEHOLDER_REGEX_PATTERN.matcher(value);
|
||||
if (cryingMatcher.find()) {
|
||||
cryingMatcher.reset();
|
||||
while (cryingMatcher.find()) {
|
||||
String group = cryingMatcher.group();
|
||||
String replaceField = group.replaceAll(CRYING_PLACEHOLDER_REX, "");
|
||||
Configmap param = configmap.get(replaceField);
|
||||
if (param != null) {
|
||||
if (param.getValue() == null) {
|
||||
if (group.length() == value.length()) {
|
||||
value = null;
|
||||
break;
|
||||
} else {
|
||||
value = value.replace(group, "");
|
||||
}
|
||||
} else {
|
||||
value = value.replace(group, (String) param.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
jsonArray.set(index, value == null ? JsonNull.INSTANCE : new JsonPrimitive(value));
|
||||
}
|
||||
} else {
|
||||
jsonArray.set(index, replaceCryPlaceholder(element, configmap));
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
return jsonElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* json parameter replacement
|
||||
*
|
||||
* @param jsonElement json
|
||||
* @param configmap parameter map
|
||||
* @return json
|
||||
*/
|
||||
public static JsonElement replaceSmilingPlaceholder(JsonElement jsonElement, Map<String, Configmap> configmap) {
|
||||
if (jsonElement.isJsonObject()) {
|
||||
JsonObject jsonObject = jsonElement.getAsJsonObject();
|
||||
Iterator<Map.Entry<String, JsonElement>> iterator = jsonObject.entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<String, JsonElement> entry = iterator.next();
|
||||
JsonElement element = entry.getValue();
|
||||
String key = entry.getKey();
|
||||
// Replace the attributes of the KEY-VALUE case such as http headers params
|
||||
if (key != null && key.startsWith(SMILING_PLACEHOLDER) && key.endsWith(SMILING_PLACEHOLDER)) {
|
||||
key = key.replaceAll(SMILING_PLACEHOLDER_REX, "");
|
||||
Configmap param = configmap.get(key);
|
||||
if (param != null && param.getType() == CommonConstants.PARAM_TYPE_MAP) {
|
||||
String jsonValue = (String) param.getValue();
|
||||
TypeReference<Map<String, String>> typeReference = new TypeReference<>() {
|
||||
};
|
||||
Map<String, String> map = JsonUtil.fromJson(jsonValue, typeReference);
|
||||
if (map != null) {
|
||||
map.forEach((name, value) -> {
|
||||
if (!StringUtils.isEmpty(name)) {
|
||||
jsonObject.addProperty(name, value);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
// Replace normal VALUE value
|
||||
if (element.isJsonPrimitive()) {
|
||||
// Check if there are special characters Replace
|
||||
String value = element.getAsString();
|
||||
Matcher smilingMatcher = SMILING_PLACEHOLDER_REGEX_PATTERN.matcher(value);
|
||||
if (smilingMatcher.find()) {
|
||||
smilingMatcher.reset();
|
||||
while (smilingMatcher.find()) {
|
||||
String group = smilingMatcher.group();
|
||||
String replaceField = group.replaceAll(SMILING_PLACEHOLDER_REX, "");
|
||||
Configmap param = configmap.get(replaceField);
|
||||
if (param != null) {
|
||||
if (param.getValue() == null) {
|
||||
if (group.length() == value.length()) {
|
||||
value = null;
|
||||
break;
|
||||
} else {
|
||||
value = value.replace(group, "");
|
||||
}
|
||||
} else {
|
||||
value = value.replace(group, (String) param.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
jsonObject.addProperty(entry.getKey(), value);
|
||||
}
|
||||
} else {
|
||||
jsonObject.add(entry.getKey(), replaceSmilingPlaceholder(entry.getValue(), configmap));
|
||||
}
|
||||
}
|
||||
} else if (jsonElement.isJsonArray()) {
|
||||
JsonArray jsonArray = jsonElement.getAsJsonArray();
|
||||
int index = 0;
|
||||
while (index < jsonArray.size()) {
|
||||
JsonElement element = jsonArray.get(index);
|
||||
if (element.isJsonPrimitive()) {
|
||||
// Check if there are special characters Replace
|
||||
String value = element.getAsString();
|
||||
Matcher smilingMatcher = SMILING_PLACEHOLDER_REGEX_PATTERN.matcher(value);
|
||||
if (smilingMatcher.find()) {
|
||||
smilingMatcher.reset();
|
||||
String[] arrayValues = null;
|
||||
while (smilingMatcher.find()) {
|
||||
String group = smilingMatcher.group();
|
||||
String replaceField = group.replaceAll(SMILING_PLACEHOLDER_REX, "");
|
||||
Configmap param = configmap.get(replaceField);
|
||||
if (param != null) {
|
||||
if (param.getValue() == null) {
|
||||
if (group.length() == value.length()) {
|
||||
value = null;
|
||||
break;
|
||||
} else {
|
||||
value = value.replace(group, "");
|
||||
}
|
||||
} else if (param.getType() == CommonConstants.PARAM_TYPE_ARRAY) {
|
||||
arrayValues = String.valueOf(param.getValue()).split(",");
|
||||
} else {
|
||||
value = value.replace(group, (String) param.getValue());
|
||||
}
|
||||
} else {
|
||||
value = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (arrayValues != null) {
|
||||
jsonArray.remove(index);
|
||||
index--;
|
||||
for (String arrayValue : arrayValues) {
|
||||
jsonArray.add(arrayValue);
|
||||
index++;
|
||||
}
|
||||
} else {
|
||||
jsonArray.set(index, value == null ? JsonNull.INSTANCE : new JsonPrimitive(value));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
jsonArray.set(index, replaceSmilingPlaceholder(element, configmap));
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
return jsonElement;
|
||||
}
|
||||
|
||||
public static String replaceUriSpecialChar(String uri) {
|
||||
uri = uri.replaceAll(" ", "%20");
|
||||
// todo more special
|
||||
return uri;
|
||||
}
|
||||
|
||||
|
||||
public static void replaceFieldsForPushStyleMonitor(Metrics metrics, Map<String, Configmap> configmap) {
|
||||
|
||||
List<Metrics.Field> pushFieldList = JsonUtil.fromJson((String) configmap.get("fields").getValue(), new TypeReference<>() {
|
||||
});
|
||||
metrics.setFields(pushFieldList);
|
||||
}
|
||||
|
||||
/**
|
||||
* convert 16 hexString to byte[]
|
||||
* eg: 302c0201010409636f6d6d756e697479a11c020419e502e7020100020100300e300c06082b060102010102000500
|
||||
* 16进制字符串不区分大小写,返回的数组相同
|
||||
* @param hexString 16 hexString
|
||||
* @return byte[]
|
||||
*/
|
||||
public static byte[] fromHexString(String hexString) {
|
||||
if (StringUtils.isEmpty(hexString)) {
|
||||
return null;
|
||||
}
|
||||
byte[] bytes = new byte[hexString.length() / HEX_STR_WIDTH];
|
||||
String hex;
|
||||
for (int i = 0; i < hexString.length() / HEX_STR_WIDTH; i++) {
|
||||
hex = hexString.substring(i * HEX_STR_WIDTH, i * HEX_STR_WIDTH + HEX_STR_WIDTH);
|
||||
bytes[i] = (byte) Integer.parseInt(hex, 16);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
-25
@@ -1,25 +0,0 @@
|
||||
org.apache.hertzbeat.collector.collect.http.HttpCollectImpl
|
||||
org.apache.hertzbeat.collector.collect.http.SslCertificateCollectImpl
|
||||
org.apache.hertzbeat.collector.collect.database.JdbcCommonCollect
|
||||
org.apache.hertzbeat.collector.collect.icmp.IcmpCollectImpl
|
||||
org.apache.hertzbeat.collector.collect.jmx.JmxCollectImpl
|
||||
org.apache.hertzbeat.collector.collect.redis.RedisCommonCollectImpl
|
||||
org.apache.hertzbeat.collector.collect.mongodb.MongodbSingleCollectImpl
|
||||
org.apache.hertzbeat.collector.collect.snmp.SnmpCollectImpl
|
||||
org.apache.hertzbeat.collector.collect.ssh.SshCollectImpl
|
||||
org.apache.hertzbeat.collector.collect.telnet.TelnetCollectImpl
|
||||
org.apache.hertzbeat.collector.collect.smtp.SmtpCollectImpl
|
||||
org.apache.hertzbeat.collector.collect.ntp.NtpCollectImpl
|
||||
org.apache.hertzbeat.collector.collect.websocket.WebsocketCollectImpl
|
||||
org.apache.hertzbeat.collector.collect.ftp.FtpCollectImpl
|
||||
org.apache.hertzbeat.collector.collect.mq.RocketmqSingleCollectImpl
|
||||
org.apache.hertzbeat.collector.collect.udp.UdpCollectImpl
|
||||
org.apache.hertzbeat.collector.collect.push.PushCollectImpl
|
||||
org.apache.hertzbeat.collector.collect.dns.DnsCollectImpl
|
||||
org.apache.hertzbeat.collector.collect.nginx.NginxCollectImpl
|
||||
org.apache.hertzbeat.collector.collect.memcached.MemcachedCollectImpl
|
||||
org.apache.hertzbeat.collector.collect.nebulagraph.NebulaGraphCollectImpl
|
||||
org.apache.hertzbeat.collector.collect.pop3.Pop3CollectImpl
|
||||
org.apache.hertzbeat.collector.collect.httpsd.HttpsdImpl
|
||||
org.apache.hertzbeat.collector.collect.redfish.RedfishCollectImpl
|
||||
org.apache.hertzbeat.collector.collect.nebulagraph.NgqlCollectImpl
|
||||
@@ -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.apache.hertzbeat.collector.config.CollectorAutoConfiguration
|
||||
@@ -1,58 +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.
|
||||
server:
|
||||
port: 1159
|
||||
shutdown: graceful
|
||||
tomcat:
|
||||
threads:
|
||||
min-spare: 1
|
||||
spring:
|
||||
application:
|
||||
name: ${HOSTNAME:@hertzbeat-collector@}${PID}
|
||||
profiles:
|
||||
active: cluster
|
||||
lifecycle:
|
||||
timeout-per-shutdown-phase: 10s
|
||||
jackson:
|
||||
default-property-inclusion: ALWAYS
|
||||
# need to disable spring boot mongodb auto config, or default mongodb connection tried and failed...
|
||||
autoconfigure:
|
||||
exclude: org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration, org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
|
||||
|
||||
---
|
||||
spring:
|
||||
config:
|
||||
activate:
|
||||
on-profile: cluster
|
||||
|
||||
collector:
|
||||
dispatch:
|
||||
entrance:
|
||||
netty:
|
||||
enabled: true
|
||||
# Config the collector unique identity name.
|
||||
identity: ${IDENTITY:}
|
||||
# Config the running mode(public or private), public cluster or private cloud-edge.
|
||||
mode: ${MODE:public}
|
||||
manager-host: ${MANAGER_HOST:}${MANAGER_IP:}
|
||||
manager-port: ${MANAGER_PORT:1158}
|
||||
|
||||
push:
|
||||
uri: "127.0.0.1:1157"
|
||||
|
||||
|
||||
common:
|
||||
queue:
|
||||
type: netty
|
||||
Vendored
-112
@@ -1,112 +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.apache.hertzbeat.collector.collect.common.cache;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import java.util.Optional;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Test case for {@link ConnectionCommonCache}
|
||||
*/
|
||||
class CommonCacheTest {
|
||||
|
||||
private AbstractConnection<?> mockConnection;
|
||||
|
||||
private ConnectionCommonCache<String, AbstractConnection<?>> cache;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
cache = new ConnectionCommonCache<>();
|
||||
mockConnection = new AbstractConnection<>() {
|
||||
@Override
|
||||
public Object getConnection() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeConnection() throws Exception {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAddAndRetrieveCache() {
|
||||
String key = "testKey";
|
||||
cache.addCache(key, mockConnection);
|
||||
|
||||
Optional<AbstractConnection<?>> retrieved = cache.getCache(key, false);
|
||||
assertTrue(retrieved.isPresent());
|
||||
assertSame(mockConnection, retrieved.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCacheTimeout() throws InterruptedException {
|
||||
String key = "timeoutKey";
|
||||
cache.addCache(key, mockConnection, 1L);
|
||||
|
||||
Thread.sleep(2);
|
||||
Optional<AbstractConnection<?>> retrieved = cache.getCache(key, false);
|
||||
assertFalse(retrieved.isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRemoveCache() {
|
||||
String key = "removeKey";
|
||||
cache.addCache(key, mockConnection);
|
||||
cache.removeCache(key);
|
||||
|
||||
Optional<AbstractConnection<?>> retrieved = cache.getCache(key, false);
|
||||
assertFalse(retrieved.isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRefreshCache() {
|
||||
String key = "refreshKey";
|
||||
cache.addCache(key, mockConnection, 5000L);
|
||||
|
||||
Optional<AbstractConnection<?>> firstRetrieval = cache.getCache(key, true);
|
||||
assertTrue(firstRetrieval.isPresent());
|
||||
|
||||
|
||||
Optional<AbstractConnection<?>> secondRetrieval = cache.getCache(key, false);
|
||||
assertTrue(secondRetrieval.isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testConcurrentAccess() throws InterruptedException {
|
||||
String key = "concurrentKey";
|
||||
cache.addCache(key, mockConnection);
|
||||
|
||||
Runnable accessCache = () -> {
|
||||
Optional<AbstractConnection<?>> retrieved = cache.getCache(key, false);
|
||||
assertTrue(retrieved.isPresent());
|
||||
};
|
||||
|
||||
Thread thread1 = new Thread(accessCache);
|
||||
Thread thread2 = new Thread(accessCache);
|
||||
thread1.start();
|
||||
thread2.start();
|
||||
|
||||
thread1.join();
|
||||
thread2.join();
|
||||
}
|
||||
}
|
||||
-35
@@ -1,35 +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.apache.hertzbeat.collector.collect.database;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Test case for {@link JdbcCommonCollect}
|
||||
*/
|
||||
class JdbcCommonCollectTest {
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
}
|
||||
|
||||
@Test
|
||||
void getInstance() {
|
||||
}
|
||||
}
|
||||
-56
@@ -1,56 +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.apache.hertzbeat.collector.collect.dns;
|
||||
|
||||
|
||||
import org.apache.hertzbeat.common.entity.job.Metrics;
|
||||
import org.apache.hertzbeat.common.entity.job.protocol.DnsProtocol;
|
||||
import org.apache.hertzbeat.common.entity.message.CollectRep;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
||||
/**
|
||||
* Test case for {@link DnsCollectImpl}
|
||||
*
|
||||
*/
|
||||
public class DnsCollectImplTest {
|
||||
private DnsProtocol dnsProtocol;
|
||||
private DnsCollectImpl dnsCollect;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
dnsCollect = new DnsCollectImpl();
|
||||
dnsProtocol = DnsProtocol.builder()
|
||||
.dnsServerIP("8.8.8.8")
|
||||
.queryClass("IN")
|
||||
.address("www.google.com")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCollect() {
|
||||
CollectRep.MetricsData.Builder builder = CollectRep.MetricsData.newBuilder();
|
||||
long monitorId = 666;
|
||||
String app = "testDNS";
|
||||
Metrics metrics = new Metrics();
|
||||
metrics.setDns(dnsProtocol);
|
||||
|
||||
dnsCollect.collect(builder, monitorId, app, metrics);
|
||||
}
|
||||
}
|
||||
-44
@@ -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.apache.hertzbeat.collector.collect.http;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Test case for {@link HttpCollectImpl}
|
||||
*/
|
||||
class HttpCollectImplTest {
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
}
|
||||
|
||||
@Test
|
||||
void getInstance() {
|
||||
}
|
||||
|
||||
@Test
|
||||
void collect() {
|
||||
}
|
||||
}
|
||||
-78
@@ -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.apache.hertzbeat.collector.collect.http.promethus.exporter;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import java.util.Map;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Test case for {@link ExporterParser}
|
||||
*/
|
||||
class ExporterParserTest {
|
||||
|
||||
@Test
|
||||
void textToMetric() {
|
||||
String resp = "# HELP disk_total_bytes Total space for path\n"
|
||||
+ "# TYPE disk_total_bytes gauge\n"
|
||||
+ "disk_total_bytes{path=\"C:\\\\hertzbeat\\\\repo\\\\testpath\",} 4.29496725504E11\n"
|
||||
+ "# HELP go_gc_cycles_automatic_gc_cycles_total Count of completed GC cycles generated by the Go runtime.\n"
|
||||
+ "# TYPE go_gc_cycles_automatic_gc_cycles_total counter\n"
|
||||
+ "go_gc_cycles_automatic_gc_cycles_total 0\n"
|
||||
+ "# HELP go_gc_cycles_forced_gc_cycles_total Count of completed GC cycles forced by the application.\n"
|
||||
+ "# TYPE go_gc_cycles_forced_gc_cycles_total counter\n"
|
||||
+ "go_gc_cycles_forced_gc_cycles_total 0\n"
|
||||
+ "# HELP go_gc_cycles_total_gc_cycles_total Count of all completed GC cycles.\n"
|
||||
+ "# TYPE go_gc_cycles_total_gc_cycles_total counter\n"
|
||||
+ "go_gc_cycles_total_gc_cycles_total 0\n"
|
||||
+ "# HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles.\n"
|
||||
+ "# TYPE go_gc_duration_seconds summary\n"
|
||||
+ "go_gc_duration_seconds{quantile=\"0\"} 0\n"
|
||||
+ "go_gc_duration_seconds{quantile=\"0.25\"} 0\n"
|
||||
+ "go_gc_duration_seconds{quantile=\"0.5\"} 0\n"
|
||||
+ "go_gc_duration_seconds{quantile=\"0.75\"} 0\n"
|
||||
+ "go_gc_duration_seconds{quantile=\"1\"} 0\n"
|
||||
+ "# TYPE jvm info\n"
|
||||
+ "# HELP jvm VM version info\n"
|
||||
+ "jvm_info{runtime=\"OpenJDK Runtime Environment\",vendor=\"Azul Systems, Inc.\",version=\"11.0.13+8-LTS\"} 1.0\n"
|
||||
+ "# TYPE jvm_gc_collection_seconds summary\n"
|
||||
+ "# HELP jvm_gc_collection_seconds Time spent in a given JVM garbage collector in seconds.\n"
|
||||
+ "jvm_gc_collection_seconds_count{gc=\"G1 Young Generation\"} 10.0\n"
|
||||
+ "jvm_gc_collection_seconds_sum{gc=\"G1 Young Generation\"} 0.051\n"
|
||||
+ "jvm_gc_collection_seconds_count{gc=\"G1 Old Generation\"} 0.0\n"
|
||||
+ "jvm_gc_collection_seconds_sum{gc=\"G1 Old Generation\"} 0.0\n"
|
||||
+ "# TYPE resource_group_aggregate_usage_secs summary\n"
|
||||
+ "resource_group_aggregate_usage_secs{cluster=\"standalone\",quantile=\"0.5\"} 2.69245E-4\n"
|
||||
+ "resource_group_aggregate_usage_secs{cluster=\"standalone\",quantile=\"0.9\"} 3.49601E-4\n"
|
||||
+ "resource_group_aggregate_usage_secs_count{cluster=\"standalone\"} 13.0\n"
|
||||
+ "resource_group_aggregate_usage_secs_sum{cluster=\"standalone\"} 0.004832498\n"
|
||||
+ "resource_group_aggregate_usage_secs_created{cluster=\"standalone\"} 1.715842140749E9\n"
|
||||
+ "# TYPE metadata_store_ops_latency_ms histogram\n"
|
||||
+ "metadata_store_ops_latency_ms_bucket{cluster=\"standalone\",name=\"metadata-store\",type=\"get\",status=\"success\",le=\"1.0\"} 59.0\n"
|
||||
+ "metadata_store_ops_latency_ms_bucket{cluster=\"standalone\",name=\"metadata-store\",type=\"get\",status=\"success\",le=\"3.0\"} 61.0\n"
|
||||
+ "metadata_store_ops_latency_ms_bucket{cluster=\"standalone\",name=\"metadata-store\",type=\"get\",status=\"success\",le=\"5.0\"} 61.0\n"
|
||||
+ "# EOF";
|
||||
|
||||
ExporterParser parser = new ExporterParser();
|
||||
Map<String, MetricFamily> metricFamilyMap = parser.textToMetric(resp);
|
||||
assertEquals(5, metricFamilyMap.get("resource_group_aggregate_usage_secs").getMetricList().size());
|
||||
assertEquals(3, metricFamilyMap.get("metadata_store_ops_latency_ms").getMetricList().size());
|
||||
assertEquals(5, metricFamilyMap.get("go_gc_duration_seconds").getMetricList().size());
|
||||
assertEquals(9, metricFamilyMap.size());
|
||||
}
|
||||
}
|
||||
-136
@@ -1,136 +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.apache.hertzbeat.collector.collect.httpsd;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.apache.hertzbeat.collector.collect.httpsd.discovery.DiscoveryClient;
|
||||
import org.apache.hertzbeat.collector.collect.httpsd.discovery.DiscoveryClientManagement;
|
||||
import org.apache.hertzbeat.collector.collect.httpsd.discovery.entity.ServerInfo;
|
||||
import org.apache.hertzbeat.collector.collect.httpsd.discovery.entity.ServiceInstance;
|
||||
import org.apache.hertzbeat.common.entity.job.Metrics;
|
||||
import org.apache.hertzbeat.common.entity.job.protocol.HttpsdProtocol;
|
||||
import org.apache.hertzbeat.common.entity.message.CollectRep;
|
||||
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.Spy;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
/**
|
||||
* Test case for {@link HttpsdImpl}
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class HttpsdImplTest {
|
||||
@InjectMocks
|
||||
@Spy
|
||||
private HttpsdImpl httpsd;
|
||||
|
||||
@Mock
|
||||
private DiscoveryClient client;
|
||||
|
||||
@Mock
|
||||
private DiscoveryClientManagement discoveryClientManagement;
|
||||
|
||||
@Test
|
||||
void testServerCollect() {
|
||||
CollectRep.MetricsData.Builder builder = CollectRep.MetricsData.newBuilder();
|
||||
|
||||
String port = "123";
|
||||
String host = "127.0.0.1";
|
||||
HttpsdProtocol httpsdProtocol = HttpsdProtocol.builder()
|
||||
.port(port)
|
||||
.host(host)
|
||||
.discoveryClientTypeName("consul")
|
||||
.build();
|
||||
List<String> aliasField = new ArrayList<>();
|
||||
aliasField.add("address");
|
||||
aliasField.add("port");
|
||||
aliasField.add("responseTime");
|
||||
Metrics metrics = new Metrics();
|
||||
metrics.setName("server");
|
||||
metrics.setHttpsd(httpsdProtocol);
|
||||
metrics.setAliasFields(aliasField);
|
||||
|
||||
Mockito.when(discoveryClientManagement.getClient(httpsdProtocol)).thenReturn(client);
|
||||
ServerInfo serverInfo = ServerInfo.builder()
|
||||
.address(host)
|
||||
.port(port)
|
||||
.build();
|
||||
Mockito.when(client.getServerInfo()).thenReturn(serverInfo);
|
||||
httpsd.setDiscoveryClientManagement(discoveryClientManagement);
|
||||
httpsd.preCheck(metrics);
|
||||
httpsd.collect(builder, 1L, "test", metrics);
|
||||
for (CollectRep.ValueRow valueRow : builder.getValuesList()) {
|
||||
assertEquals(host, valueRow.getColumns(0));
|
||||
assertEquals(port, valueRow.getColumns(1));
|
||||
assertNotNull(valueRow.getColumns(2));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testServiceCollect() {
|
||||
CollectRep.MetricsData.Builder builder = CollectRep.MetricsData.newBuilder();
|
||||
|
||||
String port = "123";
|
||||
String host = "127.0.0.1";
|
||||
HttpsdProtocol httpsdProtocol = HttpsdProtocol.builder()
|
||||
.port(port)
|
||||
.host(host)
|
||||
.discoveryClientTypeName("consul")
|
||||
.build();
|
||||
List<String> aliasField = new ArrayList<>();
|
||||
aliasField.add("serviceId");
|
||||
aliasField.add("serviceName");
|
||||
aliasField.add("address");
|
||||
aliasField.add("port");
|
||||
Metrics metrics = new Metrics();
|
||||
metrics.setName("service");
|
||||
metrics.setHttpsd(httpsdProtocol);
|
||||
metrics.setAliasFields(aliasField);
|
||||
|
||||
Mockito.when(discoveryClientManagement.getClient(httpsdProtocol)).thenReturn(client);
|
||||
|
||||
String serviceId = "test";
|
||||
String serviceName = "service";
|
||||
List<ServiceInstance> serviceInstances = new ArrayList<>();
|
||||
serviceInstances.add(ServiceInstance.builder()
|
||||
.serviceId(serviceId)
|
||||
.serviceName(serviceName)
|
||||
.address(host)
|
||||
.port(Integer.parseInt(port))
|
||||
.build());
|
||||
|
||||
Mockito.when(client.getServices()).thenReturn(serviceInstances);
|
||||
httpsd.setDiscoveryClientManagement(discoveryClientManagement);
|
||||
httpsd.preCheck(metrics);
|
||||
httpsd.collect(builder, 1L, "test", metrics);
|
||||
assertEquals(builder.getValuesCount(), 1);
|
||||
for (CollectRep.ValueRow valueRow : builder.getValuesList()) {
|
||||
assertEquals(serviceId, valueRow.getColumns(0));
|
||||
assertEquals(serviceName, valueRow.getColumns(1));
|
||||
assertEquals(host, valueRow.getColumns(2));
|
||||
assertEquals(port, valueRow.getColumns(3));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-44
@@ -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.apache.hertzbeat.collector.collect.jmx;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Test case for {@link JmxCollectImpl}
|
||||
*/
|
||||
class JmxCollectImplTest {
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
}
|
||||
|
||||
@Test
|
||||
void getInstance() {
|
||||
}
|
||||
|
||||
@Test
|
||||
void collect() {
|
||||
}
|
||||
}
|
||||
-200
@@ -1,200 +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.apache.hertzbeat.collector.collect.nebulagraph;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.apache.hertzbeat.common.entity.job.Metrics;
|
||||
import org.apache.hertzbeat.common.entity.job.protocol.NgqlProtocol;
|
||||
import org.apache.hertzbeat.common.entity.message.CollectRep;
|
||||
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.MockedConstruction;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
/**
|
||||
* Test case for {@link NgqlCollectImpl}
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class NgqlCollectImplTest {
|
||||
|
||||
@InjectMocks
|
||||
private NgqlCollectImpl ngqlCollect;
|
||||
|
||||
private NgqlProtocol ngqlProtocol;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
ngqlProtocol = NgqlProtocol.builder()
|
||||
.host("127.0.0.1")
|
||||
.port("9669")
|
||||
.password("123456")
|
||||
.username("root")
|
||||
.timeout("60000").build();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testOneRowCollect() {
|
||||
String ngql = "SHOW COLLATION;";
|
||||
String charset = "utf8";
|
||||
String collation = "utf8_bin";
|
||||
CollectRep.MetricsData.Builder builder = CollectRep.MetricsData.newBuilder();
|
||||
ngqlProtocol.setCommands(Collections.singletonList(ngql));
|
||||
ngqlProtocol.setParseType("oneRow");
|
||||
List<String> aliasField = Arrays.asList("Collation", "Charset");
|
||||
|
||||
List<Map<String, Object>> result = new ArrayList<>();
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("Collation", "utf8_bin");
|
||||
data.put("Charset", "utf8");
|
||||
result.add(data);
|
||||
|
||||
MockedConstruction<NebulaTemplate> mocked =
|
||||
Mockito.mockConstruction(NebulaTemplate.class, (template, context) -> {
|
||||
Mockito.doNothing().when(template).closeSessionAndPool();
|
||||
Mockito.when(template.initSession(ngqlProtocol)).thenReturn(true);
|
||||
Mockito.when(template.executeCommand(ngql)).thenReturn(result);
|
||||
});
|
||||
|
||||
Metrics metrics = new Metrics();
|
||||
metrics.setNgql(ngqlProtocol);
|
||||
metrics.setAliasFields(aliasField);
|
||||
ngqlCollect.preCheck(metrics);
|
||||
ngqlCollect.collect(builder, 1L, "test", metrics);
|
||||
assertEquals(builder.getValuesCount(), 1);
|
||||
assertEquals(builder.getValues(0).getColumns(0), collation);
|
||||
assertEquals(builder.getValues(0).getColumns(1), charset);
|
||||
mocked.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFilterCountCollect() {
|
||||
String command = "offline#SHOW HOSTS#Status#OFFLINE";
|
||||
CollectRep.MetricsData.Builder builder = CollectRep.MetricsData.newBuilder();
|
||||
ngqlProtocol.setCommands(Collections.singletonList(command));
|
||||
ngqlProtocol.setParseType("filterCount");
|
||||
List<String> aliasField = Collections.singletonList("offline");
|
||||
|
||||
List<Map<String, Object>> result = new ArrayList<>();
|
||||
for (int i = 0; i < 3; i++) {
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("Host", "graph" + 0);
|
||||
data.put("Port", "9669");
|
||||
data.put("Status", i == 0 ? "OFFLINE" : "ONLINE");
|
||||
result.add(data);
|
||||
}
|
||||
MockedConstruction<NebulaTemplate> mocked =
|
||||
Mockito.mockConstruction(NebulaTemplate.class, (template, context) -> {
|
||||
Mockito.doNothing().when(template).closeSessionAndPool();
|
||||
Mockito.when(template.initSession(ngqlProtocol)).thenReturn(true);
|
||||
Mockito.when(template.executeCommand("SHOW HOSTS")).thenReturn(result);
|
||||
});
|
||||
|
||||
Metrics metrics = new Metrics();
|
||||
metrics.setNgql(ngqlProtocol);
|
||||
metrics.setAliasFields(aliasField);
|
||||
ngqlCollect.preCheck(metrics);
|
||||
ngqlCollect.collect(builder, 1L, "test", metrics);
|
||||
assertEquals(1, builder.getValuesCount());
|
||||
assertEquals("1", builder.getValues(0).getColumns(0));
|
||||
mocked.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMultiRowCollect() {
|
||||
String command = "SHOW HOSTS";
|
||||
CollectRep.MetricsData.Builder builder = CollectRep.MetricsData.newBuilder();
|
||||
ngqlProtocol.setCommands(Collections.singletonList(command));
|
||||
ngqlProtocol.setParseType("multiRow");
|
||||
List<String> aliasField = Arrays.asList("Host", "Port", "Status");
|
||||
|
||||
List<Map<String, Object>> result = new ArrayList<>();
|
||||
for (int i = 0; i < 3; i++) {
|
||||
Map<String, Object> data = new LinkedHashMap<>();
|
||||
data.put("Host", "graph" + i);
|
||||
data.put("Port", "9669");
|
||||
data.put("Status", i == 0 ? "OFFLINE" : "ONLINE");
|
||||
result.add(data);
|
||||
}
|
||||
MockedConstruction<NebulaTemplate> mocked =
|
||||
Mockito.mockConstruction(NebulaTemplate.class, (template, context) -> {
|
||||
Mockito.doNothing().when(template).closeSessionAndPool();
|
||||
Mockito.when(template.initSession(ngqlProtocol)).thenReturn(true);
|
||||
Mockito.when(template.executeCommand(command)).thenReturn(result);
|
||||
});
|
||||
|
||||
Metrics metrics = new Metrics();
|
||||
metrics.setNgql(ngqlProtocol);
|
||||
metrics.setAliasFields(aliasField);
|
||||
ngqlCollect.preCheck(metrics);
|
||||
ngqlCollect.collect(builder, 1L, "test", metrics);
|
||||
assertEquals(3, builder.getValuesCount());
|
||||
for (int i = 0; i < result.size(); i++) {
|
||||
List<Map.Entry<String, Object>> list = new ArrayList<>(result.get(i).entrySet());
|
||||
for (int j = 0; j < list.size(); j++) {
|
||||
assertEquals(list.get(j).getValue().toString(), builder.getValues(i).getColumns(j));
|
||||
}
|
||||
}
|
||||
mocked.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testColumnsCollect() {
|
||||
String command = "SHOW HOSTS";
|
||||
CollectRep.MetricsData.Builder builder = CollectRep.MetricsData.newBuilder();
|
||||
ngqlProtocol.setCommands(Collections.singletonList(command));
|
||||
ngqlProtocol.setParseType("columns");
|
||||
List<String> aliasField = Arrays.asList("graph0", "graph1", "graph2");
|
||||
|
||||
List<Map<String, Object>> result = new ArrayList<>();
|
||||
for (int i = 0; i < 3; i++) {
|
||||
Map<String, Object> data = new LinkedHashMap<>();
|
||||
data.put("Host", "graph" + i);
|
||||
data.put("Port", "9669" + i);
|
||||
data.put("Status", i == 0 ? "OFFLINE" : "ONLINE");
|
||||
result.add(data);
|
||||
}
|
||||
MockedConstruction<NebulaTemplate> mocked =
|
||||
Mockito.mockConstruction(NebulaTemplate.class, (template, context) -> {
|
||||
Mockito.doNothing().when(template).closeSessionAndPool();
|
||||
Mockito.when(template.initSession(ngqlProtocol)).thenReturn(true);
|
||||
Mockito.when(template.executeCommand(command)).thenReturn(result);
|
||||
});
|
||||
|
||||
Metrics metrics = new Metrics();
|
||||
metrics.setNgql(ngqlProtocol);
|
||||
metrics.setAliasFields(aliasField);
|
||||
ngqlCollect.preCheck(metrics);
|
||||
ngqlCollect.collect(builder, 1L, "test", metrics);
|
||||
assertEquals(1, builder.getValuesCount());
|
||||
for (int i = 0; i < 3; i++) {
|
||||
assertEquals("9669" + i, builder.getValues(0).getColumns(i));
|
||||
}
|
||||
mocked.close();
|
||||
}
|
||||
|
||||
}
|
||||
-44
@@ -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.apache.hertzbeat.collector.collect.snmp;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Test case for {@link SnmpCollectImpl}
|
||||
*/
|
||||
class SnmpCollectImplTest {
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
}
|
||||
|
||||
@Test
|
||||
void getInstance() {
|
||||
}
|
||||
|
||||
@Test
|
||||
void collect() {
|
||||
}
|
||||
}
|
||||
-44
@@ -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.apache.hertzbeat.collector.collect.ssh;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Test case for {@link SshCollectImpl}
|
||||
*/
|
||||
class SshCollectImplTest {
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
}
|
||||
|
||||
@Test
|
||||
void getInstance() {
|
||||
}
|
||||
|
||||
@Test
|
||||
void collect() {
|
||||
}
|
||||
}
|
||||
-39
@@ -1,39 +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.apache.hertzbeat.collector.dispatch;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Test case for {@link CommonDispatcher}
|
||||
*/
|
||||
class CommonDispatcherTest {
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
}
|
||||
|
||||
@Test
|
||||
void dispatchMetricsTask() {
|
||||
}
|
||||
|
||||
@Test
|
||||
void dispatchCollectData() {
|
||||
}
|
||||
}
|
||||
-44
@@ -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.apache.hertzbeat.collector.dispatch;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Test case for {@link MetricsCollectorQueue}
|
||||
*/
|
||||
class MetricsCollectorQueueTest {
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
}
|
||||
|
||||
@Test
|
||||
void addJob() {
|
||||
}
|
||||
|
||||
@Test
|
||||
void getJob() {
|
||||
}
|
||||
}
|
||||
@@ -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.apache.hertzbeat.collector.dispatch;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Test case for {@link WorkerPool}
|
||||
*/
|
||||
class WorkerPoolTest {
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
}
|
||||
|
||||
@Test
|
||||
void executeJob() {
|
||||
}
|
||||
|
||||
@Test
|
||||
void destroy() {
|
||||
}
|
||||
}
|
||||
-52
@@ -1,52 +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.apache.hertzbeat.collector.dispatch.entrance.internal;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Test case for {@link CollectJobService}
|
||||
*/
|
||||
class CollectJobServiceTest {
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
}
|
||||
|
||||
@Test
|
||||
void collectSyncJobData() {
|
||||
}
|
||||
|
||||
@Test
|
||||
void addAsyncCollectJob() {
|
||||
}
|
||||
|
||||
@Test
|
||||
void updateAsyncCollectJob() {
|
||||
}
|
||||
|
||||
@Test
|
||||
void cancelAsyncCollectJob() {
|
||||
}
|
||||
}
|
||||
-70
@@ -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.apache.hertzbeat.collector.dispatch.unit;
|
||||
|
||||
import org.apache.hertzbeat.collector.dispatch.unit.impl.DataSizeConvert;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* Test case for {@link DataSizeConvert}
|
||||
*/
|
||||
|
||||
class DataSizeConvertTest {
|
||||
|
||||
private DataSizeConvert convert;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
this.convert = new DataSizeConvert();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testConvert() {
|
||||
|
||||
assertEquals("1", convert.convert("1024", "B", "KB"));
|
||||
assertEquals("1024", convert.convert("1024", "B", "B"));
|
||||
assertEquals("1", convert.convert("1024", "B", "kb"));
|
||||
assertEquals("1", convert.convert("1024", "b", "kb"));
|
||||
assertEquals("1", convert.convert("1024", "KB", "MB"));
|
||||
assertEquals("1", convert.convert("1024", "MB", "GB"));
|
||||
assertNull(convert.convert("", "B", "KB"));
|
||||
assertNull(convert.convert("1024", "INVALID", "KB"));
|
||||
assertNull(convert.convert("1024", "B", "INVALID"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCheckUnit() {
|
||||
assertTrue(convert.checkUnit("KB"));
|
||||
assertTrue(convert.checkUnit("kb"));
|
||||
assertTrue(convert.checkUnit("Kb"));
|
||||
assertTrue(convert.checkUnit("kB"));
|
||||
assertTrue(convert.checkUnit("MB"));
|
||||
assertTrue(convert.checkUnit("GB"));
|
||||
assertFalse(convert.checkUnit("INVALID"));
|
||||
assertFalse(convert.checkUnit(null));
|
||||
assertFalse(convert.checkUnit(""));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,156 +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.apache.hertzbeat.collector.util;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.apache.hertzbeat.common.entity.job.Configmap;
|
||||
import org.apache.hertzbeat.common.entity.job.Metrics;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Test case for {@link CollectUtil}
|
||||
*/
|
||||
class CollectUtilTest {
|
||||
|
||||
private static final ObjectMapper JSON_MAPPER = new ObjectMapper();
|
||||
|
||||
@Test
|
||||
void countMatchKeyword() {
|
||||
int keyword = CollectUtil.countMatchKeyword("hertzbeat", "e");
|
||||
assertEquals(2, keyword);
|
||||
int i = CollectUtil.countMatchKeyword("查询id183", "\\d");
|
||||
assertEquals(3, i);
|
||||
assertEquals(0, CollectUtil.countMatchKeyword(null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getTimeout() {
|
||||
int timeout1 = CollectUtil.getTimeout("4000");
|
||||
assertEquals(4000, timeout1);
|
||||
int timeout2 = CollectUtil.getTimeout("4000.5");
|
||||
assertEquals(4000, timeout2);
|
||||
int timeout3 = CollectUtil.getTimeout("a4000.5");
|
||||
assertEquals(60000, timeout3);
|
||||
int timeout4 = CollectUtil.getTimeout(null);
|
||||
assertEquals(60000, timeout4);
|
||||
}
|
||||
|
||||
@Test
|
||||
void extractDoubleAndUnitFromStr() {
|
||||
CollectUtil.DoubleAndUnit res1 = CollectUtil.extractDoubleAndUnitFromStr("20.5%");
|
||||
assertNotNull(res1);
|
||||
assertEquals(20.5, res1.getValue());
|
||||
assertEquals("%", res1.getUnit());
|
||||
|
||||
CollectUtil.DoubleAndUnit res2 = CollectUtil.extractDoubleAndUnitFromStr("");
|
||||
assertNull(res2);
|
||||
|
||||
CollectUtil.DoubleAndUnit res3 = CollectUtil.extractDoubleAndUnitFromStr("KB");
|
||||
assertNotNull(res3);
|
||||
assertEquals(0, res3.getValue());
|
||||
assertEquals("KB", res3.getUnit());
|
||||
|
||||
CollectUtil.DoubleAndUnit res4 = CollectUtil.extractDoubleAndUnitFromStr("GRAPH0");
|
||||
assertNull(res4.getValue());
|
||||
assertNull(res4.getUnit());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void assertPromRequireField() {
|
||||
assertEquals(true, CollectUtil.assertPromRequireField("timestamp"));
|
||||
assertEquals(true, CollectUtil.assertPromRequireField("value"));
|
||||
assertEquals(false, CollectUtil.assertPromRequireField("timestamp_value"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void containCryPlaceholder() {
|
||||
Metrics metrics = Metrics.builder().name("^o^name^o^").build();
|
||||
JsonElement jsonElement = new Gson().toJsonTree(metrics);
|
||||
assertTrue(CollectUtil.containCryPlaceholder(jsonElement));
|
||||
}
|
||||
|
||||
@Test
|
||||
void replaceCryPlaceholder() throws JsonMappingException, JsonProcessingException {
|
||||
Metrics metrics = Metrics.builder().name("^o^name^o^").build();
|
||||
JsonElement jsonElement = new Gson().toJsonTree(metrics);
|
||||
Map<String, Configmap> configmap = new HashMap<>();
|
||||
Configmap config = Configmap.builder().key("name").value("张三").build();
|
||||
configmap.put("name", config);
|
||||
JsonElement res1 = CollectUtil.replaceCryPlaceholder(jsonElement, configmap);
|
||||
|
||||
Metrics metricsTarget = Metrics.builder().name("张三").build();
|
||||
JsonElement jsonElementTarget = new Gson().toJsonTree(metricsTarget);
|
||||
assertEquals(JSON_MAPPER.readTree(jsonElementTarget.toString()), JSON_MAPPER.readTree(res1.toString()));
|
||||
|
||||
List<Metrics> metricsList = new ArrayList<>();
|
||||
metricsList.add(metrics);
|
||||
metricsList.add(metrics);
|
||||
JsonElement jsonArray = new Gson().toJsonTree(metricsList);
|
||||
JsonElement res2 = CollectUtil.replaceCryPlaceholder(jsonArray, configmap);
|
||||
|
||||
List<Metrics> metricsListTarget = new ArrayList<>();
|
||||
metricsListTarget.add(metricsTarget);
|
||||
metricsListTarget.add(metricsTarget);
|
||||
JsonElement jsonArrayTarget = new Gson().toJsonTree(metricsListTarget);
|
||||
assertEquals(JSON_MAPPER.readTree(jsonArrayTarget.toString()), JSON_MAPPER.readTree(res2.toString()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void replaceSmilingPlaceholder() throws JsonMappingException, JsonProcessingException {
|
||||
Metrics metrics = Metrics.builder().name("^_^name^_^").build();
|
||||
JsonElement jsonElement = new Gson().toJsonTree(metrics);
|
||||
HashMap<String, Configmap> configmap = new HashMap<>();
|
||||
Configmap config = Configmap.builder().key("name").value("张三").build();
|
||||
configmap.put("name", config);
|
||||
JsonElement res = CollectUtil.replaceSmilingPlaceholder(jsonElement, configmap);
|
||||
Metrics metricsTarget = Metrics.builder().name("张三").build();
|
||||
JsonElement jsonElement2 = new Gson().toJsonTree(metricsTarget);
|
||||
assertEquals(JSON_MAPPER.readTree(jsonElement2.toString()), JSON_MAPPER.readTree(res.toString()));
|
||||
|
||||
List<Metrics> metricsList = new ArrayList<>();
|
||||
metricsList.add(metrics);
|
||||
metricsList.add(metrics);
|
||||
JsonElement jsonArray = new Gson().toJsonTree(metricsList);
|
||||
JsonElement res2 = CollectUtil.replaceSmilingPlaceholder(jsonArray, configmap);
|
||||
|
||||
List<Metrics> metricsListTarget = new ArrayList<>();
|
||||
metricsListTarget.add(metricsTarget);
|
||||
metricsListTarget.add(metricsTarget);
|
||||
JsonElement jsonArrayTarget = new Gson().toJsonTree(metricsListTarget);
|
||||
assertEquals(JSON_MAPPER.readTree(jsonArrayTarget.toString()), JSON_MAPPER.readTree(res2.toString()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void replaceUriSpecialChar() {
|
||||
assertEquals("google.com%20", CollectUtil.replaceUriSpecialChar("google.com "));
|
||||
}
|
||||
}
|
||||
@@ -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.apache.hertzbeat.collector.util;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Test case for {@link JsonPathParser}
|
||||
*/
|
||||
class JsonPathParserTest {
|
||||
|
||||
private static final String JSON_ARRAY = "[{'name': 'tom', 'speed': '433'},{'name': 'lili', 'speed': '543'}]";
|
||||
|
||||
public static final String JSON_OBJECT = """
|
||||
{
|
||||
"store": {
|
||||
"book": [
|
||||
{
|
||||
"category": "reference",
|
||||
"author": "Nigel Rees",
|
||||
"title": "Sayings of the Century",
|
||||
"price": 8.95
|
||||
},
|
||||
{
|
||||
"category": "fiction",
|
||||
"author": "Evelyn Waugh",
|
||||
"title": "Sword of Honour",
|
||||
"price": 12.99
|
||||
},
|
||||
{
|
||||
"category": "fiction",
|
||||
"author": "Herman Melville",
|
||||
"title": "Moby Dick",
|
||||
"isbn": "0-553-21311-3",
|
||||
"price": 8.99
|
||||
},
|
||||
{
|
||||
"category": "fiction",
|
||||
"author": "J. R. R. Tolkien",
|
||||
"title": "The Lord of the Rings",
|
||||
"isbn": "0-395-19395-8",
|
||||
"price": 22.99
|
||||
}
|
||||
],
|
||||
"bicycle": {
|
||||
"color": "red",
|
||||
"price": 19.95,
|
||||
"gears": [23, 50],
|
||||
"extra": {"x": 0},
|
||||
"escape": "Esc\\b\\f\\n\\r\\t\\u002A",
|
||||
"nullValue": null
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
@Test
|
||||
void parseContentWithJsonPath() {
|
||||
// process array
|
||||
List<Object> tom = JsonPathParser.parseContentWithJsonPath(JSON_ARRAY, "$[0].name");
|
||||
assertNotNull(tom);
|
||||
assertEquals("tom", tom.get(0));
|
||||
// get json array map
|
||||
List<Object> entry = JsonPathParser.parseContentWithJsonPath(JSON_ARRAY, "$[1]");
|
||||
assertNotNull(entry);
|
||||
entry.forEach(e -> {
|
||||
assertInstanceOf(Map.class, e);
|
||||
assertEquals("543", ((Map) e).get("speed"));
|
||||
});
|
||||
// process object
|
||||
List<Object> author = JsonPathParser.parseContentWithJsonPath(JSON_OBJECT, "$.store.book[0].author");
|
||||
assertNotNull(author);
|
||||
assertEquals("Nigel Rees", author.get(0));
|
||||
// get json object map
|
||||
List<Object> book = JsonPathParser.parseContentWithJsonPath(JSON_OBJECT, "$.store.book[1]");
|
||||
assertNotNull(book);
|
||||
book.forEach(e -> {
|
||||
assertInstanceOf(Map.class, e);
|
||||
assertEquals("Sword of Honour", ((Map) e).get("title"));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -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.apache.hertzbeat.collector.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* test case for {@link PrivateKeyUtils}
|
||||
*/
|
||||
class PrivateKeyUtilsTest {
|
||||
|
||||
@DisplayName("write key to ~/.ssh")
|
||||
@Test
|
||||
void writePrivateKey() throws IOException {
|
||||
var key = "-----BEGIN RSA PRIVATE KEY-----\n"
|
||||
+ "MIIEogIBAAKCAQEA4ctFYk/xy89L6/6YFeeMrwCW9lCP/ThXMn+9G63s5bGn4oIN\n"
|
||||
+ "8cEf/JYkmGw8vMP41IAP9dyH8ji2wIZSLeTPWucEK6P6jA01iIBQ95ng6RTsnQgL\n"
|
||||
+ "h4pYHxlEaNHcXkjy5GlMdzaWadjdRevpThGR1VOtWFtK3yoC0c/te2Junu04f+11\n"
|
||||
+ "cpk8QvmVfzrBUooVnG0/7oekwUy1c5sSl0qVoLzXOv4XG9w34cyvacFC30zv1Nl8\n"
|
||||
+ "ASi2pmOBVx9njPvqQ7qZrDk0nwn+RZUmGh/PbmHxrBV7ZA5NjZcEnf2VGIfjGUVu\n"
|
||||
+ "qE4VnkbvS4j03afV2rsp1yo74K+k/ZC6GCHB5QIBIwKCAQBG9r4I9I3SVxfcdJYy\n"
|
||||
+ "xR2WFiDREgFeNkdKYqkl9NVsws5dIY9am8g5cQQv54DNnK1KGZ6dulaclXtD0nGZ\n"
|
||||
+ "ZSs505OYr+EHcd2f7dBN0Uavp32QcD4jSLycD0FixZ0HsIbaEnceJxlUd1t8YBYf\n"
|
||||
+ "2aLcpUUbxOulORbUOgjPAa286uDeQYN5IbdruDfvbuFFm7hBoGZoKLJ7FPcJ0U3A\n"
|
||||
+ "14KRK+Z1oCYJIS0ubaHbhaPIVPPQEmTNHpsvxIJXfZtVy9+XIuBGmD3+Aq6SSFPC\n"
|
||||
+ "A8mU1iKzzdRCXZwvPeUiivIIZc6DRXjhtJ2Lya/XndKidOT/QUj8Z+f9pWAonlzM\n"
|
||||
+ "3PMXAoGBAPvzctkkDjUJjLyEuYQq8soYokS4n4ykFTP5oFgnodK/cYocbxTT6Tn9\n"
|
||||
+ "vH7b6lK6ZAf+tZk8rcEeIO650pOvmaa1/OuZSxfcFUGBvOvYXiHF7zmkePh/pQgB\n"
|
||||
+ "7Cl0RYrI52Cjbd9aCUIYK3A82qsUq30INGeOhMNrfaHn2pgx8xlDAoGBAOVsNctw\n"
|
||||
+ "CHnLaIQX8eS+eUcQEm+NZppnDBJavdpP48ZZM/t5v/2fQ5ytbYqk0KEzIGu0dP8g\n"
|
||||
+ "jfB76JbMvStvTfB+TrXsfhGyA3oJrEcG+3IUshsRU2sohT1ScY27z2VMLgilnWvF\n"
|
||||
+ "7t49sQm9uB/yn669n8LIciHxDItOpvqgKdG3AoGBAO2NxA6PtZ+4jAIz/19bsbc7\n"
|
||||
+ "zDIqaovrKe8tMMglXg/ZE0e0aLvdvqRkRAKU1Z51Ob5lLuDwEYoyWZCgk1gL90Vp\n"
|
||||
+ "wpT+P3zlcyCBo39IWMDB8C8IydRbF/GbaaNtoKds92m+qWwwUd87XCf+3M0wvvI6\n"
|
||||
+ "75TW1PLEbyOgFz8Khh8hAoGBAJbDc87Ul9sCAtp2Ip2hvWk2coPR8vfADz9C8cn5\n"
|
||||
+ "/BShBOcVfipSt2b1n8GCP/TnFU4XgBVeiSkA9+4Rg6AzMzejdY1+JvWvfqCnRVM/\n"
|
||||
+ "GkOnMzZb17tyZi+ck8OKC/IcHkAyUYFWL0GWQSOojvBsPQxt+0V8aEIwsHjNSSha\n"
|
||||
+ "nyNpAoGAd0XqdByRxbWgg5ZsvM0tvrpMITpEZsGMG9VeQPGl0wsQvC2zw5QGLvz/\n"
|
||||
+ "57YhofOOr0M3yElcFA9Imvek5CYZsyL8eIWGZyadfRiYvGOUyvDDO3BYRG4DmhyF\n"
|
||||
+ "KVk3URjEuOCC29ORvZ/7HaCO9iuEbvAA/mrAtd7KdCA+3PzfEOw=\n"
|
||||
+ "-----END RSA PRIVATE KEY-----";
|
||||
PrivateKeyUtils.writePrivateKey("127.0.0.1", key);
|
||||
}
|
||||
}
|
||||
-120
@@ -1,120 +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.apache.hertzbeat</groupId>
|
||||
<version>2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>hertzbeat-common</artifactId>
|
||||
<name>${project.artifactId}</name>
|
||||
|
||||
<dependencies>
|
||||
<!-- 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-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||
</dependency>
|
||||
<!-- jpa -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.persistence</groupId>
|
||||
<artifactId>org.eclipse.persistence.jpa</artifactId>
|
||||
<version>4.0.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.hibernate.orm</groupId>
|
||||
<artifactId>hibernate-core</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!-- validation -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
<!-- jackson -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- swagger -->
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- Tool dependencies -->
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.protobuf</groupId>
|
||||
<artifactId>protobuf-java-util</artifactId>
|
||||
</dependency>
|
||||
<!-- Use apache.http.conn.util instead of sun.net.util -->
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
</dependency>
|
||||
<!-- caffeine-->
|
||||
<dependency>
|
||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||
<artifactId>caffeine</artifactId>
|
||||
</dependency>
|
||||
<!-- kafka -->
|
||||
<dependency>
|
||||
<groupId>org.apache.kafka</groupId>
|
||||
<artifactId>kafka-clients</artifactId>
|
||||
</dependency>
|
||||
<!-- expr calculate -->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-jexl3</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-collections4</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -1,60 +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.apache.hertzbeat.common.cache;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
/**
|
||||
* common cache factory
|
||||
*/
|
||||
public final class CacheFactory {
|
||||
private CacheFactory() {}
|
||||
|
||||
private static final CommonCacheService<String, Object> NOTICE_CACHE =
|
||||
new CaffeineCacheServiceImpl<>(10, 1000, Duration.ofDays(1), false);
|
||||
|
||||
private static final CommonCacheService<String, Object> ALERT_SILENCE_CACHE =
|
||||
new CaffeineCacheServiceImpl<>(10, 1000, Duration.ofDays(1), false);
|
||||
|
||||
private static final CommonCacheService<String, Object> ALERT_CONVERGE_CACHE =
|
||||
new CaffeineCacheServiceImpl<>(10, 1000, Duration.ofDays(1), false);
|
||||
|
||||
/**
|
||||
* get notice cache
|
||||
* @return caffeine cache
|
||||
*/
|
||||
public static CommonCacheService<String, Object> getNoticeCache() {
|
||||
return NOTICE_CACHE;
|
||||
}
|
||||
|
||||
/**
|
||||
* get alert silence cache
|
||||
* @return caffeine cache
|
||||
*/
|
||||
public static CommonCacheService<String, Object> getAlertSilenceCache() {
|
||||
return ALERT_SILENCE_CACHE;
|
||||
}
|
||||
|
||||
/**
|
||||
* get alert converge cache
|
||||
* @return converge cache
|
||||
*/
|
||||
public static CommonCacheService<String, Object> getAlertConvergeCache() {
|
||||
return ALERT_CONVERGE_CACHE;
|
||||
}
|
||||
}
|
||||
@@ -1,316 +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.apache.hertzbeat.common.config;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* common module properties
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "common")
|
||||
public class CommonProperties {
|
||||
|
||||
/**
|
||||
* secret key for password aes entry, must 16 bits
|
||||
*/
|
||||
private String secret;
|
||||
|
||||
/**
|
||||
* data queue impl
|
||||
*/
|
||||
private DataQueueProperties queue;
|
||||
|
||||
/**
|
||||
* sms impl properties
|
||||
*/
|
||||
private SmsProperties sms;
|
||||
|
||||
public String getSecret() {
|
||||
return secret;
|
||||
}
|
||||
|
||||
public DataQueueProperties getQueue() {
|
||||
return queue;
|
||||
}
|
||||
|
||||
public SmsProperties getSms() {
|
||||
return sms;
|
||||
}
|
||||
|
||||
public void setSecret(String secret) {
|
||||
this.secret = secret;
|
||||
}
|
||||
|
||||
public void setQueue(DataQueueProperties queue) {
|
||||
this.queue = queue;
|
||||
}
|
||||
|
||||
public void setSms(SmsProperties sms) {
|
||||
this.sms = sms;
|
||||
}
|
||||
|
||||
/**
|
||||
* data queue properties
|
||||
*/
|
||||
public static class DataQueueProperties {
|
||||
|
||||
private QueueType type = QueueType.Memory;
|
||||
|
||||
private KafkaProperties kafka;
|
||||
|
||||
public QueueType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(QueueType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public KafkaProperties getKafka() {
|
||||
return kafka;
|
||||
}
|
||||
|
||||
public void setKafka(KafkaProperties kafka) {
|
||||
this.kafka = kafka;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* data queue type
|
||||
*/
|
||||
public enum QueueType {
|
||||
/** in memory **/
|
||||
Memory,
|
||||
/** kafka **/
|
||||
Kafka,
|
||||
/** with netty connect **/
|
||||
Netty,
|
||||
/** rabbit mq **/
|
||||
Rabbit_Mq
|
||||
}
|
||||
|
||||
/**
|
||||
* kafka data queue properties
|
||||
*/
|
||||
public static class KafkaProperties {
|
||||
/**
|
||||
* kafka's connection server url
|
||||
*/
|
||||
private String servers;
|
||||
/**
|
||||
* metrics data topic
|
||||
*/
|
||||
private String metricsDataTopic;
|
||||
/**
|
||||
* alerts data topic
|
||||
*/
|
||||
private String alertsDataTopic;
|
||||
|
||||
public String getServers() {
|
||||
return servers;
|
||||
}
|
||||
|
||||
public void setServers(String servers) {
|
||||
this.servers = servers;
|
||||
}
|
||||
|
||||
public String getMetricsDataTopic() {
|
||||
return metricsDataTopic;
|
||||
}
|
||||
|
||||
public void setMetricsDataTopic(String metricsDataTopic) {
|
||||
this.metricsDataTopic = metricsDataTopic;
|
||||
}
|
||||
|
||||
public String getAlertsDataTopic() {
|
||||
return alertsDataTopic;
|
||||
}
|
||||
|
||||
public void setAlertsDataTopic(String alertsDataTopic) {
|
||||
this.alertsDataTopic = alertsDataTopic;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* sms properties
|
||||
*/
|
||||
public static class SmsProperties {
|
||||
//Tencent cloud SMS configuration
|
||||
private TencentSmsProperties tencent;
|
||||
//Ali cloud SMS configuration
|
||||
private AliYunSmsProperties aliYun;
|
||||
|
||||
public TencentSmsProperties getTencent() {
|
||||
return tencent;
|
||||
}
|
||||
|
||||
public void setTencent(TencentSmsProperties tencent) {
|
||||
this.tencent = tencent;
|
||||
}
|
||||
|
||||
public AliYunSmsProperties getAliYun() {
|
||||
return aliYun;
|
||||
}
|
||||
|
||||
public void setAliYun(AliYunSmsProperties aliYun) {
|
||||
this.aliYun = aliYun;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* tencent sms properties
|
||||
*/
|
||||
public static class TencentSmsProperties {
|
||||
|
||||
/**
|
||||
* Tencent cloud account secret id
|
||||
*/
|
||||
private String secretId;
|
||||
|
||||
/**
|
||||
* Tencent cloud account secret key
|
||||
*/
|
||||
private String secretKey;
|
||||
|
||||
/**
|
||||
* SMS app id
|
||||
*/
|
||||
private String appId;
|
||||
|
||||
/**
|
||||
* SMS signature
|
||||
*/
|
||||
private String signName;
|
||||
|
||||
/**
|
||||
* SMS template ID
|
||||
*/
|
||||
private String templateId;
|
||||
|
||||
public String getSecretId() {
|
||||
return secretId;
|
||||
}
|
||||
|
||||
public void setSecretId(String secretId) {
|
||||
this.secretId = secretId;
|
||||
}
|
||||
|
||||
public String getSecretKey() {
|
||||
return secretKey;
|
||||
}
|
||||
|
||||
public void setSecretKey(String secretKey) {
|
||||
this.secretKey = secretKey;
|
||||
}
|
||||
|
||||
public String getAppId() {
|
||||
return appId;
|
||||
}
|
||||
|
||||
public void setAppId(String appId) {
|
||||
this.appId = appId;
|
||||
}
|
||||
|
||||
public String getSignName() {
|
||||
return signName;
|
||||
}
|
||||
|
||||
public void setSignName(String signName) {
|
||||
this.signName = signName;
|
||||
}
|
||||
|
||||
public String getTemplateId() {
|
||||
return templateId;
|
||||
}
|
||||
|
||||
public void setTemplateId(String templateId) {
|
||||
this.templateId = templateId;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* aliYun sms properties
|
||||
*/
|
||||
public static class AliYunSmsProperties {
|
||||
|
||||
/**
|
||||
* Aliyun account access key id
|
||||
*/
|
||||
private String secretId;
|
||||
|
||||
/**
|
||||
* Ali Cloud account access key
|
||||
*/
|
||||
private String secretKey;
|
||||
|
||||
/**
|
||||
* SMS app id
|
||||
*/
|
||||
private String appId;
|
||||
|
||||
/**
|
||||
* SMS signature
|
||||
*/
|
||||
private String signName;
|
||||
|
||||
/**
|
||||
* ID of the SMS template
|
||||
*/
|
||||
private String templateId;
|
||||
|
||||
public String getAppId() {
|
||||
return appId;
|
||||
}
|
||||
|
||||
public void setAppId(String appId) {
|
||||
this.appId = appId;
|
||||
}
|
||||
|
||||
public String getSecretId() {
|
||||
return secretId;
|
||||
}
|
||||
|
||||
public void setSecretId(String secretId) {
|
||||
this.secretId = secretId;
|
||||
}
|
||||
|
||||
public String getSecretKey() {
|
||||
return secretKey;
|
||||
}
|
||||
|
||||
public void setSecretKey(String secretKey) {
|
||||
this.secretKey = secretKey;
|
||||
}
|
||||
|
||||
public String getSignName() {
|
||||
return signName;
|
||||
}
|
||||
|
||||
public void setSignName(String signName) {
|
||||
this.signName = signName;
|
||||
}
|
||||
|
||||
public String getTemplateId() {
|
||||
return templateId;
|
||||
}
|
||||
|
||||
public void setTemplateId(String templateId) {
|
||||
this.templateId = templateId;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,46 +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.apache.hertzbeat.common.constants;
|
||||
|
||||
/**
|
||||
* collector constant
|
||||
*/
|
||||
public interface CollectorConstants {
|
||||
|
||||
String RESPONSE_TIME = "responseTime";
|
||||
|
||||
String KEYWORD = "keyword";
|
||||
|
||||
String STATUS_CODE = "statusCode";
|
||||
|
||||
String ERROR_MSG = "errorMsg";
|
||||
|
||||
String URL = "url";
|
||||
|
||||
String HTTP_HEADER = "http://";
|
||||
|
||||
String HTTPS_HEADER = "https://";
|
||||
|
||||
/**
|
||||
* POSTGRESQL un reachable status code
|
||||
*/
|
||||
String POSTGRESQL_UN_REACHABLE_CODE = "08001";
|
||||
|
||||
String IPV6 = "ipv6";
|
||||
String IPV4 = "ipv4";
|
||||
}
|
||||
@@ -1,370 +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.apache.hertzbeat.common.constants;
|
||||
|
||||
/**
|
||||
* Public Common Constant
|
||||
*/
|
||||
public interface CommonConstants {
|
||||
|
||||
/**
|
||||
* Response status code: generic success
|
||||
*/
|
||||
byte SUCCESS_CODE = 0x00;
|
||||
|
||||
/**
|
||||
* Response status code: generic failure
|
||||
*/
|
||||
byte FAIL_CODE = 0x0F;
|
||||
|
||||
/**
|
||||
* Response status code: Parameter verification failed
|
||||
*/
|
||||
byte PARAM_INVALID_CODE = 0x01;
|
||||
|
||||
/**
|
||||
* Response Status Code: Probe Failed
|
||||
*/
|
||||
byte DETECT_FAILED_CODE = 0x02;
|
||||
|
||||
/**
|
||||
* Response status code: monitoring does not exist
|
||||
*/
|
||||
byte MONITOR_NOT_EXIST_CODE = 0x03;
|
||||
|
||||
/**
|
||||
* Response Status Code: Monitor Service Conflict
|
||||
*/
|
||||
byte MONITOR_CONFLICT_CODE = 0x04;
|
||||
|
||||
/**
|
||||
* Response status code: Incorrect login account password
|
||||
*/
|
||||
byte MONITOR_LOGIN_FAILED_CODE = 0x05;
|
||||
|
||||
/**
|
||||
* Monitoring status 0: Paused, 1: Up, 2: Down
|
||||
*/
|
||||
byte MONITOR_PAUSED_CODE = 0x00;
|
||||
|
||||
/**
|
||||
* Monitoring status 0: Paused, 1: Up, 2: Down
|
||||
*/
|
||||
byte MONITOR_UP_CODE = 0x01;
|
||||
|
||||
/**
|
||||
* Monitoring status 0: Paused, 1: Up, 2: Down
|
||||
*/
|
||||
byte MONITOR_DOWN_CODE = 0x02;
|
||||
|
||||
/**
|
||||
* Alarm status: 0 - normal alarm (to be processed)
|
||||
*/
|
||||
byte ALERT_STATUS_CODE_PENDING = 0x00;
|
||||
|
||||
/**
|
||||
* Alarm Status: 1 - Threshold triggered but not reached the number of alarms
|
||||
*/
|
||||
byte ALERT_STATUS_CODE_NOT_REACH = 0x01;
|
||||
|
||||
/**
|
||||
* Alarm Status: 2-Restore Alarm
|
||||
*/
|
||||
byte ALERT_STATUS_CODE_RESTORED = 0x02;
|
||||
|
||||
/**
|
||||
* Alert Status: 3-Handled
|
||||
*/
|
||||
byte ALERT_STATUS_CODE_SOLVED = 0x03;
|
||||
|
||||
/**
|
||||
* Alarm level: 0: high-emergency-emergency-red
|
||||
*/
|
||||
byte ALERT_PRIORITY_CODE_EMERGENCY = 0x00;
|
||||
|
||||
/**
|
||||
* Alarm severity: 1: medium-critical-critical alarm-orange
|
||||
*/
|
||||
byte ALERT_PRIORITY_CODE_CRITICAL = 0x01;
|
||||
|
||||
/**
|
||||
* Warning level: 2: low-warning-warning warning-yellow
|
||||
*/
|
||||
byte ALERT_PRIORITY_CODE_WARNING = 0x02;
|
||||
|
||||
/**
|
||||
* Field parameter type: number
|
||||
*/
|
||||
byte TYPE_NUMBER = 0;
|
||||
|
||||
/**
|
||||
* Field parameter type: String
|
||||
*/
|
||||
byte TYPE_STRING = 1;
|
||||
|
||||
/**
|
||||
* Field parameter type: encrypted string
|
||||
*/
|
||||
byte TYPE_SECRET = 2;
|
||||
|
||||
/**
|
||||
* Field parameter type: time
|
||||
*/
|
||||
byte TYPE_TIME = 3;
|
||||
|
||||
/**
|
||||
* Collection metric value: null placeholder for empty value
|
||||
*/
|
||||
String NULL_VALUE = " ";
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
String PROM_TIME = "timestamp";
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
String PROM_VALUE = "value";
|
||||
|
||||
/**
|
||||
* Monitor total availability metrics
|
||||
*/
|
||||
String AVAILABILITY = "availability";
|
||||
|
||||
/**
|
||||
* Parameter Type Number
|
||||
*/
|
||||
byte PARAM_TYPE_NUMBER = 0;
|
||||
|
||||
/**
|
||||
* Parameter Type String
|
||||
*/
|
||||
byte PARAM_TYPE_STRING = 1;
|
||||
|
||||
/**
|
||||
* Parameter Type Password
|
||||
*/
|
||||
byte PARAM_TYPE_PASSWORD = 2;
|
||||
|
||||
/**
|
||||
* Parameter Type Map values
|
||||
*/
|
||||
byte PARAM_TYPE_MAP = 3;
|
||||
|
||||
/**
|
||||
* Parameter Type arrays values
|
||||
*/
|
||||
byte PARAM_TYPE_ARRAY = 4;
|
||||
|
||||
/**
|
||||
* Authentication type Account password
|
||||
*/
|
||||
byte AUTH_TYPE_PASSWORD = 1;
|
||||
|
||||
/**
|
||||
* Authentication type GitHub three-party login
|
||||
*/
|
||||
byte AUTH_TYPE_GITHUB = 2;
|
||||
|
||||
/**
|
||||
* Authentication type WeChat three-party login
|
||||
*/
|
||||
byte AUTH_TYPE_WEIXIN = 3;
|
||||
|
||||
/**
|
||||
* Authentication type GITEE three-party login
|
||||
*/
|
||||
byte AUTH_TYPE_GITEE = 5;
|
||||
|
||||
/**
|
||||
* Inside the tag: monitorId Monitor task ID
|
||||
*/
|
||||
String TAG_MONITOR_ID = "monitorId";
|
||||
|
||||
/**
|
||||
* Inside the tag: monitorName Task name
|
||||
*/
|
||||
String TAG_MONITOR_NAME = "monitorName";
|
||||
|
||||
/**
|
||||
* Inside the tag: monitorHost Task host
|
||||
*/
|
||||
String TAG_MONITOR_HOST = "monitorHost";
|
||||
|
||||
/**
|
||||
* Inside the tag: policyId Alarm threshold rule ID
|
||||
*/
|
||||
String TAG_THRESHOLD_ID = "thresholdId";
|
||||
|
||||
/**
|
||||
* Inside the tag: app Type of monitoring
|
||||
*/
|
||||
String TAG_MONITOR_APP = "app";
|
||||
|
||||
/**
|
||||
* Inside the tag: metrics
|
||||
*/
|
||||
String TAG_METRICS = "metrics";
|
||||
|
||||
/**
|
||||
* Inside the tag: metric
|
||||
*/
|
||||
String TAG_METRIC = "metric";
|
||||
|
||||
/**
|
||||
* Inside the tag: code
|
||||
*/
|
||||
String TAG_CODE = "code";
|
||||
|
||||
/**
|
||||
* notice_period type Type field, daily type
|
||||
*/
|
||||
int NOTICE_PERIOD_DAILY = 0;
|
||||
|
||||
/**
|
||||
* key is receiver.id, value is noticePeriod cache key prefix
|
||||
*/
|
||||
String RECEIVER_NOTICE_PERIOD_CACHE_PREFIX = "receiver_notice_period:";
|
||||
|
||||
/**
|
||||
* cache key notice_rule
|
||||
*/
|
||||
String CACHE_NOTICE_RULE = "notice_rule";
|
||||
|
||||
/**
|
||||
* cache key alert silence
|
||||
*/
|
||||
String CACHE_ALERT_SILENCE = "alert_silence";
|
||||
|
||||
/**
|
||||
* cache key alert converge
|
||||
*/
|
||||
String CACHE_ALERT_CONVERGE = "alert_converge";
|
||||
|
||||
/**
|
||||
* collector status online 0
|
||||
*/
|
||||
byte COLLECTOR_STATUS_ONLINE = 0;
|
||||
|
||||
/**
|
||||
* collector status offline 1
|
||||
*/
|
||||
byte COLLECTOR_STATUS_OFFLINE = 1;
|
||||
|
||||
/**
|
||||
* default main collector name
|
||||
*/
|
||||
String MAIN_COLLECTOR_NODE = "main-default-collector";
|
||||
|
||||
/**
|
||||
* locale spilt
|
||||
*/
|
||||
String LOCALE_SEPARATOR = "_";
|
||||
|
||||
/**
|
||||
* ignore label
|
||||
* Handle situations where recovery alarms are not configured, but need to be used to change task state
|
||||
*/
|
||||
String IGNORE = "ignore";
|
||||
|
||||
/**
|
||||
* collector mode public
|
||||
*/
|
||||
String MODE_PUBLIC = "public";
|
||||
|
||||
/**
|
||||
* collector mode private
|
||||
*/
|
||||
String MODE_PRIVATE = "private";
|
||||
|
||||
/**
|
||||
* collector auth failed message
|
||||
*/
|
||||
String COLLECTOR_AUTH_FAILED = "Auth Failed";
|
||||
|
||||
/**
|
||||
* for prometheus task name prefix
|
||||
*/
|
||||
String PROMETHEUS_APP_PREFIX = "_prometheus_";
|
||||
|
||||
/**
|
||||
* prometheus
|
||||
*/
|
||||
String PROMETHEUS = "prometheus";
|
||||
|
||||
/**
|
||||
* status page component state normal
|
||||
*/
|
||||
byte STATUS_PAGE_COMPONENT_STATE_NORMAL = 0;
|
||||
|
||||
/**
|
||||
* status page component state abnormal
|
||||
*/
|
||||
byte STATUS_PAGE_COMPONENT_STATE_ABNORMAL = 1;
|
||||
|
||||
/**
|
||||
* status page component state unknown
|
||||
*/
|
||||
byte STATUS_PAGE_COMPONENT_STATE_UNKNOWN = 2;
|
||||
|
||||
/**
|
||||
* status page org state all normal
|
||||
*/
|
||||
byte STATUS_PAGE_ORG_STATE_ALL_NORMAL = 0;
|
||||
|
||||
/**
|
||||
* status page org state some abnormal
|
||||
*/
|
||||
byte STATUS_PAGE_ORG_STATE_SOME_ABNORMAL = 1;
|
||||
|
||||
/**
|
||||
* status page org state all abnormal
|
||||
*/
|
||||
byte STATUS_PAGE_ORG_STATE_ALL_ABNORMAL = 2;
|
||||
|
||||
/**
|
||||
* status page component calculate method auto
|
||||
*/
|
||||
byte STATUE_PAGE_CALCULATE_METHOD_AUTO = 0;
|
||||
|
||||
/**
|
||||
* status page component calculate method manual
|
||||
*/
|
||||
byte STATUS_PAGE_CALCULATE_METHOD_MANUAL = 1;
|
||||
|
||||
/**
|
||||
* status page incident state investigating
|
||||
*/
|
||||
byte STATUS_PAGE_INCIDENT_STATE_INVESTIGATING = 0;
|
||||
|
||||
/**
|
||||
* status page incident state identified
|
||||
*/
|
||||
byte STATUS_PAGE_INCIDENT_STATE_IDENTIFIED = 1;
|
||||
|
||||
/**
|
||||
* status page incident state monitoring
|
||||
*/
|
||||
byte STATUS_PAGE_INCIDENT_STATE_MONITORING = 2;
|
||||
|
||||
/**
|
||||
* status page incident state resolved
|
||||
*/
|
||||
byte STATUS_PAGE_INCIDENT_STATE_RESOLVED = 3;
|
||||
}
|
||||
@@ -1,158 +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.apache.hertzbeat.common.entity.alerter;
|
||||
|
||||
import static io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_ONLY;
|
||||
import static io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_WRITE;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Convert;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EntityListeners;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.Transient;
|
||||
import jakarta.validation.constraints.Max;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.apache.hertzbeat.common.util.JsonUtil;
|
||||
import org.springframework.data.annotation.CreatedBy;
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.data.annotation.LastModifiedBy;
|
||||
import org.springframework.data.annotation.LastModifiedDate;
|
||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
|
||||
/**
|
||||
* Alarm record entity
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "hzb_alert")
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Schema(description = "Alarm record entity")
|
||||
@EntityListeners(AuditingEntityListener.class)
|
||||
public class Alert {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Schema(title = "Alarm record entity primary key index ID",
|
||||
description = "Alarm record entity primary key index ID",
|
||||
example = "87584674384", accessMode = READ_ONLY)
|
||||
private Long id;
|
||||
|
||||
@Schema(title = "Alert target object: monitor availability-available metrics-app.metrics.field",
|
||||
description = "Alert target object: monitor availability-available metrics-app.metrics.field",
|
||||
example = "1", accessMode = READ_WRITE)
|
||||
@Size(max = 255)
|
||||
private String target;
|
||||
|
||||
@Schema(title = "Alarm definition ID associated with the alarm",
|
||||
description = "Alarm definition ID associated with the alarm",
|
||||
example = "8743267443543", accessMode = READ_WRITE)
|
||||
private Long alertDefineId;
|
||||
|
||||
@Schema(title = "Alarm level 0:High-Emergency-Critical Alarm 1:Medium-Critical-Critical Alarm 2:Low-Warning-Warning",
|
||||
example = "1", accessMode = READ_WRITE)
|
||||
@Min(0)
|
||||
@Max(2)
|
||||
private byte priority;
|
||||
|
||||
@Schema(title = "The actual content of the alarm notification",
|
||||
description = "The actual content of the alarm notification",
|
||||
example = "linux_192.134.32.1: 534543534 cpu usage high",
|
||||
accessMode = READ_WRITE)
|
||||
@Column(length = 4096)
|
||||
private String content;
|
||||
|
||||
@Schema(title = "Alarm status: "
|
||||
+ "0-normal alarm (to be processed) "
|
||||
+ "1-threshold triggered but not reached the number of alarms "
|
||||
+ "2-recovered alarm "
|
||||
+ "3-processed",
|
||||
description = "Alarm status: "
|
||||
+ "0-normal alarm (to be processed) "
|
||||
+ "1-threshold triggered but not reached the number of alarms "
|
||||
+ "2-recovered alarm "
|
||||
+ "3-processed",
|
||||
example = "1", accessMode = READ_WRITE)
|
||||
@Min(0)
|
||||
@Max(3)
|
||||
private byte status;
|
||||
|
||||
@Schema(title = "Alarm times",
|
||||
description = "Alarm times",
|
||||
example = "3", accessMode = READ_WRITE)
|
||||
private Integer times;
|
||||
|
||||
@Schema(title = "Alarm trigger time (timestamp in milliseconds)",
|
||||
description = "Alarm trigger time (timestamp in milliseconds)",
|
||||
example = "1612198922000", accessMode = READ_ONLY)
|
||||
private Long firstAlarmTime;
|
||||
|
||||
@Schema(title = "Alarm trigger time (timestamp in milliseconds)",
|
||||
description = "Alarm trigger time (timestamp in milliseconds)",
|
||||
example = "1612198922000", accessMode = READ_ONLY)
|
||||
private Long lastAlarmTime;
|
||||
|
||||
@Schema(title = "Alarm threshold trigger times",
|
||||
description = "Alarm threshold trigger times",
|
||||
example = "3", accessMode = READ_WRITE)
|
||||
@Transient
|
||||
private Integer triggerTimes;
|
||||
|
||||
@Schema(description = "Alarm information label(monitorId:xxx,monitorName:xxx)",
|
||||
example = "{key1:value1}", accessMode = READ_WRITE)
|
||||
@Convert(converter = JsonMapAttributeConverter.class)
|
||||
@SuppressWarnings("JpaAttributeTypeInspection")
|
||||
@Column(length = 2048)
|
||||
private Map<String, String> tags;
|
||||
|
||||
@Schema(title = "The creator of this record", example = "tom", accessMode = READ_ONLY)
|
||||
@CreatedBy
|
||||
private String creator;
|
||||
|
||||
@Schema(title = "The modifier of this record", example = "tom", accessMode = READ_ONLY)
|
||||
@LastModifiedBy
|
||||
private String modifier;
|
||||
|
||||
@Schema(title = "Record the latest creation time (timestamp in milliseconds)",
|
||||
description = "Record the latest creation time (timestamp in milliseconds)",
|
||||
example = "1612198922000", accessMode = READ_ONLY)
|
||||
@CreatedDate
|
||||
private LocalDateTime gmtCreate;
|
||||
|
||||
@Schema(title = "Record modify time", example = "1612198444000", accessMode = READ_ONLY)
|
||||
@LastModifiedDate
|
||||
private LocalDateTime gmtUpdate;
|
||||
|
||||
@Override
|
||||
public Alert clone() {
|
||||
// deep clone
|
||||
return JsonUtil.fromJson(JsonUtil.toJson(this), Alert.class);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user