1717
1818package org .apache .hertzbeat .manager .component .alerter .impl ;
1919
20- import com .fasterxml .jackson .annotation .JsonProperty ;
21- import java .util .ArrayList ;
22- import java .util .Collections ;
23- import java .util .List ;
24- import lombok .Data ;
20+ import java .util .Arrays ;
21+ import java .util .stream .Collectors ;
2522import lombok .RequiredArgsConstructor ;
2623import lombok .extern .slf4j .Slf4j ;
24+ import org .apache .commons .lang3 .StringUtils ;
2725import org .apache .hertzbeat .common .entity .alerter .Alert ;
2826import org .apache .hertzbeat .common .entity .manager .NoticeReceiver ;
2927import org .apache .hertzbeat .common .entity .manager .NoticeTemplate ;
30- import org .apache .hertzbeat .common .util .StrUtil ;
28+ import org .apache .hertzbeat .common .util .JsonUtil ;
3129import org .apache .hertzbeat .manager .support .exception .AlertNoticeException ;
3230import org .springframework .http .HttpEntity ;
3331import org .springframework .http .HttpHeaders ;
4442@ Slf4j
4543final class FlyBookAlertNotifyHandlerImpl extends AbstractAlertNotifyHandlerImpl {
4644
45+ /**
46+ * Title color corresponding to the alarm priority
47+ */
48+ private static final String [] TITLE_COLOR = {"red" , "yellow" , "orange" };
49+
50+
4751 @ Override
4852 public void send (NoticeReceiver receiver , NoticeTemplate noticeTemplate , Alert alert ) {
4953 try {
50- FlyBookWebHookDto flyBookWebHookDto = new FlyBookWebHookDto ();
51- flyBookWebHookDto .setMsgType ("post" );
52-
53- Content content = new Content ();
54- flyBookWebHookDto .setContent (content );
55-
56- Post post = new Post ();
57- content .setPost (post );
58-
59- ZhCn zhCn = new ZhCn ();
60- post .setZhCn (zhCn );
61-
62- zhCn .setTitle ("[" + bundle .getString ("alerter.notify.title" ) + "]" );
63-
64- List <FlyBookContent > contentList = new ArrayList <>();
65-
66- FlyBookContent textContent = new FlyBookContent ();
67- textContent .setTag ("text" );
68- textContent .setText (renderContent (noticeTemplate , alert ));
69- contentList .add (textContent );
70-
71- FlyBookContent linkContent = new FlyBookContent ();
72- linkContent .setTag ("a" );
73- linkContent .setText (bundle .getString ("alerter.notify.console" ));
74- linkContent .setHref (alerterProperties .getConsoleUrl ());
75- contentList .add (linkContent );
76-
77- String userId = receiver .getUserId ();
78- List <String > userIdList = StrUtil .analysisArgToList (userId );
79- if (userIdList != null && !userIdList .isEmpty ()) {
80- List <FlyBookContent > atContents = userIdList .stream ()
81- .map (userID -> {
82- FlyBookContent atContent = new FlyBookContent ();
83- atContent .setTag ("at" );
84- atContent .setUserId (userID );
85- return atContent ;
86- })
87- .toList ();
88- contentList .addAll (atContents );
89- }
90-
91- List <List <FlyBookContent >> contents = Collections .singletonList (contentList );
92- zhCn .setContent (contents );
93-
54+ String notificationContent = JsonUtil .toJson (renderContent (noticeTemplate , alert ));
55+ String cardMessage = createLarkMessage (receiver .getUserId (), notificationContent , alert .getPriority ());
9456 String webHookUrl = alerterProperties .getFlyBookWebhookUrl () + receiver .getAccessToken ();
9557 HttpHeaders headers = new HttpHeaders ();
9658 headers .setContentType (MediaType .APPLICATION_JSON );
97- HttpEntity <FlyBookWebHookDto > flyEntity = new HttpEntity <>(flyBookWebHookDto , headers );
59+ HttpEntity <String > flyEntity = new HttpEntity <>(cardMessage , headers );
9860 ResponseEntity <CommonRobotNotifyResp > entity = restTemplate .postForEntity (webHookUrl ,
99- flyEntity , CommonRobotNotifyResp .class );
61+ flyEntity , CommonRobotNotifyResp .class );
10062 if (entity .getStatusCode () == HttpStatus .OK ) {
10163 assert entity .getBody () != null ;
10264 if (entity .getBody ().getCode () == null || entity .getBody ().getCode () == 0 ) {
@@ -114,77 +76,129 @@ public void send(NoticeReceiver receiver, NoticeTemplate noticeTemplate, Alert a
11476 }
11577 }
11678
117-
118- @ Override
119- public byte type () {
120- return 6 ;
121- }
122-
123- @ Data
124- private static class FlyBookWebHookDto {
125-
126- private static final String DEFAULT_MSG_TYPE = "post" ;
127-
128- /**
129- * Message type
130- */
131- @ JsonProperty ("msg_type" )
132- private String msgType = DEFAULT_MSG_TYPE ;
133-
134-
135- private Content content ;
136-
137- }
138-
13979 /**
140- * Message content
80+ * create a lark notification card message
81+ *
82+ * @param userId at user id
83+ * @param notificationContent notification content
84+ * @param priority priority for alert
85+ * @return message
14186 */
142- @ Data
143- private static class Content {
144- public Post post ;
145- }
146-
147- @ Data
148- private static class FlyBookContent {
149- /**
150- * format currently supports text、hyperlink、@people function
151- */
152- public String tag ;
153-
154- /**
155- * text
156- */
157- public String text ;
158-
159- /**
160- * hyperlink address
161- */
162- public String href ;
163-
164- @ JsonProperty ("user_id" )
165- public String userId ;
166-
167- @ JsonProperty ("user_name" )
168- public String userName ;
169- }
170-
171- @ Data
172- private static class Post {
173- @ JsonProperty ("zh_cn" )
174- public ZhCn zhCn ;
87+ private String createLarkMessage (String userId , String notificationContent , byte priority ) {
88+ String larkCardMessage = """
89+ {
90+ "msg_type": "interactive",
91+ "card": {
92+ "config": {
93+ "update_multi": true
94+ },
95+ "i18n_elements": {
96+ "zh_cn": [
97+ {
98+ "tag": "column_set",
99+ "flex_mode": "none",
100+ "horizontal_spacing": "default",
101+ "background_style": "default",
102+ "columns": [
103+ {
104+ "tag": "column",
105+ "elements": [
106+ {
107+ "tag": "div",
108+ "text": {
109+ "tag": "plain_text",
110+ "content": "",
111+ "text_size": "normal",
112+ "text_align": "left",
113+ "text_color": "default"
114+ }
115+ }
116+ ],
117+ "width": "weighted",
118+ "weight": 1
119+ }
120+ ]
121+ },
122+ {
123+ "tag": "column_set",
124+ "flex_mode": "none",
125+ "horizontal_spacing": "default",
126+ "background_style": "default",
127+ "columns": [
128+ {
129+ "tag": "column",
130+ "elements": [
131+ {
132+ "tag": "div",
133+ "text": {
134+ "tag": "plain_text",
135+ "content": %s,
136+ "text_size": "normal",
137+ "text_align": "left",
138+ "text_color": "default"
139+ }
140+ }
141+ ],
142+ "width": "weighted",
143+ "weight": 1
144+ }
145+ ]
146+ },
147+ %s
148+ {
149+ "tag": "action",
150+ "actions": [
151+ {
152+ "tag": "button",
153+ "text": {
154+ "tag": "plain_text",
155+ "content": "登入控制台"
156+ },
157+ "type": "default",
158+ "complex_interaction": true,
159+ "width": "default",
160+ "size": "medium",
161+ "multi_url": {
162+ "url": "%s"
163+ }
164+ }
165+ ]
166+ }
167+ ]
168+ },
169+ "i18n_header": {
170+ "zh_cn": {
171+ "title": {
172+ "tag": "plain_text",
173+ "content": "HertzBeat 告警"
174+ },
175+ "template": "%s"
176+ }
177+ }
178+ }
179+ }
180+ """ ;
181+
182+ String atUserElement = "" ;
183+ if (StringUtils .isNotBlank (userId )) {
184+ String atUserId = Arrays .stream (userId .split ("," ))
185+ .map (id -> "<at id=" + id + "></at>" )
186+ .collect (Collectors .joining (" " ));
187+ atUserElement = String .format ("""
188+ {
189+ "tag": "div",
190+ "text": {
191+ "content": "%s",
192+ "tag": "lark_md"
193+ }
194+ },
195+ """ , atUserId );
196+ }
197+ return String .format (larkCardMessage , notificationContent , atUserElement , alerterProperties .getConsoleUrl (), TITLE_COLOR [priority ]);
175198 }
176199
177- @ Data
178- private static class ZhCn {
179- /**
180- * Title
181- */
182- public String title ;
183-
184- /**
185- * Content
186- */
187- public List <List <FlyBookContent >> content ;
200+ @ Override
201+ public byte type () {
202+ return 6 ;
188203 }
189-
190204}
0 commit comments