Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
104 commits
Select commit Hold shift + click to select a range
66f851b
codegen metadata
stainless-app[bot] May 6, 2026
fc14f66
codegen metadata
stainless-app[bot] May 6, 2026
bfb159a
codegen metadata
stainless-app[bot] May 6, 2026
49c2e97
codegen metadata
stainless-app[bot] May 6, 2026
ed365da
codegen metadata
stainless-app[bot] May 6, 2026
3c5d5b2
codegen metadata
stainless-app[bot] May 6, 2026
8369e6a
codegen metadata
stainless-app[bot] May 6, 2026
015acad
codegen metadata
stainless-app[bot] May 6, 2026
2d2f684
codegen metadata
stainless-app[bot] May 6, 2026
9cdf85e
codegen metadata
stainless-app[bot] May 6, 2026
6d3ad4b
codegen metadata
stainless-app[bot] May 7, 2026
54a9947
codegen metadata
stainless-app[bot] May 7, 2026
fcbd456
feat(client): improve logging
stainless-app[bot] May 7, 2026
7b472ce
codegen metadata
stainless-app[bot] May 7, 2026
87a22ae
codegen metadata
stainless-app[bot] May 7, 2026
f8dbe95
codegen metadata
stainless-app[bot] May 7, 2026
cf38094
codegen metadata
stainless-app[bot] May 7, 2026
f6fdbe1
codegen metadata
stainless-app[bot] May 7, 2026
c055e89
codegen metadata
stainless-app[bot] May 7, 2026
28c3e0b
codegen metadata
stainless-app[bot] May 7, 2026
d0cd2e6
codegen metadata
stainless-app[bot] May 7, 2026
870c647
codegen metadata
stainless-app[bot] May 7, 2026
11e7498
codegen metadata
stainless-app[bot] May 7, 2026
2ff3476
codegen metadata
stainless-app[bot] May 7, 2026
8813f45
codegen metadata
stainless-app[bot] May 7, 2026
f8a0fec
codegen metadata
stainless-app[bot] May 7, 2026
bf64d5b
codegen metadata
stainless-app[bot] May 7, 2026
3c82a87
codegen metadata
stainless-app[bot] May 8, 2026
774bb5b
chore: redact api-key headers in debug logs
stainless-app[bot] May 8, 2026
67605bc
codegen metadata
stainless-app[bot] May 8, 2026
a8dd931
codegen metadata
stainless-app[bot] May 8, 2026
7114aec
codegen metadata
stainless-app[bot] May 8, 2026
5709c09
codegen metadata
stainless-app[bot] May 8, 2026
918d0d7
codegen metadata
stainless-app[bot] May 8, 2026
9a0911f
codegen metadata
stainless-app[bot] May 8, 2026
a3fb0dd
codegen metadata
stainless-app[bot] May 8, 2026
8c3cea3
codegen metadata
stainless-app[bot] May 8, 2026
54c33e5
codegen metadata
stainless-app[bot] May 8, 2026
6900f7b
codegen metadata
stainless-app[bot] May 8, 2026
b7ed850
codegen metadata
stainless-app[bot] May 8, 2026
1fd5969
codegen metadata
stainless-app[bot] May 8, 2026
1c461d0
codegen metadata
stainless-app[bot] May 8, 2026
86b98d7
codegen metadata
stainless-app[bot] May 8, 2026
d1be859
codegen metadata
stainless-app[bot] May 9, 2026
4b53a1f
codegen metadata
stainless-app[bot] May 9, 2026
2b393e7
codegen metadata
stainless-app[bot] May 9, 2026
791542e
codegen metadata
stainless-app[bot] May 9, 2026
45089de
codegen metadata
stainless-app[bot] May 9, 2026
37b79b8
codegen metadata
stainless-app[bot] May 9, 2026
a9c5e23
codegen metadata
stainless-app[bot] May 9, 2026
e048ebb
codegen metadata
stainless-app[bot] May 9, 2026
8e07fe1
codegen metadata
stainless-app[bot] May 9, 2026
c1e129b
codegen metadata
stainless-app[bot] May 9, 2026
09d9769
codegen metadata
stainless-app[bot] May 9, 2026
9754d0f
codegen metadata
stainless-app[bot] May 9, 2026
6648374
codegen metadata
stainless-app[bot] May 9, 2026
8a28407
codegen metadata
stainless-app[bot] May 9, 2026
cc370cd
codegen metadata
stainless-app[bot] May 9, 2026
44722b8
codegen metadata
stainless-app[bot] May 9, 2026
7296eb4
codegen metadata
stainless-app[bot] May 9, 2026
cc9089d
codegen metadata
stainless-app[bot] May 9, 2026
1b3852a
codegen metadata
stainless-app[bot] May 10, 2026
924cd7e
codegen metadata
stainless-app[bot] May 10, 2026
30d0449
codegen metadata
stainless-app[bot] May 10, 2026
e734c80
codegen metadata
stainless-app[bot] May 10, 2026
28e0743
codegen metadata
stainless-app[bot] May 10, 2026
ec75117
codegen metadata
stainless-app[bot] May 10, 2026
c8eb103
codegen metadata
stainless-app[bot] May 10, 2026
ed8a498
codegen metadata
stainless-app[bot] May 10, 2026
504ffd4
codegen metadata
stainless-app[bot] May 10, 2026
4fb6265
codegen metadata
stainless-app[bot] May 10, 2026
0e7ec04
codegen metadata
stainless-app[bot] May 10, 2026
38feb5c
codegen metadata
stainless-app[bot] May 10, 2026
c6d1162
codegen metadata
stainless-app[bot] May 10, 2026
84dae0d
codegen metadata
stainless-app[bot] May 10, 2026
7b14e22
codegen metadata
stainless-app[bot] May 10, 2026
919c71d
codegen metadata
stainless-app[bot] May 10, 2026
8126160
codegen metadata
stainless-app[bot] May 10, 2026
a113798
codegen metadata
stainless-app[bot] May 10, 2026
676bb67
codegen metadata
stainless-app[bot] May 10, 2026
bded3fc
codegen metadata
stainless-app[bot] May 10, 2026
745f029
codegen metadata
stainless-app[bot] May 11, 2026
8298c70
codegen metadata
stainless-app[bot] May 11, 2026
6ef7eb6
codegen metadata
stainless-app[bot] May 11, 2026
ff84e3c
codegen metadata
stainless-app[bot] May 11, 2026
78000eb
codegen metadata
stainless-app[bot] May 11, 2026
72e72b1
codegen metadata
stainless-app[bot] May 11, 2026
198f906
codegen metadata
stainless-app[bot] May 11, 2026
19427d7
codegen metadata
stainless-app[bot] May 11, 2026
5934b49
codegen metadata
stainless-app[bot] May 11, 2026
67b9054
codegen metadata
stainless-app[bot] May 11, 2026
4229f17
codegen metadata
stainless-app[bot] May 11, 2026
6c43195
codegen metadata
stainless-app[bot] May 11, 2026
154afae
codegen metadata
stainless-app[bot] May 11, 2026
fb9ee95
codegen metadata
stainless-app[bot] May 11, 2026
7112086
codegen metadata
stainless-app[bot] May 11, 2026
be06913
codegen metadata
stainless-app[bot] May 11, 2026
32ac051
codegen metadata
stainless-app[bot] May 11, 2026
b1622be
codegen metadata
stainless-app[bot] May 11, 2026
fdad23b
codegen metadata
stainless-app[bot] May 11, 2026
dabd95b
codegen metadata
stainless-app[bot] May 11, 2026
1b01769
codegen metadata
stainless-app[bot] May 12, 2026
c9da566
codegen metadata
stainless-app[bot] May 12, 2026
af8aa96
release: 0.23.0
stainless-app[bot] May 12, 2026
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
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.22.0"
".": "0.23.0"
}
4 changes: 2 additions & 2 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 40
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/sent/sent-dm-7bb26574b68a4a83fda65dd095f3f54fc797d44988eb3ed8b72f6f1be768d284.yml
openapi_spec_hash: 92349dc439d33c6d4bd2a467a36a6190
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/sent/sent-dm-a9fb8deca8b7f2d5817689c8f5dc84146b24704424fd3760fa1e1ad88c1773dc.yml
openapi_spec_hash: 6d0e3d005919cd071a4bbd75e514be34
config_hash: 7fe4b7f38470a511342b783de698aa99
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Changelog

