Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
57 changes: 57 additions & 0 deletions docs/reference/logging.md
Original file line number Diff line number Diff line change
@@ -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
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
</dependency>
```

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
<configuration>
<logger name="xyz.tcheeric" level="DEBUG"/>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
</root>
</configuration>
```

## 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.

2 changes: 1 addition & 1 deletion phoenixd-base/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>xyz.tcheeric</groupId>
<artifactId>phoenixd-java</artifactId>
<version>0.1.3</version>
<version>0.1.4</version>
</parent>

<artifactId>phoenixd-base</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion phoenixd-mock/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>xyz.tcheeric</groupId>
<artifactId>phoenixd-java</artifactId>
<version>0.1.3</version>
<version>0.1.4</version>
</parent>

<artifactId>phoenixd-mock</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion phoenixd-model/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>xyz.tcheeric</groupId>
<artifactId>phoenixd-java</artifactId>
<version>0.1.3</version>
<version>0.1.4</version>
</parent>

<artifactId>phoenixd-model</artifactId>
Expand Down
4 changes: 2 additions & 2 deletions phoenixd-rest/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
<parent>
<groupId>xyz.tcheeric</groupId>
<artifactId>phoenixd-java</artifactId>
<version>0.1.3</version>
<version>0.1.4</version>
</parent>

<artifactId>phoenixd-rest</artifactId>
<packaging>jar</packaging>
<version>0.1.3</version>
<version>0.1.4</version>
<name>phoenixd-rest</name>
<url>https://maven.apache.org</url>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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) {
Expand All @@ -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
Expand All @@ -40,11 +44,12 @@ 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;
}

@Override
public Operation addHeader(String key, String value) {
throw new UnsupportedOperationException("Not supported yet.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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: {}=<redacted? {}>", key, key.equalsIgnoreCase("Authorization") ? "yes" : "no");
return super.addHeader(key, value);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -14,6 +15,7 @@

@Data
@RequiredArgsConstructor
@Slf4j
public abstract class AbstractRequest<T extends Request.Param, U extends Response> implements Request<T, U> {
private final String path;
private final T param;
Expand All @@ -23,26 +25,36 @@ public abstract class AbstractRequest<T extends Request.Param, U extends Respons
@Override
public U getResponse() {
Class<U> responseType = getResponseType();
if (log.isDebugEnabled()) {
log.debug("Executing request: path={}, paramClass={}, responseType={}", path, param != null ? param.getClass().getSimpleName() : "<none>", 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);
}
}

ObjectMapper objectMapper = new ObjectMapper();
if (log.isDebugEnabled()) log.debug("Deserializing JSON into {}", responseType.getSimpleName());
return objectMapper.readValue(body, responseType);
}

private Class<U> getResponseType() {
ParameterizedType superClass = (ParameterizedType) getClass().getGenericSuperclass();
return (Class<U>) superClass.getActualTypeArguments()[1];
}
}
}
Original file line number Diff line number Diff line change
@@ -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 {

/**
Expand All @@ -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");
}
}
}
}
13 changes: 13 additions & 0 deletions phoenixd-rest/src/main/resources/simplelogger.properties
Original file line number Diff line number Diff line change
@@ -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

2 changes: 1 addition & 1 deletion phoenixd-test/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>xyz.tcheeric</groupId>
<artifactId>phoenixd-java</artifactId>
<version>0.1.3</version>
<version>0.1.4</version>
</parent>

<artifactId>phoenixd-test</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>xyz.tcheeric</groupId>
<artifactId>phoenixd-java</artifactId>
<version>0.1.3</version>
<version>0.1.4</version>
<packaging>pom</packaging>

<modules>
Expand Down
Loading