You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2019/07/18 06:49:22 UTC
[skywalking] 05/13: Finish metrics generation.
This is an automated email from the ASF dual-hosted git repository.
wusheng pushed a commit to branch rt-oal
in repository https://gitbox.apache.org/repos/asf/skywalking.git
commit cf098be65cc8c5a30bddb0831f882410677fe392
Author: Wu Sheng <wu...@foxmail.com>
AuthorDate: Wed Jul 17 15:30:52 2019 +0800
Finish metrics generation.
---
.../org/apache/skywalking/oal/rt/OALRuntime.java | 132 +++++++++++++++++----
.../code-templates/metrics-builder/data2Map.ftl | 30 +++++
.../code-templates/metrics-builder/map2Data.ftl | 22 ++++
3 files changed, 161 insertions(+), 23 deletions(-)
diff --git a/oap-server/oal-rt/src/main/java/org/apache/skywalking/oal/rt/OALRuntime.java b/oap-server/oal-rt/src/main/java/org/apache/skywalking/oal/rt/OALRuntime.java
index e2a2426..d4f5268 100644
--- a/oap-server/oal-rt/src/main/java/org/apache/skywalking/oal/rt/OALRuntime.java
+++ b/oap-server/oal-rt/src/main/java/org/apache/skywalking/oal/rt/OALRuntime.java
@@ -20,10 +20,11 @@ package org.apache.skywalking.oal.rt;
import freemarker.template.Configuration;
import freemarker.template.Version;
+import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
import java.io.IOException;
-import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringWriter;
import java.nio.charset.Charset;
@@ -40,12 +41,12 @@ import javassist.CtNewMethod;
import javassist.NotFoundException;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.ClassFile;
-import javassist.bytecode.ClassFilePrinter;
import javassist.bytecode.ConstPool;
import javassist.bytecode.annotation.Annotation;
import javassist.bytecode.annotation.ClassMemberValue;
import javassist.bytecode.annotation.IntegerMemberValue;
import javassist.bytecode.annotation.StringMemberValue;
+import org.apache.commons.io.FileUtils;
import org.apache.skywalking.oal.rt.meta.MetaReader;
import org.apache.skywalking.oal.rt.meta.MetaSettings;
import org.apache.skywalking.oal.rt.output.AllDispatcherContext;
@@ -82,9 +83,13 @@ public class OALRuntime implements OALEngine {
private static final String DYNAMIC_METRICS_CLASS_PACKAGE = "org.apache.skywalking.oal.rt.metrics.";
private static final String DYNAMIC_METRICS_BUILDER_CLASS_PACKAGE = "org.apache.skywalking.oal.rt.metrics.builder";
private static final String WITH_METADATA_INTERFACE = "org.apache.skywalking.oap.server.core.analysis.metrics.WithMetadata";
+ private static final String STORAGE_BUILDER_INTERFACE = "org.apache.skywalking.oap.server.core.storage.StorageBuilder";
+ private static final String SOURCE_DISPATCHER_INTERFACE = "org.apache.skywalking.oap.server.core.analysis.SourceDispatcher";
private static final String METRICS_STREAM_PROCESSOR = "org.apache.skywalking.oap.server.core.analysis.worker.MetricsStreamProcessor";
private static final String[] METRICS_CLASS_METHODS =
{"id", "hashCode", "remoteHashCode", "equals", "serialize", "deserialize", "getMeta", "toDay"};
+ private static final String[] METRICS_BUILDER_CLASS_METHODS =
+ {"data2Map", "map2Data"};
private final ClassPool classPool;
private ClassLoader currentClassLoader;
private Configuration configuration;
@@ -106,6 +111,8 @@ public class OALRuntime implements OALEngine {
}
@Override public void start(ClassLoader currentClassLoader) throws ModuleStartException, OALCompileException {
+ prepareRTTempFoler();
+
this.currentClassLoader = currentClassLoader;
Reader read;
try {
@@ -156,19 +163,27 @@ public class OALRuntime implements OALEngine {
}
+ /**
+ * Generate metrics class, and inject it to classloader
+ *
+ * @param metricsStmt
+ * @return
+ * @throws OALCompileException
+ */
private Class generateMetricsClass(AnalysisResult metricsStmt) throws OALCompileException {
+ String className = metricsClassName(metricsStmt, false);
CtClass parentMetricsClass = null;
try {
parentMetricsClass = classPool.get(METRICS_FUNCTION_PACKAGE + metricsStmt.getMetricsClassName());
} catch (NotFoundException e) {
- logger.error("Can't find parent class for " + metricsStmt.getMetricsName() + ".", e);
+ logger.error("Can't find parent class for " + className + ".", e);
throw new OALCompileException(e.getMessage(), e);
}
- CtClass metricsClass = classPool.makeClass(metricsClassName(metricsStmt), parentMetricsClass);
+ CtClass metricsClass = classPool.makeClass(metricsClassName(metricsStmt, true), parentMetricsClass);
try {
metricsClass.addInterface(classPool.get(WITH_METADATA_INTERFACE));
} catch (NotFoundException e) {
- logger.error("Can't find WithMetadata interface for " + metricsStmt.getMetricsName() + ".", e);
+ logger.error("Can't find WithMetadata interface for " + className + ".", e);
throw new OALCompileException(e.getMessage(), e);
}
@@ -179,10 +194,10 @@ public class OALRuntime implements OALEngine {
* Create empty construct
*/
try {
- CtConstructor defaultConstructor = CtNewConstructor.make("public " + metricsStmt.getMetricsName() + "Metrics() {}", metricsClass);
+ CtConstructor defaultConstructor = CtNewConstructor.make("public " + className + "() {}", metricsClass);
metricsClass.addConstructor(defaultConstructor);
} catch (CannotCompileException e) {
- logger.error("Can't add empty constructor in " + metricsStmt.getMetricsName() + ".", e);
+ logger.error("Can't add empty constructor in " + className + ".", e);
throw new OALCompileException(e.getMessage(), e);
}
@@ -219,7 +234,7 @@ public class OALRuntime implements OALEngine {
newField.getFieldInfo().addAttribute(annotationsAttribute);
} catch (CannotCompileException e) {
- logger.error("Can't add field(including set/get) " + field.getFieldName() + " in " + metricsStmt.getMetricsName() + ".", e);
+ logger.error("Can't add field(including set/get) " + field.getFieldName() + " in " + className + ".", e);
throw new OALCompileException(e.getMessage(), e);
}
}
@@ -233,7 +248,7 @@ public class OALRuntime implements OALEngine {
configuration.getTemplate("metrics/" + method + ".ftl").process(metricsStmt, methodEntity);
metricsClass.addMethod(CtNewMethod.make(methodEntity.toString(), metricsClass));
} catch (Exception e) {
- logger.error("Can't generate method " + method + " for " + metricsStmt.getMetricsName() + ".", e);
+ logger.error("Can't generate method " + method + " for " + className + ".", e);
throw new OALCompileException(e.getMessage(), e);
}
}
@@ -247,7 +262,7 @@ public class OALRuntime implements OALEngine {
Annotation streamAnnotation = new Annotation(Stream.class.getName(), constPool);
streamAnnotation.addMemberValue("name", new StringMemberValue(metricsStmt.getTableName(), constPool));
streamAnnotation.addMemberValue("scopeId", new IntegerMemberValue(constPool, metricsStmt.getSourceScopeId()));
- streamAnnotation.addMemberValue("builder", new ClassMemberValue(metricsBuilderClassName(metricsStmt), constPool));
+ streamAnnotation.addMemberValue("builder", new ClassMemberValue(metricsBuilderClassName(metricsStmt, true), constPool));
streamAnnotation.addMemberValue("processor", new ClassMemberValue(METRICS_STREAM_PROCESSOR, constPool));
annotationsAttribute.addAnnotation(streamAnnotation);
@@ -257,26 +272,76 @@ public class OALRuntime implements OALEngine {
try {
targetClass = metricsClass.toClass(currentClassLoader, null);
} catch (CannotCompileException e) {
- logger.error("Can't compile/load " + metricsStmt.getMetricsName() + ".", e);
+ logger.error("Can't compile/load " + className + ".", e);
throw new OALCompileException(e.getMessage(), e);
}
logger.debug("Generate metrics class, " + metricsClass.getName());
- writeGeneratedFile(metricsClassClassFile, metricsClass.getSimpleName());
+ writeGeneratedFile(metricsClass, metricsClass.getSimpleName(), "metrics");
return targetClass;
}
+ /**
+ * Generate metrics class builder and inject it to classloader
+ *
+ * @param metricsStmt
+ * @throws OALCompileException
+ */
private void generateMetricsBuilderClass(AnalysisResult metricsStmt) throws OALCompileException {
+ String className = metricsBuilderClassName(metricsStmt, false);
+ CtClass metricsBuilderClass = classPool.makeClass(metricsBuilderClassName(metricsStmt, true));
+ try {
+ metricsBuilderClass.addInterface(classPool.get(STORAGE_BUILDER_INTERFACE));
+ } catch (NotFoundException e) {
+ logger.error("Can't find StorageBuilder interface for " + className + ".", e);
+ throw new OALCompileException(e.getMessage(), e);
+ }
+
+ ClassFile metricsClassClassFile = metricsBuilderClass.getClassFile();
+ ConstPool constPool = metricsClassClassFile.getConstPool();
+
+ /**
+ * Create empty construct
+ */
+ try {
+ CtConstructor defaultConstructor = CtNewConstructor.make("public " + className + "() {}", metricsBuilderClass);
+ metricsBuilderClass.addConstructor(defaultConstructor);
+ } catch (CannotCompileException e) {
+ logger.error("Can't add empty constructor in " + className + ".", e);
+ throw new OALCompileException(e.getMessage(), e);
+ }
+
+ /**
+ * Generate methods
+ */
+ for (String method : METRICS_BUILDER_CLASS_METHODS) {
+ StringWriter methodEntity = new StringWriter();
+ try {
+ configuration.getTemplate("metrics-builder/" + method + ".ftl").process(metricsStmt, methodEntity);
+ metricsBuilderClass.addMethod(CtNewMethod.make(methodEntity.toString(), metricsBuilderClass));
+ } catch (Exception e) {
+ logger.error("Can't generate method " + method + " for " + className + ".", e);
+ throw new OALCompileException(e.getMessage(), e);
+ }
+ }
+
+ try {
+ metricsBuilderClass.toClass(currentClassLoader, null);
+ } catch (CannotCompileException e) {
+ logger.error("Can't compile/load " + className + ".", e);
+ throw new OALCompileException(e.getMessage(), e);
+ }
+ writeGeneratedFile(metricsBuilderClass, className, "metrics/builder");
}
- private String metricsClassName(AnalysisResult metricsStmt) {
- return DYNAMIC_METRICS_CLASS_PACKAGE + metricsStmt.getMetricsName() + "Metrics";
+ private String metricsClassName(AnalysisResult metricsStmt, boolean fullName) {
+ return (fullName ? DYNAMIC_METRICS_CLASS_PACKAGE : "") + metricsStmt.getMetricsName() + "Metrics";
}
- private String metricsBuilderClassName(AnalysisResult metricsStmt) {
- return DYNAMIC_METRICS_BUILDER_CLASS_PACKAGE + metricsStmt.getMetricsName() + "MetricsBuilder";
+ private String metricsBuilderClassName(AnalysisResult metricsStmt, boolean fullName) {
+ return (fullName ? DYNAMIC_METRICS_BUILDER_CLASS_PACKAGE : "") + metricsStmt.getMetricsName() + "MetricsBuilder";
}
private void buildDispatcherContext(AnalysisResult metricsStmt) {
@@ -292,28 +357,49 @@ public class OALRuntime implements OALEngine {
context.getMetrics().add(metricsStmt);
}
- private void writeGeneratedFile(ClassFile metricsClassClassFile, String className) throws OALCompileException {
- PrintWriter printWriter = null;
+ private void prepareRTTempFoler() {
+ File workPath = WorkPath.getPath();
+ File folder = new File(workPath.getParentFile(), "oal-rt/");
+ if (folder.exists()) {
+ try {
+ FileUtils.deleteDirectory(folder);
+ } catch (IOException e) {
+ logger.warn("Can't delete " + folder.getAbsolutePath() + " temp folder.", e);
+ }
+ }
+ folder.mkdirs();
+ }
+
+ private void writeGeneratedFile(CtClass metricsClass, String className, String type) throws OALCompileException {
+ DataOutputStream printWriter = null;
try {
File workPath = WorkPath.getPath();
- File folder = new File(workPath.getParentFile(), "oal-rt");
+ File folder = new File(workPath.getParentFile(), "oal-rt/" + type);
if (!folder.exists()) {
folder.mkdirs();
}
- File file = new File(folder, className + ".txt");
+ File file = new File(folder, className + ".class");
if (file.exists()) {
file.delete();
}
file.createNewFile();
- printWriter = new PrintWriter(file);
- ClassFilePrinter.print(metricsClassClassFile, printWriter);
+
+ printWriter = new DataOutputStream(new FileOutputStream(file));
+ metricsClass.toBytecode(printWriter);
printWriter.flush();
} catch (IOException e) {
logger.warn("Can't create " + className + ".txt, ignore.", e);
return;
+ } catch (CannotCompileException e) {
+ logger.warn("Can't compile " + className + ".class(should not happen), ignore.", e);
+ return;
} finally {
if (printWriter != null) {
- printWriter.close();
+ try {
+ printWriter.close();
+ } catch (IOException e) {
+
+ }
}
}
diff --git a/oap-server/oal-rt/src/main/resources/code-templates/metrics-builder/data2Map.ftl b/oap-server/oal-rt/src/main/resources/code-templates/metrics-builder/data2Map.ftl
new file mode 100644
index 0000000..1ee5df5
--- /dev/null
+++ b/oap-server/oal-rt/src/main/resources/code-templates/metrics-builder/data2Map.ftl
@@ -0,0 +1,30 @@
+public java.util.Map data2Map(org.apache.skywalking.oal.rt.metrics.${metricsName}Metrics storageData) {
+ java.util.Map map = new java.util.HashMap();
+ <#list fieldsFromSource as field>
+ <#if field.typeName == "long">
+ map.put((Object)"${field.columnName}", new Long(storageData.${field.fieldGetter}()));
+ <#elseif field.typeName == "int">
+ map.put((Object)"${field.columnName}", new Integer(storageData.${field.fieldGetter}()));
+ <#elseif field.typeName == "double">
+ map.put((Object)"${field.columnName}", new Double(storageData.${field.fieldGetter}()));
+ <#elseif field.typeName == "float">
+ map.put((Object)"${field.columnName}", new Float(storageData.${field.fieldGetter}()));
+ <#else>
+ map.put((Object)"${field.columnName}", storageData.${field.fieldGetter}());
+ </#if>
+ </#list>
+ <#list persistentFields as field>
+ <#if field.typeName == "long">
+ map.put((Object)"${field.columnName}", new Long(storageData.${field.fieldGetter}()));
+ <#elseif field.typeName == "int">
+ map.put((Object)"${field.columnName}", new Integer(storageData.${field.fieldGetter}()));
+ <#elseif field.typeName == "double">
+ map.put((Object)"${field.columnName}", new Double(storageData.${field.fieldGetter}()));
+ <#elseif field.typeName == "float">
+ map.put((Object)"${field.columnName}", new Float(storageData.${field.fieldGetter}()));
+ <#else>
+ map.put((Object)"${field.columnName}", storageData.${field.fieldGetter}());
+ </#if>
+ </#list>
+ return map;
+}
\ No newline at end of file
diff --git a/oap-server/oal-rt/src/main/resources/code-templates/metrics-builder/map2Data.ftl b/oap-server/oal-rt/src/main/resources/code-templates/metrics-builder/map2Data.ftl
new file mode 100644
index 0000000..27f543a
--- /dev/null
+++ b/oap-server/oal-rt/src/main/resources/code-templates/metrics-builder/map2Data.ftl
@@ -0,0 +1,22 @@
+public org.apache.skywalking.oal.rt.metrics.${metricsName}Metrics map2Data(java.util.Map dbMap) {
+org.apache.skywalking.oal.rt.metrics.${metricsName}Metrics metrics = new org.apache.skywalking.oal.rt.metrics.${metricsName}Metrics();
+ <#list fieldsFromSource as field>
+ <#if field.typeName == "long" || field.typeName == "int" || field.typeName == "double" || field.typeName == "float">
+ metrics.${field.fieldSetter}(((Number)dbMap.get("${field.columnName}")).${field.typeName}Value());
+ <#elseif field.typeName == "java.lang.String">
+ metrics.${field.fieldSetter}((String)dbMap.get("${field.columnName}"));
+ <#else>
+ metrics.${field.fieldSetter}(new ${field.typeName}((String)dbMap.get("${field.columnName}")));
+ </#if>
+ </#list>
+ <#list persistentFields as field>
+ <#if field.typeName == "long" || field.typeName == "int" || field.typeName == "double" || field.typeName == "float">
+ metrics.${field.fieldSetter}(((Number)dbMap.get("${field.columnName}")).${field.typeName}Value());
+ <#elseif field.typeName == "java.lang.String">
+ metrics.${field.fieldSetter}((String)dbMap.get("${field.columnName}"));
+ <#else>
+ metrics.${field.fieldSetter}(new ${field.typeName}((String)dbMap.get("${field.columnName}")));
+ </#if>
+ </#list>
+return metrics;
+}
\ No newline at end of file