From b0a73ee86a579c2ce981e87b287e41f7923e36d6 Mon Sep 17 00:00:00 2001 From: Simon Gurcke Date: Sat, 24 Jan 2026 17:56:59 +1000 Subject: [PATCH] Reformat code with Palantir Java Format --- pom.xml | 7 +- .../io/apitally/common/ApitallyClient.java | 188 ++++------ .../io/apitally/common/ConsumerRegistry.java | 4 +- .../java/io/apitally/common/InstanceLock.java | 17 +- .../io/apitally/common/RequestCounter.java | 35 +- .../io/apitally/common/RequestLogger.java | 173 ++++----- .../io/apitally/common/ResourceMonitor.java | 3 +- .../apitally/common/ServerErrorCounter.java | 60 ++- .../io/apitally/common/SpanCollector.java | 10 +- .../java/io/apitally/common/TempGzipFile.java | 3 +- .../common/ValidationErrorCounter.java | 51 ++- .../io/apitally/common/dto/ServerError.java | 7 +- .../io/apitally/common/dto/StartupData.java | 3 +- .../apitally/common/dto/ValidationError.java | 3 +- .../apitally/common/dto/ValidationErrors.java | 8 +- .../spring/ApitallyAutoConfiguration.java | 14 +- .../io/apitally/spring/ApitallyFilter.java | 97 ++--- .../apitally/spring/ApitallyProperties.java | 8 +- .../spring/ApitallySpanCollector.java | 6 +- .../io/apitally/spring/ApitallyUtils.java | 54 +-- .../apitally/common/ApitallyClientTest.java | 44 +-- .../io/apitally/common/InstanceLockTest.java | 14 +- .../io/apitally/common/RequestLoggerTest.java | 354 ++++++++---------- .../io/apitally/common/SpanCollectorTest.java | 21 +- .../apitally/spring/ApitallyFilterTest.java | 195 ++++------ .../apitally/spring/app/TestController.java | 12 +- .../java/io/apitally/spring/app/TestItem.java | 3 +- 27 files changed, 558 insertions(+), 836 deletions(-) diff --git a/pom.xml b/pom.xml index 4a4d474..86cd6a8 100644 --- a/pom.xml +++ b/pom.xml @@ -128,10 +128,9 @@ 3.2.0 - - 1.33.0 - - + + 2.85.0 + diff --git a/src/main/java/io/apitally/common/ApitallyClient.java b/src/main/java/io/apitally/common/ApitallyClient.java index 16b735e..7d1acdd 100644 --- a/src/main/java/io/apitally/common/ApitallyClient.java +++ b/src/main/java/io/apitally/common/ApitallyClient.java @@ -44,18 +44,16 @@ public enum HubRequestStatus { private static final int INITIAL_PERIOD_SECONDS = 3600; private static final int MAX_QUEUE_TIME_SECONDS = 3600; private static final int REQUEST_TIMEOUT_SECONDS = 10; - private static final String HUB_BASE_URL = - Optional.ofNullable(System.getenv("APITALLY_HUB_BASE_URL")) - .filter(s -> !s.trim().isEmpty()) - .orElse("https://hub.apitally.io"); + private static final String HUB_BASE_URL = Optional.ofNullable(System.getenv("APITALLY_HUB_BASE_URL")) + .filter(s -> !s.trim().isEmpty()) + .orElse("https://hub.apitally.io"); private static final Logger logger = LoggerFactory.getLogger(ApitallyClient.class); - private static final RetryTemplate retryTemplate = - RetryTemplate.builder() - .maxAttempts(3) - .exponentialBackoff(Duration.ofSeconds(1), 2, Duration.ofSeconds(4), true) - .retryOn(RetryableHubRequestException.class) - .build(); + private static final RetryTemplate retryTemplate = RetryTemplate.builder() + .maxAttempts(3) + .exponentialBackoff(Duration.ofSeconds(1), 2, Duration.ofSeconds(4), true) + .retryOn(RetryableHubRequestException.class) + .build(); private final String clientId; private final String env; @@ -87,9 +85,7 @@ public ApitallyClient(String clientId, String env, RequestLoggingConfig requestL this.requestCounter = new RequestCounter(); this.requestLogger = new RequestLogger(requestLoggingConfig); this.spanCollector = - new SpanCollector( - requestLoggingConfig.isEnabled() - && requestLoggingConfig.isTracingEnabled()); + new SpanCollector(requestLoggingConfig.isEnabled() && requestLoggingConfig.isTracingEnabled()); this.validationErrorCounter = new ValidationErrorCounter(); this.serverErrorCounter = new ServerErrorCounter(); this.consumerRegistry = new ConsumerRegistry(); @@ -128,36 +124,32 @@ private void sendStartupData() { if (startupData == null) { return; } - HttpRequest request = - HttpRequest.newBuilder() - .uri(getHubUrl("startup")) - .header("Content-Type", "application/json") - .POST(HttpRequest.BodyPublishers.ofString(startupData.toJSON())) - .build(); - sendHubRequest(request) - .thenAccept( - status -> { - if (status == HubRequestStatus.OK) { - startupDataSent = true; - startupData = null; - } else if (status == HubRequestStatus.VALIDATION_ERROR) { - startupDataSent = false; - startupData = null; - } else { - startupDataSent = false; - } - }); + HttpRequest request = HttpRequest.newBuilder() + .uri(getHubUrl("startup")) + .header("Content-Type", "application/json") + .POST(HttpRequest.BodyPublishers.ofString(startupData.toJSON())) + .build(); + sendHubRequest(request).thenAccept(status -> { + if (status == HubRequestStatus.OK) { + startupDataSent = true; + startupData = null; + } else if (status == HubRequestStatus.VALIDATION_ERROR) { + startupDataSent = false; + startupData = null; + } else { + startupDataSent = false; + } + }); } private void sendSyncData() { - SyncData data = - new SyncData( - instanceLock.getInstanceUuid(), - requestCounter.getAndResetRequests(), - validationErrorCounter.getAndResetValidationErrors(), - serverErrorCounter.getAndResetServerErrors(), - consumerRegistry.getAndResetConsumers(), - resourceMonitor.getCpuMemoryUsage()); + SyncData data = new SyncData( + instanceLock.getInstanceUuid(), + requestCounter.getAndResetRequests(), + validationErrorCounter.getAndResetValidationErrors(), + serverErrorCounter.getAndResetServerErrors(), + consumerRegistry.getAndResetConsumers(), + resourceMonitor.getCpuMemoryUsage()); syncDataQueue.offer(data); int i = 0; @@ -170,12 +162,11 @@ private void sendSyncData() { // Add random delay between retries Thread.sleep(100 + random.nextInt(400)); } - HttpRequest request = - HttpRequest.newBuilder() - .uri(getHubUrl("sync")) - .header("Content-Type", "application/json") - .POST(HttpRequest.BodyPublishers.ofString(payload.toJSON())) - .build(); + HttpRequest request = HttpRequest.newBuilder() + .uri(getHubUrl("sync")) + .header("Content-Type", "application/json") + .POST(HttpRequest.BodyPublishers.ofString(payload.toJSON())) + .build(); HubRequestStatus status = sendHubRequest(request).join(); if (status == HubRequestStatus.RETRYABLE_ERROR) { syncDataQueue.offer(payload); @@ -204,12 +195,11 @@ private void sendLogData() { } } try (InputStream inputStream = logFile.getInputStream()) { - HttpRequest request = - HttpRequest.newBuilder() - .uri(getHubUrl("log", "uuid=" + logFile.getUuid().toString())) - .header("Content-Type", "application/octet-stream") - .POST(HttpRequest.BodyPublishers.ofInputStream(() -> inputStream)) - .build(); + HttpRequest request = HttpRequest.newBuilder() + .uri(getHubUrl("log", "uuid=" + logFile.getUuid().toString())) + .header("Content-Type", "application/octet-stream") + .POST(HttpRequest.BodyPublishers.ofInputStream(() -> inputStream)) + .build(); HubRequestStatus status = sendHubRequest(request).join(); if (status == HubRequestStatus.PAYMENT_REQUIRED) { requestLogger.clear(); @@ -231,63 +221,47 @@ private void sendLogData() { } public CompletableFuture sendHubRequest(HttpRequest request) { - return CompletableFuture.supplyAsync( - () -> { + return CompletableFuture.supplyAsync(() -> { + try { + return retryTemplate.execute(context -> { try { - return retryTemplate.execute( - context -> { - try { - logger.debug( - "Sending request to Apitally hub: {}", - request.uri()); - HttpResponse response = - httpClient.send( - request, - HttpResponse.BodyHandlers.ofString()); - if (response.statusCode() >= 200 - && response.statusCode() < 300) { - return HubRequestStatus.OK; - } else if (response.statusCode() == 402) { - return HubRequestStatus.PAYMENT_REQUIRED; - } else if (response.statusCode() == 404) { - enabled = false; - stopSync(); - requestLogger.close(); - logger.error( - "Invalid Apitally client ID: {}", clientId); - return HubRequestStatus.INVALID_CLIENT_ID; - } else if (response.statusCode() == 422) { - logger.error( - "Received validation error from Apitally hub: {}", - response.body()); - return HubRequestStatus.VALIDATION_ERROR; - } else { - throw new RetryableHubRequestException( - "Hub request failed with status code " - + response.statusCode()); - } - } catch (Exception e) { - throw new RetryableHubRequestException( - "Hub request failed with exception: " - + e.getMessage()); - } - }); + logger.debug("Sending request to Apitally hub: {}", request.uri()); + HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); + if (response.statusCode() >= 200 && response.statusCode() < 300) { + return HubRequestStatus.OK; + } else if (response.statusCode() == 402) { + return HubRequestStatus.PAYMENT_REQUIRED; + } else if (response.statusCode() == 404) { + enabled = false; + stopSync(); + requestLogger.close(); + logger.error("Invalid Apitally client ID: {}", clientId); + return HubRequestStatus.INVALID_CLIENT_ID; + } else if (response.statusCode() == 422) { + logger.error("Received validation error from Apitally hub: {}", response.body()); + return HubRequestStatus.VALIDATION_ERROR; + } else { + throw new RetryableHubRequestException( + "Hub request failed with status code " + response.statusCode()); + } } catch (Exception e) { - logger.error("Error sending request to Apitally hub", e); - return HubRequestStatus.RETRYABLE_ERROR; + throw new RetryableHubRequestException("Hub request failed with exception: " + e.getMessage()); } }); + } catch (Exception e) { + logger.error("Error sending request to Apitally hub", e); + return HubRequestStatus.RETRYABLE_ERROR; + } + }); } public void startSync() { if (scheduler == null) { - scheduler = - Executors.newSingleThreadScheduledExecutor( - r -> { - Thread thread = new Thread(r, "apitally-sync"); - thread.setDaemon(true); - return thread; - }); + scheduler = Executors.newSingleThreadScheduledExecutor(r -> { + Thread thread = new Thread(r, "apitally-sync"); + thread.setDaemon(true); + return thread; + }); } if (syncTask != null) { @@ -295,20 +269,14 @@ public void startSync() { } // Start with shorter initial sync interval - syncTask = - scheduler.scheduleAtFixedRate( - this::sync, 0, INITIAL_SYNC_INTERVAL_SECONDS, TimeUnit.SECONDS); + syncTask = scheduler.scheduleAtFixedRate(this::sync, 0, INITIAL_SYNC_INTERVAL_SECONDS, TimeUnit.SECONDS); // Schedule a one-time task to switch to regular sync interval scheduler.schedule( () -> { syncTask.cancel(false); - syncTask = - scheduler.scheduleAtFixedRate( - this::sync, - SYNC_INTERVAL_SECONDS, - SYNC_INTERVAL_SECONDS, - TimeUnit.SECONDS); + syncTask = scheduler.scheduleAtFixedRate( + this::sync, SYNC_INTERVAL_SECONDS, SYNC_INTERVAL_SECONDS, TimeUnit.SECONDS); }, INITIAL_PERIOD_SECONDS, TimeUnit.SECONDS); diff --git a/src/main/java/io/apitally/common/ConsumerRegistry.java b/src/main/java/io/apitally/common/ConsumerRegistry.java index 1c66360..1eb90da 100644 --- a/src/main/java/io/apitally/common/ConsumerRegistry.java +++ b/src/main/java/io/apitally/common/ConsumerRegistry.java @@ -56,9 +56,7 @@ public void addOrUpdateConsumer(Consumer consumer) { } if (hasChanges) { - consumers.put( - consumer.getIdentifier(), - new Consumer(consumer.getIdentifier(), newName, newGroup)); + consumers.put(consumer.getIdentifier(), new Consumer(consumer.getIdentifier(), newName, newGroup)); updated.add(consumer.getIdentifier()); } } diff --git a/src/main/java/io/apitally/common/InstanceLock.java b/src/main/java/io/apitally/common/InstanceLock.java index 144459f..05f2a89 100644 --- a/src/main/java/io/apitally/common/InstanceLock.java +++ b/src/main/java/io/apitally/common/InstanceLock.java @@ -55,12 +55,8 @@ static InstanceLock create(String clientId, String env, Path lockDir) { Path lockPath = lockDir.resolve("instance_" + appEnvHash + "_" + slot + ".lock"); FileChannel channel = null; try { - channel = - FileChannel.open( - lockPath, - StandardOpenOption.CREATE, - StandardOpenOption.READ, - StandardOpenOption.WRITE); + channel = FileChannel.open( + lockPath, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE); FileLock lock = channel.tryLock(); if (lock == null) { @@ -69,9 +65,9 @@ static InstanceLock create(String clientId, String env, Path lockDir) { } FileTime lastModified = Files.getLastModifiedTime(lockPath); - boolean tooOld = - Duration.between(lastModified.toInstant(), Instant.now()).getSeconds() - > MAX_LOCK_AGE_SECONDS; + boolean tooOld = Duration.between(lastModified.toInstant(), Instant.now()) + .getSeconds() + > MAX_LOCK_AGE_SECONDS; String existingUuid = readChannel(channel); UUID uuid = parseUuid(existingUuid); @@ -120,8 +116,7 @@ private static UUID parseUuid(String s) { } } - private static String getAppEnvHash(String clientId, String env) - throws NoSuchAlgorithmException { + private static String getAppEnvHash(String clientId, String env) throws NoSuchAlgorithmException { MessageDigest digest = MessageDigest.getInstance("SHA-256"); byte[] hash = digest.digest((clientId + ":" + env).getBytes(StandardCharsets.UTF_8)); return HexFormat.of().formatHex(hash, 0, 4); diff --git a/src/main/java/io/apitally/common/RequestCounter.java b/src/main/java/io/apitally/common/RequestCounter.java index 3656c6b..81fad58 100644 --- a/src/main/java/io/apitally/common/RequestCounter.java +++ b/src/main/java/io/apitally/common/RequestCounter.java @@ -31,8 +31,7 @@ public void addRequest( long responseTime, long requestSize, long responseSize) { - String key = - String.join("|", consumer, method.toUpperCase(), path, String.valueOf(statusCode)); + String key = String.join("|", consumer, method.toUpperCase(), path, String.valueOf(statusCode)); // Increment request count requestCounts.merge(key, 1, Integer::sum); @@ -73,25 +72,21 @@ public List getAndResetRequests() { String path = parts[2]; int statusCode = Integer.parseInt(parts[3]); - Map responseTimeMap = - responseTimes.getOrDefault(key, new ConcurrentHashMap<>()); - Map requestSizeMap = - requestSizes.getOrDefault(key, new ConcurrentHashMap<>()); - Map responseSizeMap = - responseSizes.getOrDefault(key, new ConcurrentHashMap<>()); + Map responseTimeMap = responseTimes.getOrDefault(key, new ConcurrentHashMap<>()); + Map requestSizeMap = requestSizes.getOrDefault(key, new ConcurrentHashMap<>()); + Map responseSizeMap = responseSizes.getOrDefault(key, new ConcurrentHashMap<>()); - Requests item = - new Requests( - consumer, - method, - path, - statusCode, - entry.getValue(), - requestSizeSums.getOrDefault(key, 0L), - responseSizeSums.getOrDefault(key, 0L), - responseTimeMap, - requestSizeMap, - responseSizeMap); + Requests item = new Requests( + consumer, + method, + path, + statusCode, + entry.getValue(), + requestSizeSums.getOrDefault(key, 0L), + responseSizeSums.getOrDefault(key, 0L), + responseTimeMap, + requestSizeMap, + responseSizeMap); data.add(item); } diff --git a/src/main/java/io/apitally/common/RequestLogger.java b/src/main/java/io/apitally/common/RequestLogger.java index 1d92819..c415ec3 100644 --- a/src/main/java/io/apitally/common/RequestLogger.java +++ b/src/main/java/io/apitally/common/RequestLogger.java @@ -36,44 +36,35 @@ public class RequestLogger { private static final int MAX_FILE_SIZE = 1_000_000; // 1 MB (compressed) private static final int MAX_FILES = 50; private static final int MAX_PENDING_WRITES = 100; - private static final byte[] BODY_TOO_LARGE = - "".getBytes(StandardCharsets.UTF_8); + private static final byte[] BODY_TOO_LARGE = "".getBytes(StandardCharsets.UTF_8); private static final byte[] BODY_MASKED = "".getBytes(StandardCharsets.UTF_8); private static final String MASKED = "******"; - public static final List ALLOWED_CONTENT_TYPES = - Arrays.asList("application/json", "text/plain"); - private static final Pattern JSON_CONTENT_TYPE_PATTERN = - Pattern.compile("\\bjson\\b", Pattern.CASE_INSENSITIVE); - private static final List EXCLUDE_PATH_PATTERNS = - Arrays.asList( - "/_?healthz?$", - "/_?health[_-]?checks?$", - "/_?heart[_-]?beats?$", - "/ping$", - "/ready$", - "/live$", - "/favicon(?:-[\\w-]+)?\\.(ico|png|svg)$", - "/apple-touch-icon(?:-[\\w-]+)?\\.png$", - "/robots\\.txt$", - "/sitemap\\.xml$", - "/manifest\\.json$", - "/site\\.webmanifest$", - "/service-worker\\.js$", - "/sw\\.js$", - "/\\.well-known/"); + public static final List ALLOWED_CONTENT_TYPES = Arrays.asList("application/json", "text/plain"); + private static final Pattern JSON_CONTENT_TYPE_PATTERN = Pattern.compile("\\bjson\\b", Pattern.CASE_INSENSITIVE); + private static final List EXCLUDE_PATH_PATTERNS = Arrays.asList( + "/_?healthz?$", + "/_?health[_-]?checks?$", + "/_?heart[_-]?beats?$", + "/ping$", + "/ready$", + "/live$", + "/favicon(?:-[\\w-]+)?\\.(ico|png|svg)$", + "/apple-touch-icon(?:-[\\w-]+)?\\.png$", + "/robots\\.txt$", + "/sitemap\\.xml$", + "/manifest\\.json$", + "/site\\.webmanifest$", + "/service-worker\\.js$", + "/sw\\.js$", + "/\\.well-known/"); private static final List EXCLUDE_USER_AGENT_PATTERNS = - Arrays.asList( - "health[-_ ]?check", - "microsoft-azure-application-lb", - "googlehc", - "kube-probe"); + Arrays.asList("health[-_ ]?check", "microsoft-azure-application-lb", "googlehc", "kube-probe"); private static final List MASK_QUERY_PARAM_PATTERNS = Arrays.asList("auth", "api-?key", "secret", "token", "password", "pwd"); private static final List MASK_HEADER_PATTERNS = Arrays.asList("auth", "api-?key", "secret", "token", "cookie"); private static final List MASK_BODY_FIELD_PATTERNS = - Arrays.asList( - "password", "pwd", "token", "secret", "auth", "card[-_ ]?number", "ccv", "ssn"); + Arrays.asList("password", "pwd", "token", "secret", "auth", "card[-_ ]?number", "ccv", "ssn"); private static final int MAINTAIN_INTERVAL_SECONDS = 1; private final RequestLoggingConfig config; @@ -101,13 +92,11 @@ public RequestLogger(RequestLoggingConfig config) { this.files = new ConcurrentLinkedDeque<>(); this.enabled = config.isEnabled(); - this.compiledPathExcludePatterns = - compilePatterns(EXCLUDE_PATH_PATTERNS, config.getPathExcludePatterns()); + this.compiledPathExcludePatterns = compilePatterns(EXCLUDE_PATH_PATTERNS, config.getPathExcludePatterns()); this.compiledUserAgentExcludePatterns = compilePatterns(EXCLUDE_USER_AGENT_PATTERNS, null); this.compiledQueryParamMaskPatterns = compilePatterns(MASK_QUERY_PARAM_PATTERNS, config.getQueryParamMaskPatterns()); - this.compiledHeaderMaskPatterns = - compilePatterns(MASK_HEADER_PATTERNS, config.getHeaderMaskPatterns()); + this.compiledHeaderMaskPatterns = compilePatterns(MASK_HEADER_PATTERNS, config.getHeaderMaskPatterns()); this.compiledBodyFieldMaskPatterns = compilePatterns(MASK_BODY_FIELD_PATTERNS, config.getBodyFieldMaskPatterns()); @@ -116,8 +105,7 @@ public RequestLogger(RequestLoggingConfig config) { } } - private static List compilePatterns( - List defaultPatterns, List additionalPatterns) { + private static List compilePatterns(List defaultPatterns, List additionalPatterns) { List patterns = new ArrayList<>(defaultPatterns); if (additionalPatterns != null) { patterns.addAll(additionalPatterns); @@ -163,16 +151,14 @@ public void logRequest( if (shouldExcludePath(path) || shouldExcludeUserAgent(userAgent)) { return; } - if (config.getCallbacks() != null - && config.getCallbacks().shouldExclude(request, response)) { + if (config.getCallbacks() != null && config.getCallbacks().shouldExclude(request, response)) { return; } if (!config.isRequestBodyIncluded() || !hasSupportedContentType(request.getHeaders())) { request.setBody(null); } - if (!config.isResponseBodyIncluded() - || !hasSupportedContentType(response.getHeaders())) { + if (!config.isResponseBodyIncluded() || !hasSupportedContentType(response.getHeaders())) { response.setBody(null); } @@ -190,8 +176,7 @@ public void logRequest( traceId = null; } - RequestLogItem item = - new RequestLogItem(request, response, exceptionDto, logs, spans, traceId); + RequestLogItem item = new RequestLogItem(request, response, exceptionDto, logs, spans, traceId); pendingWrites.add(item); if (pendingWrites.size() > MAX_PENDING_WRITES) { @@ -264,13 +249,12 @@ && hasJsonContentType(response.getHeaders())) { } else if (query != null) { query = maskQueryParams(query); } - request.setUrl( - new java.net.URL( - url.getProtocol(), - url.getHost(), - url.getPort(), - url.getPath() + (query != null ? "?" + query : "")) - .toString()); + request.setUrl(new java.net.URL( + url.getProtocol(), + url.getHost(), + url.getPort(), + url.getPath() + (query != null ? "?" + query : "")) + .toString()); } catch (MalformedURLException e) { // Keep original URL if malformed } @@ -292,10 +276,8 @@ public void writeToFile() throws IOException { ObjectNode itemNode = objectMapper.createObjectNode(); itemNode.put("uuid", item.getUuid()); - itemNode.set( - "request", skipEmptyValues(objectMapper.valueToTree(item.getRequest()))); - itemNode.set( - "response", skipEmptyValues(objectMapper.valueToTree(item.getResponse()))); + itemNode.set("request", skipEmptyValues(objectMapper.valueToTree(item.getRequest()))); + itemNode.set("response", skipEmptyValues(objectMapper.valueToTree(item.getResponse()))); if (item.getException() != null) { itemNode.set("exception", objectMapper.valueToTree(item.getException())); } @@ -375,17 +357,13 @@ public void close() { private void startMaintenance() { if (scheduler == null) { - scheduler = - Executors.newSingleThreadScheduledExecutor( - r -> { - Thread thread = new Thread(r, "apitally-request-logger"); - thread.setDaemon(true); - return thread; - }); + scheduler = Executors.newSingleThreadScheduledExecutor(r -> { + Thread thread = new Thread(r, "apitally-request-logger"); + thread.setDaemon(true); + return thread; + }); } - maintainTask = - scheduler.scheduleAtFixedRate( - this::maintain, 0, MAINTAIN_INTERVAL_SECONDS, TimeUnit.SECONDS); + maintainTask = scheduler.scheduleAtFixedRate(this::maintain, 0, MAINTAIN_INTERVAL_SECONDS, TimeUnit.SECONDS); } private void stopMaintenance() { @@ -410,7 +388,8 @@ private boolean shouldExcludePath(String path) { if (path == null || path.isEmpty()) { return false; } - return compiledPathExcludePatterns.stream().anyMatch(p -> p.matcher(path).find()); + return compiledPathExcludePatterns.stream() + .anyMatch(p -> p.matcher(path).find()); } private boolean shouldExcludeUserAgent(String userAgent) { @@ -421,7 +400,8 @@ private boolean shouldExcludeUserAgent(String userAgent) { } private boolean shouldMaskQueryParam(String name) { - return compiledQueryParamMaskPatterns.stream().anyMatch(p -> p.matcher(name).find()); + return compiledQueryParamMaskPatterns.stream() + .anyMatch(p -> p.matcher(name).find()); } private boolean shouldMaskHeader(String name) { @@ -429,7 +409,8 @@ private boolean shouldMaskHeader(String name) { } private boolean shouldMaskBodyField(String name) { - return compiledBodyFieldMaskPatterns.stream().anyMatch(p -> p.matcher(name).find()); + return compiledBodyFieldMaskPatterns.stream() + .anyMatch(p -> p.matcher(name).find()); } private String maskQueryParams(String query) { @@ -453,13 +434,8 @@ private String maskQueryParams(String query) { private List
maskHeaders(Header[] headers) { return Arrays.stream(headers) - .map( - header -> - new Header( - header.getName(), - shouldMaskHeader(header.getName()) - ? MASKED - : header.getValue())) + .map(header -> + new Header(header.getName(), shouldMaskHeader(header.getName()) ? MASKED : header.getValue())) .collect(Collectors.toList()); } @@ -477,17 +453,13 @@ private byte[] maskJsonBody(byte[] body) { private void maskJsonNode(JsonNode node) { if (node.isObject()) { ObjectNode objectNode = (ObjectNode) node; - objectNode - .fields() - .forEachRemaining( - entry -> { - if (entry.getValue().isTextual() - && shouldMaskBodyField(entry.getKey())) { - objectNode.put(entry.getKey(), MASKED); - } else { - maskJsonNode(entry.getValue()); - } - }); + objectNode.fields().forEachRemaining(entry -> { + if (entry.getValue().isTextual() && shouldMaskBodyField(entry.getKey())) { + objectNode.put(entry.getKey(), MASKED); + } else { + maskJsonNode(entry.getValue()); + } + }); } else if (node.isArray()) { node.forEach(this::maskJsonNode); } @@ -495,13 +467,13 @@ && shouldMaskBodyField(entry.getKey())) { private boolean hasSupportedContentType(Header[] headers) { String contentType = findHeader(headers, "content-type"); - return contentType != null - && ALLOWED_CONTENT_TYPES.stream().anyMatch(contentType::startsWith); + return contentType != null && ALLOWED_CONTENT_TYPES.stream().anyMatch(contentType::startsWith); } private boolean hasJsonContentType(Header[] headers) { String contentType = findHeader(headers, "content-type"); - return contentType != null && JSON_CONTENT_TYPE_PATTERN.matcher(contentType).find(); + return contentType != null + && JSON_CONTENT_TYPE_PATTERN.matcher(contentType).find(); } private String findHeader(Header[] headers, String name) { @@ -514,21 +486,18 @@ private String findHeader(Header[] headers, String name) { private ObjectNode skipEmptyValues(ObjectNode node) { ObjectNode result = objectMapper.createObjectNode(); - node.fields() - .forEachRemaining( - entry -> { - if (entry.getValue().isNull()) { - return; - } - if (entry.getValue().isArray() && entry.getValue().size() == 0) { - return; - } - if (entry.getValue().isTextual() - && entry.getValue().asText().isEmpty()) { - return; - } - result.set(entry.getKey(), entry.getValue()); - }); + node.fields().forEachRemaining(entry -> { + if (entry.getValue().isNull()) { + return; + } + if (entry.getValue().isArray() && entry.getValue().size() == 0) { + return; + } + if (entry.getValue().isTextual() && entry.getValue().asText().isEmpty()) { + return; + } + result.set(entry.getKey(), entry.getValue()); + }); return result; } } diff --git a/src/main/java/io/apitally/common/ResourceMonitor.java b/src/main/java/io/apitally/common/ResourceMonitor.java index 0cec7a0..7f812c6 100644 --- a/src/main/java/io/apitally/common/ResourceMonitor.java +++ b/src/main/java/io/apitally/common/ResourceMonitor.java @@ -21,8 +21,7 @@ public ResourceUsage getCpuMemoryUsage() { return null; } - double cpuPercent = - 100.0 * currentProcess.getProcessCpuLoadBetweenTicks(previousSnapshot); + double cpuPercent = 100.0 * currentProcess.getProcessCpuLoadBetweenTicks(previousSnapshot); long memoryRss = currentProcess.getResidentSetSize(); previousSnapshot = currentProcess; diff --git a/src/main/java/io/apitally/common/ServerErrorCounter.java b/src/main/java/io/apitally/common/ServerErrorCounter.java index 04fcd6a..2006087 100644 --- a/src/main/java/io/apitally/common/ServerErrorCounter.java +++ b/src/main/java/io/apitally/common/ServerErrorCounter.java @@ -20,14 +20,13 @@ public ServerErrorCounter() { } public void addServerError(String consumer, String method, String path, Exception exception) { - ServerError error = - new ServerError( - consumer, - method, - path, - exception.getClass().getSimpleName(), - exception.getMessage(), - exception.getStackTrace()); + ServerError error = new ServerError( + consumer, + method, + path, + exception.getClass().getSimpleName(), + exception.getMessage(), + exception.getStackTrace()); String key = getKey(error); errorDetails.putIfAbsent(key, error); errorCounts.merge(key, 1, Integer::sum); @@ -35,36 +34,33 @@ public void addServerError(String consumer, String method, String path, Exceptio public List getAndResetServerErrors() { List data = new ArrayList<>(); - errorCounts.forEach( - (key, count) -> { - ServerError error = errorDetails.get(key); - if (error != null) { - data.add( - new ServerErrors( - error.getConsumer(), - error.getMethod(), - error.getPath(), - error.getType(), - error.getMessage(), - error.getStackTrace(), - count)); - } - }); + errorCounts.forEach((key, count) -> { + ServerError error = errorDetails.get(key); + if (error != null) { + data.add(new ServerErrors( + error.getConsumer(), + error.getMethod(), + error.getPath(), + error.getType(), + error.getMessage(), + error.getStackTrace(), + count)); + } + }); errorCounts.clear(); errorDetails.clear(); return data; } private String getKey(ServerError error) { - String hashInput = - String.join( - "|", - error.getConsumer() != null ? error.getConsumer() : "", - error.getMethod(), - error.getPath(), - error.getType(), - error.getMessage(), - error.getStackTraceString()); + String hashInput = String.join( + "|", + error.getConsumer() != null ? error.getConsumer() : "", + error.getMethod(), + error.getPath(), + error.getType(), + error.getMessage(), + error.getStackTraceString()); try { MessageDigest md = MessageDigest.getInstance("MD5"); byte[] digest = md.digest(hashInput.getBytes()); diff --git a/src/main/java/io/apitally/common/SpanCollector.java b/src/main/java/io/apitally/common/SpanCollector.java index 01a562f..af0dd21 100644 --- a/src/main/java/io/apitally/common/SpanCollector.java +++ b/src/main/java/io/apitally/common/SpanCollector.java @@ -23,8 +23,7 @@ public class SpanCollector implements SpanProcessor { private final boolean enabled; private volatile Tracer tracer; private final Map> includedSpanIds = new ConcurrentHashMap<>(); - private final Map> collectedSpans = - new ConcurrentHashMap<>(); + private final Map> collectedSpans = new ConcurrentHashMap<>(); public SpanCollector(boolean enabled) { this.enabled = enabled; @@ -121,10 +120,9 @@ private SpanData serializeSpan(ReadableSpan span) { SpanContext parentSpanContext = spanData.getParentSpanContext(); String parentSpanId = parentSpanContext.isValid() ? parentSpanContext.getSpanId() : null; - String status = - spanData.getStatus().getStatusCode() != StatusCode.UNSET - ? spanData.getStatus().getStatusCode().name() - : null; + String status = spanData.getStatus().getStatusCode() != StatusCode.UNSET + ? spanData.getStatus().getStatusCode().name() + : null; Map attributes = null; if (!spanData.getAttributes().isEmpty()) { diff --git a/src/main/java/io/apitally/common/TempGzipFile.java b/src/main/java/io/apitally/common/TempGzipFile.java index 3385604..38fbf34 100644 --- a/src/main/java/io/apitally/common/TempGzipFile.java +++ b/src/main/java/io/apitally/common/TempGzipFile.java @@ -75,8 +75,7 @@ public InputStream getInputStream() throws IOException { public List readDecompressedLines() throws IOException { try (InputStream inputStream = getInputStream(); GZIPInputStream gzipInputStream = new GZIPInputStream(inputStream); - BufferedReader reader = - new BufferedReader(new InputStreamReader(gzipInputStream))) { + BufferedReader reader = new BufferedReader(new InputStreamReader(gzipInputStream))) { return reader.lines().collect(Collectors.toList()); } } diff --git a/src/main/java/io/apitally/common/ValidationErrorCounter.java b/src/main/java/io/apitally/common/ValidationErrorCounter.java index a29f16c..fab0632 100644 --- a/src/main/java/io/apitally/common/ValidationErrorCounter.java +++ b/src/main/java/io/apitally/common/ValidationErrorCounter.java @@ -19,10 +19,8 @@ public ValidationErrorCounter() { this.errorDetails = new ConcurrentHashMap<>(); } - public void addValidationError( - String consumer, String method, String path, String loc, String msg, String type) { - ValidationError validationError = - new ValidationError(consumer, method, path, loc, msg, type); + public void addValidationError(String consumer, String method, String path, String loc, String msg, String type) { + ValidationError validationError = new ValidationError(consumer, method, path, loc, msg, type); String key = getKey(validationError); errorDetails.putIfAbsent(key, validationError); errorCounts.merge(key, 1, Integer::sum); @@ -30,36 +28,33 @@ public void addValidationError( public List getAndResetValidationErrors() { List data = new ArrayList<>(); - errorCounts.forEach( - (key, count) -> { - ValidationError error = errorDetails.get(key); - if (error != null) { - data.add( - new ValidationErrors( - error.getConsumer(), - error.getMethod(), - error.getPath(), - error.getLoc(), - error.getMsg(), - error.getType(), - count)); - } - }); + errorCounts.forEach((key, count) -> { + ValidationError error = errorDetails.get(key); + if (error != null) { + data.add(new ValidationErrors( + error.getConsumer(), + error.getMethod(), + error.getPath(), + error.getLoc(), + error.getMsg(), + error.getType(), + count)); + } + }); errorCounts.clear(); errorDetails.clear(); return data; } private String getKey(ValidationError error) { - String hashInput = - String.join( - "|", - error.getConsumer() != null ? error.getConsumer() : "", - error.getMethod().toUpperCase(), - error.getPath(), - String.join(".", error.getLoc()), - error.getMsg().trim(), - error.getType()); + String hashInput = String.join( + "|", + error.getConsumer() != null ? error.getConsumer() : "", + error.getMethod().toUpperCase(), + error.getPath(), + String.join(".", error.getLoc()), + error.getMsg().trim(), + error.getType()); try { MessageDigest md = MessageDigest.getInstance("MD5"); byte[] digest = md.digest(hashInput.getBytes()); diff --git a/src/main/java/io/apitally/common/dto/ServerError.java b/src/main/java/io/apitally/common/dto/ServerError.java index 86d8201..5cd1964 100644 --- a/src/main/java/io/apitally/common/dto/ServerError.java +++ b/src/main/java/io/apitally/common/dto/ServerError.java @@ -18,12 +18,7 @@ public class ServerError { private final String stackTraceString; public ServerError( - String consumer, - String method, - String path, - String type, - String message, - StackTraceElement[] stackTrace) { + String consumer, String method, String path, String type, String message, StackTraceElement[] stackTrace) { this.consumer = consumer; this.method = method; this.path = path; diff --git a/src/main/java/io/apitally/common/dto/StartupData.java b/src/main/java/io/apitally/common/dto/StartupData.java index a094130..6710dcd 100644 --- a/src/main/java/io/apitally/common/dto/StartupData.java +++ b/src/main/java/io/apitally/common/dto/StartupData.java @@ -12,8 +12,7 @@ public class StartupData extends BaseDto { private final Map versions; private final String client; - public StartupData( - UUID instanceUuid, List paths, Map versions, String client) { + public StartupData(UUID instanceUuid, List paths, Map versions, String client) { this.instanceUuid = instanceUuid; this.messageUuid = UUID.randomUUID(); this.paths = paths; diff --git a/src/main/java/io/apitally/common/dto/ValidationError.java b/src/main/java/io/apitally/common/dto/ValidationError.java index 0de8de0..c95ad69 100644 --- a/src/main/java/io/apitally/common/dto/ValidationError.java +++ b/src/main/java/io/apitally/common/dto/ValidationError.java @@ -11,8 +11,7 @@ public class ValidationError extends BaseDto { private final String msg; private final String type; - public ValidationError( - String consumer, String method, String path, String loc, String msg, String type) { + public ValidationError(String consumer, String method, String path, String loc, String msg, String type) { this.consumer = consumer; this.method = method; this.path = path; diff --git a/src/main/java/io/apitally/common/dto/ValidationErrors.java b/src/main/java/io/apitally/common/dto/ValidationErrors.java index 48052b7..666efca 100644 --- a/src/main/java/io/apitally/common/dto/ValidationErrors.java +++ b/src/main/java/io/apitally/common/dto/ValidationErrors.java @@ -6,13 +6,7 @@ public class ValidationErrors extends ValidationError { private final int errorCount; public ValidationErrors( - String consumer, - String method, - String path, - String loc, - String msg, - String type, - int errorCount) { + String consumer, String method, String path, String loc, String msg, String type, int errorCount) { super(consumer, method, path, loc, msg, type); this.errorCount = errorCount; } diff --git a/src/main/java/io/apitally/spring/ApitallyAutoConfiguration.java b/src/main/java/io/apitally/spring/ApitallyAutoConfiguration.java index 93c84a7..b9eff9a 100644 --- a/src/main/java/io/apitally/spring/ApitallyAutoConfiguration.java +++ b/src/main/java/io/apitally/spring/ApitallyAutoConfiguration.java @@ -17,13 +17,9 @@ public class ApitallyAutoConfiguration { @Bean public ApitallyClient apitallyClient( - ApitallyProperties properties, - RequestMappingHandlerMapping requestMappingHandlerMapping) { + ApitallyProperties properties, RequestMappingHandlerMapping requestMappingHandlerMapping) { ApitallyClient client = - new ApitallyClient( - properties.getClientId(), - properties.getEnv(), - properties.getRequestLogging()); + new ApitallyClient(properties.getClientId(), properties.getEnv(), properties.getRequestLogging()); List paths = ApitallyUtils.getPaths(requestMappingHandlerMapping); Map versions = ApitallyUtils.getVersions(); client.setStartupData(paths, versions, "java:spring"); @@ -42,10 +38,8 @@ public ApitallyClient apitallyClient( } @Bean - public FilterRegistrationBean apitallyFilterRegistration( - ApitallyClient apitallyClient) { - final FilterRegistrationBean registrationBean = - new FilterRegistrationBean<>(); + public FilterRegistrationBean apitallyFilterRegistration(ApitallyClient apitallyClient) { + final FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new ApitallyFilter(apitallyClient)); registrationBean.setOrder(Ordered.LOWEST_PRECEDENCE - 10); return registrationBean; diff --git a/src/main/java/io/apitally/spring/ApitallyFilter.java b/src/main/java/io/apitally/spring/ApitallyFilter.java index dd04a42..5c1b860 100644 --- a/src/main/java/io/apitally/spring/ApitallyFilter.java +++ b/src/main/java/io/apitally/spring/ApitallyFilter.java @@ -59,16 +59,12 @@ protected void doFilterInternal( final boolean requestLoggingEnabled = requestLoggingConfig.isEnabled(); String requestContentType = request.getContentType(); - final boolean shouldCacheRequest = - requestLoggingEnabled - && requestLoggingConfig.isRequestBodyIncluded() - && requestContentType != null - && RequestLogger.ALLOWED_CONTENT_TYPES.stream() - .anyMatch( - allowedContentType -> - requestContentType.startsWith(allowedContentType)); - final boolean shouldCacheResponse = - requestLoggingEnabled && requestLoggingConfig.isResponseBodyIncluded(); + final boolean shouldCacheRequest = requestLoggingEnabled + && requestLoggingConfig.isRequestBodyIncluded() + && requestContentType != null + && RequestLogger.ALLOWED_CONTENT_TYPES.stream() + .anyMatch(allowedContentType -> requestContentType.startsWith(allowedContentType)); + final boolean shouldCacheResponse = requestLoggingEnabled && requestLoggingConfig.isResponseBodyIncluded(); ContentCachingRequestWrapper cachingRequest = shouldCacheRequest ? new ContentCachingRequestWrapper(request) : null; ContentCachingResponseWrapper cachingResponse = @@ -76,10 +72,8 @@ protected void doFilterInternal( CountingResponseWrapper countingResponse = cachingResponse == null ? new CountingResponseWrapper(response) : null; - final boolean shouldCaptureLogs = - requestLoggingEnabled && requestLoggingConfig.isLogCaptureEnabled(); - final boolean shouldCaptureSpans = - requestLoggingEnabled && requestLoggingConfig.isTracingEnabled(); + final boolean shouldCaptureLogs = requestLoggingEnabled && requestLoggingConfig.isLogCaptureEnabled(); + final boolean shouldCaptureSpans = requestLoggingEnabled && requestLoggingConfig.isTracingEnabled(); Exception exception = null; final long startTime = System.currentTimeMillis(); @@ -88,8 +82,7 @@ protected void doFilterInternal( LogAppender.startCapture(); } - final SpanCollector.SpanHandle spanHandle = - shouldCaptureSpans ? client.spanCollector.startCollection() : null; + final SpanCollector.SpanHandle spanHandle = shouldCaptureSpans ? client.spanCollector.startCollection() : null; try { filterChain.doFilter( @@ -101,17 +94,13 @@ protected void doFilterInternal( } finally { try { final long responseTimeInMillis = System.currentTimeMillis() - startTime; - final String path = - (String) - request.getAttribute( - HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE); + final String path = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE); // End span collection and get spans List spans = null; String traceId = null; if (spanHandle != null) { - Object handler = - request.getAttribute(HandlerMapping.BEST_MATCHING_HANDLER_ATTRIBUTE); + Object handler = request.getAttribute(HandlerMapping.BEST_MATCHING_HANDLER_ATTRIBUTE); if (handler instanceof HandlerMethod handlerMethod) { String controllerName = handlerMethod.getBeanType().getSimpleName(); String methodName = handlerMethod.getMethod().getName(); @@ -122,52 +111,39 @@ protected void doFilterInternal( } // End log capture and get logs - final List capturedLogs = - shouldCaptureLogs ? LogAppender.endCapture() : null; + final List capturedLogs = shouldCaptureLogs ? LogAppender.endCapture() : null; // Get request and response body final byte[] requestBody = - cachingRequest != null - ? cachingRequest.getContentAsByteArray() - : new byte[0]; + cachingRequest != null ? cachingRequest.getContentAsByteArray() : new byte[0]; final byte[] responseBody = - cachingResponse != null - ? cachingResponse.getContentAsByteArray() - : new byte[0]; + cachingResponse != null ? cachingResponse.getContentAsByteArray() : new byte[0]; if (cachingResponse != null) { cachingResponse.copyBodyToResponse(); } // Register consumer and get consumer identifier - final Consumer consumer = - ConsumerRegistry.consumerFromObject( - request.getAttribute("apitallyConsumer")); + final Consumer consumer = ConsumerRegistry.consumerFromObject(request.getAttribute("apitallyConsumer")); client.consumerRegistry.addOrUpdateConsumer(consumer); final String consumerIdentifier = consumer != null ? consumer.getIdentifier() : ""; // Get captured exception Object capturedException = request.getAttribute("apitallyCapturedException"); - if (exception == null - && capturedException != null - && capturedException instanceof Exception) { + if (exception == null && capturedException != null && capturedException instanceof Exception) { exception = (Exception) capturedException; } // Add request to counter final long requestContentLength = request.getContentLengthLong(); - final long requestSize = - requestContentLength >= 0 - ? requestContentLength - : cachingRequest != null ? requestBody.length : -1; + final long requestSize = requestContentLength >= 0 + ? requestContentLength + : cachingRequest != null ? requestBody.length : -1; final long responseContentLength = getResponseContentLength(response); - final long responseSize = - responseContentLength >= 0 - ? responseContentLength - : cachingResponse != null - ? responseBody.length - : countingResponse != null - ? countingResponse.getByteCount() - : -1; + final long responseSize = responseContentLength >= 0 + ? responseContentLength + : cachingResponse != null + ? responseBody.length + : countingResponse != null ? countingResponse.getByteCount() : -1; client.requestCounter.addRequest( consumerIdentifier, request.getMethod(), @@ -179,21 +155,13 @@ protected void doFilterInternal( // Log request if (client.requestLogger.isEnabled()) { - final Header[] requestHeaders = - Collections.list(request.getHeaderNames()).stream() - .flatMap( - name -> - Collections.list(request.getHeaders(name)) - .stream() - .map(value -> new Header(name, value))) - .toArray(Header[]::new); - final Header[] responseHeaders = - response.getHeaderNames().stream() - .flatMap( - name -> - response.getHeaders(name).stream() - .map(value -> new Header(name, value))) - .toArray(Header[]::new); + final Header[] requestHeaders = Collections.list(request.getHeaderNames()).stream() + .flatMap(name -> Collections.list(request.getHeaders(name)).stream() + .map(value -> new Header(name, value))) + .toArray(Header[]::new); + final Header[] responseHeaders = response.getHeaderNames().stream() + .flatMap(name -> response.getHeaders(name).stream().map(value -> new Header(name, value))) + .toArray(Header[]::new); client.requestLogger.logRequest( new Request( @@ -248,8 +216,7 @@ protected void doFilterInternal( // Add server error to counter if (response.getStatus() == 500 && exception != null) { - client.serverErrorCounter.addServerError( - consumerIdentifier, request.getMethod(), path, exception); + client.serverErrorCounter.addServerError(consumerIdentifier, request.getMethod(), path, exception); } } catch (Exception e) { logger.error("Error in Apitally filter", e); diff --git a/src/main/java/io/apitally/spring/ApitallyProperties.java b/src/main/java/io/apitally/spring/ApitallyProperties.java index 6b813ad..1b04c33 100644 --- a/src/main/java/io/apitally/spring/ApitallyProperties.java +++ b/src/main/java/io/apitally/spring/ApitallyProperties.java @@ -20,8 +20,7 @@ public class ApitallyProperties { @Pattern( regexp = "^[\\w-]{1,32}$", - message = - "Env must be 1-32 characters long and contain only word characters and hyphens") + message = "Env must be 1-32 characters long and contain only word characters and hyphens") private String env = "default"; private RequestLoggingConfig requestLogging = new RequestLoggingConfig(); @@ -63,9 +62,8 @@ public void setCallbacksClass(String callbacksClass) { try { Class clazz = Class.forName(callbacksClass); if (RequestLoggingCallbacks.class.isAssignableFrom(clazz)) { - setCallbacks( - (RequestLoggingCallbacks) - clazz.getDeclaredConstructor().newInstance()); + setCallbacks((RequestLoggingCallbacks) + clazz.getDeclaredConstructor().newInstance()); } } catch (ReflectiveOperationException e) { logger.error("Failed to initialize request logging callbacks", e); diff --git a/src/main/java/io/apitally/spring/ApitallySpanCollector.java b/src/main/java/io/apitally/spring/ApitallySpanCollector.java index 00bda4c..7cf948e 100644 --- a/src/main/java/io/apitally/spring/ApitallySpanCollector.java +++ b/src/main/java/io/apitally/spring/ApitallySpanCollector.java @@ -32,8 +32,10 @@ public void setDelegate(SpanCollector spanCollector) { private void initializeTracer(SpanCollector spanCollector) { try { - SdkTracerProvider provider = SdkTracerProvider.builder().addSpanProcessor(this).build(); - OpenTelemetrySdk sdk = OpenTelemetrySdk.builder().setTracerProvider(provider).build(); + SdkTracerProvider provider = + SdkTracerProvider.builder().addSpanProcessor(this).build(); + OpenTelemetrySdk sdk = + OpenTelemetrySdk.builder().setTracerProvider(provider).build(); Tracer tracer; try { GlobalOpenTelemetry.set(sdk); diff --git a/src/main/java/io/apitally/spring/ApitallyUtils.java b/src/main/java/io/apitally/spring/ApitallyUtils.java index 01616c2..51ad91c 100644 --- a/src/main/java/io/apitally/spring/ApitallyUtils.java +++ b/src/main/java/io/apitally/spring/ApitallyUtils.java @@ -15,42 +15,24 @@ public final class ApitallyUtils { public static List getPaths(RequestMappingHandlerMapping requestMappingHandlerMapping) { return requestMappingHandlerMapping.getHandlerMethods().entrySet().stream() - .flatMap( - entry -> { - RequestMappingInfo mappingInfo = entry.getKey(); - return mappingInfo.getMethodsCondition().getMethods().stream() - .filter( - method -> - method != RequestMethod.OPTIONS - && method != RequestMethod.HEAD) - .flatMap( - method -> { - PathPatternsRequestCondition pathPatterns = - mappingInfo.getPathPatternsCondition(); - if (pathPatterns != null - && pathPatterns.getPatterns() != null) { - return pathPatterns.getPatterns().stream() - .map( - pattern -> - new Path( - method.name(), - pattern - .getPatternString())); - } - PatternsRequestCondition patterns = - mappingInfo.getPatternsCondition(); - if (patterns != null - && patterns.getPatterns() != null) { - return patterns.getPatterns().stream() - .map( - pattern -> - new Path( - method.name(), - pattern)); - } - return List.of().stream(); - }); - }) + .flatMap(entry -> { + RequestMappingInfo mappingInfo = entry.getKey(); + return mappingInfo.getMethodsCondition().getMethods().stream() + .filter(method -> method != RequestMethod.OPTIONS && method != RequestMethod.HEAD) + .flatMap(method -> { + PathPatternsRequestCondition pathPatterns = mappingInfo.getPathPatternsCondition(); + if (pathPatterns != null && pathPatterns.getPatterns() != null) { + return pathPatterns.getPatterns().stream() + .map(pattern -> new Path(method.name(), pattern.getPatternString())); + } + PatternsRequestCondition patterns = mappingInfo.getPatternsCondition(); + if (patterns != null && patterns.getPatterns() != null) { + return patterns.getPatterns().stream() + .map(pattern -> new Path(method.name(), pattern)); + } + return List.of().stream(); + }); + }) .collect(Collectors.toList()); } diff --git a/src/test/java/io/apitally/common/ApitallyClientTest.java b/src/test/java/io/apitally/common/ApitallyClientTest.java index 6973cfe..e6b93b6 100644 --- a/src/test/java/io/apitally/common/ApitallyClientTest.java +++ b/src/test/java/io/apitally/common/ApitallyClientTest.java @@ -31,9 +31,7 @@ class ApitallyClientTest { void setUp() { RequestLoggingConfig requestLoggingConfig = new RequestLoggingConfig(); requestLoggingConfig.setEnabled(true); - client = - new ApitallyClient( - "00000000-0000-0000-0000-000000000000", "test", requestLoggingConfig); + client = new ApitallyClient("00000000-0000-0000-0000-000000000000", "test", requestLoggingConfig); clientSpy = spy(client); when(clientSpy.sendHubRequest(any(HttpRequest.class))) .thenReturn(CompletableFuture.completedFuture(ApitallyClient.HubRequestStatus.OK)); @@ -46,27 +44,22 @@ void tearDown() { @Test void testSync() { - Header[] requestHeaders = - new Header[] { - new Header("Content-Type", "application/json"), - new Header("User-Agent", "test-client"), - }; - Header[] responseHeaders = - new Header[] { - new Header("Content-Type", "application/json"), - }; - Request request = - new Request( - System.currentTimeMillis() / 1000.0, - "tester", - "GET", - "/items", - "http://test/items", - requestHeaders, - 0L, - new byte[0]); - Response response = - new Response(200, 0.123, responseHeaders, 13L, "{\"items\": []}".getBytes()); + Header[] requestHeaders = new Header[] { + new Header("Content-Type", "application/json"), new Header("User-Agent", "test-client"), + }; + Header[] responseHeaders = new Header[] { + new Header("Content-Type", "application/json"), + }; + Request request = new Request( + System.currentTimeMillis() / 1000.0, + "tester", + "GET", + "/items", + "http://test/items", + requestHeaders, + 0L, + new byte[0]); + Response response = new Response(200, 0.123, responseHeaders, 13L, "{\"items\": []}".getBytes()); client.requestLogger.logRequest(request, response, null, null, null, null); client.requestLogger.maintain(); @@ -79,8 +72,7 @@ void testSync() { ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(HttpRequest.class); verify(clientSpy, timeout(5000).times(3)).sendHubRequest(requestCaptor.capture()); List capturedRequests = requestCaptor.getAllValues(); - assertTrue( - capturedRequests.stream().anyMatch(r -> r.uri().toString().contains("/startup"))); + assertTrue(capturedRequests.stream().anyMatch(r -> r.uri().toString().contains("/startup"))); assertTrue(capturedRequests.stream().anyMatch(r -> r.uri().toString().contains("/sync"))); assertTrue(capturedRequests.stream().anyMatch(r -> r.uri().toString().contains("/log"))); diff --git a/src/test/java/io/apitally/common/InstanceLockTest.java b/src/test/java/io/apitally/common/InstanceLockTest.java index 6e0ded3..b8eebd8 100644 --- a/src/test/java/io/apitally/common/InstanceLockTest.java +++ b/src/test/java/io/apitally/common/InstanceLockTest.java @@ -32,14 +32,12 @@ void setUp() throws IOException { void tearDown() throws IOException { if (tempDir != null && Files.exists(tempDir)) { try (var paths = Files.walk(tempDir)) { - paths.sorted(Comparator.reverseOrder()) - .forEach( - path -> { - try { - Files.deleteIfExists(path); - } catch (IOException ignored) { - } - }); + paths.sorted(Comparator.reverseOrder()).forEach(path -> { + try { + Files.deleteIfExists(path); + } catch (IOException ignored) { + } + }); } } } diff --git a/src/test/java/io/apitally/common/RequestLoggerTest.java b/src/test/java/io/apitally/common/RequestLoggerTest.java index adbf2ff..8eee9b0 100644 --- a/src/test/java/io/apitally/common/RequestLoggerTest.java +++ b/src/test/java/io/apitally/common/RequestLoggerTest.java @@ -46,55 +46,29 @@ void tearDown() { @Test void testEndToEnd() { - Header[] requestHeaders = - new Header[] { - new Header("User-Agent", "Test"), - }; - Header[] responseHeaders = - new Header[] { - new Header("Content-Type", "application/json"), - }; - Request request = - new Request( - System.currentTimeMillis() / 1000.0, - "tester", - "GET", - "/items", - "http://test/items", - requestHeaders, - 0L, - new byte[0]); - Response response = - new Response(200, 0.123, responseHeaders, 13L, "{\"items\": []}".getBytes()); + Header[] requestHeaders = new Header[] { + new Header("User-Agent", "Test"), + }; + Header[] responseHeaders = new Header[] { + new Header("Content-Type", "application/json"), + }; + Request request = new Request( + System.currentTimeMillis() / 1000.0, + "tester", + "GET", + "/items", + "http://test/items", + requestHeaders, + 0L, + new byte[0]); + Response response = new Response(200, 0.123, responseHeaders, 13L, "{\"items\": []}".getBytes()); Exception exception = new Exception("test"); List logs = new ArrayList<>(); - logs.add( - new LogRecord( - System.currentTimeMillis() / 1000.0, - "test.Logger", - "INFO", - "Test log message")); + logs.add(new LogRecord(System.currentTimeMillis() / 1000.0, "test.Logger", "INFO", "Test log message")); List spans = new ArrayList<>(); - spans.add( - new SpanData( - "a1b2c3d4e5f6a7b8", - null, - "root", - "INTERNAL", - 1000000L, - 2000000L, - null, - null)); - spans.add( - new SpanData( - "b2c3d4e5f6a7b8c9", - "a1b2c3d4e5f6a7b8", - "child", - "INTERNAL", - 1100000L, - 1900000L, - "OK", - null)); + spans.add(new SpanData("a1b2c3d4e5f6a7b8", null, "root", "INTERNAL", 1000000L, 2000000L, null, null)); + spans.add(new SpanData( + "b2c3d4e5f6a7b8c9", "a1b2c3d4e5f6a7b8", "child", "INTERNAL", 1100000L, 1900000L, "OK", null)); String traceId = "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"; requestLogger.logRequest(request, response, exception, logs, spans, traceId); @@ -110,8 +84,8 @@ void testEndToEnd() { assertEquals(0.123, jsonNode.get("response").get("responseTime").asDouble(), 0.001); assertEquals( "{\"items\":[]}", - new String( - Base64.getDecoder().decode(jsonNode.get("response").get("body").asText()))); + new String(Base64.getDecoder() + .decode(jsonNode.get("response").get("body").asText()))); JsonNode requestHeadersNode = jsonNode.get("request").get("headers"); assertTrue(requestHeadersNode.isArray()); @@ -138,7 +112,8 @@ void testEndToEnd() { assertEquals("INFO", logsNode.get(0).get("level").asText()); assertEquals("Test log message", logsNode.get(0).get("message").asText()); - assertEquals("a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6", jsonNode.get("trace_id").asText()); + assertEquals( + "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6", jsonNode.get("trace_id").asText()); JsonNode spansNode = jsonNode.get("spans"); assertTrue(spansNode.isArray()); assertEquals(2, spansNode.size()); @@ -162,26 +137,22 @@ void testExcludeBasedOnOptions() { requestLoggingConfig.setResponseBodyIncluded(false); requestLogger = new RequestLogger(requestLoggingConfig); - Header[] requestHeaders = - new Header[] { - new Header("Content-Type", "application/json"), - }; - Header[] responseHeaders = - new Header[] { - new Header("Content-Type", "application/json"), - }; - Request request = - new Request( - System.currentTimeMillis() / 1000.0, - "tester", - "POST", - "/items", - "http://test/items?token=my-secret-token", - requestHeaders, - 16L, - "{\"key\": \"value\"}".getBytes()); - Response response = - new Response(200, 0.123, responseHeaders, 16L, "{\"key\": \"value\"}".getBytes()); + Header[] requestHeaders = new Header[] { + new Header("Content-Type", "application/json"), + }; + Header[] responseHeaders = new Header[] { + new Header("Content-Type", "application/json"), + }; + Request request = new Request( + System.currentTimeMillis() / 1000.0, + "tester", + "POST", + "/items", + "http://test/items?token=my-secret-token", + requestHeaders, + 16L, + "{\"key\": \"value\"}".getBytes()); + Response response = new Response(200, 0.123, responseHeaders, 16L, "{\"key\": \"value\"}".getBytes()); requestLogger.logRequest(request, response, null, null, null, null); @@ -197,28 +168,24 @@ void testExcludeBasedOnOptions() { @Test void testExcludeBasedOnCallback() { requestLoggingConfig.setEnabled(true); - requestLoggingConfig.setCallbacks( - new RequestLoggingCallbacks() { - @Override - public boolean shouldExclude(Request request, Response response) { - return request.getConsumer() != null - && request.getConsumer().contains("tester"); - } - }); + requestLoggingConfig.setCallbacks(new RequestLoggingCallbacks() { + @Override + public boolean shouldExclude(Request request, Response response) { + return request.getConsumer() != null && request.getConsumer().contains("tester"); + } + }); requestLogger = new RequestLogger(requestLoggingConfig); - Request request = - new Request( - System.currentTimeMillis() / 1000.0, - "tester", - "GET", - "/items", - "http://test/items", - new Header[0], - 0L, - new byte[0]); - Response response = - new Response(200, 0.123, new Header[0], 13L, "{\"items\": []}".getBytes()); + Request request = new Request( + System.currentTimeMillis() / 1000.0, + "tester", + "GET", + "/items", + "http://test/items", + new Header[0], + 0L, + new byte[0]); + Response response = new Response(200, 0.123, new Header[0], 13L, "{\"items\": []}".getBytes()); requestLogger.logRequest(request, response, null, null, null, null); @@ -228,18 +195,16 @@ public boolean shouldExclude(Request request, Response response) { @Test void testExcludeBasedOnPath() { - Request request = - new Request( - System.currentTimeMillis() / 1000.0, - null, - "GET", - "/healthz", - "http://test/healthz", - new Header[0], - 0L, - new byte[0]); - Response response = - new Response(200, 0.123, new Header[0], 17L, "{\"healthy\": true}".getBytes()); + Request request = new Request( + System.currentTimeMillis() / 1000.0, + null, + "GET", + "/healthz", + "http://test/healthz", + new Header[0], + 0L, + new byte[0]); + Response response = new Response(200, 0.123, new Header[0], 17L, "{\"healthy\": true}".getBytes()); requestLogger.logRequest(request, response, null, null, null, null); @@ -249,20 +214,11 @@ void testExcludeBasedOnPath() { @Test void testExcludeBasedOnUserAgent() { - Header[] requestHeaders = - new Header[] { - new Header("User-Agent", "ELB-HealthChecker/2.0"), - }; - Request request = - new Request( - System.currentTimeMillis() / 1000.0, - null, - "GET", - "/", - "http://test/", - requestHeaders, - 0L, - new byte[0]); + Header[] requestHeaders = new Header[] { + new Header("User-Agent", "ELB-HealthChecker/2.0"), + }; + Request request = new Request( + System.currentTimeMillis() / 1000.0, null, "GET", "/", "http://test/", requestHeaders, 0L, new byte[0]); Response response = new Response(200, 0, new Header[0], 0L, new byte[0]); requestLogger.logRequest(request, response, null, null, null, null); @@ -278,22 +234,20 @@ void testMaskHeaders() { requestLoggingConfig.setHeaderMaskPatterns(List.of("(?i)test")); requestLogger = new RequestLogger(requestLoggingConfig); - Header[] requestHeaders = - new Header[] { - new Header("Accept", "text/plain"), - new Header("Authorization", "Bearer 123456"), - new Header("X-Test", "123456"), - }; - Request request = - new Request( - System.currentTimeMillis() / 1000.0, - null, - "GET", - "/test", - "http://localhost:8000/test?foo=bar", - requestHeaders, - 0L, - new byte[0]); + Header[] requestHeaders = new Header[] { + new Header("Accept", "text/plain"), + new Header("Authorization", "Bearer 123456"), + new Header("X-Test", "123456"), + }; + Request request = new Request( + System.currentTimeMillis() / 1000.0, + null, + "GET", + "/test", + "http://localhost:8000/test?foo=bar", + requestHeaders, + 0L, + new byte[0]); Response response = new Response(200, 0, new Header[0], 0L, new byte[0]); requestLogger.logRequest(request, response, null, null, null, null); @@ -320,16 +274,15 @@ void testMaskQueryParams() { requestLoggingConfig.setQueryParamMaskPatterns(List.of("(?i)test")); requestLogger = new RequestLogger(requestLoggingConfig); - Request request = - new Request( - System.currentTimeMillis() / 1000.0, - null, - "GET", - "/test", - "http://localhost/test?secret=123456&test=123456&other=abcdef", - new Header[0], - 0L, - new byte[0]); + Request request = new Request( + System.currentTimeMillis() / 1000.0, + null, + "GET", + "/test", + "http://localhost/test?secret=123456&test=123456&other=abcdef", + new Header[0], + 0L, + new byte[0]); Response response = new Response(200, 0, new Header[0], 0L, new byte[0]); requestLogger.logRequest(request, response, null, null, null, null); @@ -347,60 +300,50 @@ void testMaskBodyUsingCallback() { requestLoggingConfig.setEnabled(true); requestLoggingConfig.setRequestBodyIncluded(true); requestLoggingConfig.setResponseBodyIncluded(true); - requestLoggingConfig.setCallbacks( - new RequestLoggingCallbacks() { - @Override - public byte[] maskRequestBody(Request request) { - if ("/test".equals(request.getPath())) { - return null; - } - return request.getBody(); - } - - @Override - public byte[] maskResponseBody(Request request, Response response) { - if ("/test".equals(request.getPath())) { - return null; - } - return response.getBody(); - } - }); + requestLoggingConfig.setCallbacks(new RequestLoggingCallbacks() { + @Override + public byte[] maskRequestBody(Request request) { + if ("/test".equals(request.getPath())) { + return null; + } + return request.getBody(); + } + + @Override + public byte[] maskResponseBody(Request request, Response response) { + if ("/test".equals(request.getPath())) { + return null; + } + return response.getBody(); + } + }); requestLogger = new RequestLogger(requestLoggingConfig); - Header[] requestHeaders = - new Header[] { - new Header("Content-Type", "application/json"), - }; - Request request = - new Request( - System.currentTimeMillis() / 1000.0, - null, - "GET", - "/test", - "http://test/test", - requestHeaders, - 4L, - "test".getBytes()); - Response response = - new Response( - 200, - 0, - new Header[] {new Header("Content-Type", "application/json")}, - 4L, - "test".getBytes()); + Header[] requestHeaders = new Header[] { + new Header("Content-Type", "application/json"), + }; + Request request = new Request( + System.currentTimeMillis() / 1000.0, + null, + "GET", + "/test", + "http://test/test", + requestHeaders, + 4L, + "test".getBytes()); + Response response = new Response( + 200, 0, new Header[] {new Header("Content-Type", "application/json")}, 4L, "test".getBytes()); requestLogger.logRequest(request, response, null, null, null, null); JsonNode[] items = getLoggedItems(requestLogger); assertEquals(1, items.length); - String requestBody = - new String( - Base64.getDecoder().decode(items[0].get("request").get("body").asText())); + String requestBody = new String( + Base64.getDecoder().decode(items[0].get("request").get("body").asText())); assertEquals("", requestBody); - String responseBody = - new String( - Base64.getDecoder().decode(items[0].get("response").get("body").asText())); + String responseBody = new String( + Base64.getDecoder().decode(items[0].get("response").get("body").asText())); assertEquals("", responseBody); } @@ -417,27 +360,24 @@ void testMaskBodyFields() { String responseBodyJson = "{\"status\":\"success\",\"secret\":\"response_secret\",\"data\":{\"pwd\":\"response_pwd\"}}"; - Header[] requestHeaders = - new Header[] { - new Header("Content-Type", "application/json"), - }; - Request request = - new Request( - System.currentTimeMillis() / 1000.0, - null, - "POST", - "/test", - "http://localhost:8000/test?foo=bar", - requestHeaders, - (long) requestBodyJson.getBytes().length, - requestBodyJson.getBytes()); - Response response = - new Response( - 200, - 0.1, - new Header[] {new Header("Content-Type", "application/json")}, - (long) responseBodyJson.getBytes().length, - responseBodyJson.getBytes()); + Header[] requestHeaders = new Header[] { + new Header("Content-Type", "application/json"), + }; + Request request = new Request( + System.currentTimeMillis() / 1000.0, + null, + "POST", + "/test", + "http://localhost:8000/test?foo=bar", + requestHeaders, + (long) requestBodyJson.getBytes().length, + requestBodyJson.getBytes()); + Response response = new Response( + 200, + 0.1, + new Header[] {new Header("Content-Type", "application/json")}, + (long) responseBodyJson.getBytes().length, + responseBodyJson.getBytes()); requestLogger.logRequest(request, response, null, null, null, null); diff --git a/src/test/java/io/apitally/common/SpanCollectorTest.java b/src/test/java/io/apitally/common/SpanCollectorTest.java index 95a08d4..c49ab2a 100644 --- a/src/test/java/io/apitally/common/SpanCollectorTest.java +++ b/src/test/java/io/apitally/common/SpanCollectorTest.java @@ -92,16 +92,17 @@ void testCollectorWithChildSpans() { assertTrue(spanNames.contains("child1")); assertTrue(spanNames.contains("child2")); - SpanData rootSpan = - spans.stream() - .filter(s -> s.getName().equals("TestController.getTest")) - .findFirst() - .orElse(null); + SpanData rootSpan = spans.stream() + .filter(s -> s.getName().equals("TestController.getTest")) + .findFirst() + .orElse(null); assertNotNull(rootSpan); assertNull(rootSpan.getParentSpanId()); - SpanData childSpan = - spans.stream().filter(s -> s.getName().equals("child1")).findFirst().orElse(null); + SpanData childSpan = spans.stream() + .filter(s -> s.getName().equals("child1")) + .findFirst() + .orElse(null); assertNotNull(childSpan); assertEquals(rootSpan.getSpanId(), childSpan.getParentSpanId()); } @@ -144,8 +145,10 @@ void testSpanDataSerialization() { List spans = handle.end(); assertNotNull(spans); - SpanData testSpan = - spans.stream().filter(s -> s.getName().equals("testSpan")).findFirst().orElse(null); + SpanData testSpan = spans.stream() + .filter(s -> s.getName().equals("testSpan")) + .findFirst() + .orElse(null); assertNotNull(testSpan); assertEquals(16, testSpan.getSpanId().length()); assertEquals("INTERNAL", testSpan.getKind()); diff --git a/src/test/java/io/apitally/spring/ApitallyFilterTest.java b/src/test/java/io/apitally/spring/ApitallyFilterTest.java index c596f14..fd40f0e 100644 --- a/src/test/java/io/apitally/spring/ApitallyFilterTest.java +++ b/src/test/java/io/apitally/spring/ApitallyFilterTest.java @@ -39,9 +39,7 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; -@SpringBootTest( - classes = TestApplication.class, - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@SpringBootTest(classes = TestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @ContextConfiguration(classes = {ApitallyFilterTest.TestConfig.class}) class ApitallyFilterTest { @@ -54,19 +52,14 @@ static class TestConfig { public ApitallyClient apitallyClient(ApitallyProperties properties) { LogAppender.register(); ApitallyClient client = - new ApitallyClient( - properties.getClientId(), - properties.getEnv(), - properties.getRequestLogging()); + new ApitallyClient(properties.getClientId(), properties.getEnv(), properties.getRequestLogging()); ApitallySpanCollector.getInstance().setDelegate(client.spanCollector); return client; } @Bean - public FilterRegistrationBean filterRegistration( - ApitallyClient apitallyClient) { - final FilterRegistrationBean registrationBean = - new FilterRegistrationBean<>(); + public FilterRegistrationBean filterRegistration(ApitallyClient apitallyClient) { + final FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new ApitallyFilter(apitallyClient)); registrationBean.setOrder(Ordered.LOWEST_PRECEDENCE - 10); return registrationBean; @@ -78,11 +71,14 @@ public ApitallyExceptionResolver apitallyExceptionResolver() { } } - @Autowired private TestRestTemplate restTemplate; + @Autowired + private TestRestTemplate restTemplate; - @Autowired private ApitallyClient apitallyClient; + @Autowired + private ApitallyClient apitallyClient; - @Autowired private RequestMappingHandlerMapping requestMappingHandlerMapping; + @Autowired + private RequestMappingHandlerMapping requestMappingHandlerMapping; @BeforeEach void setUp() { @@ -117,40 +113,28 @@ void testRequestCounter() { List requests = apitallyClient.requestCounter.getAndResetRequests(); assertEquals(4, requests.size(), "4 requests counted"); - assertTrue( - requests.stream() - .anyMatch( - r -> - r.getMethod().equals("GET") - && r.getPath().equals("/items") - && r.getStatusCode() == 200 - && r.getRequestCount() == 1 - && r.getResponseSizeSum() > 0)); - assertTrue( - requests.stream() - .anyMatch( - r -> - r.getMethod().equals("GET") - && r.getPath().equals("/items/{id}") - && r.getStatusCode() == 200 - && r.getRequestCount() == 2)); - assertTrue( - requests.stream() - .anyMatch( - r -> - r.getMethod().equals("GET") - && r.getPath().equals("/items/{id}") - && r.getStatusCode() == 400 - && r.getRequestCount() == 1)); - assertTrue( - requests.stream() - .anyMatch( - r -> - r.getMethod().equals("GET") - && r.getPath().equals("/throw") - && r.getStatusCode() == 500 - && r.getRequestCount() == 1 - && r.getResponseSizeSum() == 0)); + assertTrue(requests.stream() + .anyMatch(r -> r.getMethod().equals("GET") + && r.getPath().equals("/items") + && r.getStatusCode() == 200 + && r.getRequestCount() == 1 + && r.getResponseSizeSum() > 0)); + assertTrue(requests.stream() + .anyMatch(r -> r.getMethod().equals("GET") + && r.getPath().equals("/items/{id}") + && r.getStatusCode() == 200 + && r.getRequestCount() == 2)); + assertTrue(requests.stream() + .anyMatch(r -> r.getMethod().equals("GET") + && r.getPath().equals("/items/{id}") + && r.getStatusCode() == 400 + && r.getRequestCount() == 1)); + assertTrue(requests.stream() + .anyMatch(r -> r.getMethod().equals("GET") + && r.getPath().equals("/throw") + && r.getStatusCode() == 500 + && r.getRequestCount() == 1 + && r.getResponseSizeSum() == 0)); requests = apitallyClient.requestCounter.getAndResetRequests(); assertEquals(0, requests.size(), "No requests counted after reset"); @@ -174,36 +158,26 @@ void testValidationErrorCounter() { delay(100); - List validationErrors = - apitallyClient.validationErrorCounter.getAndResetValidationErrors(); + List validationErrors = apitallyClient.validationErrorCounter.getAndResetValidationErrors(); assertEquals(3, validationErrors.size()); - assertTrue( - validationErrors.stream() - .anyMatch( - e -> - e.getMethod().equals("POST") - && e.getPath().equals("/items") - && e.getLoc().equals("testItem.name") - && e.getType().equals("Size") - && e.getErrorCount() == 1)); - assertTrue( - validationErrors.stream() - .anyMatch( - e -> - e.getMethod().equals("GET") - && e.getPath().equals("/items") - && e.getLoc().equals("getItems.name") - && e.getType().equals("Size") - && e.getErrorCount() == 1)); - assertTrue( - validationErrors.stream() - .anyMatch( - e -> - e.getMethod().equals("GET") - && e.getPath().equals("/items/{id}") - && e.getLoc().equals("getItem.id") - && e.getType().equals("Min") - && e.getErrorCount() == 1)); + assertTrue(validationErrors.stream() + .anyMatch(e -> e.getMethod().equals("POST") + && e.getPath().equals("/items") + && e.getLoc().equals("testItem.name") + && e.getType().equals("Size") + && e.getErrorCount() == 1)); + assertTrue(validationErrors.stream() + .anyMatch(e -> e.getMethod().equals("GET") + && e.getPath().equals("/items") + && e.getLoc().equals("getItems.name") + && e.getType().equals("Size") + && e.getErrorCount() == 1)); + assertTrue(validationErrors.stream() + .anyMatch(e -> e.getMethod().equals("GET") + && e.getPath().equals("/items/{id}") + && e.getLoc().equals("getItem.id") + && e.getType().equals("Min") + && e.getErrorCount() == 1)); validationErrors = apitallyClient.validationErrorCounter.getAndResetValidationErrors(); assertEquals(0, validationErrors.size()); @@ -216,17 +190,13 @@ void testServerErrorCounter() { delay(100); - List serverErrors = - apitallyClient.serverErrorCounter.getAndResetServerErrors(); + List serverErrors = apitallyClient.serverErrorCounter.getAndResetServerErrors(); assertEquals(1, serverErrors.size()); - assertTrue( - serverErrors.stream() - .anyMatch( - e -> - e.getType().equals("TestException") - && e.getMessage().equals("test") - && e.getStackTraceString().length() > 100 - && e.getErrorCount() == 1)); + assertTrue(serverErrors.stream() + .anyMatch(e -> e.getType().equals("TestException") + && e.getMessage().equals("test") + && e.getStackTraceString().length() > 100 + && e.getErrorCount() == 1)); serverErrors = apitallyClient.serverErrorCounter.getAndResetServerErrors(); assertEquals(0, serverErrors.size()); @@ -254,32 +224,16 @@ void testConsumerRegistry() { void testGetPaths() { List paths = ApitallyUtils.getPaths(requestMappingHandlerMapping); assertEquals(6, paths.size()); - assertTrue( - paths.stream() - .anyMatch( - p -> p.getMethod().equals("GET") && p.getPath().equals("/items"))); - assertTrue( - paths.stream() - .anyMatch( - p -> - p.getMethod().equals("GET") - && p.getPath().equals("/items/{id}"))); - assertTrue( - paths.stream() - .anyMatch( - p -> p.getMethod().equals("POST") && p.getPath().equals("/items"))); - assertTrue( - paths.stream() - .anyMatch( - p -> - p.getMethod().equals("PUT") - && p.getPath().equals("/items/{id}"))); - assertTrue( - paths.stream() - .anyMatch( - p -> - p.getMethod().equals("DELETE") - && p.getPath().equals("/items/{id}"))); + assertTrue(paths.stream() + .anyMatch(p -> p.getMethod().equals("GET") && p.getPath().equals("/items"))); + assertTrue(paths.stream() + .anyMatch(p -> p.getMethod().equals("GET") && p.getPath().equals("/items/{id}"))); + assertTrue(paths.stream() + .anyMatch(p -> p.getMethod().equals("POST") && p.getPath().equals("/items"))); + assertTrue(paths.stream() + .anyMatch(p -> p.getMethod().equals("PUT") && p.getPath().equals("/items/{id}"))); + assertTrue(paths.stream() + .anyMatch(p -> p.getMethod().equals("DELETE") && p.getPath().equals("/items/{id}"))); } @Test @@ -317,9 +271,8 @@ void testRequestLogger() { assertEquals("GET", firstItem.get("request").get("method").asText()); assertTrue(firstItem.get("request").get("url").asText().contains("/items")); assertEquals(200, firstItem.get("response").get("statusCode").asInt()); - String responseBody = - new String( - Base64.getDecoder().decode(firstItem.get("response").get("body").asText())); + String responseBody = new String( + Base64.getDecoder().decode(firstItem.get("response").get("body").asText())); assertTrue(responseBody.contains("alice")); // Verify application logs were captured @@ -332,17 +285,15 @@ void testRequestLogger() { assertTrue(firstItem.has("spans")); assertTrue(firstItem.get("spans").isArray()); assertTrue(firstItem.get("spans").size() >= 2); // root span + child span - assertTrue( - StreamSupport.stream(firstItem.get("spans").spliterator(), false) - .anyMatch(span -> span.get("name").asText().equals("fetchItems"))); + assertTrue(StreamSupport.stream(firstItem.get("spans").spliterator(), false) + .anyMatch(span -> span.get("name").asText().equals("fetchItems"))); // Verify POST request logging with request body JsonNode secondItem = items[1]; assertEquals("POST", secondItem.get("request").get("method").asText()); assertTrue(secondItem.get("request").get("url").asText().contains("/items")); - String requestBody = - new String( - Base64.getDecoder().decode(secondItem.get("request").get("body").asText())); + String requestBody = new String( + Base64.getDecoder().decode(secondItem.get("request").get("body").asText())); assertTrue(requestBody.contains("bob")); } diff --git a/src/test/java/io/apitally/spring/app/TestController.java b/src/test/java/io/apitally/spring/app/TestController.java index 017e0b1..9f936ba 100644 --- a/src/test/java/io/apitally/spring/app/TestController.java +++ b/src/test/java/io/apitally/spring/app/TestController.java @@ -35,8 +35,7 @@ public class TestController { @GetMapping("/items") public List getItems( - HttpServletRequest request, - @RequestParam(required = false) @Size(min = 2, max = 10) String name) { + HttpServletRequest request, @RequestParam(required = false) @Size(min = 2, max = 10) String name) { logger.info("Getting items with filter: {}", name != null ? name : "none"); ApitallyConsumer consumer = new ApitallyConsumer("tester", "Tester", "Test Group"); @@ -66,8 +65,7 @@ public TestItem getItem(@PathVariable @Min(1) Integer id) { @PutMapping("/items/{id}") @ResponseStatus(HttpStatus.NO_CONTENT) - public void updateItem( - @Valid @RequestBody TestItem newItem, @PathVariable @Min(1) Integer id) {} + public void updateItem(@Valid @RequestBody TestItem newItem, @PathVariable @Min(1) Integer id) {} @DeleteMapping(value = "/items/{id}") @ResponseStatus(HttpStatus.NO_CONTENT) @@ -80,10 +78,8 @@ public String getError() { @ExceptionHandler({ConstraintViolationException.class}) @ResponseStatus(HttpStatus.BAD_REQUEST) - private ResponseEntity handleConstraintViolationException( - ConstraintViolationException e) { - return ResponseEntity.of( - ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, e.getMessage())) + private ResponseEntity handleConstraintViolationException(ConstraintViolationException e) { + return ResponseEntity.of(ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, e.getMessage())) .build(); } } diff --git a/src/test/java/io/apitally/spring/app/TestItem.java b/src/test/java/io/apitally/spring/app/TestItem.java index d7ef54b..e68f953 100644 --- a/src/test/java/io/apitally/spring/app/TestItem.java +++ b/src/test/java/io/apitally/spring/app/TestItem.java @@ -3,4 +3,5 @@ import jakarta.validation.constraints.Min; import jakarta.validation.constraints.Size; -public record TestItem(@Min(1) Integer id, @Size(min = 2, max = 10) String name) {} +public record TestItem( + @Min(1) Integer id, @Size(min = 2, max = 10) String name) {}