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'
- 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] |
| [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 {
@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