3 * Copyright (C) 2009-2024 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.server.monitoring;
22 import com.google.gson.Gson;
23 import com.google.gson.JsonObject;
24 import io.prometheus.client.CollectorRegistry;
25 import java.io.IOException;
27 import java.nio.charset.StandardCharsets;
28 import org.assertj.core.api.Assertions;
29 import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
30 import org.elasticsearch.cluster.health.ClusterHealthStatus;
31 import org.junit.Before;
32 import org.junit.Rule;
33 import org.junit.Test;
34 import org.mockito.Mockito;
35 import org.slf4j.event.Level;
36 import org.sonar.api.config.Configuration;
37 import org.sonar.api.config.internal.MapSettings;
38 import org.sonar.api.internal.apachecommons.io.IOUtils;
39 import org.sonar.api.internal.apachecommons.lang.StringUtils;
40 import org.sonar.api.testfixtures.log.LogTester;
41 import org.sonar.server.es.EsClient;
42 import org.sonar.server.es.response.NodeStatsResponse;
44 import static org.assertj.core.api.Assertions.assertThat;
45 import static org.mockito.ArgumentMatchers.any;
46 import static org.mockito.Mockito.mock;
47 import static org.mockito.Mockito.times;
48 import static org.mockito.Mockito.verify;
49 import static org.mockito.Mockito.verifyNoMoreInteractions;
50 import static org.mockito.Mockito.when;
52 public class ElasticSearchMetricTaskTest {
55 public LogTester logTester = new LogTester();
57 private final ServerMonitoringMetrics serverMonitoringMetrics = mock(ServerMonitoringMetrics.class);
58 private final EsClient esClient = mock(EsClient.class);
59 private final Configuration configuration = new MapSettings().asConfig();
61 private final ElasticSearchMetricTask underTest = new ElasticSearchMetricTask(serverMonitoringMetrics, esClient, configuration);
64 public void before() {
65 CollectorRegistry.defaultRegistry.clear();
69 public void when_elasticsearch_up_status_is_updated_to_green() {
70 ClusterHealthResponse clusterHealthResponse = new ClusterHealthResponse();
71 clusterHealthResponse.setStatus(ClusterHealthStatus.GREEN);
72 when(esClient.clusterHealth(any())).thenReturn(clusterHealthResponse);
76 verify(serverMonitoringMetrics, times(1)).setElasticSearchStatusToGreen();
77 verifyNoMoreInteractions(serverMonitoringMetrics);
83 public void elasticsearch_free_disk_space_is_updated() throws IOException {
84 URL esNodeResponseUrl = getClass().getResource("es-node-response.json");
85 String jsonPayload = StringUtils.trim(IOUtils.toString(esNodeResponseUrl, StandardCharsets.UTF_8));
87 JsonObject jsonObject = new Gson().fromJson(jsonPayload, JsonObject.class);
88 NodeStatsResponse nodeStats = NodeStatsResponse.toNodeStatsResponse(jsonObject);
90 when(esClient.nodesStats()).thenReturn(nodeStats);
94 String nodeName = nodeStats.getNodeStats().get(0).getName();
95 verify(serverMonitoringMetrics, times(1)).setElasticSearchDiskSpaceFreeBytes(nodeName, 136144027648L);
96 verify(serverMonitoringMetrics, times(1)).setElasticSearchDiskSpaceTotalBytes(nodeName, 250685575168L);
98 // elasticsearch health status is not mocked in this test, so this part raise an exception
99 assertThat(logTester.logs()).hasSize(1);
100 assertThat(logTester.logs(Level.ERROR)).containsOnly("Failed to query ES status");
104 public void when_elasticsearch_yellow_status_is_updated_to_green() {
105 ClusterHealthResponse clusterHealthResponse = new ClusterHealthResponse();
106 clusterHealthResponse.setStatus(ClusterHealthStatus.YELLOW);
107 when(esClient.clusterHealth(any())).thenReturn(clusterHealthResponse);
111 verify(serverMonitoringMetrics, times(1)).setElasticSearchStatusToGreen();
112 verifyNoMoreInteractions(serverMonitoringMetrics);
116 public void when_elasticsearch_down_status_is_updated_to_red() {
117 ClusterHealthResponse clusterHealthResponse = new ClusterHealthResponse();
118 clusterHealthResponse.setStatus(ClusterHealthStatus.RED);
119 when(esClient.clusterHealth(any())).thenReturn(clusterHealthResponse);
123 verify(serverMonitoringMetrics, times(1)).setElasticSearchStatusToRed();
124 verifyNoMoreInteractions(serverMonitoringMetrics);
128 public void when_no_es_status_null_status_is_updated_to_red() {
129 ClusterHealthResponse clusterHealthResponse = Mockito.mock(ClusterHealthResponse.class);
130 when(clusterHealthResponse.getStatus()).thenReturn(null);
131 when(esClient.clusterHealth(any())).thenReturn(clusterHealthResponse);
135 verify(serverMonitoringMetrics, times(1)).setElasticSearchStatusToRed();
136 verifyNoMoreInteractions(serverMonitoringMetrics);
140 public void when_es_status_throw_exception_status_is_updated_to_red() {
141 when(esClient.clusterHealth(any())).thenThrow(new IllegalStateException("exception in cluster health"));
145 verify(serverMonitoringMetrics, times(1)).setElasticSearchStatusToRed();
146 verifyNoMoreInteractions(serverMonitoringMetrics);
148 assertThat(logTester.logs()).hasSize(2);
149 assertThat(logTester.logs(Level.ERROR)).containsOnly("Failed to query ES status");
153 public void task_has_default_delay(){
154 Assertions.assertThat(underTest.getDelay()).isPositive();
155 Assertions.assertThat(underTest.getPeriod()).isPositive();