Skip to content

Commit

Permalink
Merge pull request #2 from openrewrite/timer_to_observation
Browse files Browse the repository at this point in the history
Timer to Observation
  • Loading branch information
Joan Viladrosa authored Aug 30, 2023
2 parents 5052c0f + cc8de74 commit b4601a8
Show file tree
Hide file tree
Showing 6 changed files with 764 additions and 0 deletions.
143 changes: 143 additions & 0 deletions src/main/java/org/openrewrite/micrometer/TimerToObservation.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*
* Copyright 2023 the original author or authors.
* <p>
* Licensed under the Apache License, Version 2.0 (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://www.apache.org/licenses/LICENSE-2.0
* <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.micrometer;

import org.openrewrite.ExecutionContext;
import org.openrewrite.Preconditions;
import org.openrewrite.Recipe;
import org.openrewrite.TreeVisitor;
import org.openrewrite.internal.StringUtils;
import org.openrewrite.java.*;
import org.openrewrite.java.search.UsesMethod;
import org.openrewrite.java.tree.Expression;
import org.openrewrite.java.tree.J;

import java.util.ArrayList;
import java.util.List;

public class TimerToObservation extends Recipe {
private static final String TIMER = "io.micrometer.core.instrument.Timer";
private static final String OBSERVATION = "io.micrometer.observation.Observation";

@Override
public String getDisplayName() {
return "Convert Micrometer Timer to Observations";
}

@Override
public String getDescription() {
return "Convert Micrometer Timer to Observations.";
}

@Override
public TreeVisitor<?, ExecutionContext> getVisitor() {
return Preconditions.check(
Preconditions.and(
Preconditions.or(
new UsesMethod<>(TIMER + " record*(..)", false),
new UsesMethod<>(TIMER + " wrap(..)", false)
),
Preconditions.and(
Preconditions.not(new UsesMethod<>(TIMER + " record(java.time.Duration)", false)),
Preconditions.not(new UsesMethod<>(TIMER + " record(long, java.util.concurrent.TimeUnit)", false))
)
),
new JavaIsoVisitor<ExecutionContext>() {
private final MethodMatcher builderMatcher = new MethodMatcher(OBSERVATION + " builder(String)");
private final MethodMatcher registerMatcher = new MethodMatcher(TIMER + ".Builder register(io.micrometer.observation.ObservationRegistry)");
private final MethodMatcher tagMatcher = new MethodMatcher(TIMER + ".Builder tag(String, String)");
private final MethodMatcher tagsMatcher = new MethodMatcher(TIMER + ".Builder tags(..)");
private final MethodMatcher tagsIterableMatcher = new MethodMatcher(TIMER + ".Builder tags(Iterable)");

private final ChangeType changeTypeRegistry = new ChangeType("io.micrometer.core.instrument.MeterRegistry", "io.micrometer.observation.ObservationRegistry", null);
private final ChangeType changeTypeTimer = new ChangeType("io.micrometer.core.instrument.Timer","io.micrometer.observation.Observation", null);
private final ChangeMethodName changeRecord = new ChangeMethodName(OBSERVATION + " record*(..)", "observe", null, null);

@Override
public J.CompilationUnit visitCompilationUnit(J.CompilationUnit compilationUnit, ExecutionContext executionContext) {
J.CompilationUnit cu = compilationUnit;
cu = (J.CompilationUnit) changeTypeRegistry.getVisitor().visit(cu, executionContext);
cu = (J.CompilationUnit) changeTypeTimer.getVisitor().visit(cu, executionContext);
cu = (J.CompilationUnit) changeRecord.getVisitor().visit(cu, executionContext);
assert cu != null;
return super.visitCompilationUnit(cu, executionContext);
}

@Override
public J.MethodInvocation visitMethodInvocation(J.MethodInvocation mi, ExecutionContext executionContext) {
if (registerMatcher.matches(mi)) {
Expression timerName = null;
Expression registry = mi.getArguments().get(0);

List<String> builder = new ArrayList<>();
List<Expression> parameters = new ArrayList<>();

Expression maybeBuilder = mi.getSelect();
while (maybeBuilder instanceof J.MethodInvocation) {
J.MethodInvocation builderMethod = (J.MethodInvocation) maybeBuilder;
if (builderMatcher.matches(maybeBuilder)) {
timerName = builderMethod.getArguments().get(0);
}
else if (tagMatcher.matches(maybeBuilder)) {
builder.add("\n.highCardinalityKeyValue(#{any(String)}, #{any(String)})");
parameters.add(builderMethod.getArguments().get(0));
parameters.add(builderMethod.getArguments().get(1));
}
else if (tagsIterableMatcher.matches(maybeBuilder)) {
builder.add("\n.highCardinalityKeyValues(KeyValues.of(#{any(Iterable)}, Tag::getKey, Tag::getValue))");
parameters.addAll(builderMethod.getArguments());
maybeAddImport("io.micrometer.common.KeyValues");
maybeAddImport("io.micrometer.core.instrument.Tag");
}
else if (tagsMatcher.matches(maybeBuilder)) {
String args = StringUtils.repeat("#{any(String)},", builderMethod.getArguments().size());
args = args.substring(0, args.length() - 1);
builder.add("\n.highCardinalityKeyValues(KeyValues.of(" + args + "))");
parameters.addAll(builderMethod.getArguments());
maybeAddImport("io.micrometer.common.KeyValues");
}
maybeBuilder = ((J.MethodInvocation) maybeBuilder).getSelect();
}
if (timerName != null) {
parameters.add(0, timerName);
parameters.add(1, registry);

maybeAddImport("io.micrometer.observation.Observation");
maybeRemoveImport("io.micrometer.core.instrument.Timer");

JavaTemplate template = JavaTemplate
.builder("Observation.createNotStarted(#{any(java.lang.String)}, #{any()})"
+ String.join("", builder))
.contextSensitive()
.javaParser(JavaParser.fromJavaVersion()
.classpathFromResources(executionContext, "micrometer-observation", "micrometer-commons", "micrometer-core"))
.imports("io.micrometer.observation.Observation")
.imports("io.micrometer.common.KeyValues")
.imports("io.micrometer.core.instrument.Tag")
.build();

mi = autoFormat(
template.apply(updateCursor(mi), mi.getCoordinates().replace(), parameters.toArray()),
executionContext
);
}
}
return super.visitMethodInvocation(mi, executionContext);
}

});
}
}
20 changes: 20 additions & 0 deletions src/main/java/org/openrewrite/micrometer/package-info.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright 2023 the original author or authors.
* <p>
* Licensed under the Apache License, Version 2.0 (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://www.apache.org/licenses/LICENSE-2.0
* <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.
*/
@NonNullApi @NonNullFields
package org.openrewrite.micrometer;

import org.openrewrite.internal.lang.NonNullApi;
import org.openrewrite.internal.lang.NonNullFields;
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading

0 comments on commit b4601a8

Please sign in to comment.