Skip to content

Commit 36f84a6

Browse files
committed
fix: exclude user-caused multipart exceptions from telemetry
Add EXCLUDE_TELEMETRY marker to all log.debug calls in PartHelper/MultipartHelper that handle exceptions from user-controlled data (malformed parts, stream I/O failures). These are not actionable from the agent side and would pollute telemetry signal. The MethodHandle invocation failure in PartHelper.getAllParts is intentionally left without the marker — that failure IS actionable as it indicates an instrumentation-internal issue.
1 parent ff703f4 commit 36f84a6

5 files changed

Lines changed: 26 additions & 23 deletions

File tree

  • dd-java-agent/instrumentation/jetty/jetty-appsec

dd-java-agent/instrumentation/jetty/jetty-appsec/jetty-appsec-11.0/src/main/java/datadog/trace/instrumentation/jetty11/MultipartHelper.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package datadog.trace.instrumentation.jetty11;
22

33
import static datadog.trace.api.gateway.Events.EVENTS;
4+
import static datadog.trace.api.telemetry.LogCollector.EXCLUDE_TELEMETRY;
45

56
import datadog.appsec.api.blocking.BlockingException;
67
import datadog.trace.api.Config;
@@ -49,7 +50,7 @@ public static List<String> extractFilenames(Collection<Part> parts) {
4950
}
5051
} catch (Exception ignored) {
5152
// malformed or inaccessible part — skip and continue with remaining parts
52-
log.debug("extractFilenames: skipping malformed part", ignored);
53+
log.debug(EXCLUDE_TELEMETRY, "extractFilenames: skipping malformed part", ignored);
5354
}
5455
}
5556
return filenames;
@@ -77,7 +78,7 @@ public static List<String> extractContents(Collection<Part> parts) {
7778
}
7879
contents.add(readFileContent(part));
7980
} catch (Exception ignored) {
80-
log.debug("extractContents: skipping malformed part", ignored);
81+
log.debug(EXCLUDE_TELEMETRY, "extractContents: skipping malformed part", ignored);
8182
}
8283
}
8384
return contents;
@@ -87,7 +88,7 @@ private static String readFileContent(Part part) {
8788
try (InputStream is = part.getInputStream()) {
8889
return MultipartContentDecoder.readInputStream(is, MAX_CONTENT_BYTES, part.getContentType());
8990
} catch (Exception e) {
90-
log.debug("readFileContent: stream read failed", e);
91+
log.debug(EXCLUDE_TELEMETRY, "readFileContent: stream read failed", e);
9192
return "";
9293
}
9394
}

dd-java-agent/instrumentation/jetty/jetty-appsec/jetty-appsec-8.1.3/src/main/java/datadog/trace/instrumentation/jetty8/PartHelper.java

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package datadog.trace.instrumentation.jetty8;
22

33
import static datadog.trace.api.gateway.Events.EVENTS;
4+
import static datadog.trace.api.telemetry.LogCollector.EXCLUDE_TELEMETRY;
45

