Skip to content

Commit 18ed548

Browse files
authored
Use bounded size buffers (#181)
* Use bounded size buffers Signed-off-by: Pavol Loffay <[email protected]> * Use config Signed-off-by: Pavol Loffay <[email protected]>
1 parent 56d5f1f commit 18ed548

File tree

15 files changed

+199
-9
lines changed

15 files changed

+199
-9
lines changed

instrumentation/apache-httpclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/apachehttpclient/v4_0/ApacheClientInstrumentationModule.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import org.apache.http.HttpMessage;
5252
import org.apache.http.HttpResponse;
5353
import org.hypertrace.agent.config.Config.AgentConfig;
54+
import org.hypertrace.agent.core.BoundedByteArrayOutputStreamFactory;
5455
import org.hypertrace.agent.core.ContentEncodingUtils;
5556
import org.hypertrace.agent.core.ContentLengthUtils;
5657
import org.hypertrace.agent.core.ContentTypeUtils;
@@ -238,7 +239,7 @@ public static void exit(@Advice.This HttpEntity thizz, @Advice.Return InputStrea
238239
SpanAndBuffer spanAndBuffer =
239240
new SpanAndBuffer(
240241
clientSpan,
241-
new ByteArrayOutputStream((int) contentSize),
242+
BoundedByteArrayOutputStreamFactory.create((int) contentSize),
242243
HypertraceSemanticAttributes.HTTP_RESPONSE_BODY,
243244
charset);
244245
GlobalObjectRegistry.inputStreamToSpanAndBufferMap.put(inputStream, spanAndBuffer);
@@ -257,7 +258,8 @@ public static void enter(
257258
if (contentSize <= 0 || contentSize == Long.MAX_VALUE) {
258259
contentSize = ContentLengthUtils.DEFAULT;
259260
}
260-
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream((int) contentSize);
261+
ByteArrayOutputStream byteArrayOutputStream =
262+
BoundedByteArrayOutputStreamFactory.create((int) contentSize);
261263

262264
GlobalObjectRegistry.outputStreamToBufferMap.put(outputStream, byteArrayOutputStream);
263265
}

instrumentation/apache-httpclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/apachehttpclient/v4_0/ApacheHttpClientUtils.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.apache.http.HttpEntityEnclosingRequest;
3030
import org.apache.http.HttpMessage;
3131
import org.hypertrace.agent.config.Config.AgentConfig;
32+
import org.hypertrace.agent.core.BoundedByteArrayOutputStreamFactory;
3233
import org.hypertrace.agent.core.ContentEncodingUtils;
3334
import org.hypertrace.agent.core.HypertraceConfig;
3435
import org.hypertrace.agent.core.HypertraceSemanticAttributes;
@@ -81,7 +82,7 @@ public static void traceEntity(Span span, String bodyAttributeKey, HttpEntity en
8182

8283
if (entity.isRepeatable()) {
8384
try {
84-
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
85+
ByteArrayOutputStream byteArrayOutputStream = BoundedByteArrayOutputStreamFactory.create();
8586
entity.writeTo(byteArrayOutputStream);
8687
String encoding =
8788
entity.getContentEncoding() != null ? entity.getContentEncoding().getValue() : "";

instrumentation/apache-httpclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/apachehttpclient/v4_0/readall/ApacheClientReadAllInstrumentationModule.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import org.apache.http.Header;
4949
import org.apache.http.HttpEntity;
5050
import org.apache.http.HttpResponse;
51+
import org.hypertrace.agent.core.BoundedByteArrayOutputStreamFactory;
5152
import org.hypertrace.agent.core.ContentTypeUtils;
5253
import org.hypertrace.agent.core.GlobalObjectRegistry;
5354
import org.hypertrace.agent.core.HypertraceSemanticAttributes;
@@ -195,7 +196,8 @@ public static void exit(@Return Object response) {
195196
}
196197

197198
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
198-
ByteArrayOutputStream buffer = new ByteArrayOutputStream((int) contentSize);
199+
ByteArrayOutputStream buffer =
200+
BoundedByteArrayOutputStreamFactory.create((int) contentSize);
199201
byte ch;
200202
while ((ch = (byte) bufferedInputStream.read()) != -1) {
201203
buffer.write(ch);

instrumentation/jaxrs-client-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/jaxrs/v2_0/JaxrsClientEntityInterceptor.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import javax.ws.rs.ext.WriterInterceptor;
3232
import javax.ws.rs.ext.WriterInterceptorContext;
3333
import org.hypertrace.agent.config.Config.AgentConfig;
34+
import org.hypertrace.agent.core.BoundedByteArrayOutputStreamFactory;
3435
import org.hypertrace.agent.core.ContentEncodingUtils;
3536
import org.hypertrace.agent.core.ContentLengthUtils;
3637
import org.hypertrace.agent.core.ContentTypeUtils;
@@ -78,7 +79,7 @@ public Object aroundReadFrom(ReaderInterceptorContext responseContext)
7879
String contentLengthStr = responseContext.getHeaders().getFirst(HttpHeaders.CONTENT_LENGTH);
7980
int contentLength = ContentLengthUtils.parseLength(contentLengthStr);
8081

81-
ByteArrayOutputStream buffer = new ByteArrayOutputStream(contentLength);
82+
ByteArrayOutputStream buffer = BoundedByteArrayOutputStreamFactory.create(contentLength);
8283
GlobalObjectRegistry.inputStreamToSpanAndBufferMap.put(
8384
entityStream,
8485
new SpanAndBuffer(
@@ -118,7 +119,7 @@ public void aroundWriteTo(WriterInterceptorContext requestContext)
118119
}
119120

120121
// TODO length is not known
121-
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
122+
ByteArrayOutputStream buffer = BoundedByteArrayOutputStreamFactory.create();
122123
OutputStream entityStream = requestContext.getOutputStream();
123124
try {
124125
GlobalObjectRegistry.outputStreamToBufferMap.put(entityStream, buffer);

instrumentation/servlet/servlet-common/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/servlet/common/ByteBufferData.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@
1919
import java.nio.charset.Charset;
2020
import java.nio.charset.StandardCharsets;
2121
import java.util.Arrays;
22+
import org.hypertrace.agent.core.HypertraceConfig;
2223

2324
public class ByteBufferData {
2425

2526
private static final int MIN_BUFFER_SIZE = 128;
26-
private static final int MAX_BUFFER_SIZE = 1048576; // 1MB
27+
private static final int MAX_BUFFER_SIZE =
28+
HypertraceConfig.get().getDataCapture().getBodyMaxSizeBytes().getValue();
2729
private static final int GROW_FACTOR = 4;
2830
private static final Charset ISO_8859_1 = StandardCharsets.ISO_8859_1;
2931
private Charset charset;

instrumentation/servlet/servlet-common/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/servlet/common/CharBufferData.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@
1717
package io.opentelemetry.javaagent.instrumentation.hypertrace.servlet.common;
1818

1919
import java.util.Arrays;
20+
import org.hypertrace.agent.core.HypertraceConfig;
2021

2122
public class CharBufferData {
2223

2324
private static final int MIN_BUFFER_SIZE = 128;
24-
private static final int MAX_BUFFER_SIZE = 1048576; // 1MB
25+
private static final int MAX_BUFFER_SIZE =
26+
HypertraceConfig.get().getDataCapture().getBodyMaxSizeBytes().getValue();
2527
private static final int GROW_FACTOR = 4;
2628
private char[] buffer;
2729
private int bufferLen;
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright The Hypertrace Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.hypertrace.agent.core;
18+
19+
import java.io.ByteArrayOutputStream;
20+
import java.io.IOException;
21+
22+
/**
23+
* {@link ByteArrayOutputStream} with a bounded capacity. Write methods are no-op if the size
24+
* reaches the maximum capacity.
25+
*/
26+
public class BoundedByteArrayOutputStream extends ByteArrayOutputStream {
27+
28+
private final int maxCapacity;
29+
30+
BoundedByteArrayOutputStream(int maxCapacity) {
31+
this.maxCapacity = maxCapacity;
32+
}
33+
34+
BoundedByteArrayOutputStream(int maxCapacity, int size) {
35+
super(size);
36+
this.maxCapacity = maxCapacity;
37+
}
38+
39+
@Override
40+
public synchronized void write(int b) {
41+
if (size() == maxCapacity) {
42+
return;
43+
}
44+
super.write(b);
45+
}
46+
47+
@Override
48+
public void write(byte[] b) throws IOException {
49+
// ByteArrayOutputStream calls write(b, off, len)
50+
super.write(b);
51+
}
52+
53+
@Override
54+
public synchronized void write(byte[] b, int off, int len) {
55+
int size = size();
56+
if (size + len > maxCapacity) {
57+
super.write(b, off, maxCapacity - size);
58+
return;
59+
}
60+
super.write(b, off, len);
61+
}
62+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright The Hypertrace Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.hypertrace.agent.core;
18+
19+
public class BoundedByteArrayOutputStreamFactory {
20+
21+
private static final int DEFAULT_SIZE = 128;
22+
23+
public static BoundedByteArrayOutputStream create() {
24+
return new BoundedByteArrayOutputStream(DEFAULT_SIZE);
25+
}
26+
27+
public static BoundedByteArrayOutputStream create(int initialSize) {
28+
if (initialSize > DEFAULT_SIZE) {
29+
initialSize = DEFAULT_SIZE;
30+
}
31+
return new BoundedByteArrayOutputStream(DEFAULT_SIZE, initialSize);
32+
}
33+
}

javaagent-core/src/main/java/org/hypertrace/agent/core/EnvironmentConfig.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ private EnvironmentConfig() {}
4747
static final String OPA_POLL_PERIOD = OPA_PREFIX + "poll.period.seconds";
4848

4949
private static final String CAPTURE_PREFIX = HT_PREFIX + "data.capture.";
50+
public static final String CAPTURE_BODY_MAX_SIZE_BYTES = CAPTURE_PREFIX + "body.max.size.bytes";
5051
public static final String CAPTURE_HTTP_HEADERS_PREFIX = CAPTURE_PREFIX + "http.headers.";
5152
public static final String CAPTURE_HTTP_BODY_PREFIX = CAPTURE_PREFIX + "http.body.";
5253
public static final String CAPTURE_RPC_METADATA_PREFIX = CAPTURE_PREFIX + "rpc.metadata.";
@@ -106,6 +107,11 @@ private static Opa.Builder applyOpa(Opa.Builder builder) {
106107
}
107108

108109
private static DataCapture.Builder setDefaultsToDataCapture(DataCapture.Builder builder) {
110+
String bodyMaxSizeBytes = getProperty(CAPTURE_BODY_MAX_SIZE_BYTES);
111+
if (bodyMaxSizeBytes != null) {
112+
builder.setBodyMaxSizeBytes(
113+
Int32Value.newBuilder().setValue(Integer.valueOf(bodyMaxSizeBytes)).build());
114+
}
109115
builder.setHttpHeaders(
110116
applyMessageDefaults(builder.getHttpHeaders().toBuilder(), CAPTURE_HTTP_HEADERS_PREFIX));
111117
builder.setHttpBody(

javaagent-core/src/main/java/org/hypertrace/agent/core/HypertraceConfig.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ private HypertraceConfig() {}
5757
static final String DEFAULT_REPORTING_ENDPOINT = "http://localhost:9411/api/v2/spans";
5858
static final String DEFAULT_OPA_ENDPOINT = "http://opa.traceableai:8181/";
5959
static final int DEFAULT_OPA_POLL_PERIOD_SECONDS = 30;
60+
// 128 KiB
61+
static final int DEFAULT_BODY_MAX_SIZE_BYTES = 128 * 1024;
6062

6163
public static AgentConfig get() {
6264
if (agentConfig == null) {
@@ -199,6 +201,10 @@ private static DataCapture.Builder setDefaultsToDataCapture(DataCapture.Builder
199201
builder.setHttpBody(applyMessageDefaults(builder.getHttpBody().toBuilder()));
200202
builder.setRpcMetadata(applyMessageDefaults(builder.getRpcMetadata().toBuilder()));
201203
builder.setRpcBody(applyMessageDefaults(builder.getRpcBody().toBuilder()));
204+
if (!builder.hasBodyMaxSizeBytes()) {
205+
builder.setBodyMaxSizeBytes(
206+
Int32Value.newBuilder().setValue(DEFAULT_BODY_MAX_SIZE_BYTES).build());
207+
}
202208
return builder;
203209
}
204210

0 commit comments

Comments
 (0)