From 8b2b81926c76f52e6a26e967f6cc37f04fdaf803 Mon Sep 17 00:00:00 2001 From: Harrison Date: Mon, 7 Mar 2022 16:33:43 +0800 Subject: [PATCH 1/8] =?UTF-8?q?feat:=20KERNEL-10354=20bytebuddy=20/=20?= =?UTF-8?q?=E5=8A=A0=E8=A7=A3=E5=AF=86=E6=80=A7=E8=83=BD=E4=BC=98=E5=8C=96?= =?UTF-8?q?=20@Harrison=201=E3=80=81FineAnalyzer=E9=83=A8=E5=88=86?= =?UTF-8?q?=E5=BB=B6=E8=BF=9F=E5=90=AF=E5=8A=A8=202=E3=80=81FineAnalyzer?= =?UTF-8?q?=20=E8=A1=A5=E5=85=85=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95=203?= =?UTF-8?q?=E3=80=81=E8=A1=A5=E5=85=85=E4=BC=98=E5=8C=96=E5=BC=80=E5=85=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../record/analyzer/DesignerAnalyzer.java | 22 +++ .../analyzer/DesignerAnalyzerActivator.java | 121 +++++++++++++ .../analyzer/DesignerAnalyzerAdvice.java | 12 ++ .../analyzer/advice/DBMonitorAdvice.java | 29 ++++ .../analyzer/advice/FaultToleranceAdvice.java | 35 ++++ .../record/analyzer/advice/FocusAdvice.java | 32 ++++ .../record/analyzer/advice/MonitorAdvice.java | 159 ++++++++++++++++++ .../advice/PerformancePointAdvice.java | 54 ++++++ .../analyzer/BytebuddyRedefineTest.java | 81 +++++++++ .../fr/design/record/analyzer/TestClass.java | 11 ++ .../analyzer/TestModifyReturnAdvice.java | 29 ++++ .../analyzer/TestThrowExceptionAdvice.java | 19 +++ .../analyzer/TestTransferValueAdvice.java | 37 ++++ .../main/java/com/fr/start/MainDesigner.java | 2 + 14 files changed, 643 insertions(+) create mode 100644 designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzer.java create mode 100644 designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java create mode 100644 designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerAdvice.java create mode 100644 designer-base/src/main/java/com/fr/design/record/analyzer/advice/DBMonitorAdvice.java create mode 100644 designer-base/src/main/java/com/fr/design/record/analyzer/advice/FaultToleranceAdvice.java create mode 100644 designer-base/src/main/java/com/fr/design/record/analyzer/advice/FocusAdvice.java create mode 100644 designer-base/src/main/java/com/fr/design/record/analyzer/advice/MonitorAdvice.java create mode 100644 designer-base/src/main/java/com/fr/design/record/analyzer/advice/PerformancePointAdvice.java create mode 100644 designer-base/src/test/java/com/fr/design/record/analyzer/BytebuddyRedefineTest.java create mode 100644 designer-base/src/test/java/com/fr/design/record/analyzer/TestClass.java create mode 100644 designer-base/src/test/java/com/fr/design/record/analyzer/TestModifyReturnAdvice.java create mode 100644 designer-base/src/test/java/com/fr/design/record/analyzer/TestThrowExceptionAdvice.java create mode 100644 designer-base/src/test/java/com/fr/design/record/analyzer/TestTransferValueAdvice.java diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzer.java b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzer.java new file mode 100644 index 000000000..fe4b30806 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzer.java @@ -0,0 +1,22 @@ +package com.fr.design.record.analyzer; + +import com.fr.record.analyzer.AnalyzerConfiguration; +import com.fr.record.analyzer.AnalyzerUnit; +import com.fr.record.analyzer.configuration.AnalyzerAssemblyFactory; +import com.fr.record.analyzer.configuration.impl.RedefineAssemblyFactory; + +/** + * created by Harrison on 2022/03/08 + **/ +public class DesignerAnalyzer { + + private static final AnalyzerUnit ANALYZER = new AnalyzerUnit(); + + public static synchronized void init(AnalyzerAssemblyFactory factory, AnalyzerConfiguration... configurations) { + + AnalyzerAssemblyFactory redefineFactory = factory.prepare(RedefineAssemblyFactory.getInstance()); + + ANALYZER.init(redefineFactory, configurations); + } + +} diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java new file mode 100644 index 000000000..60b65b1a1 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java @@ -0,0 +1,121 @@ +package com.fr.design.record.analyzer; + +import com.fr.base.OptimizeUtil; +import com.fr.concurrent.NamedThreadFactory; +import com.fr.design.record.analyzer.advice.DBMonitorAdvice; +import com.fr.design.record.analyzer.advice.FaultToleranceAdvice; +import com.fr.design.record.analyzer.advice.FocusAdvice; +import com.fr.design.record.analyzer.advice.MonitorAdvice; +import com.fr.design.record.analyzer.advice.PerformancePointAdvice; +import com.fr.intelli.metrics.Compute; +import com.fr.intelli.record.Focus; +import com.fr.intelli.record.PerformancePoint; +import com.fr.module.Activator; +import com.fr.module.extension.Prepare; +import com.fr.record.analyzer.AnalyzerConfiguration; +import com.fr.record.analyzer.AnalyzerKey; +import com.fr.record.analyzer.DBMetrics; +import com.fr.record.analyzer.FineAdviceTransformer; +import com.fr.record.analyzer.FineAnalyzer; +import com.fr.record.analyzer.advice.AnalyzerAdviceConfiguration; +import com.fr.record.analyzer.advice.AnalyzerAdviceKey; +import com.fr.record.analyzer.configuration.AnalyzerAssemblyFactory; +import com.fr.record.analyzer.configuration.FineAnalyzerAssemblyFactory; +import com.fr.stable.collections.CollectionUtils; +import com.fr.third.net.bytebuddy.matcher.ElementMatchers; +import com.fr.tolerance.FaultTolerance; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.concurrent.ExecutorService; + +/** + * created by Harrison on 2022/03/04 + **/ +public class DesignerAnalyzerActivator extends Activator implements Prepare { + + @Override + public void start() { + + OptimizeUtil.open(() -> { + ExecutorService es = newSingleThreadExecutor(new NamedThreadFactory("designer-analyzer", true)); + + try { + AnalyzerAssemblyFactory basicFactory = createBasicFactory(); + + // 兼容逻辑 + List backwardsConfigurations = findMutableBackwards(AnalyzerKey.KEY); + if (!CollectionUtils.isEmpty(backwardsConfigurations)) { + es.submit(() -> { + FineAnalyzer.init(basicFactory, backwardsConfigurations.toArray(new AnalyzerConfiguration[0])); + }); + } + + // 加入 retransform 部分的逻辑 + List adviceConfigurations = findMutable(AnalyzerAdviceKey.KEY); + + if (!CollectionUtils.isEmpty(adviceConfigurations)) { + AnalyzerConfiguration[] configurations = convertConfigurations(adviceConfigurations); + es.submit(() -> { + DesignerAnalyzer.init(basicFactory, configurations); + }); + } + + } finally { + es.shutdown(); + } + }); + } + + @NotNull + private AnalyzerConfiguration[] convertConfigurations(List list) { + + return list.stream() + .map((e) -> AnalyzerConfiguration.create(e.getMatcher(), new FineAdviceTransformer(e.getMatcher(), e.getAdviceClass()))) + .toArray(AnalyzerConfiguration[]::new); + } + + @Override + public void stop() { + + } + + @Override + public void prepare() { + + addMutable(AnalyzerAdviceKey.KEY, AnalyzerAdviceConfiguration.create( + ElementMatchers.isAnnotatedWith(Focus.class), + FocusAdvice.class + )); + + addMutable(AnalyzerAdviceKey.KEY, AnalyzerAdviceConfiguration.create( + ElementMatchers.isAnnotatedWith(Compute.class), + MonitorAdvice.class + )); + + addMutable(AnalyzerAdviceKey.KEY, AnalyzerAdviceConfiguration.create( + ElementMatchers.isAnnotatedWith(DBMetrics.class), + DBMonitorAdvice.class + )); + + addMutable(AnalyzerAdviceKey.KEY, AnalyzerAdviceConfiguration.create( + ElementMatchers.isAnnotatedWith(PerformancePoint.class), + PerformancePointAdvice.class + )); + + addMutable(AnalyzerAdviceKey.KEY, AnalyzerAdviceConfiguration.create( + ElementMatchers.isAnnotatedWith(FaultTolerance.class), + FaultToleranceAdvice.class + )); + + } + + + private AnalyzerAssemblyFactory createBasicFactory() { + + AnalyzerAssemblyFactory factory = findSingleton(AnalyzerAssemblyFactory.class); + FineAnalyzerAssemblyFactory basicFactory = new FineAnalyzerAssemblyFactory(); + basicFactory.prepare(factory); + return basicFactory; + } +} diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerAdvice.java b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerAdvice.java new file mode 100644 index 000000000..301634aa6 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerAdvice.java @@ -0,0 +1,12 @@ +package com.fr.design.record.analyzer; + +import com.fr.record.analyzer.advice.AnalyzerAdvice; + +/** + * 仅作为标志 + * 没有方法 + * + * created by Harrison on 2022/03/04 + **/ +public interface DesignerAnalyzerAdvice extends AnalyzerAdvice { +} diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/advice/DBMonitorAdvice.java b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/DBMonitorAdvice.java new file mode 100644 index 000000000..9b22e07b2 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/DBMonitorAdvice.java @@ -0,0 +1,29 @@ +package com.fr.design.record.analyzer.advice; + +import com.fr.design.record.analyzer.DesignerAnalyzerAdvice; +import com.fr.general.data.DataModel; +import com.fr.measure.DBMeterFactory; +import com.fr.measure.metric.DBMetric; +import com.fr.third.net.bytebuddy.asm.Advice; +import com.fr.third.net.bytebuddy.implementation.bytecode.assign.Assigner; + +import java.lang.reflect.Method; + +/** + * created by Harrison on 2022/03/07 + **/ +public class DBMonitorAdvice implements DesignerAnalyzerAdvice { + + @Advice.OnMethodExit(onThrowable = Exception.class) + public static void onMethodExit(@Advice.This(optional = true, typing = Assigner.Typing.DYNAMIC) Object self, + @Advice.Origin Method method, + @Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args, + @Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object result, + @Advice.Thrown(typing = Assigner.Typing.DYNAMIC) Exception e) { + + if (args.length > 1 && args[1] instanceof DataModel) { + DBMetric meter = ((DataModel) args[1]).getMetric(); + DBMeterFactory.getMeter().record(meter); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/advice/FaultToleranceAdvice.java b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/FaultToleranceAdvice.java new file mode 100644 index 000000000..f0d089b3e --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/FaultToleranceAdvice.java @@ -0,0 +1,35 @@ +package com.fr.design.record.analyzer.advice; + +import com.fr.design.record.analyzer.DesignerAnalyzerAdvice; +import com.fr.third.net.bytebuddy.asm.Advice; +import com.fr.third.net.bytebuddy.implementation.bytecode.assign.Assigner; +import com.fr.tolerance.FaultTolerance; +import com.fr.tolerance.FaultToleranceFactory; + +import java.lang.reflect.Method; +import java.util.concurrent.Callable; + +/** + * created by Harrison on 2022/03/07 + **/ +public class FaultToleranceAdvice implements DesignerAnalyzerAdvice { + + @Advice.OnMethodEnter(skipOn = Advice.OnDefaultValue.class) + public static int onMethodEnter(@Advice.This(optional = true, typing = Assigner.Typing.DYNAMIC) Object self, + @Advice.Origin Method method, + @Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args) throws Exception { + return 0; + } + + @Advice.OnMethodExit(onThrowable = Exception.class) + public static void onMethodExit(@Advice.This(optional = true, typing = Assigner.Typing.DYNAMIC) Object self, + @Advice.Origin Method method, + @Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args, + @Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object result) throws Exception { + + + FaultTolerance faultTolerance = method.getAnnotation(FaultTolerance.class); + Callable callable = () -> method.invoke(self, args); + result = FaultToleranceFactory.getInstance().getScene(faultTolerance.scene()).getProcessor().execute(self, callable, args); + } +} diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/advice/FocusAdvice.java b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/FocusAdvice.java new file mode 100644 index 000000000..653ce9109 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/FocusAdvice.java @@ -0,0 +1,32 @@ +package com.fr.design.record.analyzer.advice; + +import com.fr.design.record.analyzer.DesignerAnalyzerAdvice; +import com.fr.intelli.record.Focus; +import com.fr.intelli.record.FocusPoint; +import com.fr.intelli.record.FocusPolicy; +import com.fr.log.counter.DefaultLimitedMetric; +import com.fr.third.net.bytebuddy.asm.Advice; +import com.fr.third.net.bytebuddy.implementation.bytecode.assign.Assigner; + +import java.lang.reflect.Method; + +/** + * created by Harrison on 2022/03/07 + **/ +public class FocusAdvice implements DesignerAnalyzerAdvice { + + private static final String FOCUS_POINT_ID_PREFIX = "function_"; + + @Advice.OnMethodExit(onThrowable = Exception.class) + public static void onMethodExit(@Advice.Origin Method method, + @Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] arguments, + @Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object result) throws Exception { + + if (FocusPolicy.IGNORE == result) { + return; + } + Focus focus = method.getAnnotation(Focus.class); + String id = FOCUS_POINT_ID_PREFIX + focus.id(); + DefaultLimitedMetric.INSTANCE.submit(FocusPoint.create(id, focus.text(), focus.source()), id); + } +} diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/advice/MonitorAdvice.java b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/MonitorAdvice.java new file mode 100644 index 000000000..826cc1e64 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/MonitorAdvice.java @@ -0,0 +1,159 @@ +package com.fr.design.record.analyzer.advice; + +import com.fr.design.record.analyzer.DesignerAnalyzerAdvice; +import com.fr.general.GeneralUtils; +import com.fr.intelli.metrics.Compute; +import com.fr.intelli.metrics.SupervisoryConfig; +import com.fr.intelli.record.Measurable; +import com.fr.intelli.record.MeasureObject; +import com.fr.intelli.record.MeasureUnit; +import com.fr.intelli.record.MetricRegistry; +import com.fr.measure.DBMeterFactory; +import com.fr.stable.ArrayUtils; +import com.fr.stable.StringUtils; +import com.fr.stable.web.Session; +import com.fr.stable.web.SessionProvider; +import com.fr.third.net.bytebuddy.asm.Advice; +import com.fr.third.net.bytebuddy.implementation.bytecode.assign.Assigner; +import com.fr.web.core.SessionPoolManager; +import com.fr.web.session.SessionLocalManager; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * created by Harrison on 2022/03/07 + **/ +public class MonitorAdvice implements DesignerAnalyzerAdvice { + + private static final Pattern P = Pattern.compile("-?\\d+"); + private static final int MIN_ERROR_CODE = 10000000; + + @Advice.OnMethodEnter + public static void onMethodEnter(@Advice.This(optional = true, typing = Assigner.Typing.DYNAMIC) Object self, + @Advice.Origin Method method, + @Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args, + @Advice.Local("startTime") Long startTime, + @Advice.Local("registeredSession") Boolean registeredSession) { + + startTime = (System.currentTimeMillis()); + registeredSession = (findSessionAnnotation(method, args)); + } + + @Advice.OnMethodExit(onThrowable = Exception.class) + public static void onMethodExit(@Advice.This(optional = true, typing = Assigner.Typing.DYNAMIC) Object self, + @Advice.Origin Method method, + @Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args, + @Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object result, + @Advice.Thrown(typing = Assigner.Typing.DYNAMIC) Exception e, + @Advice.Local("startTime") Long startTime, + @Advice.Local("registeredSession") Boolean registeredSession) throws Exception { + + String error = StringUtils.EMPTY; + + try { + + if (e != null) { + try { + error = getErrorContent(e); + } catch (Exception ignore) { + } + } + } finally { + try { + if (self instanceof Measurable) { + long consume = System.currentTimeMillis() - startTime; + Compute once = method.getAnnotation(Compute.class); + Measurable measurable = (Measurable) self; + MeasureObject measureObject = MeasureObject.create(); + recordMemory(once, measurable, measureObject); + recordSQL(once, measureObject); + measureObject.consume(consume); + measureObject.error(error); + String id = UUID.randomUUID().toString(); + List newArgs = new ArrayList(Arrays.asList(args)); + newArgs.add(id); + recordSQLDetail(id); + Object message; + try { + message = measurable.durableEntity(measureObject, newArgs.toArray()); + } catch (Throwable ignore) { + //埋点生成失败,降级逻辑 + message = measurable.fallBackEntity(); + } + if (message != null) { + SessionProvider provider = SessionLocalManager.getSession(); + if (provider == null) { + MetricRegistry.getMetric().submit(message); + } else { + MetricRegistry.getMetric().submitAccumulativeData(provider.getSessionID(), message); + } + } + } + } catch (Exception ignore) { + //埋点信息入库失败应该不能影响业务流程 + } finally { + if (registeredSession) { + // 如果上面记录了,这里就要释放 + SessionLocalManager.releaseSession(); + } + } + } + } + + private static String getErrorContent(Exception e) { + int errorCode = GeneralUtils.objectToNumber( + extractCodeFromString(e.getMessage()) + ).intValue(); + // 提取字符串中的第一个数字,最小的错误码为10000000 + return e.getClass().getName() + ":" + (errorCode >= MIN_ERROR_CODE ? errorCode : StringUtils.EMPTY); + } + + private static String extractCodeFromString(String errorMsg) { + Matcher m = P.matcher(errorMsg); + if (m.find()) { + return m.group(); + } + return StringUtils.EMPTY; + } + + private static void recordSQLDetail(String uuid) { + DBMeterFactory.getMeter().submit(uuid); + } + + private static void recordSQL(Compute once, MeasureObject measureObject) { + if (SupervisoryConfig.getInstance().isEnableMeasureSql() && once.computeSql()) { + measureObject.sqlTime(SessionLocalManager.getSqlTime()); + measureObject.sql(SessionLocalManager.getSql()); + } + } + + private static void recordMemory(Compute once, Measurable measurable, MeasureObject measureObject) { + if (SupervisoryConfig.getInstance().isEnableMeasureMemory() && once.computeMemory()) { + MeasureUnit unit = measurable.measureUnit(); + measureObject.memory(unit.measureMemory()); + } + } + + private static boolean findSessionAnnotation(Method method, Object[] args) { + Annotation[][] all = method.getParameterAnnotations(); + int len = ArrayUtils.getLength(args); + for (int i = 0; i < len; i++) { + Annotation[] current = all[i]; + for (Annotation annotation : current) { + if (annotation.annotationType().equals(Session.class)) { + SessionLocalManager.setSession( + SessionPoolManager.getSessionIDInfor(GeneralUtils.objectToString(args[i]), SessionProvider.class)); + return true; + } + } + } + return false; + } +} diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/advice/PerformancePointAdvice.java b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/PerformancePointAdvice.java new file mode 100644 index 000000000..80aab8bd1 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/PerformancePointAdvice.java @@ -0,0 +1,54 @@ +package com.fr.design.record.analyzer.advice; + +import com.fr.design.record.analyzer.DesignerAnalyzerAdvice; +import com.fr.intelli.record.ConsumePoint; +import com.fr.intelli.record.MetricRegistry; +import com.fr.intelli.record.PerformancePoint; +import com.fr.intelli.record.PerformancePointRecord; +import com.fr.stable.StringUtils; +import com.fr.third.net.bytebuddy.asm.Advice; +import com.fr.third.net.bytebuddy.implementation.bytecode.assign.Assigner; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * created by Harrison on 2022/03/07 + **/ +public class PerformancePointAdvice implements DesignerAnalyzerAdvice { + + @Advice.OnMethodEnter + public static void onMethodEnter(@Advice.This(optional = true, typing = Assigner.Typing.DYNAMIC) Object self, + @Advice.Origin Method method, + @Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args, + @Advice.Local("startTime") Long startTime) { + + startTime = (System.currentTimeMillis()); + } + + @Advice.OnMethodExit(onThrowable = Exception.class) + public static void onMethodExit(@Advice.This(optional = true, typing = Assigner.Typing.DYNAMIC) Object self, + @Advice.Origin Method method, + @Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args, + @Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object result, + @Advice.Thrown(typing = Assigner.Typing.DYNAMIC) Exception e, + @Advice.Local("startTime") Long startTime) { + + PerformancePoint point = method.getAnnotation(PerformancePoint.class); + String id = point.id(); + long endTime = System.currentTimeMillis(); + long consume = endTime - startTime; + if (self instanceof PerformancePointRecord) { + PerformancePointRecord measurable = (PerformancePointRecord) self; + List newArgs = new ArrayList(Arrays.asList(args)); + ConsumePoint consumePoint = ConsumePoint.create(id, startTime, endTime, consume, point.source()); + MetricRegistry.getMetric().submit(measurable.recordPoint(consumePoint, newArgs.toArray())); + } else { + if (StringUtils.isNotEmpty(id)) { + MetricRegistry.getMetric().submit(ConsumePoint.create(id, consume, point.source())); + } + } + } +} diff --git a/designer-base/src/test/java/com/fr/design/record/analyzer/BytebuddyRedefineTest.java b/designer-base/src/test/java/com/fr/design/record/analyzer/BytebuddyRedefineTest.java new file mode 100644 index 000000000..f9ec6e21e --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/record/analyzer/BytebuddyRedefineTest.java @@ -0,0 +1,81 @@ +package com.fr.design.record.analyzer; + +import com.fr.third.net.bytebuddy.ByteBuddy; +import com.fr.third.net.bytebuddy.agent.ByteBuddyAgent; +import com.fr.third.net.bytebuddy.asm.Advice; +import com.fr.third.net.bytebuddy.dynamic.loading.ClassReloadingStrategy; +import com.fr.third.net.bytebuddy.matcher.ElementMatchers; +import org.junit.Test; + +/** + * 测试一下,通过 redefine 去处理代码时 + * 相应的 advice 应该怎么写 + */ +public class BytebuddyRedefineTest { + + /** + * 测试一下是否可以直接抛出异常 + */ + @Test + public void testThrowException() { + + try { + ByteBuddyAgent.install(); + + new ByteBuddy() + .redefine(TestClass.class) + .visit(Advice.to(TestThrowExceptionAdvice.class).on(ElementMatchers.named("testPrint"))) + .make() + .load(TestClass.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent()); + + TestClass testClass = new TestClass(); + testClass.testPrint(); + } catch (Throwable throwable) { + + } + } + + /** + * 测试是否可以直接传值 + */ + @Test + public void testTransferValue() { + + ByteBuddyAgent.install(); + + new ByteBuddy() + .redefine(TestClass.class) + .visit(Advice.to(TestTransferValueAdvice.class).on(ElementMatchers.named("testPrint"))) + .make() + .load(TestClass.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent()); + + TestClass testClass = new TestClass(); + String print = testClass.testPrint(); + + System.out.println(TestTransferValueAdvice.intField); + System.out.println(TestTransferValueAdvice.stringField); + System.out.println(TestTransferValueAdvice.objectField); + + } + + /** + * 测试是否可以改变返回值 + */ + @Test + public void testModifyReturn() { + + ByteBuddyAgent.install(); + + new ByteBuddy() + .redefine(TestClass.class) + .visit(Advice.to(TestModifyReturnAdvice.class).on(ElementMatchers.named("testPrint"))) + .make() + .load(TestClass.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent()); + + TestClass testClass = new TestClass(); + String print = testClass.testPrint(); + + System.out.println(print); + } + +} \ No newline at end of file diff --git a/designer-base/src/test/java/com/fr/design/record/analyzer/TestClass.java b/designer-base/src/test/java/com/fr/design/record/analyzer/TestClass.java new file mode 100644 index 000000000..e1a2761aa --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/record/analyzer/TestClass.java @@ -0,0 +1,11 @@ +package com.fr.design.record.analyzer; + +/** + * created by Harrison on 2022/03/04 + **/ +public class TestClass { + + public String testPrint() { + return ""; + } +} diff --git a/designer-base/src/test/java/com/fr/design/record/analyzer/TestModifyReturnAdvice.java b/designer-base/src/test/java/com/fr/design/record/analyzer/TestModifyReturnAdvice.java new file mode 100644 index 000000000..7c2dae455 --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/record/analyzer/TestModifyReturnAdvice.java @@ -0,0 +1,29 @@ +package com.fr.design.record.analyzer; + +import com.fr.third.net.bytebuddy.asm.Advice; +import com.fr.third.net.bytebuddy.implementation.bytecode.assign.Assigner; + +import java.lang.reflect.Method; + +/** + * created by Harrison on 2022/03/07 + **/ +public class TestModifyReturnAdvice { + + @Advice.OnMethodEnter(skipOn = Advice.OnDefaultValue.class) + public static int onMethodEnter() throws Exception { + + return 0; + } + + @Advice.OnMethodExit(onThrowable = Exception.class) + public static void onMethodExit(@Advice.This(optional = true, typing = Assigner.Typing.DYNAMIC) Object self, + @Advice.Origin Method method, + @Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args, + @Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object result) throws Exception { + + result = "[test]Modify Return Value"; + + } + +} diff --git a/designer-base/src/test/java/com/fr/design/record/analyzer/TestThrowExceptionAdvice.java b/designer-base/src/test/java/com/fr/design/record/analyzer/TestThrowExceptionAdvice.java new file mode 100644 index 000000000..53c54c28d --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/record/analyzer/TestThrowExceptionAdvice.java @@ -0,0 +1,19 @@ +package com.fr.design.record.analyzer; + +import com.fr.third.net.bytebuddy.asm.Advice; +import com.fr.third.net.bytebuddy.implementation.bytecode.assign.Assigner; + +import java.lang.reflect.Method; + +/** + * created by Harrison on 2022/03/07 + **/ +public class TestThrowExceptionAdvice { + + @Advice.OnMethodExit(onThrowable = Exception.class) + public static void onMethodExit(@Advice.Origin Method method, + @Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] arguments, + @Advice.Thrown(typing = Assigner.Typing.DYNAMIC) Exception e) throws Exception { + throw new RuntimeException("[test] throw exception in advice"); + } +} diff --git a/designer-base/src/test/java/com/fr/design/record/analyzer/TestTransferValueAdvice.java b/designer-base/src/test/java/com/fr/design/record/analyzer/TestTransferValueAdvice.java new file mode 100644 index 000000000..fa0bf6f09 --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/record/analyzer/TestTransferValueAdvice.java @@ -0,0 +1,37 @@ +package com.fr.design.record.analyzer; + +import com.fr.third.net.bytebuddy.asm.Advice; + +/** + * created by Harrison on 2022/03/07 + **/ +public class TestTransferValueAdvice { + + public static int intField; + + public static String stringField; + + public static Object objectField; + + @Advice.OnMethodEnter + public static void onMethodEnter(@Advice.Local("int") int intField, + @Advice.Local("string") String stringField, + @Advice.Local("Object") Object objectField) { + + intField = 10; + stringField = "[test]stringField"; + objectField = "[test]objectField"; + } + + @Advice.OnMethodExit(onThrowable = Exception.class) + public static void onMethodExit(@Advice.Local("int") int intField, + @Advice.Local("string") String stringField, + @Advice.Local("Object") Object objectField) throws Exception { + + TestTransferValueAdvice.intField = intField; + TestTransferValueAdvice.stringField = stringField; + TestTransferValueAdvice.objectField = objectField; + + } + +} diff --git a/designer-realize/src/main/java/com/fr/start/MainDesigner.java b/designer-realize/src/main/java/com/fr/start/MainDesigner.java index ce355076b..5d4055fbc 100644 --- a/designer-realize/src/main/java/com/fr/start/MainDesigner.java +++ b/designer-realize/src/main/java/com/fr/start/MainDesigner.java @@ -136,6 +136,8 @@ public class MainDesigner extends BaseDesigner { } FineLoggerFactory.getLogger().info("Designer started.Time used {} ms", watch.getTime()); watch.stop(); + + } /** From 278ab67f0b884ee76fee67728bdfee4ea01b4e0b Mon Sep 17 00:00:00 2001 From: Harrison Date: Tue, 8 Mar 2022 14:00:22 +0800 Subject: [PATCH 2/8] =?UTF-8?q?feat:=20KERNEL-10354=20bytebuddy=20/=20?= =?UTF-8?q?=E5=8A=A0=E8=A7=A3=E5=AF=86=E6=80=A7=E8=83=BD=E4=BC=98=E5=8C=96?= =?UTF-8?q?=20@Harrison=20=E9=98=B2=E6=AD=A2=E6=95=B4=E4=B8=AA=20UI=20?= =?UTF-8?q?=E5=A0=B5=E5=A1=9E=EF=BC=8C=E9=97=B4=E6=AD=87=E6=80=A7=E8=BF=9B?= =?UTF-8?q?=E8=A1=8C=E8=BD=AC=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../env/LocalDesignerWorkspaceInfo.java | 31 +++---- .../record/analyzer/DesignerAnalyzer.java | 3 +- .../analyzer/DesignerAnalyzerActivator.java | 55 ++++++----- .../analyzer/DesignerAssemblyFactory.java | 91 +++++++++++++++++++ 4 files changed, 136 insertions(+), 44 deletions(-) create mode 100644 designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAssemblyFactory.java diff --git a/designer-base/src/main/java/com/fr/design/env/LocalDesignerWorkspaceInfo.java b/designer-base/src/main/java/com/fr/design/env/LocalDesignerWorkspaceInfo.java index a7d6eb6c1..4a488cb2d 100644 --- a/designer-base/src/main/java/com/fr/design/env/LocalDesignerWorkspaceInfo.java +++ b/designer-base/src/main/java/com/fr/design/env/LocalDesignerWorkspaceInfo.java @@ -1,17 +1,10 @@ package com.fr.design.env; -import com.fr.general.ComparatorUtils; -import com.fr.general.GeneralUtils; -import com.fr.locale.InterProviderFactory; -import com.fr.stable.CoreConstants; -import com.fr.stable.StableUtils; import com.fr.stable.StringUtils; -import com.fr.stable.project.ProjectConstants; import com.fr.stable.xml.XMLPrintWriter; import com.fr.stable.xml.XMLableReader; import com.fr.workspace.connect.WorkspaceConnectionInfo; -import com.fr.workspace.engine.exception.MainVersionNotMatchException; import java.io.File; import java.util.Properties; @@ -101,18 +94,18 @@ public class LocalDesignerWorkspaceInfo implements DesignerWorkspaceInfo { @Override public boolean checkValid(){ File file = new File(this.path); - //判断不是文件夹/路径不在WEB-INF下/代码启动三种情况 - if(!file.isDirectory() || !ComparatorUtils.equals(file.getName(), "WEB-INF") || this.path.startsWith(".")) { - return false; - } - - File engineLib = new File(StableUtils.pathJoin(this.path, ProjectConstants.LIB_NAME, REPORT_ENGINE_JAR)); - // 非安装版本允许自由切换 - boolean notExistLib = !CoreConstants.DOT.equals(StableUtils.getInstallHome()) - && !engineLib.exists(); - if (notExistLib) { - throw new MainVersionNotMatchException(); - } + ////判断不是文件夹/路径不在WEB-INF下/代码启动三种情况 + //if(!file.isDirectory() || !ComparatorUtils.equals(file.getName(), "WEB-INF") || this.path.startsWith(".")) { + // return false; + //} + // + //File engineLib = new File(StableUtils.pathJoin(this.path, ProjectConstants.LIB_NAME, REPORT_ENGINE_JAR)); + //// 非安装版本允许自由切换 + //boolean notExistLib = !CoreConstants.DOT.equals(StableUtils.getInstallHome()) + // && !engineLib.exists(); + //if (notExistLib) { + // throw new MainVersionNotMatchException(); + //} return true; } diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzer.java b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzer.java index fe4b30806..bdd437ac1 100644 --- a/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzer.java +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzer.java @@ -3,7 +3,6 @@ package com.fr.design.record.analyzer; import com.fr.record.analyzer.AnalyzerConfiguration; import com.fr.record.analyzer.AnalyzerUnit; import com.fr.record.analyzer.configuration.AnalyzerAssemblyFactory; -import com.fr.record.analyzer.configuration.impl.RedefineAssemblyFactory; /** * created by Harrison on 2022/03/08 @@ -14,7 +13,7 @@ public class DesignerAnalyzer { public static synchronized void init(AnalyzerAssemblyFactory factory, AnalyzerConfiguration... configurations) { - AnalyzerAssemblyFactory redefineFactory = factory.prepare(RedefineAssemblyFactory.getInstance()); + AnalyzerAssemblyFactory redefineFactory = factory.prepare(DesignerAssemblyFactory.getInstance()); ANALYZER.init(redefineFactory, configurations); } diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java index 60b65b1a1..45c302c26 100644 --- a/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java @@ -2,11 +2,16 @@ package com.fr.design.record.analyzer; import com.fr.base.OptimizeUtil; import com.fr.concurrent.NamedThreadFactory; +import com.fr.design.constants.DesignerLaunchStatus; import com.fr.design.record.analyzer.advice.DBMonitorAdvice; import com.fr.design.record.analyzer.advice.FaultToleranceAdvice; import com.fr.design.record.analyzer.advice.FocusAdvice; import com.fr.design.record.analyzer.advice.MonitorAdvice; import com.fr.design.record.analyzer.advice.PerformancePointAdvice; +import com.fr.event.Event; +import com.fr.event.EventDispatcher; +import com.fr.event.Listener; +import com.fr.event.Null; import com.fr.intelli.metrics.Compute; import com.fr.intelli.record.Focus; import com.fr.intelli.record.PerformancePoint; @@ -15,10 +20,10 @@ import com.fr.module.extension.Prepare; import com.fr.record.analyzer.AnalyzerConfiguration; import com.fr.record.analyzer.AnalyzerKey; import com.fr.record.analyzer.DBMetrics; -import com.fr.record.analyzer.FineAdviceTransformer; import com.fr.record.analyzer.FineAnalyzer; import com.fr.record.analyzer.advice.AnalyzerAdviceConfiguration; import com.fr.record.analyzer.advice.AnalyzerAdviceKey; +import com.fr.record.analyzer.advice.FineAdviceTransformer; import com.fr.record.analyzer.configuration.AnalyzerAssemblyFactory; import com.fr.record.analyzer.configuration.FineAnalyzerAssemblyFactory; import com.fr.stable.collections.CollectionUtils; @@ -38,32 +43,36 @@ public class DesignerAnalyzerActivator extends Activator implements Prepare { public void start() { OptimizeUtil.open(() -> { - ExecutorService es = newSingleThreadExecutor(new NamedThreadFactory("designer-analyzer", true)); - - try { - AnalyzerAssemblyFactory basicFactory = createBasicFactory(); + + AnalyzerAssemblyFactory basicFactory = createBasicFactory(); + + // 兼容逻辑 + List backwardsConfigurations = findMutableBackwards(AnalyzerKey.KEY); + if (!CollectionUtils.isEmpty(backwardsConfigurations)) { + FineAnalyzer.init(basicFactory, backwardsConfigurations.toArray(new AnalyzerConfiguration[0])); + } + + EventDispatcher.listen(DesignerLaunchStatus.STARTUP_COMPLETE, new Listener() { - // 兼容逻辑 - List backwardsConfigurations = findMutableBackwards(AnalyzerKey.KEY); - if (!CollectionUtils.isEmpty(backwardsConfigurations)) { - es.submit(() -> { - FineAnalyzer.init(basicFactory, backwardsConfigurations.toArray(new AnalyzerConfiguration[0])); - }); - } + @Override + public void on(Event event, Null param) { - // 加入 retransform 部分的逻辑 - List adviceConfigurations = findMutable(AnalyzerAdviceKey.KEY); + ExecutorService es = newSingleThreadExecutor(new NamedThreadFactory("designer-analyzer", true)); + try { + // 加入 retransform 部分的逻辑 + List adviceConfigurations = findMutable(AnalyzerAdviceKey.KEY); - if (!CollectionUtils.isEmpty(adviceConfigurations)) { - AnalyzerConfiguration[] configurations = convertConfigurations(adviceConfigurations); - es.submit(() -> { - DesignerAnalyzer.init(basicFactory, configurations); - }); + if (!CollectionUtils.isEmpty(adviceConfigurations)) { + AnalyzerConfiguration[] configurations = convertConfigurations(adviceConfigurations); + es.submit(() -> { + DesignerAnalyzer.init(basicFactory, configurations); + }); + } + } finally { + es.shutdown(); + } } - - } finally { - es.shutdown(); - } + }); }); } diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAssemblyFactory.java b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAssemblyFactory.java new file mode 100644 index 000000000..0c8ffa40e --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAssemblyFactory.java @@ -0,0 +1,91 @@ +package com.fr.design.record.analyzer; + +import com.fr.record.analyzer.configuration.AnalyzerAssemblyFactory; +import com.fr.third.net.bytebuddy.agent.builder.AgentBuilder; + +import java.util.List; +import java.util.Map; + +/** + * 装配 Agent 为后置启动 + *

必须在一个线程中处理 retransform 的事务,否则会阻塞整个的线程,导致效果不佳

+ * + * created by Harrison on 2022/03/07 + **/ +public class DesignerAssemblyFactory implements AnalyzerAssemblyFactory { + + /** + * 每次执行 1 个 class 的 retransform + */ + private static final int FIXED_SIZE = 1; + + /** + * 单位 ms + * 每次间隔 500 ms, 执行一次 + */ + private static final int DELAY_INTERVAL = 500; + + private final AgentBuilder.RedefinitionStrategy.BatchAllocator batchAllocator = AgentBuilder.RedefinitionStrategy.BatchAllocator.ForFixedSize.ofSize(FIXED_SIZE); + + private final AgentBuilder.RedefinitionStrategy.Listener redefinitionListener = new DelayListener(DELAY_INTERVAL); + + public static DesignerAssemblyFactory getInstance() { + return DesignerAssemblyFactoryHolder.INSTANCE; + } + + private static class DesignerAssemblyFactoryHolder { + private static final DesignerAssemblyFactory INSTANCE = new DesignerAssemblyFactory(); + } + + @Override + public AnalyzerAssemblyFactory prepare(Object material) { + + return this; + } + + @Override + public AgentBuilder assembly(AgentBuilder raw) { + + return raw.disableClassFormatChanges() + .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION) + // 每次只 transform 一部分否则会导致 UI 变慢 + .with(batchAllocator) + .with(redefinitionListener) + .with(AgentBuilder.InitializationStrategy.NoOp.INSTANCE) + .with(AgentBuilder.TypeStrategy.Default.REDEFINE); + } + + private class DelayListener implements AgentBuilder.RedefinitionStrategy.Listener { + + /** + * 单位 ms + */ + private final int interval; + + public DelayListener(int interval) { + this.interval = interval; + } + + /** + * 执行完后,等待一段时间再执行。 + */ + @Override + public void onBatch(int index, List> batch, List> types) { + + try { + Thread.sleep(interval); + } catch (Exception ignore) { + } + } + + @Override + public Iterable>> onError(int index, List> batch, Throwable throwable, List> types) { + return null; + } + + @Override + public void onComplete(int amount, List> types, Map>, Throwable> failures) { + + } + } +} From 5d37a22e48f83b8f53de3316f92ca9e827fd928c Mon Sep 17 00:00:00 2001 From: Harrison Date: Tue, 8 Mar 2022 14:57:31 +0800 Subject: [PATCH 3/8] =?UTF-8?q?feat:=20KERNEL-10354=20bytebuddy=20/=20?= =?UTF-8?q?=E5=8A=A0=E8=A7=A3=E5=AF=86=E6=80=A7=E8=83=BD=E4=BC=98=E5=8C=96?= =?UTF-8?q?=20@Harrison=201=E3=80=81=E6=9B=BF=E6=8D=A2=20listener,=20?= =?UTF-8?q?=E4=BB=8E=E8=80=8C=E6=89=93=E5=8D=B0=E4=B8=8D=E5=90=8C=E7=9A=84?= =?UTF-8?q?=E9=80=BB=E8=BE=91=202=E3=80=81=E4=BF=AE=E5=A4=8D=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E7=9A=84=20transformer=20=E7=9A=84=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E3=80=82=E8=AE=A9=20Designer-Analyzer=20=E5=8E=BB=E5=A4=84?= =?UTF-8?q?=E7=90=86=E9=BB=98=E8=AE=A4=E7=9A=84=E9=80=BB=E8=BE=91=EF=BC=8C?= =?UTF-8?q?=E8=80=8C=E9=9D=9E=20Fine-Analyzer=20=E5=8E=BB=E5=A4=84?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../record/analyzer/DesignerAnalyzer.java | 26 +++++++++++++- .../analyzer/DesignerAnalyzerActivator.java | 4 +-- .../analyzer/DesignerAnalyzerListener.java | 23 ++++++++++++ .../analyzer/advice/DBMonitorAdvice.java | 8 +---- .../analyzer/advice/FaultToleranceAdvice.java | 4 +-- .../record/analyzer/advice/FocusAdvice.java | 1 - .../record/analyzer/advice/MonitorAdvice.java | 10 +++--- .../advice/PerformancePointAdvice.java | 7 +--- .../record/analyzer/advice/TimeAdvice.java | 36 +++++++++++++++++++ .../record/analyzer/advice/TrackAdvice.java | 25 +++++++++++++ 10 files changed, 118 insertions(+), 26 deletions(-) create mode 100644 designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerListener.java create mode 100644 designer-base/src/main/java/com/fr/design/record/analyzer/advice/TimeAdvice.java create mode 100644 designer-base/src/main/java/com/fr/design/record/analyzer/advice/TrackAdvice.java diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzer.java b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzer.java index bdd437ac1..2397f0548 100644 --- a/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzer.java +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzer.java @@ -1,8 +1,19 @@ package com.fr.design.record.analyzer; +import com.fr.design.record.analyzer.advice.TimeAdvice; +import com.fr.design.record.analyzer.advice.TrackAdvice; import com.fr.record.analyzer.AnalyzerConfiguration; import com.fr.record.analyzer.AnalyzerUnit; +import com.fr.record.analyzer.Assistant; +import com.fr.record.analyzer.Metrics; +import com.fr.record.analyzer.Track; import com.fr.record.analyzer.configuration.AnalyzerAssemblyFactory; +import com.fr.stable.ArrayUtils; +import com.fr.third.net.bytebuddy.asm.Advice; +import com.fr.third.net.bytebuddy.description.type.TypeDescription; +import com.fr.third.net.bytebuddy.dynamic.DynamicType; +import com.fr.third.net.bytebuddy.matcher.ElementMatchers; +import com.fr.third.net.bytebuddy.utility.JavaModule; /** * created by Harrison on 2022/03/08 @@ -15,7 +26,20 @@ public class DesignerAnalyzer { AnalyzerAssemblyFactory redefineFactory = factory.prepare(DesignerAssemblyFactory.getInstance()); - ANALYZER.init(redefineFactory, configurations); + AnalyzerConfiguration defaultConfiguration = AnalyzerConfiguration.create(new Assistant() { + @Override + public DynamicType.Builder supply(DynamicType.Builder builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule module) { + return builder + .visit(Advice.to(TimeAdvice.class).on(ElementMatchers.isAnnotatedWith(Metrics.class))) + .visit(Advice.to(TrackAdvice.class).on(ElementMatchers.isAnnotatedWith(Track.class))); + } + }); + AnalyzerConfiguration[] allConfigurations = ArrayUtils.add(configurations, defaultConfiguration); + + // 准备监听 + ANALYZER.setAgentListener(new DesignerAnalyzerListener()); + + ANALYZER.init(redefineFactory, allConfigurations); } } diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java index 45c302c26..61ce3cdad 100644 --- a/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java @@ -23,7 +23,7 @@ import com.fr.record.analyzer.DBMetrics; import com.fr.record.analyzer.FineAnalyzer; import com.fr.record.analyzer.advice.AnalyzerAdviceConfiguration; import com.fr.record.analyzer.advice.AnalyzerAdviceKey; -import com.fr.record.analyzer.advice.FineAdviceTransformer; +import com.fr.record.analyzer.advice.FineAdviceAssistant; import com.fr.record.analyzer.configuration.AnalyzerAssemblyFactory; import com.fr.record.analyzer.configuration.FineAnalyzerAssemblyFactory; import com.fr.stable.collections.CollectionUtils; @@ -80,7 +80,7 @@ public class DesignerAnalyzerActivator extends Activator implements Prepare { private AnalyzerConfiguration[] convertConfigurations(List list) { return list.stream() - .map((e) -> AnalyzerConfiguration.create(e.getMatcher(), new FineAdviceTransformer(e.getMatcher(), e.getAdviceClass()))) + .map((e) -> AnalyzerConfiguration.create(new FineAdviceAssistant(e.getMatcher(), e.getAdviceClass()))) .toArray(AnalyzerConfiguration[]::new); } diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerListener.java b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerListener.java new file mode 100644 index 000000000..8db3a395f --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerListener.java @@ -0,0 +1,23 @@ +package com.fr.design.record.analyzer; + +import com.fr.log.FineLoggerFactory; +import com.fr.third.net.bytebuddy.agent.builder.AgentBuilder; +import com.fr.third.net.bytebuddy.description.type.TypeDescription; +import com.fr.third.net.bytebuddy.dynamic.DynamicType; +import com.fr.third.net.bytebuddy.utility.JavaModule; + +/** + * created by Harrison on 2022/03/08 + **/ +public class DesignerAnalyzerListener extends AgentBuilder.Listener.Adapter { + + @Override + public void onTransformation(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, boolean loaded, DynamicType dynamicType) { + FineLoggerFactory.getLogger().debug("Designer-Analyzer transform successfully:{}", typeDescription); + } + + @Override + public void onError(String typeName, ClassLoader classLoader, JavaModule module, boolean loaded, Throwable throwable) { + FineLoggerFactory.getLogger().error("Designer-Analyzer transform error:" + typeName); + } +} diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/advice/DBMonitorAdvice.java b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/DBMonitorAdvice.java index 9b22e07b2..aba2c2bdf 100644 --- a/designer-base/src/main/java/com/fr/design/record/analyzer/advice/DBMonitorAdvice.java +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/DBMonitorAdvice.java @@ -7,19 +7,13 @@ import com.fr.measure.metric.DBMetric; import com.fr.third.net.bytebuddy.asm.Advice; import com.fr.third.net.bytebuddy.implementation.bytecode.assign.Assigner; -import java.lang.reflect.Method; - /** * created by Harrison on 2022/03/07 **/ public class DBMonitorAdvice implements DesignerAnalyzerAdvice { @Advice.OnMethodExit(onThrowable = Exception.class) - public static void onMethodExit(@Advice.This(optional = true, typing = Assigner.Typing.DYNAMIC) Object self, - @Advice.Origin Method method, - @Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args, - @Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object result, - @Advice.Thrown(typing = Assigner.Typing.DYNAMIC) Exception e) { + public static void onMethodExit(@Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args) { if (args.length > 1 && args[1] instanceof DataModel) { DBMetric meter = ((DataModel) args[1]).getMetric(); diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/advice/FaultToleranceAdvice.java b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/FaultToleranceAdvice.java index f0d089b3e..a8198363e 100644 --- a/designer-base/src/main/java/com/fr/design/record/analyzer/advice/FaultToleranceAdvice.java +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/FaultToleranceAdvice.java @@ -15,9 +15,7 @@ import java.util.concurrent.Callable; public class FaultToleranceAdvice implements DesignerAnalyzerAdvice { @Advice.OnMethodEnter(skipOn = Advice.OnDefaultValue.class) - public static int onMethodEnter(@Advice.This(optional = true, typing = Assigner.Typing.DYNAMIC) Object self, - @Advice.Origin Method method, - @Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args) throws Exception { + public static int onMethodEnter() throws Exception { return 0; } diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/advice/FocusAdvice.java b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/FocusAdvice.java index 653ce9109..7bc79cc6c 100644 --- a/designer-base/src/main/java/com/fr/design/record/analyzer/advice/FocusAdvice.java +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/FocusAdvice.java @@ -19,7 +19,6 @@ public class FocusAdvice implements DesignerAnalyzerAdvice { @Advice.OnMethodExit(onThrowable = Exception.class) public static void onMethodExit(@Advice.Origin Method method, - @Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] arguments, @Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object result) throws Exception { if (FocusPolicy.IGNORE == result) { diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/advice/MonitorAdvice.java b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/MonitorAdvice.java index 826cc1e64..8b6d0dbcd 100644 --- a/designer-base/src/main/java/com/fr/design/record/analyzer/advice/MonitorAdvice.java +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/MonitorAdvice.java @@ -36,11 +36,10 @@ public class MonitorAdvice implements DesignerAnalyzerAdvice { private static final int MIN_ERROR_CODE = 10000000; @Advice.OnMethodEnter - public static void onMethodEnter(@Advice.This(optional = true, typing = Assigner.Typing.DYNAMIC) Object self, - @Advice.Origin Method method, - @Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args, - @Advice.Local("startTime") Long startTime, - @Advice.Local("registeredSession") Boolean registeredSession) { + public static void onMethodEnter(@Advice.Origin Method method, + @Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args, + @Advice.Local("startTime") Long startTime, + @Advice.Local("registeredSession") Boolean registeredSession) { startTime = (System.currentTimeMillis()); registeredSession = (findSessionAnnotation(method, args)); @@ -50,7 +49,6 @@ public class MonitorAdvice implements DesignerAnalyzerAdvice { public static void onMethodExit(@Advice.This(optional = true, typing = Assigner.Typing.DYNAMIC) Object self, @Advice.Origin Method method, @Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args, - @Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object result, @Advice.Thrown(typing = Assigner.Typing.DYNAMIC) Exception e, @Advice.Local("startTime") Long startTime, @Advice.Local("registeredSession") Boolean registeredSession) throws Exception { diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/advice/PerformancePointAdvice.java b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/PerformancePointAdvice.java index 80aab8bd1..5b54f6653 100644 --- a/designer-base/src/main/java/com/fr/design/record/analyzer/advice/PerformancePointAdvice.java +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/PerformancePointAdvice.java @@ -20,10 +20,7 @@ import java.util.List; public class PerformancePointAdvice implements DesignerAnalyzerAdvice { @Advice.OnMethodEnter - public static void onMethodEnter(@Advice.This(optional = true, typing = Assigner.Typing.DYNAMIC) Object self, - @Advice.Origin Method method, - @Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args, - @Advice.Local("startTime") Long startTime) { + public static void onMethodEnter(@Advice.Local("startTime") Long startTime) { startTime = (System.currentTimeMillis()); } @@ -32,8 +29,6 @@ public class PerformancePointAdvice implements DesignerAnalyzerAdvice { public static void onMethodExit(@Advice.This(optional = true, typing = Assigner.Typing.DYNAMIC) Object self, @Advice.Origin Method method, @Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args, - @Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object result, - @Advice.Thrown(typing = Assigner.Typing.DYNAMIC) Exception e, @Advice.Local("startTime") Long startTime) { PerformancePoint point = method.getAnnotation(PerformancePoint.class); diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/advice/TimeAdvice.java b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/TimeAdvice.java new file mode 100644 index 000000000..b60b5c2d3 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/TimeAdvice.java @@ -0,0 +1,36 @@ +package com.fr.design.record.analyzer.advice; + +import com.fr.design.record.analyzer.DesignerAnalyzerAdvice; +import com.fr.log.FineLoggerFactory; +import com.fr.record.analyzer.Metrics; +import com.fr.third.net.bytebuddy.asm.Advice; + +import java.lang.reflect.Method; + +/** + * created by Harrison on 2022/03/08 + **/ +public class TimeAdvice implements DesignerAnalyzerAdvice { + + + @Advice.OnMethodEnter + public static void onMethodEnter(@Advice.Local("startTime") Long startTime) { + + startTime = (System.currentTimeMillis()); + } + + @Advice.OnMethodExit(onThrowable = Exception.class) + public static void onMethodExit(@Advice.Origin Method method, + @Advice.Local("startTime") Long startTime) { + + Metrics metrics = method.getAnnotation(Metrics.class); + Object prefix; + String description = metrics.description(); + if ("".equals(description)) { + prefix = method.getDeclaringClass().getName() + "#" + method.getName(); + } else { + prefix = description; + } + FineLoggerFactory.getLogger().info("{} took {} ms.", prefix, System.currentTimeMillis() - startTime); + } +} diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/advice/TrackAdvice.java b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/TrackAdvice.java new file mode 100644 index 000000000..bdebecc60 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/TrackAdvice.java @@ -0,0 +1,25 @@ +package com.fr.design.record.analyzer.advice; + +import com.fr.intelli.record.MetricRegistry; +import com.fr.third.javax.persistence.Entity; +import com.fr.third.net.bytebuddy.asm.Advice; +import com.fr.third.net.bytebuddy.implementation.bytecode.assign.Assigner; + +import java.util.List; + +/** + * created by Harrison on 2022/03/08 + **/ +public class TrackAdvice { + + @Advice.OnMethodExit(onThrowable = Exception.class) + public static void onMethodExit(@Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object result) { + + if (result != null) { + Class clazz = result.getClass(); + if (clazz.getAnnotation(Entity.class) != null || result instanceof List) { + MetricRegistry.getMetric().submit(result); + } + } + } +} From 56f1f97761ec80bc8e6edda7f66d13ba4f9aa487 Mon Sep 17 00:00:00 2001 From: Harrison Date: Tue, 8 Mar 2022 15:04:54 +0800 Subject: [PATCH 4/8] =?UTF-8?q?feat:=20KERNEL-10354=20bytebuddy=20/=20?= =?UTF-8?q?=E5=8A=A0=E8=A7=A3=E5=AF=86=E6=80=A7=E8=83=BD=E4=BC=98=E5=8C=96?= =?UTF-8?q?=20@Harrison=201.=20=E5=88=A0=E6=8E=89=E4=B8=80=E9=83=A8?= =?UTF-8?q?=E5=88=86=E4=BB=A3=E7=A0=81=EF=BC=8C=E7=B2=BE=E7=AE=80=E6=95=B4?= =?UTF-8?q?=E4=BD=93=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../analyzer/DesignerAnalyzerActivator.java | 17 ++++++++--------- .../analyzer/DesignerAssemblyFactory.java | 4 ++-- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java index 61ce3cdad..f2e57ef7d 100644 --- a/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java @@ -21,7 +21,6 @@ import com.fr.record.analyzer.AnalyzerConfiguration; import com.fr.record.analyzer.AnalyzerKey; import com.fr.record.analyzer.DBMetrics; import com.fr.record.analyzer.FineAnalyzer; -import com.fr.record.analyzer.advice.AnalyzerAdviceConfiguration; import com.fr.record.analyzer.advice.AnalyzerAdviceKey; import com.fr.record.analyzer.advice.FineAdviceAssistant; import com.fr.record.analyzer.configuration.AnalyzerAssemblyFactory; @@ -60,7 +59,7 @@ public class DesignerAnalyzerActivator extends Activator implements Prepare { ExecutorService es = newSingleThreadExecutor(new NamedThreadFactory("designer-analyzer", true)); try { // 加入 retransform 部分的逻辑 - List adviceConfigurations = findMutable(AnalyzerAdviceKey.KEY); + List adviceConfigurations = findMutable(AnalyzerAdviceKey.KEY); if (!CollectionUtils.isEmpty(adviceConfigurations)) { AnalyzerConfiguration[] configurations = convertConfigurations(adviceConfigurations); @@ -77,10 +76,10 @@ public class DesignerAnalyzerActivator extends Activator implements Prepare { } @NotNull - private AnalyzerConfiguration[] convertConfigurations(List list) { + private AnalyzerConfiguration[] convertConfigurations(List list) { return list.stream() - .map((e) -> AnalyzerConfiguration.create(new FineAdviceAssistant(e.getMatcher(), e.getAdviceClass()))) + .map(AnalyzerConfiguration::create) .toArray(AnalyzerConfiguration[]::new); } @@ -92,27 +91,27 @@ public class DesignerAnalyzerActivator extends Activator implements Prepare { @Override public void prepare() { - addMutable(AnalyzerAdviceKey.KEY, AnalyzerAdviceConfiguration.create( + addMutable(AnalyzerAdviceKey.KEY, FineAdviceAssistant.create( ElementMatchers.isAnnotatedWith(Focus.class), FocusAdvice.class )); - addMutable(AnalyzerAdviceKey.KEY, AnalyzerAdviceConfiguration.create( + addMutable(AnalyzerAdviceKey.KEY, FineAdviceAssistant.create( ElementMatchers.isAnnotatedWith(Compute.class), MonitorAdvice.class )); - addMutable(AnalyzerAdviceKey.KEY, AnalyzerAdviceConfiguration.create( + addMutable(AnalyzerAdviceKey.KEY, FineAdviceAssistant.create( ElementMatchers.isAnnotatedWith(DBMetrics.class), DBMonitorAdvice.class )); - addMutable(AnalyzerAdviceKey.KEY, AnalyzerAdviceConfiguration.create( + addMutable(AnalyzerAdviceKey.KEY, FineAdviceAssistant.create( ElementMatchers.isAnnotatedWith(PerformancePoint.class), PerformancePointAdvice.class )); - addMutable(AnalyzerAdviceKey.KEY, AnalyzerAdviceConfiguration.create( + addMutable(AnalyzerAdviceKey.KEY, FineAdviceAssistant.create( ElementMatchers.isAnnotatedWith(FaultTolerance.class), FaultToleranceAdvice.class )); diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAssemblyFactory.java b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAssemblyFactory.java index 0c8ffa40e..2e5fdc408 100644 --- a/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAssemblyFactory.java +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAssemblyFactory.java @@ -12,7 +12,7 @@ import java.util.Map; * * created by Harrison on 2022/03/07 **/ -public class DesignerAssemblyFactory implements AnalyzerAssemblyFactory { +public class DesignerAssemblyFactory implements AnalyzerAssemblyFactory { /** * 每次执行 1 个 class 的 retransform @@ -38,7 +38,7 @@ public class DesignerAssemblyFactory implements AnalyzerAssemblyFactory { } @Override - public AnalyzerAssemblyFactory prepare(Object material) { + public AnalyzerAssemblyFactory prepare(Void material) { return this; } From 823bf0d328b2b1214f3ae4720a2309de83f43bae Mon Sep 17 00:00:00 2001 From: Harrison Date: Tue, 8 Mar 2022 15:58:55 +0800 Subject: [PATCH 5/8] =?UTF-8?q?feat:=20KERNEL-10354=20bytebuddy=20/=20?= =?UTF-8?q?=E5=8A=A0=E8=A7=A3=E5=AF=86=E6=80=A7=E8=83=BD=E4=BC=98=E5=8C=96?= =?UTF-8?q?=20@Harrison=20=E6=B7=BB=E5=8A=A0=E5=8D=95=E5=85=83=E6=B5=8B?= =?UTF-8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fr/design/record/analyzer/DesignerAnalyzerActivator.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java index f2e57ef7d..0a83d81c2 100644 --- a/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java @@ -48,9 +48,11 @@ public class DesignerAnalyzerActivator extends Activator implements Prepare { // 兼容逻辑 List backwardsConfigurations = findMutableBackwards(AnalyzerKey.KEY); if (!CollectionUtils.isEmpty(backwardsConfigurations)) { - FineAnalyzer.init(basicFactory, backwardsConfigurations.toArray(new AnalyzerConfiguration[0])); + // 直接初始化,不添加默认值,防止和下面的冲突 + FineAnalyzer.initDirectly(basicFactory, backwardsConfigurations.toArray(new AnalyzerConfiguration[0])); } + // 等页面完全打开后,再进行 retransform, 别影响了启动速度 EventDispatcher.listen(DesignerLaunchStatus.STARTUP_COMPLETE, new Listener() { @Override From 091fc1ee64029730ab6ef7a41bf9fbb534e6dcfb Mon Sep 17 00:00:00 2001 From: Harrison Date: Tue, 8 Mar 2022 16:30:31 +0800 Subject: [PATCH 6/8] =?UTF-8?q?feat:=20KERNEL-10354=20bytebuddy=20/=20?= =?UTF-8?q?=E5=8A=A0=E8=A7=A3=E5=AF=86=E6=80=A7=E8=83=BD=E4=BC=98=E5=8C=96?= =?UTF-8?q?=20@Harrison=20=E5=8A=A0=E5=85=A5=E9=83=A8=E5=88=86=20bytebuddy?= =?UTF-8?q?=20=E7=9B=B8=E5=85=B3=E7=9A=84=E5=8D=95=E5=85=83=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=EF=BC=8C=E5=B8=AE=E5=8A=A9=E7=90=86=E8=A7=A3=20advice?= =?UTF-8?q?=20=E7=9B=B8=E5=85=B3=E7=9A=84=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../record/analyzer/BytebuddyRedefineTest.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/designer-base/src/test/java/com/fr/design/record/analyzer/BytebuddyRedefineTest.java b/designer-base/src/test/java/com/fr/design/record/analyzer/BytebuddyRedefineTest.java index f9ec6e21e..aade4591e 100644 --- a/designer-base/src/test/java/com/fr/design/record/analyzer/BytebuddyRedefineTest.java +++ b/designer-base/src/test/java/com/fr/design/record/analyzer/BytebuddyRedefineTest.java @@ -5,6 +5,7 @@ import com.fr.third.net.bytebuddy.agent.ByteBuddyAgent; import com.fr.third.net.bytebuddy.asm.Advice; import com.fr.third.net.bytebuddy.dynamic.loading.ClassReloadingStrategy; import com.fr.third.net.bytebuddy.matcher.ElementMatchers; +import org.junit.Assert; import org.junit.Test; /** @@ -31,7 +32,7 @@ public class BytebuddyRedefineTest { TestClass testClass = new TestClass(); testClass.testPrint(); } catch (Throwable throwable) { - + Assert.assertNotNull("expected throw exception", throwable); } } @@ -52,9 +53,9 @@ public class BytebuddyRedefineTest { TestClass testClass = new TestClass(); String print = testClass.testPrint(); - System.out.println(TestTransferValueAdvice.intField); - System.out.println(TestTransferValueAdvice.stringField); - System.out.println(TestTransferValueAdvice.objectField); + Assert.assertEquals(10, TestTransferValueAdvice.intField); + Assert.assertEquals("[test]stringField", TestTransferValueAdvice.stringField); + Assert.assertEquals("[test]objectField", TestTransferValueAdvice.objectField); } @@ -75,7 +76,8 @@ public class BytebuddyRedefineTest { TestClass testClass = new TestClass(); String print = testClass.testPrint(); - System.out.println(print); + Assert.assertEquals("[test]Modify Return Value", print); + } } \ No newline at end of file From 2b8b7a30c2a31dc7e2841cc4dd58d7f9372a9508 Mon Sep 17 00:00:00 2001 From: Harrison Date: Tue, 8 Mar 2022 16:33:14 +0800 Subject: [PATCH 7/8] =?UTF-8?q?=E6=97=A0=20JIRA=20=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=EF=BC=8C=E6=81=A2=E5=A4=8D=E9=83=A8=E5=88=86=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- designer-realize/src/main/java/com/fr/start/MainDesigner.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/designer-realize/src/main/java/com/fr/start/MainDesigner.java b/designer-realize/src/main/java/com/fr/start/MainDesigner.java index 66b548797..e29a4e804 100644 --- a/designer-realize/src/main/java/com/fr/start/MainDesigner.java +++ b/designer-realize/src/main/java/com/fr/start/MainDesigner.java @@ -135,8 +135,6 @@ public class MainDesigner extends BaseDesigner { } FineLoggerFactory.getLogger().info("Designer started.Time used {} ms", watch.getTime()); watch.stop(); - - } /** From 4872caf558c2114e59371900fb99894a1d5e0324 Mon Sep 17 00:00:00 2001 From: Harrison Date: Tue, 8 Mar 2022 16:36:37 +0800 Subject: [PATCH 8/8] =?UTF-8?q?=E6=97=A0=20JIRA=20=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=EF=BC=8C=E6=81=A2=E5=A4=8D=E9=83=A8=E5=88=86=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../env/LocalDesignerWorkspaceInfo.java | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/designer-base/src/main/java/com/fr/design/env/LocalDesignerWorkspaceInfo.java b/designer-base/src/main/java/com/fr/design/env/LocalDesignerWorkspaceInfo.java index 4a488cb2d..ec8d997c3 100644 --- a/designer-base/src/main/java/com/fr/design/env/LocalDesignerWorkspaceInfo.java +++ b/designer-base/src/main/java/com/fr/design/env/LocalDesignerWorkspaceInfo.java @@ -1,9 +1,14 @@ package com.fr.design.env; +import com.fr.general.ComparatorUtils; +import com.fr.stable.CoreConstants; +import com.fr.stable.StableUtils; import com.fr.stable.StringUtils; +import com.fr.stable.project.ProjectConstants; import com.fr.stable.xml.XMLPrintWriter; import com.fr.stable.xml.XMLableReader; import com.fr.workspace.connect.WorkspaceConnectionInfo; +import com.fr.workspace.engine.exception.MainVersionNotMatchException; import java.io.File; import java.util.Properties; @@ -94,18 +99,18 @@ public class LocalDesignerWorkspaceInfo implements DesignerWorkspaceInfo { @Override public boolean checkValid(){ File file = new File(this.path); - ////判断不是文件夹/路径不在WEB-INF下/代码启动三种情况 - //if(!file.isDirectory() || !ComparatorUtils.equals(file.getName(), "WEB-INF") || this.path.startsWith(".")) { - // return false; - //} - // - //File engineLib = new File(StableUtils.pathJoin(this.path, ProjectConstants.LIB_NAME, REPORT_ENGINE_JAR)); - //// 非安装版本允许自由切换 - //boolean notExistLib = !CoreConstants.DOT.equals(StableUtils.getInstallHome()) - // && !engineLib.exists(); - //if (notExistLib) { - // throw new MainVersionNotMatchException(); - //} + //判断不是文件夹/路径不在WEB-INF下/代码启动三种情况 + if(!file.isDirectory() || !ComparatorUtils.equals(file.getName(), "WEB-INF") || this.path.startsWith(".")) { + return false; + } + + File engineLib = new File(StableUtils.pathJoin(this.path, ProjectConstants.LIB_NAME, REPORT_ENGINE_JAR)); + // 非安装版本允许自由切换 + boolean notExistLib = !CoreConstants.DOT.equals(StableUtils.getInstallHome()) + && !engineLib.exists(); + if (notExistLib) { + throw new MainVersionNotMatchException(); + } return true; }