-
Notifications
You must be signed in to change notification settings - Fork 127
feat: Add OpenTelemetry migration recipes for Spring Boot applications #893
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 2 commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
93b330a
feat(opentelemetry): add opentelemetry support
sandy2008 6cc6dac
Merge branch 'openrewrite:main' into main
sandy2008 223c623
Merge branch 'main' into main
timtebeek f85a8dc
parserClasspath entries were not used at all
timtebeek fe4f1f5
feat(opentelemetry): simplify migration recipes for Sleuth and OpenTr…
sandy2008 064e24d
Merge branch 'main' into main
timtebeek 91c93ce
Regenerate recipes.csv
timtebeek 134b836
chore(): Replaces Java migration recipes with YAML equivalents
sandy2008 4c11784
Inline two recipes and delete package-info.java
timtebeek f954a0a
Change package to spring.opentelemetry
timtebeek 9b23386
Restore `ReplaceRestTemplateBuilderMethods` in recipes.csv
timtebeek 960713e
Minimize modifiers in tests
timtebeek 400c718
Remove duplicate entries from recipes.csv
timtebeek 4f2e19d
Use wildcard
timtebeek c793351
Merge branch 'main' into main
timtebeek 228db0e
Inline small recipes only used once
timtebeek cf22ecf
Remove obsolete `AddOpenTelemetryOtlpExporter`
timtebeek f32cdb2
Remove unused `UpgradeOpenTelemetry_2_23`
timtebeek b191d17
Restructure recipes top down
timtebeek c389446
Fix test references
timtebeek 259f3b2
Merge branch 'main' into main
timtebeek 317c72e
Add versions to added dependencies
timtebeek File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
83 changes: 83 additions & 0 deletions
83
src/main/java/org/openrewrite/java/spring/opentelemetry/MigrateDatadogToOpenTelemetry.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| /* | ||
| * Copyright 2025 the original author or authors. | ||
| * <p> | ||
| * Licensed under the Moderne Source Available License (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * <p> | ||
| * https://docs.moderne.io/licensing/moderne-source-available-license | ||
| * <p> | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| package org.openrewrite.java.spring.opentelemetry; | ||
|
|
||
| import org.openrewrite.ExecutionContext; | ||
| import org.openrewrite.Recipe; | ||
| import org.openrewrite.TreeVisitor; | ||
| import org.openrewrite.java.ChangeType; | ||
|
|
||
| import java.util.Arrays; | ||
| import java.util.List; | ||
|
|
||
| /** | ||
| * Migrates Datadog tracing API types to OpenTelemetry API equivalents. | ||
| * <p> | ||
| * This recipe handles the migration of: | ||
| * <ul> | ||
| * <li>Datadog Tracer → OpenTelemetry Tracer</li> | ||
| * <li>Datadog Span → OpenTelemetry Span</li> | ||
| * <li>Datadog SpanContext → OpenTelemetry SpanContext</li> | ||
| * <li>Datadog Scope → OpenTelemetry Scope</li> | ||
| * <li>Datadog @Trace annotation → OpenTelemetry @WithSpan</li> | ||
| * </ul> | ||
| */ | ||
| public class MigrateDatadogToOpenTelemetry extends Recipe { | ||
|
|
||
| @Override | ||
| public String getDisplayName() { | ||
| return "Migrate Datadog tracing to OpenTelemetry"; | ||
| } | ||
|
|
||
| @Override | ||
| public String getDescription() { | ||
| return "Migrates Datadog tracing API types and annotations to OpenTelemetry API equivalents. " + | ||
| "This includes migrating the Datadog Tracer, Span, SpanContext, Scope, and @Trace annotation."; | ||
| } | ||
|
|
||
| @Override | ||
| public List<Recipe> getRecipeList() { | ||
| return Arrays.asList( | ||
| // Datadog core tracing types to OpenTelemetry | ||
| new ChangeType("datadog.trace.api.Tracer", "io.opentelemetry.api.trace.Tracer", true), | ||
| new ChangeType("io.opentracing.Tracer", "io.opentelemetry.api.trace.Tracer", true), | ||
| new ChangeType("datadog.trace.api.DDTracer", "io.opentelemetry.api.trace.Tracer", true), | ||
|
|
||
| // Span types | ||
| new ChangeType("datadog.trace.api.Span", "io.opentelemetry.api.trace.Span", true), | ||
| new ChangeType("io.opentracing.Span", "io.opentelemetry.api.trace.Span", true), | ||
| new ChangeType("datadog.trace.api.DDSpan", "io.opentelemetry.api.trace.Span", true), | ||
|
|
||
| // SpanContext | ||
| new ChangeType("datadog.trace.api.SpanContext", "io.opentelemetry.api.trace.SpanContext", true), | ||
| new ChangeType("io.opentracing.SpanContext", "io.opentelemetry.api.trace.SpanContext", true), | ||
| new ChangeType("datadog.trace.api.DDSpanContext", "io.opentelemetry.api.trace.SpanContext", true), | ||
|
|
||
| // Scope | ||
| new ChangeType("datadog.trace.context.TraceScope", "io.opentelemetry.context.Scope", true), | ||
| new ChangeType("io.opentracing.Scope", "io.opentelemetry.context.Scope", true), | ||
|
|
||
| // @Trace annotation to @WithSpan | ||
| new ChangeType("datadog.trace.api.Trace", "io.opentelemetry.instrumentation.annotations.WithSpan", true) | ||
| ); | ||
| } | ||
|
|
||
| @Override | ||
| public TreeVisitor<?, ExecutionContext> getVisitor() { | ||
| // Use the composite recipe approach via getRecipeList() | ||
| return TreeVisitor.noop(); | ||
| } | ||
| } | ||
80 changes: 80 additions & 0 deletions
80
...ain/java/org/openrewrite/java/spring/opentelemetry/MigrateOpenTracingToOpenTelemetry.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| /* | ||
| * Copyright 2025 the original author or authors. | ||
| * <p> | ||
| * Licensed under the Moderne Source Available License (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * <p> | ||
| * https://docs.moderne.io/licensing/moderne-source-available-license | ||
| * <p> | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| package org.openrewrite.java.spring.opentelemetry; | ||
|
|
||
| import org.openrewrite.ExecutionContext; | ||
| import org.openrewrite.Preconditions; | ||
| import org.openrewrite.Recipe; | ||
| import org.openrewrite.TreeVisitor; | ||
| import org.openrewrite.java.ChangeType; | ||
| import org.openrewrite.java.JavaIsoVisitor; | ||
| import org.openrewrite.java.search.UsesType; | ||
|
|
||
| import java.util.Arrays; | ||
| import java.util.List; | ||
|
|
||
| /** | ||
| * Migrates OpenTracing API to OpenTelemetry API. | ||
| * <p> | ||
| * OpenTracing has been superseded by OpenTelemetry and is no longer actively maintained. | ||
| * This recipe handles the migration of core OpenTracing types to their OpenTelemetry equivalents. | ||
| * | ||
| * @see <a href="https://opentelemetry.io/docs/migration/opentracing/">OpenTracing Migration Guide</a> | ||
| */ | ||
| public class MigrateOpenTracingToOpenTelemetry extends Recipe { | ||
sandy2008 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| private static final String OPENTRACING_PACKAGE = "io.opentracing"; | ||
| private static final String OTEL_API_PACKAGE = "io.opentelemetry.api"; | ||
| private static final String OTEL_CONTEXT_PACKAGE = "io.opentelemetry.context"; | ||
|
|
||
| @Override | ||
| public String getDisplayName() { | ||
| return "Migrate OpenTracing API to OpenTelemetry API"; | ||
| } | ||
|
|
||
| @Override | ||
| public String getDescription() { | ||
| return "Migrate OpenTracing API to OpenTelemetry API. " + | ||
| "OpenTracing has been superseded by OpenTelemetry and is no longer actively maintained."; | ||
| } | ||
|
|
||
| @Override | ||
| public List<Recipe> getRecipeList() { | ||
| return Arrays.asList( | ||
| // Core types | ||
| new ChangeType(OPENTRACING_PACKAGE + ".Tracer", OTEL_API_PACKAGE + ".trace.Tracer", true), | ||
| new ChangeType(OPENTRACING_PACKAGE + ".Span", OTEL_API_PACKAGE + ".trace.Span", true), | ||
| new ChangeType(OPENTRACING_PACKAGE + ".SpanContext", OTEL_API_PACKAGE + ".trace.SpanContext", true), | ||
| new ChangeType(OPENTRACING_PACKAGE + ".Scope", OTEL_CONTEXT_PACKAGE + ".Scope", true), | ||
| new ChangeType(OPENTRACING_PACKAGE + ".ScopeManager", OTEL_CONTEXT_PACKAGE + ".Context", true), | ||
|
|
||
| // Propagation types | ||
| new ChangeType(OPENTRACING_PACKAGE + ".propagation.Format", OTEL_CONTEXT_PACKAGE + ".propagation.TextMapPropagator", true), | ||
| new ChangeType(OPENTRACING_PACKAGE + ".propagation.TextMapExtract", OTEL_CONTEXT_PACKAGE + ".propagation.TextMapGetter", true), | ||
| new ChangeType(OPENTRACING_PACKAGE + ".propagation.TextMapInject", OTEL_CONTEXT_PACKAGE + ".propagation.TextMapSetter", true) | ||
| ); | ||
| } | ||
|
|
||
| @Override | ||
| public TreeVisitor<?, ExecutionContext> getVisitor() { | ||
| return Preconditions.check( | ||
| new UsesType<>(OPENTRACING_PACKAGE + ".*", false), | ||
| new JavaIsoVisitor<ExecutionContext>() { | ||
| // The actual migration is done by the recipe list above | ||
| } | ||
| ); | ||
| } | ||
| } | ||
78 changes: 78 additions & 0 deletions
78
...va/org/openrewrite/java/spring/opentelemetry/MigrateSleuthAnnotationsToOpenTelemetry.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| /* | ||
| * Copyright 2025 the original author or authors. | ||
| * <p> | ||
| * Licensed under the Moderne Source Available License (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * <p> | ||
| * https://docs.moderne.io/licensing/moderne-source-available-license | ||
| * <p> | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| package org.openrewrite.java.spring.opentelemetry; | ||
|
|
||
| import org.openrewrite.ExecutionContext; | ||
| import org.openrewrite.Preconditions; | ||
| import org.openrewrite.Recipe; | ||
| import org.openrewrite.TreeVisitor; | ||
| import org.openrewrite.java.ChangeType; | ||
| import org.openrewrite.java.JavaIsoVisitor; | ||
| import org.openrewrite.java.search.UsesType; | ||
|
|
||
| import java.util.Arrays; | ||
| import java.util.List; | ||
|
|
||
| /** | ||
| * Migrates Spring Cloud Sleuth annotations to OpenTelemetry annotations. | ||
| * <p> | ||
| * This recipe handles the migration of: | ||
| * <ul> | ||
| * <li>{@code @NewSpan} → {@code @WithSpan}</li> | ||
| * <li>{@code @SpanTag} → {@code @SpanAttribute}</li> | ||
| * <li>{@code @ContinueSpan} → {@code @WithSpan}</li> | ||
| * </ul> | ||
| * | ||
| * @see <a href="https://opentelemetry.io/docs/zero-code/java/spring-boot-starter/annotations/">OpenTelemetry Annotations</a> | ||
| */ | ||
| public class MigrateSleuthAnnotationsToOpenTelemetry extends Recipe { | ||
|
|
||
| private static final String SLEUTH_ANNOTATION_PACKAGE = "org.springframework.cloud.sleuth.annotation"; | ||
| private static final String OTEL_ANNOTATION_PACKAGE = "io.opentelemetry.instrumentation.annotations"; | ||
|
|
||
| @Override | ||
| public String getDisplayName() { | ||
| return "Migrate Sleuth annotations to OpenTelemetry annotations"; | ||
| } | ||
|
|
||
| @Override | ||
| public String getDescription() { | ||
| return "Migrate Spring Cloud Sleuth annotations (@NewSpan, @SpanTag, @ContinueSpan) " + | ||
| "to OpenTelemetry annotations (@WithSpan, @SpanAttribute)."; | ||
| } | ||
|
|
||
| @Override | ||
| public List<Recipe> getRecipeList() { | ||
| return Arrays.asList( | ||
| // @NewSpan -> @WithSpan | ||
| new ChangeType(SLEUTH_ANNOTATION_PACKAGE + ".NewSpan", OTEL_ANNOTATION_PACKAGE + ".WithSpan", true), | ||
| // @SpanTag -> @SpanAttribute | ||
| new ChangeType(SLEUTH_ANNOTATION_PACKAGE + ".SpanTag", OTEL_ANNOTATION_PACKAGE + ".SpanAttribute", true), | ||
| // @ContinueSpan -> @WithSpan (note: semantics differ slightly) | ||
| new ChangeType(SLEUTH_ANNOTATION_PACKAGE + ".ContinueSpan", OTEL_ANNOTATION_PACKAGE + ".WithSpan", true) | ||
| ); | ||
| } | ||
|
|
||
| @Override | ||
| public TreeVisitor<?, ExecutionContext> getVisitor() { | ||
| return Preconditions.check( | ||
| new UsesType<>(SLEUTH_ANNOTATION_PACKAGE + ".*", false), | ||
| new JavaIsoVisitor<ExecutionContext>() { | ||
| // The actual migration is done by the recipe list above | ||
| } | ||
| ); | ||
| } | ||
| } |
93 changes: 93 additions & 0 deletions
93
...main/java/org/openrewrite/java/spring/opentelemetry/MigrateSleuthToMicrometerTracing.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| /* | ||
| * Copyright 2025 the original author or authors. | ||
| * <p> | ||
| * Licensed under the Moderne Source Available License (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * <p> | ||
| * https://docs.moderne.io/licensing/moderne-source-available-license | ||
| * <p> | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| package org.openrewrite.java.spring.opentelemetry; | ||
|
|
||
| import org.openrewrite.ExecutionContext; | ||
| import org.openrewrite.Preconditions; | ||
| import org.openrewrite.Recipe; | ||
| import org.openrewrite.TreeVisitor; | ||
| import org.openrewrite.java.ChangePackage; | ||
| import org.openrewrite.java.ChangeType; | ||
timtebeek marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
timtebeek marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| import org.openrewrite.java.JavaIsoVisitor; | ||
| import org.openrewrite.java.search.UsesType; | ||
| import org.openrewrite.java.tree.J; | ||
|
|
||
| import java.util.Arrays; | ||
| import java.util.List; | ||
|
|
||
| /** | ||
| * Migrates Spring Cloud Sleuth API to Micrometer Tracing API. | ||
| * <p> | ||
| * Spring Cloud Sleuth has been deprecated and is replaced by Micrometer Tracing | ||
| * with OpenTelemetry as the recommended backend. | ||
| * | ||
| * @see <a href="https://github.com/spring-cloud/spring-cloud-sleuth#spring-cloud-sleuth">Spring Cloud Sleuth README</a> | ||
| * @see <a href="https://micrometer.io/docs/tracing">Micrometer Tracing Documentation</a> | ||
| */ | ||
| public class MigrateSleuthToMicrometerTracing extends Recipe { | ||
sandy2008 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| private static final String SLEUTH_PACKAGE = "org.springframework.cloud.sleuth"; | ||
| private static final String MICROMETER_TRACING_PACKAGE = "io.micrometer.tracing"; | ||
|
|
||
| @Override | ||
| public String getDisplayName() { | ||
| return "Migrate Spring Cloud Sleuth to Micrometer Tracing"; | ||
| } | ||
|
|
||
| @Override | ||
| public String getDescription() { | ||
| return "Migrate Spring Cloud Sleuth API to Micrometer Tracing API. " + | ||
| "Spring Cloud Sleuth has been deprecated and is replaced by Micrometer Tracing " + | ||
| "with OpenTelemetry as the recommended backend."; | ||
| } | ||
|
|
||
| @Override | ||
| public List<Recipe> getRecipeList() { | ||
| return Arrays.asList( | ||
| // Core types migration | ||
| new ChangeType(SLEUTH_PACKAGE + ".Tracer", MICROMETER_TRACING_PACKAGE + ".Tracer", true), | ||
| new ChangeType(SLEUTH_PACKAGE + ".Span", MICROMETER_TRACING_PACKAGE + ".Span", true), | ||
| new ChangeType(SLEUTH_PACKAGE + ".Span$Kind", MICROMETER_TRACING_PACKAGE + ".Span$Kind", true), | ||
| new ChangeType(SLEUTH_PACKAGE + ".SpanCustomizer", MICROMETER_TRACING_PACKAGE + ".SpanCustomizer", true), | ||
| new ChangeType(SLEUTH_PACKAGE + ".CurrentTraceContext", MICROMETER_TRACING_PACKAGE + ".CurrentTraceContext", true), | ||
| new ChangeType(SLEUTH_PACKAGE + ".TraceContext", MICROMETER_TRACING_PACKAGE + ".TraceContext", true), | ||
| new ChangeType(SLEUTH_PACKAGE + ".ScopedSpan", MICROMETER_TRACING_PACKAGE + ".ScopedSpan", true), | ||
| new ChangeType(SLEUTH_PACKAGE + ".SpanAndScope", MICROMETER_TRACING_PACKAGE + ".SpanAndScope", true), | ||
|
|
||
| // Baggage types | ||
| new ChangeType(SLEUTH_PACKAGE + ".Baggage", MICROMETER_TRACING_PACKAGE + ".Baggage", true), | ||
| new ChangeType(SLEUTH_PACKAGE + ".BaggageInScope", MICROMETER_TRACING_PACKAGE + ".BaggageInScope", true), | ||
|
|
||
| // Propagation types | ||
| new ChangeType(SLEUTH_PACKAGE + ".propagation.Propagator", MICROMETER_TRACING_PACKAGE + ".propagation.Propagator", true), | ||
|
|
||
| // Exporter types | ||
| new ChangeType(SLEUTH_PACKAGE + ".exporter.SpanFilter", MICROMETER_TRACING_PACKAGE + ".exporter.SpanExportingPredicate", true), | ||
| new ChangeType(SLEUTH_PACKAGE + ".exporter.SpanReporter", MICROMETER_TRACING_PACKAGE + ".exporter.SpanReporter", true) | ||
| ); | ||
| } | ||
|
|
||
| @Override | ||
| public TreeVisitor<?, ExecutionContext> getVisitor() { | ||
| return Preconditions.check( | ||
| new UsesType<>(SLEUTH_PACKAGE + ".*", false), | ||
| new JavaIsoVisitor<ExecutionContext>() { | ||
| // The actual migration is done by the recipe list above | ||
| // This visitor serves as a precondition check | ||
| } | ||
| ); | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.