Merge pull request #10436 from zzzeebra/transport_log_optimization

[3.7] Http Transport log optimization
This commit is contained in:
Andrew Shvayka 2024-04-01 12:08:15 +03:00 committed by GitHub
commit ffad62892d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 136 additions and 33 deletions

View File

@ -16,12 +16,11 @@
package org.thingsboard.server.transport.http; package org.thingsboard.server.transport.http;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -31,6 +30,7 @@ import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@ -56,6 +56,7 @@ import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeRequestMsg; import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponseMsg; import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponseMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetOtaPackageResponseMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg; import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg;
import org.thingsboard.server.gen.transport.TransportProtos.SessionCloseNotificationProto; import org.thingsboard.server.gen.transport.TransportProtos.SessionCloseNotificationProto;
import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto;
@ -429,22 +430,17 @@ public class DeviceApiController implements TbTransportService {
.setDeviceIdMSB(sessionInfo.getDeviceIdMSB()) .setDeviceIdMSB(sessionInfo.getDeviceIdMSB())
.setDeviceIdLSB(sessionInfo.getDeviceIdLSB()) .setDeviceIdLSB(sessionInfo.getDeviceIdLSB())
.setType(firmwareType.name()).build(); .setType(firmwareType.name()).build();
transportContext.getTransportService().process(sessionInfo, requestMsg, new GetOtaPackageCallback(responseWriter, title, version, size, chunk)); transportContext.getTransportService().process(sessionInfo, requestMsg, new GetOtaPackageCallback(transportContext, responseWriter, title, version, size, chunk));
})); }));
return responseWriter; return responseWriter;
} }
private static class DeviceAuthCallback implements TransportServiceCallback<ValidateDeviceCredentialsResponse> { @RequiredArgsConstructor
static class DeviceAuthCallback implements TransportServiceCallback<ValidateDeviceCredentialsResponse> {
private final TransportContext transportContext; private final TransportContext transportContext;
private final DeferredResult<ResponseEntity> responseWriter; private final DeferredResult<ResponseEntity> responseWriter;
private final Consumer<SessionInfoProto> onSuccess; private final Consumer<SessionInfoProto> onSuccess;
DeviceAuthCallback(TransportContext transportContext, DeferredResult<ResponseEntity> responseWriter, Consumer<SessionInfoProto> onSuccess) {
this.transportContext = transportContext;
this.responseWriter = responseWriter;
this.onSuccess = onSuccess;
}
@Override @Override
public void onSuccess(ValidateDeviceCredentialsResponse msg) { public void onSuccess(ValidateDeviceCredentialsResponse msg) {
if (msg.hasDeviceInfo()) { if (msg.hasDeviceInfo()) {
@ -456,18 +452,21 @@ public class DeviceApiController implements TbTransportService {
@Override @Override
public void onError(Throwable e) { public void onError(Throwable e) {
log.warn("Failed to process request", e); String body = null;
responseWriter.setResult(new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR)); if (e instanceof HttpMessageNotReadableException || e instanceof JsonParseException) {
body = e.getMessage();
log.debug("Failed to process request in DeviceAuthCallback: {}", body);
} else {
log.warn("Failed to process request in DeviceAuthCallback", e);
}
responseWriter.setResult(new ResponseEntity<>(body, HttpStatus.INTERNAL_SERVER_ERROR));
} }
} }
private static class DeviceProvisionCallback implements TransportServiceCallback<ProvisionDeviceResponseMsg> { @RequiredArgsConstructor
static class DeviceProvisionCallback implements TransportServiceCallback<ProvisionDeviceResponseMsg> {
private final DeferredResult<ResponseEntity> responseWriter; private final DeferredResult<ResponseEntity> responseWriter;
DeviceProvisionCallback(DeferredResult<ResponseEntity> responseWriter) {
this.responseWriter = responseWriter;
}
@Override @Override
public void onSuccess(ProvisionDeviceResponseMsg msg) { public void onSuccess(ProvisionDeviceResponseMsg msg) {
responseWriter.setResult(new ResponseEntity<>(JsonConverter.toJson(msg).toString(), HttpStatus.OK)); responseWriter.setResult(new ResponseEntity<>(JsonConverter.toJson(msg).toString(), HttpStatus.OK));
@ -475,25 +474,25 @@ public class DeviceApiController implements TbTransportService {
@Override @Override
public void onError(Throwable e) { public void onError(Throwable e) {
log.warn("Failed to process request", e); String body = null;
responseWriter.setResult(new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR)); if (e instanceof HttpMessageNotReadableException || e instanceof JsonParseException) {
body = e.getMessage();
log.debug("Failed to process request in DeviceProvisionCallback: {}", body);
} else {
log.warn("Failed to process request in DeviceProvisionCallback", e);
}
responseWriter.setResult(new ResponseEntity<>(body, HttpStatus.INTERNAL_SERVER_ERROR));
} }
} }
private class GetOtaPackageCallback implements TransportServiceCallback<TransportProtos.GetOtaPackageResponseMsg> { @RequiredArgsConstructor
static class GetOtaPackageCallback implements TransportServiceCallback<GetOtaPackageResponseMsg> {
private final TransportContext transportContext;
private final DeferredResult<ResponseEntity> responseWriter; private final DeferredResult<ResponseEntity> responseWriter;
private final String title; private final String title;
private final String version; private final String version;
private final int chuckSize; private final int chunkSize;
private final int chuck; private final int chunk;
GetOtaPackageCallback(DeferredResult<ResponseEntity> responseWriter, String title, String version, int chuckSize, int chuck) {
this.responseWriter = responseWriter;
this.title = title;
this.version = version;
this.chuckSize = chuckSize;
this.chuck = chuck;
}
@Override @Override
public void onSuccess(TransportProtos.GetOtaPackageResponseMsg otaPackageResponseMsg) { public void onSuccess(TransportProtos.GetOtaPackageResponseMsg otaPackageResponseMsg) {
@ -501,7 +500,7 @@ public class DeviceApiController implements TbTransportService {
responseWriter.setResult(new ResponseEntity<>(HttpStatus.NOT_FOUND)); responseWriter.setResult(new ResponseEntity<>(HttpStatus.NOT_FOUND));
} else if (title.equals(otaPackageResponseMsg.getTitle()) && version.equals(otaPackageResponseMsg.getVersion())) { } else if (title.equals(otaPackageResponseMsg.getTitle()) && version.equals(otaPackageResponseMsg.getVersion())) {
String otaPackageId = new UUID(otaPackageResponseMsg.getOtaPackageIdMSB(), otaPackageResponseMsg.getOtaPackageIdLSB()).toString(); String otaPackageId = new UUID(otaPackageResponseMsg.getOtaPackageIdMSB(), otaPackageResponseMsg.getOtaPackageIdLSB()).toString();
ByteArrayResource resource = new ByteArrayResource(transportContext.getOtaPackageDataCache().get(otaPackageId, chuckSize, chuck)); ByteArrayResource resource = new ByteArrayResource(transportContext.getOtaPackageDataCache().get(otaPackageId, chunkSize, chunk));
ResponseEntity<ByteArrayResource> response = ResponseEntity.ok() ResponseEntity<ByteArrayResource> response = ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + otaPackageResponseMsg.getFileName()) .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + otaPackageResponseMsg.getFileName())
.header("x-filename", otaPackageResponseMsg.getFileName()) .header("x-filename", otaPackageResponseMsg.getFileName())
@ -516,8 +515,14 @@ public class DeviceApiController implements TbTransportService {
@Override @Override
public void onError(Throwable e) { public void onError(Throwable e) {
log.warn("Failed to process request", e); String body = null;
responseWriter.setResult(new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR)); if (e instanceof HttpMessageNotReadableException || e instanceof JsonParseException) {
body = e.getMessage();
log.debug("Failed to process request in GetOtaPackageCallback: {}", body);
} else {
log.warn("Failed to process request in GetOtaPackageCallback", e);
}
responseWriter.setResult(new ResponseEntity<>(body, HttpStatus.INTERNAL_SERVER_ERROR));
} }
} }

View File

@ -0,0 +1,82 @@
/**
* Copyright © 2016-2024 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.server.transport.http;
import com.google.gson.JsonParseException;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.context.request.async.DeferredResult;
import org.thingsboard.server.common.transport.TransportContext;
import org.thingsboard.server.gen.transport.TransportProtos;
import java.io.IOException;
import java.util.function.Consumer;
class DeviceApiControllerTest {
@Test
void deviceAuthCallbackTest() {
TransportContext transportContext = Mockito.mock(TransportContext.class);
DeferredResult<ResponseEntity> responseWriter = Mockito.mock(DeferredResult.class);
Consumer<TransportProtos.SessionInfoProto> onSuccess = x -> {
};
var callback = new DeviceApiController.DeviceAuthCallback(transportContext, responseWriter, onSuccess);
callback.onError(new HttpMessageNotReadableException("JSON incorrect syntax"));
callback.onError(new JsonParseException("Json ; expected"));
callback.onError(new IOException("not found"));
callback.onError(new RuntimeException("oops it is run time error"));
}
@Test
void deviceProvisionCallbackTest() {
DeferredResult<ResponseEntity> responseWriter = Mockito.mock(DeferredResult.class);
var callback = new DeviceApiController.DeviceProvisionCallback(responseWriter);
callback.onError(new HttpMessageNotReadableException("JSON incorrect syntax"));
callback.onError(new JsonParseException("Json ; expected"));
callback.onError(new IOException("not found"));
callback.onError(new RuntimeException("oops it is run time error"));
}
@Test
void getOtaPackageCallback() {
TransportContext transportContext = Mockito.mock(TransportContext.class);
DeferredResult<ResponseEntity> responseWriter = Mockito.mock(DeferredResult.class);
String title = "Title";
String version = "version";
int chunkSize = 11;
int chunk = 3;
var callback = new DeviceApiController.GetOtaPackageCallback(transportContext, responseWriter, title, version, chunkSize, chunk);
callback.onError(new HttpMessageNotReadableException("JSON incorrect syntax"));
callback.onError(new JsonParseException("Json ; expected"));
callback.onError(new IOException("not found"));
callback.onError(new RuntimeException("oops it is run time error"));
}
}

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{ISO8601} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
logger name="org.thingsboard.server.transport.http.DeviceApiController" level="DEBUG" />
<root level="INFO">
<appender-ref ref="console"/>
</root>
</configuration>