Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix WithSpan annotation instrumentation #929

Merged
merged 4 commits into from
Aug 10, 2020
Merged
Show file tree
Hide file tree
Changes from 3 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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ OpenTelemetry `getTracer` and API directly, configure a `@WithSpan`
annotation. Add the trace annotation to your application's code:

```java
import io.opentelemetry.contrib.auto.annotations.WithSpan;
import io.opentelemetry.extensions.auto.annotations.WithSpan;

public class MyClass {
@WithSpan
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,11 @@
* limitations under the License.
*/

package io.opentelemetry.auto.instrumentation.traceannotation;
package io.opentelemetry.auto.config;

import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import io.opentelemetry.auto.config.Config;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
Expand Down Expand Up @@ -59,7 +58,7 @@ public static Map<String, Set<String>> parse(String configString) {
configString);
return Collections.emptyMap();
} else {
Map<String, Set<String>> toTrace = Maps.newHashMap();
Map<String, Set<String>> toTrace = new HashMap<>();
String[] classMethods = configString.split(";", -1);
for (String classMethod : classMethods) {
if (classMethod.trim().isEmpty()) {
Expand All @@ -70,7 +69,7 @@ public static Map<String, Set<String>> parse(String configString) {
String method = splitClassMethod[1].trim();
String methodNames = method.substring(0, method.length() - 1);
String[] splitMethodNames = methodNames.split(",", -1);
Set<String> trimmedMethodNames = Sets.newHashSetWithExpectedSize(splitMethodNames.length);
Set<String> trimmedMethodNames = new HashSet<>(splitMethodNames.length);
for (String methodName : splitMethodNames) {
String trimmedMethodName = methodName.trim();
if (!trimmedMethodName.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package io.opentelemetry.auto.instrumentation.traceannotation
package io.opentelemetry.auto.config


import spock.lang.Specification
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ public class AutoInstrumentationPlugin implements Plugin<Project> {
"io.opentelemetry.internal", // OpenTelemetry API
"io.opentelemetry.metrics", // OpenTelemetry API
"io.opentelemetry.trace", // OpenTelemetry API
"io.opentelemetry.contrib.auto.annotations", // OpenTelemetry API Contrib
"io.grpc.Context", // OpenTelemetry API dependency
"io.grpc.Deadline", // OpenTelemetry API dependency
"io.grpc.PersistentHashArrayMappedTrie", // OpenTelemetry API dependency
Expand Down
42 changes: 21 additions & 21 deletions gradle/dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,22 @@ ext {

deps = [
// OpenTelemetry
opentelemetryApi : dependencies.create(group: 'io.opentelemetry', name: 'opentelemetry-api', version: versions.opentelemetry),
opentelemetryApiAutoAnnotations: dependencies.create(group: 'io.opentelemetry', name: 'opentelemetry-extension-auto-annotations', version: versions.opentelemetryOther),
opentelemetryTraceProps : dependencies.create(group: 'io.opentelemetry', name: 'opentelemetry-extension-trace-propagators', version: versions.opentelemetryOther),
opentelemetrySdk : dependencies.create(group: 'io.opentelemetry', name: 'opentelemetry-sdk', version: versions.opentelemetry),
opentelemetrySdkAutoConfig : dependencies.create(group: 'io.opentelemetry', name: 'opentelemetry-sdk-extension-auto-config', version: versions.opentelemetryOther),
opentelemetryJaeger : dependencies.create(group: 'io.opentelemetry', name: 'opentelemetry-exporters-jaeger', version: versions.opentelemetry),
opentelemetryOtlp : dependencies.create(group: 'io.opentelemetry', name: 'opentelemetry-exporters-otlp', version: versions.opentelemetryOther),
opentelemetryZipkin : dependencies.create(group: 'io.opentelemetry', name: 'opentelemetry-exporters-zipkin', version: versions.opentelemetryOther),
opentelemetryLogging : dependencies.create(group: 'io.opentelemetry', name: 'opentelemetry-exporters-logging', version: versions.opentelemetryOther),
opentelemetryApi : dependencies.create(group: 'io.opentelemetry', name: 'opentelemetry-api', version: versions.opentelemetry),
opentelemetryAutoAnnotations: dependencies.create(group: 'io.opentelemetry', name: 'opentelemetry-extension-auto-annotations', version: versions.opentelemetryOther),
opentelemetryTraceProps : dependencies.create(group: 'io.opentelemetry', name: 'opentelemetry-extension-trace-propagators', version: versions.opentelemetryOther),
opentelemetrySdk : dependencies.create(group: 'io.opentelemetry', name: 'opentelemetry-sdk', version: versions.opentelemetry),
opentelemetrySdkAutoConfig : dependencies.create(group: 'io.opentelemetry', name: 'opentelemetry-sdk-extension-auto-config', version: versions.opentelemetryOther),
opentelemetryJaeger : dependencies.create(group: 'io.opentelemetry', name: 'opentelemetry-exporters-jaeger', version: versions.opentelemetry),
opentelemetryOtlp : dependencies.create(group: 'io.opentelemetry', name: 'opentelemetry-exporters-otlp', version: versions.opentelemetryOther),
opentelemetryZipkin : dependencies.create(group: 'io.opentelemetry', name: 'opentelemetry-exporters-zipkin', version: versions.opentelemetryOther),
opentelemetryLogging : dependencies.create(group: 'io.opentelemetry', name: 'opentelemetry-exporters-logging', version: versions.opentelemetryOther),

// General
slf4j : "org.slf4j:slf4j-api:${versions.slf4j}",
guava : "com.google.guava:guava:$versions.guava",
bytebuddy : dependencies.create(group: 'net.bytebuddy', name: 'byte-buddy', version: "${versions.bytebuddy}"),
bytebuddyagent : dependencies.create(group: 'net.bytebuddy', name: 'byte-buddy-agent', version: "${versions.bytebuddy}"),
autoservice : [
slf4j : "org.slf4j:slf4j-api:${versions.slf4j}",
guava : "com.google.guava:guava:$versions.guava",
bytebuddy : dependencies.create(group: 'net.bytebuddy', name: 'byte-buddy', version: "${versions.bytebuddy}"),
bytebuddyagent : dependencies.create(group: 'net.bytebuddy', name: 'byte-buddy-agent', version: "${versions.bytebuddy}"),
autoservice : [
dependencies.create(group: 'com.google.auto.service', name: 'auto-service', version: '1.0-rc3'),
dependencies.create(group: 'com.google.auto', name: 'auto-common', version: '0.8'),
// These are the last versions that support guava 20.0. Upgrading has odd interactions with shadow.
Expand All @@ -52,23 +52,23 @@ ext {

// Testing

spock : [
spock : [
dependencies.create("org.spockframework:spock-core:${versions.spock}", {
exclude group: 'org.codehaus.groovy', module: 'groovy-all'
}),
// Used by Spock for mocking:
dependencies.create(group: 'org.objenesis', name: 'objenesis', version: '2.6') // Last version to support Java7
],
groovy : "org.codehaus.groovy:groovy-all:${versions.groovy}",
testcontainers : "org.testcontainers:testcontainers:1.12.2",
testLogging : [
groovy : "org.codehaus.groovy:groovy-all:${versions.groovy}",
testcontainers : "org.testcontainers:testcontainers:1.12.2",
testLogging : [
dependencies.create(group: 'ch.qos.logback', name: 'logback-classic', version: versions.logback),
dependencies.create(group: 'org.slf4j', name: 'log4j-over-slf4j', version: versions.slf4j),
dependencies.create(group: 'org.slf4j', name: 'jcl-over-slf4j', version: versions.slf4j),
dependencies.create(group: 'org.slf4j', name: 'jul-to-slf4j', version: versions.slf4j),
],
scala : dependencies.create(group: 'org.scala-lang', name: 'scala-library', version: "${versions.scala}"),
kotlin : dependencies.create(group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib', version: "${versions.kotlin}"),
coroutines : dependencies.create(group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: "${versions.coroutines}"),
scala : dependencies.create(group: 'org.scala-lang', name: 'scala-library', version: "${versions.scala}"),
kotlin : dependencies.create(group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib', version: "${versions.kotlin}"),
coroutines : dependencies.create(group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: "${versions.coroutines}"),
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ dependencies {
implementation group: 'org.springframework.boot', name: 'spring-boot-autoconfigure', version: versions.springboot
annotationProcessor group: 'org.springframework.boot', name: 'spring-boot-autoconfigure-processor', version: versions.springboot
implementation group: 'javax.validation', name: 'validation-api', version: '2.0.1.Final'

compileOnly group: 'org.springframework.boot', name: 'spring-boot-starter-aop', version: versions.springboot
compileOnly group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: versions.springboot
compileOnly group: 'org.springframework.boot', name: 'spring-boot-starter-webflux', version: versions.springboot
implementation project(':instrumentation-core:spring:spring-webmvc-3.1')
implementation project(':instrumentation-core:spring:spring-webmvc-3.1')
implementation project(':instrumentation-core:spring:spring-web-3.1')
implementation project(':instrumentation-core:spring:spring-webflux-5.0')
compileOnly deps.opentelemetryApiAutoAnnotations

compileOnly deps.opentelemetryAutoAnnotations
compileOnly group: 'io.grpc', name: 'grpc-api', version: '1.30.2'
compileOnly deps.opentelemetryLogging
compileOnly deps.opentelemetryJaeger
Expand All @@ -34,9 +34,9 @@ dependencies {
testImplementation(group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: versions.springboot) {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}

testImplementation deps.opentelemetrySdk
testImplementation deps.opentelemetryApiAutoAnnotations
testImplementation deps.opentelemetryAutoAnnotations
testImplementation group: 'io.grpc', name: 'grpc-api', version: '1.30.2'
testImplementation group: 'io.grpc', name: 'grpc-netty-shaded', version: '1.30.2'
testImplementation deps.opentelemetryLogging
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ apply from: "$rootDir/gradle/publish.gradle"

sourceCompatibility = '8'

dependencies {
dependencies {
api group: "org.springframework.boot", name: "spring-boot-starter", version: versions.springboot
api group: 'org.springframework.boot', name: 'spring-boot-starter-aop', version: versions.springboot
api project(':instrumentation-core:spring:spring-boot-autoconfigure')
api deps.opentelemetryApiAutoAnnotations
api deps.opentelemetryAutoAnnotations
api deps.opentelemetryApi
api deps.opentelemetryLogging
api deps.opentelemetrySdk
Expand Down
2 changes: 0 additions & 2 deletions instrumentation/annotations/annotations.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ muzzle {
}

dependencies {
implementation deps.opentelemetryApiAutoAnnotations

testImplementation group: 'com.newrelic.agent.java', name: 'newrelic-api', version: '+'
testImplementation(group: 'io.opentracing.contrib.dropwizard', name: 'dropwizard-opentracing', version: '0.2.2') {
transitive = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import static net.bytebuddy.matcher.ElementMatchers.none;

import io.opentelemetry.auto.config.Config;
import io.opentelemetry.auto.config.MethodsConfigurationParser;
import io.opentelemetry.auto.tooling.Instrumenter;
import java.util.Map;
import java.util.Set;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

import com.google.auto.service.AutoService;
import io.opentelemetry.auto.config.Config;
import io.opentelemetry.auto.config.MethodsConfigurationParser;
import io.opentelemetry.auto.tooling.Instrumenter;
import java.util.Collections;
import java.util.Map;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,35 +18,11 @@

import io.opentelemetry.OpenTelemetry;
import io.opentelemetry.auto.bootstrap.instrumentation.decorator.BaseDecorator;
import io.opentelemetry.extensions.auto.annotations.WithSpan;
import io.opentelemetry.trace.Span;
import io.opentelemetry.trace.Span.Kind;
import io.opentelemetry.trace.Tracer;
import java.lang.reflect.Method;

public class TraceDecorator extends BaseDecorator {
public static final TraceDecorator DECORATE = new TraceDecorator();

public static final Tracer TRACER =
OpenTelemetry.getTracerProvider().get("io.opentelemetry.auto.trace-annotation");

/**
* This method is used to generate an acceptable span (operation) name based on a given method
* reference. It first checks for existence of {@link WithSpan} annotation. If it is present, then
* tries to derive name from its {@code value} attribute. Otherwise delegates to {@link
* #spanNameForMethod(Method)}.
*/
public String spanNameForMethodWithAnnotation(final Method method) {
WithSpan annotation = method.getAnnotation(WithSpan.class);
if (annotation != null && !annotation.value().isEmpty()) {
return annotation.value();
}

return spanNameForMethod(method);
}

public Span.Kind extractSpanKind(final Method method) {
WithSpan annotation = method.getAnnotation(WithSpan.class);
return annotation != null ? annotation.kind() : Kind.INTERNAL;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ dependencies {
// and in the code "io.opentelemetry.*" refers to the (shaded) OpenTelemetry API that is in the
// bootstrap class loader (as those references will later be shaded)
compileOnly project(path: ':opentelemetry-api-beta-shaded-for-instrumenting', configuration: 'shadow')
compileOnly project(path: ':opentelemetry-auto-annotations-beta-shaded-for-instrumenting', configuration: 'shadow')

testImplementation project(path: ':opentelemetry-api-beta-shaded-for-instrumenting', configuration: 'shadow')
testImplementation project(path: ':opentelemetry-auto-annotations-beta-shaded-for-instrumenting', configuration: 'shadow')
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.opentelemetry.auto.instrumentation.opentelemetryapi.anotations;

import static net.bytebuddy.matcher.ElementMatchers.isDeclaredBy;
import static net.bytebuddy.matcher.ElementMatchers.none;

import io.opentelemetry.auto.config.Config;
import io.opentelemetry.auto.config.MethodsConfigurationParser;
import io.opentelemetry.auto.tooling.Instrumenter;
import java.util.Map;
import java.util.Set;
import net.bytebuddy.description.ByteCodeElement;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.ElementMatchers;

public abstract class AbstractTraceAnnotationInstrumentation extends Instrumenter.Default {
public AbstractTraceAnnotationInstrumentation(
String instrumentationName, String... additionalNames) {
super(instrumentationName, additionalNames);
}

/*
Returns a matcher for all methods that should be excluded from auto-instrumentation by
annotation-based advices.
*/
ElementMatcher.Junction<MethodDescription> configureExcludedMethods() {
ElementMatcher.Junction<MethodDescription> result = none();

Map<String, Set<String>> excludedMethods =
MethodsConfigurationParser.parse(Config.get().getTraceAnnotatedMethodsExclude());
for (Map.Entry<String, Set<String>> entry : excludedMethods.entrySet()) {
String className = entry.getKey();
ElementMatcher.Junction<ByteCodeElement> classMather =
isDeclaredBy(ElementMatchers.<TypeDescription>named(className));

ElementMatcher.Junction<MethodDescription> excludedMethodsMatcher = none();
for (String methodName : entry.getValue()) {
excludedMethodsMatcher = excludedMethodsMatcher.or(ElementMatchers.named(methodName));
}

result = result.or(classMather.and(excludedMethodsMatcher));
}

return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.opentelemetry.auto.instrumentation.opentelemetryapi.anotations;

import io.opentelemetry.OpenTelemetry;
import io.opentelemetry.auto.bootstrap.instrumentation.decorator.BaseDecorator;
import io.opentelemetry.trace.Span;
import io.opentelemetry.trace.Tracer;
import java.lang.reflect.Method;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import unshaded.io.opentelemetry.extensions.auto.annotations.WithSpan;
import unshaded.io.opentelemetry.trace.Span.Kind;

public class TraceDecorator extends BaseDecorator {
public static final TraceDecorator DECORATE = new TraceDecorator();

public static final Tracer TRACER =
OpenTelemetry.getTracerProvider().get("io.opentelemetry.auto.trace-annotation");

private static final Logger log = LoggerFactory.getLogger(TraceDecorator.class);

/**
* This method is used to generate an acceptable span (operation) name based on a given method
* reference. It first checks for existence of {@link WithSpan} annotation. If it is present, then
* tries to derive name from its {@code value} attribute. Otherwise delegates to {@link
* #spanNameForMethod(Method)}.
*/
public String spanNameForMethodWithAnnotation(WithSpan annotation, Method method) {
if (annotation != null && !annotation.value().isEmpty()) {
return annotation.value();
}
return spanNameForMethod(method);
}

public Span.Kind extractSpanKind(WithSpan annotation) {
Kind unshadedKind = annotation != null ? annotation.kind() : Kind.INTERNAL;
return toShadedOrNull(unshadedKind);
}

public static io.opentelemetry.trace.Span.Kind toShadedOrNull(
final unshaded.io.opentelemetry.trace.Span.Kind unshadedSpanKind) {
try {
return io.opentelemetry.trace.Span.Kind.valueOf(unshadedSpanKind.name());
} catch (final IllegalArgumentException e) {
log.debug("unexpected span kind: {}", unshadedSpanKind.name());
return io.opentelemetry.trace.Span.Kind.INTERNAL;
}
}
}
Loading