-
Notifications
You must be signed in to change notification settings - Fork 858
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
AddingSpanAttributes annotation #7787
Conversation
|
652c565
to
1144ffc
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @sfriberg !
...in/java/io/opentelemetry/instrumentation/api/annotation/support/AttributeBindingFactory.java
Outdated
Show resolved
Hide resolved
...in/java/io/opentelemetry/instrumentation/api/annotation/support/SpanAttributesExtractor.java
Outdated
Show resolved
Hide resolved
...in/java/io/opentelemetry/instrumentation/api/annotation/support/SpanAttributesExtractor.java
Outdated
Show resolved
Hide resolved
...ry/javaagent/instrumentation/instrumentationannotations/AnnotationInstrumentationModule.java
Outdated
Show resolved
Hide resolved
...try/javaagent/instrumentation/instrumentationannotations/WithCurrentSpanInstrumentation.java
Outdated
Show resolved
Hide resolved
...try/javaagent/instrumentation/instrumentationannotations/WithCurrentSpanInstrumentation.java
Outdated
Show resolved
Hide resolved
...ntation-annotations-1.16/javaagent/src/test/groovy/WithCurrentSpanInstrumentationTest.groovy
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this idea a lot and think it could be useful. I wonder if @WithSpan(useParent=true, ...)
might possibly be more useful and less clashy? In any case, I think a few behaviors need to be clarified. Thanks!
...elemetry/javaagent/instrumentation/instrumentationannotations/AnnotationInstrumentation.java
Outdated
Show resolved
Hide resolved
name "external" | ||
kind INTERNAL |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seeing external
and INTERNAL
on the same span can be slightly misleading. Maybe rename external
to parent
or root
for clarity?
@WithSpan | ||
@WithCurrentSpan | ||
public String withSpanAttributes( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a reader would quickly question this use of seemingly conflicting annotations. One explicitly creates a new span, one explicitly does not and uses the parent context. You can't have it both ways, so which one wins? It's not easily understood.
Looking at the test, it seems like @WithCurrentSpan
wins here, because there's only 1 span in the resulting trace. Can you confirm that that is intentional?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that is intentional. The WithCurrenSpan instrumentation explicitly filters out any method that happens for some reason to be annotated with both.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isAnnotatedWith(
named("application.io.opentelemetry.instrumentation.annotations.WithCurrentSpan"))
// Avoid repeat extraction if method is already annotation with WithSpan
.and(
not(
isAnnotatedWith(
named(
"application.io.opentelemetry.instrumentation.annotations.WithSpan"))));
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What will happen if in the scope of a single span, 2 different methods with @WithCurrentSpan
and their particular @SpanAttribute
are invoked in chain?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It will overwrite in the same way calls to span.setAttribute(k,v)
would if the key was already used.
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like there's also a missing test or two here --
- what's the behavior if/when
@WithCurrentSpan
is used when there is no parent context? - what's the behavior if/when the current span already has an attribute with the same name defined?
33e0dd3
to
604b68d
Compare
I think this could be an interesting path. Probably name the variable |
My ByteBuddy knowledge isn't good enough to figure out how to write an element matcher that also looks at the value of an annotation field, or if it is even possible. So far what I have seen is that you can access that in your Advice methods which would be a bit of a hassle since you don't want to do extra work in the instrumented code. |
I think you could do sth like this: declaresAnnotation(
annotationType(
named(
"application.io.opentelemetry.instrumentation.annotations.WithSpan"))
.and(new AnnotationHasBooleanValue("useCurrent", true))); where static final class AnnotationHasBooleanValue implements ElementMatcher<AnnotationDescription> {
private final String fieldName;
private final boolean fieldValue;
AnnotationHasBooleanValue(String fieldName, boolean fieldValue) {
this.fieldName = fieldName;
this.fieldValue = fieldValue;
}
@Override
public boolean matches(AnnotationDescription target) {
AnnotationValue<?, ?> value = target.getValue(fieldName);
return value.resolve(boolean.class) == fieldValue;
}
} I haven't tested it though. |
*/ | ||
@Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
public @interface WithCurrentSpan {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if there is not current span? Will it create one?
Should we name it @SpanAttributes
(plural) or similar, instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If now span exists nothing will happen. Working on an updated impl which will instead reuse WithSpan with a variable useCurrent
to select if you want a new Span or reuse an existing one.
@WithSpan | ||
@WithCurrentSpan | ||
public String withSpanAttributes( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What will happen if in the scope of a single span, 2 different methods with @WithCurrentSpan
and their particular @SpanAttribute
are invoked in chain?
@mateuszrzeszutek Thanks for the pointers was able to get things working. Only thing was that you must use Boolean.class rather than boolean.class it seems like. However as I tested things and started to write some Javadoc I realized that reusing WithSpan will probably cause more confusion that simplify things. If you set Since the focus is really just span attributes I kind of like the name suggested by @brunobat, but WithCurrentSpan also keeps it close to the current naming rather than changing things completely. I should be able to join this coming Thursday and perhaps we can make a quick decision there.
|
|
||
public class SpanAttributesWithCurrentSpan { | ||
|
||
@WithCurrentSpan |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
alternatives:
WithSpanAttributes
✅UpdateCurrentSpan
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @sfriberg !
...ry/javaagent/instrumentation/instrumentationannotations/AnnotationInstrumentationModule.java
Outdated
Show resolved
Hide resolved
....0/javaagent/src/test/java/io/opentelemetry/test/annotation/WithSpanInstrumentationTest.java
Outdated
Show resolved
Hide resolved
....0/javaagent/src/test/java/io/opentelemetry/test/annotation/WithSpanInstrumentationTest.java
Outdated
Show resolved
Hide resolved
Anything further for me todo, or ready to be approved and merged? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thx @sfriberg!
@sfriberg could you rebase so that this pr could be merged |
@sfriberg sorry, I had second thoughts on the annotation name because "with" implies to me "in the scope of", or possibly immutable, and this is mutating something already in scope. we discussed in Java SIG meeting and came up with |
@sfriberg would you mind adding some code snippet examples in the PR description so it's easier to understand what this does and how it should be used? |
Co-authored-by: Mateusz Rzeszutek <[email protected]>
…ent/src/test/java/io/opentelemetry/test/annotation/WithSpanInstrumentationTest.java Co-authored-by: Mateusz Rzeszutek <[email protected]>
…ent/src/test/java/io/opentelemetry/test/annotation/WithSpanInstrumentationTest.java Co-authored-by: Mateusz Rzeszutek <[email protected]>
…/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/instrumentationannotations/AnnotationInstrumentationModule.java Co-authored-by: Mateusz Rzeszutek <[email protected]>
19bbf3c
to
f7baa03
Compare
@trask No problem, think the name changes make sense. Should be all updated now. |
...est/java/io/opentelemetry/instrumentation/annotations/AddingSpanAttributesUsageExamples.java
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sfriberg thanks for improving the description. That makes things much clearer.
@sfriberg thx 🎉 (and thx for your patience) |
Does For example, using a Customer object. Does that work out the box? Or is it possible to pick only some fields from Customer?
|
AFAIR it'll just set the value to the result of Span.current().setAttribute("something", customer.getSomething()); |
Expand the capabilities of
SpanAttribute
annotations to allow adding method parameters to and existing span on not only when the method is annotated withWithSpan
.To add to an existing span use the
AddingSpanAttributes
annotation on the method and applySpanAttribute
annotations as you would do withWithSpan
.As an example the following annotated method would if auto instrumentation is enabled add two attributes on every execution to the current span that is in context. If there is no current span no new span will be created. Similar to setAttribute any existing attributes will be overwritten.
Suggestion for implementation of the discussion we had in the OTel Java meeting on 2023-02-02 and 2023-03-02.