Ability to add extra service information (WIP)

This commit is contained in:
Guillaume Polaert 2017-08-07 12:04:26 +02:00
parent f1b31a661a
commit 4072edb405
7 changed files with 170 additions and 1 deletions

View File

@ -7,13 +7,19 @@ import com.datadoghq.trace.sampling.AllSampler;
import com.datadoghq.trace.sampling.Sampler;
import com.datadoghq.trace.writer.LoggingWriter;
import com.datadoghq.trace.writer.Writer;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.opentracing.ActiveSpan;
import io.opentracing.ActiveSpanSource;
import io.opentracing.BaseSpan;
import io.opentracing.SpanContext;
import io.opentracing.propagation.Format;
import io.opentracing.util.ThreadLocalActiveSpanSource;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ThreadLocalRandom;
import lombok.extern.slf4j.Slf4j;
@ -37,6 +43,7 @@ public class DDTracer extends ThreadLocalActiveSpanSource implements io.opentrac
private final Map<String, List<AbstractDecorator>> spanContextDecorators = new HashMap<>();
private final CodecRegistry registry;
private final List<Service> services = new ArrayList<>();
/** Default constructor, trace/spans are logged, no trace/span dropped */
public DDTracer() {
@ -137,6 +144,33 @@ public class DDTracer extends ThreadLocalActiveSpanSource implements io.opentrac
return "DDTracer{" + "writer=" + writer + ", sampler=" + sampler + '}';
}
/**
* Register additional information about a service. Service additional information are a Datadog
* feature only. Services are reported through a specific Datadog endpoint.
*
* @param service additional service information
*/
public void addServiceInfo(final Service service) {
services.add(service);
// Update the write
try {
// We don't bother to send multiple times the list of services at this time
writer.writeServices(services);
} catch (final Throwable ex) {
log.warn("Failed to report additional service information, reason: {}", ex.getMessage());
}
}
/**
* Return the list of additional service information registered
*
* @return the list of additional service information
*/
@JsonIgnore
public List<Service> getServiceInfo() {
return services;
}
private static class CodecRegistry {
private final Map<Format<?>, Codec<?>> codecs = new HashMap<>();

View File

@ -0,0 +1,47 @@
package com.datadoghq.trace;
import com.fasterxml.jackson.annotation.JsonProperty;
public class Service {
private final String name;
private final String appName;
private final Service.AppType appType;
public Service(final String name, final String appName, final AppType appType) {
this.name = name;
this.appName = appName;
this.appType = appType;
}
@JsonProperty("service")
public String getName() {
return name;
}
@JsonProperty("app")
public String getAppName() {
return appName;
}
@JsonProperty("app_type")
public AppType getAppType() {
return appType;
}
public enum AppType {
WEB("web"),
DB("db"),
CUSTOM("custom");
private final String type;
AppType(final String type) {
this.type = type;
}
public String toString() {
return type;
}
}
}

View File

@ -1,6 +1,7 @@
package com.datadoghq.trace.writer;
import com.datadoghq.trace.DDBaseSpan;
import com.datadoghq.trace.Service;
import com.google.auto.service.AutoService;
import java.util.List;
import java.util.concurrent.Callable;
@ -80,6 +81,9 @@ public class DDAgentWriter implements Writer {
queueFullReported = false;
}
@Override
public void writeServices(final List<Service> services) {}
/* (non-Javadoc)
* @see com.datadoghq.trace.writer.Writer#start()
*/

View File

@ -1,8 +1,10 @@
package com.datadoghq.trace.writer;
import com.datadoghq.trace.DDBaseSpan;
import com.datadoghq.trace.Service;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
/** List writer used by tests mostly */
public class ListWriter extends CopyOnWriteArrayList<List<DDBaseSpan<?>>> implements Writer {
@ -20,6 +22,11 @@ public class ListWriter extends CopyOnWriteArrayList<List<DDBaseSpan<?>>> implem
add(trace);
}
@Override
public void writeServices(final List<Service> services) {
throw new NotImplementedException();
}
@Override
public void start() {
clear();

View File

@ -1,6 +1,7 @@
package com.datadoghq.trace.writer;
import com.datadoghq.trace.DDBaseSpan;
import com.datadoghq.trace.Service;
import com.google.auto.service.AutoService;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
@ -14,6 +15,11 @@ public class LoggingWriter implements Writer {
log.info("write(trace): {}", trace);
}
@Override
public void writeServices(final List<Service> services) {
log.info("additional service information: {}", services);
}
@Override
public void close() {
log.info("close()");

View File

@ -1,6 +1,7 @@
package com.datadoghq.trace.writer;
import com.datadoghq.trace.DDBaseSpan;
import com.datadoghq.trace.Service;
import java.util.List;
/** A writer is responsible to send collected spans to some place */
@ -13,6 +14,13 @@ public interface Writer {
*/
void write(List<DDBaseSpan<?>> trace);
/**
* Report additional service information to the endpoint
*
* @param services a list of extra information about services
*/
void writeServices(List<Service> services);
/** Start the writer */
void start();

View File

@ -0,0 +1,63 @@
package com.datadoghq.trace
import com.datadoghq.trace.sampling.AllSampler
import com.datadoghq.trace.writer.DDAgentWriter
import org.mockito.Mockito
import spock.lang.Specification
class ServiceTest extends Specification {
def "getter/setter"() {
setup:
def service = new Service("service-name", "app-name", Service.AppType.CUSTOM)
expect:
service.getName() == "service-name"
service.getAppName() == "app-name"
service.getAppType() == Service.AppType.CUSTOM
}
def "enum"() {
expect:
Service.AppType.values().size() == 3
Service.AppType.DB.toString() == "db"
Service.AppType.WEB.toString() == "web"
Service.AppType.CUSTOM.toString() == "custom"
}
def "add extra info about a specific service"() {
setup:
def tracer = new DDTracer()
def service = new Service("service-name", "app-name", Service.AppType.CUSTOM)
when:
tracer.addServiceInfo(service)
then:
tracer.getServiceInfo().size() == 1
tracer.getServiceInfo().get(0) == service
}
def "add a extra info is reported to the writer"() {
setup:
def writer = Mockito.spy(new DDAgentWriter())
def tracer = new DDTracer(writer, new AllSampler())
when:
tracer.addServiceInfo(new Service("service-name", "app-name", Service.AppType.CUSTOM))
then:
Mockito.verify(writer, Mockito.times(1)).writeServices(Mockito.any(List.class))
}
}