Skip to content

Commit

Permalink
Annotation parity with Sleuth
Browse files Browse the repository at this point in the history
adds missing implementations of interfaces for @NewSpan and @ContinueSpan aspects.

feature parity will not be full cause we don't have access to Spring code in Micrometer so aspects will not work as well as they did in Sleuth. The difference will be that annotations (@NewSpan and @ContinueSpan) on interfaces will not be supported. We will only support them on the implementing classes, however we will support @SpanTag on the interfaces too).

fixes gh-163
  • Loading branch information
marcingrzejszczak committed Mar 10, 2023
1 parent cd86ecc commit ca3241d
Show file tree
Hide file tree
Showing 21 changed files with 1,552 additions and 13 deletions.
4 changes: 4 additions & 0 deletions dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ def VERSIONS = [
'io.micrometer:context-propagation:1.1.+',

'aopalliance:aopalliance:1.0',
'org.aspectj:aspectjweaver:1.8.+',
'org.springframework:spring-context:5.+',
'org.springframework:spring-core:5+',

// logging
'ch.qos.logback:logback-classic:1.2.+',
'org.apache.logging.log4j:log4j-core:2.+',
Expand Down
4 changes: 4 additions & 0 deletions micrometer-tracing-tests/micrometer-tracing-test/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@ dependencies {
// Tests for tests
testImplementation 'ch.qos.logback:logback-classic'
testImplementation 'org.junit.jupiter:junit-jupiter'

// aspects
testImplementation 'org.springframework:spring-context'
testImplementation 'org.aspectj:aspectjweaver'
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
import java.time.Instant;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static java.util.concurrent.TimeUnit.MILLISECONDS;

Expand All @@ -47,7 +49,7 @@ public class SimpleSpan implements Span, FinishedSpan {

private volatile Span.Kind spanKind;

private final Map<Long, String> events = new ConcurrentHashMap<>();
private final Queue<Event> events = new ConcurrentLinkedQueue<>();

private volatile String name;

Expand Down Expand Up @@ -92,13 +94,13 @@ public SimpleSpan name(String name) {

@Override
public SimpleSpan event(String value) {
this.events.put(MILLISECONDS.toMicros(this.clock.wallTime()), value);
this.events.add(new Event(MILLISECONDS.toMicros(this.clock.wallTime()), value));
return this;
}

@Override
public Span event(String value, long time, TimeUnit timeUnit) {
this.events.put(timeUnit.toMicros(time), value);
this.events.add(new Event(timeUnit.toMicros(time), value));
return this;
}

Expand Down Expand Up @@ -158,7 +160,7 @@ public FinishedSpan setEvents(Collection<Map.Entry<Long, String>> events) {

@Override
public Collection<Map.Entry<Long, String>> getEvents() {
return this.events.entrySet();
return this.events.stream().map(Event::toEntry).collect(Collectors.toList());
}

void setStartMillis(long startMillis) {
Expand Down Expand Up @@ -285,4 +287,38 @@ public String toString() {
+ '\'' + ", port=" + port + ", noop=" + noop + ", clock=" + clock + ", context=" + context + '}';
}

static class Event {

final Long timestamp;

final String eventName;

Event(Long timestamp, String eventName) {
this.timestamp = timestamp;
this.eventName = eventName;
}

Map.Entry<Long, String> toEntry() {
return new AbstractMap.SimpleEntry<>(this.timestamp, this.eventName);
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Event event = (Event) o;
return Objects.equals(this.timestamp, event.timestamp) && Objects.equals(this.eventName, event.eventName);
}

@Override
public int hashCode() {
return Objects.hash(this.timestamp, this.eventName);
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
*/
package io.micrometer.tracing.test.simple;

import io.micrometer.tracing.Span;
import io.micrometer.tracing.SpanCustomizer;
import io.micrometer.tracing.Tracer;

/**
* A test implementation of a span customizer.
Expand All @@ -27,29 +29,51 @@ public class SimpleSpanCustomizer implements SpanCustomizer {

private final SimpleSpan span;

private final Tracer tracer;

/**
* Creates a new instance of {@link SimpleSpanCustomizer}.
* @param span simple span
* @deprecated use {@link SimpleSpanCustomizer(SimpleTracer)}
*/
@Deprecated
public SimpleSpanCustomizer(SimpleSpan span) {
this.span = span;
this.tracer = Tracer.NOOP;
}

/**
* Creates a new instance of {@link SimpleSpanCustomizer}.
* @param tracer simple tracer
*/
public SimpleSpanCustomizer(SimpleTracer tracer) {
this.span = null;
this.tracer = tracer;
}

private Span currentSpan() {
Span currentSpan = this.tracer.currentSpan();
if (currentSpan == null) {
throw new IllegalStateException("Current span is null");
}
return currentSpan;
}

@Override
public SpanCustomizer name(String name) {
this.span.name(name);
currentSpan().name(name);
return this;
}

@Override
public SpanCustomizer tag(String key, String value) {
this.span.tag(key, value);
currentSpan().tag(key, value);
return this;
}

@Override
public SpanCustomizer event(String value) {
this.span.event(value);
currentSpan().event(value);
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public SimpleSpanInScope withSpan(Span span) {

@Override
public SimpleSpanCustomizer currentSpanCustomizer() {
return new SimpleSpanCustomizer(currentSpan());
return new SimpleSpanCustomizer(this);
}

@Override
Expand Down Expand Up @@ -150,6 +150,16 @@ public Baggage createBaggage(String name, String value) {
return this.simpleBaggageManager.createBaggage(name, value);
}

@Override
public BaggageInScope createBaggageInScope(String name, String value) {
return this.simpleBaggageManager.createBaggageInScope(name, value);
}

@Override
public BaggageInScope createBaggageInScope(TraceContext traceContext, String name, String value) {
return this.simpleBaggageManager.createBaggageInScope(traceContext, name, value);
}

/**
* Created spans.
* @return all created spans
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
* Copyright 2023 VMware, Inc.
*
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* 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.tracing.test.annotation;

import io.micrometer.tracing.annotation.*;
import io.micrometer.tracing.test.simple.SimpleTracer;
import io.micrometer.tracing.test.simple.TracerAssert;
import org.assertj.core.api.BDDAssertions;
import org.junit.jupiter.api.Test;
import org.springframework.aop.aspectj.annotation.AspectJProxyFactory;

class SpanCreatorAspectNegativeTests {

SimpleTracer tracer = new SimpleTracer();

NotAnnotatedTestBeanInterface testBean = new NotAnnotatedTestBean();

TestBeanInterface annotatedTestBean = new TestBean();

@Test
void shouldNotCallAdviceForNotAnnotatedBean() {
AspectJProxyFactory pf = new AspectJProxyFactory(this.testBean);
pf.addAspect(new SpanAspect(new ImperativeMethodInvocationProcessor(new DefaultNewSpanParser(), tracer,
aClass -> null, aClass -> null)));

((NotAnnotatedTestBeanInterface) pf.getProxy()).testMethod();

BDDAssertions.then(tracer.getSpans()).isEmpty();
}

@Test
void shouldCallAdviceForAnnotatedBean() throws Throwable {
AspectJProxyFactory pf = new AspectJProxyFactory(this.annotatedTestBean);
pf.addAspect(new SpanAspect(new ImperativeMethodInvocationProcessor(new DefaultNewSpanParser(), tracer,
aClass -> null, aClass -> null)));

// Sleuth allowed checking for parent methods / interfaces
((TestBeanInterface) pf.getProxy()).testMethod2();

TracerAssert.assertThat(tracer).onlySpan().isStarted().isEnded().hasNameEqualTo("test-method2");
}

protected interface NotAnnotatedTestBeanInterface {

void testMethod();

}

protected interface TestBeanInterface {

@NewSpan
void testMethod();

void testMethod2();

void testMethod3();

@NewSpan(name = "testMethod4")
void testMethod4();

@NewSpan(name = "testMethod5")
void testMethod5(@SpanTag("testTag") String test);

void testMethod6(String test);

void testMethod7();

}

protected static class NotAnnotatedTestBean implements NotAnnotatedTestBeanInterface {

@Override
public void testMethod() {
}

}

protected static class TestBean implements TestBeanInterface {

@Override
public void testMethod() {
}

@NewSpan
@Override
public void testMethod2() {
}

@NewSpan(name = "testMethod3")
@Override
public void testMethod3() {
}

@Override
public void testMethod4() {
}

@Override
public void testMethod5(String test) {
}

@NewSpan(name = "testMethod6")
@Override
public void testMethod6(@SpanTag("testTag6") String test) {

}

@Override
public void testMethod7() {
}

}

}

0 comments on commit ca3241d

Please sign in to comment.