• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

FIWARE / contract-management / #102

30 Sep 2026 10:28AM UTC coverage: 4.485% (+0.7%) from 3.796%
#102

Pull #28

vramperez
Remove stack trace floods from connection errors

- Micronaut's DefaultHttpClient logged every failed connection at ERROR with a
  ~125 line stack trace, duplicating the one-line WARN of the failed call. It is
  off by default now (LOG_LEVEL_MICRONAUT_HTTP_CLIENT to bring it back)
- The subscription retry warning names the event and the reason instead of
  attaching the stack trace on every retry
- Suppress logback's status dump on startup

Without a reachable TM Forum API this reduces 25s of logs from ~1100 to ~60 lines.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Pull Request #28: Add failure reasons, downstream error descriptions and configurable log output

229 of 453 new or added lines in 31 files covered. (50.55%)

11 existing lines in 7 files now uncovered.

1608 of 35855 relevant lines covered (4.48%)

0.04 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

59.38
/src/main/java/org/fiware/iam/exception/CatchAllExceptionHandler.java
1
package org.fiware.iam.exception;
2

3
import io.micronaut.context.annotation.Requires;
4
import io.micronaut.http.HttpRequest;
5
import io.micronaut.http.HttpResponse;
6
import io.micronaut.http.HttpStatus;
7
import io.micronaut.http.annotation.Produces;
8
import io.micronaut.http.client.exceptions.HttpClientResponseException;
9
import io.micronaut.http.server.exceptions.ExceptionHandler;
10
import jakarta.inject.Singleton;
11
import lombok.extern.slf4j.Slf4j;
12
import org.fiware.iam.logging.DownstreamError;
13
import org.fiware.iam.tmforum.productorder.model.ErrorVO;
14

15
import java.time.format.DateTimeParseException;
16

17
/**
18
 * Handler to catch and log all exceptions and translate them into a proper error response.
19
 * <p>
20
 * Expected failures (known exception types, failed downstream calls) are logged as a single line with their
21
 * reason, only really unexpected ones are logged with their stack trace.
22
 */
23
@Produces
24
@Singleton
25
@Requires(classes = {Exception.class, ExceptionHandler.class})
26
@Slf4j
1 ✔
27
public class CatchAllExceptionHandler implements ExceptionHandler<Exception, HttpResponse<ErrorVO>> {
1 ✔
28

29
        @Override
30
        public HttpResponse<ErrorVO> handle(HttpRequest request, Exception exception) {
31
                if (exception instanceof DateTimeParseException dateTimeParseException) {
1 ✔
NEW
32
                        return respond(request, HttpStatus.BAD_REQUEST,
×
NEW
33
                                        "Request could not be answered due to an invalid date: %s.".formatted(dateTimeParseException.getParsedString()),
×
34
                                        exception);
35
                }
36
                if (exception instanceof TMForumException) {
1 ✔
37
                        return respond(request, HttpStatus.BAD_GATEWAY,
1 ✔
38
                                        "Request could not be answered due to error in downstream tmforum service: %s".formatted(DownstreamError.describe(exception)),
1 ✔
39
                                        exception);
40
                }
41
                if (exception instanceof TrustedIssuersException) {
1 ✔
NEW
42
                        return respond(request, HttpStatus.BAD_GATEWAY,
×
NEW
43
                                        "Request could not be answered due to error in downstream trusted issuers list service: %s".formatted(DownstreamError.describe(exception)),
×
44
                                        exception);
45
                }
46
                if (exception instanceof RainbowException) {
1 ✔
NEW
47
                        return respond(request, HttpStatus.BAD_GATEWAY,
×
NEW
48
                                        "Request could not be answered due to error in downstream rainbow service: %s".formatted(DownstreamError.describe(exception)),
×
49
                                        exception);
50
                }
51
                if (exception instanceof PapException) {
1 ✔
NEW
52
                        return respond(request, HttpStatus.BAD_GATEWAY,
×
NEW
53
                                        "Request could not be answered due to error in downstream odrl-pap service: %s".formatted(DownstreamError.describe(exception)),
×
54
                                        exception);
55
                }
56
                if (exception instanceof HttpClientResponseException) {
1 ✔
57
                        return respond(request, HttpStatus.BAD_GATEWAY,
1 ✔
58
                                        "Request could not be answered due to error in a downstream service: %s".formatted(DownstreamError.describe(exception)),
1 ✔
59
                                        exception);
60
                }
61
                if (exception instanceof IllegalArgumentException) {
1 ✔
62
                        return respond(request, HttpStatus.BAD_REQUEST, exception.getMessage(), exception);
1 ✔
63
                }
NEW
64
                log.error("Unexpected error while handling {} {}: {}", request.getMethod(), request.getUri(), DownstreamError.describe(exception), exception);
×
65
                return HttpResponse.status(HttpStatus.INTERNAL_SERVER_ERROR)
×
66
                                .body(new ErrorVO().status(HttpStatus.INTERNAL_SERVER_ERROR.toString())
×
67
                                                .reason(HttpStatus.INTERNAL_SERVER_ERROR.getReason())
×
68
                                                .message("Request could not be answered due to an unexpected internal error."));
×
69
        }
70

71
        private HttpResponse<ErrorVO> respond(HttpRequest<?> request, HttpStatus status, String message, Exception exception) {
72
                log.warn("Answered {} {} with {}: {}", request.getMethod(), request.getUri(), status.getCode(), DownstreamError.describe(exception));
1 ✔
73
                return HttpResponse.status(status)
1 ✔
74
                                .body(new ErrorVO().status(status.toString())
1 ✔
75
                                                .reason(status.getReason())
1 ✔
76
                                                .message(message));
1 ✔
77
        }
78
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc