如何删除时间测量逻辑
How to remove the time measurement logic
我需要计算一些方法的执行时间。这些是 class 中的私有方法,因此 Spring AOP 是不合适的。现在代码看起来像这样。
public void method() {
StopWatch sw = new StopWatch();
sw.start();
innerMethod1();
sw.stop();
Monitoring.add("eventType1", sw.getLastTaskTimeMillis());
sw.start();
innerMethod2("abs");
sw.stop();
Monitoring.add("eventType2", sw.getLastTaskTimeMillis());
sw.start();
innerMethod3(5, 29);
sw.stop();
Monitoring.add("eventType3", sw.getLastTaskTimeMillis());
}
但是带有时间度量的插入符合业务逻辑。有什么解决办法吗?然后这些数据会记录到grafana的数据库中。我正在寻找 AspectJ,但在启动应用程序时无法传递密钥。
When class instrumentation is required in environments that do not support or are not supported by the existing LoadTimeWeaver implementations, a JDK agent can be the only solution. For such cases, Spring provides InstrumentationLoadTimeWeaver, which requires a Spring-specific (but very general) VM agent,org.springframework.instrument-{version}.jar (previously named spring-agent.jar).
To use it, you must start the virtual machine with the Spring agent, by supplying the following JVM options:
-javaagent:/path/to/org.springframework.instrument-{version}.jar
马克·布拉姆尼克
如果我没理解错,那么对于方法
private List<String> innerMethod3(int value, int count) {
//
}
private String innerMethod2(String event) {
//
}
需要方法
public <T, R, U> U timed(T value, R count, BiFunction<T, R, U> function) {
long start = System.currentTimeMillis();
U result = function.apply(value, count);
Monitoring.add("method", System.currentTimeMillis() - start);
return result;
}
public <T, R> R timed(T value, Function<T, R> function) {
long start = System.currentTimeMillis();
R result = function.apply(value);
Monitoring.add("method", System.currentTimeMillis() - start);
return result;
}
以及调用方法:
List<String> timed = timed(5, 5, this::innerMethod3);
String string = timed("string", this::innerMethod2);
但是如果method4有4个参数,那么我需要一个新的时间测量方法和一个新的功能接口
您可以采用多种方法,但所有方法都归结为重构。
方法一:
class Timed {
public static void timed(String name, Runnable codeBlock) {
long from = System.currentTimeMillis();
codeBlock.run();
long to = System.currentTimeMillis();
System.out.println("Monitored: " + name + " : " + (to - from) + " ms");
}
public static <T> T timed(String name, Supplier<T> codeBlock) {
long from = System.currentTimeMillis();
T result = codeBlock.get();
long to = System.currentTimeMillis();
System.out.println("Monitored: " + name + " : " + (to - from) + " ms");
return result;
}
}
备注:
- 为了简单起见,我使用了 Runnable / Supplier 接口,您可能想为此创建自己的功能接口。
- 我已经使用了 System.out - 您将使用现有的
Monitoring.add
调用
上述代码可以这样使用:
Timed.timed("sample.runnable", ()-> { // Timed. can be statically imported for even further brevity
// some code block here
});
// will measure
int result = Timed.timed("sample.callable", () -> 42);
// will measure and result will be 42
另一种方法。
将代码重构为 public 方法并与 Micrometer that already has annotations support (see @Timed) 集成。
我不知道 Monitoring
是什么,但 Micrometer 已经包含与 Prometheus 的集成(以及其他可以存储指标并稍后从 grafana 中使用的类似产品)+它在内存中保存数学模型您的测量值,并且不会将每次测量的信息保存在内存中。在自定义实现中,维护起来很复杂。
更新 1
不,你弄错了,你不需要维护 timed
的不同版本 - 你只需要我在解决方案中提供的两个版本。如果您在问题中提出,您甚至不需要 timed
.
的第二个版本
您的代码将变为:
public void method() {
Timed.timed("eventType1", () -> {
innerMethod1();
});
Timed.timed("eventType2", () -> {
innerMethod2("abs");
});
Timed.timed("eventType3", () -> {
innerMethod3(5, 29);
});
}
第二个版本对于您实际 return 来自“定时”代码的一些值的情况是必需的:
示例:
假设您有 innerMethod4
和 returns 字符串,因此您将编写以下代码:
String result = Timed.timed("eventType3", () -> {
return innerMethod4(5, 29);
});
我需要计算一些方法的执行时间。这些是 class 中的私有方法,因此 Spring AOP 是不合适的。现在代码看起来像这样。
public void method() {
StopWatch sw = new StopWatch();
sw.start();
innerMethod1();
sw.stop();
Monitoring.add("eventType1", sw.getLastTaskTimeMillis());
sw.start();
innerMethod2("abs");
sw.stop();
Monitoring.add("eventType2", sw.getLastTaskTimeMillis());
sw.start();
innerMethod3(5, 29);
sw.stop();
Monitoring.add("eventType3", sw.getLastTaskTimeMillis());
}
但是带有时间度量的插入符合业务逻辑。有什么解决办法吗?然后这些数据会记录到grafana的数据库中。我正在寻找 AspectJ,但在启动应用程序时无法传递密钥。
When class instrumentation is required in environments that do not support or are not supported by the existing LoadTimeWeaver implementations, a JDK agent can be the only solution. For such cases, Spring provides InstrumentationLoadTimeWeaver, which requires a Spring-specific (but very general) VM agent,org.springframework.instrument-{version}.jar (previously named spring-agent.jar). To use it, you must start the virtual machine with the Spring agent, by supplying the following JVM options: -javaagent:/path/to/org.springframework.instrument-{version}.jar
马克·布拉姆尼克 如果我没理解错,那么对于方法
private List<String> innerMethod3(int value, int count) {
//
}
private String innerMethod2(String event) {
//
}
需要方法
public <T, R, U> U timed(T value, R count, BiFunction<T, R, U> function) {
long start = System.currentTimeMillis();
U result = function.apply(value, count);
Monitoring.add("method", System.currentTimeMillis() - start);
return result;
}
public <T, R> R timed(T value, Function<T, R> function) {
long start = System.currentTimeMillis();
R result = function.apply(value);
Monitoring.add("method", System.currentTimeMillis() - start);
return result;
}
以及调用方法:
List<String> timed = timed(5, 5, this::innerMethod3);
String string = timed("string", this::innerMethod2);
但是如果method4有4个参数,那么我需要一个新的时间测量方法和一个新的功能接口
您可以采用多种方法,但所有方法都归结为重构。
方法一:
class Timed {
public static void timed(String name, Runnable codeBlock) {
long from = System.currentTimeMillis();
codeBlock.run();
long to = System.currentTimeMillis();
System.out.println("Monitored: " + name + " : " + (to - from) + " ms");
}
public static <T> T timed(String name, Supplier<T> codeBlock) {
long from = System.currentTimeMillis();
T result = codeBlock.get();
long to = System.currentTimeMillis();
System.out.println("Monitored: " + name + " : " + (to - from) + " ms");
return result;
}
}
备注:
- 为了简单起见,我使用了 Runnable / Supplier 接口,您可能想为此创建自己的功能接口。
- 我已经使用了 System.out - 您将使用现有的
Monitoring.add
调用
上述代码可以这样使用:
Timed.timed("sample.runnable", ()-> { // Timed. can be statically imported for even further brevity
// some code block here
});
// will measure
int result = Timed.timed("sample.callable", () -> 42);
// will measure and result will be 42
另一种方法。
将代码重构为 public 方法并与 Micrometer that already has annotations support (see @Timed) 集成。
我不知道 Monitoring
是什么,但 Micrometer 已经包含与 Prometheus 的集成(以及其他可以存储指标并稍后从 grafana 中使用的类似产品)+它在内存中保存数学模型您的测量值,并且不会将每次测量的信息保存在内存中。在自定义实现中,维护起来很复杂。
更新 1
不,你弄错了,你不需要维护 timed
的不同版本 - 你只需要我在解决方案中提供的两个版本。如果您在问题中提出,您甚至不需要 timed
.
您的代码将变为:
public void method() {
Timed.timed("eventType1", () -> {
innerMethod1();
});
Timed.timed("eventType2", () -> {
innerMethod2("abs");
});
Timed.timed("eventType3", () -> {
innerMethod3(5, 29);
});
}
第二个版本对于您实际 return 来自“定时”代码的一些值的情况是必需的:
示例:
假设您有 innerMethod4
和 returns 字符串,因此您将编写以下代码:
String result = Timed.timed("eventType3", () -> {
return innerMethod4(5, 29);
});