Skip to content

Commit cdd5bbe

Browse files
authored
ipc: extract content length from header (#1183)
If a `Content-Length` header is present and the payload length hasn't already been explicitly set, then try to extract from the header.
1 parent 4914a64 commit cdd5bbe

File tree

2 files changed

+66
-2
lines changed

2 files changed

+66
-2
lines changed

spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcLogEntry.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2023 Netflix, Inc.
2+
* Copyright 2014-2025 Netflix, Inc.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -40,6 +40,8 @@
4040
@SuppressWarnings({"PMD.ExcessiveClassLength", "PMD.AvoidStringBufferField"})
4141
public final class IpcLogEntry {
4242

43+
private static final String CONTENT_LENGTH = "Content-Length";
44+
4345
private final Clock clock;
4446

4547
private Registry registry;
@@ -526,6 +528,14 @@ public IpcLogEntry withUri(URI uri) {
526528
return withUri(uri.toString(), uri.getPath());
527529
}
528530

531+
private long parseContentLength(String value) {
532+
try {
533+
return Long.parseLong(value);
534+
} catch (NumberFormatException e) {
535+
return -1L;
536+
}
537+
}
538+
529539
/**
530540
* Set the length for the request entity if it is known at the time of logging. If the size
531541
* is not known, e.g. a chunked HTTP entity, then a negative value can be used and the length
@@ -559,6 +569,8 @@ public IpcLogEntry addRequestHeader(String name, String value) {
559569
withClientNode(value);
560570
} else if (vip == null && name.equalsIgnoreCase(NetflixHeader.Vip.headerName())) {
561571
withVip(value);
572+
} else if (requestContentLength < 0L && CONTENT_LENGTH.equalsIgnoreCase(name)) {
573+
withRequestContentLength(parseContentLength(value));
562574
} else if (isMeshRequest(name, value)) {
563575
disableMetrics();
564576
}
@@ -584,6 +596,8 @@ public IpcLogEntry addResponseHeader(String name, String value) {
584596
withServerNode(value);
585597
} else if (endpoint == null && name.equalsIgnoreCase(NetflixHeader.Endpoint.headerName())) {
586598
withEndpoint(value);
599+
} else if (responseContentLength < 0L && CONTENT_LENGTH.equalsIgnoreCase(name)) {
600+
withResponseContentLength(parseContentLength(value));
587601
}
588602
this.responseHeaders.add(new Header(name, value));
589603
return this;

spectator-ext-ipc/src/test/java/com/netflix/spectator/ipc/IpcLogEntryTest.java

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2024 Netflix, Inc.
2+
* Copyright 2014-2025 Netflix, Inc.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -394,6 +394,31 @@ public void addRequestAsgHeaderExplicitAsg() {
394394
Assertions.assertEquals("foo", map.get("clientAsg"));
395395
}
396396

397+
@Test
398+
public void addRequestContentLengthHeader() {
399+
Map<String, Object> map = entry
400+
.addRequestHeader("Content-Length", "123")
401+
.convert(this::toMap);
402+
Assertions.assertEquals(123, map.get("requestContentLength"));
403+
}
404+
405+
@Test
406+
public void addRequestContentLengthHeaderExplicitPreferred() {
407+
Map<String, Object> map = entry
408+
.withRequestContentLength(456)
409+
.addRequestHeader("Content-Length", "123")
410+
.convert(this::toMap);
411+
Assertions.assertEquals(456, map.get("requestContentLength"));
412+
}
413+
414+
@Test
415+
public void addRequestContentLengthHeaderInvalid() {
416+
Map<String, Object> map = entry
417+
.addRequestHeader("Content-Length", "foo")
418+
.convert(this::toMap);
419+
Assertions.assertNull(map.get("requestContentLength"));
420+
}
421+
397422
@Test
398423
public void addResponseAsgHeader() {
399424
Map<String, Object> map = entry
@@ -479,6 +504,31 @@ public void addResponseEndpointHeader() {
479504
Assertions.assertEquals("/api/v1/test", map.get("endpoint"));
480505
}
481506

507+
@Test
508+
public void addResponseContentLengthHeader() {
509+
Map<String, Object> map = entry
510+
.addResponseHeader("Content-Length", "123")
511+
.convert(this::toMap);
512+
Assertions.assertEquals(123, map.get("responseContentLength"));
513+
}
514+
515+
@Test
516+
public void addResponseContentLengthHeaderExplicitPreferred() {
517+
Map<String, Object> map = entry
518+
.withResponseContentLength(456)
519+
.addResponseHeader("Content-Length", "123")
520+
.convert(this::toMap);
521+
Assertions.assertEquals(456, map.get("responseContentLength"));
522+
}
523+
524+
@Test
525+
public void addResponseContentLengthHeaderInvalid() {
526+
Map<String, Object> map = entry
527+
.addResponseHeader("Content-Length", "foo")
528+
.convert(this::toMap);
529+
Assertions.assertNull(map.get("responseContentLength"));
530+
}
531+
482532
@Test
483533
public void source() {
484534
String expected = IpcSource.direct.value();

0 commit comments

Comments
 (0)