rate) {
44 | return rate.get() != null ? rate.get() : 0;
45 | }
46 |
47 | @Override
48 | public boolean isSampled(long traceId) {
49 | return this.sampler.isSampled(traceId);
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/spring-observability-tracing/spring-observability-tracing-api/src/main/java/org/springframework/observability/tracing/SpanAndScope.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2021 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.tracing;
18 |
19 | import java.io.Closeable;
20 |
21 | /**
22 | * Container object for {@link Span} and its corresponding {@link Tracer.SpanInScope}.
23 | *
24 | * @author Marcin Grzejszczak
25 | * @since 1.0.0
26 | */
27 | public class SpanAndScope implements Closeable {
28 |
29 | private final Span span;
30 |
31 | private final Tracer.SpanInScope scope;
32 |
33 | /**
34 | * @param span span
35 | * @param scope scope of the span
36 | */
37 | public SpanAndScope(Span span, Tracer.SpanInScope scope) {
38 | this.span = span;
39 | this.scope = scope;
40 | }
41 |
42 | /**
43 | * @return stored span
44 | */
45 | public Span getSpan() {
46 | return this.span;
47 | }
48 |
49 | /**
50 | * @return stored scope of the span
51 | */
52 | public Tracer.SpanInScope getScope() {
53 | return this.scope;
54 | }
55 |
56 | @Override
57 | public String toString() {
58 | return "SpanAndScope{" + "span=" + this.span + '}';
59 | }
60 |
61 | @Override
62 | public void close() {
63 | this.scope.close();
64 | this.span.end();
65 | }
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/docs/src/main/asciidoc/README.adoc:
--------------------------------------------------------------------------------
1 | image::https://github.com/spring-projects/spring-observability/workflows/Build/badge.svg?branch=main&style=svg["Build",link="https://github.com/spring-projects/spring-observability/actions"]
2 |
3 | == Building and Deploying
4 |
5 | To install locally:
6 |
7 | ----
8 |
9 | $ mvn install
10 | ----
11 |
12 | and to deploy snapshots to repo.spring.io:
13 |
14 | ----
15 | $ mvn deploy -DaltSnapshotDeploymentRepository=repo.spring.io::default::https://repo.spring.io/snapshot
16 | ----
17 |
18 | for a RELEASE build use
19 |
20 | ----
21 | $ mvn deploy -DaltReleaseDeploymentRepository=repo.spring.io::default::https://repo.spring.io/release
22 | ----
23 |
24 | and for Maven Central use
25 |
26 | ----
27 | $ mvn deploy -P central -DaltReleaseDeploymentRepository=sonatype-nexus-staging::default::https://oss.sonatype.org/service/local/staging/deploy/maven2
28 | ----
29 |
30 | (the "central" profile is available for all projects in Spring Observability and it sets up the gpg jar signing, and the repository has to be specified separately for this project because it is a parent of the starter parent which users in turn have as their own parent).
31 |
32 | == Contributing
33 |
34 | include::https://raw.githubusercontent.com/spring-projects/spring-observability/main/docs/src/main/asciidoc/contributing.adoc[]
35 |
36 | == Flattening the POMs
37 |
38 | To avoid propagating build setup that is required to build a Spring Observability project, we're using the maven flatten plugin. It has the advantage of letting you use whatever features you need while publishing "clean" pom to the repository.
39 |
40 | In order to add it, add the `org.codehaus.mojo:flatten-maven-plugin` to your `pom.xml`.
41 |
42 | [source,xml]
43 | ----
44 |
45 |
46 |
47 | org.codehaus.mojo
48 | flatten-maven-plugin
49 |
50 |
51 |
52 | ----
53 |
--------------------------------------------------------------------------------
/spring-observability-tracing/spring-observability-tracing-reporters/spring-observability-tracing-reporters-wavefront/src/test/java/org/springframework/observability/tracing/reporter/wavefront/WavefrontSleuthBraveSpanHandlerTests.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2020 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.tracing.reporter.wavefront;
18 |
19 | import brave.handler.MutableSpan;
20 | import brave.handler.SpanHandler;
21 | import brave.propagation.TraceContext;
22 | import org.junit.jupiter.api.Test;
23 | import org.mockito.BDDMockito;
24 |
25 | import org.springframework.observability.tracing.exporter.FinishedSpan;
26 |
27 | class WavefrontSleuthBraveSpanHandlerTests {
28 |
29 | @Test
30 | void should_delegate_to_generic_sleuth_span_handler() {
31 | WavefrontSleuthSpanHandler sleuthSpanHandler = BDDMockito.mock(WavefrontSleuthSpanHandler.class);
32 | WavefrontSleuthBraveSpanHandler handler = new WavefrontSleuthBraveSpanHandler(sleuthSpanHandler);
33 |
34 | handler.end(TraceContext.newBuilder().traceId(1L).spanId(2L).build(), new MutableSpan(),
35 | SpanHandler.Cause.FINISHED);
36 |
37 | BDDMockito.then(sleuthSpanHandler).should().end(
38 | BDDMockito.any(org.springframework.observability.tracing.TraceContext.class),
39 | BDDMockito.any(FinishedSpan.class));
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/spring-observability-api/src/main/java/org/springframework/observability/lang/NonNullFields.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2002-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.lang;
18 |
19 | import java.lang.annotation.Documented;
20 | import java.lang.annotation.ElementType;
21 | import java.lang.annotation.Retention;
22 | import java.lang.annotation.RetentionPolicy;
23 | import java.lang.annotation.Target;
24 |
25 | import javax.annotation.Nonnull;
26 | import javax.annotation.meta.TypeQualifierDefault;
27 |
28 | /**
29 | * A common Spring annotation to declare that fields are to be considered as non-nullable
30 | * by default for a given package.
31 | *
32 | *
33 | * Leverages JSR-305 meta-annotations to indicate nullability in Java to common tools with
34 | * JSR-305 support and used by Kotlin to infer nullability of Spring API.
35 | *
36 | *
37 | * Should be used at package level in association with {@link Nullable} annotations at
38 | * field level.
39 | *
40 | * @author Sebastien Deleuze
41 | * @since 1.0.0
42 | * @see NonNullApi
43 | * @see Nullable
44 | * @see NonNull
45 | */
46 | @Target(ElementType.PACKAGE)
47 | @Retention(RetentionPolicy.RUNTIME)
48 | @Documented
49 | @Nonnull
50 | @TypeQualifierDefault(ElementType.FIELD)
51 | public @interface NonNullFields {
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/spring-observability-api/src/main/java/org/springframework/observability/event/instant/InstantRecording.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2021-2021 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.event.instant;
18 |
19 | import org.springframework.observability.event.Recording;
20 | import org.springframework.observability.event.listener.RecordingListener;
21 |
22 | /**
23 | * Represents the recording of an {@link InstantEvent}. Calling the
24 | * {@link InstantRecording#recordInstant()} method should result in a call of
25 | * {@link RecordingListener#recordInstant(InstantRecording)}.
26 | *
27 | * @author Jonatan Ivanov
28 | * @since 1.0.0
29 | */
30 | public interface InstantRecording extends Recording {
31 |
32 | /**
33 | * Signals that an {@link InstantEvent} happened.
34 | */
35 | void recordInstant();
36 |
37 | /**
38 | * Signals that an {@link InstantEvent} happened at a given time.
39 | * @param wallTime the wall time (system time) in nanoseconds since the epoch at the
40 | * time the event happened
41 | */
42 | void recordInstant(long wallTime);
43 |
44 | /**
45 | * The wall time (system time) in nanoseconds since the epoch at the time the event
46 | * happened.
47 | * @return the wall time (system time)
48 | */
49 | long getWallTime();
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/spring-observability-api/src/main/java/org/springframework/observability/event/interval/IntervalHttpEvent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2021-2021 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.event.interval;
18 |
19 | import org.springframework.observability.lang.NonNull;
20 | import org.springframework.observability.lang.Nullable;
21 | import org.springframework.observability.transport.http.Request;
22 | import org.springframework.observability.transport.http.Response;
23 |
24 | /**
25 | * An IntervalEvent that represents an HTTP event.
26 | *
27 | * @param request type
28 | * @param response type
29 | * @author Marcin Grzejszczak
30 | * @since 1.0.0
31 | */
32 | public interface IntervalHttpEvent extends IntervalEvent {
33 |
34 | /**
35 | * Returns the HTTP request.
36 | * @return request
37 | */
38 | @NonNull
39 | REQ getRequest();
40 |
41 | /**
42 | * Returns the HTTP response.
43 | * @return response
44 | */
45 | @Nullable
46 | RES getResponse();
47 |
48 | /**
49 | * Sets the given HTTP response on the event. Might be {@code null} when an exception
50 | * occurred and there's no response.
51 | * @param response a HTTP response
52 | * @return this
53 | */
54 | IntervalHttpEvent setResponse(RES response);
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/spring-observability-api/src/main/java/org/springframework/observability/event/Event.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2021-2021 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.event;
18 |
19 | /**
20 | * An Event represents that something happened. You must always name your events and
21 | * should provide a meaningful description if you can.
22 | *
23 | * @author Jonatan Ivanov
24 | * @since 1.0.0
25 | */
26 | public interface Event {
27 |
28 | /**
29 | * Low cardinality name of the event. May be used e.g. in a metric name.
30 | * @return the name of the event, the method mustn't return null. The method must
31 | * return values with low cardinality
32 | */
33 | String getLowCardinalityName();
34 |
35 | /**
36 | * Sets the low cardinality name of the event.
37 | * @param name low cardinality name to set
38 | */
39 | default void lowCardinalityName(String name) {
40 |
41 | }
42 |
43 | /**
44 | * Description of the event. May be used e.g. in a metric description.
45 | * @return the description of the event, the method shouldn't return null
46 | */
47 | default String getDescription() {
48 | return "";
49 | }
50 |
51 | /**
52 | * Sets the description of the event. May be used e.g. in a metric description.
53 | * @param description description to set
54 | */
55 | default void description(String description) {
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/docs/src/test/java/org/springframework/observability/internal/asciidoctor/ReadmeMainTests.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2020 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.internal.asciidoctor;
18 |
19 | import java.io.File;
20 | import java.io.IOException;
21 | import java.net.URISyntaxException;
22 | import java.nio.file.Files;
23 |
24 | import org.junit.jupiter.api.Test;
25 |
26 | import static org.assertj.core.api.BDDAssertions.then;
27 |
28 | class ReadmeMainTests {
29 |
30 | @Test
31 | void should_convert_input_with_include_of_external_sources_to_a_single_file()
32 | throws URISyntaxException, IOException {
33 | File inputFile = new File(ReadmeMainTests.class.getResource("/README.adoc").toURI());
34 | File outputFile = deleteIfExists(new File("target/output.adoc"));
35 |
36 | ReadmeMain.main(inputFile.getAbsolutePath(), outputFile.getAbsolutePath());
37 |
38 | then(new String(Files.readAllBytes(outputFile.toPath()))).doesNotContain("include:")
39 | .doesNotContain("Unresolved directive").contains("DO NOT EDIT THIS FILE. IT WAS GENERATED")
40 | .contains("Hello world!");
41 | then(new File("target/output.html")).as("Conversion to HTML must not happen").doesNotExist();
42 | }
43 |
44 | private File deleteIfExists(File outputFile) {
45 | if (outputFile.exists()) {
46 | outputFile.delete();
47 | }
48 | return outputFile;
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/spring-observability-api/src/main/java/org/springframework/observability/lang/NonNullApi.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2002-2017 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.lang;
18 |
19 | import java.lang.annotation.Documented;
20 | import java.lang.annotation.ElementType;
21 | import java.lang.annotation.Retention;
22 | import java.lang.annotation.RetentionPolicy;
23 | import java.lang.annotation.Target;
24 |
25 | import javax.annotation.Nonnull;
26 | import javax.annotation.meta.TypeQualifierDefault;
27 |
28 | /**
29 | * A common Spring annotation to declare that parameters and return values are to be
30 | * considered as non-nullable by default for a given package.
31 | *
32 | *
33 | * Leverages JSR-305 meta-annotations to indicate nullability in Java to common tools with
34 | * JSR-305 support and used by Kotlin to infer nullability of Spring API.
35 | *
36 | *
37 | * Should be used at package level in association with {@link Nullable} annotations at
38 | * parameter and return value level.
39 | *
40 | * @author Sebastien Deleuze
41 | * @author Juergen Hoeller
42 | * @since 1.0.0
43 | * @see NonNullFields
44 | * @see Nullable
45 | * @see NonNull
46 | */
47 | @Target(ElementType.PACKAGE)
48 | @Retention(RetentionPolicy.RUNTIME)
49 | @Documented
50 | @Nonnull
51 | @TypeQualifierDefault({ ElementType.METHOD, ElementType.PARAMETER })
52 | public @interface NonNullApi {
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/spring-observability-tracing/spring-observability-tracing-test-utils/src/main/java/org/springframework/observability/tracing/test/simple/SimpleHttpServerHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2021 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.tracing.test.simple;
18 |
19 | import org.springframework.observability.tracing.Span;
20 | import org.springframework.observability.tracing.http.HttpServerHandler;
21 | import org.springframework.observability.transport.http.HttpServerRequest;
22 | import org.springframework.observability.transport.http.HttpServerResponse;
23 |
24 | /**
25 | * A test http server handler implementation.
26 | *
27 | * @author Marcin Grzejszczak
28 | * @since 1.0.0
29 | */
30 | public class SimpleHttpServerHandler implements HttpServerHandler {
31 |
32 | private final SimpleTracer simpleTracer;
33 |
34 | /**
35 | * Was the handle receive method called?
36 | */
37 | public boolean receiveHandled;
38 |
39 | /**
40 | * @param simpleTracer simple tracer
41 | */
42 | public SimpleHttpServerHandler(SimpleTracer simpleTracer) {
43 | this.simpleTracer = simpleTracer;
44 | }
45 |
46 | @Override
47 | public Span handleReceive(HttpServerRequest request) {
48 | return this.simpleTracer.nextSpan().start();
49 | }
50 |
51 | @Override
52 | public void handleSend(HttpServerResponse response, Span span) {
53 | span.end();
54 | this.receiveHandled = true;
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/spring-observability-core/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 | spring-observability-core
7 | spring-observability-core
8 | jar
9 | Spring Observability Core Implementation
10 |
11 | org.springframework
12 | spring-observability-parent
13 | 1.0.0-SNAPSHOT
14 | ..
15 |
16 |
17 |
18 | org.springframework
19 | spring-observability-api
20 |
21 |
22 | org.springframework
23 | spring-observability-tracing-api
24 |
25 |
26 | io.micrometer
27 | micrometer-core
28 | provided
29 |
30 |
31 | org.springframework
32 | spring-observability-tracing-test-utils
33 | test
34 |
35 |
36 | org.junit.jupiter
37 | junit-jupiter-engine
38 | test
39 |
40 |
41 | org.mockito
42 | mockito-core
43 | test
44 |
45 |
46 | org.mockito
47 | mockito-junit-jupiter
48 | test
49 |
50 |
51 | org.assertj
52 | assertj-core
53 | test
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/spring-observability-api/src/main/java/org/springframework/observability/event/interval/IntervalHttpClientEvent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2021-2021 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.event.interval;
18 |
19 | import org.springframework.observability.lang.NonNull;
20 | import org.springframework.observability.transport.http.HttpClientRequest;
21 | import org.springframework.observability.transport.http.HttpClientResponse;
22 |
23 | /**
24 | * An IntervalEvent that represents an HTTP client event.
25 | *
26 | * @author Jonatan Ivanov
27 | * @author Marcin Grzejszczak
28 | * @since 1.0.0
29 | */
30 | public abstract class IntervalHttpClientEvent implements IntervalHttpEvent {
31 |
32 | private final HttpClientRequest request;
33 |
34 | private HttpClientResponse response;
35 |
36 | /**
37 | * Crates a new {@link IntervalHttpClientEvent}.
38 | * @param request http client request
39 | */
40 | public IntervalHttpClientEvent(HttpClientRequest request) {
41 | this.request = request;
42 | }
43 |
44 | @NonNull
45 | @Override
46 | public HttpClientRequest getRequest() {
47 | return this.request;
48 | }
49 |
50 | @Override
51 | public HttpClientResponse getResponse() {
52 | return this.response;
53 | }
54 |
55 | @Override
56 | public IntervalHttpClientEvent setResponse(HttpClientResponse response) {
57 | this.response = response;
58 | return this;
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/spring-observability-tracing/spring-observability-tracing-test-utils/src/main/java/org/springframework/observability/tracing/test/TestSpanHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2021 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.tracing.test;
18 |
19 | import java.util.List;
20 |
21 | import org.springframework.observability.tracing.Span;
22 | import org.springframework.observability.tracing.exporter.FinishedSpan;
23 |
24 | /**
25 | * A testing span handler that takes hold of finished spans.
26 | *
27 | * @author Marcin Grzejszczak
28 | * @since 1.0.0
29 | */
30 | public interface TestSpanHandler extends Iterable {
31 |
32 | /**
33 | * @return a list of {@link FinishedSpan}s
34 | */
35 | List reportedSpans();
36 |
37 | /**
38 | * @return a first local finished span
39 | */
40 | FinishedSpan takeLocalSpan();
41 |
42 | /**
43 | * Clears the reported finished spans.
44 | */
45 | void clear();
46 |
47 | /**
48 | * @param kind kind of a span to take
49 | * @return picks the first remote span of a given kind
50 | */
51 | FinishedSpan takeRemoteSpan(Span.Kind kind);
52 |
53 | /**
54 | * @param kind kind of a span to take
55 | * @return picks the first remote span of a given kind with an error
56 | */
57 | FinishedSpan takeRemoteSpanWithError(Span.Kind kind);
58 |
59 | /**
60 | * @param index index of the finished span
61 | * @return a {@link FinishedSpan} with a given index
62 | */
63 | FinishedSpan get(int index);
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/spring-observability-tracing/spring-observability-tracing-api/src/main/java/org/springframework/observability/tracing/http/HttpServerHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2021 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.tracing.http;
18 |
19 | import org.springframework.observability.tracing.Span;
20 | import org.springframework.observability.transport.http.HttpServerRequest;
21 | import org.springframework.observability.transport.http.HttpServerResponse;
22 |
23 | /**
24 | * This API is taken from OpenZipkin Brave.
25 | *
26 | * This standardizes a way to instrument http servers, particularly in a way that
27 | * encourages use of portable customizations via {@link HttpRequestParser} and
28 | * {@link HttpResponseParser}.
29 | *
30 | * @author OpenZipkin Brave Authors
31 | * @author Marcin Grzejszczak
32 | * @since 1.0.0
33 | */
34 | public interface HttpServerHandler {
35 |
36 | /**
37 | * Conditionally joins a span, or starts a new trace, depending on if a trace context
38 | * was extracted from the request. Tags are added before the span is started.
39 | * @param request HTTP request
40 | * @return server side span (either joined or a new trace)
41 | */
42 | Span handleReceive(HttpServerRequest request);
43 |
44 | /**
45 | * Finishes the server span after assigning it tags according to the response or
46 | * error.
47 | * @param response HTTP response
48 | * @param span server side span to end
49 | */
50 | void handleSend(HttpServerResponse response, Span span);
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/spring-observability-api/src/test/java/org/springframework/observability/event/listener/composite/CompositeContextTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2021-2021 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.event.listener.composite;
18 |
19 | import org.junit.jupiter.api.Test;
20 |
21 | import org.springframework.observability.event.listener.RecordingListener;
22 |
23 | import static org.assertj.core.api.Assertions.assertThat;
24 | import static org.mockito.Mockito.mock;
25 | import static org.mockito.Mockito.when;
26 |
27 | /**
28 | * @author Jonatan Ivanov
29 | */
30 | class CompositeContextTest {
31 |
32 | @Test
33 | void shouldGiveTheRightContextToTheRightListener() {
34 | RecordingListener listener1 = mock(RecordingListener.class);
35 | CompositeContext context1 = new CompositeContext();
36 | when(listener1.createContext()).thenReturn(context1);
37 |
38 | RecordingListener listener2 = mock(RecordingListener.class);
39 | String context2 = "context2";
40 | when(listener2.createContext()).thenReturn(context2);
41 |
42 | RecordingListener listener3 = mock(RecordingListener.class);
43 | Void context3 = null;
44 | when(listener3.createContext()).thenReturn(null);
45 |
46 | CompositeContext context = new CompositeContext(listener1, listener2, listener3);
47 | assertThat(context.byListener(listener1)).isSameAs(context1);
48 | assertThat(context.byListener(listener2)).isSameAs(context2);
49 | assertThat(context.byListener(listener3)).isSameAs(context3);
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/spring-observability-tracing/spring-observability-tracing-api/src/test/java/org/springframework/observability/tracing/internal/SpanNameUtilTests.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2021 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.tracing.internal;
18 |
19 | import org.assertj.core.api.BDDAssertions;
20 | import org.junit.jupiter.api.Test;
21 |
22 | public class SpanNameUtilTests {
23 |
24 | @Test
25 | void should_convert_a_name_in_hyphen_based_notation() throws Exception {
26 | BDDAssertions.then(SpanNameUtil.toLowerHyphen("aMethodNameInCamelCaseNotation"))
27 | .isEqualTo("a-method-name-in-camel-case-notation");
28 | }
29 |
30 | @Test
31 | void should_convert_a_class_name_in_hyphen_based_notation() throws Exception {
32 | BDDAssertions.then(SpanNameUtil.toLowerHyphen("MySuperClassName")).isEqualTo("my-super-class-name");
33 | }
34 |
35 | @Test
36 | void should_not_shorten_a_name_that_is_below_max_threshold() throws Exception {
37 | BDDAssertions.then(SpanNameUtil.shorten("someName")).isEqualTo("someName");
38 | }
39 |
40 | @Test
41 | void should_not_shorten_a_name_that_is_null() throws Exception {
42 | BDDAssertions.then(SpanNameUtil.shorten(null)).isNull();
43 | }
44 |
45 | @Test
46 | void should_shorten_a_name_that_is_above_max_threshold() throws Exception {
47 | StringBuilder sb = new StringBuilder();
48 | for (int i = 0; i < 60; i++) {
49 | sb.append("a");
50 | }
51 | BDDAssertions.then(SpanNameUtil.shorten(sb.toString()).length()).isEqualTo(SpanNameUtil.MAX_NAME_LENGTH);
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/spring-observability-tracing/spring-observability-tracing-brave/src/main/java/org/springframework/observability/tracing/brave/bridge/BraveHttpServerHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2021 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.tracing.brave.bridge;
18 |
19 | import org.springframework.observability.tracing.Span;
20 | import org.springframework.observability.tracing.http.HttpServerHandler;
21 | import org.springframework.observability.transport.http.HttpServerRequest;
22 | import org.springframework.observability.transport.http.HttpServerResponse;
23 |
24 | /**
25 | * Brave implementation of a {@link HttpServerHandler}.
26 | *
27 | * @author Marcin Grzejszczak
28 | * @since 1.0.0
29 | */
30 | public class BraveHttpServerHandler implements HttpServerHandler {
31 |
32 | final brave.http.HttpServerHandler delegate;
33 |
34 | /**
35 | * @param delegate Brave delegate
36 | */
37 | public BraveHttpServerHandler(
38 | brave.http.HttpServerHandler delegate) {
39 | this.delegate = delegate;
40 | }
41 |
42 | @Override
43 | public Span handleReceive(HttpServerRequest request) {
44 | return BraveSpan.fromBrave(this.delegate.handleReceive(BraveHttpServerRequest.toBrave(request)));
45 | }
46 |
47 | @Override
48 | public void handleSend(HttpServerResponse response, Span span) {
49 | this.delegate.handleSend(BraveHttpServerResponse.toBrave(response), BraveSpan.toBrave(span));
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/spring-observability-api/src/main/java/org/springframework/observability/event/tag/Tag.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2021-2021 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.event.tag;
18 |
19 | import org.springframework.observability.event.Recording;
20 |
21 | /**
22 | * Represents a key-vale pair in order to attach data to a {@link Recording}.
23 | * Implementations must make sure that none of the methods return null.
24 | *
25 | * @author Jonatan Ivanov
26 | * @since 1.0.0
27 | */
28 | public interface Tag extends Comparable {
29 |
30 | /**
31 | * Tag key.
32 | * @return tag key
33 | */
34 | String getKey();
35 |
36 | /**
37 | * Tag value.
38 | * @return tag value
39 | */
40 | String getValue();
41 |
42 | /**
43 | * Tag cardinality.
44 | * @return tag cardinality
45 | */
46 | default Cardinality getCardinality() {
47 | return Cardinality.LOW;
48 | }
49 |
50 | /**
51 | * Builds a tag.
52 | * @param key tag key
53 | * @param value tag value
54 | * @return tag
55 | */
56 | static Tag of(String key, String value) {
57 | return Tag.of(key, value, Cardinality.LOW); // TODO: or HIGH?
58 | }
59 |
60 | /**
61 | * Builds a tag.
62 | * @param key tag key
63 | * @param value tag value
64 | * @param cardinality tag cardinality
65 | * @return tag
66 | */
67 | static Tag of(String key, String value, Cardinality cardinality) {
68 | return new ImmutableTag(key, value, cardinality);
69 | }
70 |
71 | @Override
72 | default int compareTo(Tag o) {
73 | return getKey().compareTo(o.getKey());
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/spring-observability-tracing/spring-observability-tracing-api/src/main/java/org/springframework/observability/tracing/internal/SpanNameUtil.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2021 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.tracing.internal;
18 |
19 | import org.springframework.util.StringUtils;
20 |
21 | /**
22 | * Utility class that provides the name in hyphen based notation.
23 | *
24 | * @author Adrian Cole
25 | * @since 1.0.0
26 | */
27 | public final class SpanNameUtil {
28 |
29 | static final int MAX_NAME_LENGTH = 50;
30 |
31 | private SpanNameUtil() {
32 |
33 | }
34 |
35 | /**
36 | * Shortens the name of a span.
37 | * @param name name to shorten
38 | * @return shortened name
39 | */
40 | public static String shorten(String name) {
41 | if (!StringUtils.hasText(name)) {
42 | return name;
43 | }
44 | int maxLength = Math.min(name.length(), MAX_NAME_LENGTH);
45 | return name.substring(0, maxLength);
46 | }
47 |
48 | /**
49 | * Converts the name to a lower hyphen version.
50 | * @param name name to change
51 | * @return changed name
52 | */
53 | public static String toLowerHyphen(String name) {
54 | StringBuilder result = new StringBuilder();
55 | for (int i = 0; i < name.length(); i++) {
56 | char c = name.charAt(i);
57 | if (Character.isUpperCase(c)) {
58 | if (i != 0) {
59 | result.append('-');
60 | }
61 | result.append(Character.toLowerCase(c));
62 | }
63 | else {
64 | result.append(c);
65 | }
66 | }
67 | return SpanNameUtil.shorten(result.toString());
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/spring-observability-tracing/spring-observability-tracing-reporters/spring-observability-tracing-reporters-wavefront/src/main/java/org/springframework/observability/tracing/reporter/wavefront/WavefrontSleuthBraveSpanHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2020 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.tracing.reporter.wavefront;
18 |
19 | import java.io.Closeable;
20 |
21 | import brave.handler.MutableSpan;
22 | import brave.handler.SpanHandler;
23 | import brave.propagation.TraceContext;
24 |
25 | import org.springframework.observability.tracing.brave.bridge.BraveFinishedSpan;
26 | import org.springframework.observability.tracing.brave.bridge.BraveTraceContext;
27 |
28 | /**
29 | * A {@link SpanHandler} that sends spans to Wavefront.
30 | *
31 | * @author Marcin Grzejszczak
32 | * @since 1.0.0
33 | */
34 | public class WavefrontSleuthBraveSpanHandler extends SpanHandler implements Runnable, Closeable {
35 |
36 | private final WavefrontSleuthSpanHandler spanHandler;
37 |
38 | /**
39 | * @param spanHandler wavefront span handler
40 | */
41 | public WavefrontSleuthBraveSpanHandler(WavefrontSleuthSpanHandler spanHandler) {
42 | this.spanHandler = spanHandler;
43 | }
44 |
45 | @Override
46 | public boolean end(TraceContext context, MutableSpan span, Cause cause) {
47 | return spanHandler.end(BraveTraceContext.fromBrave(context), BraveFinishedSpan.fromBrave(span));
48 | }
49 |
50 | @Override
51 | public void close() {
52 | this.spanHandler.close();
53 | }
54 |
55 | @Override
56 | public void run() {
57 | this.spanHandler.run();
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/spring-observability-tracing/spring-observability-tracing-api/src/main/java/org/springframework/observability/tracing/docs/ImmutableAssertingSpanCustomizer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2021 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.tracing.docs;
18 |
19 | import java.util.Objects;
20 |
21 | import org.springframework.observability.tracing.SpanCustomizer;
22 |
23 | import static java.util.Objects.requireNonNull;
24 |
25 | class ImmutableAssertingSpanCustomizer implements AssertingSpanCustomizer {
26 |
27 | private final DocumentedSpan documentedSpan;
28 |
29 | private final SpanCustomizer delegate;
30 |
31 | ImmutableAssertingSpanCustomizer(DocumentedSpan documentedSpan, SpanCustomizer delegate) {
32 | requireNonNull(documentedSpan);
33 | requireNonNull(delegate);
34 | this.documentedSpan = documentedSpan;
35 | this.delegate = delegate;
36 | }
37 |
38 | @Override
39 | public boolean equals(Object o) {
40 | if (this == o) {
41 | return true;
42 | }
43 | if (o == null || getClass() != o.getClass()) {
44 | return false;
45 | }
46 | ImmutableAssertingSpanCustomizer that = (ImmutableAssertingSpanCustomizer) o;
47 | return Objects.equals(documentedSpan, that.documentedSpan) && Objects.equals(delegate, that.delegate);
48 | }
49 |
50 | @Override
51 | public int hashCode() {
52 | return Objects.hash(documentedSpan, delegate);
53 | }
54 |
55 | @Override
56 | public DocumentedSpan getDocumentedSpan() {
57 | return this.documentedSpan;
58 | }
59 |
60 | @Override
61 | public SpanCustomizer getDelegate() {
62 | return this.delegate;
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/spring-observability-tracing/spring-observability-tracing-test-utils/src/main/java/org/springframework/observability/tracing/test/simple/SimpleHttpClientHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2021 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.tracing.test.simple;
18 |
19 | import org.springframework.observability.tracing.Span;
20 | import org.springframework.observability.tracing.TraceContext;
21 | import org.springframework.observability.tracing.http.HttpClientHandler;
22 | import org.springframework.observability.transport.http.HttpClientRequest;
23 | import org.springframework.observability.transport.http.HttpClientResponse;
24 |
25 | /**
26 | * A test http client handler implementation.
27 | *
28 | * @author Marcin Grzejszczak
29 | * @since 1.0.0
30 | */
31 | public class SimpleHttpClientHandler implements HttpClientHandler {
32 |
33 | private final SimpleTracer simpleTracer;
34 |
35 | /**
36 | * Was the handle receive method called?
37 | */
38 | public boolean receiveHandled;
39 |
40 | /**
41 | * @param simpleTracer simple tracer
42 | */
43 | public SimpleHttpClientHandler(SimpleTracer simpleTracer) {
44 | this.simpleTracer = simpleTracer;
45 | }
46 |
47 | @Override
48 | public Span handleSend(HttpClientRequest request) {
49 | return this.simpleTracer.nextSpan().start();
50 | }
51 |
52 | @Override
53 | public Span handleSend(HttpClientRequest request, TraceContext parent) {
54 | return this.simpleTracer.nextSpan().start();
55 | }
56 |
57 | @Override
58 | public void handleReceive(HttpClientResponse response, Span span) {
59 | span.end();
60 | this.receiveHandled = true;
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/spring-observability-api/src/main/java/org/springframework/observability/lang/Nullable.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2002-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.lang;
18 |
19 | import java.lang.annotation.Documented;
20 | import java.lang.annotation.ElementType;
21 | import java.lang.annotation.Retention;
22 | import java.lang.annotation.RetentionPolicy;
23 | import java.lang.annotation.Target;
24 |
25 | import javax.annotation.Nonnull;
26 | import javax.annotation.meta.TypeQualifierNickname;
27 | import javax.annotation.meta.When;
28 |
29 | /**
30 | * A common Spring annotation to declare that annotated elements can be {@code null} under
31 | * some circumstance.
32 | *
33 | *
34 | * Leverages JSR-305 meta-annotations to indicate nullability in Java to common tools with
35 | * JSR-305 support and used by Kotlin to infer nullability of Spring API.
36 | *
37 | *
38 | * Should be used at parameter, return value, and field level. Methods override should
39 | * repeat parent {@code @Nullable} annotations unless they behave differently.
40 | *
41 | *
42 | * Can be used in association with {@code @NonNullApi} or {@code @NonNullFields} to
43 | * override the default non-nullable semantic to nullable.
44 | *
45 | * @author Sebastien Deleuze
46 | * @author Juergen Hoeller
47 | * @since 1.0.0
48 | * @see NonNullApi
49 | * @see NonNullFields
50 | * @see NonNull
51 | */
52 | @Target({ ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD })
53 | @Retention(RetentionPolicy.RUNTIME)
54 | @Documented
55 | @Nonnull(when = When.MAYBE)
56 | @TypeQualifierNickname
57 | public @interface Nullable {
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/spring-observability-api/src/main/java/org/springframework/observability/lang/NonNull.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2002-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.lang;
18 |
19 | import java.lang.annotation.Documented;
20 | import java.lang.annotation.ElementType;
21 | import java.lang.annotation.Retention;
22 | import java.lang.annotation.RetentionPolicy;
23 | import java.lang.annotation.Target;
24 |
25 | import javax.annotation.Nonnull;
26 | import javax.annotation.meta.TypeQualifierNickname;
27 |
28 | /**
29 | * A common Spring annotation to declare that annotated elements cannot be {@code null}.
30 | *
31 | *
32 | * Leverages JSR-305 meta-annotations to indicate nullability in Java to common tools with
33 | * JSR-305 support and used by Kotlin to infer nullability of Spring API.
34 | *
35 | *
36 | * Should be used at parameter, return value, and field level. Method overrides should
37 | * repeat parent {@code @NonNull} annotations unless they behave differently.
38 | *
39 | *
40 | * Use {@code @NonNullApi} (scope = parameters + return values) and/or
41 | * {@code @NonNullFields} (scope = fields) to set the default behavior to non-nullable in
42 | * order to avoid annotating your whole codebase with {@code @NonNull}.
43 | *
44 | * @author Sebastien Deleuze
45 | * @author Juergen Hoeller
46 | * @since 1.0.0
47 | * @see NonNullApi
48 | * @see NonNullFields
49 | * @see Nullable
50 | */
51 | @Target({ ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD })
52 | @Retention(RetentionPolicy.RUNTIME)
53 | @Documented
54 | @Nonnull
55 | @TypeQualifierNickname
56 | public @interface NonNull {
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/spring-observability-tracing/spring-observability-tracing-api/src/main/java/org/springframework/observability/tracing/annotation/NewSpan.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2021 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.tracing.annotation;
18 |
19 | import java.lang.annotation.ElementType;
20 | import java.lang.annotation.Inherited;
21 | import java.lang.annotation.Retention;
22 | import java.lang.annotation.RetentionPolicy;
23 | import java.lang.annotation.Target;
24 |
25 | import org.springframework.core.annotation.AliasFor;
26 |
27 | /**
28 | * Allows to create a new span around a public method. The new span will be either a child
29 | * of an existing span if a trace is already in progress or a new span will be created if
30 | * there was no previous trace.
31 | *
32 | * Method parameters can be annotated with {@link SpanTag}, which will end in adding the
33 | * parameter value as a tag value to the span. The tag key will be the value of the
34 | * {@code key} annotation from {@link SpanTag}.
35 | *
36 | *
37 | * @author Christian Schwerdtfeger
38 | * @since 1.0.0
39 | */
40 | @Retention(RetentionPolicy.RUNTIME)
41 | @Inherited
42 | @Target(ElementType.METHOD)
43 | public @interface NewSpan {
44 |
45 | /**
46 | * @return - The name of the span which will be created. Default is the annotated
47 | * method's name separated by hyphens.
48 | */
49 | @AliasFor("value")
50 | String name() default "";
51 |
52 | /**
53 | * @return - The name of the span which will be created. Default is the annotated
54 | * method's name separated by hyphens.
55 | */
56 | @AliasFor("name")
57 | String value() default "";
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/spring-observability-tracing/spring-observability-tracing-reporters/spring-observability-tracing-reporters-zipkin/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 | spring-observability-tracing-reporters-zipkin
7 | spring-observability-tracing-reporters-zipkin
8 | jar
9 | Spring Observability Tracing Reporters Zipkin
10 |
11 | org.springframework
12 | spring-observability-tracing-reporters-parent
13 | 1.0.0-SNAPSHOT
14 | ..
15 |
16 |
17 |
18 |
19 | org.springframework
20 | spring-observability-tracing-brave
21 | true
22 |
23 |
24 | io.zipkin.zipkin2
25 | zipkin
26 |
27 |
28 | io.zipkin.reporter2
29 | zipkin-reporter
30 |
31 |
32 | org.springframework
33 | spring-web
34 |
35 |
36 | org.springframework
37 | spring-jcl
38 |
39 |
40 |
41 | org.junit.jupiter
42 | junit-jupiter-engine
43 | test
44 |
45 |
46 | org.assertj
47 | assertj-core
48 | test
49 |
50 |
51 | com.squareup.okhttp3
52 | mockwebserver
53 | test
54 |
55 |
56 | com.tngtech.archunit
57 | archunit-junit5
58 | test
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/spring-observability-tracing/spring-observability-tracing-api/src/main/java/org/springframework/observability/tracing/docs/ImmutableAssertingSpanBuilder.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2021 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.tracing.docs;
18 |
19 | import java.util.Objects;
20 |
21 | import org.springframework.observability.tracing.Span;
22 |
23 | import static java.util.Objects.requireNonNull;
24 |
25 | class ImmutableAssertingSpanBuilder implements AssertingSpanBuilder {
26 |
27 | private final DocumentedSpan documentedSpan;
28 |
29 | private final Span.Builder delegate;
30 |
31 | ImmutableAssertingSpanBuilder(DocumentedSpan documentedSpan, Span.Builder delegate) {
32 | requireNonNull(documentedSpan);
33 | requireNonNull(delegate);
34 | this.documentedSpan = documentedSpan;
35 | this.delegate = delegate;
36 | }
37 |
38 | @Override
39 | public boolean equals(Object o) {
40 | if (this == o) {
41 | return true;
42 | }
43 | if (o == null || getClass() != o.getClass()) {
44 | return false;
45 | }
46 | ImmutableAssertingSpanBuilder that = (ImmutableAssertingSpanBuilder) o;
47 | return Objects.equals(documentedSpan, that.documentedSpan) && Objects.equals(delegate, that.delegate);
48 | }
49 |
50 | @Override
51 | public String toString() {
52 | return this.delegate.toString();
53 | }
54 |
55 | @Override
56 | public int hashCode() {
57 | return Objects.hash(documentedSpan, delegate);
58 | }
59 |
60 | @Override
61 | public DocumentedSpan getDocumentedSpan() {
62 | return this.documentedSpan;
63 | }
64 |
65 | @Override
66 | public Span.Builder getDelegate() {
67 | return this.delegate;
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/spring-observability-tracing/spring-observability-tracing-brave/src/main/java/org/springframework/observability/tracing/brave/bridge/BraveSpanCustomizer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2021 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.tracing.brave.bridge;
18 |
19 | import org.springframework.observability.tracing.SpanCustomizer;
20 | import org.springframework.observability.tracing.docs.AssertingSpanCustomizer;
21 |
22 | /**
23 | * Brave implementation of a {@link SpanCustomizer}.
24 | *
25 | * @author Marcin Grzejszczak
26 | * @since 1.0.0
27 | */
28 | public class BraveSpanCustomizer implements SpanCustomizer {
29 |
30 | private final brave.SpanCustomizer spanCustomizer;
31 |
32 | /**
33 | * @param spanCustomizer Brave delegate
34 | */
35 | public BraveSpanCustomizer(brave.SpanCustomizer spanCustomizer) {
36 | this.spanCustomizer = spanCustomizer;
37 | }
38 |
39 | static brave.SpanCustomizer toBrave(SpanCustomizer spanCustomizer) {
40 | return ((BraveSpanCustomizer) AssertingSpanCustomizer.unwrap(spanCustomizer)).spanCustomizer;
41 | }
42 |
43 | static SpanCustomizer fromBrave(brave.SpanCustomizer spanCustomizer) {
44 | return new BraveSpanCustomizer(spanCustomizer);
45 | }
46 |
47 | @Override
48 | public SpanCustomizer name(String name) {
49 | return new BraveSpanCustomizer(this.spanCustomizer.name(name));
50 | }
51 |
52 | @Override
53 | public SpanCustomizer tag(String key, String value) {
54 | return new BraveSpanCustomizer(this.spanCustomizer.tag(key, value));
55 | }
56 |
57 | @Override
58 | public SpanCustomizer event(String value) {
59 | return new BraveSpanCustomizer(this.spanCustomizer.annotate(value));
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/spring-observability-tracing/spring-observability-tracing-api/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 | spring-observability-tracing-api
7 | spring-observability-tracing-api
8 | jar
9 | Spring Observability Tracing API
10 |
11 | org.springframework
12 | spring-observability-tracing-parent
13 | 1.0.0-SNAPSHOT
14 | ..
15 |
16 |
17 |
18 |
19 | org.springframework
20 | spring-observability-api
21 |
22 |
23 | org.springframework
24 | spring-core
25 |
26 |
27 | org.springframework
28 | spring-jcl
29 |
30 |
31 | aopalliance
32 | aopalliance
33 |
34 |
35 |
36 | org.junit.jupiter
37 | junit-jupiter-engine
38 | test
39 |
40 |
41 | org.mockito
42 | mockito-core
43 | test
44 |
45 |
46 | org.mockito
47 | mockito-junit-jupiter
48 | test
49 |
50 |
51 | org.assertj
52 | assertj-core
53 | test
54 |
55 |
56 | org.awaitility
57 | awaitility
58 | test
59 |
60 |
61 | com.tngtech.archunit
62 | archunit-junit5
63 | test
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/spring-observability-api/src/main/java/org/springframework/observability/time/Clock.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2021-2021 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.time;
18 |
19 | import java.time.Instant;
20 | import java.util.concurrent.TimeUnit;
21 |
22 | /**
23 | * Clock abstraction to guide users and simplify testing.
24 | *
25 | * Mostly from:
26 | * https://github.com/micrometer-metrics/micrometer/blob/main/micrometer-core/src/main/java/io/micrometer/core/instrument/Clock.java
27 | *
28 | * @author Jon Schneider
29 | * @author Jonatan Ivanov
30 | * @since 1.0.0
31 | */
32 | public interface Clock {
33 |
34 | /**
35 | * Default clock implementation using standard JDK components.
36 | */
37 | Clock SYSTEM = new Clock() {
38 | @Override
39 | public long wallTime() {
40 | Instant instant = java.time.Clock.systemUTC().instant();
41 | return TimeUnit.SECONDS.toNanos(instant.getEpochSecond()) + instant.getNano();
42 | }
43 |
44 | @Override
45 | public long monotonicTime() {
46 | return System.nanoTime();
47 | }
48 | };
49 |
50 | /**
51 | * Current wall time (system time) in nanoseconds since the epoch. Should not be used
52 | * to determine durations.
53 | * @return Wall time in nanoseconds
54 | */
55 | long wallTime();
56 |
57 | /**
58 | * Current time from a monotonic clock source. The value is only meaningful when
59 | * compared with another value to determine the elapsed time for an operation. The
60 | * difference between two samples has a unit of nanoseconds. The returned value is
61 | * typically equivalent to System.nanoTime.
62 | * @return Monotonic time in nanoseconds
63 | */
64 | long monotonicTime();
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/spring-observability-tracing/spring-observability-tracing-brave/src/test/java/org/springframework/observability/tracing/brave/bridge/BraveTraceContextBuilderTests.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2021 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.tracing.brave.bridge;
18 |
19 | import org.junit.jupiter.api.Test;
20 |
21 | import org.springframework.observability.tracing.TraceContext;
22 |
23 | import static org.assertj.core.api.BDDAssertions.then;
24 |
25 | class BraveTraceContextBuilderTests {
26 |
27 | @Test
28 | void should_set_trace_context_for_64_bit() {
29 | BraveTraceContextBuilder builder = new BraveTraceContextBuilder();
30 |
31 | TraceContext traceContext = builder.parentId("7c6239a5ad0a4287").spanId("caff89f7f0f229dd")
32 | .traceId("596e1787feb11040").sampled(true).build();
33 |
34 | then(traceContext.parentId()).isEqualTo("7c6239a5ad0a4287");
35 | then(traceContext.spanId()).isEqualTo("caff89f7f0f229dd");
36 | then(traceContext.traceId()).isEqualTo("596e1787feb11040");
37 | then(traceContext.sampled()).isTrue();
38 | }
39 |
40 | @Test
41 | void should_set_trace_context_for_128_bit() {
42 | BraveTraceContextBuilder builder = new BraveTraceContextBuilder();
43 |
44 | TraceContext traceContext = builder.parentId("00000000000000007c6239a5ad0a4287")
45 | .spanId("0000000000000000caff89f7f0f229dd").traceId("596e1787feb11040caff89f7f0f229dd").sampled(true)
46 | .build();
47 |
48 | then(traceContext.parentId()).isEqualTo("7c6239a5ad0a4287");
49 | then(traceContext.spanId()).isEqualTo("caff89f7f0f229dd");
50 | then(traceContext.traceId()).isEqualTo("596e1787feb11040caff89f7f0f229dd");
51 | then(traceContext.sampled()).isTrue();
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/spring-observability-api/src/main/java/org/springframework/observability/event/interval/IntervalHttpServerEvent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2021-2021 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.event.interval;
18 |
19 | import org.springframework.observability.lang.NonNull;
20 | import org.springframework.observability.transport.http.HttpServerRequest;
21 | import org.springframework.observability.transport.http.HttpServerResponse;
22 |
23 | /**
24 | * An IntervalEvent that represents an HTTP server event.
25 | *
26 | * @author Marcin Grzejszczak
27 | * @since 1.0.0
28 | */
29 | public abstract class IntervalHttpServerEvent implements IntervalHttpEvent {
30 |
31 | private final HttpServerRequest request;
32 |
33 | private HttpServerResponse response;
34 |
35 | private Object handler;
36 |
37 | /**
38 | * Creates a new {@link IntervalHttpServerEvent}.
39 | * @param request http server request
40 | */
41 | public IntervalHttpServerEvent(HttpServerRequest request) {
42 | this.request = request;
43 | }
44 |
45 | @NonNull
46 | @Override
47 | public HttpServerRequest getRequest() {
48 | return this.request;
49 | }
50 |
51 | /**
52 | * Sets a request handler.
53 | * @param handler handler for this request
54 | * @return this
55 | */
56 | public IntervalHttpServerEvent setHandler(Object handler) {
57 | this.handler = handler;
58 | return this;
59 | }
60 |
61 | @Override
62 | public HttpServerResponse getResponse() {
63 | return this.response;
64 | }
65 |
66 | @Override
67 | public IntervalHttpServerEvent setResponse(HttpServerResponse response) {
68 | this.response = response;
69 | return this;
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/spring-observability-tracing/spring-observability-tracing-api/src/main/java/org/springframework/observability/tracing/ScopedSpan.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2021 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.tracing;
18 |
19 | /**
20 | * Represents the "current span" until {@link ScopedSpan#end()} ()} is called.
21 | *
22 | * @author OpenZipkin Brave Authors
23 | * @author Marcin Grzejszczak
24 | * @since 1.0.0
25 | */
26 | public interface ScopedSpan {
27 |
28 | /**
29 | * @return {@code true} when no recording is done and nothing is reported to an
30 | * external system. However, this span should still be injected into outgoing
31 | * requests. Use this flag to avoid performing expensive computation.
32 | */
33 | boolean isNoop();
34 |
35 | /**
36 | * @return {@link TraceContext} corresponding to this span.
37 | */
38 | TraceContext context();
39 |
40 | /**
41 | * Sets a name on this span.
42 | * @param name name to set on the span
43 | * @return this span
44 | */
45 | ScopedSpan name(String name);
46 |
47 | /**
48 | * Sets a tag on this span.
49 | * @param key tag key
50 | * @param value tag value
51 | * @return this span
52 | */
53 | ScopedSpan tag(String key, String value);
54 |
55 | /**
56 | * Sets an event on this span.
57 | * @param value event name to set on the span
58 | * @return this span
59 | */
60 | ScopedSpan event(String value);
61 |
62 | /**
63 | * Records an exception for this span.
64 | * @param throwable to record
65 | * @return this span
66 | */
67 | ScopedSpan error(Throwable throwable);
68 |
69 | /**
70 | * Ends the span. The span gets stopped and recorded if not noop.
71 | */
72 | void end();
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/spring-observability-tracing/spring-observability-tracing-api/src/test/java/org/springframework/observability/tracing/ThreadLocalSpanTests.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2021 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.tracing;
18 |
19 | import org.junit.jupiter.api.Test;
20 | import org.mockito.BDDMockito;
21 |
22 | import static org.assertj.core.api.BDDAssertions.then;
23 |
24 | class ThreadLocalSpanTests {
25 |
26 | @Test
27 | void should_set_and_retrieve_values_from_thread_local() {
28 | // given
29 | ThreadLocalSpan span = new ThreadLocalSpan(new WithMockSpanTracer());
30 | Span firstSpan = BDDMockito.mock(Span.class);
31 | Span secondSpan = BDDMockito.mock(Span.class);
32 |
33 | // when
34 | span.set(firstSpan);
35 |
36 | // then
37 | SpanAndScope spanAndScope = span.get();
38 | then(spanAndScope).isNotNull();
39 | then(spanAndScope.getSpan()).isSameAs(firstSpan);
40 |
41 | // when
42 | span.set(secondSpan);
43 |
44 | // then
45 | spanAndScope = span.get();
46 | then(spanAndScope).isNotNull();
47 | then(spanAndScope.getSpan()).isSameAs(secondSpan);
48 |
49 | // when
50 | span.remove();
51 |
52 | // then
53 | spanAndScope = span.get();
54 | then(spanAndScope).isNotNull();
55 | then(spanAndScope.getSpan()).isSameAs(firstSpan);
56 |
57 | // when
58 | span.remove();
59 | spanAndScope = span.get();
60 | then(spanAndScope).isNull();
61 | }
62 |
63 | @Test
64 | void should_create_a_new_thread_local_span() {
65 | // given
66 | ThreadLocalSpan span = new ThreadLocalSpan(new WithMockSpanTracer());
67 |
68 | // when
69 | Span firstSpan = span.nextSpan();
70 |
71 | // then
72 | then(span.get().getSpan()).isSameAs(firstSpan);
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/spring-observability-tracing/spring-observability-tracing-brave/src/main/java/org/springframework/observability/tracing/brave/bridge/BraveBaggageInScope.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2021 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.tracing.brave.bridge;
18 |
19 | import brave.baggage.BaggageField;
20 |
21 | import org.springframework.observability.tracing.BaggageInScope;
22 | import org.springframework.observability.tracing.TraceContext;
23 |
24 | /**
25 | * Brave implementation of a {@link BaggageInScope}.
26 | *
27 | * @author Marcin Grzejszczak
28 | * @since 1.0.0
29 | */
30 | class BraveBaggageInScope implements BaggageInScope {
31 |
32 | private final BaggageField delegate;
33 |
34 | BraveBaggageInScope(BaggageField delegate) {
35 | this.delegate = delegate;
36 | }
37 |
38 | @Override
39 | public String name() {
40 | return this.delegate.name();
41 | }
42 |
43 | @Override
44 | public String get() {
45 | return this.delegate.getValue();
46 | }
47 |
48 | @Override
49 | public String get(TraceContext traceContext) {
50 | return this.delegate.getValue(BraveTraceContext.toBrave(traceContext));
51 | }
52 |
53 | @Override
54 | public BraveBaggageInScope set(String value) {
55 | this.delegate.updateValue(value);
56 | return this;
57 | }
58 |
59 | BaggageField unwrap() {
60 | return this.delegate;
61 | }
62 |
63 | @Override
64 | public BraveBaggageInScope set(TraceContext traceContext, String value) {
65 | this.delegate.updateValue(BraveTraceContext.toBrave(traceContext), value);
66 | return this;
67 | }
68 |
69 | @Override
70 | public BaggageInScope makeCurrent() {
71 | return this;
72 | }
73 |
74 | @Override
75 | public void close() {
76 |
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/spring-observability-api/src/main/java/org/springframework/observability/transport/http/HttpResponse.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2021 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.transport.http;
18 |
19 | import org.springframework.observability.lang.Nullable;
20 |
21 | /**
22 | * This API is taken from OpenZipkin Brave.
23 | *
24 | * Abstract response type used for parsing and sampling. Represents an HTTP response.
25 | *
26 | * @author OpenZipkin Brave Authors
27 | * @author Marcin Grzejszczak
28 | * @since 1.0.0
29 | */
30 | public interface HttpResponse extends Response {
31 |
32 | @Nullable
33 | @Override
34 | default HttpRequest request() {
35 | return null;
36 | }
37 |
38 | /**
39 | * @return HTTP method
40 | */
41 | @Nullable
42 | default String method() {
43 | HttpRequest request = request();
44 | return request != null ? request.method() : null;
45 | }
46 |
47 | /**
48 | * Returns an expression such as "/items/:itemId" representing an application
49 | * endpoint, conventionally associated with the tag key "http.route". If no route
50 | * matched, "" (empty string) is returned. {@code null} indicates this instrumentation
51 | * doesn't understand http routes.
52 | * @return HTTP route or {@code null} if not set.
53 | */
54 | @Nullable
55 | default String route() {
56 | HttpRequest request = request();
57 | return request != null ? request.route() : null;
58 | }
59 |
60 | /**
61 | * @return The HTTP status code or zero if unreadable.
62 | */
63 | int statusCode();
64 |
65 | /**
66 | * @param header header name
67 | * @return HTTP header or {@code null} if not set.
68 | */
69 | default String header(String header) {
70 | return null;
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/spring-observability-tracing/spring-observability-tracing-brave/src/main/java/org/springframework/observability/tracing/brave/bridge/BraveHttpRequestParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2021 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.tracing.brave.bridge;
18 |
19 | import org.springframework.observability.tracing.SpanCustomizer;
20 | import org.springframework.observability.tracing.TraceContext;
21 | import org.springframework.observability.tracing.http.HttpRequestParser;
22 | import org.springframework.observability.transport.http.HttpRequest;
23 |
24 | /**
25 | * Brave implementation of a {@link HttpRequestParser}.
26 | *
27 | * @author Marcin Grzejszczak
28 | * @since 1.0.0
29 | */
30 | public class BraveHttpRequestParser implements HttpRequestParser {
31 |
32 | final brave.http.HttpRequestParser delegate;
33 |
34 | /**
35 | * @param delegate Brave delegate
36 | */
37 | public BraveHttpRequestParser(brave.http.HttpRequestParser delegate) {
38 | this.delegate = delegate;
39 | }
40 |
41 | /**
42 | * @param parser Sleuth's API parser
43 | * @return Brave version of the parser
44 | */
45 | public static brave.http.HttpRequestParser toBrave(HttpRequestParser parser) {
46 | if (parser instanceof BraveHttpRequestParser) {
47 | return ((BraveHttpRequestParser) parser).delegate;
48 | }
49 | return (request, context, span) -> parser.parse(BraveHttpRequest.fromBrave(request),
50 | BraveTraceContext.fromBrave(context), BraveSpanCustomizer.fromBrave(span));
51 | }
52 |
53 | @Override
54 | public void parse(HttpRequest request, TraceContext context, SpanCustomizer span) {
55 | this.delegate.parse(BraveHttpRequest.toBrave(request), BraveTraceContext.toBrave(context),
56 | BraveSpanCustomizer.toBrave(span));
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/spring-observability-tracing/spring-observability-tracing-brave/src/main/java/org/springframework/observability/tracing/brave/bridge/BraveHttpResponseParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2021 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.tracing.brave.bridge;
18 |
19 | import org.springframework.observability.tracing.SpanCustomizer;
20 | import org.springframework.observability.tracing.TraceContext;
21 | import org.springframework.observability.tracing.http.HttpResponseParser;
22 | import org.springframework.observability.transport.http.HttpResponse;
23 |
24 | /**
25 | * Brave implementation of a {@link HttpResponseParser}.
26 | *
27 | * @author Marcin Grzejszczak
28 | * @since 1.0.0
29 | */
30 | public class BraveHttpResponseParser implements HttpResponseParser {
31 |
32 | final brave.http.HttpResponseParser delegate;
33 |
34 | /**
35 | * @param delegate Brave delegate
36 | */
37 | public BraveHttpResponseParser(brave.http.HttpResponseParser delegate) {
38 | this.delegate = delegate;
39 | }
40 |
41 | /**
42 | * @param parser Sleuth's API parser
43 | * @return Brave's parser
44 | */
45 | public static brave.http.HttpResponseParser toBrave(HttpResponseParser parser) {
46 | if (parser instanceof BraveHttpResponseParser) {
47 | return ((BraveHttpResponseParser) parser).delegate;
48 | }
49 | return (response, context, span) -> parser.parse(BraveHttpResponse.fromBrave(response),
50 | BraveTraceContext.fromBrave(context), BraveSpanCustomizer.fromBrave(span));
51 | }
52 |
53 | @Override
54 | public void parse(HttpResponse response, TraceContext context, SpanCustomizer span) {
55 | this.delegate.parse(BraveHttpResponse.toBrave(response), BraveTraceContext.toBrave(context),
56 | BraveSpanCustomizer.toBrave(span));
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/spring-observability-tracing/spring-observability-tracing-brave/src/main/java/org/springframework/observability/tracing/brave/bridge/BraveBaggageManager.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2021 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.tracing.brave.bridge;
18 |
19 | import java.io.Closeable;
20 | import java.util.Map;
21 | import java.util.concurrent.ConcurrentHashMap;
22 |
23 | import brave.baggage.BaggageField;
24 |
25 | import org.springframework.observability.tracing.BaggageInScope;
26 | import org.springframework.observability.tracing.BaggageManager;
27 | import org.springframework.observability.tracing.TraceContext;
28 |
29 | /**
30 | * Brave implementation of a {@link BaggageManager}.
31 | *
32 | * @author Marcin Grzejszczak
33 | * @since 1.0.0
34 | */
35 | public class BraveBaggageManager implements Closeable, BaggageManager {
36 |
37 | private static final Map CACHE = new ConcurrentHashMap<>();
38 |
39 | public Map getAllBaggage() {
40 | return BaggageField.getAllValues();
41 | }
42 |
43 | @Override
44 | public BaggageInScope getBaggage(String name) {
45 | return createBaggage(name);
46 | }
47 |
48 | @Override
49 | public BaggageInScope getBaggage(TraceContext traceContext, String name) {
50 | return new BraveBaggageInScope(BaggageField.getByName(BraveTraceContext.toBrave(traceContext), name));
51 | }
52 |
53 | @Override
54 | public BaggageInScope createBaggage(String name) {
55 | return CACHE.computeIfAbsent(name, s -> new BraveBaggageInScope(BaggageField.create(s)));
56 | }
57 |
58 | @Override
59 | public BaggageInScope createBaggage(String name, String value) {
60 | return createBaggage(name).set(value);
61 | }
62 |
63 | @Override
64 | public void close() {
65 | CACHE.clear();
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/spring-observability-api/src/main/java/org/springframework/observability/transport/http/HttpRequest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2021 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.transport.http;
18 |
19 | import org.springframework.observability.lang.Nullable;
20 |
21 | /**
22 | * This API is taken from OpenZipkin Brave.
23 | *
24 | * Abstract response type used for parsing and sampling. Represents an HTTP request.
25 | *
26 | * @author OpenZipkin Brave Authors
27 | * @author Marcin Grzejszczak
28 | * @since 1.0.0
29 | */
30 | public interface HttpRequest extends Request {
31 |
32 | /**
33 | * @return HTTP method.
34 | */
35 | String method();
36 |
37 | /**
38 | * @return HTTP path or {@code null} if not set.
39 | */
40 | @Nullable
41 | String path();
42 |
43 | /**
44 | * Returns an expression such as "/items/:itemId" representing an application
45 | * endpoint, conventionally associated with the tag key "http.route". If no route
46 | * matched, "" (empty string) is returned. {@code null} indicates this instrumentation
47 | * doesn't understand http routes.
48 | * @return HTTP route or {@code null} if not set.
49 | */
50 | @Nullable
51 | default String route() {
52 | return null;
53 | }
54 |
55 | /**
56 | * @return HTTP URL or {@code null} if not set.
57 | */
58 | @Nullable
59 | String url();
60 |
61 | /**
62 | * @param name header name
63 | * @return HTTP header or {@code null} if not set.
64 | */
65 | @Nullable
66 | String header(String name);
67 |
68 | /**
69 | * @return remote IP for the given connection.
70 | */
71 | default String remoteIp() {
72 | return null;
73 | }
74 |
75 | /**
76 | * @return remote port for the given connection.
77 | */
78 | default int remotePort() {
79 | return 0;
80 | }
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/spring-observability-tracing/spring-observability-tracing-reporters/spring-observability-tracing-reporters-wavefront/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 | spring-observability-tracing-reporters-wavefront
7 | spring-observability-tracing-reporters-wavefront
8 | jar
9 | Spring Observability Tracing Reporters Wavefront
10 |
11 | org.springframework
12 | spring-observability-tracing-reporters-parent
13 | 1.0.0-SNAPSHOT
14 | ..
15 |
16 |
17 |
18 |
19 | org.springframework
20 | spring-observability-tracing-brave
21 | true
22 |
23 |
24 | io.micrometer
25 | micrometer-core
26 |
27 |
28 | org.springframework
29 | spring-core
30 |
31 |
32 | com.wavefront
33 | wavefront-runtime-sdk-jvm
34 |
35 |
36 | com.wavefront
37 | wavefront-sdk-java
38 |
39 |
40 | org.springframework
41 | spring-jcl
42 |
43 |
44 |
45 | org.junit.jupiter
46 | junit-jupiter-engine
47 | test
48 |
49 |
50 | org.assertj
51 | assertj-core
52 | test
53 |
54 |
55 | org.mockito
56 | mockito-core
57 | test
58 |
59 |
60 | com.tngtech.archunit
61 | archunit-junit5
62 | test
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/spring-observability-tracing/spring-observability-tracing-brave/src/main/java/org/springframework/observability/tracing/brave/bridge/BravePropagator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2021 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.observability.tracing.brave.bridge;
18 |
19 | import java.util.List;
20 |
21 | import brave.Tracing;
22 | import brave.propagation.SamplingFlags;
23 | import brave.propagation.TraceContextOrSamplingFlags;
24 |
25 | import org.springframework.observability.tracing.Span;
26 | import org.springframework.observability.tracing.TraceContext;
27 | import org.springframework.observability.tracing.propagation.Propagator;
28 |
29 | /**
30 | * Brave implementation of a {@link Propagator}.
31 | *
32 | * @author Marcin Grzejszczak
33 | * @since 1.0.0
34 | */
35 | public class BravePropagator implements Propagator {
36 |
37 | private final Tracing tracing;
38 |
39 | /**
40 | * @param tracing Brave tracing
41 | */
42 | public BravePropagator(Tracing tracing) {
43 | this.tracing = tracing;
44 | }
45 |
46 | @Override
47 | public List fields() {
48 | return this.tracing.propagation().keys();
49 | }
50 |
51 | @Override
52 | public void inject(TraceContext traceContext, C carrier, Setter setter) {
53 | this.tracing.propagation().injector(setter::set).inject(BraveTraceContext.toBrave(traceContext), carrier);
54 | }
55 |
56 | @Override
57 | public Span.Builder extract(C carrier, Getter getter) {
58 | TraceContextOrSamplingFlags extract = this.tracing.propagation().extractor(getter::get).extract(carrier);
59 | if (extract.samplingFlags() == SamplingFlags.EMPTY) {
60 | this.tracing.tracer().nextSpan();
61 | return new BraveSpanBuilder(this.tracing.tracer());
62 | }
63 | return BraveSpanBuilder.toBuilder(this.tracing.tracer(), extract);
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------