## 0.23.0 (2026-05-12)

Full Changelog: [v0.22.0...v0.23.0](https://github.com/sentdm/sent-dm-java/compare/v0.22.0...v0.23.0)

### Features

* **client:** improve logging ([fcbd456](https://github.com/sentdm/sent-dm-java/commit/fcbd4563cbfd02d714a9dfe8fdbf991c4f10161b))


### Chores

* redact api-key headers in debug logs ([774bb5b](https://github.com/sentdm/sent-dm-java/commit/774bb5bd688635b3c7cfe52d3eba1457f5748405))

## 0.22.0 (2026-05-06)

Full Changelog: [v0.21.0...v0.22.0](https://github.com/sentdm/sent-dm-java/compare/v0.21.0...v0.22.0)
Expand Down
25 changes: 18 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

<!-- x-release-please-start-version -->

[![Maven Central](https://img.shields.io/maven-central/v/dm.sent/sent-java)](https://central.sonatype.com/artifact/dm.sent/sent-java/0.22.0)
[![javadoc](https://javadoc.io/badge2/dm.sent/sent-java/0.22.0/javadoc.svg)](https://javadoc.io/doc/dm.sent/sent-java/0.22.0)
[![Maven Central](https://img.shields.io/maven-central/v/dm.sent/sent-java)](https://central.sonatype.com/artifact/dm.sent/sent-java/0.23.0)
[![javadoc](https://javadoc.io/badge2/dm.sent/sent-java/0.23.0/javadoc.svg)](https://javadoc.io/doc/dm.sent/sent-java/0.23.0)

<!-- x-release-please-end -->

Expand All @@ -22,7 +22,7 @@ Use the Sent MCP Server to enable AI assistants to interact with this API, allow

<!-- x-release-please-start-version -->

The REST API documentation can be found on [docs.sent.dm](https://docs.sent.dm). Javadocs are available on [javadoc.io](https://javadoc.io/doc/dm.sent/sent-java/0.22.0).
The REST API documentation can be found on [docs.sent.dm](https://docs.sent.dm). Javadocs are available on [javadoc.io](https://javadoc.io/doc/dm.sent/sent-java/0.23.0).

<!-- x-release-please-end -->

Expand All @@ -33,7 +33,7 @@ The REST API documentation can be found on [docs.sent.dm](https://docs.sent.dm).
### Gradle

```kotlin
implementation("dm.sent:sent-java:0.22.0")
implementation("dm.sent:sent-java:0.23.0")
```

### Maven
Expand All @@ -42,7 +42,7 @@ implementation("dm.sent:sent-java:0.22.0")
<dependency>
<groupId>dm.sent</groupId>
<artifactId>sent-java</artifactId>
<version>0.22.0</version>
<version>0.23.0</version>
</dependency>
```

Expand Down Expand Up @@ -294,8 +294,6 @@ The SDK throws custom unchecked exception types:

## Logging

The SDK uses the standard [OkHttp logging interceptor](https://github.com/square/okhttp/tree/master/okhttp-logging-interceptor).

Enable logging by setting the `SENT_LOG` environment variable to `info`:

```sh
Expand All @@ -308,6 +306,19 @@ Or to `debug` for more verbose logging:
export SENT_LOG=debug
```

Or configure the client manually using the `logLevel` method:

```java
import dm.sent.client.SentClient;
import dm.sent.client.okhttp.SentOkHttpClient;
import dm.sent.core.LogLevel;

SentClient client = SentOkHttpClient.builder()
.fromEnv()
.logLevel(LogLevel.INFO)
.build();
```

## ProGuard and R8

Although the SDK uses reflection, it is still usable with [ProGuard](https://github.com/Guardsquare/proguard) and [R8](https://developer.android.com/topic/performance/app-optimization/enable-app-optimization) because `sent-java-core` is published with a [configuration file](sent-java-core/src/main/resources/META-INF/proguard/sent-java-core.pro) containing [keep rules](https://www.guardsquare.com/manual/configuration/usage).
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ repositories {

allprojects {
group = "dm.sent"
version = "0.22.0" // x-release-please-version
version = "0.23.0" // x-release-please-version
}

subprojects {
Expand Down
1 change: 0 additions & 1 deletion sent-java-client-okhttp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ dependencies {
api(project(":sent-java-core"))

implementation("com.squareup.okhttp3:okhttp:4.12.0")
implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")

testImplementation(kotlin("test"))
testImplementation("org.assertj:assertj-core:3.27.7")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ import okhttp3.Request
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import okhttp3.logging.HttpLoggingInterceptor
import okio.BufferedSink
import okio.buffer
import okio.sink
Expand Down Expand Up @@ -93,18 +92,6 @@ internal constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClie
private fun newCall(request: HttpRequest, requestOptions: RequestOptions): Call {
val clientBuilder = okHttpClient.newBuilder()

val logLevel =
when (System.getenv("SENT_LOG")?.lowercase()) {
"info" -> HttpLoggingInterceptor.Level.BASIC
"debug" -> HttpLoggingInterceptor.Level.BODY
else -> null
}
if (logLevel != null) {
clientBuilder.addNetworkInterceptor(
HttpLoggingInterceptor().setLevel(logLevel).apply { redactHeader("x-api-key") }
)
}

requestOptions.timeout?.let {
clientBuilder
.connectTimeout(it.connect())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.fasterxml.jackson.databind.json.JsonMapper
import dm.sent.client.SentClient
import dm.sent.client.SentClientImpl
import dm.sent.core.ClientOptions
import dm.sent.core.LogLevel
import dm.sent.core.Sleeper
import dm.sent.core.Timeout
import dm.sent.core.http.Headers
Expand Down Expand Up @@ -277,6 +278,15 @@ class SentOkHttpClient private constructor() {
*/
fun maxRetries(maxRetries: Int) = apply { clientOptions.maxRetries(maxRetries) }

/**
* The level at which to log request and response information.
*
* [fromEnv] will set the level from environment variables. See [LogLevel.fromEnv].
*
* Defaults to [LogLevel.fromEnv].
*/
fun logLevel(logLevel: LogLevel) = apply { clientOptions.logLevel(logLevel) }

/**
* Customer API key for authentication. Use `sk_live_*` keys for production and `sk_test_*`
* keys for sandbox/testing. Pass via the `x-api-key` header.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.fasterxml.jackson.databind.json.JsonMapper
import dm.sent.client.SentClientAsync
import dm.sent.client.SentClientAsyncImpl
import dm.sent.core.ClientOptions
import dm.sent.core.LogLevel
import dm.sent.core.Sleeper
import dm.sent.core.Timeout
import dm.sent.core.http.Headers
Expand Down Expand Up @@ -277,6 +278,15 @@ class SentOkHttpClientAsync private constructor() {
*/
fun maxRetries(maxRetries: Int) = apply { clientOptions.maxRetries(maxRetries) }

/**
* The level at which to log request and response information.
*
* [fromEnv] will set the level from environment variables. See [LogLevel.fromEnv].
*
* Defaults to [LogLevel.fromEnv].
*/
fun logLevel(logLevel: LogLevel) = apply { clientOptions.logLevel(logLevel) }

/**
* Customer API key for authentication. Use `sk_live_*` keys for production and `sk_test_*`
* keys for sandbox/testing. Pass via the `x-api-key` header.
Expand Down
30 changes: 29 additions & 1 deletion sent-java-core/src/main/kotlin/dm/sent/core/ClientOptions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package dm.sent.core
import com.fasterxml.jackson.databind.json.JsonMapper
import dm.sent.core.http.Headers
import dm.sent.core.http.HttpClient
import dm.sent.core.http.LoggingHttpClient
import dm.sent.core.http.PhantomReachableClosingHttpClient
import dm.sent.core.http.QueryParams
import dm.sent.core.http.RetryingHttpClient
Expand Down Expand Up @@ -96,6 +97,14 @@ private constructor(
* Defaults to 2.
*/
@get:JvmName("maxRetries") val maxRetries: Int,
/**
* The level at which to log request and response information.
*
* [fromEnv] will set the level from environment variables. See [LogLevel.fromEnv].
*
* Defaults to [LogLevel.fromEnv].
*/
@get:JvmName("logLevel") val logLevel: LogLevel,
/**
* Customer API key for authentication. Use `sk_live_*` keys for production and `sk_test_*` keys
* for sandbox/testing. Pass via the `x-api-key` header.
Expand Down Expand Up @@ -155,6 +164,7 @@ private constructor(
private var responseValidation: Boolean = false
private var timeout: Timeout = Timeout.default()
private var maxRetries: Int = 2
private var logLevel: LogLevel = LogLevel.fromEnv()
private var apiKey: String? = null

@JvmSynthetic
Expand All @@ -170,6 +180,7 @@ private constructor(
responseValidation = clientOptions.responseValidation
timeout = clientOptions.timeout
maxRetries = clientOptions.maxRetries
logLevel = clientOptions.logLevel
apiKey = clientOptions.apiKey
}

Expand Down Expand Up @@ -280,6 +291,15 @@ private constructor(
*/
fun maxRetries(maxRetries: Int) = apply { this.maxRetries = maxRetries }

/**
* The level at which to log request and response information.
*
* [fromEnv] will set the level from environment variables. See [LogLevel.fromEnv].
*
* Defaults to [LogLevel.fromEnv].
*/
fun logLevel(logLevel: LogLevel) = apply { this.logLevel = logLevel }

/**
* Customer API key for authentication. Use `sk_live_*` keys for production and `sk_test_*`
* keys for sandbox/testing. Pass via the `x-api-key` header.
Expand Down Expand Up @@ -381,6 +401,7 @@ private constructor(
* System properties take precedence over environment variables.
*/
fun fromEnv() = apply {
logLevel(LogLevel.fromEnv())
(System.getProperty("sent.baseUrl") ?: System.getenv("SENT_BASE_URL"))?.let {
baseUrl(it)
}
Expand Down Expand Up @@ -437,7 +458,13 @@ private constructor(
return ClientOptions(
httpClient,
RetryingHttpClient.builder()
.httpClient(httpClient)
.httpClient(
LoggingHttpClient.builder()
.httpClient(httpClient)
.clock(clock)
.level(logLevel)
.build()
)
.sleeper(sleeper)
.clock(clock)
.maxRetries(maxRetries)
Expand All @@ -452,6 +479,7 @@ private constructor(
responseValidation,
timeout,
maxRetries,
logLevel,
apiKey,
)
}
Expand Down
33 changes: 33 additions & 0 deletions sent-java-core/src/main/kotlin/dm/sent/core/LogLevel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// File generated from our OpenAPI spec by Stainless.

package dm.sent.core

/** The level at which to log request and response information. */
enum class LogLevel {
/** No logging. */
OFF,
/** Minimal request and response summary logs. No headers or bodies are logged. */
INFO,
/** [INFO] logs plus details about request failures. */
ERROR,
/**
* Full request and response logs. Sensitive headers are redacted, but sensitive data in request
* and response bodies may still be visible.
*/
DEBUG;

/** Returns whether this level is at or higher than the given [level]. */
fun shouldLog(level: LogLevel): Boolean = ordinal >= level.ordinal

companion object {

/** Returns a [LogLevel] based on the `SENT_LOG` environment variable. */
fun fromEnv() =
when (System.getenv("SENT_LOG")?.lowercase()) {
"info" -> INFO
"error" -> ERROR
"debug" -> DEBUG
else -> OFF
}
}
}
6 changes: 6 additions & 0 deletions sent-java-core/src/main/kotlin/dm/sent/core/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package dm.sent.core
import dm.sent.errors.SentInvalidDataException
import java.util.Collections
import java.util.SortedMap
import java.util.SortedSet
import java.util.concurrent.CompletableFuture
import java.util.concurrent.locks.Lock

Expand All @@ -16,6 +17,11 @@ internal fun <T : Any> T?.getOrThrow(name: String): T =
internal fun <T> List<T>.toImmutable(): List<T> =
if (isEmpty()) Collections.emptyList() else Collections.unmodifiableList(toList())

@JvmSynthetic
internal fun <V : Comparable<V>> SortedSet<V>.toImmutable(): SortedSet<V> =
if (isEmpty()) Collections.emptySortedSet()
else Collections.unmodifiableSortedSet(toSortedSet(comparator() ?: Comparator.naturalOrder()))

@JvmSynthetic
internal fun <K, V> Map<K, V>.toImmutable(): Map<K, V> =
if (isEmpty()) immutableEmptyMap() else Collections.unmodifiableMap(toMap())
Expand Down
Loading
Loading