Add more logging; fix race condition in WS client

This commit is contained in:
ViacheslavKlimov 2023-01-09 13:08:15 +02:00
parent 1ffc8107d5
commit 8a12c63400
7 changed files with 58 additions and 15 deletions

View File

@ -17,7 +17,7 @@
--> -->
<!DOCTYPE configuration> <!DOCTYPE configuration>
<configuration> <configuration scan="true" scanPeriod="30 seconds">
<appender name="fileLogAppender" <appender name="fileLogAppender"
class="ch.qos.logback.core.rolling.RollingFileAppender"> class="ch.qos.logback.core.rolling.RollingFileAppender">
@ -41,10 +41,8 @@
<logger name="org" level="WARN"/> <logger name="org" level="WARN"/>
<logger name="org.thingsboard.server" level="INFO"/> <logger name="org.thingsboard.server" level="INFO"/>
<logger name="org.thingsboard.monitoring" level="TRACE"/> <logger name="org.thingsboard.monitoring" level="DEBUG"/>
<logger name="org.thingsboard.monitoring.client" level="WARN"/> <logger name="org.thingsboard.monitoring.client" level="INFO"/>
<logger name="org.openqa.selenium" level="WARN"/>
<logger name="io.github.bonigarcia" level="WARN"/>
<root level="INFO"> <root level="INFO">
<appender-ref ref="fileLogAppender"/> <appender-ref ref="fileLogAppender"/>

View File

