Skip to content

Commit c5b39b1

Browse files
authored
feat: use shaded protobuf-java , instead of applications (#414)
* test to use shaded util, instead of client * muzzle fix * nit fix * feat spotlessApply * refactor code
1 parent 1036b35 commit c5b39b1

File tree

4 files changed

+106
-13
lines changed

4 files changed

+106
-13
lines changed

instrumentation/grpc-1.6/build.gradle.kts

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ muzzle {
1515
group = "io.grpc"
1616
module = "grpc-core"
1717
versions = "[1.6.0,)"
18-
// for body capture via com.google.protobuf.Message to exist always
18+
1919
extraDependency("com.google.protobuf:protobuf-java:3.3.1")
2020
extraDependency("io.grpc:grpc-netty:1.6.0")
2121
}

instrumentation/grpc-1.6/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/grpc/v1_6/GrpcSpanDecorator.java

+6-8
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,10 @@
2323
import io.opentelemetry.api.trace.Span;
2424
import io.opentelemetry.javaagent.instrumentation.hypertrace.com.google.protobuf.util.JsonFormat;
2525
import io.opentelemetry.javaagent.instrumentation.hypertrace.grpc.GrpcSemanticAttributes;
26-
import java.io.IOException;
2726
import java.util.LinkedHashMap;
2827
import java.util.Map;
2928
import java.util.function.Function;
3029
import org.hypertrace.agent.core.instrumentation.HypertraceSemanticAttributes;
31-
import org.hypertrace.agent.core.instrumentation.buffer.BoundedBuffersFactory;
32-
import org.hypertrace.agent.core.instrumentation.buffer.BoundedCharArrayWriter;
3330
import org.slf4j.Logger;
3431
import org.slf4j.LoggerFactory;
3532

@@ -44,12 +41,13 @@ public static void addMessageAttribute(Object message, Span span, AttributeKey<S
4441
if (message instanceof Message) {
4542
Message mb = (Message) message;
4643
try {
47-
BoundedCharArrayWriter writer = BoundedBuffersFactory.createWriter();
48-
PRINTER.appendTo(mb, writer);
49-
span.setAttribute(key, writer.toString());
50-
} catch (IOException e) {
51-
log.error("Failed to decode message to JSON", e);
44+
String jsonOutput = ProtobufMessageConverter.getMessage(mb);
45+
span.setAttribute(key, jsonOutput);
46+
} catch (Exception e) {
47+
log.error("Failed to decode message as JSON", e);
5248
}
49+
} else {
50+
log.debug("message is not an instance of com.google.protobuf.Message");
5351
}
5452
}
5553

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
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 io.opentelemetry.javaagent.instrumentation.hypertrace.grpc.v1_6;
18+
19+
import com.google.protobuf.Descriptors;
20+
import com.google.protobuf.Message;
21+
import io.opentelemetry.javaagent.instrumentation.hypertrace.com.google.protobuf.DescriptorProtos.FileDescriptorProto;
22+
import io.opentelemetry.javaagent.instrumentation.hypertrace.com.google.protobuf.Descriptors.Descriptor;
23+
import io.opentelemetry.javaagent.instrumentation.hypertrace.com.google.protobuf.Descriptors.FileDescriptor;
24+
import io.opentelemetry.javaagent.instrumentation.hypertrace.com.google.protobuf.DynamicMessage;
25+
import io.opentelemetry.javaagent.instrumentation.hypertrace.com.google.protobuf.util.JsonFormat;
26+
import org.slf4j.Logger;
27+
import org.slf4j.LoggerFactory;
28+
29+
public class ProtobufMessageConverter {
30+
private static final Logger log = LoggerFactory.getLogger(ProtobufMessageConverter.class);
31+
/**
32+
* Converts an unrelocated protobuf message into a relocated DynamicMessage via a byte-array
33+
* round-trip.
34+
*
35+
* @param message The original protobuf message (an instance of com.google.protobuf.Message).
36+
* @return A relocated DynamicMessage built from your relocated protobuf classes.
37+
* @throws Exception if conversion fails.
38+
*/
39+
public static DynamicMessage convertToRelocatedDynamicMessage(Message message) throws Exception {
40+
// 1. Serialize the original message to bytes.
41+
byte[] messageBytes = message.toByteArray();
42+
43+
// 2. Obtain the original (unrelocated) message descriptor.
44+
Descriptors.Descriptor originalDescriptor = message.getDescriptorForType();
45+
46+
// 3. Get the unrelocated file descriptor and its proto representation.
47+
Descriptors.FileDescriptor unrelocatedFileDescriptor = originalDescriptor.getFile();
48+
com.google.protobuf.DescriptorProtos.FileDescriptorProto unrelocatedFileProto =
49+
unrelocatedFileDescriptor.toProto();
50+
byte[] fileProtoBytes = unrelocatedFileProto.toByteArray();
51+
52+
// 4. Parse the file descriptor proto using relocated classes.
53+
// This converts the unrelocated FileDescriptorProto into your relocated FileDescriptorProto.
54+
FileDescriptorProto relocatedFileProto = FileDescriptorProto.parseFrom(fileProtoBytes);
55+
56+
// 5. Build the relocated FileDescriptor.
57+
FileDescriptor relocatedFileDescriptor =
58+
FileDescriptor.buildFrom(relocatedFileProto, new FileDescriptor[] {});
59+
60+
// 6. Find the relocated message descriptor by name.
61+
Descriptor relocatedDescriptor =
62+
relocatedFileDescriptor.findMessageTypeByName(originalDescriptor.getName());
63+
if (relocatedDescriptor == null) {
64+
throw new IllegalStateException(
65+
"Could not find relocated descriptor for message type: " + originalDescriptor.getName());
66+
}
67+
68+
// 7. Parse the original message bytes using the relocated descriptor.
69+
DynamicMessage relocatedMessage = DynamicMessage.parseFrom(relocatedDescriptor, messageBytes);
70+
return relocatedMessage;
71+
}
72+
73+
/**
74+
* Method that takes an incoming message, converts it to a relocated one, prints it as JSON using
75+
* the relocated JsonFormat
76+
*
77+
* @param message The incoming (unrelocated) protobuf message.
78+
*/
79+
public static String getMessage(Message message) {
80+
try {
81+
// Convert the unrelocated message into a relocated DynamicMessage.
82+
DynamicMessage relocatedMessage = convertToRelocatedDynamicMessage(message);
83+
84+
// Use the relocated JsonFormat to print the message as JSON.
85+
JsonFormat.Printer relocatedPrinter = JsonFormat.printer();
86+
String jsonOutput = relocatedPrinter.print(relocatedMessage);
87+
88+
return jsonOutput;
89+
} catch (Exception e) {
90+
log.error("Failed to convert message with relocated protobuf message: {}", e.getMessage());
91+
}
92+
return "";
93+
}
94+
}

shaded-protobuf-java-util/build.gradle.kts

+5-4
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,18 @@ plugins {
44
}
55

66
dependencies {
7-
implementation("com.google.protobuf:protobuf-java-util:3.25.5") {
8-
exclude("com.google.protobuf", "protobuf-java")
9-
exclude("com.google.guava", "guava")
10-
}
7+
implementation("com.google.protobuf:protobuf-java-util:3.25.5")
8+
119
// fix vulnerability
1210
constraints {
1311
implementation("com.google.code.gson:gson:2.8.9")
1412
}
1513
}
1614

1715
tasks.shadowJar {
16+
relocate("com.google.protobuf", "io.opentelemetry.javaagent.instrumentation.hypertrace.com.google.protobuf")
1817
relocate("com.google.protobuf.util", "io.opentelemetry.javaagent.instrumentation.hypertrace.com.google.protobuf.util")
1918
relocate("com.google.gson", "io.opentelemetry.javaagent.instrumentation.hypertrace.com.google.gson")
19+
relocate("com.google.common", "io.opentelemetry.javaagent.instrumentation.hypertrace.com.google.common") // Add this
20+
relocate("com.google.guava", "io.opentelemetry.javaagent.instrumentation.hypertrace.com.google.guava")
2021
}

0 commit comments

Comments
 (0)