Make it cleaner

This commit is contained in:
Guillaume Polaert 2017-05-30 10:18:25 +02:00
parent 26342e48d9
commit 8180a9cd0d
5 changed files with 133 additions and 117 deletions

View File

@ -2,33 +2,40 @@
### Purpose
This project aims at demonstrating how to instrument legacy code based on Dropwizard and a client querying a Mongo database.
We also demonstrate cross-process tracing through the `TracedClient` example.
This project aims at demonstrating how to instrument legacy code based on:
* the Dropwizard framework
* a Mongo database.
We also demonstrate user cross-process tracing through the `TracedClient` example.
### Run the demo
#### Prerequisites
1. Please make sure that you read and executed the prerequisites provided [on this page](../README.md)
2. Make sure that you have a local mongo database running.
1. Make sure that you have a local mongo database running (hostname: `localhost`, port: `27017`).
2. No process holding the 8080 and the 8081 port, they are used by the Dropwizard server.
If you're using Docker, you can run a mongo instance as follow:
```bash
docker run -it --rm -p 27017:27017 --name mongo -d mongo
```
#### Run the application
If you want to enable tracing you have to launch the application with the datadog java agent.
Get the latest version of the dd-java-agent:
If you want to enable tracing you have to launch the application with the Datadog java agent.
First, get the latest version of the dd-java-agent:
```
# use latest version
# Use latest version
curl -OL http://central.maven.org/maven2/com/datadoghq/dd-java-agent/0.0.1/dd-java-agent-0.0.1.jar
```
Then add the agent to the JVM. That can be done by providing the following argument:
`-javaagent:/path/to/dd-java-agent-0.0.1.jar`.
Then, add the agent to the JVM. That can be done by providing the following argument:
`java -javaagent:/path/to/dd-java-agent-0.0.1.jar ...`.
### Generate traces
*A trace example*
![](./apm.png)
#### With your web browser
@ -46,27 +53,19 @@ In that case, we instrument the `OkHttpClient` and you then observe a similar tr
Cross process tracing is working thanks to headers injected on the client side that are extracted on the server. If you want to understand more you can refer to the [opentracing documentation](http://opentracing.io/documentation/pages/api/cross-process-tracing.html).
*A trace example*
![](./apm.png)
### How did we instrument this project?
#### Auto-instrumentation with the `dd-trace-agent`
The instrumentation is entirely done by the datadog agent which embed a set of rules that automatically recognizes & instruments:
- The java servlet filters
- The Java servlet filters
- The Mongo client
- The OkHTTP client
The datadog agent embeds the [open tracing java agent](https://github.com/opentracing-contrib/java-agent).
#### Custom methods instrumentation
As an illustration of
We wrote 4 rules in the `otarules.btm` files in order to instrument the `HelloWorldResource.beforeDB()` & `HelloWorldResource.afterDB()` methods.
It brief, it consists in wrapping the content of this method with 2 rules:
* 1 ENTRY rule: that start a child span
* 1 EXIT rule: that finishes & deactivate the current span
We encourage to open the rules file to get the details.
The Datadog agent embeds the [open tracing java agent](https://github.com/opentracing-contrib/java-agent).
We strongly recommend you to refer to the [Datadog Agent documentation](../../dd-java-agent) if you want to dig deeper.

View File

@ -1,53 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.datadoghq</groupId>
<artifactId>dd-trace-examples</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<parent>
<groupId>com.datadoghq</groupId>
<artifactId>dd-trace-examples</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>dropwizard-mongo-client</artifactId>
<packaging>jar</packaging>
<name>dropwizard-mongo-client</name>
<properties>
<dropwizard.version>0.9.2</dropwizard.version>
<ot.agent.version>0.0.12</ot.agent.version>
</properties>
<dependencies>
<!-- dropwizard + http client -->
<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-core</artifactId>
<version>${dropwizard.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-client</artifactId>
<version>3.1.11</version>
</dependency>
<artifactId>dropwizard-mongo-client</artifactId>
<name>dropwizard-mongo-client</name>
<packaging>jar</packaging>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.7.0</version>
</dependency>
<dependency>
<groupId>com.datadoghq</groupId>
<artifactId>dd-java-agent</artifactId>
<version>${ot.dd-trace.version}</version>
</dependency>
</dependencies>
<dependencies>
<!-- This dependency is required for the @trace annotation -->
<dependency>
<groupId>com.datadoghq</groupId>
<artifactId>dd-java-agent</artifactId>
<version>${ot.dd-trace.version}</version>
</dependency>
<!-- Application dependencies -->
<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-core</artifactId>
<version>0.9.2</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.7.0</version>
</dependency>
</dependencies>
</project>

View File

@ -2,28 +2,29 @@ package com.example.helloworld;
import com.example.helloworld.resources.SimpleCrudResource;
import io.dropwizard.Application;
import io.dropwizard.Configuration;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
public class HelloWorldApplication extends Application<HelloWorldConfiguration> {
public static void main(String[] args) throws Exception {
new HelloWorldApplication().run(args);
}
public class HelloWorldApplication extends Application<Configuration> {
public static void main(String[] args) throws Exception {
new HelloWorldApplication().run(args);
}
@Override
public String getName() {
return "hello-world";
}
@Override
public String getName() {
return "hello-world";
}
@Override
public void initialize(Bootstrap<HelloWorldConfiguration> bootstrap) {
// nothing to do yet
}
@Override
public void initialize(Bootstrap<Configuration> bootstrap) {
// nothing to do yet
}
@Override
public void run(HelloWorldConfiguration configuration, Environment environment) {
@Override
public void run(Configuration configuration, Environment environment) {
environment.jersey().register(new SimpleCrudResource());
}
environment.jersey().register(new SimpleCrudResource());
}
}

View File

@ -1,8 +0,0 @@
package com.example.helloworld;
import io.dropwizard.Configuration;
public class HelloWorldConfiguration extends Configuration {
}

View File

@ -3,7 +3,6 @@ package com.example.helloworld.resources;
import com.example.helloworld.api.Book;
import com.google.common.base.Optional;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import io.opentracing.contrib.agent.Trace;
@ -21,26 +20,36 @@ import java.util.List;
@Produces(MediaType.APPLICATION_JSON)
public class SimpleCrudResource {
// Instantiate Synchronous Tracing MongoClient
private final MongoClient client;
private final MongoDatabase db;
private static final String HOSTNAME = "localhost";
private static final String DATABASE = "demo";
private static final java.lang.String COLLECTION = "books";
public SimpleCrudResource() {
MongoClientOptions settings = MongoClientOptions.builder()
.codecRegistry(com.mongodb.MongoClient.getDefaultCodecRegistry())
.build();
MongoClient client = new MongoClient("localhost", settings);
client.dropDatabase("demo");
db = client.getDatabase("demo");
db.createCollection("books");
// Init the client
client = new MongoClient(HOSTNAME);
// For this example, start from a fresh DB
try {
client.dropDatabase(DATABASE);
} catch (Exception e) {
// do nothing here
}
// Init the connection to the collection
db = client.getDatabase(DATABASE);
db.createCollection(COLLECTION);
}
/**
* Add a book to the DB
*
* @return The status of the save
* @throws InterruptedException
*/
@GET
@Path("/add")
public String addBook(
@ -50,7 +59,7 @@ public class SimpleCrudResource {
) throws InterruptedException {
// Simple business need to execute before saving a new book
// The methodDB is traced (see below), this will be produced a new child span
beforeDB();
if (!isbn.isPresent()) {
@ -59,40 +68,65 @@ public class SimpleCrudResource {
Book book = new Book(
isbn.get(),
title.or("missing title"),
title.or("Missing title"),
page.or(0));
db.getCollection("books").insertOne(book.toDocument());
return "Book saved";
db.getCollection(COLLECTION).insertOne(book.toDocument());
return "Book saved!";
}
/**
* List all books present in the DB
*
* @return list of Books
* @throws InterruptedException
*/
@GET
public List<Book> getBooks() throws InterruptedException {
// Simple business need to execute before saving a new book
// The methodDB is traced (see below), this will be produced a new childre span
beforeDB();
List<Book> books = new ArrayList<>();
try (MongoCursor<Document> cursor = db.getCollection("books").find().iterator();) {
try (MongoCursor<Document> cursor = db.getCollection(COLLECTION).find().iterator();) {
while (cursor.hasNext()) {
books.add(new Book(cursor.next()));
}
}
// Simple business need to execute after retrieve the book list
afterDB();
// The methodDB is traced (see below), this will be produced a new child span
beforeDB();
return books;
}
/**
* The beforeDB is traced using the annotation @trace
* Tags, the operation name can be configured using tagsKV and operationName options
*
* @throws InterruptedException
*/
@Trace(operationName = "Before DB", tagsKV = {"mytag", "myvalue"})
public void beforeDB() throws InterruptedException {
Thread.sleep(333);
}
/**
* The beforeDB is traced using the annotation @trace
* Tags, the operation name can be configured using tagsKV and operationName options
*
* @throws InterruptedException
*/
@Trace(operationName = "After DB", tagsKV = {"mytag", "myvalue"})
public void afterDB() throws InterruptedException {
Thread.sleep(111);
}
/**
* Flush resources
*/
public void close() {
client.close();
}
}