Skip to content

Commit 4816a22

Browse files
authored
🐛 gRPC header capture with shaded netty module and body capture without com.google.protobuf.util.JsonFormat (#339)
* ✅ add test tasks for gRPC 1.30.0 * ♻️ move GrpcSemanticAttributes to common library for access across grpc instrumentation modules * ✨ add instrumentation for grpc-shaded-netty-1.9 * 🎨 format grpc-1.6 build * 🐛 fix classpath for versioned test source set * ✅ add muzzle check for module * 🎨 format shaded netty module * ♻️ move usages of grpc-common to util class * 🐛 add names to instrumentation module * 🎨 format utils * 🚚 rename NettyUtils * 🚚 move around classes * 🚚 move instrumentation classes to separate file * 🐛 copy-paste build script bug * 🔥 remove unneeded helper class method * ✅ update muzzle policy to be more restrictive, we need to work without JsonFormat available on the application class loader * ✨ add shaded project for protobuf-java-util * ♻️ use shaded protobuf java util in grpc instrumentation * 🔥 remove unneeded relocations
1 parent 500fa76 commit 4816a22

File tree

15 files changed

+385
-11
lines changed

15 files changed

+385
-11
lines changed

instrumentation/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ dependencies{
3434
implementation(project(":instrumentation:servlet:servlet-3.0"))
3535
implementation(project(":instrumentation:spark-2.3"))
3636
implementation(project(":instrumentation:grpc-1.6"))
37+
implementation(project(":instrumentation:grpc-shaded-netty-1.9"))
3738
implementation(project(":instrumentation:okhttp:okhttp-3.0"))
3839
implementation(project(":instrumentation:apache-httpclient-4.0"))
3940
implementation(project(":instrumentation:jaxrs-client-2.0"))

instrumentation/grpc-1.6/build.gradle.kts

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ muzzle {
1414
group = "io.grpc"
1515
module = "grpc-core"
1616
versions = "[1.6.0,)"
17-
// for body capture via com.google.protobuf.util.JsonFormat
18-
extraDependency("io.grpc:grpc-protobuf:1.6.0")
17+
// for body capture via com.google.protobuf.Message to exist always
18+
extraDependency("com.google.protobuf:protobuf-java:3.3.1")
1919
extraDependency("io.grpc:grpc-netty:1.6.0")
2020
}
2121
}
@@ -34,6 +34,8 @@ idea {
3434
}
3535
}
3636

