Added Redis instrumentation via Jedis client 2.9 and changed spring-boot-jdbc to spring-boot-jdbc-redis
This commit is contained in:
parent
53ceb74912
commit
cef86291e3
|
@ -0,0 +1,13 @@
|
||||||
|
|
||||||
|
apply from: "${rootDir}/gradle/java.gradle"
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compileOnly group: 'redis.clients', name: 'jedis', version: '2.9.0'
|
||||||
|
|
||||||
|
compile project(':dd-trace-ot')
|
||||||
|
compile project(':dd-java-agent:tooling')
|
||||||
|
|
||||||
|
compile deps.bytebuddy
|
||||||
|
compile deps.opentracing
|
||||||
|
compile deps.autoservice
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
package datadog.trace.instrumentation.jedis;
|
||||||
|
|
||||||
|
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
|
||||||
|
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
|
||||||
|
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
|
||||||
|
import static net.bytebuddy.matcher.ElementMatchers.isProtected;
|
||||||
|
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
|
||||||
|
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||||
|
import static net.bytebuddy.matcher.ElementMatchers.not;
|
||||||
|
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
|
||||||
|
|
||||||
|
import com.google.auto.service.AutoService;
|
||||||
|
import datadog.trace.agent.tooling.DDAdvice;
|
||||||
|
import datadog.trace.agent.tooling.Instrumenter;
|
||||||
|
import datadog.trace.api.DDTags;
|
||||||
|
import io.opentracing.Scope;
|
||||||
|
import io.opentracing.Span;
|
||||||
|
import io.opentracing.tag.Tags;
|
||||||
|
import io.opentracing.util.GlobalTracer;
|
||||||
|
import java.util.Collections;
|
||||||
|
import net.bytebuddy.agent.builder.AgentBuilder;
|
||||||
|
import net.bytebuddy.asm.Advice;
|
||||||
|
import redis.clients.jedis.Protocol.Command;
|
||||||
|
|
||||||
|
@AutoService(Instrumenter.class)
|
||||||
|
public final class JedisInstrumentation implements Instrumenter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
|
||||||
|
return agentBuilder
|
||||||
|
.type(not(isInterface()).and(hasSuperType(named("redis.clients.jedis.Connection"))))
|
||||||
|
.transform(
|
||||||
|
DDAdvice.create()
|
||||||
|
.advice(
|
||||||
|
isMethod()
|
||||||
|
.and(isProtected())
|
||||||
|
.and(nameStartsWith("sendCommand"))
|
||||||
|
.and(takesArgument(1, byte[][].class)),
|
||||||
|
JedisAdvice.class.getName()))
|
||||||
|
.asDecorator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class JedisAdvice {
|
||||||
|
|
||||||
|
@Advice.OnMethodEnter(suppress = Throwable.class)
|
||||||
|
public static Scope nameResource(@Advice.Argument(0) final Command command) {
|
||||||
|
|
||||||
|
final Scope scope = GlobalTracer.get().buildSpan("redis.command").startActive(true);
|
||||||
|
|
||||||
|
final Span span = scope.span();
|
||||||
|
Tags.DB_TYPE.set(span, "redis");
|
||||||
|
Tags.SPAN_KIND.set(span, Tags.SPAN_KIND_CLIENT);
|
||||||
|
Tags.COMPONENT.set(span, "redis-command");
|
||||||
|
|
||||||
|
span.setTag(DDTags.RESOURCE_NAME, command.name());
|
||||||
|
span.setTag(DDTags.SERVICE_NAME, "redis");
|
||||||
|
span.setTag(DDTags.SPAN_TYPE, "redis");
|
||||||
|
span.setTag("span.origin.type", command.getClass().getName());
|
||||||
|
|
||||||
|
return scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||||
|
public static void stopSpan(
|
||||||
|
@Advice.Enter final Scope scope, @Advice.Thrown final Throwable throwable) {
|
||||||
|
if (throwable != null) {
|
||||||
|
final Span span = scope.span();
|
||||||
|
Tags.ERROR.set(span, true);
|
||||||
|
span.log(Collections.singletonMap("error.object", throwable));
|
||||||
|
}
|
||||||
|
scope.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ using the OpenTracing API and the DD Tracer.
|
||||||
|
|
||||||
Here are the examples
|
Here are the examples
|
||||||
* [Dropwizard (Jax-Rs) + Mongo database + HTTP Client](dropwizard-mongo-client/README.md)
|
* [Dropwizard (Jax-Rs) + Mongo database + HTTP Client](dropwizard-mongo-client/README.md)
|
||||||
* [Spring-boot + MySQL JDBC database](spring-boot-jdbc/README.md)
|
* [Spring-boot + MySQL JDBC database + Redis (Jedis client)](spring-boot-jdbc-redis/README.md)
|
||||||
* [Instrumenting using a Java Agent](javaagent/README.md)
|
* [Instrumenting using a Java Agent](javaagent/README.md)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,9 @@ all libraries and examples launching from the ``dd-trace-java`` root folder:
|
||||||
./gradlew clean shadowJar bootRepackage
|
./gradlew clean shadowJar bootRepackage
|
||||||
```
|
```
|
||||||
|
|
||||||
Then you can launch the Datadog agent as follows:
|
Then you can launch the Datadog agent and a Redis instance as follows:
|
||||||
```bash
|
```bash
|
||||||
cd examples/spring-boot-jdbc
|
cd examples/spring-boot-jdbc-redis
|
||||||
DD_API_KEY=<your_datadog_api_key> docker-compose up -d
|
DD_API_KEY=<your_datadog_api_key> docker-compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -31,12 +31,12 @@ To launch the application, just:
|
||||||
```
|
```
|
||||||
|
|
||||||
*Note: The ``bootRun`` Gradle command appends automatically the ``-javaagent`` argument, so that you don't need to specify
|
*Note: The ``bootRun`` Gradle command appends automatically the ``-javaagent`` argument, so that you don't need to specify
|
||||||
the path of the Java Agent. Gradle executes the ``:examples:spring-boot-jdbc:bootRun`` task until you
|
the path of the Java Agent. Gradle executes the ``:examples:spring-boot-jdbc-redis:bootRun`` task until you
|
||||||
stop it.*
|
stop it.*
|
||||||
|
|
||||||
Or as an executable jar:
|
Or as an executable jar:
|
||||||
```bash
|
```bash
|
||||||
java -javaagent:../../dd-java-agent/build/libs/dd-java-agent-{version}.jar -Ddd.service.name=spring-boot-jdbc -jar build/libs/spring-boot-jdbc-demo.jar
|
java -javaagent:../../dd-java-agent/build/libs/dd-java-agent-{version}.jar -Ddd.service.name=spring-boot-jdbc-redis -jar build/libs/spring-boot-jdbc-redis-demo.jar
|
||||||
```
|
```
|
||||||
|
|
||||||
### Generate traces
|
### Generate traces
|
||||||
|
@ -45,6 +45,7 @@ Once the Gradle task is running. Go to the following urls:
|
||||||
|
|
||||||
* [http://localhost:8080/user/add?name=foo&email=bar](http://localhost:8080/user/add?name=foo&email=bar)
|
* [http://localhost:8080/user/add?name=foo&email=bar](http://localhost:8080/user/add?name=foo&email=bar)
|
||||||
* [http://localhost:8080/user/all](http://localhost:8080/user/all)
|
* [http://localhost:8080/user/all](http://localhost:8080/user/all)
|
||||||
|
* [http://localhost:8080/user/all](http://localhost:8080/user/random)
|
||||||
|
|
||||||
Then get back to Datadog and wait a bit to see a trace coming.
|
Then get back to Datadog and wait a bit to see a trace coming.
|
||||||
|
|
||||||
|
@ -55,5 +56,6 @@ instruments:
|
||||||
|
|
||||||
- The java servlet filters
|
- The java servlet filters
|
||||||
- The JDBC driver
|
- The JDBC driver
|
||||||
|
- The Jedis Redis client
|
||||||
|
|
||||||
The Java Agent embeds the [OpenTracing Java Agent](https://github.com/opentracing-contrib/java-agent).
|
The Java Agent embeds the [OpenTracing Java Agent](https://github.com/opentracing-contrib/java-agent).
|
|
@ -5,3 +5,7 @@ ddagent:
|
||||||
- DD_API_KEY
|
- DD_API_KEY
|
||||||
ports:
|
ports:
|
||||||
- "127.0.0.1:8126:8126"
|
- "127.0.0.1:8126:8126"
|
||||||
|
redis:
|
||||||
|
image: redis
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:6379:6379"
|
|
@ -1,19 +1,21 @@
|
||||||
plugins {
|
plugins {
|
||||||
id 'org.springframework.boot' version '1.5.4.RELEASE'
|
id 'org.springframework.boot' version '1.5.10.RELEASE'
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: "${rootDir}/gradle/java.gradle"
|
apply from: "${rootDir}/gradle/java.gradle"
|
||||||
apply from: "${rootDir}/gradle/jacoco.gradle"
|
apply from: "${rootDir}/gradle/jacoco.gradle"
|
||||||
|
|
||||||
version = 'demo'
|
version = 'demo'
|
||||||
description = 'spring-boot-jdbc'
|
description = 'spring-boot-jdbc-redis'
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.3'
|
compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.3'
|
||||||
|
|
||||||
compile group: 'com.h2database', name: 'h2', version: '1.4.196'
|
compile group: 'com.h2database', name: 'h2', version: '1.4.196'
|
||||||
compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '1.5.4.RELEASE'
|
compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '1.5.10.RELEASE'
|
||||||
compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: '1.5.4.RELEASE'
|
compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: '1.5.10.RELEASE'
|
||||||
|
compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-redis', version: '1.5.10.RELEASE'
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bootRepackage {
|
bootRepackage {
|
||||||
|
@ -22,9 +24,9 @@ bootRepackage {
|
||||||
|
|
||||||
bootRun {
|
bootRun {
|
||||||
if (project.hasProperty('javaagent')) {
|
if (project.hasProperty('javaagent')) {
|
||||||
jvmArgs = ["-javaagent:$javaagent", "-Ddd.service.name=spring-boot-jdbc"]
|
jvmArgs = ["-javaagent:$javaagent", "-Ddd.service.name=spring-boot-jdbc-redis"]
|
||||||
} else {
|
} else {
|
||||||
jvmArgs = ["-javaagent:${project(':dd-java-agent').tasks.shadowJar.outputs.files.getFiles().iterator().next()}", "-Ddd.service.name=spring-boot-jdbc"]
|
jvmArgs = ["-javaagent:${project(':dd-java-agent').tasks.shadowJar.outputs.files.getFiles().iterator().next()}", "-Ddd.service.name=spring-boot-jdbc-redis"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@ package datadog.examples.resources;
|
||||||
import datadog.examples.entities.User;
|
import datadog.examples.entities.User;
|
||||||
import datadog.examples.entities.UserRepository;
|
import datadog.examples.entities.UserRepository;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
|
import org.springframework.data.redis.core.ValueOperations;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
@ -17,9 +19,16 @@ public class DBResource {
|
||||||
// Which is auto-generated by Spring, we will use it to handle the data
|
// Which is auto-generated by Spring, we will use it to handle the data
|
||||||
private UserRepository userRepository;
|
private UserRepository userRepository;
|
||||||
|
|
||||||
|
private ValueOperations<String, String> ops;
|
||||||
|
|
||||||
|
public DBResource(@Autowired StringRedisTemplate template) {
|
||||||
|
this.ops = template.opsForValue();
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping(path = "/add") // Map ONLY GET Requests
|
@GetMapping(path = "/add") // Map ONLY GET Requests
|
||||||
public @ResponseBody String addNewUser(
|
public @ResponseBody String addNewUser(
|
||||||
@RequestParam final String name, @RequestParam final String email) {
|
@RequestParam final String name, @RequestParam final String email) {
|
||||||
|
|
||||||
// @ResponseBody means the returned String is the response, not a view name
|
// @ResponseBody means the returned String is the response, not a view name
|
||||||
// @RequestParam means it is a parameter from the GET or POST request
|
// @RequestParam means it is a parameter from the GET or POST request
|
||||||
|
|
||||||
|
@ -27,6 +36,10 @@ public class DBResource {
|
||||||
n.setName(name);
|
n.setName(name);
|
||||||
n.setEmail(email);
|
n.setEmail(email);
|
||||||
userRepository.save(n);
|
userRepository.save(n);
|
||||||
|
|
||||||
|
// Also save to redis as key/value
|
||||||
|
ops.set(name, email);
|
||||||
|
|
||||||
return "Saved";
|
return "Saved";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +51,17 @@ public class DBResource {
|
||||||
|
|
||||||
@GetMapping(path = "/get")
|
@GetMapping(path = "/get")
|
||||||
public @ResponseBody User getUser(@RequestParam final int id) {
|
public @ResponseBody User getUser(@RequestParam final int id) {
|
||||||
// This returns a JSON or XML with the users
|
// This returns a JSON or XML with the user
|
||||||
return userRepository.findOne(id);
|
return userRepository.findOne(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping(path = "/getredis")
|
||||||
|
public @ResponseBody String getUserRedis(@RequestParam final String name) {
|
||||||
|
return ops.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping(path = "/random")
|
||||||
|
public @ResponseBody String flushRedis() {
|
||||||
|
return ops.getOperations().randomKey();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -15,9 +15,13 @@ public class HomeResource {
|
||||||
|
|
||||||
template.append("Demo links");
|
template.append("Demo links");
|
||||||
template.append("<ul>");
|
template.append("<ul>");
|
||||||
template.append("<li><a href=\"/user/add?name=name&email=f@example.com\">Add a user</a></li>");
|
template.append(
|
||||||
|
"<li><a href=\"/user/add?name=unnamed&email=unnamed@example.com\">Add a user</a></li>");
|
||||||
template.append("<li><a href=\"/user/all\">List all users</a></li>");
|
template.append("<li><a href=\"/user/all\">List all users</a></li>");
|
||||||
template.append("<li><a href=\"/user/get?id=1\">Get user with id=1</a></li>");
|
template.append("<li><a href=\"/user/get?id=1\">Get user with id=1</a></li>");
|
||||||
|
template.append(
|
||||||
|
"<li><a href=\"/user/getredis?name=unnamed\">Get user with name=unnamed</a></li>");
|
||||||
|
template.append("<li><a href=\"/user/random\">Get a random user's name</a></li>");
|
||||||
template.append("</ul>");
|
template.append("</ul>");
|
||||||
|
|
||||||
return template.toString();
|
return template.toString();
|
|
@ -1,7 +0,0 @@
|
||||||
# you must set the following so that OpenTracing traced driver is used
|
|
||||||
spring.datasource.driver-class-name=org.h2.Driver
|
|
||||||
spring.datasource.url=jdbc:h2:mem:spring-test;DB_CLOSE_ON_EXIT=FALSE
|
|
||||||
|
|
||||||
# set the logging level
|
|
||||||
logging.level.root=INFO
|
|
||||||
logging.level.datadog.trace=DEBUG
|
|
|
@ -12,6 +12,7 @@ include ':dd-java-agent:instrumentation:apache-httpclient-4.3'
|
||||||
include ':dd-java-agent:instrumentation:aws-sdk'
|
include ':dd-java-agent:instrumentation:aws-sdk'
|
||||||
include ':dd-java-agent:instrumentation:datastax-cassandra-3.2'
|
include ':dd-java-agent:instrumentation:datastax-cassandra-3.2'
|
||||||
include ':dd-java-agent:instrumentation:jdbc'
|
include ':dd-java-agent:instrumentation:jdbc'
|
||||||
|
include ':dd-java-agent:instrumentation:jedis-2.9'
|
||||||
include ':dd-java-agent:instrumentation:jms-1'
|
include ':dd-java-agent:instrumentation:jms-1'
|
||||||
include ':dd-java-agent:instrumentation:jms-2'
|
include ':dd-java-agent:instrumentation:jms-2'
|
||||||
include ':dd-java-agent:instrumentation:mongo-3.1'
|
include ':dd-java-agent:instrumentation:mongo-3.1'
|
||||||
|
@ -31,7 +32,7 @@ if (JavaVersion.current().isJava8Compatible()) {
|
||||||
|
|
||||||
// examples
|
// examples
|
||||||
include ':examples:dropwizard-mongo-client'
|
include ':examples:dropwizard-mongo-client'
|
||||||
include ':examples:spring-boot-jdbc'
|
include ':examples:spring-boot-jdbc-redis'
|
||||||
include ':examples:rest-spark'
|
include ':examples:rest-spark'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue