diff --git a/.github/project.yaml b/.github/project.yaml
index 7daa27c..0b40189 100644
--- a/.github/project.yaml
+++ b/.github/project.yaml
@@ -1,5 +1,5 @@
name: Quarkus Commons
release:
- current-version: "1.0.2"
- next-version: "1.0.3-SNAPSHOT"
+ current-version: "1.0.8"
+ next-version: "1.0.9-SNAPSHOT"
diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
index b32c3db..1272b20 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -4,6 +4,8 @@ on:
push:
branches:
- "main"
+ tags:
+ - '[0-9]+.[0-9]+.[0-9]+'
paths-ignore:
- '.gitattributes'
- '.gitignore'
@@ -12,6 +14,7 @@ on:
- 'docs/**'
- 'README.md'
pull_request:
+ workflow_dispatch:
env:
COMMON_MAVEN_OPTS: "-e -B --fae"
@@ -60,19 +63,24 @@ jobs:
servers: |
[{
"id": "phoenix-oss",
- "configuration": {
- "httpHeaders": {
- "property": {
- "name": "Authorization",
- "value": "token ${{ secrets.ORG_PACKAGE_WRITER_TOKEN }}"
- }
- }
- }
+ "username": "${{ vars.ORG_PACKAGE_WRITER_USERNAME }}",
+ "password": "${{ secrets.ORG_PACKAGE_WRITER_TOKEN }}"
}]
- name: Make maven wrapper executable
run: chmod +x mvnw
+ - name: Validate tag
+ if: startsWith(github.ref, 'refs/tags/')
+ run: |
+ TAG_NAME="${GITHUB_REF#refs/tags/}"
+ PROJECT_VERSION=$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout)
+
+ if [[ "$PROJECT_VERSION" != "$TAG_NAME" ]]; then
+ echo "::error::pom.xml version '$PROJECT_VERSION' does not match tag '$TAG_NAME'"
+ exit 1
+ fi
+
- name: Download dependencies
run: ./mvnw $COMMON_MAVEN_OPTS quarkus:go-offline
@@ -87,5 +95,5 @@ jobs:
run: ./mvnw $COMMON_MAVEN_OPTS org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=quarkus-commons -Dsonar.projectName='quarkus-commons' -Dsonar.coverage.jacoco.xmlReportPaths=../**/target/jacoco-report/jacoco.xml
- name: Publish jars
- if: github.ref == 'refs/heads/main'
+ if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')
run: ./mvnw $COMMON_MAVEN_OPTS deploy -Dmaven.test.skip=true -Dmaven.javadoc.skip=true
\ No newline at end of file
diff --git a/README.md b/README.md
index 6f32452..1cfb1f7 100644
--- a/README.md
+++ b/README.md
@@ -2,12 +2,12 @@ Quarkus Commons
===============
[](https://openjdk.org/projects/jdk/21/)
-[](https://sonarqube.pub.production.kvant.cloud/dashboard?id=quarkus-commons)
-[](https://sonarqube.pub.production.kvant.cloud/dashboard?id=quarkus-commons)
-[](https://sonarqube.pub.production.kvant.cloud/dashboard?id=quarkus-commons)
-[](https://sonarqube.pub.production.kvant.cloud/dashboard?id=quarkus-commons)
-[](https://sonarqube.pub.production.kvant.cloud/dashboard?id=quarkus-commons)
-[](https://sonarqube.pub.production.kvant.cloud/dashboard?id=quarkus-commons)
+[](https://sonarqube.pub.basel.kvant.cloud/dashboard?id=quarkus-commons)
+[](https://sonarqube.pub.basel.kvant.cloud/dashboard?id=quarkus-commons)
+[](https://sonarqube.pub.basel.kvant.cloud/dashboard?id=quarkus-commons)
+[](https://sonarqube.pub.basel.kvant.cloud/dashboard?id=quarkus-commons)
+[](https://sonarqube.pub.basel.kvant.cloud/dashboard?id=quarkus-commons)
+[](https://sonarqube.pub.basel.kvant.cloud/dashboard?id=quarkus-commons)
# Introduction
diff --git a/pom.xml b/pom.xml
index ba69779..3b61944 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,11 +3,12 @@
4.0.0
ch.phoenix.oss
quarkus-commons
- 1.0.2
+ 1.0.9-SNAPSHOT
pom
quarkus-audit-tools
+ quarkus-client-logger
quarkus-clock-service
quarkus-json-service
quarkus-message-digest-service
@@ -20,15 +21,15 @@
quarkus-bom
io.quarkus.platform
- 3.23.3
+ 3.25.0
3.14.0
3.5.3
- 2.44.4
- 2.66.0
+ 2.46.1
+ 2.72.0
0.8.13
- 3.3.1
+ 3.4.0
3.1.1
3.3.1
@@ -72,7 +73,7 @@
scm:git:ssh://git@git-ssh.kvant.cloud:2222/phoenix-oss/quarkus-commons.git
scm:git:ssh://git@git-ssh.kvant.cloud:2222/phoenix-oss/quarkus-commons.git
https://git.kvant.cloud/phoenix-oss/quarkus-commons.git
- 1.0.2
+ HEAD
@@ -195,7 +196,7 @@
@{project.version}
mvnw
chore: release @{releaseLabel}
- chore: prepare for next development iteration [skip ci]
+ chore: prepare for next development iteration
true
diff --git a/quarkus-audit-tools/pom.xml b/quarkus-audit-tools/pom.xml
index 9a4fc6d..1a01d07 100644
--- a/quarkus-audit-tools/pom.xml
+++ b/quarkus-audit-tools/pom.xml
@@ -5,7 +5,7 @@
ch.phoenix.oss
quarkus-commons
- 1.0.2
+ 1.0.9-SNAPSHOT
quarkus-audit-tools
@@ -51,38 +51,38 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ ${jacoco-plugin.version}
+
+
+ jacoco-check
+
+ check
+
+ test
+
+ ${project.build.directory}/jacoco-quarkus.exec
+
+
+ BUNDLE
+
+
+ INSTRUCTION
+ COVEREDRATIO
+ 1
+
+
+
+
+
+
+
+
+
+
diff --git a/quarkus-audit-tools/src/test/java/ch/phoenix/oss/quarkus/commons/audit/DefaultRevisionContextProviderTest.java b/quarkus-audit-tools/src/test/java/ch/phoenix/oss/quarkus/commons/audit/DefaultRevisionContextProviderTest.java
index 5ad9ff7..8ef3a73 100644
--- a/quarkus-audit-tools/src/test/java/ch/phoenix/oss/quarkus/commons/audit/DefaultRevisionContextProviderTest.java
+++ b/quarkus-audit-tools/src/test/java/ch/phoenix/oss/quarkus/commons/audit/DefaultRevisionContextProviderTest.java
@@ -1,7 +1,6 @@
package ch.phoenix.oss.quarkus.commons.audit;
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
-import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.mockStatic;
import io.quarkus.test.junit.QuarkusTest;
diff --git a/quarkus-audit-tools/src/test/java/ch/phoenix/oss/quarkus/commons/audit/RevisionTest.java b/quarkus-audit-tools/src/test/java/ch/phoenix/oss/quarkus/commons/audit/RevisionTest.java
index 1b08c56..d0f5d1f 100644
--- a/quarkus-audit-tools/src/test/java/ch/phoenix/oss/quarkus/commons/audit/RevisionTest.java
+++ b/quarkus-audit-tools/src/test/java/ch/phoenix/oss/quarkus/commons/audit/RevisionTest.java
@@ -1,7 +1,6 @@
package ch.phoenix.oss.quarkus.commons.audit;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.jupiter.api.Assertions.*;
import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Test;
@@ -17,12 +16,36 @@ class RevisionTest {
var r2 = new Revision();
r2.rev = 1;
- assertThat(r1).as("Revisions should be equal").isEqualTo(r2);
+ var r3 = new Revision();
+ r3.rev = 2;
+
+ assertThat(r1)
+ .as("Revisions equality should should match expected value")
+ .isEqualTo(r1)
+ .isEqualTo(r2)
+ .isNotEqualTo(r3)
+ .isNotEqualTo(new Object());
}
@Test
- void testHashCode() {}
+ void testHashCode() {
+ var r1 = new Revision();
+ r1.rev = 123;
+
+ var r2 = new Revision();
+ r2.rev = 123;
+
+ var r3 = new Revision();
+ r3.rev = 2;
+
+ assertThat(r1.hashCode()).isEqualTo(123).isEqualTo(r2.hashCode()).isNotEqualTo(r3.hashCode());
+ }
@Test
- void testToString() {}
+ void testToString() {
+ var rev = new Revision();
+ rev.rev = 1;
+
+ assertThat(rev).as("Revision's toString should match expected value").hasToString("Revision{rev=1}");
+ }
}
diff --git a/quarkus-client-logger/pom.xml b/quarkus-client-logger/pom.xml
new file mode 100644
index 0000000..3095369
--- /dev/null
+++ b/quarkus-client-logger/pom.xml
@@ -0,0 +1,65 @@
+
+
+ 4.0.0
+
+
+ ch.phoenix.oss
+ quarkus-commons
+ 1.0.9-SNAPSHOT
+
+
+ quarkus-client-logger
+ jar
+
+
+
+ io.quarkus
+ quarkus-rest-client
+
+
+ io.quarkus
+ quarkus-config-yaml
+ test
+
+
+ io.quarkus
+ quarkus-rest-jackson
+ test
+
+
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ ${jacoco-plugin.version}
+
+
+ jacoco-check
+
+ check
+
+ test
+
+ ${project.build.directory}/jacoco-quarkus.exec
+
+
+ BUNDLE
+
+
+ INSTRUCTION
+ COVEREDRATIO
+ 0.92
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/quarkus-client-logger/src/main/java/ch/phoenix/oss/quarkus/commons/client/logger/LowerCaseStringConverter.java b/quarkus-client-logger/src/main/java/ch/phoenix/oss/quarkus/commons/client/logger/LowerCaseStringConverter.java
new file mode 100644
index 0000000..498e318
--- /dev/null
+++ b/quarkus-client-logger/src/main/java/ch/phoenix/oss/quarkus/commons/client/logger/LowerCaseStringConverter.java
@@ -0,0 +1,10 @@
+package ch.phoenix.oss.quarkus.commons.client.logger;
+
+import org.eclipse.microprofile.config.spi.Converter;
+
+public class LowerCaseStringConverter implements Converter {
+ @Override
+ public String convert(String value) throws IllegalArgumentException, NullPointerException {
+ return value.toLowerCase();
+ }
+}
diff --git a/quarkus-client-logger/src/main/java/ch/phoenix/oss/quarkus/commons/client/logger/RedactingClientLogger.java b/quarkus-client-logger/src/main/java/ch/phoenix/oss/quarkus/commons/client/logger/RedactingClientLogger.java
new file mode 100644
index 0000000..cb2b63b
--- /dev/null
+++ b/quarkus-client-logger/src/main/java/ch/phoenix/oss/quarkus/commons/client/logger/RedactingClientLogger.java
@@ -0,0 +1,119 @@
+package ch.phoenix.oss.quarkus.commons.client.logger;
+
+import io.vertx.core.Handler;
+import io.vertx.core.MultiMap;
+import io.vertx.core.buffer.Buffer;
+import io.vertx.core.http.HttpClientRequest;
+import io.vertx.core.http.HttpClientResponse;
+import jakarta.enterprise.context.Dependent;
+import jakarta.inject.Inject;
+import java.util.Map;
+import java.util.Set;
+import org.jboss.logging.Logger;
+import org.jboss.resteasy.reactive.client.api.ClientLogger;
+
+/**
+ * This is based on org.jboss.resteasy.reactive.client.logging.DefaultClientLogger,
+ * with the only change being that headers are redacted based on the Set provided
+ * by the configuration.
+ */
+@Dependent
+public class RedactingClientLogger implements ClientLogger {
+
+ private static final Logger log = Logger.getLogger(RedactingClientLogger.class);
+
+ private static final String REDACTED_VALUE = "*****";
+
+ private final Set redactedHeaders;
+
+ private int bodySize;
+
+ @Inject
+ public RedactingClientLogger(RedactingClientLoggerConfiguration configuration) {
+ this.redactedHeaders = configuration
+ .headers()
+ .redact()
+ .orElse(RedactingClientLoggerConfiguration.Headers.DEFAULT_REDACTED_HEADERS);
+ }
+
+ @Override
+ public void setBodySize(int bodySize) {
+ this.bodySize = bodySize;
+ }
+
+ @Override
+ public void logResponse(HttpClientResponse response, boolean redirect) {
+ if (!log.isDebugEnabled()) {
+ return;
+ }
+
+ //noinspection Convert2Lambda
+ response.bodyHandler(new Handler<>() {
+ @Override
+ public void handle(Buffer body) {
+ log.debugf(
+ "%s: %s %s, Status[%d %s], Headers[%s], Body:\n%s",
+ redirect ? "Redirect" : "Response",
+ response.request().getMethod(),
+ response.request().absoluteURI(),
+ response.statusCode(),
+ response.statusMessage(),
+ asString(response.headers()),
+ bodyToString(body));
+ }
+ });
+ }
+
+ @Override
+ public void logRequest(HttpClientRequest request, Buffer body, boolean omitBody) {
+ if (!log.isDebugEnabled()) {
+ return;
+ }
+ if (omitBody) {
+ log.debugf(
+ "Request: %s %s Headers[%s], Body omitted",
+ request.getMethod(), request.absoluteURI(), asString(request.headers()));
+ } else if (body == null || body.length() == 0) {
+ log.debugf(
+ "Request: %s %s Headers[%s], Empty body",
+ request.getMethod(), request.absoluteURI(), asString(request.headers()));
+ } else {
+ log.debugf(
+ "Request: %s %s Headers[%s], Body:\n%s",
+ request.getMethod(), request.absoluteURI(), asString(request.headers()), bodyToString(body));
+ }
+ }
+
+ private String bodyToString(Buffer body) {
+ if (body == null) {
+ return "";
+ } else if (bodySize <= 0) {
+ return body.toString();
+ } else {
+ String bodyAsString = body.toString();
+ return bodyAsString.substring(0, Math.min(bodySize, bodyAsString.length()));
+ }
+ }
+
+ private String asString(MultiMap headers) {
+ if (headers.isEmpty()) {
+ return "";
+ }
+ StringBuilder sb = new StringBuilder((headers.size() * (6 + 1 + 6))
+ + (headers.size() - 1)); // this is a very rough estimate of a result like 'key1=value1 key2=value2'
+ boolean isFirst = true;
+ for (Map.Entry entry : headers) {
+ if (isFirst) {
+ isFirst = false;
+ } else {
+ sb.append(' ');
+ }
+
+ var key = entry.getKey();
+ var value = redactedHeaders.contains(key.toLowerCase()) ? REDACTED_VALUE : entry.getValue();
+
+ sb.append(key).append('=').append(value);
+ }
+ return sb.toString();
+ }
+}
diff --git a/quarkus-client-logger/src/main/java/ch/phoenix/oss/quarkus/commons/client/logger/RedactingClientLoggerConfiguration.java b/quarkus-client-logger/src/main/java/ch/phoenix/oss/quarkus/commons/client/logger/RedactingClientLoggerConfiguration.java
new file mode 100644
index 0000000..24fa05f
--- /dev/null
+++ b/quarkus-client-logger/src/main/java/ch/phoenix/oss/quarkus/commons/client/logger/RedactingClientLoggerConfiguration.java
@@ -0,0 +1,20 @@
+package ch.phoenix.oss.quarkus.commons.client.logger;
+
+import io.smallrye.config.ConfigMapping;
+import io.smallrye.config.WithConverter;
+import jakarta.ws.rs.core.HttpHeaders;
+import java.util.Optional;
+import java.util.Set;
+
+@ConfigMapping(prefix = "phoenix.client-logger")
+public interface RedactingClientLoggerConfiguration {
+
+ Headers headers();
+
+ interface Headers {
+
+ Set DEFAULT_REDACTED_HEADERS = Set.of(HttpHeaders.AUTHORIZATION.toLowerCase());
+
+ Optional> redact();
+ }
+}
diff --git a/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/InfoLevelProfile.java b/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/InfoLevelProfile.java
new file mode 100644
index 0000000..35acb14
--- /dev/null
+++ b/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/InfoLevelProfile.java
@@ -0,0 +1,12 @@
+package ch.phoenix.oss.quarkus.commons.client.logger;
+
+import io.quarkus.test.junit.QuarkusTestProfile;
+import java.util.Map;
+
+public class InfoLevelProfile implements QuarkusTestProfile {
+
+ @Override
+ public Map getConfigOverrides() {
+ return Map.of("quarkus.log.category.\"ch.phoenix.oss.quarkus.commons.client.logger\".level", "INFO");
+ }
+}
diff --git a/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/InfoLevelTest.java b/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/InfoLevelTest.java
new file mode 100644
index 0000000..c6b27ef
--- /dev/null
+++ b/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/InfoLevelTest.java
@@ -0,0 +1,44 @@
+package ch.phoenix.oss.quarkus.commons.client.logger;
+
+import io.quarkus.rest.client.reactive.QuarkusRestClientBuilder;
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
+import jakarta.inject.Inject;
+import java.net.URI;
+import java.util.Optional;
+import org.eclipse.microprofile.rest.client.inject.RestClient;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
+@TestProfile(InfoLevelProfile.class)
+class InfoLevelTest {
+
+ @Inject
+ @RestClient
+ TestClient injectedClient;
+
+ TestClient builtClient = QuarkusRestClientBuilder.newBuilder()
+ .clientLogger(new RedactingClientLogger(() -> Optional::empty))
+ .baseUri(URI.create("http://localhost:8087"))
+ .build(TestClient.class);
+
+ @Test
+ void getWithInjectedClient() {
+ injectedClient.get("this will be redacted", "5c0d8e45-e402-4b71-8f84-24cc0cfd7eec", "also redacted");
+ }
+
+ @Test
+ void getWithBuiltClientAndEmptyConfig() {
+ builtClient.get("this will be redacted", "5c0d8e45-e402-4b71-8f84-24cc0cfd7eec", "not redacted");
+ }
+
+ @Test
+ void postWithInjectedClient() {
+ injectedClient.post("this will be redacted", "5c0d8e45-e402-4b71-8f84-24cc0cfd7eec", "also redacted", "body");
+ }
+
+ @Test
+ void postWithBuiltClientAndEmptyConfig() {
+ builtClient.post("this will be redacted", "5c0d8e45-e402-4b71-8f84-24cc0cfd7eec", "not redacted", "");
+ }
+}
diff --git a/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/RedactingClientLoggerTest.java b/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/RedactingClientLoggerTest.java
new file mode 100644
index 0000000..01e9389
--- /dev/null
+++ b/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/RedactingClientLoggerTest.java
@@ -0,0 +1,47 @@
+package ch.phoenix.oss.quarkus.commons.client.logger;
+
+import io.quarkus.rest.client.reactive.QuarkusRestClientBuilder;
+import io.quarkus.test.junit.QuarkusTest;
+import jakarta.inject.Inject;
+import java.net.URI;
+import java.util.Optional;
+import org.eclipse.microprofile.rest.client.inject.RestClient;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
+class RedactingClientLoggerTest {
+
+ @Inject
+ @RestClient
+ TestClient injectedClient;
+
+ TestClient builtClient = QuarkusRestClientBuilder.newBuilder()
+ .clientLogger(new RedactingClientLogger(() -> Optional::empty))
+ .baseUri(URI.create("http://localhost:8087"))
+ .build(TestClient.class);
+
+ @Test
+ void getWithInjectedClient() {
+ injectedClient.get("this will be redacted", "5c0d8e45-e402-4b71-8f84-24cc0cfd7eec", "also redacted");
+ }
+
+ @Test
+ void getWithBuiltClientAndEmptyConfig() {
+ builtClient.get("this will be redacted", "5c0d8e45-e402-4b71-8f84-24cc0cfd7eec", "not redacted");
+ }
+
+ @Test
+ void postWithInjectedClient() {
+ injectedClient.post("this will be redacted", "5c0d8e45-e402-4b71-8f84-24cc0cfd7eec", "also redacted", "body");
+ }
+
+ @Test
+ void postWithInjectedClientAndNullBody() {
+ injectedClient.post("this will be redacted", "5c0d8e45-e402-4b71-8f84-24cc0cfd7eec", "also redacted", null);
+ }
+
+ @Test
+ void postWithBuiltClientAndEmptyConfig() {
+ builtClient.post("this will be redacted", "5c0d8e45-e402-4b71-8f84-24cc0cfd7eec", "not redacted", "");
+ }
+}
diff --git a/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/ScopeNoneProfile.java b/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/ScopeNoneProfile.java
new file mode 100644
index 0000000..42daa28
--- /dev/null
+++ b/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/ScopeNoneProfile.java
@@ -0,0 +1,12 @@
+package ch.phoenix.oss.quarkus.commons.client.logger;
+
+import io.quarkus.test.junit.QuarkusTestProfile;
+import java.util.Map;
+
+public class ScopeNoneProfile implements QuarkusTestProfile {
+
+ @Override
+ public Map getConfigOverrides() {
+ return Map.of("quarkus.rest-client.logging.scope", "none");
+ }
+}
diff --git a/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/ScopeNoneTest.java b/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/ScopeNoneTest.java
new file mode 100644
index 0000000..14538b2
--- /dev/null
+++ b/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/ScopeNoneTest.java
@@ -0,0 +1,44 @@
+package ch.phoenix.oss.quarkus.commons.client.logger;
+
+import io.quarkus.rest.client.reactive.QuarkusRestClientBuilder;
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
+import jakarta.inject.Inject;
+import java.net.URI;
+import java.util.Optional;
+import org.eclipse.microprofile.rest.client.inject.RestClient;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
+@TestProfile(ScopeNoneProfile.class)
+class ScopeNoneTest {
+
+ @Inject
+ @RestClient
+ TestClient injectedClient;
+
+ TestClient builtClient = QuarkusRestClientBuilder.newBuilder()
+ .clientLogger(new RedactingClientLogger(() -> Optional::empty))
+ .baseUri(URI.create("http://localhost:8087"))
+ .build(TestClient.class);
+
+ @Test
+ void getWithInjectedClient() {
+ injectedClient.get("this will be redacted", "5c0d8e45-e402-4b71-8f84-24cc0cfd7eec", "also redacted");
+ }
+
+ @Test
+ void getWithBuiltClientAndEmptyConfig() {
+ builtClient.get("this will be redacted", "5c0d8e45-e402-4b71-8f84-24cc0cfd7eec", "not redacted");
+ }
+
+ @Test
+ void postWithInjectedClient() {
+ injectedClient.post("this will be redacted", "5c0d8e45-e402-4b71-8f84-24cc0cfd7eec", "also redacted", "body");
+ }
+
+ @Test
+ void postWithBuiltClientAndEmptyConfig() {
+ builtClient.post("this will be redacted", "5c0d8e45-e402-4b71-8f84-24cc0cfd7eec", "not redacted", "");
+ }
+}
diff --git a/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/TestClient.java b/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/TestClient.java
new file mode 100644
index 0000000..79769ac
--- /dev/null
+++ b/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/TestClient.java
@@ -0,0 +1,28 @@
+package ch.phoenix.oss.quarkus.commons.client.logger;
+
+import jakarta.ws.rs.*;
+import jakarta.ws.rs.core.MediaType;
+import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
+
+@SuppressWarnings("UastIncorrectHttpHeaderInspection")
+@RegisterRestClient(configKey = "test")
+public interface TestClient {
+
+ @GET
+ @Path("/")
+ @Produces(MediaType.TEXT_PLAIN)
+ String get(
+ @HeaderParam("Authorization") String authorization,
+ @HeaderParam("X-Request-ID") String requestId,
+ @HeaderParam("X-Something-Else") String somethingElse);
+
+ @POST
+ @Path("/")
+ @Consumes(MediaType.TEXT_PLAIN)
+ @Produces(MediaType.TEXT_PLAIN)
+ String post(
+ @HeaderParam("Authorization") String authorization,
+ @HeaderParam("X-Request-ID") String requestId,
+ @HeaderParam("X-Something-Else") String somethingElse,
+ String body);
+}
diff --git a/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/TestResource.java b/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/TestResource.java
new file mode 100644
index 0000000..c83bdd0
--- /dev/null
+++ b/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/TestResource.java
@@ -0,0 +1,21 @@
+package ch.phoenix.oss.quarkus.commons.client.logger;
+
+import jakarta.ws.rs.*;
+import jakarta.ws.rs.core.MediaType;
+
+@Path("/")
+public class TestResource {
+
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public String get() {
+ return "get";
+ }
+
+ @POST
+ @Consumes(MediaType.TEXT_PLAIN)
+ @Produces(MediaType.TEXT_PLAIN)
+ public String post(String body) {
+ return body;
+ }
+}
diff --git a/quarkus-client-logger/src/test/resources/application.yaml b/quarkus-client-logger/src/test/resources/application.yaml
new file mode 100644
index 0000000..a02f41d
--- /dev/null
+++ b/quarkus-client-logger/src/test/resources/application.yaml
@@ -0,0 +1,20 @@
+quarkus:
+ http:
+ test-port: 8087
+ rest-client:
+ logging:
+ scope: request-response
+ body-limit: 10000
+ test:
+ url: http://localhost:${quarkus.http.test-port}
+ log:
+ category:
+ "ch.phoenix.oss.quarkus.commons.client.logger":
+ level: DEBUG
+
+phoenix:
+ client-logger:
+ headers:
+ redact:
+ - AUTHORIZATION
+ - X-SOMETHING-ELSE
diff --git a/quarkus-clock-service/pom.xml b/quarkus-clock-service/pom.xml
index 6a39da6..aaab0c1 100644
--- a/quarkus-clock-service/pom.xml
+++ b/quarkus-clock-service/pom.xml
@@ -5,7 +5,7 @@
ch.phoenix.oss
quarkus-commons
- 1.0.2
+ 1.0.9-SNAPSHOT
quarkus-clock-service
diff --git a/quarkus-json-service/pom.xml b/quarkus-json-service/pom.xml
index a4d7197..717c39f 100644
--- a/quarkus-json-service/pom.xml
+++ b/quarkus-json-service/pom.xml
@@ -5,7 +5,7 @@
ch.phoenix.oss
quarkus-commons
- 1.0.2
+ 1.0.9-SNAPSHOT
quarkus-json-service
diff --git a/quarkus-message-digest-service/pom.xml b/quarkus-message-digest-service/pom.xml
index 3a71d83..c5d2c2d 100644
--- a/quarkus-message-digest-service/pom.xml
+++ b/quarkus-message-digest-service/pom.xml
@@ -5,7 +5,7 @@
ch.phoenix.oss
quarkus-commons
- 1.0.2
+ 1.0.9-SNAPSHOT
quarkus-message-digest-service
diff --git a/quarkus-random-number-generator/pom.xml b/quarkus-random-number-generator/pom.xml
index 96d5c87..940f965 100644
--- a/quarkus-random-number-generator/pom.xml
+++ b/quarkus-random-number-generator/pom.xml
@@ -5,7 +5,7 @@
ch.phoenix.oss
quarkus-commons
- 1.0.2
+ 1.0.9-SNAPSHOT
quarkus-random-number-generator
diff --git a/quarkus-tracing-service/pom.xml b/quarkus-tracing-service/pom.xml
index e052fd3..214e936 100644
--- a/quarkus-tracing-service/pom.xml
+++ b/quarkus-tracing-service/pom.xml
@@ -5,7 +5,7 @@
ch.phoenix.oss
quarkus-commons
- 1.0.2
+ 1.0.9-SNAPSHOT
quarkus-tracing-service
@@ -41,4 +41,38 @@
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ ${jacoco-plugin.version}
+
+
+ jacoco-check
+
+ check
+
+ test
+
+ ${project.build.directory}/jacoco-quarkus.exec
+
+
+ BUNDLE
+
+
+ INSTRUCTION
+ COVEREDRATIO
+ 0.95
+
+
+
+
+
+
+
+
+
+
+
diff --git a/quarkus-tracing-service/src/main/java/ch/phoenix/oss/quarkus/commons/tracing/TracingConfiguration.java b/quarkus-tracing-service/src/main/java/ch/phoenix/oss/quarkus/commons/tracing/TracingConfiguration.java
index 46e2854..1093348 100644
--- a/quarkus-tracing-service/src/main/java/ch/phoenix/oss/quarkus/commons/tracing/TracingConfiguration.java
+++ b/quarkus-tracing-service/src/main/java/ch/phoenix/oss/quarkus/commons/tracing/TracingConfiguration.java
@@ -3,6 +3,7 @@ package ch.phoenix.oss.quarkus.commons.tracing;
import io.smallrye.config.ConfigMapping;
import io.smallrye.config.WithConverter;
import io.smallrye.config.WithDefault;
+import jakarta.ws.rs.core.HttpHeaders;
import java.util.Optional;
import java.util.Set;
@@ -17,6 +18,14 @@ public interface TracingConfiguration {
interface Headers {
+ Set DEFAULT_REDACTED = Set.of(HttpHeaders.AUTHORIZATION.toLowerCase());
+
+ /**
+ * Optional set of headers to redact when tracing. By default, redacts
+ * the 'Authorization' header.
+ *
+ * @return the set of headers to be redacted
+ */
Optional> redact();
}
@@ -31,9 +40,18 @@ public interface TracingConfiguration {
Query query();
interface Query {
+
+ Set DEFAULT_REDACTED = Set.of("access_token", "refresh_token", "apikey");
+
@WithDefault("false")
boolean includeRaw();
+ /**
+ * Optional set of query params to redact when tracing. By default, redacts
+ * the following params: 'access_token', 'refresh_token' and 'apikey'.
+ *
+ * @return the set of query params to be redacted
+ */
Optional> redact();
}
}
diff --git a/quarkus-tracing-service/src/main/java/ch/phoenix/oss/quarkus/commons/tracing/TracingRequestFilter.java b/quarkus-tracing-service/src/main/java/ch/phoenix/oss/quarkus/commons/tracing/TracingRequestFilter.java
index 4a1cbd4..7bb2427 100644
--- a/quarkus-tracing-service/src/main/java/ch/phoenix/oss/quarkus/commons/tracing/TracingRequestFilter.java
+++ b/quarkus-tracing-service/src/main/java/ch/phoenix/oss/quarkus/commons/tracing/TracingRequestFilter.java
@@ -9,12 +9,13 @@ import jakarta.ws.rs.Path;
import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.container.ResourceInfo;
import java.util.List;
-import java.util.Set;
import org.jboss.resteasy.reactive.server.ServerRequestFilter;
@Unremovable
public class TracingRequestFilter {
+ private static final String REDACTED_VALUE = "********";
+
private final RoutingContext routingContext;
private final TracingService tracingService;
private final SecurityIdentity securityIdentity;
@@ -57,24 +58,38 @@ public class TracingRequestFilter {
TracingConstants.REQUEST_PATH_RAW, uriInfo.getAbsolutePath().getRawPath());
}
+ var redactedHeaders = configuration
+ .requestFilter()
+ .headers()
+ .redact()
+ .orElse(TracingConfiguration.RequestFilterConfiguration.Headers.DEFAULT_REDACTED);
+
requestContext.getHeaders().forEach((key, value) -> {
var lowerCaseKey = key.toLowerCase();
var property = TracingConstants.REQUEST_HEADERS + '.' + lowerCaseKey;
- if (configuration
- .requestFilter()
- .headers()
- .redact()
- .orElse(Set.of())
- .contains(lowerCaseKey)) {
- tracingService.trace(property, "********");
+ if (redactedHeaders.contains(lowerCaseKey)) {
+ tracingService.trace(property, REDACTED_VALUE);
} else {
tracingService.trace(property, joinStrings(value));
}
});
- uriInfo.getQueryParameters()
- .forEach((key, value) ->
- tracingService.trace(TracingConstants.REQUEST_QUERY_PARAMS + '.' + key, joinStrings(value)));
+ var redactedQueryParams = configuration
+ .requestFilter()
+ .query()
+ .redact()
+ .orElse(TracingConfiguration.RequestFilterConfiguration.Query.DEFAULT_REDACTED);
+
+ uriInfo.getQueryParameters().forEach((key, value) -> {
+ var lowerCaseKey = key.toLowerCase();
+ var property = TracingConstants.REQUEST_QUERY_PARAMS + '.' + lowerCaseKey;
+
+ if (redactedQueryParams.contains(lowerCaseKey)) {
+ tracingService.trace(property, REDACTED_VALUE);
+ } else {
+ tracingService.trace(property, joinStrings(value));
+ }
+ });
if (configuration.requestFilter().query().includeRaw()) {
var rawQuery = uriInfo.getRequestUri().getRawQuery();
@@ -87,10 +102,7 @@ public class TracingRequestFilter {
TracingConstants.REQUEST_CLIENT_IP,
routingContext.request().connection().remoteAddress(true).hostAddress());
- if (Log.isTraceEnabled()) {
- Log.tracef(
- "Incoming request: %s %s", method, uriInfo.getAbsolutePath().getRawPath());
- }
+ Log.debugf("Incoming request: %s %s", method, uriInfo.getAbsolutePath().getRawPath());
}
private static String joinStrings(List value) {
diff --git a/quarkus-tracing-service/src/main/java/ch/phoenix/oss/quarkus/commons/tracing/TracingService.java b/quarkus-tracing-service/src/main/java/ch/phoenix/oss/quarkus/commons/tracing/TracingService.java
index 2b1ac38..812867d 100644
--- a/quarkus-tracing-service/src/main/java/ch/phoenix/oss/quarkus/commons/tracing/TracingService.java
+++ b/quarkus-tracing-service/src/main/java/ch/phoenix/oss/quarkus/commons/tracing/TracingService.java
@@ -8,7 +8,7 @@ public interface TracingService {
String getActor();
- String getRequestPath();
+ String getRequestPathRaw();
String getRequestMethod();
diff --git a/quarkus-tracing-service/src/main/java/ch/phoenix/oss/quarkus/commons/tracing/TracingServiceImpl.java b/quarkus-tracing-service/src/main/java/ch/phoenix/oss/quarkus/commons/tracing/TracingServiceImpl.java
index b5f295b..d46f684 100644
--- a/quarkus-tracing-service/src/main/java/ch/phoenix/oss/quarkus/commons/tracing/TracingServiceImpl.java
+++ b/quarkus-tracing-service/src/main/java/ch/phoenix/oss/quarkus/commons/tracing/TracingServiceImpl.java
@@ -33,7 +33,7 @@ class TracingServiceImpl implements TracingService {
}
@Override
- public String getRequestPath() {
+ public String getRequestPathRaw() {
return (String) MDC.get(TracingConstants.REQUEST_PATH_RAW);
}
diff --git a/quarkus-tracing-service/src/test/java/ch/phoenix/oss/quarkus/commons/tracing/ActorTest.java b/quarkus-tracing-service/src/test/java/ch/phoenix/oss/quarkus/commons/tracing/ActorTest.java
index 2190561..8ab52eb 100644
--- a/quarkus-tracing-service/src/test/java/ch/phoenix/oss/quarkus/commons/tracing/ActorTest.java
+++ b/quarkus-tracing-service/src/test/java/ch/phoenix/oss/quarkus/commons/tracing/ActorTest.java
@@ -12,7 +12,7 @@ import io.restassured.http.ContentType;
import org.junit.jupiter.api.Test;
@QuarkusTest
-public class ActorTest {
+class ActorTest {
@InjectSpy
TracingService tracingService;
@@ -34,7 +34,7 @@ public class ActorTest {
verify(tracingService).trace("request.route", route);
verify(tracingService).trace("request.headers.accept", "text/plain");
verify(tracingService).trace("request.headers.accept-encoding", "gzip,deflate");
- verify(tracingService).trace("request.headers.authorization", "Basic am9uOmRvZQ==");
+ verify(tracingService).trace("request.headers.authorization", "********");
verify(tracingService).trace("request.headers.connection", "Keep-Alive");
verify(tracingService).trace(eq("request.headers.host"), startsWith("localhost:"));
verify(tracingService).trace(eq("request.headers.user-agent"), startsWith("Apache-HttpClient"));
diff --git a/quarkus-tracing-service/src/test/java/ch/phoenix/oss/quarkus/commons/tracing/QueryParamTest.java b/quarkus-tracing-service/src/test/java/ch/phoenix/oss/quarkus/commons/tracing/QueryParamTest.java
new file mode 100644
index 0000000..10b3894
--- /dev/null
+++ b/quarkus-tracing-service/src/test/java/ch/phoenix/oss/quarkus/commons/tracing/QueryParamTest.java
@@ -0,0 +1,54 @@
+package ch.phoenix.oss.quarkus.commons.tracing;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.startsWith;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.mockito.InjectSpy;
+import io.restassured.RestAssured;
+import io.restassured.http.ContentType;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
+class QueryParamTest {
+
+ @InjectSpy
+ TracingService tracingService;
+
+ @Test
+ void traceQueryParams() {
+ var route = "/authenticated";
+ RestAssured.given()
+ .auth()
+ .basic("jon", "doe")
+ .accept(ContentType.TEXT)
+ .header("X-SOMETHING-ELSE", "whatever")
+ .queryParam("access_token", "api123")
+ .queryParam("refresh_token", "refresh123")
+ .queryParam("apikey", "apikey123")
+ .queryParam("grant_type", "authorization_code")
+ .when()
+ .get(route)
+ .then()
+ .statusCode(200);
+
+ verify(tracingService).trace("actor", "jon");
+ verify(tracingService).trace("request.method", "GET");
+ verify(tracingService).trace("request.route", route);
+ verify(tracingService).trace("request.headers.accept", "text/plain");
+ verify(tracingService).trace("request.headers.accept-encoding", "gzip,deflate");
+ verify(tracingService).trace("request.headers.authorization", "********");
+ verify(tracingService).trace("request.headers.connection", "Keep-Alive");
+ verify(tracingService).trace(eq("request.headers.host"), startsWith("localhost:"));
+ verify(tracingService).trace(eq("request.headers.user-agent"), startsWith("Apache-HttpClient"));
+ verify(tracingService).trace("request.headers.x-something-else", "whatever");
+ verify(tracingService).trace("request.query.params.access_token", "********");
+ verify(tracingService).trace("request.query.params.refresh_token", "********");
+ verify(tracingService).trace("request.query.params.apikey", "********");
+ verify(tracingService).trace("request.query.params.grant_type", "authorization_code");
+ verify(tracingService).trace("request.client.ip", "127.0.0.1");
+ verifyNoMoreInteractions(tracingService);
+ }
+}
diff --git a/quarkus-tracing-service/src/test/java/ch/phoenix/oss/quarkus/commons/tracing/RawPathTest.java b/quarkus-tracing-service/src/test/java/ch/phoenix/oss/quarkus/commons/tracing/RawPathTest.java
index 96d8956..e3579ba 100644
--- a/quarkus-tracing-service/src/test/java/ch/phoenix/oss/quarkus/commons/tracing/RawPathTest.java
+++ b/quarkus-tracing-service/src/test/java/ch/phoenix/oss/quarkus/commons/tracing/RawPathTest.java
@@ -14,7 +14,7 @@ import org.junit.jupiter.api.Test;
@QuarkusTest
@TestProfile(Test2Profile.class)
-public class RawPathTest {
+class RawPathTest {
@InjectSpy
TracingService tracingService;
diff --git a/quarkus-tracing-service/src/test/java/ch/phoenix/oss/quarkus/commons/tracing/RedactedTest.java b/quarkus-tracing-service/src/test/java/ch/phoenix/oss/quarkus/commons/tracing/RedactedTest.java
new file mode 100644
index 0000000..c928917
--- /dev/null
+++ b/quarkus-tracing-service/src/test/java/ch/phoenix/oss/quarkus/commons/tracing/RedactedTest.java
@@ -0,0 +1,61 @@
+package ch.phoenix.oss.quarkus.commons.tracing;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.startsWith;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
+import io.quarkus.test.junit.mockito.InjectSpy;
+import io.restassured.RestAssured;
+import io.restassured.http.ContentType;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
+@TestProfile(Test2Profile.class)
+class RedactedTest {
+
+ @InjectSpy
+ TracingService tracingService;
+
+ @Test
+ void traceRedactedValues() {
+ var route = "/authenticated";
+ RestAssured.given()
+ .auth()
+ .basic("jon", "doe")
+ .accept(ContentType.TEXT)
+ .header("X-SOMETHING-ELSE", "whatever")
+ .queryParam("access_token", "api123")
+ .queryParam("refresh_token", "refresh123")
+ .queryParam("apikey", "apikey123")
+ .queryParam("grant_type", "authorization_code")
+ .when()
+ .get(route)
+ .then()
+ .statusCode(200);
+
+ verify(tracingService).trace("actor", "jon");
+ verify(tracingService).trace("request.method", "GET");
+ verify(tracingService).trace("request.route", route);
+ verify(tracingService).trace("request.path.raw", route);
+ verify(tracingService).trace("request.headers.accept", "text/plain");
+ verify(tracingService).trace("request.headers.accept-encoding", "gzip,deflate");
+ verify(tracingService).trace("request.headers.authorization", "********");
+ verify(tracingService).trace("request.headers.connection", "Keep-Alive");
+ verify(tracingService).trace(eq("request.headers.host"), startsWith("localhost:"));
+ verify(tracingService).trace(eq("request.headers.user-agent"), startsWith("Apache-HttpClient"));
+ verify(tracingService).trace("request.headers.x-something-else", "********");
+ verify(tracingService).trace("request.query.params.access_token", "********");
+ verify(tracingService).trace("request.query.params.refresh_token", "refresh123");
+ verify(tracingService).trace("request.query.params.apikey", "apikey123");
+ verify(tracingService).trace("request.query.params.grant_type", "authorization_code");
+ verify(tracingService)
+ .trace(
+ "request.query.raw",
+ "access_token=api123&refresh_token=refresh123&apikey=apikey123&grant_type=authorization_code");
+ verify(tracingService).trace("request.client.ip", "127.0.0.1");
+ verifyNoMoreInteractions(tracingService);
+ }
+}
diff --git a/quarkus-tracing-service/src/test/java/ch/phoenix/oss/quarkus/commons/tracing/RoutePatternTest.java b/quarkus-tracing-service/src/test/java/ch/phoenix/oss/quarkus/commons/tracing/RoutePatternTest.java
index 11f1689..156c0a4 100644
--- a/quarkus-tracing-service/src/test/java/ch/phoenix/oss/quarkus/commons/tracing/RoutePatternTest.java
+++ b/quarkus-tracing-service/src/test/java/ch/phoenix/oss/quarkus/commons/tracing/RoutePatternTest.java
@@ -1,5 +1,6 @@
package ch.phoenix.oss.quarkus.commons.tracing;
+import static org.junit.jupiter.params.provider.Arguments.arguments;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.startsWith;
import static org.mockito.Mockito.verify;
@@ -10,7 +11,11 @@ import io.quarkus.test.junit.mockito.InjectSpy;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import java.util.Map;
+import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
@QuarkusTest
class RoutePatternTest {
@@ -18,12 +23,46 @@ class RoutePatternTest {
@InjectSpy
TracingService tracingService;
- @Test
- void getBlankResource() {
- var route = "/";
- RestAssured.given().accept(ContentType.TEXT).when().get(route).then().statusCode(200);
+ static Stream get() {
+ return Stream.of(
+ arguments("/", Map.of()),
+ arguments("/leading-and-no-trailing", Map.of()),
+ arguments("/leading/{param}/{param2}", Map.of("param", "1", "param2", "2")),
+ arguments("/{param}/{param2}/trailing", Map.of("param", "1", "param2", "2")),
+ arguments("/leading-and-no-trailing/{param}", Map.of("param", "1")),
+ arguments("/leading-and-no-trailing/{param}/{param2}", Map.of("param", "1", "param2", "2")),
+ arguments("/leading-and-trailing", Map.of()),
+ arguments("/leading-and-trailing/{param}", Map.of("param", "1")),
+ arguments("/leading-and-trailing/{param}/{param2}", Map.of("param", "1", "param2", "2")),
+ arguments("/no-leading-and-no-trailing", Map.of()),
+ arguments("/no-leading-and-no-trailing/{param}", Map.of("param", "1")),
+ arguments("/no-leading-and-no-trailing/{param}/{param2}", Map.of("param", "1", "param2", "2")),
+ arguments("/no-leading-and-trailing", Map.of()),
+ arguments("/no-leading-and-trailing/{param}", Map.of("param", "1")),
+ arguments("/no-leading-and-trailing/{param}/{param2}", Map.of("param", "1", "param2", "2")));
+ }
- verifyGetTracing(route, Map.of());
+ @MethodSource
+ @ParameterizedTest
+ void get(String route, Map pathParams) {
+ RestAssured.given()
+ .accept(ContentType.TEXT)
+ .when()
+ .get(route, pathParams)
+ .then()
+ .statusCode(200);
+
+ verify(tracingService).trace("actor", "anonymous");
+ verify(tracingService).trace("request.method", "GET");
+ verify(tracingService).trace("request.route", route);
+ pathParams.forEach((key, value) -> verify(tracingService).trace("request.path.params." + key, value));
+ verify(tracingService).trace("request.headers.accept", "text/plain");
+ verify(tracingService).trace("request.headers.accept-encoding", "gzip,deflate");
+ verify(tracingService).trace("request.headers.connection", "Keep-Alive");
+ verify(tracingService).trace(eq("request.headers.host"), startsWith("localhost:"));
+ verify(tracingService).trace(eq("request.headers.user-agent"), startsWith("Apache-HttpClient"));
+ verify(tracingService).trace("request.client.ip", "127.0.0.1");
+ verifyNoMoreInteractions(tracingService);
}
@Test
@@ -45,160 +84,4 @@ class RoutePatternTest {
verify(tracingService).trace("request.client.ip", "127.0.0.1");
verifyNoMoreInteractions(tracingService);
}
-
- @Test
- void getLeadingResource() {
- var route = "/leading/{id}/{anotherId}";
- RestAssured.given()
- .accept(ContentType.TEXT)
- .when()
- .get(route, 1, 2)
- .then()
- .statusCode(200);
-
- verifyGetTracing(route, Map.of("id", "1", "anotherId", "2"));
- }
-
- @Test
- void getTrailingResource() {
- var route = "/{id}/{anotherId}/trailing";
- RestAssured.given()
- .accept(ContentType.TEXT)
- .when()
- .get(route, 1, 2)
- .then()
- .statusCode(200);
-
- verifyGetTracing(route, Map.of("id", "1", "anotherId", "2"));
- }
-
- @Test
- void getLeadingAndNoTrailingResource() {
- var route = "/leading-and-no-trailing";
- RestAssured.given().accept(ContentType.TEXT).when().get(route).then().statusCode(200);
-
- verifyGetTracing(route, Map.of());
- }
-
- @Test
- void getLeadingAndNoTrailingWithSingleParamResource() {
- var route = "/leading-and-no-trailing/{param}";
- RestAssured.given().accept(ContentType.TEXT).when().get(route, 1).then().statusCode(200);
-
- verifyGetTracing(route, Map.of("param", "1"));
- }
-
- @Test
- void getLeadingAndNoTrailingWithMultiParamResource() {
- var route = "/leading-and-no-trailing/{param}/{param2}";
- RestAssured.given()
- .accept(ContentType.TEXT)
- .when()
- .get(route, 1, 2)
- .then()
- .statusCode(200);
-
- verifyGetTracing(route, Map.of("param", "1", "param2", "2"));
- }
-
- @Test
- void getLeadingAndTrailingResource() {
- var route = "/leading-and-trailing";
- RestAssured.given().accept(ContentType.TEXT).when().get(route).then().statusCode(200);
-
- verifyGetTracing(route, Map.of());
- }
-
- @Test
- void getLeadingAndTrailingWithSingleParamResource() {
- var route = "/leading-and-trailing/{param}";
- RestAssured.given().accept(ContentType.TEXT).when().get(route, 1).then().statusCode(200);
-
- verifyGetTracing(route, Map.of("param", "1"));
- }
-
- @Test
- void getLeadingAndTrailingWithMultiParamResource() {
- var route = "/leading-and-trailing/{param}/{param2}";
- RestAssured.given()
- .accept(ContentType.TEXT)
- .when()
- .get(route, 1, 2)
- .then()
- .statusCode(200);
-
- verifyGetTracing(route, Map.of("param", "1", "param2", "2"));
- }
-
- @Test
- void getNoLeadingAndNoTrailingResource() {
- var route = "/no-leading-and-no-trailing";
- RestAssured.given().accept(ContentType.TEXT).when().get(route).then().statusCode(200);
-
- verifyGetTracing(route, Map.of());
- }
-
- @Test
- void geNoLeadingAndNoTrailingWithSingleParamResource() {
- var route = "/no-leading-and-no-trailing/{param}";
- RestAssured.given().accept(ContentType.TEXT).when().get(route, 1).then().statusCode(200);
-
- verifyGetTracing(route, Map.of("param", "1"));
- }
-
- @Test
- void getNoLeadingAndNoTrailingWithMultiParamResource() {
- var route = "/no-leading-and-no-trailing/{param}/{param2}";
- RestAssured.given()
- .accept(ContentType.TEXT)
- .when()
- .get(route, 1, 2)
- .then()
- .statusCode(200);
-
- verifyGetTracing(route, Map.of("param", "1", "param2", "2"));
- }
-
- @Test
- void getNoLeadingAndTrailingResource() {
- var route = "/no-leading-and-trailing";
- RestAssured.given().accept(ContentType.TEXT).when().get(route).then().statusCode(200);
-
- verifyGetTracing(route, Map.of());
- }
-
- @Test
- void getNoLeadingAndTrailingWithSingleParamResource() {
- var route = "/no-leading-and-trailing/{param}";
- RestAssured.given().accept(ContentType.TEXT).when().get(route, 1).then().statusCode(200);
-
- verifyGetTracing(route, Map.of("param", "1"));
- }
-
- @Test
- void getNoLeadingAndTrailingWithMultiParamResource() {
- var route = "/no-leading-and-trailing/{param}/{param2}";
- RestAssured.given()
- .accept(ContentType.TEXT)
- .when()
- .get(route, 1, 2)
- .then()
- .statusCode(200);
-
- verifyGetTracing(route, Map.of("param", "1", "param2", "2"));
- }
-
- private void verifyGetTracing(String route, Map pathParams) {
- verify(tracingService).trace("actor", "anonymous");
- verify(tracingService).trace("request.method", "GET");
- verify(tracingService).trace("request.route", route);
- pathParams.forEach((key, value) -> verify(tracingService).trace("request.path.params." + key, value));
- verify(tracingService).trace("request.headers.accept", "text/plain");
- verify(tracingService).trace("request.headers.accept-encoding", "gzip,deflate");
- verify(tracingService).trace("request.headers.connection", "Keep-Alive");
- verify(tracingService).trace(eq("request.headers.host"), startsWith("localhost:"));
- verify(tracingService).trace(eq("request.headers.user-agent"), startsWith("Apache-HttpClient"));
- verify(tracingService).trace("request.client.ip", "127.0.0.1");
- verifyNoMoreInteractions(tracingService);
- }
}
diff --git a/quarkus-tracing-service/src/test/java/ch/phoenix/oss/quarkus/commons/tracing/TracingServiceImplTest.java b/quarkus-tracing-service/src/test/java/ch/phoenix/oss/quarkus/commons/tracing/TracingServiceImplTest.java
new file mode 100644
index 0000000..f728e14
--- /dev/null
+++ b/quarkus-tracing-service/src/test/java/ch/phoenix/oss/quarkus/commons/tracing/TracingServiceImplTest.java
@@ -0,0 +1,98 @@
+package ch.phoenix.oss.quarkus.commons.tracing;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import io.opentelemetry.api.trace.Span;
+import io.opentelemetry.instrumentation.annotations.WithSpan;
+import io.quarkus.test.junit.QuarkusTest;
+import jakarta.inject.Inject;
+import org.jboss.logging.MDC;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
+class TracingServiceImplTest {
+
+ @Inject
+ TracingService tracingService;
+
+ @Inject
+ Span span;
+
+ @BeforeEach
+ void setUp() {
+ MDC.clear();
+ }
+
+ @Test
+ void getActor() {
+ tracingService.trace("actor", "abc");
+ assertThat(tracingService.getActor())
+ .as("Actor should match expected value")
+ .isEqualTo("abc");
+ }
+
+ @Test
+ void getRequestPathRaw() {
+ tracingService.trace("request.path.raw", "/foo/bar");
+ assertThat(tracingService.getRequestPathRaw())
+ .as("Request Path Raw should match expected value")
+ .isEqualTo("/foo/bar");
+ }
+
+ @Test
+ void getRequestMethod() {
+ tracingService.trace("request.method", "GET");
+ assertThat(tracingService.getRequestMethod())
+ .as("Request Method should match expected value")
+ .isEqualTo("GET");
+ }
+
+ @Test
+ void getRequestId() {
+ tracingService.trace("request.headers.x-request-id", "ba458367-bfeb-46ba-87da-50b9343be8f9");
+ assertThat(tracingService.getRequestId())
+ .as("Request Id should match expected value")
+ .isEqualTo("ba458367-bfeb-46ba-87da-50b9343be8f9");
+ }
+
+ @Test
+ @WithSpan
+ void getTraceId() {
+ assertThat(tracingService.getTraceId())
+ .as("Request Trace Id should match expected value")
+ .isEqualTo(span.getSpanContext().getTraceId());
+ }
+
+ @Test
+ @WithSpan
+ void getSpanId() {
+ assertThat(tracingService.getSpanId())
+ .as("Request Span Id should match expected value")
+ .isEqualTo(span.getSpanContext().getSpanId());
+ }
+
+ @Test
+ void getClientIp() {
+ tracingService.trace("request.client.ip", "127.0.0.1");
+ assertThat(tracingService.getClientIp())
+ .as("Request Client Iü should match expected value")
+ .isEqualTo("127.0.0.1");
+ }
+
+ @Test
+ void getSchedulerJob() {
+ tracingService.trace("scheduler.job.name", "scheduler/abc");
+ assertThat(tracingService.getSchedulerJob())
+ .as("Scheduler Job Name should match expected value")
+ .isEqualTo("scheduler/abc");
+ }
+
+ @Test
+ void clearAll() {
+ tracingService.trace("aaa", "bbb");
+ assertThat(MDC.get("aaa")).isEqualTo("bbb");
+ tracingService.clearAll();
+ assertThat(MDC.get("aaa")).isNull();
+ }
+}
diff --git a/quarkus-tracing-service/src/test/java/ch/phoenix/oss/quarkus/commons/tracing/resource/SlashResource.java b/quarkus-tracing-service/src/test/java/ch/phoenix/oss/quarkus/commons/tracing/resource/SlashResource.java
index 690c84a..8c8bdc7 100644
--- a/quarkus-tracing-service/src/test/java/ch/phoenix/oss/quarkus/commons/tracing/resource/SlashResource.java
+++ b/quarkus-tracing-service/src/test/java/ch/phoenix/oss/quarkus/commons/tracing/resource/SlashResource.java
@@ -10,14 +10,14 @@ import jakarta.ws.rs.core.MediaType;
public class SlashResource {
@GET
- @Path("/leading/{id}/{anotherId}")
- public String doubleLeading(int id, int anotherId) {
- return "leading/" + id + "/" + anotherId;
+ @Path("/leading/{param}/{param2}")
+ public String doubleLeading(int param, int param2) {
+ return "leading/" + param + "/" + param2;
}
@GET
- @Path("{id}/{anotherId}/trailing/")
- public String doubleTrailing(int id, int anotherId) {
- return id + "/" + anotherId + "/trailing";
+ @Path("{param}/{param2}/trailing/")
+ public String doubleTrailing(int param, int param2) {
+ return param + "/" + param2 + "/trailing";
}
}
diff --git a/quarkus-tracing-service/src/test/resources/application.yaml b/quarkus-tracing-service/src/test/resources/application.yaml
index 9d0943f..3c6bb6f 100644
--- a/quarkus-tracing-service/src/test/resources/application.yaml
+++ b/quarkus-tracing-service/src/test/resources/application.yaml
@@ -32,6 +32,7 @@ quarkus:
headers:
redact:
- AUTHORIZATION
+ - X-SOMETHING-ELSE
query:
include-raw: true
redact:
diff --git a/quarkus-uuid-generator/pom.xml b/quarkus-uuid-generator/pom.xml
index 60dfe9f..a6c395c 100644
--- a/quarkus-uuid-generator/pom.xml
+++ b/quarkus-uuid-generator/pom.xml
@@ -5,7 +5,7 @@
ch.phoenix.oss
quarkus-commons
- 1.0.2
+ 1.0.9-SNAPSHOT
quarkus-uuid-generator