37+
val testGrpcVersion = "1.30.0"
38+
3739
protobuf {
3840
protoc {
3941
// The artifact spec for the Protobuf Compiler
@@ -60,15 +62,21 @@ val grpcVersion = "1.6.0"
6062
dependencies {
6163
api("io.opentelemetry.javaagent.instrumentation:opentelemetry-javaagent-grpc-1.6:${versions["opentelemetry_java_agent"]}")
6264
api("io.opentelemetry.instrumentation:opentelemetry-grpc-1.6:${versions["opentelemetry_java_agent"]}")
65+
implementation(project(":instrumentation:grpc-common"))
66+
implementation(project(":shaded-protobuf-java-util", "shadow"))
6367

6468
compileOnly("io.grpc:grpc-core:${grpcVersion}")
65-
compileOnly("io.grpc:grpc-protobuf:${grpcVersion}")
69+
compileOnly("io.grpc:grpc-protobuf:${grpcVersion}") {
70+
exclude("com.google.protobuf", "protobuf-java-util")
71+
}
6672
compileOnly("io.grpc:grpc-stub:${grpcVersion}")
6773
compileOnly("io.grpc:grpc-netty:${grpcVersion}")
6874

6975
implementation("javax.annotation:javax.annotation-api:1.3.2")
7076

71-
testImplementation(testFixtures(project(":testing-common")))
77+
testImplementation(testFixtures(project(":testing-common")))
78+
testImplementation(project(":instrumentation:grpc-shaded-netty-1.9"))
79+
7280
testImplementation("io.grpc:grpc-core:${grpcVersion}") {
7381
version {
7482
strictly(grpcVersion)
@@ -90,3 +98,46 @@ dependencies {
9098
}
9199
}
92100
}
101+
102+
val grpcVersions = listOf(grpcVersion, "1.30.0")
103+
104+
sourceSets {
105+
for (version in grpcVersions) {
106+
create("test_$version") {
107+
dependencies {
108+
implementationConfigurationName("io.grpc:grpc-core:$version")
109+
}
110+
}
111+
}
112+
}
113+
114+
tasks.compileTestJava {
115+
this.classpath += sourceSets.named("test_$grpcVersion").get().output
116+
}
117+
tasks.test {
118+
classpath += sourceSets.named("test_$grpcVersion").get().output
119+
}
120+
121+
for (version in listOf("1.30.0")) {
122+
val versionedConfiguration = configurations.create("test_${version}") {
123+
extendsFrom(configurations.runtimeClasspath.get())
124+
}
125+
dependencies {
126+
versionedConfiguration(testFixtures(project(":testing-common")))
127+
versionedConfiguration("io.opentelemetry.javaagent.instrumentation:opentelemetry-javaagent-grpc-1.6:${versions["opentelemetry_java_agent"]}")
128+
versionedConfiguration("io.opentelemetry.instrumentation:opentelemetry-grpc-1.6:${versions["opentelemetry_java_agent"]}")
129+
versionedConfiguration(project(":instrumentation:grpc-shaded-netty-1.9"))
130+
versionedConfiguration(platform("io.grpc:grpc-bom:$version"))
131+
versionedConfiguration("io.grpc:grpc-core")
132+
versionedConfiguration("io.grpc:grpc-protobuf")
133+
versionedConfiguration("io.grpc:grpc-stub")
134+
versionedConfiguration("io.grpc:grpc-netty")
135+
136+
}
137+
val versionedTest = task<Test>("test_${version}") {
138+
group = "verification"
139+
classpath = versionedConfiguration + sourceSets.main.get().output + sourceSets.test.get().output + sourceSets.named("test_$version").get().output
140+
useJUnitPlatform()
141+
}
142+
tasks.check { dependsOn(versionedTest) }
143+
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,12 @@
1717
package io.opentelemetry.javaagent.instrumentation.hypertrace.grpc.v1_6;
1818

1919
import com.google.protobuf.Message;
20-
import com.google.protobuf.util.JsonFormat;
2120
import io.grpc.Metadata;
2221
import io.grpc.Metadata.Key;
2322
import io.opentelemetry.api.common.AttributeKey;
2423
import io.opentelemetry.api.trace.Span;
24+
import io.opentelemetry.javaagent.instrumentation.hypertrace.com.google.protobuf.util.JsonFormat;
25+
import io.opentelemetry.javaagent.instrumentation.hypertrace.grpc.GrpcSemanticAttributes;
2526
import java.io.IOException;
2627
import java.util.LinkedHashMap;
2728
import java.util.Map;

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
2929
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
3030
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
31+
import io.opentelemetry.javaagent.instrumentation.hypertrace.grpc.GrpcSemanticAttributes;
3132
import java.util.ArrayList;
3233
import java.util.Arrays;
3334
import java.util.HashMap;

instrumentation/grpc-1.6/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/grpc/v1_6/GrpcInstrumentationTest.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import com.google.protobuf.util.JsonFormat;
2020
import io.grpc.ForwardingServerCall;
2121
import io.grpc.ManagedChannel;
22-
import io.grpc.ManagedChannelBuilder;
2322
import io.grpc.Metadata;
2423
import io.grpc.Server;
2524
import io.grpc.ServerBuilder;
@@ -30,6 +29,7 @@
3029
import io.grpc.Status;
3130
import io.grpc.StatusRuntimeException;
3231
import io.grpc.stub.MetadataUtils;
32+
import io.opentelemetry.javaagent.instrumentation.hypertrace.grpc.GrpcSemanticAttributes;
3333
import io.opentelemetry.sdk.trace.data.SpanData;
3434
import java.io.IOException;
3535
import java.net.URL;
@@ -104,10 +104,7 @@ public void sendHeaders(Metadata headers) {
104104
.build();
105105
SERVER.start();
106106

107-
CHANNEL =
108-
ManagedChannelBuilder.forTarget(String.format("localhost:%d", SERVER.getPort()))
109-
.usePlaintext(true)
110-
.build();
107+
CHANNEL = new GrpcChannelProvider(SERVER.getPort()).get();
111108
}
112109

113110
@AfterAll
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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 io.grpc.ManagedChannel;
20+
import io.grpc.ManagedChannelBuilder;
21+
import java.util.function.Supplier;
22+
23+
final class GrpcChannelProvider implements Supplier<ManagedChannel> {
24+
25+
private final int port;
26+
27+
GrpcChannelProvider(final int port) {
28+
this.port = port;
29+
}
30+
31+
@Override
32+
public ManagedChannel get() {
33+
return ManagedChannelBuilder.forTarget(String.format("localhost:%d", port))
34+
.usePlaintext()
35+
.build();
36+
}
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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 io.grpc.ManagedChannel;
20+
import io.grpc.ManagedChannelBuilder;
21+
import java.util.function.Supplier;
22+
23+
final class GrpcChannelProvider implements Supplier<ManagedChannel> {
24+
25+
private final int port;
26+
27+
GrpcChannelProvider(final int port) {
28+
this.port = port;
29+
}
30+
31+
@Override
32+
public ManagedChannel get() {
33+
return ManagedChannelBuilder.forTarget(String.format("localhost:%d", port))
34+
.usePlaintext(true)
35+
.build();
36+
}
37+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
plugins {
2+
`java-library`
3+
}
4+
5+
dependencies {
6+
compileOnly("io.grpc:grpc-core:1.6.0")
7+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
package io.opentelemetry.javaagent.instrumentation.hypertrace.grpc.v1_6;
17+
package io.opentelemetry.javaagent.instrumentation.hypertrace.grpc;
1818

1919
import io.grpc.Metadata;
2020

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
plugins {
2+
`java-library`
3+
id("net.bytebuddy.byte-buddy")
4+
id("io.opentelemetry.instrumentation.auto-instrumentation")
5+
muzzle
6+
}
7+
8+
muzzle {
9+
pass {
10+
group = "io.grpc"
11+
module = "grpc-netty-shaded"
12+
versions = "[1.9.0,)"
13+
assertInverse = true
14+
}
15+
}
16+
17+
afterEvaluate{
18+
io.opentelemetry.instrumentation.gradle.bytebuddy.ByteBuddyPluginConfigurator(project,
19+
sourceSets.main.get(),
20+
"io.opentelemetry.javaagent.tooling.muzzle.collector.MuzzleCodeGenerationPlugin",
21+
project(":javaagent-tooling").configurations["instrumentationMuzzle"] + configurations.runtimeClasspath
22+
).configure()
23+
}
24+
25+
dependencies {
26+
compileOnly("io.grpc:grpc-core:1.9.0")
27+
compileOnly("io.grpc:grpc-netty-shaded:1.9.0")
28+
implementation(project(":instrumentation:grpc-common"))
29+
}

0 commit comments

Comments
 (0)