56
import datadog.appsec.api.blocking.BlockingException;
67
import datadog.trace.api.Config;
@@ -104,7 +105,7 @@ public static List<String> extractFilenames(Collection<?> parts) {
104105
filenames.add(filename);
105106
}
106107
} catch (Exception e) {
107-
log.debug("extractFilenames: skipping malformed part", e);
108+
log.debug(EXCLUDE_TELEMETRY, "extractFilenames: skipping malformed part", e);
108109
}
109110
}
110111
return filenames;
@@ -122,11 +123,10 @@ public static Map<String, List<String>> extractFormFields(Collection<?> parts) {
122123
if (parts == null || parts.isEmpty()) {
123124
return Collections.emptyMap();
124125
}
125-
int maxFields = Config.get().getAppSecMaxFileContentCount();
126126
Map<String, List<String>> result = new LinkedHashMap<>();
127127
int count = 0;
128128
for (Object obj : parts) {
129-
if (count >= maxFields) {
129+
if (count >= MAX_FILES_TO_INSPECT) {
130130
break;
131131
}
132132
try {
@@ -145,7 +145,7 @@ public static Map<String, List<String>> extractFormFields(Collection<?> parts) {
145145
result.computeIfAbsent(name, k -> new ArrayList<>()).add(value);
146146
count++;
147147
} catch (Exception e) {
148-
log.debug("extractFormFields: skipping malformed part", e);
148+
log.debug(EXCLUDE_TELEMETRY, "extractFormFields: skipping malformed part", e);
149149
}
150150
}
151151
return result;
@@ -295,7 +295,7 @@ public static List<String> extractContents(Collection<?> parts) {
295295
}
296296
contents.add(readFileContent(part));
297297
} catch (Exception e) {
298-
log.debug("extractContents: skipping malformed part", e);
298+
log.debug(EXCLUDE_TELEMETRY, "extractContents: skipping malformed part", e);
299299
}
300300
}
301301
return contents;
@@ -305,7 +305,7 @@ private static String readFileContent(Part part) {
305305
try (InputStream is = part.getInputStream()) {
306306
return MultipartContentDecoder.readInputStream(is, MAX_CONTENT_BYTES, part.getContentType());
307307
} catch (Exception e) {
308-
log.debug("readFileContent: stream read failed", e);
308+
log.debug(EXCLUDE_TELEMETRY, "readFileContent: stream read failed", e);
309309
return "";
310310
}
311311
}
@@ -344,23 +344,22 @@ public static BlockingException fireFilesContentEvent(
344344
private static String readPartContent(Part part) {
345345
Charset charset = charsetFromContentType(part.getContentType());
346346
// Bound the buffered form-field text by the file-content byte cap. There is no dedicated
347-
// "max form-field bytes" config, so we intentionally reuse getAppSecMaxFileContentBytes():
347+
// "max form-field bytes" config, so we intentionally reuse MAX_CONTENT_BYTES:
348348
// this is the only framework that must manually buffer form-field text (Servlet 3.0 has no
349349
// container-side bound), and without a cap a single huge text field could exhaust the heap.
350-
int maxBytes = Config.get().getAppSecMaxFileContentBytes();
351350
try (InputStream is = part.getInputStream()) {
352351
ByteArrayOutputStream baos = new ByteArrayOutputStream();
353352
byte[] buf = new byte[4096];
354353
int total = 0;
355354
int read;
356-
while (total < maxBytes
357-
&& (read = is.read(buf, 0, Math.min(buf.length, maxBytes - total))) != -1) {
355+
while (total < MAX_CONTENT_BYTES
356+
&& (read = is.read(buf, 0, Math.min(buf.length, MAX_CONTENT_BYTES - total))) != -1) {
358357
baos.write(buf, 0, read);
359358
total += read;
360359
}
361360
return new String(baos.toByteArray(), charset);
362361
} catch (IOException e) {
363-
log.debug("readPartContent: stream read failed", e);
362+
log.debug(EXCLUDE_TELEMETRY, "readPartContent: stream read failed", e);
364363
return null;
365364
}
366365
}

dd-java-agent/instrumentation/jetty/jetty-appsec/jetty-appsec-9.2/src/main/java/datadog/trace/instrumentation/jetty92/MultipartHelper.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package datadog.trace.instrumentation.jetty92;
22

33
import static datadog.trace.api.gateway.Events.EVENTS;
4+
import static datadog.trace.api.telemetry.LogCollector.EXCLUDE_TELEMETRY;
45

56
import datadog.appsec.api.blocking.BlockingException;
67
import datadog.trace.api.Config;
@@ -49,7 +50,7 @@ public static List<String> extractFilenames(Collection<Part> parts) {
4950
}
5051
} catch (Exception ignored) {
5152
// malformed or inaccessible part — skip and continue with remaining parts
52-
log.debug("extractFilenames: skipping malformed part", ignored);
53+
log.debug(EXCLUDE_TELEMETRY, "extractFilenames: skipping malformed part", ignored);
5354
}
5455
}
5556
return filenames;
@@ -77,7 +78,7 @@ public static List<String> extractContents(Collection<Part> parts) {
7778
}
7879
contents.add(readFileContent(part));
7980
} catch (Exception ignored) {
80-
log.debug("extractContents: skipping malformed part", ignored);
81+
log.debug(EXCLUDE_TELEMETRY, "extractContents: skipping malformed part", ignored);
8182
}
8283
}
8384
return contents;
@@ -87,7 +88,7 @@ private static String readFileContent(Part part) {
8788
try (InputStream is = part.getInputStream()) {
8889
return MultipartContentDecoder.readInputStream(is, MAX_CONTENT_BYTES, part.getContentType());
8990
} catch (Exception e) {
90-
log.debug("readFileContent: stream read failed", e);
91+
log.debug(EXCLUDE_TELEMETRY, "readFileContent: stream read failed", e);
9192
return "";
9293
}
9394
}

