Skip to content

Commit e076234

Browse files
authored
passing dependencies to protobuf (#418)
1 parent d0f7aa7 commit e076234

File tree

1 file changed

+69
-22
lines changed

1 file changed

+69
-22
lines changed

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

+69-22
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,17 @@
2323
import io.opentelemetry.javaagent.instrumentation.hypertrace.com.google.protobuf.Descriptors.FileDescriptor;
2424
import io.opentelemetry.javaagent.instrumentation.hypertrace.com.google.protobuf.DynamicMessage;
2525
import io.opentelemetry.javaagent.instrumentation.hypertrace.com.google.protobuf.util.JsonFormat;
26+
import java.util.ArrayList;
27+
import java.util.HashMap;
28+
import java.util.List;
29+
import java.util.Map;
2630
import org.slf4j.Logger;
2731
import org.slf4j.LoggerFactory;
2832

2933
public class ProtobufMessageConverter {
3034
private static final Logger log = LoggerFactory.getLogger(ProtobufMessageConverter.class);
35+
private static final Map<String, FileDescriptor> fileDescriptorCache = new HashMap<>();
36+
3137
/**
3238
* Converts an unrelocated protobuf message into a relocated DynamicMessage via a byte-array
3339
* round-trip.
@@ -43,31 +49,64 @@ public static DynamicMessage convertToRelocatedDynamicMessage(Message message) t
4349
// 2. Obtain the original (unrelocated) message descriptor.
4450
Descriptors.Descriptor originalDescriptor = message.getDescriptorForType();
4551

46-
// 3. Get the unrelocated file descriptor and its proto representation.
52+
// 3. Build the relocated descriptor with all dependencies
53+
Descriptor relocatedDescriptor = getRelocatedDescriptor(originalDescriptor);
54+
if (relocatedDescriptor == null) {
55+
throw new IllegalStateException(
56+
"Could not find relocated descriptor for message type: "
57+
+ originalDescriptor.getFullName());
58+
}
59+
60+
// 4. Parse the original message bytes using the relocated descriptor.
61+
try {
62+
return DynamicMessage.parseFrom(relocatedDescriptor, messageBytes);
63+
} catch (Exception e) {
64+
log.debug("Failed to parse message bytes using relocated descriptor: {}", e.getMessage());
65+
throw e;
66+
}
67+
}
68+
69+
/** Recursively builds relocated file descriptors with all dependencies. */
70+
private static Descriptor getRelocatedDescriptor(Descriptors.Descriptor originalDescriptor)
71+
throws Exception {
4772
Descriptors.FileDescriptor unrelocatedFileDescriptor = originalDescriptor.getFile();
73+
74+
// Check if we've already processed this file descriptor
75+
String fileKey = unrelocatedFileDescriptor.getName();
76+
if (fileDescriptorCache.containsKey(fileKey)) {
77+
FileDescriptor relocatedFileDescriptor = fileDescriptorCache.get(fileKey);
78+
return relocatedFileDescriptor.findMessageTypeByName(originalDescriptor.getName());
79+
}
80+
81+
// Process all dependencies first
82+
List<FileDescriptor> dependencies = new ArrayList<>();
83+
for (Descriptors.FileDescriptor dependency : unrelocatedFileDescriptor.getDependencies()) {
84+
String depKey = dependency.getName();
85+
if (!fileDescriptorCache.containsKey(depKey)) {
86+
// Convert the dependency file descriptor
87+
com.google.protobuf.DescriptorProtos.FileDescriptorProto depProto = dependency.toProto();
88+
byte[] depBytes = depProto.toByteArray();
89+
FileDescriptorProto relocatedDepProto = FileDescriptorProto.parseFrom(depBytes);
90+
91+
// Build with empty dependencies first (we'll fill them in later)
92+
FileDescriptor relocatedDep =
93+
FileDescriptor.buildFrom(relocatedDepProto, new FileDescriptor[] {});
94+
fileDescriptorCache.put(depKey, relocatedDep);
95+
}
96+
dependencies.add(fileDescriptorCache.get(depKey));
97+
}
98+
99+
// Now build the current file descriptor with its dependencies
48100
com.google.protobuf.DescriptorProtos.FileDescriptorProto unrelocatedFileProto =
49101
unrelocatedFileDescriptor.toProto();
50102
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.
54103
FileDescriptorProto relocatedFileProto = FileDescriptorProto.parseFrom(fileProtoBytes);
55104

56-
// 5. Build the relocated FileDescriptor.
57105
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-
}
106+
FileDescriptor.buildFrom(relocatedFileProto, dependencies.toArray(new FileDescriptor[0]));
107+
fileDescriptorCache.put(fileKey, relocatedFileDescriptor);
67108

68-
// 7. Parse the original message bytes using the relocated descriptor.
69-
DynamicMessage relocatedMessage = DynamicMessage.parseFrom(relocatedDescriptor, messageBytes);
70-
return relocatedMessage;
109+
return relocatedFileDescriptor.findMessageTypeByName(originalDescriptor.getName());
71110
}
72111

73112
/**
@@ -77,17 +116,25 @@ public static DynamicMessage convertToRelocatedDynamicMessage(Message message) t
77116
* @param message The incoming (unrelocated) protobuf message.
78117
*/
79118
public static String getMessage(Message message) {
119+
if (message == null) {
120+
log.debug("Cannot convert null message to JSON");
121+
return "";
122+
}
123+
80124
try {
81125
// Convert the unrelocated message into a relocated DynamicMessage.
82126
DynamicMessage relocatedMessage = convertToRelocatedDynamicMessage(message);
83127

84128
// 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;
129+
JsonFormat.Printer relocatedPrinter =
130+
JsonFormat.printer().includingDefaultValueFields().preservingProtoFieldNames();
131+
return relocatedPrinter.print(relocatedMessage);
89132
} catch (Exception e) {
90-
log.error("Failed to convert message with relocated protobuf message: {}", e.getMessage());
133+
log.error("Failed to convert message to JSON: {}", e.getMessage(), e);
134+
if (log.isDebugEnabled()) {
135+
log.debug("Message type: {}", message.getClass().getName());
136+
log.debug("Message descriptor: {}", message.getDescriptorForType().getFullName());
137+
}
91138
}
92139
return "";
93140
}

0 commit comments

Comments
 (0)