-
Notifications
You must be signed in to change notification settings - Fork 344
Start implementation of new tracer API #631
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,11 +5,17 @@ dependencies { | |
| annotationProcessor deps.autoservice | ||
| implementation deps.autoservice | ||
|
|
||
| compile project(':dd-java-agent:agent-bootstrap') | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 This is great. |
||
| compile project(':dd-trace-api') | ||
|
|
||
| compile deps.jackson | ||
| compile deps.slf4j | ||
| // any higher versions seems to break ES tests with this exception: | ||
| // java.lang.NoSuchMethodError: com.fasterxml.jackson.dataformat.smile.SmileGenerator.getOutputContext() | ||
| compile group: 'org.msgpack', name: 'jackson-dataformat-msgpack', version: '0.8.14' | ||
|
|
||
| // Spock uses that for mocking | ||
| testCompile deps.bytebuddy | ||
| testCompile group: 'org.objenesis', name: 'objenesis', version: '2.6' // Last version to support Java7 | ||
| testCompile group: 'nl.jqno.equalsverifier', name: 'equalsverifier', version: '2.5.2' // Last version to support Java7 | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,34 +1,59 @@ | ||
| package datadog.trace.tracer; | ||
|
|
||
| import java.util.concurrent.TimeUnit; | ||
| import lombok.EqualsAndHashCode; | ||
|
|
||
| /** | ||
| * A simple wrapper for system clock that aims to provide the current time | ||
| * | ||
| * <p> | ||
| * | ||
| * <p> | ||
| * | ||
| * <p> | ||
| * This is a wrapper to System clock that provides an easier way to get nanosecond precision. | ||
| * | ||
| * <p>The JDK provides two clocks: | ||
| * <li>one in nanoseconds, for precision, but it can only use to measure durations | ||
| * <li>one in milliseconds, for accuracy, useful to provide epoch time | ||
| * | ||
| * <p> | ||
| * <p>Once created this class captures current time with millisecond presition and current | ||
| * nanosecond counter. | ||
| * | ||
| * <p>At this time, we are using a millis precision (converted to micros) in order to guarantee | ||
| * consistency between the span start times and the durations | ||
| * <p>It provides an API to create {@link Timestamp} that can be used to measure durations with | ||
| * nanosecond precision. | ||
| */ | ||
| @EqualsAndHashCode | ||
| public class Clock { | ||
|
|
||
| /** Tracer that created this clock */ | ||
| private final Tracer tracer; | ||
|
|
||
| /** Trace start time in nano seconds measured up to a millisecond accuracy */ | ||
| private final long startTimeNano; | ||
| /** Nano ticks counter when clock is created */ | ||
| private final long startNanoTicks; | ||
|
|
||
| public Clock(final Tracer tracer) { | ||
| this.tracer = tracer; | ||
| startTimeNano = epochTimeNano(); | ||
| startNanoTicks = nanoTicks(); | ||
| } | ||
|
|
||
| /** @return {@link Tracer} that created this clock. */ | ||
| public Tracer getTracer() { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why does clock need to maintain a reference to the source tracer? Is this only so
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, right now that is the only reason. |
||
| return tracer; | ||
| } | ||
|
|
||
| /** | ||
| * Create new timestamp instance for current time. | ||
| * | ||
| * @return new timestamp capturing current time. | ||
| */ | ||
| public Timestamp createCurrentTimestamp() { | ||
| return new Timestamp(this); | ||
| } | ||
|
|
||
| /** | ||
| * Get the current nanos ticks (i.e. System.nanonTime()), this method can't be use for date | ||
| * accuracy (only duration calculations) | ||
| * Get the current nanos ticks (i.e. System.nanoTime()), this method can't be use for date | ||
| * accuracy (only duration calculations). | ||
| * | ||
| * @return The current nanos ticks | ||
| * @return The current nanos ticks. | ||
| */ | ||
| public static long nanoTime() { | ||
| long nanoTicks() { | ||
| return System.nanoTime(); | ||
| } | ||
|
|
||
|
|
@@ -37,20 +62,38 @@ public static long nanoTime() { | |
| * | ||
| * <p>Note: The actual precision is the millis. | ||
| * | ||
| * @return the current epoch time in micros | ||
| * @return the current epoch time in micros. | ||
| */ | ||
| public static long epochTimeMicro() { | ||
| long epochTimeMicro() { | ||
| return TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis()); | ||
| } | ||
|
|
||
| /** | ||
| * Get the current epoch time in nanos. | ||
| * | ||
| * <p>Note: The actual precision is the millis. This will overflow ~290 years after epoch | ||
| * <p>Note: The actual precision is the millis. This will overflow ~290 years after epoch. | ||
| * | ||
| * @return the current epoch time in nanos | ||
| * @return the current epoch time in nanos. | ||
| */ | ||
| public static long epochTimeNano() { | ||
| long epochTimeNano() { | ||
| return TimeUnit.MILLISECONDS.toNanos(System.currentTimeMillis()); | ||
| } | ||
|
|
||
| /** | ||
| * Get time this clock instance was created in nanos. | ||
| * | ||
| * @return the time this clock instance was created in nanos. | ||
| */ | ||
| long getStartTimeNano() { | ||
| return startTimeNano; | ||
| } | ||
|
|
||
| /** | ||
| * Get nano ticks counter value when this clock instance was created. | ||
| * | ||
| * @return nano ticks counter value when this clock instance was created. | ||
| */ | ||
| long getStartNanoTicks() { | ||
| return startNanoTicks; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| package datadog.trace.tracer; | ||
|
|
||
| /** | ||
| * Continuations are used to prevent a trace from reporting without creating a span. | ||
| * | ||
| * <p>All spans are thread safe. | ||
| * | ||
| * <p>To create a Span, see {@link Trace#createContinuation(Span parentSpan)} | ||
| */ | ||
| public interface Continuation { | ||
|
|
||
| /** @return parent span used to create this continuation. */ | ||
| Span getSpan(); | ||
|
|
||
| /** @return trace used to create this continuation. */ | ||
| Trace getTrace(); | ||
|
|
||
| /** @return true iff continuation has been closed. */ | ||
| boolean isClosed(); | ||
|
|
||
| /** | ||
| * Close the continuation. Continuation's trace will not block reporting on account of this | ||
| * continuation. | ||
| */ | ||
| void close(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| package datadog.trace.tracer; | ||
|
|
||
| import lombok.extern.slf4j.Slf4j; | ||
|
|
||
| /** Concrete implementation of a continuation */ | ||
| @Slf4j | ||
| class ContinuationImpl implements Continuation { | ||
|
|
||
| private final TraceInternal trace; | ||
| private final Span span; | ||
| private volatile boolean closed = false; | ||
|
|
||
| ContinuationImpl(final TraceInternal trace, final Span span) { | ||
| this.trace = trace; | ||
| this.span = span; | ||
| } | ||
|
|
||
| @Override | ||
| public Trace getTrace() { | ||
| return trace; | ||
| } | ||
|
|
||
| @Override | ||
| public Span getSpan() { | ||
| return span; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean isClosed() { | ||
| return closed; | ||
| } | ||
|
|
||
| @Override | ||
| public synchronized void close() { | ||
| if (closed) { | ||
| reportUsageError("Attempted to close continuation that is already closed: %s", this); | ||
| } else { | ||
| closeContinuation(false); | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| protected synchronized void finalize() { | ||
| try { | ||
| if (!closed) { | ||
| trace | ||
| .getTracer() | ||
| .reportWarning( | ||
| "Closing continuation due to GC, this will prevent trace from being reported: %s", | ||
| this); | ||
| closeContinuation(true); | ||
| } | ||
| } catch (final Throwable t) { | ||
| // Exceptions thrown in finalizer are eaten up and ignored, so log them instead | ||
| log.debug("Span finalizer had thrown an exception: ", t); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Helper method to perform operations needed to close the continuation. | ||
| * | ||
| * <p>Note: This has to be called under object lock. | ||
| * | ||
| * @param invalid true iff continuation is being closed due to GC, this will make trace invalid. | ||
| */ | ||
| private void closeContinuation(final boolean invalid) { | ||
| closed = true; | ||
| trace.closeContinuation(this, invalid); | ||
| } | ||
|
|
||
| private void reportUsageError(final String message, final Object... args) { | ||
| trace.getTracer().reportError(message, args); | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.