Skip to content

Commit

Permalink
Merge pull request #218 from buerokratt/215-provide-error-details-in-…
Browse files Browse the repository at this point in the history
…logs-and-response

215 provide error details in logs and response
  • Loading branch information
RayDNoper authored Nov 28, 2023
2 parents e028ba4 + a6ba86f commit 7e5fd54
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 3 deletions.
11 changes: 11 additions & 0 deletions samples/CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,14 @@ These can be accessed only from IPs that are specified in `allowedIPs` configura
allowedIPs: ["127.0.0.1", "192.168.0.1", "172.21.0.1"]
allowedURLs: ["http://localhost/internalTest"]
```


### Meaningful errors

To help debugging different problems in Ruuter and other components some extra
logging can be turned on.
* `(application,)logging.meaningfulErrors` - boolean

If this value is set to `true`, a specified error message written to
error log and also sent as a response to request with relevant error code.

14 changes: 14 additions & 0 deletions src/main/java/ee/buerokratt/ruuter/controller/DslController.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import ee.buerokratt.ruuter.domain.DslInstance;
import ee.buerokratt.ruuter.domain.RuuterResponse;
import ee.buerokratt.ruuter.service.DslService;
import ee.buerokratt.ruuter.service.exception.StepExecutionException;
import ee.buerokratt.ruuter.util.LoggingUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -16,11 +17,13 @@
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;

import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Base64;

import java.util.Map;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -73,12 +76,23 @@ public ResponseEntity<Object> queryDsl(@RequestBody(required = false) Map<String
LoggingUtils.logError(log, errorMsg, request.getRemoteAddr(), INCOMING_REQUEST);
return status(HttpStatus.METHOD_NOT_ALLOWED).body(new RuuterResponse());
}

DslInstance di = dslService.execute(dsl, request.getMethod(), requestBody, requestQuery, requestHeaders, request.getRemoteAddr());

Object returnObj;
if (di.isReturnWithWrapper()) returnObj = new RuuterResponse(di.getReturnValue());
else returnObj = di.getReturnValue();

if (di.getProperties().getLogging().getMeaningfulErrors() && di.getErrorMessage() != null) {
String errorMsg = "DSL %s caught error: %s";
LoggingUtils.logError(log, errorMsg.formatted(dsl, di.getErrorMessage()), request.getRemoteAddr(), INCOMING_REQUEST);

if (di.getReturnValue() == null) {
returnObj = new HashMap<>() {{ put("error", di.getErrorMessage()); }};
}
di.setReturnStatus(di.getErrorStatus().value());
}

return status(di.getReturnStatus() == null ? getReturnStatus(di.getReturnValue()) : HttpStatus.valueOf(di.getReturnStatus()))
.headers(httpHeaders -> di.getReturnHeaders().forEach(httpHeaders::add))
.body(returnObj);
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/ee/buerokratt/ruuter/domain/DslInstance.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.http.HttpStatus;

import java.util.HashMap;
import java.util.List;
Expand Down Expand Up @@ -44,6 +45,9 @@ public class DslInstance {
private Map<String, Integer> recursions;
private boolean returnWithWrapper;

private String errorMessage;
private HttpStatus errorStatus;

public void execute() {
addGlobalIncomingHeadersToRequestHeaders();
List<String> stepNames = steps.keySet().stream().toList();
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/ee/buerokratt/ruuter/domain/Logging.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ public class Logging {

@JsonAlias("response")
private Boolean displayResponseContent;

private Boolean meaningfulErrors;
}
12 changes: 12 additions & 0 deletions src/main/java/ee/buerokratt/ruuter/domain/steps/DslStep.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.fasterxml.jackson.annotation.JsonAlias;
import ee.buerokratt.ruuter.domain.DslInstance;
import ee.buerokratt.ruuter.helper.exception.ScriptEvaluationException;
import ee.buerokratt.ruuter.service.exception.StepExecutionException;
import ee.buerokratt.ruuter.util.LoggingUtils;
import lombok.AllArgsConstructor;
Expand All @@ -10,6 +11,7 @@
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.http.HttpStatus;

@Slf4j
@Data
Expand Down Expand Up @@ -38,6 +40,10 @@ public final void execute(DslInstance di) {
executeStepAction(di);
}
logStep(System.currentTimeMillis() - startTime, di);
} catch (ScriptEvaluationException see) {
handleFailedResult(di);
di.setErrorMessage("ScriptingException: " + see.getMessage());
di.setErrorStatus(HttpStatus.INTERNAL_SERVER_ERROR);
} catch (Exception e) {
handleFailedResult(di);
if (di.getProperties().getStopInCaseOfException() != null && di.getProperties().getStopInCaseOfException()) {
Expand All @@ -51,6 +57,12 @@ public final void execute(DslInstance di) {

protected void handleFailedResult(DslInstance di) {
LoggingUtils.logError(log, "Error: %s".formatted(name), di.getRequestOrigin(), getType());

if (di.getProperties().getLogging().getMeaningfulErrors() != null &&
di.getProperties().getLogging().getMeaningfulErrors() &&
di.getErrorMessage() != null) {
LoggingUtils.logError(log, "Error: %s, message: ".formatted(name, di.getErrorMessage()), di.getRequestOrigin(), getType());
}
}

protected void logStep(Long elapsedTime, DslInstance di) {
Expand Down
24 changes: 22 additions & 2 deletions src/main/java/ee/buerokratt/ruuter/domain/steps/http/HttpStep.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,20 @@
import ee.buerokratt.ruuter.domain.Logging;
import ee.buerokratt.ruuter.helper.MappingHelper;
import ee.buerokratt.ruuter.util.LoggingUtils;
import io.netty.channel.ConnectTimeoutException;
import io.netty.handler.timeout.ReadTimeoutException;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.reactive.function.client.WebClientRequestException;
import org.springframework.web.reactive.function.client.WebClientResponseException;

import java.net.http.HttpTimeoutException;

@Slf4j
@Data
Expand Down Expand Up @@ -45,15 +52,28 @@ public abstract class HttpStep extends DslStep {
@Override
protected void executeStepAction(DslInstance di) {
args.checkUrl(di);
ResponseEntity<Object> response = getRequestResponse(di);
ResponseEntity<Object> response;
try {
response = getRequestResponse(di);
} catch (WebClientRequestException | WebClientResponseException wcre) {
di.setErrorMessage("Webclient error: "+wcre.getMessage());
if (wcre.getRootCause() instanceof ConnectTimeoutException)
di.setErrorStatus(HttpStatus.REQUEST_TIMEOUT);
else
di.setErrorStatus(HttpStatus.BAD_REQUEST);
throw wcre;
}
di.getContext().put(resultName, new HttpStepResult(args, response, MDC.get("spanId")));

if (!isAllowedHttpStatusCode(di, response.getStatusCodeValue())) {
if (getOnErrorStep() != null) {
setNextStepName(getOnErrorStep());
}
else
else {
di.setErrorStatus(response.getStatusCode());
di.setErrorMessage("HTTP returned with non-OK");
throw new IllegalArgumentException();
}
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ application:
logging:
displayRequestContent: false
displayResponseContent: false
meaningfulErrors: true
incomingRequests:
allowedMethodTypes: [ POST, GET ]
headers:
Expand All @@ -23,7 +24,7 @@ application:
CORS:
allowedOrigins: ["https://test.buerokratt.ee", "https://admin.test.buerokratt.ee/", "https://tim.test.buerokratt.ee/"]
DSL:
allowedFiletypes: [".yml", ".yaml", ".tmp"]
allowedFiletypes: [".yml", ".yaml", ".tmp", ".DS_Store"]
processedFiletypes: [".yml", ".yaml"]
allowDslReloading: true
internalRequests:
Expand Down

0 comments on commit 7e5fd54

Please sign in to comment.