-
Notifications
You must be signed in to change notification settings - Fork 896
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Moved jdbc-datasource instrumentation to Instrumenter API (#3160)
- Loading branch information
Mateusz Rzeszutek
authored
Jun 3, 2021
1 parent
0ad8c1b
commit 5e4c568
Showing
10 changed files
with
323 additions
and
45 deletions.
There are no files selected for viewing
47 changes: 47 additions & 0 deletions
47
.../java/io/opentelemetry/instrumentation/api/instrumenter/code/CodeAttributesExtractor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.instrumentation.api.instrumenter.code; | ||
|
||
import io.opentelemetry.api.common.AttributesBuilder; | ||
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; | ||
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; | ||
import org.checkerframework.checker.nullness.qual.Nullable; | ||
|
||
/** | ||
* Extractor of <a | ||
* href="https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/span-general.md#source-code-attributes">source | ||
* code attributes</a>. | ||
*/ | ||
public abstract class CodeAttributesExtractor<REQUEST, RESPONSE> | ||
extends AttributesExtractor<REQUEST, RESPONSE> { | ||
|
||
@Override | ||
protected final void onStart(AttributesBuilder attributes, REQUEST request) { | ||
Class<?> cls = codeClass(request); | ||
if (cls != null) { | ||
set(attributes, SemanticAttributes.CODE_NAMESPACE, cls.getName()); | ||
} | ||
set(attributes, SemanticAttributes.CODE_FUNCTION, methodName(request)); | ||
set(attributes, SemanticAttributes.CODE_FILEPATH, filePath(request)); | ||
set(attributes, SemanticAttributes.CODE_LINENO, lineNumber(request)); | ||
} | ||
|
||
@Override | ||
protected final void onEnd( | ||
AttributesBuilder attributes, REQUEST request, @Nullable RESPONSE response) {} | ||
|
||
@Nullable | ||
protected abstract Class<?> codeClass(REQUEST request); | ||
|
||
@Nullable | ||
protected abstract String methodName(REQUEST request); | ||
|
||
@Nullable | ||
protected abstract String filePath(REQUEST request); | ||
|
||
@Nullable | ||
protected abstract Long lineNumber(REQUEST request); | ||
} |
44 changes: 44 additions & 0 deletions
44
...in/java/io/opentelemetry/instrumentation/api/instrumenter/code/CodeSpanNameExtractor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.instrumentation.api.instrumenter.code; | ||
|
||
import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; | ||
import io.opentelemetry.instrumentation.api.tracer.SpanNames; | ||
|
||
/** | ||
* A helper {@link SpanNameExtractor} implementation for instrumentations that target specific Java | ||
* classes/methods. | ||
*/ | ||
public final class CodeSpanNameExtractor<REQUEST> implements SpanNameExtractor<REQUEST> { | ||
|
||
/** | ||
* Returns a {@link SpanNameExtractor} that constructs the span name according to the following | ||
* pattern: {@code <class.simpleName>.<methodName>}. | ||
*/ | ||
public static <REQUEST> SpanNameExtractor<REQUEST> create( | ||
CodeAttributesExtractor<REQUEST, ?> attributesExtractor) { | ||
return new CodeSpanNameExtractor<>(attributesExtractor); | ||
} | ||
|
||
private final CodeAttributesExtractor<REQUEST, ?> attributesExtractor; | ||
|
||
private CodeSpanNameExtractor(CodeAttributesExtractor<REQUEST, ?> attributesExtractor) { | ||
this.attributesExtractor = attributesExtractor; | ||
} | ||
|
||
@Override | ||
public String extract(REQUEST request) { | ||
Class<?> cls = attributesExtractor.codeClass(request); | ||
// TODO: avoid using SpanNames, encapsulate the logic here | ||
String className = cls != null ? SpanNames.spanNameForClass(cls) : "<unknown>"; | ||
String methodName = defaultString(attributesExtractor.methodName(request)); | ||
return className + "." + methodName; | ||
} | ||
|
||
private static String defaultString(String s) { | ||
return s == null ? "<unknown>" : s; | ||
} | ||
} |
88 changes: 88 additions & 0 deletions
88
...a/io/opentelemetry/instrumentation/api/instrumenter/code/CodeAttributesExtractorTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.instrumentation.api.instrumenter.code; | ||
|
||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; | ||
import static org.assertj.core.api.Assertions.entry; | ||
|
||
import io.opentelemetry.api.common.Attributes; | ||
import io.opentelemetry.api.common.AttributesBuilder; | ||
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; | ||
import java.util.Collections; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import org.junit.jupiter.api.Test; | ||
|
||
class CodeAttributesExtractorTest { | ||
|
||
CodeAttributesExtractor<Map<String, String>, Void> underTest = | ||
new CodeAttributesExtractor<Map<String, String>, Void>() { | ||
@Override | ||
protected Class<?> codeClass(Map<String, String> request) { | ||
try { | ||
String className = request.get("class"); | ||
return className == null ? null : Class.forName(className); | ||
} catch (ClassNotFoundException e) { | ||
throw new AssertionError(e); | ||
} | ||
} | ||
|
||
@Override | ||
protected String methodName(Map<String, String> request) { | ||
return request.get("methodName"); | ||
} | ||
|
||
@Override | ||
protected String filePath(Map<String, String> request) { | ||
return request.get("filePath"); | ||
} | ||
|
||
@Override | ||
protected Long lineNumber(Map<String, String> request) { | ||
String lineNo = request.get("lineNo"); | ||
return lineNo == null ? null : Long.parseLong(lineNo); | ||
} | ||
}; | ||
|
||
@Test | ||
void shouldExtractAllAttributes() { | ||
// given | ||
Map<String, String> request = new HashMap<>(); | ||
request.put("class", TestClass.class.getName()); | ||
request.put("methodName", "doSomething"); | ||
request.put("filePath", "/tmp/TestClass.java"); | ||
request.put("lineNo", "42"); | ||
|
||
// when | ||
AttributesBuilder startAttributes = Attributes.builder(); | ||
underTest.onStart(startAttributes, request); | ||
|
||
AttributesBuilder endAttributes = Attributes.builder(); | ||
underTest.onEnd(endAttributes, request, null); | ||
|
||
// then | ||
assertThat(startAttributes.build()) | ||
.containsOnly( | ||
entry(SemanticAttributes.CODE_NAMESPACE, TestClass.class.getName()), | ||
entry(SemanticAttributes.CODE_FUNCTION, "doSomething"), | ||
entry(SemanticAttributes.CODE_FILEPATH, "/tmp/TestClass.java"), | ||
entry(SemanticAttributes.CODE_LINENO, 42L)); | ||
|
||
assertThat(endAttributes.build().isEmpty()).isTrue(); | ||
} | ||
|
||
@Test | ||
void shouldExtractNoAttributesIfNoneAreAvailable() { | ||
// when | ||
AttributesBuilder attributes = Attributes.builder(); | ||
underTest.onStart(attributes, Collections.emptyMap()); | ||
|
||
// then | ||
assertThat(attributes.build().isEmpty()).isTrue(); | ||
} | ||
|
||
static class TestClass {} | ||
} |
59 changes: 59 additions & 0 deletions
59
...ava/io/opentelemetry/instrumentation/api/instrumenter/code/CodeSpanNameExtractorTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.instrumentation.api.instrumenter.code; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
import static org.mockito.BDDMockito.willReturn; | ||
|
||
import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.ExtendWith; | ||
import org.mockito.Mock; | ||
import org.mockito.junit.jupiter.MockitoExtension; | ||
|
||
@ExtendWith(MockitoExtension.class) | ||
class CodeSpanNameExtractorTest { | ||
@Mock CodeAttributesExtractor<Object, Void> attributesExtractor; | ||
|
||
@Test | ||
void shouldExtractFullSpanName() { | ||
// given | ||
Object request = new Object(); | ||
|
||
willReturn(TestClass.class).given(attributesExtractor).codeClass(request); | ||
willReturn("doSomething").given(attributesExtractor).methodName(request); | ||
|
||
SpanNameExtractor<Object> underTest = CodeSpanNameExtractor.create(attributesExtractor); | ||
|
||
// when | ||
String spanName = underTest.extract(request); | ||
|
||
// then | ||
assertEquals("TestClass.doSomething", spanName); | ||
} | ||
|
||
@Test | ||
void shouldExtractFullSpanNameForAnonymousClass() { | ||
// given | ||
AnonymousBaseClass anon = new AnonymousBaseClass() {}; | ||
Object request = new Object(); | ||
|
||
willReturn(anon.getClass()).given(attributesExtractor).codeClass(request); | ||
willReturn("doSomething").given(attributesExtractor).methodName(request); | ||
|
||
SpanNameExtractor<Object> underTest = CodeSpanNameExtractor.create(attributesExtractor); | ||
|
||
// when | ||
String spanName = underTest.extract(request); | ||
|
||
// then | ||
assertEquals(getClass().getSimpleName() + "$1.doSomething", spanName); | ||
} | ||
|
||
static class TestClass {} | ||
|
||
static class AnonymousBaseClass {} | ||
} |
21 changes: 0 additions & 21 deletions
21
...agent/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/DataSourceTracer.java
This file was deleted.
Oops, something went wrong.
33 changes: 33 additions & 0 deletions
33
...elemetry/javaagent/instrumentation/jdbc/datasource/DataSourceCodeAttributesExtractor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.javaagent.instrumentation.jdbc.datasource; | ||
|
||
import io.opentelemetry.instrumentation.api.instrumenter.code.CodeAttributesExtractor; | ||
import javax.sql.DataSource; | ||
import org.checkerframework.checker.nullness.qual.Nullable; | ||
|
||
final class DataSourceCodeAttributesExtractor extends CodeAttributesExtractor<DataSource, Void> { | ||
|
||
@Override | ||
protected Class<?> codeClass(DataSource dataSource) { | ||
return dataSource.getClass(); | ||
} | ||
|
||
@Override | ||
protected String methodName(DataSource dataSource) { | ||
return "getConnection"; | ||
} | ||
|
||
@Override | ||
protected @Nullable String filePath(DataSource dataSource) { | ||
return null; | ||
} | ||
|
||
@Override | ||
protected @Nullable Long lineNumber(DataSource dataSource) { | ||
return null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
36 changes: 36 additions & 0 deletions
36
...a/io/opentelemetry/javaagent/instrumentation/jdbc/datasource/DataSourceInstrumenters.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.javaagent.instrumentation.jdbc.datasource; | ||
|
||
import io.opentelemetry.api.GlobalOpenTelemetry; | ||
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; | ||
import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; | ||
import io.opentelemetry.instrumentation.api.instrumenter.code.CodeAttributesExtractor; | ||
import io.opentelemetry.instrumentation.api.instrumenter.code.CodeSpanNameExtractor; | ||
import javax.sql.DataSource; | ||
|
||
public final class DataSourceInstrumenters { | ||
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.javaagent.jdbc"; | ||
|
||
private static final Instrumenter<DataSource, Void> INSTRUMENTER; | ||
|
||
static { | ||
CodeAttributesExtractor<DataSource, Void> attributesExtractor = | ||
new DataSourceCodeAttributesExtractor(); | ||
SpanNameExtractor<DataSource> spanNameExtractor = | ||
CodeSpanNameExtractor.create(attributesExtractor); | ||
|
||
INSTRUMENTER = | ||
Instrumenter.<DataSource, Void>newBuilder( | ||
GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, spanNameExtractor) | ||
.addAttributesExtractor(attributesExtractor) | ||
.newInstrumenter(); | ||
} | ||
|
||
public static Instrumenter<DataSource, Void> instrumenter() { | ||
return INSTRUMENTER; | ||
} | ||
} |
Oops, something went wrong.