dd-java-agent/instrumentation/jetty/jetty-appsec/jetty-appsec-9.3/src/main/java/datadog/trace/instrumentation/jetty93/MultipartHelper.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package datadog.trace.instrumentation.jetty93;
22

33
import static datadog.trace.api.gateway.Events.EVENTS;
4+
import static datadog.trace.api.telemetry.LogCollector.EXCLUDE_TELEMETRY;
45

56
import datadog.appsec.api.blocking.BlockingException;
67
import datadog.trace.api.Config;
@@ -49,7 +50,7 @@ public static List<String> extractFilenames(Collection<Part> parts) {
4950
}
5051
} catch (Exception ignored) {
5152
// malformed or inaccessible part — skip and continue with remaining parts
52-
log.debug("extractFilenames: skipping malformed part", ignored);
53+
log.debug(EXCLUDE_TELEMETRY, "extractFilenames: skipping malformed part", ignored);
5354
}
5455
}
5556
return filenames;
@@ -77,7 +78,7 @@ public static List<String> extractContents(Collection<Part> parts) {
7778
}
7879
contents.add(readFileContent(part));
7980
} catch (Exception ignored) {
80-
log.debug("extractContents: skipping malformed part", ignored);
81+
log.debug(EXCLUDE_TELEMETRY, "extractContents: skipping malformed part", ignored);
8182
}
8283
}
8384
return contents;
@@ -87,7 +88,7 @@ private static String readFileContent(Part part) {
8788
try (InputStream is = part.getInputStream()) {
8889
return MultipartContentDecoder.readInputStream(is, MAX_CONTENT_BYTES, part.getContentType());
8990
} catch (Exception e) {
90-
log.debug("readFileContent: stream read failed", e);
91+
log.debug(EXCLUDE_TELEMETRY, "readFileContent: stream read failed", e);
9192
return "";
9293
}
9394
}

dd-java-agent/instrumentation/jetty/jetty-appsec/jetty-appsec-9.4/src/main/java/datadog/trace/instrumentation/jetty94/MultipartHelper.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package datadog.trace.instrumentation.jetty94;
22

33
import static datadog.trace.api.gateway.Events.EVENTS;
4+
import static datadog.trace.api.telemetry.LogCollector.EXCLUDE_TELEMETRY;
45

56
import datadog.appsec.api.blocking.BlockingException;
67
import datadog.trace.api.Config;
@@ -49,7 +50,7 @@ public static List<String> extractFilenames(Collection<Part> parts) {
4950
}
5051
} catch (Exception ignored) {
5152
// malformed or inaccessible part — skip and continue with remaining parts
52-
log.debug("extractFilenames: skipping malformed part", ignored);
53+
log.debug(EXCLUDE_TELEMETRY, "extractFilenames: skipping malformed part", ignored);
5354
}
5455
}
5556
return filenames;
@@ -77,7 +78,7 @@ public static List<String> extractContents(Collection<Part> parts) {
7778
}
7879
contents.add(readFileContent(part));
7980
} catch (Exception ignored) {
80-
log.debug("extractContents: skipping malformed part", ignored);
81+
log.debug(EXCLUDE_TELEMETRY, "extractContents: skipping malformed part", ignored);
8182
}
8283
}
8384
return contents;
@@ -87,7 +88,7 @@ private static String readFileContent(Part part) {
8788
try (InputStream is = part.getInputStream()) {
8889
return MultipartContentDecoder.readInputStream(is, MAX_CONTENT_BYTES, part.getContentType());
8990
} catch (Exception e) {
90-
log.debug("readFileContent: stream read failed", e);
91+
log.debug(EXCLUDE_TELEMETRY, "readFileContent: stream read failed", e);
9192
return "";
9293
}
9394
}

0 commit comments

Comments
 (0)