Improvements for transports monitoring; remove UI healthchecker
This commit is contained in:
parent
7eff0fc346
commit
1ffc8107d5
@ -21,12 +21,11 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.thingsboard</groupId>
|
||||
<version>3.4.2-SNAPSHOT</version>
|
||||
<version>3.4.3-SNAPSHOT</version>
|
||||
<artifactId>thingsboard</artifactId>
|
||||
</parent>
|
||||
|
||||
<artifactId>monitoring</artifactId>
|
||||
<version>3.4.2-SNAPSHOT</version>
|
||||
<name>ThingsBoard Monitoring Service</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
@ -96,20 +95,9 @@
|
||||
<artifactId>Java-WebSocket</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.seleniumhq.selenium</groupId>
|
||||
<artifactId>selenium-java</artifactId>
|
||||
<version>4.6.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>31.1-jre</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.bonigarcia</groupId>
|
||||
<artifactId>webdrivermanager</artifactId>
|
||||
<version>5.3.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
|
||||
@ -14,9 +14,9 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
export JAVA_OPTS="$JAVA_OPTS -Xlog:gc*,heap*,age*,safepoint=debug:file=@pkg.logFolder@/gc.log:time,uptime,level,tags:filecount=10,filesize=10M"
|
||||
export JAVA_OPTS="$JAVA_OPTS -Xlog:gc*,heap*,age*,safepoint=debug:file=/var/log/tb-monitoring/gc.log:time,uptime,level,tags:filecount=10,filesize=10M"
|
||||
export JAVA_OPTS="$JAVA_OPTS -XX:+IgnoreUnrecognizedVMOptions -XX:+HeapDumpOnOutOfMemoryError"
|
||||
export JAVA_OPTS="$JAVA_OPTS -XX:-UseBiasedLocking -XX:+UseTLAB -XX:+ResizeTLAB -XX:+PerfDisableSharedMem -XX:+UseCondCardMark"
|
||||
export JAVA_OPTS="$JAVA_OPTS -XX:+UseG1GC -XX:MaxGCPauseMillis=500 -XX:+UseStringDeduplication -XX:+ParallelRefProcEnabled -XX:MaxTenuringThreshold=10"
|
||||
export LOG_FILENAME=${pkg.name}.out
|
||||
export LOADER_PATH=${pkg.installFolder}/conf
|
||||
export LOG_FILENAME=tb-monitoring.out
|
||||
export LOADER_PATH=/usr/share/tb-monitoring/conf
|
||||
|
||||
@ -36,6 +36,10 @@ public class Latency {
|
||||
return latencySum.get() / counter.get();
|
||||
}
|
||||
|
||||
public boolean isNotEmpty() {
|
||||
return counter.get() > 0;
|
||||
}
|
||||
|
||||
public synchronized void reset() {
|
||||
latencySum.set(0.0);
|
||||
counter.set(0);
|
||||
|
||||
@ -73,7 +73,9 @@ public class MonitoringReporter {
|
||||
return;
|
||||
}
|
||||
log.info("Latencies:\n{}", latencies.values());
|
||||
if (latencies.values().stream().anyMatch(latency -> latency.getAvg() >= (double) latencyThresholdMs)) {
|
||||
if (latencies.values().stream()
|
||||
.filter(Latency::isNotEmpty)
|
||||
.anyMatch(latency -> latency.getAvg() >= (double) latencyThresholdMs)) {
|
||||
HighLatencyNotification highLatencyNotification = new HighLatencyNotification(latencies.values(), latencyThresholdMs);
|
||||
notificationService.sendNotification(highLatencyNotification);
|
||||
}
|
||||
@ -89,9 +91,11 @@ public class MonitoringReporter {
|
||||
tbClient.logIn();
|
||||
ObjectNode msg = JacksonUtil.newObjectNode();
|
||||
latencies.forEach((key, latency) -> {
|
||||
msg.set(key, new DoubleNode(latency.getAvg()));
|
||||
if (latency.isNotEmpty()) {
|
||||
msg.set(key, new DoubleNode(latency.getAvg()));
|
||||
latency.reset();
|
||||
}
|
||||
});
|
||||
latencies.clear();
|
||||
tbClient.saveEntityTelemetry(entityId, "time", msg);
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to report latencies: {}", e.getMessage());
|
||||
|
||||
@ -143,7 +143,7 @@ public abstract class TransportMonitoringService<C extends TransportMonitoringSe
|
||||
wsClient.waitForUpdate(wsConfig.getResultCheckTimeoutMs());
|
||||
Object update = wsClient.getTelemetryKeyUpdate(TEST_TELEMETRY_KEY);
|
||||
if (update == null) {
|
||||
throw new TransportFailureException("No WS update arrived");
|
||||
throw new TransportFailureException("No WS update arrived within " + wsConfig.getResultCheckTimeoutMs() + " ms");
|
||||
} else if (!update.toString().equals(testValue)) {
|
||||
throw new TransportFailureException("Was expecting value " + testValue + " but got " + update);
|
||||
}
|
||||
|
||||
@ -1,113 +0,0 @@
|
||||
/**
|
||||
* Copyright © 2016-2022 The Thingsboard Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.thingsboard.monitoring.service;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.chrome.ChromeOptions;
|
||||
import org.openqa.selenium.remote.RemoteWebDriver;
|
||||
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.thingsboard.monitoring.data.Latencies;
|
||||
import org.thingsboard.monitoring.data.MonitoredServiceKey;
|
||||
import org.thingsboard.monitoring.util.TbStopWatch;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.openqa.selenium.By.xpath;
|
||||
import static org.openqa.selenium.support.ui.ExpectedConditions.elementToBeClickable;
|
||||
import static org.openqa.selenium.support.ui.ExpectedConditions.urlContains;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
@ConditionalOnProperty(name = "monitoring.ui.enabled", havingValue = "true")
|
||||
public class WebUiHealthChecker {
|
||||
|
||||
@Value("${monitoring.ui.url}")
|
||||
private String url;
|
||||
@Value("${monitoring.auth.username}")
|
||||
private String username;
|
||||
@Value("${monitoring.auth.password}")
|
||||
private String password;
|
||||
@Value("${monitoring.ui.monitoring_rate_sec}")
|
||||
private int monitoringRateSec;
|
||||
@Value("${monitoring.rest_request_timeout_ms}")
|
||||
private int timeoutMs;
|
||||
@Value("${monitoring.ui.remote_webdriver_url}")
|
||||
private String remoteWebdriverUrl;
|
||||
|
||||
private final MonitoringReporter monitoringReporter;
|
||||
private final ScheduledExecutorService monitoringExecutor;
|
||||
private final TbStopWatch stopWatch;
|
||||
|
||||
private static final String EMAIL_FIELD = "//input[@id='username-input']";
|
||||
private static final String PASSWORD_FIELD = "//input[@id='password-input']";
|
||||
private static final String SUBMIT_BTN = "//button[@type='submit']";
|
||||
private static final String DEVICES_BTN = "//mat-toolbar//a[@href='/devices']";
|
||||
|
||||
@EventListener(ApplicationReadyEvent.class)
|
||||
public void startMonitoring() {
|
||||
monitoringExecutor.scheduleWithFixedDelay(() -> {
|
||||
RemoteWebDriver driver = null;
|
||||
try {
|
||||
driver = createDriver();
|
||||
WebDriverWait wait = createDriverWait(driver);
|
||||
driver.manage().window().maximize();
|
||||
driver.get(url + "/login");
|
||||
|
||||
try {
|
||||
stopWatch.start();
|
||||
wait.until(elementToBeClickable(xpath(EMAIL_FIELD))).sendKeys(username);
|
||||
wait.until(elementToBeClickable(xpath(PASSWORD_FIELD))).sendKeys(password);
|
||||
wait.until(elementToBeClickable(xpath(SUBMIT_BTN))).click();
|
||||
monitoringReporter.reportLatency(Latencies.WEB_UI_LOAD, stopWatch.getTime());
|
||||
|
||||
wait.until(urlContains("/home"));
|
||||
wait.until(elementToBeClickable(xpath(DEVICES_BTN))).click();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Expected web UI elements were not displayed", e);
|
||||
}
|
||||
|
||||
monitoringReporter.serviceIsOk(MonitoredServiceKey.WEB_UI);
|
||||
} catch (Exception e) {
|
||||
monitoringReporter.serviceFailure(MonitoredServiceKey.WEB_UI, e);
|
||||
} finally {
|
||||
if (driver != null) driver.quit();
|
||||
}
|
||||
}, 0, monitoringRateSec, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
private RemoteWebDriver createDriver() throws MalformedURLException {
|
||||
ChromeOptions options = new ChromeOptions();
|
||||
options.setPageLoadTimeout(Duration.ofMillis(timeoutMs));
|
||||
return new RemoteWebDriver(new URL(remoteWebdriverUrl + "/wd/hub"), options);
|
||||
}
|
||||
|
||||
private WebDriverWait createDriverWait(WebDriver driver) {
|
||||
return new WebDriverWait(driver, Duration.ofMillis(timeoutMs));
|
||||
}
|
||||
|
||||
}
|
||||
@ -15,7 +15,9 @@
|
||||
*/
|
||||
package org.thingsboard.monitoring.service.impl;
|
||||
|
||||
import org.eclipse.paho.client.mqttv3.IMqttToken;
|
||||
import org.eclipse.paho.client.mqttv3.MqttAsyncClient;
|
||||
import org.eclipse.paho.client.mqttv3.MqttClient;
|
||||
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
|
||||
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
||||
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
|
||||
@ -31,7 +33,7 @@ import org.thingsboard.monitoring.service.TransportMonitoringService;
|
||||
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public class MqttTransportMonitoringService extends TransportMonitoringService<MqttTransportMonitoringServiceConfig> {
|
||||
|
||||
private MqttAsyncClient mqttClient;
|
||||
private MqttClient mqttClient;
|
||||
|
||||
private static final String DEVICE_TELEMETRY_TOPIC = "v1/devices/me/telemetry";
|
||||
|
||||
@ -44,11 +46,16 @@ public class MqttTransportMonitoringService extends TransportMonitoringService<M
|
||||
if (mqttClient == null || !mqttClient.isConnected()) {
|
||||
String clientId = MqttAsyncClient.generateClientId();
|
||||
String accessToken = target.getDevice().getCredentials().getCredentialsId();
|
||||
mqttClient = new MqttAsyncClient(target.getBaseUrl(), clientId, new MemoryPersistence());
|
||||
mqttClient = new MqttClient(target.getBaseUrl(), clientId, new MemoryPersistence());
|
||||
mqttClient.setTimeToWait(config.getRequestTimeoutMs());
|
||||
|
||||
MqttConnectOptions options = new MqttConnectOptions();
|
||||
options.setUserName(accessToken);
|
||||
mqttClient.connect(options).waitForCompletion(config.getRequestTimeoutMs());
|
||||
options.setConnectionTimeout(config.getRequestTimeoutMs() / 1000);
|
||||
IMqttToken result = mqttClient.connectWithResult(options);
|
||||
if (result.getException() != null) {
|
||||
throw result.getException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,7 +64,7 @@ public class MqttTransportMonitoringService extends TransportMonitoringService<M
|
||||
MqttMessage message = new MqttMessage();
|
||||
message.setPayload(payload.getBytes());
|
||||
message.setQos(config.getQos());
|
||||
mqttClient.publish(DEVICE_TELEMETRY_TOPIC, message).waitForCompletion(config.getRequestTimeoutMs());
|
||||
mqttClient.publish(DEVICE_TELEMETRY_TOPIC, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -63,12 +63,6 @@ monitoring:
|
||||
device:
|
||||
id: '${HTTP_TRANSPORT_TARGET_DEVICE_ID:}'
|
||||
|
||||
ui:
|
||||
enabled: '${UI_MONITORING_ENABLED:false}'
|
||||
url: '${UI_URL:http://localhost:4200}'
|
||||
remote_webdriver_url: '${UI_MONITORING_REMOTE_WEBDRIVER_URL:http://localhost:4444}'
|
||||
monitoring_rate_sec: '${UI_MONITORING_RATE_SEC:300}'
|
||||
|
||||
notification_channels:
|
||||
slack:
|
||||
enabled: '${SLACK_NOTIFICATION_CHANNEL_ENABLED:false}'
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.thingsboard</groupId>
|
||||
<version>3.4.2-SNAPSHOT</version>
|
||||
<version>3.4.3-SNAPSHOT</version>
|
||||
<artifactId>msa</artifactId>
|
||||
</parent>
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user