-
Notifications
You must be signed in to change notification settings - Fork 879
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
add metric annotation instrumentation #11354
base: main
Are you sure you want to change the base?
Changes from all commits
21cbf96
ff05043
f5d339f
22d6c43
aa3b47c
36a9ab5
d954ebe
9eac550
37733c1
6cdfff9
771cc58
42aa73b
c9ea9a0
43855a5
a844fa3
2c2c3d5
7fefa91
3e3b100
de28d29
99c2937
8a01999
172f2ac
6ba7771
0010367
430e690
f6887ae
630eeac
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 |
---|---|---|
@@ -0,0 +1,13 @@ | ||
plugins { | ||
id("otel.java-conventions") | ||
id("otel.japicmp-conventions") | ||
id("otel.publish-conventions") | ||
|
||
id("otel.animalsniffer-conventions") | ||
} | ||
|
||
group = "io.opentelemetry.instrumentation" | ||
|
||
dependencies { | ||
api("io.opentelemetry:opentelemetry-api") | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.instrumentation.annotations.incubator; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
/** | ||
* This annotation creates a {@link io.opentelemetry.api.metrics.LongCounter Counter} instrument | ||
* recording the number of invocations of the annotated method or constructor. | ||
* | ||
* <p>By default, the Counter instrument will have the following attributes: | ||
* | ||
* <ul> | ||
* <li><b>code.namespace:</b> The fully qualified name of the class whose method is invoked. | ||
* <li><b>code.function:</b> The name of the annotated method. | ||
* <li><b>exception.type:</b> This is only present if an Exception is thrown, and contains the | ||
* {@link Class#getName name} of the Exception class. | ||
* </ul> | ||
* | ||
* <p>Application developers can use this annotation to signal OpenTelemetry auto-instrumentation | ||
* that the Counter instrument should be created. | ||
* | ||
* <p>If you are a library developer, then probably you should NOT use this annotation, because it | ||
* is non-functional without the OpenTelemetry auto-instrumentation agent, or some other annotation | ||
* processor. | ||
*/ | ||
@Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
public @interface Counted { | ||
|
||
/** | ||
* Name of the Counter instrument. | ||
* | ||
* <p>The name should follow the instrument naming rule: <a | ||
* href="https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-naming-rule">https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-naming-rule</a> | ||
*/ | ||
String value(); | ||
|
||
/** | ||
* Description of the instrument. | ||
* | ||
* <p>Description strings should follow the instrument description rules: <a | ||
* href="https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-description">https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-description</a> | ||
* | ||
* <p>This property would not take effect if the value is not specified. | ||
*/ | ||
String description() default ""; | ||
|
||
/** | ||
* Unit of the instrument. | ||
* | ||
* <p>Unit strings should follow the instrument unit rules: <a | ||
* href="https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-unit">https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-unit</a> | ||
* | ||
* <p>This property would not take effect if the value is not specified. | ||
*/ | ||
String unit() default "{invocation}"; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.instrumentation.annotations.incubator; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
/** | ||
* This annotation marks that a parameter of a method or constructor annotated with {@link Timed} or | ||
* {@link Counted} should be added as an attribute to the instrument. | ||
* | ||
* <p>Application developers can use this annotation to signal OpenTelemetry auto-instrumentation | ||
* that the attribute should be created. | ||
* | ||
* <p>If you are a library developer, then probably you should NOT use this annotation, because it | ||
* is non-functional without the OpenTelemetry auto-instrumentation agent, or some other annotation | ||
* processor. | ||
* | ||
* <p>Warning: be careful using this because it might cause an explosion of the cardinality on your | ||
* metric. | ||
*/ | ||
@Target(ElementType.PARAMETER) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
public @interface MetricAttribute { | ||
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. I would call this 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. I totally agree that the current names are not ideal, but I think they are good enough for the first prototype and give a good base to build upon. To be honest I wasn't really interested in driving this effort I only wanted to help getting this PR into mergeable shape. 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. It's probably worth to discuss this a bit because if we have to change it in the future, it will be yet another breaking change. |
||
|
||
/** | ||
* Optional name of the attribute. | ||
* | ||
* <p>If not specified and the code is compiled using the `{@code -parameters}` argument to | ||
trask marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* `javac`, the parameter name will be used instead. If the parameter name is not available, e.g., | ||
* because the code was not compiled with that flag, the attribute will be ignored. | ||
*/ | ||
String value() default ""; | ||
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. I wonder if it's worth renaming this to 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. I don't really like forcing users to use |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.instrumentation.annotations.incubator; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
/** | ||
* This annotation allows for adding method return value as attribute to the metrics recorded using | ||
* {@link Timed} and {@link Counted} annotations. | ||
* | ||
* <p>Application developers can use this annotation to signal OpenTelemetry auto-instrumentation | ||
* that the attribute should be created. | ||
* | ||
* <p>If you are a library developer, then probably you should NOT use this annotation, because it | ||
* is non-functional without the OpenTelemetry auto-instrumentation agent, or some other annotation | ||
* processor. | ||
* | ||
* <p>Warning: be careful using this because it might cause an explosion of the cardinality on your | ||
* metric. | ||
*/ | ||
@Target(ElementType.METHOD) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
public @interface MetricAttributeForReturnValue { | ||
|
||
/** | ||
* Attribute name for the return value. | ||
* | ||
* <p>The name of the attribute for the return value of the method call. {@link Object#toString()} | ||
* may be called on the return value to convert it to a String. | ||
*/ | ||
String value(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.instrumentation.annotations.incubator; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Repeatable; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
/** | ||
* This annotation allows for adding attributes to the metrics recorded using {@link Timed} and | ||
* {@link Counted} annotations. | ||
* | ||
* <p>Application developers can use this annotation to signal OpenTelemetry auto-instrumentation | ||
* that the attribute should be created. | ||
* | ||
* <p>If you are a library developer, then probably you should NOT use this annotation, because it | ||
* is non-functional without the OpenTelemetry auto-instrumentation agent, or some other annotation | ||
* processor. | ||
*/ | ||
@Target(ElementType.METHOD) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
@Repeatable(StaticMetricAttributes.class) | ||
public @interface StaticMetricAttribute { | ||
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.
|
||
|
||
/** Name of the attribute. */ | ||
String name(); | ||
|
||
/** Value of the attribute. */ | ||
String value(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.instrumentation.annotations.incubator; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
/** | ||
* This annotation allows for adding attributes to the metrics recorded using {@link Timed} and | ||
* {@link Counted} annotations. | ||
* | ||
* <p>Application developers can use this annotation to signal OpenTelemetry auto-instrumentation | ||
* that the attribute should be created. | ||
* | ||
* <p>If you are a library developer, then probably you should NOT use this annotation, because it | ||
* is non-functional without the OpenTelemetry auto-instrumentation agent, or some other annotation | ||
* processor. | ||
*/ | ||
@Target(ElementType.METHOD) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
public @interface StaticMetricAttributes { | ||
|
||
/** Array of {@link StaticMetricAttribute} annotations describing the added attributes. */ | ||
StaticMetricAttribute[] value(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.instrumentation.annotations.incubator; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
import java.util.concurrent.TimeUnit; | ||
|
||
/** | ||
* This annotation creates a {@link io.opentelemetry.api.metrics.DoubleHistogram Histogram} | ||
* instrument observing the duration of invocations of the annotated method or constructor. | ||
* | ||
* <p>By default, the Histogram instrument will have the following attributes: | ||
* | ||
* <ul> | ||
* <li><b>code.namespace:</b> The fully qualified name of the class whose method is invoked. | ||
* <li><b>code.function:</b> The name of the annotated method. | ||
* <li><b>exception.type:</b> This is only present if an Exception is thrown, and contains the | ||
* {@link Class#getName name} of the Exception class. | ||
* </ul> | ||
* | ||
* <p>Application developers can use this annotation to signal OpenTelemetry auto-instrumentation | ||
* that the Histogram instrument should be created. | ||
* | ||
* <p>If you are a library developer, then probably you should NOT use this annotation, because it | ||
* is non-functional without the OpenTelemetry auto-instrumentation agent, or some other annotation | ||
* processor. | ||
*/ | ||
@Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
public @interface Timed { | ||
|
||
/** | ||
* Name of the Histogram instrument. | ||
* | ||
* <p>The name should follow the instrument naming rule: <a | ||
* href="https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-naming-rule">https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-naming-rule</a> | ||
*/ | ||
String value(); | ||
|
||
/** | ||
* Description for the instrument. | ||
* | ||
* <p>Description strings should follow the instrument description rules: <a | ||
* href="https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-description">https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-description</a> | ||
*/ | ||
String description() default ""; | ||
|
||
/** | ||
* The unit for the instrument. | ||
* | ||
* <p>Default is seconds. | ||
*/ | ||
TimeUnit unit() default TimeUnit.SECONDS; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.instrumentation.annotations.incubator; | ||
|
||
public class CountedUsageExamples { | ||
|
||
@Counted("customizedName") | ||
public void method() {} | ||
|
||
@Counted("methodWithAttributes") | ||
public void attributes( | ||
@MetricAttribute String attribute1, @MetricAttribute("attribute2") long attribute2) {} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.instrumentation.annotations.incubator; | ||
|
||
public class TimedUsageExamples { | ||
|
||
@Timed("customizedName") | ||
public void method() {} | ||
|
||
@Timed("methodWithAttributes") | ||
public void attributes( | ||
@MetricAttribute String attribute1, @MetricAttribute("attribute2") long attribute2) {} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.instrumentation.api.annotation.support; | ||
|
||
import io.opentelemetry.api.common.AttributesBuilder; | ||
import java.lang.reflect.Method; | ||
import java.util.function.BiConsumer; | ||
import javax.annotation.Nullable; | ||
|
||
/** Helper class for binding method parameters and return value to attributes. */ | ||
public final class MethodBinder { | ||
|
||
/** Create binding for method return value. */ | ||
@Nullable | ||
public static BiConsumer<AttributesBuilder, Object> bindReturnValue( | ||
Method method, String attributeName) { | ||
Class<?> returnType = method.getReturnType(); | ||
if (returnType == void.class) { | ||
return null; | ||
} | ||
AttributeBinding binding = AttributeBindingFactory.createBinding(attributeName, returnType); | ||
return binding::apply; | ||
} | ||
|
||
/** Create binding for method parameters. */ | ||
@Nullable | ||
public static BiConsumer<AttributesBuilder, Object[]> bindParameters( | ||
Method method, ParameterAttributeNamesExtractor parameterAttributeNamesExtractor) { | ||
AttributeBindings bindings = AttributeBindings.bind(method, parameterAttributeNamesExtractor); | ||
if (bindings.isEmpty()) { | ||
return null; | ||
} | ||
return bindings::apply; | ||
} | ||
|
||
private MethodBinder() {} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.instrumentation.api.annotation.support.async; | ||
|
||
import io.opentelemetry.context.Context; | ||
import javax.annotation.Nullable; | ||
|
||
/** Callback that is called when async computation completes. */ | ||
public interface AsyncOperationEndHandler<REQUEST, RESPONSE> { | ||
void handle( | ||
Context context, REQUEST request, @Nullable RESPONSE response, @Nullable Throwable error); | ||
} |
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.
Can we doc the attribute type that will be used for the metric attribute?
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.
The attribute type is chosen based on the same logic as with
SpanAttribute
. The logic for choosing the type in https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/instrumentation-annotations-support/src/main/java/io/opentelemetry/instrumentation/api/annotation/support/AttributeBindingFactory.java is quite complicated but in my opinion still not complete. For example it does not handlebyte
andshort
and their arrays as numeric types. In the span attribute code there are differences between attribute types used in the default and kotlin coroutine implementation.