Skip to content

Commit dcb6874

Browse files
committed
actframework#482 simplified measuring of method execution
1 parent 2776727 commit dcb6874

14 files changed

Lines changed: 769 additions & 14 deletions

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
# ActFramework Change Log
22

33
**1.7.0**
4-
* ResourceLoader - support any object type #497
54
* Update JPA api to 2.2
65
* EntityMetaInfo and scanner - support JPA plugin
76
* Improve built-in service performance by make them as nonblock when possible
7+
* ResourceLoader - support any object type #497
88
* Do not `Set-Cookie` for session and flash if there is no state #484
99
* Make `act.metric.Timer` be a `Closable` #483
10+
* Simplify measuring of method execution #482
1011
* DB: add annotation to mark created and last modified timestamp fields #480
1112
* Missing actframework version in the banner text in dev mode with Eclipse project #478
1213
* Rename `AppEvent` to `SysEvent` #475

src/main/java/act/app/App.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@
5757
import act.job.bytecode.JobByteCodeScanner;
5858
import act.mail.MailerConfigManager;
5959
import act.mail.bytecode.MailerByteCodeScanner;
60+
import act.metric.Metric;
61+
import act.metric.MetricContextScanner;
62+
import act.metric.MetricMetaInfoRepo;
63+
import act.metric.MetricProvider;
6064
import act.route.RouteSource;
6165
import act.route.RouteTableRouterBuilder;
6266
import act.route.Router;
@@ -142,6 +146,7 @@ public enum F {
142146
private MasterEntityMetaInfoRepo entityMetaInfoRepo;
143147
private Map<String, Daemon> daemonRegistry;
144148
private WebSocketConnectionManager webSocketConnectionManager;
149+
private MetricMetaInfoRepo metricMetaInfoRepo;
145150
private AppCrypto crypto;
146151
private IdGenerator idGenerator;
147152
private SessionManager sessionManager;
@@ -595,6 +600,7 @@ public synchronized void refresh() {
595600
initApiManager();
596601
initCliDispatcher();
597602
initCliServer();
603+
initMetricMetaInfoRepo();
598604
initEntityMetaInfoRepo();
599605

600606
initWebSocketConnectionManager();
@@ -661,6 +667,7 @@ public synchronized void refresh() {
661667
// are cleared
662668
emit(DEPENDENCY_INJECTOR_PROVISIONED);
663669
emit(SINGLETON_PROVISIONED);
670+
registerMetricProvider();
664671
config().preloadConfigurations();
665672
initSessionManager();
666673
Runnable runnable = new Runnable() {
@@ -709,6 +716,13 @@ public boolean isSingleton(Class<?> cls) {
709716
return null != singletonRegistry.get(cls) || hasSingletonAnnotation(cls);
710717
}
711718

719+
private void registerMetricProvider() {
720+
GenieInjector gi = this.injector();
721+
MetricProvider mp = new MetricProvider();
722+
gi.genie().registerNamedProvider(Metric.class, mp);
723+
gi.genie().registerProvider(Metric.class, mp);
724+
}
725+
712726
private boolean hasSingletonAnnotation(Class<?> cls) {
713727
boolean found = false;
714728
GenieInjector injector = Act.app().injector();
@@ -836,6 +850,10 @@ public JobManager jobManager() {
836850
return jobManager;
837851
}
838852

853+
public MetricMetaInfoRepo metricMetaInfoRepo() {
854+
return metricMetaInfoRepo;
855+
}
856+
839857
public <DI extends DependencyInjector> App injector(DI dependencyInjector) {
840858
E.NPE(dependencyInjector);
841859
E.illegalStateIf(null != this.dependencyInjector, "Dependency injection factory already set");
@@ -1056,6 +1074,10 @@ private void initIdGenerator() {
10561074
);
10571075
}
10581076

1077+
private void initMetricMetaInfoRepo() {
1078+
metricMetaInfoRepo = new MetricMetaInfoRepo(this);
1079+
}
1080+
10591081
private void initDaemonRegistry() {
10601082
if (null != daemonRegistry) {
10611083
Destroyable.Util.tryDestroyAll(daemonRegistry.values(), ApplicationScoped.class);
@@ -1279,6 +1301,7 @@ private void loadBuiltInScanners() {
12791301
scannerManager.register(new CommanderByteCodeScanner());
12801302
scannerManager.register(new EntityInfoByteCodeScanner());
12811303
scannerManager.register(new RythmTransformerScanner());
1304+
scannerManager.register(new MetricContextScanner());
12821305
scannerManager.register(new ImplicitVariableProvider.TemplateVariableScanner(this));
12831306
}
12841307

src/main/java/act/inject/genie/GenieInjector.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ private Set<Object> factories() {
167167
return set;
168168
}
169169

170-
private Genie genie() {
170+
public Genie genie() {
171171
if (null == genie) {
172172
synchronized (this) {
173173
if (null == genie) {
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package act.metric;
2+
3+
/*-
4+
* #%L
5+
* ACT Framework
6+
* %%
7+
* Copyright (C) 2014 - 2017 ActFramework
8+
* %%
9+
* Licensed under the Apache License, Version 2.0 (the "License");
10+
* you may not use this file except in compliance with the License.
11+
* You may obtain a copy of the License at
12+
*
13+
* http://www.apache.org/licenses/LICENSE-2.0
14+
*
15+
* Unless required by applicable law or agreed to in writing, software
16+
* distributed under the License is distributed on an "AS IS" BASIS,
17+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
* See the License for the specific language governing permissions and
19+
* limitations under the License.
20+
* #L%
21+
*/
22+
23+
import java.lang.annotation.ElementType;
24+
import java.lang.annotation.Retention;
25+
import java.lang.annotation.RetentionPolicy;
26+
import java.lang.annotation.Target;
27+
28+
/**
29+
* Mark a method is subject to metric count measurement
30+
*/
31+
@Retention(RetentionPolicy.RUNTIME)
32+
@Target(ElementType.METHOD)
33+
public @interface MeasureCount {
34+
35+
/**
36+
* Specify the metric label.
37+
*
38+
* If the label starts with `/` then the {@link MetricContext}
39+
* of the containing class will not effect. Otherwise the label
40+
* will be concatenated with the metric context of the containing
41+
* class if presented.
42+
*
43+
* If not specified then it will use the method name as
44+
* the label
45+
*
46+
* @return metric label
47+
*/
48+
String value() default "";
49+
50+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package act.metric;
2+
3+
/*-
4+
* #%L
5+
* ACT Framework
6+
* %%
7+
* Copyright (C) 2014 - 2017 ActFramework
8+
* %%
9+
* Licensed under the Apache License, Version 2.0 (the "License");
10+
* you may not use this file except in compliance with the License.
11+
* You may obtain a copy of the License at
12+
*
13+
* http://www.apache.org/licenses/LICENSE-2.0
14+
*
15+
* Unless required by applicable law or agreed to in writing, software
16+
* distributed under the License is distributed on an "AS IS" BASIS,
17+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
* See the License for the specific language governing permissions and
19+
* limitations under the License.
20+
* #L%
21+
*/
22+
23+
import java.lang.annotation.*;
24+
25+
/**
26+
* Mark a method is subject to metric time measurement
27+
*/
28+
@Retention(RetentionPolicy.RUNTIME)
29+
@Target(ElementType.METHOD)
30+
public @interface MeasureTime {
31+
32+
/**
33+
* Specify the metric label.
34+
*
35+
* If the label starts with `/` then the {@link MetricContext}
36+
* of the containing class will not effect. Otherwise the label
37+
* will be concatenated with the metric context of the containing
38+
* class if presented.
39+
*
40+
* If not specified then it will use the method name as
41+
* the label
42+
*
43+
* @return metric label
44+
*/
45+
String value() default "";
46+
47+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package act.metric;
2+
3+
/*-
4+
* #%L
5+
* ACT Framework
6+
* %%
7+
* Copyright (C) 2014 - 2017 ActFramework
8+
* %%
9+
* Licensed under the Apache License, Version 2.0 (the "License");
10+
* you may not use this file except in compliance with the License.
11+
* You may obtain a copy of the License at
12+
*
13+
* http://www.apache.org/licenses/LICENSE-2.0
14+
*
15+
* Unless required by applicable law or agreed to in writing, software
16+
* distributed under the License is distributed on an "AS IS" BASIS,
17+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
* See the License for the specific language governing permissions and
19+
* limitations under the License.
20+
* #L%
21+
*/
22+
23+
import java.lang.annotation.*;
24+
25+
/**
26+
* Specify the metric context of a class.
27+
*
28+
* **Note** this annotation is inherited
29+
*/
30+
@Retention(RetentionPolicy.RUNTIME)
31+
@Inherited
32+
@Target(ElementType.TYPE)
33+
public @interface MetricContext {
34+
35+
/**
36+
* Specify the metric context
37+
*
38+
* @return metric context
39+
*/
40+
String value();
41+
42+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package act.metric;
2+
3+
/*-
4+
* #%L
5+
* ACT Framework
6+
* %%
7+
* Copyright (C) 2014 - 2018 ActFramework
8+
* %%
9+
* Licensed under the Apache License, Version 2.0 (the "License");
10+
* you may not use this file except in compliance with the License.
11+
* You may obtain a copy of the License at
12+
*
13+
* http://www.apache.org/licenses/LICENSE-2.0
14+
*
15+
* Unless required by applicable law or agreed to in writing, software
16+
* distributed under the License is distributed on an "AS IS" BASIS,
17+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
* See the License for the specific language governing permissions and
19+
* limitations under the License.
20+
* #L%
21+
*/
22+
23+
import act.app.AppByteCodeScannerBase;
24+
import act.asm.AnnotationVisitor;
25+
import act.asm.Type;
26+
import act.util.ByteCodeVisitor;
27+
28+
public class MetricContextScanner extends AppByteCodeScannerBase {
29+
30+
private static final String DESC_METRIC_CONTEXT = Type.getType(MetricContext.class).getDescriptor();
31+
private MetricMetaInfoRepo repo;
32+
33+
@Override
34+
protected void onAppSet() {
35+
repo = app().metricMetaInfoRepo();
36+
}
37+
38+
@Override
39+
protected boolean shouldScan(String className) {
40+
return true;
41+
}
42+
43+
@Override
44+
public ByteCodeVisitor byteCodeVisitor() {
45+
return new ByteCodeVisitor() {
46+
47+
private String className;
48+
49+
@Override
50+
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
51+
super.visit(version, access, name, signature, superName, interfaces);
52+
className = Type.getObjectType(name).getClassName();
53+
}
54+
55+
@Override
56+
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
57+
AnnotationVisitor av = super.visitAnnotation(desc, visible);
58+
if (DESC_METRIC_CONTEXT.equals(desc)) {
59+
return new AnnotationVisitor(ASM5, av) {
60+
@Override
61+
public void visit(String name, Object value) {
62+
super.visit(name, value);
63+
if ("value".equals(name)) {
64+
repo.registerMetricContext(className, value.toString());
65+
}
66+
}
67+
};
68+
}
69+
return av;
70+
}
71+
};
72+
}
73+
74+
@Override
75+
public void scanFinished(String className) {
76+
77+
}
78+
}
79+

0 commit comments

Comments
 (0)