Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .fossa.yml
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,12 @@ targets:
- type: gradle
path: ./
target: ':instrumentation:scala-fork-join-2.8:javaagent'
- type: gradle
path: ./
target: ':instrumentation:sofa-rpc-5.4:javaagent'
- type: gradle
path: ./
target: ':instrumentation:sofa-rpc-5.4:library-autoconfigure'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the name autoconfigure here doesn't follow the normal pattern. Seems like it should just be library ? I see that this is also the case in the dubbo module, which is maybe where you copied from, but I'm not sure it's correct there either

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

library-autoconfigure is used by library instrumentations that are automatically enabled when the library instrumentation jar is added to the project as opposed to library instrumentations where user has to write code to enable the instrumentation. Typically the library-autoconfigure use some sort of spi that is automatically picked up by the instrumented framework. Often it makes sense for instrumentation to provide both library and library-autoconfigure modules (for example see aws2.2 instrumentation) since library-autoconfigure instrumentations can't often be configured.

- type: gradle
path: ./
target: ':instrumentation:spark-2.3:javaagent'
Expand Down
79 changes: 79 additions & 0 deletions docs/instrumentation-list.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10796,6 +10796,85 @@ libraries:
target_versions:
javaagent:
- jakarta.servlet:jakarta.servlet-api:[5.0.0,)
sofastack:
- name: sofa-rpc-5.4
display_name: SOFARPC
description: |
The SOFARPC instrumentation provides RPC client spans and metrics, and RPC server spans and metrics for Apache SOFARPC RPC calls.
semantic_conventions:
- RPC_CLIENT_SPANS
- RPC_CLIENT_METRICS
- RPC_SERVER_SPANS
- RPC_SERVER_METRICS
library_link: https://github.com/sofastack/sofa-rpc/
source_path: instrumentation/sofa-rpc-5.4
scope:
name: io.opentelemetry.sofa-rpc-5.4
target_versions:
javaagent:
- com.alipay.sofa:sofa-rpc-all:[5.4.0,)
configurations:
- name: otel.instrumentation.common.peer-service-mapping
description: Used to specify a mapping from host names or IP addresses to peer
services.
type: map
default: ''
telemetry:
- when: default
metrics:
- name: rpc.client.duration
description: The duration of an outbound RPC invocation.
type: HISTOGRAM
unit: ms
attributes:
- name: rpc.method
type: STRING
- name: rpc.service
type: STRING
- name: rpc.system
type: STRING
- name: server.address
type: STRING
- name: server.port
type: LONG
- name: rpc.server.duration
description: The duration of an inbound RPC invocation.
type: HISTOGRAM
unit: ms
attributes:
- name: rpc.method
type: STRING
- name: rpc.service
type: STRING
- name: rpc.system
type: STRING
spans:
- span_kind: CLIENT
attributes:
- name: peer.service
type: STRING
- name: rpc.method
type: STRING
- name: rpc.service
type: STRING
- name: rpc.system
type: STRING
- name: server.address
type: STRING
- name: server.port
type: LONG
- span_kind: SERVER
attributes:
- name: network.peer.address
type: STRING
- name: network.peer.port
type: LONG
- name: rpc.method
type: STRING
- name: rpc.service
type: STRING
- name: rpc.system
type: STRING
spark:
- name: spark-2.3
description: |
Expand Down
1 change: 1 addition & 0 deletions docs/supported-libraries.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ These are the supported libraries and frameworks:
| [RxJava](https://github.com/ReactiveX/RxJava) | 1.0+ | [opentelemetry-rxjava-1.0](../instrumentation/rxjava/rxjava-1.0/library),<br>[opentelemetry-rxjava-2.0](../instrumentation/rxjava/rxjava-2.0/library),<br>[opentelemetry-rxjava-3.0](../instrumentation/rxjava/rxjava-3.0/library),<br>[opentelemetry-rxjava-3.1.1](../instrumentation/rxjava/rxjava-3.1.1/library) | Context propagation |
| [Scala ForkJoinPool](https://www.scala-lang.org/api/2.12.0/scala/concurrent/forkjoin/package$$ForkJoinPool$.html) | 2.8+ | N/A | Context propagation |
| [Servlet](https://javaee.github.io/javaee-spec/javadocs/javax/servlet/package-summary.html) | 2.2+ | [opentelemetry-servlet-3.0](../instrumentation/servlet/servlet-3.0/library) | [HTTP Server Spans], [HTTP Server Metrics] |
| [SOFARPC](https://github.com/sofastack/sofa-rpc/) | 5.4.0+ | [opentelemetry-sofa-rpc-5.4](../instrumentation/sofa-rpc-5.4/library-autoconfigure) | [RPC Client Spans], [RPC Server Spans] |
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
| [SOFARPC](https://github.com/sofastack/sofa-rpc/) | 5.4.0+ | [opentelemetry-sofa-rpc-5.4](../instrumentation/sofa-rpc-5.4/library-autoconfigure) | [RPC Client Spans], [RPC Server Spans] |
| [SOFARPC](https://github.com/sofastack/sofa-rpc/) | 5.4+ | [opentelemetry-sofa-rpc-5.4](../instrumentation/sofa-rpc-5.4/library-autoconfigure) | [RPC Client Spans], [RPC Client Metrics], [RPC Server Spans], [RPC Server Metrics] |

| [Spark Web Framework](https://github.com/perwendel/spark) | 2.3+ | N/A | Provides `http.route` [2] |
| [Spring Batch](https://spring.io/projects/spring-batch) | 3.0+ (not including 5.0+ yet) | N/A | none |
| [Spring Boot](https://spring.io/projects/spring-boot) | | [opentelemetry-spring-boot-resources](https://opentelemetry.io/docs/zero-code/java/spring-boot/) | none |
Expand Down
1 change: 1 addition & 0 deletions instrumentation-docs/instrumentations.sh
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ readonly INSTRUMENTATIONS=(
"pulsar:pulsar-2.8:javaagent:testExperimental"
"reactor:reactor-netty:reactor-netty-0.9:javaagent:test"
"reactor:reactor-netty:reactor-netty-1.0:javaagent:test"
"sofa-rpc-5.4:javaagent:testSofaRpc"
"spring:spring-batch-3.0:javaagent:test"
"spring:spring-data:spring-data-1.8:javaagent:test"
"spring:spring-integration-4.1:javaagent:test"
Expand Down
74 changes: 74 additions & 0 deletions instrumentation/sofa-rpc-5.4/javaagent/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
plugins {
id("otel.javaagent-instrumentation")
}

muzzle {
pass {
group.set("com.alipay.sofa")
module.set("sofa-rpc-all")
versions.set("[5.4.0,)")
assertInverse.set(true)
}
}

dependencies {
implementation(project(":instrumentation:sofa-rpc-5.4:library-autoconfigure"))

library("com.alipay.sofa:sofa-rpc-all:5.4.0")
}

val latestDepTest = findProperty("testLatestDeps") as Boolean

testing {
suites {
// using a test suite to ensure that project(":instrumentation:sofa-rpc-5.4:library-autoconfigure")
// is not available on test runtime class path, otherwise instrumentation from library-autoconfigure
// module would be used instead of the javaagent instrumentation that we want to test
val testSofaRpc by registering(JvmTestSuite::class) {
dependencies {
implementation(project(":instrumentation:sofa-rpc-5.4:testing"))
if (latestDepTest) {
implementation("com.alipay.sofa:sofa-rpc-all:latest.release")
} else {
implementation("com.alipay.sofa:sofa-rpc-all:5.4.0")
}
runtimeOnly("ch.qos.logback:logback-classic:1.2.13")
runtimeOnly("ch.qos.logback:logback-core:1.2.13")
runtimeOnly("org.slf4j:slf4j-api:1.7.21")
}
}
}
}

tasks.withType<Test>().configureEach {
systemProperty("testLatestDeps", findProperty("testLatestDeps") as Boolean)
jvmArgs("-XX:+IgnoreUnrecognizedVMOptions")
// to suppress non-fatal errors on jdk17
jvmArgs("--add-opens=java.base/java.math=ALL-UNNAMED")
// required on jdk17
jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED")

systemProperty("collectMetadata", findProperty("collectMetadata")?.toString() ?: "false")
}

tasks {
check {
dependsOn(testing.suites)
}

if (findProperty("denyUnsafe") as Boolean) {
// SOFA RPC's tracer module uses Disruptor which requires sun.misc.Unsafe.
withType<Test>().configureEach {
enabled = false
}
}
}

configurations.named("testSofaRpcRuntimeClasspath") {
resolutionStrategy {
// requires old logback (and therefore also old slf4j)
force("ch.qos.logback:logback-classic:1.2.13")
force("ch.qos.logback:logback-core:1.2.13")
force("org.slf4j:slf4j-api:1.7.21")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.sofarpc.v5_4;

import com.alipay.sofa.rpc.config.ConsumerConfig;
import com.alipay.sofa.rpc.core.exception.SofaRpcException;
import com.alipay.sofa.rpc.core.request.SofaRequest;
import com.alipay.sofa.rpc.core.response.SofaResponse;
import com.alipay.sofa.rpc.ext.Extension;
import com.alipay.sofa.rpc.filter.AutoActive;
import com.alipay.sofa.rpc.filter.Filter;
import com.alipay.sofa.rpc.filter.FilterInvoker;

@Extension(value = "openTelemetryClient", order = -25000)
@AutoActive(consumerSide = true)
public final class OpenTelemetryClientFilter extends Filter {

private final Filter delegate;

public OpenTelemetryClientFilter() {
delegate = SofaRpcSingletons.CLIENT_FILTER;
}

@Override
@SuppressWarnings("ThrowsUncheckedException")
public SofaResponse invoke(FilterInvoker invoker, SofaRequest request) throws SofaRpcException {
return delegate.invoke(invoker, request);
}

@Override
// Suppress rawtypes warning: SOFARPC Filter interface uses raw ConsumerConfig type
@SuppressWarnings({"rawtypes", "ThrowsUncheckedException"})
public void onAsyncResponse(
ConsumerConfig config, SofaRequest request, SofaResponse response, Throwable exception)
throws SofaRpcException {
delegate.onAsyncResponse(config, request, response, exception);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.sofarpc.v5_4;

import com.alipay.sofa.rpc.core.exception.SofaRpcException;
import com.alipay.sofa.rpc.core.request.SofaRequest;
import com.alipay.sofa.rpc.core.response.SofaResponse;
import com.alipay.sofa.rpc.ext.Extension;
import com.alipay.sofa.rpc.filter.AutoActive;
import com.alipay.sofa.rpc.filter.Filter;
import com.alipay.sofa.rpc.filter.FilterInvoker;

@Extension(value = "openTelemetryServer", order = -25000)
@AutoActive(providerSide = true)
public final class OpenTelemetryServerFilter extends Filter {

private final Filter delegate;

public OpenTelemetryServerFilter() {
delegate = SofaRpcSingletons.SERVER_FILTER;
}

@Override
@SuppressWarnings("ThrowsUncheckedException")
public SofaResponse invoke(FilterInvoker invoker, SofaRequest request) throws SofaRpcException {
return delegate.invoke(invoker, request);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.sofarpc.v5_4;

import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
import static java.util.Collections.singletonList;
import static net.bytebuddy.matcher.ElementMatchers.named;

import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.extension.instrumentation.HelperResourceBuilder;
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule;
import io.opentelemetry.javaagent.extension.instrumentation.internal.injection.ClassInjector;
import io.opentelemetry.javaagent.extension.instrumentation.internal.injection.InjectionMode;
import java.util.List;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;

@AutoService(InstrumentationModule.class)
public class SofaRpcInstrumentationModule extends InstrumentationModule
implements ExperimentalInstrumentationModule {
public SofaRpcInstrumentationModule() {
super("sofa-rpc", "sofa-rpc-5.4");
}

@Override
public void registerHelperResources(HelperResourceBuilder helperResourceBuilder) {
helperResourceBuilder.register(
"META-INF/services/com.alipay.sofa.rpc.filter.Filter",
"sofa-rpc-5.4/META-INF/com.alipay.sofa.rpc.filter.Filter");
}

@Override
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
return hasClassesNamed("com.alipay.sofa.rpc.filter.Filter")
// Class was added in 5.4.0
.and(hasClassesNamed("com.alipay.sofa.rpc.transport.ClientHandler"));
}

@Override
public void injectClasses(ClassInjector injector) {
injector
.proxyBuilder(
"io.opentelemetry.javaagent.instrumentation.sofarpc.v5_4.OpenTelemetryClientFilter")
.inject(InjectionMode.CLASS_ONLY);
injector
.proxyBuilder(
"io.opentelemetry.javaagent.instrumentation.sofarpc.v5_4.OpenTelemetryServerFilter")
.inject(InjectionMode.CLASS_ONLY);
}

@Override
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new ResourceInjectingTypeInstrumentation());
}

// A type instrumentation is needed to trigger resource injection.
public static class ResourceInjectingTypeInstrumentation implements TypeInstrumentation {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any reason not to put this in a separate file? we don't typically include instrumentations in the InstrumentationModule itself

@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return named("com.alipay.sofa.rpc.ext.ExtensionLoader");
}

@Override
public void transform(TypeTransformer transformer) {
// Nothing to transform, this type instrumentation is only used for injecting resources.
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.sofarpc.v5_4;

import com.alipay.sofa.rpc.filter.Filter;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.instrumentation.api.incubator.semconv.net.PeerServiceAttributesExtractor;
import io.opentelemetry.instrumentation.sofarpc.v5_4.SofaRpcTelemetry;
import io.opentelemetry.instrumentation.sofarpc.v5_4.internal.SofaRpcClientNetworkAttributesGetter;
import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig;

public final class SofaRpcSingletons {
public static final Filter CLIENT_FILTER;
public static final Filter SERVER_FILTER;

static {
SofaRpcTelemetry telemetry =
SofaRpcTelemetry.builder(GlobalOpenTelemetry.get())
.addAttributesExtractor(
PeerServiceAttributesExtractor.create(
new SofaRpcClientNetworkAttributesGetter(),
AgentCommonConfig.get().getPeerServiceResolver()))
.build();
CLIENT_FILTER = telemetry.newClientFilter();
SERVER_FILTER = telemetry.newServerFilter();
}

private SofaRpcSingletons() {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
io.opentelemetry.javaagent.instrumentation.sofarpc.v5_4.OpenTelemetryClientFilter
io.opentelemetry.javaagent.instrumentation.sofarpc.v5_4.OpenTelemetryServerFilter

Loading
Loading