Move noop-api from opentelemetry-java (#430)
* Move noop-api from opentelemetry-java * Move test * Spotless
This commit is contained in:
parent
1e7f1d0e20
commit
add40c1fd8
|
@ -33,6 +33,8 @@ components:
|
|||
- kenfinnigan
|
||||
micrometer-meter-provider:
|
||||
- HaloFour
|
||||
noop-api:
|
||||
- jack-berg
|
||||
runtime-attach:
|
||||
- iNikem
|
||||
- jeanbisutti
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
# OpenTelemetry Noop API
|
||||
|
||||
[![Javadocs][javadoc-image]][javadoc-url]
|
||||
|
||||
An implementation of `OpenTelemetry` that is completely no-op. Unlike `OpenTelemetry#noop()`, this
|
||||
implementation does not support in-process context propagation at all. This means that no objects
|
||||
are allocated nor {@link ThreadLocal}s used in an application using this implementation.
|
||||
|
||||
## Component owners
|
||||
|
||||
- [Jack Berg](https://github.com/jack-berg), New Relic
|
||||
|
||||
Learn more about component owners in [component_owners.yml](../.github/component_owners.yml).
|
||||
|
||||
[javadoc-image]: https://www.javadoc.io/badge/io.opentelemetry/opentelemetry-extension-noop-api.svg
|
||||
[javadoc-url]: https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-extension-noop-api
|
|
@ -0,0 +1,8 @@
|
|||
plugins {
|
||||
id("otel.java-conventions")
|
||||
id("otel.publish-conventions")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api("io.opentelemetry:opentelemetry-api")
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.contrib.noopapi;
|
||||
|
||||
import io.opentelemetry.context.Context;
|
||||
import io.opentelemetry.context.ContextKey;
|
||||
import io.opentelemetry.context.ContextStorage;
|
||||
import io.opentelemetry.context.ContextStorageProvider;
|
||||
import io.opentelemetry.context.Scope;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* A {@link ContextStorageProvider} that returns a {@link ContextStorage} which is completely no-op.
|
||||
*/
|
||||
public class NoopContextStorageProvider implements ContextStorageProvider {
|
||||
|
||||
/** Returns a no-op context storage. */
|
||||
@Override
|
||||
public ContextStorage get() {
|
||||
return NoopContextStorage.INSTANCE;
|
||||
}
|
||||
|
||||
enum NoopContextStorage implements ContextStorage {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public Scope attach(Context toAttach) {
|
||||
return Scope.noop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Context current() {
|
||||
return NoopContext.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
enum NoopContext implements Context {
|
||||
INSTANCE;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <V> V get(ContextKey<V> key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <V> Context with(ContextKey<V> k1, V v1) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.contrib.noopapi;
|
||||
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import io.opentelemetry.api.metrics.MeterProvider;
|
||||
import io.opentelemetry.api.trace.SpanContext;
|
||||
import io.opentelemetry.api.trace.TracerProvider;
|
||||
import io.opentelemetry.context.propagation.ContextPropagators;
|
||||
|
||||
/**
|
||||
* An implementation of {@link OpenTelemetry} that is completely no-op. Unlike {@link
|
||||
* OpenTelemetry#noop()}, this implementation does not support in-process context propagation at
|
||||
* all. This means that no objects are allocated nor {@link ThreadLocal}s used in an application
|
||||
* using this implementation. This can be a good option for use in frameworks shared across a large
|
||||
* number of servers to introduce instrumentation without forcing overhead on any users of the
|
||||
* framework. If such overhead is not a concern, always use either {@link OpenTelemetry#noop()},
|
||||
* {@link OpenTelemetry#propagating(ContextPropagators)}, or the OpenTelemetry SDK.
|
||||
*
|
||||
* <p>The following code will fail because context is not mounted.
|
||||
*
|
||||
* <pre>{@code
|
||||
* try (Scope ignored = Context.current().with(Span.wrap(VALID_SPAN_CONTEXT).makeCurrent()) {
|
||||
* assert Span.current().spanContext().equals(VALID_SPAN_CONTEXT);
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* <p>In most cases when instrumenting a library, the above pattern does not happen because {@link
|
||||
* io.opentelemetry.api.trace.Span#wrap(SpanContext)} is primarily for use in remote propagators.
|
||||
* The common pattern looks like
|
||||
*
|
||||
* <pre>{@code
|
||||
* Span span = tracer.spanBuilder().setAttribute(...).startSpan();
|
||||
* try (Scope ignored = Context.current().with(span).makeCurrent()) {
|
||||
* assert Span.current().spanContext().equals(SpanContext.getInvalid());
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* <p>The above will succeed both with the {@linkplain OpenTelemetry#noop() default implementation}
|
||||
* and this one, but with this implementation there will be no overhead at all.
|
||||
*/
|
||||
public class NoopOpenTelemetry implements OpenTelemetry {
|
||||
|
||||
private static final OpenTelemetry INSTANCE = new NoopOpenTelemetry();
|
||||
|
||||
public static OpenTelemetry getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TracerProvider getTracerProvider() {
|
||||
return NoopTracerProvider.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MeterProvider getMeterProvider() {
|
||||
// Default implementation is already truly no-op.
|
||||
return MeterProvider.noop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContextPropagators getPropagators() {
|
||||
return ContextPropagators.noop();
|
||||
}
|
||||
|
||||
private NoopOpenTelemetry() {}
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.contrib.noopapi;
|
||||
|
||||
import io.opentelemetry.api.common.AttributeKey;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.trace.Span;
|
||||
import io.opentelemetry.api.trace.SpanBuilder;
|
||||
import io.opentelemetry.api.trace.SpanContext;
|
||||
import io.opentelemetry.api.trace.SpanKind;
|
||||
import io.opentelemetry.api.trace.Tracer;
|
||||
import io.opentelemetry.api.trace.TracerProvider;
|
||||
import io.opentelemetry.context.Context;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
enum NoopTracerProvider implements TracerProvider {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public Tracer get(String instrumentationScopeName) {
|
||||
return NoopTracer.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tracer get(String instrumentationScopeName, String instrumentationScopeVersion) {
|
||||
return NoopTracer.INSTANCE;
|
||||
}
|
||||
|
||||
enum NoopTracer implements Tracer {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public SpanBuilder spanBuilder(String spanName) {
|
||||
return NoopSpanBuilder.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
enum NoopSpanBuilder implements SpanBuilder {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public SpanBuilder setParent(Context context) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpanBuilder setNoParent() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpanBuilder addLink(SpanContext spanContext) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpanBuilder addLink(SpanContext spanContext, Attributes attributes) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpanBuilder setAttribute(String key, String value) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpanBuilder setAttribute(String key, long value) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpanBuilder setAttribute(String key, double value) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpanBuilder setAttribute(String key, boolean value) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> SpanBuilder setAttribute(AttributeKey<T> key, T value) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpanBuilder setSpanKind(SpanKind spanKind) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpanBuilder setStartTimestamp(long startTimestamp, TimeUnit unit) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Span startSpan() {
|
||||
return Span.getInvalid();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
io.opentelemetry.contrib.noopapi.NoopContextStorageProvider
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.contrib.noopapi;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import io.opentelemetry.api.common.AttributeKey;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.trace.Span;
|
||||
import io.opentelemetry.api.trace.SpanBuilder;
|
||||
import io.opentelemetry.api.trace.SpanContext;
|
||||
import io.opentelemetry.api.trace.SpanKind;
|
||||
import io.opentelemetry.api.trace.TraceFlags;
|
||||
import io.opentelemetry.api.trace.TraceState;
|
||||
import io.opentelemetry.context.Context;
|
||||
import io.opentelemetry.context.Scope;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class NoopOpenTelemetryTest {
|
||||
|
||||
private static final SpanContext SPAN_CONTEXT =
|
||||
SpanContext.create(
|
||||
"00000000000000000000000000000061",
|
||||
"0000000000000061",
|
||||
TraceFlags.getDefault(),
|
||||
TraceState.getDefault());
|
||||
|
||||
@Test
|
||||
void contextNoOp() {
|
||||
// Context.root() is not a no-op Context, so the default context is never root.
|
||||
Context context = Context.current();
|
||||
assertThat(context).isNotSameAs(Context.root());
|
||||
// No allocations
|
||||
assertThat(context.with(Span.wrap(SPAN_CONTEXT))).isSameAs(context);
|
||||
assertThat(SPAN_CONTEXT.isValid()).isTrue();
|
||||
try (Scope ignored = Context.current().with(Span.wrap(SPAN_CONTEXT)).makeCurrent()) {
|
||||
// No context mounted, so always an invalid span.
|
||||
assertThat(Span.fromContext(Context.current()).getSpanContext().isValid()).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void tracerNoOp() {
|
||||
SpanBuilder span1 = NoopOpenTelemetry.getInstance().getTracer("test").spanBuilder("test");
|
||||
SpanBuilder span2 = NoopOpenTelemetry.getInstance().getTracer("test").spanBuilder("test");
|
||||
// No allocations
|
||||
assertThat(span1).isSameAs(span2);
|
||||
|
||||
// No crash
|
||||
span1.setParent(Context.current());
|
||||
span1.setNoParent();
|
||||
span1.addLink(SPAN_CONTEXT);
|
||||
span1.addLink(SPAN_CONTEXT, Attributes.empty());
|
||||
span1.setAttribute("key", "value");
|
||||
span1.setAttribute("key", 1L);
|
||||
span1.setAttribute("key", 1.0);
|
||||
span1.setAttribute("key", true);
|
||||
span1.setAttribute(AttributeKey.stringKey("key"), "value");
|
||||
span1.setSpanKind(SpanKind.CLIENT);
|
||||
span1.setStartTimestamp(1, TimeUnit.DAYS);
|
||||
|
||||
// No allocations
|
||||
assertThat(span1.startSpan()).isSameAs(Span.getInvalid());
|
||||
}
|
||||
}
|
|
@ -44,9 +44,10 @@ include(":dependencyManagement")
|
|||
include(":example")
|
||||
include(":jfr-events")
|
||||
include(":jfr-streaming")
|
||||
include(":micrometer-meter-provider")
|
||||
include(":jmx-metrics")
|
||||
include(":maven-extension")
|
||||
include(":micrometer-meter-provider")
|
||||
include(":noop-api")
|
||||
include(":runtime-attach:runtime-attach")
|
||||
include(":runtime-attach:runtime-attach-core")
|
||||
include(":samplers")
|
||||
|
|
Loading…
Reference in New Issue