From 9fae050b3670704486ceda061abf363e8f46e77b Mon Sep 17 00:00:00 2001 From: automation Date: Sun, 14 Sep 2025 05:05:56 +0100 Subject: [PATCH 1/3] feat: add Lombok @Slf4j logging across phoenixd-rest (requests, operations, factory) with safe, meaningful messages --- .../operation/impl/DeleteOperation.java | 7 ++++++- .../phoenixd/operation/impl/GetOperation.java | 4 ++++ .../operation/impl/PatchOperation.java | 5 +++++ .../phoenixd/operation/impl/PostOperation.java | 4 ++++ .../phoenixd/request/AbstractRequest.java | 18 +++++++++++++++--- .../request/impl/rest/PayRequestFactory.java | 9 +++++++-- 6 files changed, 41 insertions(+), 6 deletions(-) diff --git a/phoenixd-rest/src/main/java/xyz/tcheeric/phoenixd/operation/impl/DeleteOperation.java b/phoenixd-rest/src/main/java/xyz/tcheeric/phoenixd/operation/impl/DeleteOperation.java index c8cb934..b280483 100644 --- a/phoenixd-rest/src/main/java/xyz/tcheeric/phoenixd/operation/impl/DeleteOperation.java +++ b/phoenixd-rest/src/main/java/xyz/tcheeric/phoenixd/operation/impl/DeleteOperation.java @@ -2,6 +2,7 @@ import lombok.NonNull; import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; import xyz.tcheeric.phoenixd.common.rest.Operation; import xyz.tcheeric.phoenixd.common.rest.Request; import xyz.tcheeric.phoenixd.common.rest.util.Constants; @@ -11,6 +12,7 @@ import java.net.http.HttpRequest; import java.net.http.HttpRequest.Builder; +@Slf4j public class DeleteOperation extends AbstractOperation { public DeleteOperation(HttpRequest httpRequest) { @@ -20,11 +22,13 @@ public DeleteOperation(HttpRequest httpRequest) { @SneakyThrows public DeleteOperation(@NonNull String path) { super(Constants.HTTP_DELETE_METHOD, path, null); + if (log.isDebugEnabled()) log.debug("Initialized DELETE operation for path={}", path); } @SneakyThrows public DeleteOperation(@NonNull String path, @NonNull Request.Param requestParam) { super(Constants.HTTP_DELETE_METHOD, path, requestParam, null); + if (log.isDebugEnabled()) log.debug("Initialized DELETE operation for path={} with params", path); } @Override @@ -40,6 +44,7 @@ public Operation removeHeader(@NonNull String key) { }); this.httpRequest = requestBuilder.build(); + if (log.isDebugEnabled()) log.debug("Removed header '{}' from DELETE request {} {}", key, httpRequest.method(), httpRequest.uri()); return this; } @@ -47,4 +52,4 @@ public Operation removeHeader(@NonNull String key) { public Operation addHeader(String key, String value) { throw new UnsupportedOperationException("Not supported yet."); } -} \ No newline at end of file +} diff --git a/phoenixd-rest/src/main/java/xyz/tcheeric/phoenixd/operation/impl/GetOperation.java b/phoenixd-rest/src/main/java/xyz/tcheeric/phoenixd/operation/impl/GetOperation.java index 5213736..a5a12e7 100644 --- a/phoenixd-rest/src/main/java/xyz/tcheeric/phoenixd/operation/impl/GetOperation.java +++ b/phoenixd-rest/src/main/java/xyz/tcheeric/phoenixd/operation/impl/GetOperation.java @@ -2,12 +2,14 @@ import lombok.NonNull; import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; import xyz.tcheeric.phoenixd.common.rest.Request; import xyz.tcheeric.phoenixd.common.rest.util.Constants; import xyz.tcheeric.phoenixd.operation.AbstractOperation; import java.net.http.HttpRequest; +@Slf4j public class GetOperation extends AbstractOperation { public GetOperation(HttpRequest httpRequest) { @@ -17,10 +19,12 @@ public GetOperation(HttpRequest httpRequest) { @SneakyThrows public GetOperation(@NonNull String path) { super(Constants.HTTP_GET_METHOD, path, null); + if (log.isDebugEnabled()) log.debug("Initialized GET operation for path={}", path); } @SneakyThrows public GetOperation(@NonNull String path, @NonNull Request.Param requestParam) { super(Constants.HTTP_GET_METHOD, path, requestParam, null); + if (log.isDebugEnabled()) log.debug("Initialized GET operation for path={} with params", path); } } diff --git a/phoenixd-rest/src/main/java/xyz/tcheeric/phoenixd/operation/impl/PatchOperation.java b/phoenixd-rest/src/main/java/xyz/tcheeric/phoenixd/operation/impl/PatchOperation.java index 6109100..1b5c594 100644 --- a/phoenixd-rest/src/main/java/xyz/tcheeric/phoenixd/operation/impl/PatchOperation.java +++ b/phoenixd-rest/src/main/java/xyz/tcheeric/phoenixd/operation/impl/PatchOperation.java @@ -2,21 +2,25 @@ import lombok.NonNull; import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; import xyz.tcheeric.phoenixd.common.rest.Operation; import xyz.tcheeric.phoenixd.common.rest.Request; import xyz.tcheeric.phoenixd.common.rest.util.Constants; import xyz.tcheeric.phoenixd.operation.AbstractOperation; +@Slf4j public class PatchOperation extends AbstractOperation { @SneakyThrows public PatchOperation(@NonNull String path) { super(Constants.HTTP_PATCH_METHOD, path, null); + if (log.isDebugEnabled()) log.debug("Initialized PATCH operation for path={}", path); } @SneakyThrows public PatchOperation(@NonNull String path, @NonNull Request.Param param) { super(Constants.HTTP_PATCH_METHOD, path, param, null); + if (log.isDebugEnabled()) log.debug("Initialized PATCH operation for path={} with params", path); } @Override @@ -26,6 +30,7 @@ public Operation removeHeader(String key) { @Override public Operation addHeader(String key, String value) { + if (log.isDebugEnabled()) log.debug("Adding header on PATCH operation: {}=", key, key.equalsIgnoreCase("Authorization") ? "yes" : "no"); return super.addHeader(key, value); } diff --git a/phoenixd-rest/src/main/java/xyz/tcheeric/phoenixd/operation/impl/PostOperation.java b/phoenixd-rest/src/main/java/xyz/tcheeric/phoenixd/operation/impl/PostOperation.java index 22a835a..a8e002f 100644 --- a/phoenixd-rest/src/main/java/xyz/tcheeric/phoenixd/operation/impl/PostOperation.java +++ b/phoenixd-rest/src/main/java/xyz/tcheeric/phoenixd/operation/impl/PostOperation.java @@ -2,12 +2,14 @@ import lombok.NonNull; import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; import xyz.tcheeric.phoenixd.common.rest.Request; import xyz.tcheeric.phoenixd.common.rest.util.Constants; import xyz.tcheeric.phoenixd.operation.AbstractOperation; import java.net.http.HttpRequest; +@Slf4j public class PostOperation extends AbstractOperation { public PostOperation(HttpRequest httpRequest) { @@ -17,11 +19,13 @@ public PostOperation(HttpRequest httpRequest) { public PostOperation(@NonNull String path, @NonNull String data) { super(Constants.HTTP_POST_METHOD, path, data); this.addHeader("Content-Type", "application/x-www-form-urlencoded"); + if (log.isDebugEnabled()) log.debug("Initialized POST operation for path={} with body size={}", path, data.length()); } @SneakyThrows public PostOperation(@NonNull String path, @NonNull Request.Param param, @NonNull String data) { super(Constants.HTTP_POST_METHOD, path, param, data); this.addHeader("Content-Type", "application/x-www-form-urlencoded"); + if (log.isDebugEnabled()) log.debug("Initialized POST operation for path={} with params and body size={}", path, data.length()); } } diff --git a/phoenixd-rest/src/main/java/xyz/tcheeric/phoenixd/request/AbstractRequest.java b/phoenixd-rest/src/main/java/xyz/tcheeric/phoenixd/request/AbstractRequest.java index fbb68aa..e8631de 100644 --- a/phoenixd-rest/src/main/java/xyz/tcheeric/phoenixd/request/AbstractRequest.java +++ b/phoenixd-rest/src/main/java/xyz/tcheeric/phoenixd/request/AbstractRequest.java @@ -4,6 +4,7 @@ import lombok.Data; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; import xyz.tcheeric.phoenixd.common.rest.Operation; import xyz.tcheeric.phoenixd.common.rest.Request; import xyz.tcheeric.phoenixd.common.rest.Response; @@ -14,6 +15,7 @@ @Data @RequiredArgsConstructor +@Slf4j public abstract class AbstractRequest implements Request { private final String path; private final T param; @@ -23,14 +25,23 @@ public abstract class AbstractRequest responseType = getResponseType(); + if (log.isDebugEnabled()) { + log.debug("Executing request: path={}, paramClass={}, responseType={}", path, param != null ? param.getClass().getSimpleName() : "", responseType.getSimpleName()); + } if (VoidResponse.class.isAssignableFrom(responseType)) { + if (log.isDebugEnabled()) log.debug("VoidResponse detected; skipping network call for path={}", path); return (U) new VoidResponse(); } String body = this.getOperation().execute().getResponseBody(); + if (log.isDebugEnabled()) { + String preview = body == null ? "" : (body.length() > 256 ? body.substring(0, 256) + "..." : body); + log.debug("Received response body (truncated): {}", preview); + } if(GetLightningAddressResponse.class.equals(responseType)) { - // Remove the ₿ prefix - if(body.charAt(0) == '₿') { + // Hack: Remove the ₿ prefix + if(body != null && !body.isEmpty() && body.charAt(0) == '₿') { + if (log.isDebugEnabled()) log.debug("Stripping leading '₿' from lightning address response"); return (U) new GetLightningAddressResponse(body.substring(1)); } else { return (U) new GetLightningAddressResponse(body); @@ -38,6 +49,7 @@ public U getResponse() { } ObjectMapper objectMapper = new ObjectMapper(); + if (log.isDebugEnabled()) log.debug("Deserializing JSON into {}", responseType.getSimpleName()); return objectMapper.readValue(body, responseType); } @@ -45,4 +57,4 @@ private Class getResponseType() { ParameterizedType superClass = (ParameterizedType) getClass().getGenericSuperclass(); return (Class) superClass.getActualTypeArguments()[1]; } -} \ No newline at end of file +} diff --git a/phoenixd-rest/src/main/java/xyz/tcheeric/phoenixd/request/impl/rest/PayRequestFactory.java b/phoenixd-rest/src/main/java/xyz/tcheeric/phoenixd/request/impl/rest/PayRequestFactory.java index 812c450..7b5e947 100644 --- a/phoenixd-rest/src/main/java/xyz/tcheeric/phoenixd/request/impl/rest/PayRequestFactory.java +++ b/phoenixd-rest/src/main/java/xyz/tcheeric/phoenixd/request/impl/rest/PayRequestFactory.java @@ -1,11 +1,13 @@ package xyz.tcheeric.phoenixd.request.impl.rest; import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; import xyz.tcheeric.phoenixd.model.param.PayBolt11InvoiceParam; import xyz.tcheeric.phoenixd.model.param.PayLightningAddressParam; import java.util.regex.Pattern; +@Slf4j public class PayRequestFactory { /** @@ -16,17 +18,20 @@ public class PayRequestFactory { Pattern.CASE_INSENSITIVE); public static BasePayRequest createPayRequest(@NonNull String request) { - + if (log.isDebugEnabled()) log.debug("Creating pay request for input of length {}", request.length()); if (request.contains("@")) { PayLightningAddressParam param = new PayLightningAddressParam(); param.setAddress(request); + if (log.isDebugEnabled()) log.debug("Detected Lightning Address format"); return new PayLightningAddressRequest(param); } else if (BOLT11_PATTERN.matcher(request).matches()) { PayBolt11InvoiceParam param = new PayBolt11InvoiceParam(); param.setInvoice(request); + if (log.isDebugEnabled()) log.debug("Detected BOLT11 invoice format"); return new PayBolt11InvoiceRequest(param); } else { + log.warn("Invalid pay request format; input begins with: {}", request.length() > 8 ? request.substring(0, 8) + "..." : request); throw new IllegalArgumentException("Invalid request format"); } } -} \ No newline at end of file +} From 23d62be6c80b544390a600534aebc65f789605fa Mon Sep 17 00:00:00 2001 From: automation Date: Sun, 14 Sep 2025 05:08:18 +0100 Subject: [PATCH 2/3] docs: add logging guide and ship simplelogger.properties to make DEBUG logs visible out of the box --- README.md | 1 + docs/reference/logging.md | 57 +++++++++++++++++++ .../main/resources/simplelogger.properties | 13 +++++ 3 files changed, 71 insertions(+) create mode 100644 docs/reference/logging.md create mode 100644 phoenixd-rest/src/main/resources/simplelogger.properties diff --git a/README.md b/README.md index b2bd441..0da11a1 100644 --- a/README.md +++ b/README.md @@ -46,3 +46,4 @@ version and `latest`, allowing consumers to pull the most recent build without s - [Docker](docs/how-to/docker.md) - [Code coverage](docs/how-to/coverage.md) - [Release](docs/how-to/release.md) + - [Logging](docs/reference/logging.md) diff --git a/docs/reference/logging.md b/docs/reference/logging.md new file mode 100644 index 0000000..7f53e7a --- /dev/null +++ b/docs/reference/logging.md @@ -0,0 +1,57 @@ +# Logging + +phoenixd-rest and phoenixd-base use SLF4J for logging with Lombok's `@Slf4j`. +This lets your application choose the logging backend (Logback, Log4j2, slf4j-simple, etc.). + +## Quick Start (slf4j-simple) + +If your app does not already have a logging backend, add: + +```xml + + org.slf4j + slf4j-simple + ${slf4j.version} + +``` + +The module ships a `simplelogger.properties` that sets: + +- `org.slf4j.simpleLogger.defaultLogLevel=info` +- `org.slf4j.simpleLogger.log.xyz.tcheeric=debug` +- date/time and thread name output + +Override levels at runtime with system properties, for example: + +```bash +JAVA_TOOL_OPTIONS="-Dorg.slf4j.simpleLogger.defaultLogLevel=info \ + -Dorg.slf4j.simpleLogger.log.xyz.tcheeric=debug" +``` + +## Spring Boot (Logback) + +Add to `application.properties`: + +``` +logging.level.xyz.tcheeric=DEBUG +``` + +Or to `logback-spring.xml`: + +```xml + + + + + + +``` + +## What’s Logged + +- HTTP requests: method, URI, timeout, status; error responses include a truncated body. +- Configuration resolution: whether values come from ENV, system properties, or `app.properties` (base module). +- Request factory decisions: Lightning address vs BOLT11 detection. + +Sensitive values (e.g. Authorization) are redacted. + diff --git a/phoenixd-rest/src/main/resources/simplelogger.properties b/phoenixd-rest/src/main/resources/simplelogger.properties new file mode 100644 index 0000000..c58c518 --- /dev/null +++ b/phoenixd-rest/src/main/resources/simplelogger.properties @@ -0,0 +1,13 @@ +# SLF4J SimpleLogger configuration for phoenixd-rest +# This file is only used when slf4j-simple is on the classpath. +# It does not affect applications that use Logback, Log4j2, etc. + +org.slf4j.simpleLogger.showDateTime=true +org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss.SSS +org.slf4j.simpleLogger.showThreadName=true +org.slf4j.simpleLogger.showLogName=false +org.slf4j.simpleLogger.defaultLogLevel=info + +# Turn on detailed logs for our packages +org.slf4j.simpleLogger.log.xyz.tcheeric=debug + From 76b528ac28319fb0f7d234ff2a6839c4689c8982 Mon Sep 17 00:00:00 2001 From: automation Date: Sun, 14 Sep 2025 05:16:26 +0100 Subject: [PATCH 3/3] build: bump version to 0.1.4 and update CHANGELOG for logging configuration --- CHANGELOG.md | 5 +++++ phoenixd-base/pom.xml | 2 +- phoenixd-mock/pom.xml | 2 +- phoenixd-model/pom.xml | 2 +- phoenixd-rest/pom.xml | 4 ++-- phoenixd-test/pom.xml | 2 +- pom.xml | 2 +- 7 files changed, 12 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf26215..1cf34e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,4 +58,9 @@ ### Notes - Enable debug logs with `logging.level.xyz.tcheeric=DEBUG` to see detailed request and configuration traces. +## 0.1.4 — 2025-09-13 + +### Enhancements +- Add default logging configuration for SLF4J Simple in phoenixd-rest (`simplelogger.properties`). +- Document logging usage and configuration. diff --git a/phoenixd-base/pom.xml b/phoenixd-base/pom.xml index aed2dfd..26e1432 100644 --- a/phoenixd-base/pom.xml +++ b/phoenixd-base/pom.xml @@ -4,7 +4,7 @@ xyz.tcheeric phoenixd-java - 0.1.3 + 0.1.4 phoenixd-base diff --git a/phoenixd-mock/pom.xml b/phoenixd-mock/pom.xml index ff6adc3..abb112f 100644 --- a/phoenixd-mock/pom.xml +++ b/phoenixd-mock/pom.xml @@ -6,7 +6,7 @@ xyz.tcheeric phoenixd-java - 0.1.3 + 0.1.4 phoenixd-mock diff --git a/phoenixd-model/pom.xml b/phoenixd-model/pom.xml index a1fa00e..866dfc2 100644 --- a/phoenixd-model/pom.xml +++ b/phoenixd-model/pom.xml @@ -4,7 +4,7 @@ xyz.tcheeric phoenixd-java - 0.1.3 + 0.1.4 phoenixd-model diff --git a/phoenixd-rest/pom.xml b/phoenixd-rest/pom.xml index c852ee6..3adf419 100644 --- a/phoenixd-rest/pom.xml +++ b/phoenixd-rest/pom.xml @@ -4,12 +4,12 @@ xyz.tcheeric phoenixd-java - 0.1.3 + 0.1.4 phoenixd-rest jar - 0.1.3 + 0.1.4 phoenixd-rest https://maven.apache.org diff --git a/phoenixd-test/pom.xml b/phoenixd-test/pom.xml index 46d5b1e..9dda937 100644 --- a/phoenixd-test/pom.xml +++ b/phoenixd-test/pom.xml @@ -4,7 +4,7 @@ xyz.tcheeric phoenixd-java - 0.1.3 + 0.1.4 phoenixd-test diff --git a/pom.xml b/pom.xml index e67abc7..45a964b 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 xyz.tcheeric phoenixd-java - 0.1.3 + 0.1.4 pom