@@ -80,8 +80,13 @@ public void indexDocument(final Document document) {
8080 // (auth and configurable index name applied via applyAuth() and indexName())
8181 final HttpResponse <String > resp = httpClient .send (req , HttpResponse .BodyHandlers .ofString ());
8282 if (resp .statusCode () / 100 != 2 ) {
83- log .warn ("OpenSearch indexing returned HTTP {} for document {} ({}): {}" ,
84- resp .statusCode (), document .getId (), url , truncate (resp .body ()));
83+ // Do not log resp.body() — a non-2xx index response from OpenSearch echoes
84+ // parts of the request payload, which carries the document's PII-bearing
85+ // originalText. Body length is enough for an operator to tell a parse error
86+ // (a few bytes) from a quota / mapping error (a longer JSON envelope).
87+ log .warn ("OpenSearch indexing returned HTTP {} for document {} ({}); body length {}" ,
88+ resp .statusCode (), document .getId (), url ,
89+ resp .body () == null ? 0 : resp .body ().length ());
8590 }
8691 } catch (Exception e ) {
8792 log .warn ("OpenSearch indexing failed for document {} at {}: {}" ,
@@ -184,8 +189,14 @@ public SearchResults search(final String query, final int from, final int size,
184189 return new SearchResults (0 , safeFrom , safeSize , List .of ());
185190 }
186191 if (resp .statusCode () / 100 != 2 ) {
187- log .warn ("OpenSearch search returned HTTP {} for query '{}': {}" ,
188- resp .statusCode (), query , truncate (resp .body ()));
192+ // Never log the raw query — users routinely search for PII (an email
193+ // address, a phone number, a partial name) and that string would land
194+ // in the log file. Never log the response body either — it contains
195+ // matched document originalText snippets. A length + status is enough
196+ // for triage; the OpenSearch cluster's own logs carry the full payload.
197+ log .warn ("OpenSearch search returned HTTP {} (query length {}, response length {})" ,
198+ resp .statusCode (), query .length (),
199+ resp .body () == null ? 0 : resp .body ().length ());
189200 return empty ;
190201 }
191202 final JsonNode root = objectMapper .readTree (resp .body ());
@@ -210,7 +221,9 @@ public SearchResults search(final String query, final int from, final int size,
210221 }
211222 return new SearchResults (total , safeFrom , safeSize , List .copyOf (hits ));
212223 } catch (Exception e ) {
213- log .warn ("OpenSearch search failed for query '{}' at {}: {}" , query , url , e .getMessage ());
224+ // Same reasoning as the non-2xx branch above — log only metadata.
225+ log .warn ("OpenSearch search failed at {} (query length {}): {}" ,
226+ url , query .length (), e .getMessage ());
214227 return empty ;
215228 }
216229 }
@@ -264,8 +277,11 @@ public SearchResults findSimilar(final String documentId, final String batchId,
264277 final HttpResponse <String > resp = httpClient .send (req , HttpResponse .BodyHandlers .ofString ());
265278 if (resp .statusCode () == 404 ) return empty ;
266279 if (resp .statusCode () / 100 != 2 ) {
267- log .warn ("OpenSearch findSimilar returned HTTP {} for document {}: {}" ,
268- resp .statusCode (), documentId , truncate (resp .body ()));
280+ // The findSimilar response body contains matched documents' originalText
281+ // snippets — never log it. Length is enough for triage.
282+ log .warn ("OpenSearch findSimilar returned HTTP {} for document {}; body length {}" ,
283+ resp .statusCode (), documentId ,
284+ resp .body () == null ? 0 : resp .body ().length ());
269285 return empty ;
270286 }
271287 final JsonNode root = objectMapper .readTree (resp .body ());
@@ -354,11 +370,6 @@ private HttpRequest.Builder applyAuth(final HttpRequest.Builder b) {
354370 return b ;
355371 }
356372
357- private static String truncate (final String s ) {
358- if (s == null ) return "" ;
359- return s .length () <= 200 ? s : s .substring (0 , 200 ) + "…" ;
360- }
361-
362373 /**
363374 * Render a highlight snippet as safe HTML. The raw snippet contains the surrounding
364375 * document text (which may include user-typed {@code <script>} payloads) bracketed by
0 commit comments