Skip to content

Commit

Permalink
Create TracingTimer that leverages OpenTracing
Browse files Browse the repository at this point in the history
  • Loading branch information
Clint Checketts committed Nov 12, 2017
1 parent f760e24 commit 059debe
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 1 deletion.
5 changes: 5 additions & 0 deletions micrometer-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ dependencies {

compile 'com.squareup.okhttp3:okhttp:3.9.0',optional

//tracing
compile 'io.opentracing:opentracing-api:0.30.0', optional
testCompile 'io.opentracing:opentracing-mock:0.30.0'
testCompile 'io.opentracing:opentracing-util:0.30.0'

testCompile 'io.projectreactor:reactor-test:3.1.0.RELEASE'
testCompile 'io.projectreactor.ipc:reactor-netty:0.7.0.RELEASE'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ class Builder {
private String description;
private final HistogramConfig.Builder histogramConfigBuilder;

private Builder(String name) {
Builder(String name) {
this.name = name;
this.histogramConfigBuilder = new HistogramConfig.Builder();
minimumExpectedValue(Duration.ofMillis(1));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/**
* Copyright 2017 Pivotal Software, Inc.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.micrometer.core.instrument;

import io.opentracing.ActiveSpan;
import io.opentracing.Tracer;

import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

public class TracingTimer implements Timer{

static Builder builder(String name, Tracer tracer) {
return new Builder(name, tracer);
}

static class Builder extends Timer.Builder{
private final Tracer tracer;

Builder(String name, Tracer tracer) {
super(name);
this.tracer = tracer;
}

@Override
public Timer register(MeterRegistry registry) {
return new TracingTimer(super.register(registry), tracer);
}
}

private final Timer delegate;
private final Tracer tracer;

TracingTimer(Timer delegate, Tracer tracer) {
this.delegate = delegate;
this.tracer = tracer;
}

private ActiveSpan createSpan() {
Tracer.SpanBuilder spanBuilder = tracer.buildSpan(getId().getName());
getId().getTags().forEach(t -> spanBuilder.withTag(t.getKey(), t.getValue()));
return spanBuilder.startActive();
}


@Override
public <T> T record(Supplier<T> f) {
try(@SuppressWarnings("unused") ActiveSpan span = createSpan()){
return delegate.record(f);
}
}

@Override
public <T> T recordCallable(Callable<T> f) throws Exception {
try(@SuppressWarnings("unused") ActiveSpan span = createSpan()) {
return delegate.recordCallable(f);
}
}

@Override
public void record(Runnable f) {
try(@SuppressWarnings("unused") ActiveSpan span = createSpan()) {
delegate.record(f);
}
}

@Override
public <T> Callable<T> wrap(Callable<T> f) {
return () -> {
try(@SuppressWarnings("unused") ActiveSpan span = createSpan()) {
return delegate.wrap(f).call();
}
};
}

@Override
public void record(long amount, TimeUnit unit) {
delegate.record(amount, unit);
}

@Override
public long count() {
return delegate.count();
}

@Override
public double totalTime(TimeUnit unit) {
return delegate.totalTime(unit);
}

@Override
public double max(TimeUnit unit) {
return delegate.max(unit);
}

@Override
public double percentile(double percentile, TimeUnit unit) {
return delegate.percentile(percentile, unit);
}

@Override
public double histogramCountAtValue(long valueNanos) {
return delegate.histogramCountAtValue(valueNanos);
}

@Override
public Id getId() {
return delegate.getId();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* Copyright 2017 Pivotal Software, Inc.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.micrometer.core.instrument;

import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import io.opentracing.mock.MockSpan;
import io.opentracing.mock.MockTracer;
import io.opentracing.util.ThreadLocalActiveSpanSource;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

class TracingTimerTest {

private MockTracer tracer;
private SimpleMeterRegistry registry;

@BeforeEach
void setup(){
tracer = new MockTracer(new ThreadLocalActiveSpanSource(), MockTracer.Propagator.TEXT_MAP);
registry = new SimpleMeterRegistry();
registry.config().commonTags("commonTag1", "commonVal1");
}

@Test
void tracingTimer() {
TracingTimer.builder("trace.outer.timer", tracer).tags("testTag1","testVal1").register(registry).record(() -> {
TracingTimer.builder("trace.inner.timer", tracer).tags("testTag2","testVal2").register(registry).record(() -> {
//Nothing to do here
});
});

List<MockSpan> mockSpans = tracer.finishedSpans();
assertThat(mockSpans).hasSize(2);

MockSpan innerSpan = mockSpans.get(0);
assertThat(innerSpan.operationName()).isEqualTo("trace.inner.timer");
assertThat(innerSpan.tags().get("commonTag1")).describedAs("Common tags are applied").isEqualTo("commonVal1");
assertThat(innerSpan.parentId()).isEqualTo(2L);

MockSpan outerSpan = mockSpans.get(1);
assertThat(outerSpan.operationName()).isEqualTo("trace.outer.timer");
assertThat(outerSpan.tags()).hasSize(2);
assertThat(outerSpan.tags().get("testTag1")).isEqualTo("testVal1");


}

}

0 comments on commit 059debe

Please sign in to comment.