@ -33,14 +33,18 @@ import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@Slf4j @Slf4j
public class WsClient extends WebSocketClient { public class WsClient extends WebSocketClient {
private volatile String lastMsg; public volatile String lastMsg;
private CountDownLatch reply; private CountDownLatch reply;
private CountDownLatch update; private CountDownLatch update;
private final Lock updateLock = new ReentrantLock();
public WsClient(URI serverUri) { public WsClient(URI serverUri) {
super(serverUri); super(serverUri);
} }
@ -52,12 +56,21 @@ public class WsClient extends WebSocketClient {
@Override @Override
public void onMessage(String s) { public void onMessage(String s) {
log.trace("Received new msg: {}", s);
if (s == null) {
return;
}
updateLock.lock();
try {
lastMsg = s; lastMsg = s;
if (update != null) {
update.countDown();
}
if (reply != null) { if (reply != null) {
reply.countDown(); reply.countDown();
} }
if (update != null) { } finally {
update.countDown(); updateLock.unlock();
} }
} }
@ -72,13 +85,24 @@ public class WsClient extends WebSocketClient {
} }
public void registerWaitForUpdate() { public void registerWaitForUpdate() {
updateLock.lock();
try {
lastMsg = null; lastMsg = null;
update = new CountDownLatch(1); update = new CountDownLatch(1);
} finally {
updateLock.unlock();
}
log.trace("Registered wait for update");
} }
@Override @Override
public void send(String text) throws NotYetConnectedException { public void send(String text) throws NotYetConnectedException {
updateLock.lock();
try {
reply = new CountDownLatch(1); reply = new CountDownLatch(1);
} finally {
updateLock.unlock();
}
super.send(text); super.send(text);
} }
@ -93,27 +117,33 @@ public class WsClient extends WebSocketClient {
CmdsWrapper wrapper = new CmdsWrapper(); CmdsWrapper wrapper = new CmdsWrapper();
wrapper.setTsSubCmds(List.of(subCmd)); wrapper.setTsSubCmds(List.of(subCmd));
send(JacksonUtil.toString(wrapper)); send(JacksonUtil.toString(wrapper));
log.trace("Subscribed for telemetry (key: {})", telemetryKey);
} }
public JsonNode waitForUpdate(long ms) { public JsonNode waitForUpdate(long ms) {
log.trace("update latch count: {}", update.getCount());
try { try {
if (update.await(ms, TimeUnit.MILLISECONDS)) { if (update.await(ms, TimeUnit.MILLISECONDS)) {
log.trace("Waited for update");
return getLastMsg(); return getLastMsg();
} }
} catch (InterruptedException e) { } catch (InterruptedException e) {
log.debug("Failed to await reply", e); log.debug("Failed to await reply", e);
} }
log.trace("No update arrived within {} ms", ms);
return null; return null;
} }
public JsonNode waitForReply(int ms) { public JsonNode waitForReply(int ms) {
try { try {
if (reply.await(ms, TimeUnit.MILLISECONDS)) { if (reply.await(ms, TimeUnit.MILLISECONDS)) {
log.trace("Waited for reply");
return getLastMsg(); return getLastMsg();
} }
} catch (InterruptedException e) { } catch (InterruptedException e) {
log.debug("Failed to await reply", e); log.debug("Failed to await reply", e);
} }
log.trace("No reply arrived within {} ms", ms);
return null; return null;
} }

View File

@ -18,6 +18,5 @@ package org.thingsboard.monitoring.data;
public class MonitoredServiceKey { public class MonitoredServiceKey {
public static final String GENERAL = "Monitoring"; public static final String GENERAL = "Monitoring";
public static final String WEB_UI = "Web UI";
} }

View File

@ -81,6 +81,7 @@ public abstract class TransportMonitoringService<C extends TransportMonitoringSe
monitoringExecutor.scheduleWithFixedDelay(() -> { monitoringExecutor.scheduleWithFixedDelay(() -> {
WsClient wsClient = null; WsClient wsClient = null;
try { try {
log.trace("[{}] Checking", transportInfo);
wsClient = establishWsClient(); wsClient = establishWsClient();
wsClient.registerWaitForUpdate(); wsClient.registerWaitForUpdate();
@ -88,13 +89,16 @@ public abstract class TransportMonitoringService<C extends TransportMonitoringSe
String testPayload = JacksonUtil.newObjectNode().set(TEST_TELEMETRY_KEY, new TextNode(testValue)).toString(); String testPayload = JacksonUtil.newObjectNode().set(TEST_TELEMETRY_KEY, new TextNode(testValue)).toString();
try { try {
initClientAndSendPayload(testPayload); initClientAndSendPayload(testPayload);
log.trace("[{}] Sent test payload ({})", transportInfo, testPayload);
} catch (Throwable e) { } catch (Throwable e) {
throw new TransportFailureException(e); throw new TransportFailureException(e);
} }
log.trace("[{}] Waiting for WS update", transportInfo);
checkWsUpdate(wsClient, testValue); checkWsUpdate(wsClient, testValue);
monitoringReporter.serviceIsOk(transportInfo); monitoringReporter.serviceIsOk(transportInfo);
monitoringReporter.serviceIsOk(MonitoredServiceKey.GENERAL);
} catch (TransportFailureException transportFailureException) { } catch (TransportFailureException transportFailureException) {
monitoringReporter.serviceFailure(transportInfo, transportFailureException); monitoringReporter.serviceFailure(transportInfo, transportFailureException);
} catch (Exception e) { } catch (Exception e) {
@ -141,6 +145,7 @@ public abstract class TransportMonitoringService<C extends TransportMonitoringSe
private void checkWsUpdate(WsClient wsClient, String testValue) { private void checkWsUpdate(WsClient wsClient, String testValue) {
stopWatch.start(); stopWatch.start();
wsClient.waitForUpdate(wsConfig.getResultCheckTimeoutMs()); wsClient.waitForUpdate(wsConfig.getResultCheckTimeoutMs());
log.trace("[{}] Waited for WS update. Last WS msg: {}", transportInfo, wsClient.lastMsg);
Object update = wsClient.getTelemetryKeyUpdate(TEST_TELEMETRY_KEY); Object update = wsClient.getTelemetryKeyUpdate(TEST_TELEMETRY_KEY);
if (update == null) { if (update == null) {
throw new TransportFailureException("No WS update arrived within " + wsConfig.getResultCheckTimeoutMs() + " ms"); throw new TransportFailureException("No WS update arrived within " + wsConfig.getResultCheckTimeoutMs() + " ms");

View File

@ -15,6 +15,7 @@
*/ */
package org.thingsboard.monitoring.service.impl; package org.thingsboard.monitoring.service.impl;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.californium.core.CoapClient; import org.eclipse.californium.core.CoapClient;
import org.eclipse.californium.core.CoapResponse; import org.eclipse.californium.core.CoapResponse;
import org.eclipse.californium.core.coap.CoAP; import org.eclipse.californium.core.coap.CoAP;
@ -31,6 +32,7 @@ import java.io.IOException;
@Component @Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Slf4j
public class CoapTransportMonitoringService extends TransportMonitoringService<CoapTransportMonitoringServiceConfig> { public class CoapTransportMonitoringService extends TransportMonitoringService<CoapTransportMonitoringServiceConfig> {
private CoapClient coapClient; private CoapClient coapClient;
@ -46,6 +48,7 @@ public class CoapTransportMonitoringService extends TransportMonitoringService<C
String uri = target.getBaseUrl() + "/api/v1/" + accessToken + "/telemetry"; String uri = target.getBaseUrl() + "/api/v1/" + accessToken + "/telemetry";
coapClient = new CoapClient(uri); coapClient = new CoapClient(uri);
coapClient.setTimeout((long) config.getRequestTimeoutMs()); coapClient.setTimeout((long) config.getRequestTimeoutMs());
log.debug("Initialized CoAP client for URI {}", uri);
} }
} }
@ -63,6 +66,7 @@ public class CoapTransportMonitoringService extends TransportMonitoringService<C
if (coapClient != null) { if (coapClient != null) {
coapClient.shutdown(); coapClient.shutdown();
coapClient = null; coapClient = null;
log.info("Disconnected CoAP client");
} }
} }

View File

@ -15,6 +15,7 @@
*/ */
package org.thingsboard.monitoring.service.impl; package org.thingsboard.monitoring.service.impl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
@ -29,6 +30,7 @@ import java.time.Duration;
@Component @Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Slf4j
public class HttpTransportMonitoringService extends TransportMonitoringService<HttpTransportMonitoringServiceConfig> { public class HttpTransportMonitoringService extends TransportMonitoringService<HttpTransportMonitoringServiceConfig> {
private RestTemplate restTemplate; private RestTemplate restTemplate;
@ -44,6 +46,7 @@ public class HttpTransportMonitoringService extends TransportMonitoringService<H
.setConnectTimeout(Duration.ofMillis(config.getRequestTimeoutMs())) .setConnectTimeout(Duration.ofMillis(config.getRequestTimeoutMs()))
.setReadTimeout(Duration.ofMillis(config.getRequestTimeoutMs())) .setReadTimeout(Duration.ofMillis(config.getRequestTimeoutMs()))
.build(); .build();
log.debug("Initialized HTTP client");
} }
} }

View File

@ -15,6 +15,7 @@
*/ */
package org.thingsboard.monitoring.service.impl; package org.thingsboard.monitoring.service.impl;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.IMqttToken; import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttAsyncClient; import org.eclipse.paho.client.mqttv3.MqttAsyncClient;
import org.eclipse.paho.client.mqttv3.MqttClient; import org.eclipse.paho.client.mqttv3.MqttClient;
@ -31,6 +32,7 @@ import org.thingsboard.monitoring.service.TransportMonitoringService;
@Component @Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Slf4j
public class MqttTransportMonitoringService extends TransportMonitoringService<MqttTransportMonitoringServiceConfig> { public class MqttTransportMonitoringService extends TransportMonitoringService<MqttTransportMonitoringServiceConfig> {
private MqttClient mqttClient; private MqttClient mqttClient;
@ -56,6 +58,7 @@ public class MqttTransportMonitoringService extends TransportMonitoringService<M
if (result.getException() != null) { if (result.getException() != null) {
throw result.getException(); throw result.getException();
} }
log.debug("Initialized MQTT client for URI {}", mqttClient.getServerURI());
} }
} }
@ -72,6 +75,7 @@ public class MqttTransportMonitoringService extends TransportMonitoringService<M
if (mqttClient != null) { if (mqttClient != null) {
mqttClient.disconnect(); mqttClient.disconnect();
mqttClient = null; mqttClient = null;
log.info("Disconnected MQTT client");
} }
} }