diff --git a/datahub-java-sdk/AGENTS.md b/datahub-java-sdk/AGENTS.md index b5b34f7a..255688b2 100644 --- a/datahub-java-sdk/AGENTS.md +++ b/datahub-java-sdk/AGENTS.md @@ -6,7 +6,7 @@ Thin, synchronous Java client for the DataHub Platform REST API, published as ## Hard constraints - **No server stack.** Built on the JDK `java.net.http.HttpClient`; depends only on - `datahub-api-model` (the wire contract) plus Jackson 3 and zstd-jni. No Spring, no Feign, no + `datahub-api-model` (the wire contract) plus Jackson 3, zstd-jni and slf4j-api. No Spring, no Feign, no Vault client — the Spring Boot plugins in `build.gradle` exist only for BOM version management. Keep the dependency surface at zero-/tiny-transitive jars; this artifact ships to external users. zstd-jni is the one native library, and it is there because the binary datapoint path requires @@ -27,6 +27,8 @@ Thin, synchronous Java client for the DataHub Platform REST API, published as token is `change-request` — that request will never work as it stands — yet holding the data while someone renews the credential is exactly what the spool is for. Going by `retry` in `isBufferable` would stop buffering 401/403 and defeat the feature. +- **Log through SLF4J, never `System.err`/`System.out`.** The SDK runs inside someone else's + application, and its warnings belong in that application's logging backend. - **Wire types come from `datahub-api-model`** — never redefine request/response DTOs here. In-tree it is a project dependency (`api project(':datahub-api-model')`); the published POM pins resolved versions so non-Spring consumers work. diff --git a/datahub-java-sdk/build.gradle b/datahub-java-sdk/build.gradle index e60d13ee..7e515c41 100644 --- a/datahub-java-sdk/build.gradle +++ b/datahub-java-sdk/build.gradle @@ -29,6 +29,10 @@ dependencies { // has no zstd). api-model's ZstdPayloadCodec compiles against it but does not carry it. implementation 'com.github.luben:zstd-jni:1.5.7-17' + // The SDK's own warnings (spooled data dropped or unreadable) go to the caller's logging + // backend. api-model already brings slf4j-api; declared here because the SDK uses it directly. + implementation 'org.slf4j:slf4j-api' + // JUnit (version managed by the Spring Boot BOM) is supplied by java-common-conventions. } diff --git a/datahub-java-sdk/src/main/java/ai/intellistream/datahub/sdk/ingest/DurableSpool.java b/datahub-java-sdk/src/main/java/ai/intellistream/datahub/sdk/ingest/DurableSpool.java index 9f7e6de6..b7d5e1b3 100644 --- a/datahub-java-sdk/src/main/java/ai/intellistream/datahub/sdk/ingest/DurableSpool.java +++ b/datahub-java-sdk/src/main/java/ai/intellistream/datahub/sdk/ingest/DurableSpool.java @@ -3,6 +3,8 @@ import tools.jackson.databind.JavaType; import tools.jackson.databind.json.JsonMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.BufferedOutputStream; import java.io.BufferedReader; @@ -53,6 +55,8 @@ */ public final class DurableSpool { + private static final Logger log = LoggerFactory.getLogger(DurableSpool.class); + /** Sends one chunk of records; returns {@code true} if the server accepted them (so they can be dropped). */ @FunctionalInterface public interface ChunkSender { @@ -299,7 +303,7 @@ record = mapper.readValue(line, elementType); } } } catch (IOException e) { - System.err.println("DataHub SDK: ignoring unreadable spool segment " + segment.path + ": " + e.getMessage()); + log.warn("Ignoring unreadable spool segment {}: {}", segment.path, e.getMessage()); } } @@ -323,7 +327,7 @@ private void recover() { } }); } catch (IOException e) { - System.err.println("DataHub SDK: could not list spool dir " + dir + ": " + e.getMessage()); + log.warn("Could not list spool dir {}: {}", dir, e.getMessage()); return; } deleteQuietly(temps); diff --git a/datahub-java-sdk/src/main/java/ai/intellistream/datahub/sdk/services/EventService.java b/datahub-java-sdk/src/main/java/ai/intellistream/datahub/sdk/services/EventService.java index c702bcae..b9b29be0 100644 --- a/datahub-java-sdk/src/main/java/ai/intellistream/datahub/sdk/services/EventService.java +++ b/datahub-java-sdk/src/main/java/ai/intellistream/datahub/sdk/services/EventService.java @@ -16,6 +16,8 @@ import ai.intellistream.datahub.sdk.util.UuidV7; import ai.intellistream.datahub.models.SearchBody; import tools.jackson.databind.JavaType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; @@ -25,6 +27,8 @@ /** Events — record and query operational events. Mirrors the {@code /events} endpoints. */ public final class EventService { + private static final Logger log = LoggerFactory.getLogger(EventService.class); + private static final String CREATE_PATH = "/events/create"; private final ApiHttp http; @@ -278,7 +282,7 @@ private boolean sendChunk(List chunk, IngestOptions options) { if (result.isBufferable()) { return false; // stop draining; server unreachable or auth not yet restored } - System.err.println("DataHub SDK: dropping spooled events after a terminal error: " + result.errors()); + log.warn("Dropping spooled events after a terminal error: {}", result.errors()); return true; // terminal: drop so the spool can't get stuck forever } diff --git a/datahub-java-sdk/src/main/java/ai/intellistream/datahub/sdk/services/TimeseriesService.java b/datahub-java-sdk/src/main/java/ai/intellistream/datahub/sdk/services/TimeseriesService.java index 5a9e16a0..6d1093e3 100644 --- a/datahub-java-sdk/src/main/java/ai/intellistream/datahub/sdk/services/TimeseriesService.java +++ b/datahub-java-sdk/src/main/java/ai/intellistream/datahub/sdk/services/TimeseriesService.java @@ -29,6 +29,8 @@ import ai.intellistream.datahub.models.SearchBody; import tools.jackson.databind.JavaType; import tools.jackson.databind.type.TypeFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; @@ -45,6 +47,8 @@ */ public final class TimeseriesService { + private static final Logger log = LoggerFactory.getLogger(TimeseriesService.class); + private static final String DATA_PATH = "/timeseries/data"; private final ApiHttp http; @@ -383,7 +387,7 @@ private boolean sendChunk(List chunk, IngestOptions option if (result.isBufferable()) { return false; // stop draining; server unreachable or auth not yet restored } - System.err.println("DataHub SDK: dropping spooled datapoints after a terminal error: " + result.errors()); + log.warn("Dropping spooled datapoints after a terminal error: {}", result.errors()); return true; // terminal: drop so the spool can't get stuck forever }