From 5585993503d7b6f0963b2ad0a768f31c10af4141 Mon Sep 17 00:00:00 2001 From: Logic Date: Tue, 16 Jul 2024 16:35:44 +0800 Subject: [PATCH 1/6] [bugfix] added basic auth support for VictoriaMetrics status check (#2282) --- .../vm/VictoriaMetricsDataStorage.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/vm/VictoriaMetricsDataStorage.java b/warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/vm/VictoriaMetricsDataStorage.java index 6a687fa2982..2770956a35e 100644 --- a/warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/vm/VictoriaMetricsDataStorage.java +++ b/warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/vm/VictoriaMetricsDataStorage.java @@ -17,7 +17,6 @@ package org.apache.hertzbeat.warehouse.store.history.vm; -import com.fasterxml.jackson.databind.JsonNode; import java.math.BigDecimal; import java.math.RoundingMode; import java.net.URI; @@ -103,13 +102,21 @@ public VictoriaMetricsDataStorage(VictoriaMetricsProperties victoriaMetricsPrope private boolean checkVictoriaMetricsDatasourceAvailable() { // check server status try { - String result = restTemplate.getForObject(victoriaMetricsProp.url() + STATUS_PATH, String.class); - - JsonNode jsonNode = JsonUtil.fromJson(result); - if (jsonNode != null && STATUS_SUCCESS.equalsIgnoreCase(jsonNode.get(STATUS).asText())) { + HttpHeaders headers = new HttpHeaders(); + if (StringUtils.hasText(victoriaMetricsProp.username()) + && StringUtils.hasText(victoriaMetricsProp.password())) { + String authStr = victoriaMetricsProp.username() + ":" + victoriaMetricsProp.password(); + String encodedAuth = new String(Base64.encodeBase64(authStr.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8); + headers.add(HttpHeaders.AUTHORIZATION, BASIC + " " + encodedAuth); + } + HttpEntity httpEntity = new HttpEntity<>(headers); + ResponseEntity responseEntity = restTemplate.exchange(victoriaMetricsProp.url() + STATUS_PATH, + HttpMethod.GET, httpEntity, String.class); + if (responseEntity.getStatusCode().is2xxSuccessful()) { + log.info("check victoria metrics server status success."); return true; } - log.error("check victoria metrics server status not success: {}.", result); + log.error("check victoria metrics server status not success: {}.", responseEntity.getBody()); } catch (Exception e) { log.error("check victoria metrics server status error: {}.", e.getMessage()); } From acc617f9bd9c027ef2fdfa2ffa5af0ec28703ff2 Mon Sep 17 00:00:00 2001 From: YuLuo Date: Tue, 16 Jul 2024 21:33:50 +0800 Subject: [PATCH 2/6] [Improve] add springContextHolder unit test (#2287) Signed-off-by: yuluo-yx Co-authored-by: tomsun28 --- .../support/SpringContextHolderTest.java | 75 +++++++++++++++++-- 1 file changed, 69 insertions(+), 6 deletions(-) diff --git a/common/src/test/java/org/apache/hertzbeat/common/support/SpringContextHolderTest.java b/common/src/test/java/org/apache/hertzbeat/common/support/SpringContextHolderTest.java index c4959745501..e3b208b9694 100644 --- a/common/src/test/java/org/apache/hertzbeat/common/support/SpringContextHolderTest.java +++ b/common/src/test/java/org/apache/hertzbeat/common/support/SpringContextHolderTest.java @@ -20,28 +20,91 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ConfigurableApplicationContext; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + /** * Test case for {@link SpringContextHolder} */ class SpringContextHolderTest { + private ApplicationContext applicationContext; + + private ConfigurableApplicationContext configurableApplicationContext; + + private SpringContextHolder springContextHolder; + @BeforeEach - void setUp() { + public void setUp() { + + applicationContext = mock(ApplicationContext.class); + configurableApplicationContext = mock(ConfigurableApplicationContext.class); + springContextHolder = new SpringContextHolder(); } @Test - void setApplicationContext() { + public void testSetApplicationContext() throws BeansException { + + springContextHolder.setApplicationContext(configurableApplicationContext); + + assertNotNull(SpringContextHolder.getApplicationContext()); } @Test - void getApplicationContext() { + public void testGetApplicationContext() { + + springContextHolder.setApplicationContext(applicationContext); + assertNotNull(SpringContextHolder.getApplicationContext()); } @Test - void getBean() { + public void testGetBeanByClass() { + + Class beanClass = String.class; + String bean = "bean"; + when(applicationContext.getBean(beanClass)).thenReturn(bean); + + springContextHolder.setApplicationContext(applicationContext); + String retrievedBean = SpringContextHolder.getBean(beanClass); + + assertEquals(bean, retrievedBean); } @Test - void testGetBean() { + public void testShutdown() { + + springContextHolder.setApplicationContext(configurableApplicationContext); + SpringContextHolder.shutdown(); + + verify(configurableApplicationContext, times(1)).close(); + } + + @Test + public void testIsActive() { + + when(configurableApplicationContext.isActive()).thenReturn(true); + springContextHolder.setApplicationContext(configurableApplicationContext); + assertTrue(SpringContextHolder.isActive()); } -} \ No newline at end of file + + @Test + public void testAssertApplicationContextThrowsException() { + + RuntimeException exception = assertThrows(RuntimeException.class, SpringContextHolder::getApplicationContext); + assertEquals( + "applicationContext is null, please inject the springContextHolder", + exception.getMessage() + ); + } + +} From 3b323e1882381445cc4e480e066800a29dc31dd9 Mon Sep 17 00:00:00 2001 From: linDong <56677297@qq.com> Date: Tue, 16 Jul 2024 22:57:02 +0800 Subject: [PATCH 3/6] [test] add NoticeConfigControllerTest and MonitorsControllerTest test (#2290) --- .../controller/MonitorsControllerTest.java | 47 ++++++- .../NoticeConfigControllerTest.java | 133 +++++++++++++++--- 2 files changed, 162 insertions(+), 18 deletions(-) diff --git a/manager/src/test/java/org/apache/hertzbeat/manager/controller/MonitorsControllerTest.java b/manager/src/test/java/org/apache/hertzbeat/manager/controller/MonitorsControllerTest.java index c8d5bc873fa..5c630dcf431 100644 --- a/manager/src/test/java/org/apache/hertzbeat/manager/controller/MonitorsControllerTest.java +++ b/manager/src/test/java/org/apache/hertzbeat/manager/controller/MonitorsControllerTest.java @@ -17,10 +17,14 @@ package org.apache.hertzbeat.manager.controller; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.mockito.Mockito.doNothing; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; + import org.apache.hertzbeat.common.constants.CommonConstants; import org.apache.hertzbeat.common.util.JsonUtil; import org.apache.hertzbeat.manager.service.impl.MonitorServiceImpl; @@ -29,11 +33,13 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.multipart.MultipartFile; /** * Test case for {@link MonitorsController} @@ -115,4 +121,41 @@ void enableManageMonitors() throws Exception { .andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE)) .andReturn(); } + + @Test + void export() throws Exception { + List ids = Arrays.asList(6565463543L, 6565463544L); + String type = "JSON"; + + this.mockMvc.perform(MockMvcRequestBuilders.get("/api/monitors/export") + .param("ids", String.join(",", ids.stream().map(String::valueOf).collect(Collectors.toList()))) + .param("type", type)) + .andExpect(status().isOk()) + .andReturn(); + } + + @Test + void export2() throws Exception { + // Mock the behavior of monitorService.importConfig + doNothing().when(monitorService).importConfig((MultipartFile) Mockito.any()); + + // Perform the request and verify the response + this.mockMvc.perform(MockMvcRequestBuilders.post("/api/monitors/import") + .contentType(MediaType.MULTIPART_FORM_DATA) + .param("file", "testFileContent")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value("0")) + .andExpect(jsonPath("$.msg").value("Import success")); + } + + @Test + void duplicateMonitors() throws Exception { + // Mock the behavior of monitorService.copyMonitors + doNothing().when(monitorService).copyMonitors(List.of(6565463543L)); + + // Perform the POST request and verify the response + this.mockMvc.perform(MockMvcRequestBuilders.post("/api/monitors/copy") + .param("ids", "6565463543")) + .andExpect(status().isOk()); + } } diff --git a/manager/src/test/java/org/apache/hertzbeat/manager/controller/NoticeConfigControllerTest.java b/manager/src/test/java/org/apache/hertzbeat/manager/controller/NoticeConfigControllerTest.java index 33a775818a5..8ba3ef29128 100644 --- a/manager/src/test/java/org/apache/hertzbeat/manager/controller/NoticeConfigControllerTest.java +++ b/manager/src/test/java/org/apache/hertzbeat/manager/controller/NoticeConfigControllerTest.java @@ -17,10 +17,15 @@ package org.apache.hertzbeat.manager.controller; +import static org.mockito.Mockito.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; 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.Arrays; import java.util.List; +import java.util.Optional; + import org.apache.hertzbeat.common.constants.CommonConstants; import org.apache.hertzbeat.common.entity.manager.NoticeReceiver; import org.apache.hertzbeat.common.entity.manager.NoticeRule; @@ -117,7 +122,7 @@ void setUp() { void addNewNoticeReceiver() throws Exception { NoticeReceiver noticeReceiver = getNoticeReceiver(); System.out.println(noticeReceiver); - this.mockMvc.perform(MockMvcRequestBuilders.post("/api/notice/receiver") + this.mockMvc.perform(post("/api/notice/receiver") .contentType(MediaType.APPLICATION_JSON) .content(JsonUtil.toJson(noticeReceiver))) .andExpect(status().isOk()) @@ -130,7 +135,7 @@ void addNewNoticeReceiver() throws Exception { void editNoticeReceiver() throws Exception { NoticeReceiver noticeReceiver = getNoticeReceiver(); System.out.println(noticeReceiver); - this.mockMvc.perform(MockMvcRequestBuilders.put("/api/notice/receiver") + this.mockMvc.perform(put("/api/notice/receiver") .contentType(MediaType.APPLICATION_JSON) .content(JsonUtil.toJson(noticeReceiver))) .andExpect(status().isOk()) @@ -144,19 +149,19 @@ void editNoticeReceiver() throws Exception { void deleteNoticeReceiver() throws Exception { NoticeReceiver noticeReceiver = getNoticeReceiver(); - Mockito.when(noticeConfigService.getReceiverById(7565463543L)) + when(noticeConfigService.getReceiverById(7565463543L)) .thenReturn(noticeReceiver); - Mockito.when(noticeConfigService.getReceiverById(6565463543L)) + when(noticeConfigService.getReceiverById(6565463543L)) .thenReturn(null); - this.mockMvc.perform(MockMvcRequestBuilders.delete("/api/notice/receiver/{id}", 6565463543L)) + this.mockMvc.perform(delete("/api/notice/receiver/{id}", 6565463543L)) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE)) .andExpect(jsonPath("$.msg").value("The relevant information of the recipient could not be found, please check whether the parameters are correct")) .andReturn(); - this.mockMvc.perform(MockMvcRequestBuilders.delete("/api/notice/receiver/{id}", 7565463543L)) + this.mockMvc.perform(delete("/api/notice/receiver/{id}", 7565463543L)) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE)) .andExpect(jsonPath("$.msg").value("Delete success")) @@ -177,7 +182,7 @@ void getReceivers() throws Exception { @Test void addNewNoticeRule() throws Exception { NoticeRule noticeRule = getNoticeRule(); - this.mockMvc.perform(MockMvcRequestBuilders.post("/api/notice/rule") + this.mockMvc.perform(post("/api/notice/rule") .contentType(MediaType.APPLICATION_JSON) .content(JsonUtil.toJson(noticeRule))) .andExpect(status().isOk()) @@ -189,7 +194,7 @@ void addNewNoticeRule() throws Exception { @Test void editNoticeRule() throws Exception { NoticeRule noticeRule = getNoticeRule(); - this.mockMvc.perform(MockMvcRequestBuilders.put("/api/notice/rule") + this.mockMvc.perform(put("/api/notice/rule") .contentType(MediaType.APPLICATION_JSON) .content(JsonUtil.toJson(noticeRule))) .andExpect(status().isOk()) @@ -202,19 +207,19 @@ void editNoticeRule() throws Exception { void deleteNoticeRule() throws Exception { NoticeRule noticeRule = getNoticeRule(); - Mockito.when(noticeConfigService.getNoticeRulesById(7565463543L)) + when(noticeConfigService.getNoticeRulesById(7565463543L)) .thenReturn(noticeRule); - Mockito.when(noticeConfigService.getNoticeRulesById(6565463543L)) + when(noticeConfigService.getNoticeRulesById(6565463543L)) .thenReturn(null); - this.mockMvc.perform(MockMvcRequestBuilders.delete("/api/notice/rule/{id}", 6565463543L)) + this.mockMvc.perform(delete("/api/notice/rule/{id}", 6565463543L)) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE)) .andExpect(jsonPath("$.msg").value("The specified notification rule could not be queried, please check whether the parameters are correct")) .andReturn(); - this.mockMvc.perform(MockMvcRequestBuilders.delete("/api/notice/rule/{id}", 7565463543L)) + this.mockMvc.perform(delete("/api/notice/rule/{id}", 7565463543L)) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE)) .andExpect(jsonPath("$.msg").value("Delete success")) @@ -238,10 +243,10 @@ void getRules() throws Exception { @Test void sendTestMsg() throws Exception { NoticeReceiver noticeReceiver = getNoticeReceiver(); - Mockito.when(noticeConfigService.sendTestMsg(noticeReceiver)) + when(noticeConfigService.sendTestMsg(noticeReceiver)) .thenReturn(false); - this.mockMvc.perform(MockMvcRequestBuilders.post("/api/notice/receiver/send-test-msg") + this.mockMvc.perform(post("/api/notice/receiver/send-test-msg") .contentType(MediaType.APPLICATION_JSON) .content(JsonUtil.toJson(noticeReceiver))) .andExpect(status().isOk()) @@ -250,10 +255,10 @@ void sendTestMsg() throws Exception { .andReturn(); - Mockito.when(noticeConfigService.sendTestMsg(noticeReceiver)) + when(noticeConfigService.sendTestMsg(noticeReceiver)) .thenReturn(true); - this.mockMvc.perform(MockMvcRequestBuilders.post("/api/notice/receiver/send-test-msg") + this.mockMvc.perform(post("/api/notice/receiver/send-test-msg") .contentType(MediaType.APPLICATION_JSON) .content(JsonUtil.toJson(noticeReceiver))) .andExpect(status().isOk()) @@ -261,4 +266,100 @@ void sendTestMsg() throws Exception { //.andExpect(jsonPath("$.msg").value("Notify service not available, please check config!")) .andReturn(); } + + @Test + void addNewNoticeTemplate() throws Exception { + NoticeTemplate noticeTemplate = getNoticeTemplate(); + doNothing().when(noticeConfigService).addNoticeTemplate(noticeTemplate); + + this.mockMvc.perform(post("/api/notice/template") + .contentType(MediaType.APPLICATION_JSON) + .content(JsonUtil.toJson(noticeTemplate))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE)) + .andExpect(jsonPath("$.msg").value("Add success")) + .andReturn(); + + verify(noticeConfigService).addNoticeTemplate(noticeTemplate); + } + + @Test + void editNoticeTemplate() throws Exception { + NoticeTemplate noticeTemplate = getNoticeTemplate(); + doNothing().when(noticeConfigService).editNoticeTemplate(noticeTemplate); + + this.mockMvc.perform(put("/api/notice/template") + .contentType(MediaType.APPLICATION_JSON) + .content(JsonUtil.toJson(noticeTemplate))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE)) + .andExpect(jsonPath("$.msg").value("Edit success")) + .andReturn(); + + verify(noticeConfigService).editNoticeTemplate(noticeTemplate); + } + + @Test + void deleteNoticeTemplate_Success() throws Exception { + Long templateId = 1L; + when(noticeConfigService.getNoticeTemplatesById(templateId)).thenReturn(Optional.of(new NoticeTemplate())); + + mockMvc.perform(delete("/api/notice/template/{id}", templateId)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE)) + .andExpect(jsonPath("$.msg").value("Delete success")); + + Mockito.verify(noticeConfigService, Mockito.times(1)).deleteNoticeTemplate(templateId); + } + + @Test + void deleteNoticeTemplate_NotFound() throws Exception { + Long templateId = 1L; + when(noticeConfigService.getNoticeTemplatesById(templateId)).thenReturn(Optional.empty()); + + mockMvc.perform(delete("/api/notice/template/{id}", templateId)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE)) + .andExpect(jsonPath("$.msg").value("The specified notification template could not be queried, please check whether the parameters are correct")); + + Mockito.verify(noticeConfigService, Mockito.never()).deleteNoticeTemplate(templateId); + } + + @Test + void testGetTemplates() throws Exception { + // Mock the service response + NoticeTemplate template1 = new NoticeTemplate(); + template1.setName("Template1"); + NoticeTemplate template2 = new NoticeTemplate(); + template2.setName("Template2"); + List templates = Arrays.asList(template1, template2); + when(noticeConfigService.getNoticeTemplates(any())).thenReturn(templates); + + // Perform the GET request and verify the response + this.mockMvc.perform(get("/api/notice/templates") + .param("name", "Template")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE)) + .andExpect(jsonPath("$.data[0].name").value("Template1")) + .andExpect(jsonPath("$.data[1].name").value("Template2")); + } + + @Test + void sendTestMsg_Failure() throws Exception { + NoticeReceiver noticeReceiver = getNoticeReceiver(); + when(noticeConfigService.sendTestMsg(noticeReceiver)).thenReturn(false); + + this.mockMvc.perform(post("/api/notice/receiver/send-test-msg") + .contentType(MediaType.APPLICATION_JSON) + .content(JsonUtil.toJson(noticeReceiver))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value((int) CommonConstants.FAIL_CODE)) + .andExpect(jsonPath("$.msg").value("Notify service not available, please check config!")) + .andReturn(); + + verify(noticeConfigService, times(1)).sendTestMsg(noticeReceiver); + } + + + } From 7a4ee880c33567de5617dcefec1d82c3616b7431 Mon Sep 17 00:00:00 2001 From: liutianyou Date: Tue, 16 Jul 2024 23:18:53 +0800 Subject: [PATCH 4/6] [doc]add new committer blog (#2291) Co-authored-by: tomsun28 --- home/blog/2024-07-15-new-committer.md | 34 ++++++++++++++++++ .../2024-07-15-new-committer.md | 35 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 home/blog/2024-07-15-new-committer.md create mode 100644 home/i18n/zh-cn/docusaurus-plugin-content-blog/2024-07-15-new-committer.md diff --git a/home/blog/2024-07-15-new-committer.md b/home/blog/2024-07-15-new-committer.md new file mode 100644 index 00000000000..cd8b172c609 --- /dev/null +++ b/home/blog/2024-07-15-new-committer.md @@ -0,0 +1,34 @@ +--- +title: Welcome to HertzBeat Community Committer! +author: LiuTianyou +author_title: LiuTianyou +author_url: https://github.com/LiuTianyou +author_image_url: https://avatars.githubusercontent.com/u/30208283?v=4 +tags: [opensource, practice] +keywords: [open source monitoring system, alerting system] +--- + + +![hertzBeat](/img/blog/new-committer.png) + +Hello everyone, I am very honored to receive an invitation from the community to be nominated as a Committer for Apache HertzBeat. Let me introduce myself briefly. I have been working as a backend developer since 2019, mainly using Java. Currently, I am working at a network security company, focusing on the backend development of network security-related products. + +### Encounter + +In my work, several physical servers are deployed, running various databases and middleware. Although we have deployed the Prometheus + Grafana monitoring combination, most services and servers require additional installation of exporters. As a result, this monitoring system does not cover the entire project. Sometimes, we only realize a service is down when it is too late. One day in April, I came across an article introducing HertzBeat. I was immediately attracted by its unique features, such as no need for agents and fully visualized configuration, along with support for one-click deployment via Docker. I quickly deployed HertzBeat and put it into use. + +### Familiarization + +Due to the fully visualized operation, I quickly incorporated the servers, databases, and middleware used in the project into HertzBeat's management. Afterwards, the community was preparing to release the first Apache version and needed to supplement a large amount of documentation. I attempted to submit some documents to familiarize myself with the community's process for submitting code and documentation, and at the same time, I got familiar with the relevant parts of the code while supplementing the documents. + +### Trying to Add Something + +The first major change I made was to enable HertzBeat to support querying metrics from NebulaGraph using NGQL statements. Additionally, I added a monitoring template for NebulaGraph clusters based on this protocol. The idea initially came from my own needs. When I submitted this idea to the community, I quickly received a response and affirmation from the community, which greatly increased my confidence in continuously participating in this project. + +### Joining + +Due to my continuous writing of documents and contributing code, I started to become familiar with this community and this project, and began to make some of my own suggestions. Many of these suggestions were adopted by the community and released in new versions. After the first Apache version was released, I received an invitation from @tomsun28 and @TJxiaobao to be nominated as a Committer. + +### Conclusion + +I am very honored to be able to participate in this project and be recognized by the community. I would like to thank @tomsun28, @TJxiaobao, @zqr10159, @tuohai666, @yuluo-yx, @crossoverJie, @zhangshenghang, and @pwallk for reviewing my code, providing guidance, and helping me. Finally, I wish Apache HertzBeat to grow strong and have more and more contributors participating. diff --git a/home/i18n/zh-cn/docusaurus-plugin-content-blog/2024-07-15-new-committer.md b/home/i18n/zh-cn/docusaurus-plugin-content-blog/2024-07-15-new-committer.md new file mode 100644 index 00000000000..2cba35df2ce --- /dev/null +++ b/home/i18n/zh-cn/docusaurus-plugin-content-blog/2024-07-15-new-committer.md @@ -0,0 +1,35 @@ +--- +title: 热烈欢迎 HertzBeat 小伙伴新晋社区 Committer! +author: LiuTianyou +author_title: LiuTianyou +author_url: https://github.com/LiuTianyou +author_image_url: https://avatars.githubusercontent.com/u/30208283?v=4 +tags: [opensource, practice] +keywords: [open source monitoring system, alerting system] +--- + + +![hertzBeat](/img/blog/new-committer.png) + +大家好,非常荣幸可以收到社区邀请被提名为 Apache HertzBeat 的 Committer。我先做一个简单的自我介绍,从2019年工作开始,一直从事后端开发工作,主要使用Java语言,目前在一家网络安全公司从事网络安全相关产品后端开发工作。 + + +### 遇见 + +我工作的项目里部署着数台物理服务器,其中运行着各种数据库,中间件,尽管部署了 Prometheus + grafana 的监控组合,但由于大多数的服务和服务器都需要额外安装 exporter,这套监控系统并没有覆盖到项目的全部,有时候服务宕机了,被用到了才发现。四月份的某一天我刷到了一篇公众号文章介绍了 HertzBeat,我马上被不需要 agent,全程可视化配置的特新吸引加上支持docker一键部署,我迅速的部署起来了 HertzBeat 并投入了使用。 + +### 熟悉 + +由于完全可视化操作,很快就将项目中用到的服务器,数据库,中间件纳入了 HertzBeat 的管理。之后,恰好社区为发布第一个Apache版本做准备,需要补充大量的文档。我尝试提交一些文档,来熟悉社区的提交代码和文档的流程,也顺便在补充的文档的过程的熟悉相关部分的代码。 + +### 尝试加一点东西 + +我做的第一个大的改动是让 HertzBeat 支持使用NGQL语句从NebulaGraph中查询指标,并且这个基于协议增加了NebulaGraph集群的监控模板。最开始有这个想法来源于自己的需求,当我把这个想法提交给社区时,很快就得到了社区的回应,并得到了肯定,这也让对持续参与这个项目信心倍增。 + +### 加入 + +由于我不停的写文档,贡献代码,我开始熟悉这个社区,熟悉这个项目,开始尝试提出一些自己的建议。很多建议都被社区采纳,并且在新版本中发布,在第一个Apache版本发布后,我收到了@tomsun28和@TJxiaobao的邀请被提名为Committer。 + +### 结语 + +非常荣幸可以参与到这个项目中并被社区认可,感谢帮我review代码,给我指导和帮助的 @tomsun28,@TJxiaobao,@zqr10159,@tuohai666,@yuluo-yx,@crossoverJie,@zhangshenghang,@pwallk。最后祝 Apache HertzBeat 茁壮成长,有越来越多的贡献者参与其中。 From 8f659f0fd177efbf36f0a907b436911ea753cf11 Mon Sep 17 00:00:00 2001 From: YuLuo Date: Wed, 17 Jul 2024 09:51:04 +0800 Subject: [PATCH 5/6] [Improve] add common memory unit test (#2280) Co-authored-by: tomsun28 --- .../impl/InMemoryCommonDataQueueTest.java | 117 ++++++++++++++++++ .../KafkaCommonDataQueueTest.java} | 53 ++++---- 2 files changed, 140 insertions(+), 30 deletions(-) create mode 100644 common/src/test/java/org/apache/hertzbeat/common/queue/impl/InMemoryCommonDataQueueTest.java rename common/src/test/java/org/apache/hertzbeat/common/queue/{CommonDataQueueTest.java => impl/KafkaCommonDataQueueTest.java} (62%) diff --git a/common/src/test/java/org/apache/hertzbeat/common/queue/impl/InMemoryCommonDataQueueTest.java b/common/src/test/java/org/apache/hertzbeat/common/queue/impl/InMemoryCommonDataQueueTest.java new file mode 100644 index 00000000000..059f883dede --- /dev/null +++ b/common/src/test/java/org/apache/hertzbeat/common/queue/impl/InMemoryCommonDataQueueTest.java @@ -0,0 +1,117 @@ +/* + * 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.queue.impl; + +import java.util.Map; + +import org.apache.hertzbeat.common.entity.alerter.Alert; +import org.apache.hertzbeat.common.entity.message.CollectRep; +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.assertNotNull; + +/** + * Test case for {@link InMemoryCommonDataQueue} + */ +class InMemoryCommonDataQueueTest { + + private InMemoryCommonDataQueue queue; + + @BeforeEach + void setUp() { + queue = new InMemoryCommonDataQueue(); + } + + @Test + void testAlertsData() throws InterruptedException { + + var alert = new Alert(); + + queue.sendAlertsData(alert); + assertEquals(1, queue.getQueueSizeMetricsInfo().get("alertDataQueue")); + + var polledAlert = queue.pollAlertsData(); + assertEquals(0, queue.getQueueSizeMetricsInfo().get("alertDataQueue")); + + assertNotNull(polledAlert); + assertEquals(alert, polledAlert); + } + + @Test + void testMetricsData() throws InterruptedException { + + var metricsData = CollectRep.MetricsData.newBuilder().build(); + + queue.sendMetricsData(metricsData); + + CollectRep.MetricsData polledMetricsData = queue.pollMetricsDataToAlerter(); + + assertNotNull(polledMetricsData); + assertEquals(metricsData, polledMetricsData); + + polledMetricsData = queue.pollMetricsDataToPersistentStorage(); + + assertNotNull(polledMetricsData); + assertEquals(metricsData, polledMetricsData); + + polledMetricsData = queue.pollMetricsDataToRealTimeStorage(); + + assertNotNull(polledMetricsData); + assertEquals(metricsData, polledMetricsData); + } + + @Test + void testGetQueueSizeMetricsInfo() { + + Map metricsInfo = queue.getQueueSizeMetricsInfo(); + + assertEquals(0, metricsInfo.get("alertDataQueue")); + assertEquals(0, metricsInfo.get("metricsDataToAlertQueue")); + assertEquals(0, metricsInfo.get("metricsDataToPersistentStorageQueue")); + assertEquals(0, metricsInfo.get("metricsDataToMemoryStorageQueue")); + + queue.sendAlertsData(new Alert()); + queue.sendMetricsData(CollectRep.MetricsData.newBuilder().build()); + + metricsInfo = queue.getQueueSizeMetricsInfo(); + + assertEquals(1, metricsInfo.get("alertDataQueue")); + assertEquals(1, metricsInfo.get("metricsDataToAlertQueue")); + assertEquals(1, metricsInfo.get("metricsDataToPersistentStorageQueue")); + assertEquals(1, metricsInfo.get("metricsDataToMemoryStorageQueue")); + } + + @Test + void testDestroy() { + + queue.sendAlertsData(new Alert()); + queue.sendMetricsData(CollectRep.MetricsData.newBuilder().build()); + + queue.destroy(); + + Map metricsInfo = queue.getQueueSizeMetricsInfo(); + + assertEquals(0, metricsInfo.get("alertDataQueue")); + assertEquals(0, metricsInfo.get("metricsDataToAlertQueue")); + assertEquals(0, metricsInfo.get("metricsDataToPersistentStorageQueue")); + assertEquals(0, metricsInfo.get("metricsDataToMemoryStorageQueue")); + } + +} diff --git a/common/src/test/java/org/apache/hertzbeat/common/queue/CommonDataQueueTest.java b/common/src/test/java/org/apache/hertzbeat/common/queue/impl/KafkaCommonDataQueueTest.java similarity index 62% rename from common/src/test/java/org/apache/hertzbeat/common/queue/CommonDataQueueTest.java rename to common/src/test/java/org/apache/hertzbeat/common/queue/impl/KafkaCommonDataQueueTest.java index 5b6e836d55b..8f2c0e7ca46 100644 --- a/common/src/test/java/org/apache/hertzbeat/common/queue/CommonDataQueueTest.java +++ b/common/src/test/java/org/apache/hertzbeat/common/queue/impl/KafkaCommonDataQueueTest.java @@ -15,46 +15,39 @@ * limitations under the License. */ -package org.apache.hertzbeat.common.queue; +package org.apache.hertzbeat.common.queue.impl; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; + /** - * Test case for {@link CommonDataQueue} + * Test case for {@link KafkaCommonDataQueue} */ -class CommonDataQueueTest { - - @BeforeEach - void setUp() { - } +class KafkaCommonDataQueueTest { - @AfterEach - void tearDown() { - } + @BeforeEach + void setUp() { + } - @Test - void addAlertData() { - } + @Test + void testSendAlertsData() { + } - @Test - void pollAlertData() { - } + @Test + void testPollAlertsData() { + } - @Test - void pollAlertMetricsData() { - } + @Test + void testSendMetricsData() { + } - @Test - void pollPersistentStorageMetricsData() { - } + @Test + void testPollMetricsDataToAlerter() { + } - @Test - void pollRealTimeStorageMetricsData() { - } + @Test + void testDestroy() { + } - @Test - void sendMetricsData() { - } -} \ No newline at end of file +} From 7e5283ea0d9e9c020651bfaa87a9832e39659232 Mon Sep 17 00:00:00 2001 From: QBH-insist Date: Wed, 17 Jul 2024 10:25:42 +0800 Subject: [PATCH 6/6] [doc] fix mysql connections field explanation (#2294) --- manager/src/main/resources/define/app-mysql.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manager/src/main/resources/define/app-mysql.yml b/manager/src/main/resources/define/app-mysql.yml index 1ec1c086306..f3d1cc4f6a2 100644 --- a/manager/src/main/resources/define/app-mysql.yml +++ b/manager/src/main/resources/define/app-mysql.yml @@ -569,7 +569,7 @@ metrics: - field: connections type: 0 i18n: - zh-CN: 当前连接数 + zh-CN: 连接的总次数 en-US: Connections - field: max_used_connections type: 0