关键词搜索

源码搜索 ×
×

Skywalking-07:OAL原理——解释器实现

发布2021-09-01浏览566次

详情内容

OAL 解释器实现

OAL 解释器是基于 Antlr4 实现的,我们先来了解下 Antlr4

Antlr4 基本介绍

Antlr4 使用案例

参考Antlr4的使用简介这篇文章,我们实现了一个简单的案例:antlr案例:简单的计算器,下面来讲讲这个案例。

首先,装好ANTLR v4(IDEA插件)插件,这个之后验证语法树的时候会用到。

在 pom.xml 中配置 antlr4 的依赖和插件

  1. <dependency>
  2. <groupId>org.antlr</groupId>
  3. <artifactId>antlr4-runtime</artifactId>
  4. <version>4.7.1</version>
  5. </dependency>
  1. <plugin>
  2. <groupId>org.antlr</groupId>
  3. <artifactId>antlr4-maven-plugin</artifactId>
  4. <version>${antlr.version}</version>
  5. <executions>
  6. <execution>
  7. <id>antlr</id>
  8. <goals>
  9. <goal>antlr4</goal>
  10. </goals>
  11. </execution>
  12. </executions>
  13. </plugin>

在 src/main/antlr4/com/switchvov/antlr/demo/calc 目录下添加一个 Calc.g4 文件

  1. grammar Calc; //名称需要和文件名一致
  2. root : expr EOF; //解决问题: no viable alternative at input '<EOF>'
  3. expr
  4. : expr '+' expr #add //标签会生成对应访问方法方便我们实现调用逻辑编写
  5. | expr '-' expr #sub
  6. | INT #int
  7. ;
  8. INT : [0-9]+ //定义整数
  9. ;
  10. WS : [ \r\n\t]+ -> skip //跳过空白类字符
  11. ;

执行一下: mvn compile -Dmaven.test.skip=true ,在 target/generated-sources/antlr4 会生成相应的 Java 代码。

使用方式默认是监听器模式,也可以配置成访问者模式。

监听器模式:主要借助了 ParseTreeWalker 这样一个类,相当于是一个 hook ,每经过一个树的节点,便会触发对应节点的方法。好处就算是比较方python教程便,但是灵活性不够,不能够自主性的调用任意节点进行使用。

访问者模式:将每个数据的节点类型高度抽象出来够,根据你传入的上下文类型来判断你想要访问的是哪个节点,触发对应的方法

PS:结论,简单语法监听器模式就可以了,如果语法比较灵活可以考虑使用访问者模式。

  1. antlr4
  2. ├── Calc.tokens
  3. ├── CalcLexer.tokens
  4. └── com
  5. └── switchvov
  6. └── antlr
  7. └── demo
  8. └── calc
  9. ├── Calc.interp
  10. ├── CalcBaseListener.java # 监听模式下生成的监听器基类,实现类监听器接口,通过继承该类可以实现相应的功能
  11. ├── CalcLexer.interp
  12. ├── CalcLexer.java # 词法解析器
  13. ├── CalcListener.java # 监听模式下生成的监听器接口
  14. └── CalcParser.java # 语法解析器

继承 com.switchvov.antlr.demo.calc.CalcBaseListener ,实现计算器相应功能

  1. package com.switchvov.antlr.demo.calc;
  2. import java.util.ArrayDeque;
  3. import java.util.Deque;
  4. /**
  5. * @author switch
  6. * @since 2021/6/30
  7. */
  8. public class CalcExecuteListener extends CalcBaseListener {
  9. Deque<Integer> queue = new ArrayDeque<>(16);
  10. @Override
  11. public void exitInt(CalcParser.IntContext ctx) {
  12. queue.add(Integer.parseInt(ctx.INT().getText()));
  13. }
  14. @Override
  15. public void exitAdd(CalcParser.AddContext ctx) {
  16. int r = queue.pop();
  17. int l = queue.pop();
  18. queue.add(l + r);
  19. }
  20. @Override
  21. public void exitSub(CalcParser.SubContext ctx) {
  22. int r = queue.pop();
  23. int l = queue.pop();
  24. queue.add(l - r);
  25. }
  26. public int result() {
  27. return queue.pop();
  28. }
  29. }

测试一下

  1. package com.switchvov.antlr.demo.calc;
  2. import org.antlr.v4.runtime.CharStreams;
  3. import org.antlr.v4.runtime.CodePointCharStream;
  4. import org.antlr.v4.runtime.CommonTokenStream;
  5. import org.antlr.v4.runtime.tree.ParseTree;
  6. import org.antlr.v4.runtime.tree.ParseTreeWalker;
  7. import org.junit.Test;
  8. /**
  9. * @author switch
  10. * @since 2021/6/30
  11. */
  12. public class CalcTest {
  13. public static int exec(String input) {
  14. // 读入字符串
  15. CodePointCharStream cs = CharStreams.fromString(input);
  16. // 词法解析
  17. CalcLexer lexer = new CalcLexer(cs);
  18. CommonTokenStream tokens = new CommonTokenStream(lexer);
  19. // 语法解析
  20. CalcParser parser = new CalcParser(tokens);
  21. // 监听器触发获取执行结果
  22. ParseTree tree = parser.expr();
  23. ParseTreeWalker walker = new ParseTreeWalker();
  24. CalcExecuteListener listener = new CalcExecuteListener();
  25. walker.walk(listener, tree);
  26. return listener.result();
  27. }
  28. @Test
  29. public void testCalc() {
  30. String input = "1+2";
  31. // 输出结果:3
  32. System.out.println(exec(input));
  33. }
  34. }

Antlr4 IDEA 插件使用

在 Calc.g4 语法定义文件中,鼠标右击可以选择 Test Rule root ,然后在 ANTLR Preview 的输入框中填入 1 + 2 就可以校验语法文件是否 OK ,并且也可以看到相应的语法树

file

file

Antlr4 在 Skywalking 的应用

通过“ Antlr4 基本介绍”一节,基本上对 Antlr4 使用有了个大概的认识。下面来看看 Skywalking 中 Antlr4 是如何使用的。

词法定义

在 oap-server/oal-grammar/src/main/antlr4/org/apache/skywalking/oal/rt/grammar/OALLexer.g4 文件中,我们能看到 OAL 的词法定义

  1. // Observability Analysis Language lexer
  2. lexer grammar OALLexer;
  3. @Header {package org.apache.skywalking.oal.rt.grammar;}
  4. // Keywords
  5. FROM: 'from';
  6. FILTER: 'filter';
  7. DISABLE: 'disable';
  8. SRC_ALL: 'All';
  9. SRC_SERVICE: 'Service';
  10. SRC_SERVICE_INSTANCE: 'ServiceInstance';
  11. SRC_ENDPOINT: 'Endpoint';
  12. SRC_SERVICE_RELATION: 'ServiceRelation';
  13. SRC_SERVICE_INSTANCE_RELATION: 'ServiceInstanceRelation';
  14. SRC_ENDPOINT_RELATION: 'EndpointRelation';
  15. SRC_SERVICE_INSTANCE_JVM_CPU: 'ServiceInstanceJVMCPU';
  16. SRC_SERVICE_INSTANCE_JVM_MEMORY: 'ServiceInstanceJVMMemory';
  17. SRC_SERVICE_INSTANCE_JVM_MEMORY_POOL: 'ServiceInstanceJVMMemoryPool';
  18. SRC_SERVICE_INSTANCE_JVM_GC: 'ServiceInstanceJVMGC';
  19. SRC_SERVICE_INSTANCE_JVM_THREAD: 'ServiceInstanceJVMThread';
  20. SRC_SERVICE_INSTANCE_JVM_CLASS:'ServiceInstanceJVMClass';
  21. SRC_DATABASE_ACCESS: 'DatabaseAccess';
  22. SRC_SERVICE_INSTANCE_CLR_CPU: 'ServiceInstanceCLRCPU';
  23. SRC_SERVICE_INSTANCE_CLR_GC: 'ServiceInstanceCLRGC';
  24. SRC_SERVICE_INSTANCE_CLR_THREAD: 'ServiceInstanceCLRThread';
  25. SRC_ENVOY_INSTANCE_METRIC: 'EnvoyInstanceMetric';
  26. // Browser keywords
  27. SRC_BROWSER_APP_PERF: 'BrowserAppPerf';
  28. SRC_BROWSER_APP_PAGE_PERF: 'BrowserAppPagePerf';
  29. SRC_BROWSER_APP_SINGLE_VERSION_PERF: 'BrowserAppSingleVersionPerf';
  30. SRC_BROWSER_APP_TRAFFIC: 'BrowserAppTraffic';
  31. SRC_BROWSER_APP_PAGE_TRAFFIC: 'BrowserAppPageTraffic';
  32. SRC_BROWSER_APP_SINGLE_VERSION_TRAFFIC: 'BrowserAppSingleVersionTraffic';
  33. // Constructors symbols
  34. DOT: '.';
  35. LR_BRACKET: '(';
  36. RR_BRACKET: ')';
  37. LS_BRACKET: '[';
  38. RS_BRACKET: ']';
  39. COMMA: ',';
  40. SEMI: ';';
  41. EQUAL: '=';
  42. DUALEQUALS: '==';
  43. ALL: '*';
  44. GREATER: '>';
  45. LESS: '<';
  46. GREATER_EQUAL: '>=';
  47. LESS_EQUAL: '<=';
  48. NOT_EQUAL: '!=';
  49. LIKE: 'like';
  50. IN: 'in';
  51. CONTAIN: 'contain';
  52. NOT_CONTAIN: 'not contain';
  53. // Literals
  54. BOOL_LITERAL: 'true'
  55. | 'false'
  56. ;
  57. NUMBER_LITERAL : Digits+;
  58. CHAR_LITERAL: '\'' (~['\\\r\n] | EscapeSequence) '\'';
  59. STRING_LITERAL: '"' (~["\\\r\n] | EscapeSequence)* '"';
  60. DelimitedComment
  61. : '/*' ( DelimitedComment | . )*? '*/'
  62. -> channel(HIDDEN)
  63. ;
  64. LineComment
  65. : '//' ~[\u000A\u000D]*
  66. -> channel(HIDDEN)
  67. ;
  68. SPACE: [ \t\r\n]+ -> channel(HIDDEN);
  69. // Identifiers
  70. IDENTIFIER: Letter LetterOrDigit*;
  71. // Fragment rules
  72. fragment EscapeSequence
  73. : '\\' [btnfr"'\\]
  74. | '\\' ([0-3]? [0-7])? [0-7]
  75. | '\\' 'u'+ HexDigit HexDigit HexDigit HexDigit
  76. ;
  77. fragment HexDigits
  78. : HexDigit ((HexDigit | '_')* HexDigit)?
  79. ;
  80. fragment HexDigit
  81. : [0-9a-fA-F]
  82. ;
  83. fragment Digits
  84. : [0-9] ([0-9_]* [0-9])?
  85. ;
  86. fragment LetterOrDigit
  87. : Letter
  88. | [0-9]
  89. ;
  90. fragment Letter
  91. : [a-zA-Z$_] // these are the "java letters" below 0x7F
  92. | ~[\u0000-\u007F\uD800-\uDBFF] // covers all characters above 0x7F which are not a surrogate
  93. | [\uD800-\uDBFF] [\uDC00-\uDFFF] // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF
  94. ;

语法定义

在 oap-server/oal-grammar/src/main/antlr4/org/apache/skywalking/oal/rt/grammar/OALParser.g4 文件中,我们能看到 OAL 的语法定义

  1. parser grammar OALParser;
  2. @Header {package org.apache.skywalking.oal.rt.grammar;}
  3. options { tokenVocab=OALLexer; }
  4. // Top Level Description
  5. root
  6. : (aggregationStatement | disableStatement)*
  7. ;
  8. aggregationStatement
  9. : variable (SPACE)? EQUAL (SPACE)? metricStatement DelimitedComment? LineComment? (SEMI|EOF)
  10. ;
  11. disableStatement
  12. : DISABLE LR_BRACKET disableSource RR_BRACKET DelimitedComment? LineComment? (SEMI|EOF)
  13. ;
  14. metricStatement
  15. : FROM LR_BRACKET source (sourceAttributeStmt+) RR_BRACKET (filterStatement+)? DOT aggregateFunction
  16. ;
  17. filterStatement
  18. : DOT FILTER LR_BRACKET filterExpression RR_BRACKET
  19. ;
  20. filterExpression
  21. : expression
  22. ;
  23. source
  24. : SRC_ALL | SRC_SERVICE | SRC_DATABASE_ACCESS | SRC_SERVICE_INSTANCE | SRC_ENDPOINT |
  25. SRC_SERVICE_RELATION | SRC_SERVICE_INSTANCE_RELATION | SRC_ENDPOINT_RELATION |
  26. SRC_SERVICE_INSTANCE_JVM_CPU | SRC_SERVICE_INSTANCE_JVM_MEMORY | SRC_SERVICE_INSTANCE_JVM_MEMORY_POOL | SRC_SERVICE_INSTANCE_JVM_GC | SRC_SERVICE_INSTANCE_JVM_THREAD | SRC_SERVICE_INSTANCE_JVM_CLASS |// JVM source of service instance
  27. SRC_SERVICE_INSTANCE_CLR_CPU | SRC_SERVICE_INSTANCE_CLR_GC | SRC_SERVICE_INSTANCE_CLR_THREAD |
  28. SRC_ENVOY_INSTANCE_METRIC |
  29. SRC_BROWSER_APP_PERF | SRC_BROWSER_APP_PAGE_PERF | SRC_BROWSER_APP_SINGLE_VERSION_PERF |
  30. SRC_BROWSER_APP_TRAFFIC | SRC_BROWSER_APP_PAGE_TRAFFIC | SRC_BROWSER_APP_SINGLE_VERSION_TRAFFIC
  31. ;
  32. disableSource
  33. : IDENTIFIER
  34. ;
  35. sourceAttributeStmt
  36. : DOT sourceAttribute
  37. ;
  38. sourceAttribute
  39. : IDENTIFIER | ALL
  40. ;
  41. variable
  42. : IDENTIFIER
  43. ;
  44. aggregateFunction
  45. : functionName LR_BRACKET ((funcParamExpression (COMMA funcParamExpression)?) | (literalExpression (COMMA literalExpression)?))? RR_BRACKET
  46. ;
  47. functionName
  48. : IDENTIFIER
  49. ;
  50. funcParamExpression
  51. : expression
  52. ;
  53. literalExpression
  54. : BOOL_LITERAL | NUMBER_LITERAL | IDENTIFIER
  55. ;
  56. expression
  57. : booleanMatch | stringMatch | greaterMatch | lessMatch | greaterEqualMatch | lessEqualMatch | notEqualMatch | booleanNotEqualMatch | likeMatch | inMatch | containMatch | notContainMatch
  58. ;
  59. containMatch
  60. : conditionAttributeStmt CONTAIN stringConditionValue
  61. ;
  62. notContainMatch
  63. : conditionAttributeStmt NOT_CONTAIN stringConditionValue
  64. ;
  65. booleanMatch
  66. : conditionAttributeStmt DUALEQUALS booleanConditionValue
  67. ;
  68. stringMatch
  69. : conditionAttributeStmt DUALEQUALS (stringConditionValue | enumConditionValue)
  70. ;
  71. greaterMatch
  72. : conditionAttributeStmt GREATER numberConditionValue
  73. ;
  74. lessMatch
  75. : conditionAttributeStmt LESS numberConditionValue
  76. ;
  77. greaterEqualMatch
  78. : conditionAttributeStmt GREATER_EQUAL numberConditionValue
  79. ;
  80. lessEqualMatch
  81. : conditionAttributeStmt LESS_EQUAL numberConditionValue
  82. ;
  83. booleanNotEqualMatch
  84. : conditionAttributeStmt NOT_EQUAL booleanConditionValue
  85. ;
  86. notEqualMatch
  87. : conditionAttributeStmt NOT_EQUAL (numberConditionValue | stringConditionValue | enumConditionValue)
  88. ;
  89. likeMatch
  90. : conditionAttributeStmt LIKE stringConditionValue
  91. ;
  92. inMatch
  93. : conditionAttributeStmt IN multiConditionValue
  94. ;
  95. multiConditionValue
  96. : LS_BRACKET (numberConditionValue ((COMMA numberConditionValue)*) | stringConditionValue ((COMMA stringConditionValue)*) | enumConditionValue ((COMMA enumConditionValue)*)) RS_BRACKET
  97. ;
  98. conditionAttributeStmt
  99. : conditionAttribute ((DOT conditionAttribute)*)
  100. ;
  101. conditionAttribute
  102. : IDENTIFIER
  103. ;
  104. booleanConditionValue
  105. : BOOL_LITERAL
  106. ;
  107. stringConditionValue
  108. : STRING_LITERAL
  109. ;
  110. enumConditionValue
  111. : IDENTIFIER DOT IDENTIFIER
  112. ;
  113. numberConditionValue
  114. : NUMBER_LITERAL
  115. ;

Antlr4 生成 Java 代码

在 oap-server/oal-grammar 下执行 mvn compile -Dmaven.test.skip=true 会在 oap-server/oal-grammar/target/generated-sources/antlr4 目录下生成相应的 Java 代码

  1. .
  2. ├── OALLexer.tokens
  3. ├── OALParser.tokens
  4. └── org
  5. └── apache
  6. └── skywalking
  7. └── oal
  8. └── rt
  9. └── grammar
  10. ├── OALLexer.interp
  11. ├── OALLexer.java # 词法解析器
  12. ├── OALParser.interp
  13. ├── OALParser.java # 语法解析器
  14. ├── OALParserBaseListener.java # 监听器
  15. └── OALParserListener.java

在 Skywalking 的使用

通过“ Antlr4 使用案例”一节,可以知道 Antlr4 有两种功能实现方式:监听器或者访问器。

通过“ Antlr4 生成 Java 代码”一节,知道 Skywalking 使用的是监听器模式。

Skywalking 关于 OAL 的相应的代码都在 oap-server/oal-rt 模块中。

org.apache.skywalking.oal.rt.grammar.OALParserBaseListener 的继承类坐标是 org.apache.skywalking.oal.rt.parser.OALListener

  1. package org.apache.skywalking.oal.rt.parser;
  2. import java.util.Arrays;
  3. import java.util.List;
  4. import org.antlr.v4.runtime.misc.NotNull;
  5. import org.apache.skywalking.oal.rt.grammar.OALParser;
  6. import org.apache.skywalking.oal.rt.grammar.OALParserBaseListener;
  7. import org.apache.skywalking.oap.server.core.source.DefaultScopeDefine;
  8. public class OALListener extends OALParserBaseListener {
  9. private List<AnalysisResult> results;
  10. private AnalysisResult current;
  11. private DisableCollection collection;
  12. private ConditionExpression conditionExpression;
  13. private final String sourcePackage;
  14. public OALListener(OALScripts scripts, String sourcePackage) {
  15. this.results = scripts.getMetricsStmts();
  16. this.collection = scripts.getDisableCollection();
  17. this.sourcePackage = sourcePackage;
  18. }
  19. @Override
  20. public void enterAggregationStatement(@NotNull OALParser.AggregationStatementContext ctx) {
  21. current = new AnalysisResult();
  22. }
  23. @Override
  24. public void exitAggregationStatement(@NotNull OALParser.AggregationStatementContext ctx) {
  25. DeepAnalysis deepAnalysis = new DeepAnalysis();
  26. results.add(deepAnalysis.analysis(current));
  27. current = null;
  28. }
  29. @Override
  30. public void enterSource(OALParser.SourceContext ctx) {
  31. current.setSourceName(ctx.getText());
  32. current.setSourceScopeId(DefaultScopeDefine.valueOf(metricsNameFormat(ctx.getText())));
  33. }
  34. @Override
  35. public void enterSourceAttribute(OALParser.SourceAttributeContext ctx) {
  36. current.getSourceAttribute().add(ctx.getText());
  37. }
  38. @Override
  39. public void enterVariable(OALParser.VariableContext ctx) {
  40. }
  41. @Override
  42. public void exitVariable(OALParser.VariableContext ctx) {
  43. current.setVarName(ctx.getText());
  44. current.setMetricsName(metricsNameFormat(ctx.getText()));
  45. current.setTableName(ctx.getText().toLowerCase());
  46. }
  47. @Override
  48. public void enterFunctionName(OALParser.FunctionNameContext ctx) {
  49. current.setAggregationFunctionName(ctx.getText());
  50. }
  51. @Override
  52. public void enterFilterStatement(OALParser.FilterStatementContext ctx) {
  53. conditionExpression = new ConditionExpression();
  54. }
  55. @Override
  56. public void exitFilterStatement(OALParser.FilterStatementContext ctx) {
  57. current.addFilterExpressionsParserResult(conditionExpression);
  58. conditionExpression = null;
  59. }
  60. @Override
  61. public void enterFuncParamExpression(OALParser.FuncParamExpressionContext ctx) {
  62. conditionExpression = new ConditionExpression();
  63. }
  64. @Override
  65. public void exitFuncParamExpression(OALParser.FuncParamExpressionContext ctx) {
  66. current.addFuncConditionExpression(conditionExpression);
  67. conditionExpression = null;
  68. }
  69. /
  70. // Expression
  71. @Override
  72. public void enterConditionAttribute(OALParser.ConditionAttributeContext ctx) {
  73. conditionExpression.getAttributes().add(ctx.getText());
  74. }
  75. @Override
  76. public void enterBooleanMatch(OALParser.BooleanMatchContext ctx) {
  77. conditionExpression.setExpressionType("booleanMatch");
  78. }
  79. @Override
  80. public void enterStringMatch(OALParser.StringMatchContext ctx) {
  81. conditionExpression.setExpressionType("stringMatch");
  82. }
  83. @Override
  84. public void enterGreaterMatch(OALParser.GreaterMatchContext ctx) {
  85. conditionExpression.setExpressionType("greaterMatch");
  86. }
  87. @Override
  88. public void enterGreaterEqualMatch(OALParser.GreaterEqualMatchContext ctx) {
  89. conditionExpression.setExpressionType("greaterEqualMatch");
  90. }
  91. @Override
  92. public void enterLessMatch(OALParser.LessMatchContext ctx) {
  93. conditionExpression.setExpressionType("lessMatch");
  94. }
  95. @Override
  96. public void enterLessEqualMatch(OALParser.LessEqualMatchContext ctx) {
  97. conditionExpression.setExpressionType("lessEqualMatch");
  98. }
  99. @Override
  100. public void enterNotEqualMatch(final OALParser.NotEqualMatchContext ctx) {
  101. conditionExpression.setExpressionType("notEqualMatch");
  102. }
  103. @Override
  104. public void enterBooleanNotEqualMatch(final OALParser.BooleanNotEqualMatchContext ctx) {
  105. conditionExpression.setExpressionType("booleanNotEqualMatch");
  106. }
  107. @Override
  108. public void enterLikeMatch(final OALParser.LikeMatchContext ctx) {
  109. conditionExpression.setExpressionType("likeMatch");
  110. }
  111. @Override
  112. public void enterContainMatch(final OALParser.ContainMatchContext ctx) {
  113. conditionExpression.setExpressionType("containMatch");
  114. }
  115. @Override
  116. public void enterNotContainMatch(final OALParser.NotContainMatchContext ctx) {
  117. conditionExpression.setExpressionType("notContainMatch");
  118. }
  119. @Override
  120. public void enterInMatch(final OALParser.InMatchContext ctx) {
  121. conditionExpression.setExpressionType("inMatch");
  122. }
  123. @Override
  124. public void enterMultiConditionValue(final OALParser.MultiConditionValueContext ctx) {
  125. conditionExpression.enterMultiConditionValue();
  126. }
  127. @Override
  128. public void exitMultiConditionValue(final OALParser.MultiConditionValueContext ctx) {
  129. conditionExpression.exitMultiConditionValue();
  130. }
  131. @Override
  132. public void enterBooleanConditionValue(OALParser.BooleanConditionValueContext ctx) {
  133. enterConditionValue(ctx.getText());
  134. }
  135. @Override
  136. public void enterStringConditionValue(OALParser.StringConditionValueContext ctx) {
  137. enterConditionValue(ctx.getText());
  138. }
  139. @Override
  140. public void enterEnumConditionValue(OALParser.EnumConditionValueContext ctx) {
  141. enterConditionValue(ctx.getText());
  142. }
  143. @Override
  144. public void enterNumberConditionValue(OALParser.NumberConditionValueContext ctx) {
  145. conditionExpression.isNumber();
  146. enterConditionValue(ctx.getText());
  147. }
  148. private void enterConditionValue(String value) {
  149. if (value.split("\\.").length == 2 && !value.startsWith("\"")) {
  150. // Value is an enum.
  151. value = sourcePackage + value;
  152. }
  153. conditionExpression.addValue(value);
  154. }
  155. /
  156. // Expression end.
  157. @Override
  158. public void enterLiteralExpression(OALParser.LiteralExpressionContext ctx) {
  159. if (ctx.IDENTIFIER() == null) {
  160. current.addFuncArg(new Argument(EntryMethod.LITERAL_TYPE, Arrays.asList(ctx.getText())));
  161. return;
  162. }
  163. current.addFuncArg(new Argument(EntryMethod.IDENTIFIER_TYPE, Arrays.asList(ctx.getText().split("\\."))));
  164. }
  165. private String metricsNameFormat(String source) {
  166. source = firstLetterUpper(source);
  167. int idx;
  168. while ((idx = source.indexOf("_")) > -1) {
  169. source = source.substring(0, idx) + firstLetterUpper(source.substring(idx + 1));
  170. }
  171. return source;
  172. }
  173. /**
  174. * Disable source
  175. */
  176. @Override
  177. public void enterDisableSource(OALParser.DisableSourceContext ctx) {
  178. collection.add(ctx.getText());
  179. }
  180. private String firstLetterUpper(String source) {
  181. return source.substring(0, 1).toUpperCase() + source.substring(1);
  182. }
  183. }

简单来说,就是通过监python教程听器封装了个 org.apache.skywalking.oal.rt.parser.OALScripts 对象

  1. package org.apache.skywalking.oal.rt.parser;
  2. import java.util.LinkedList;
  3. import java.util.List;
  4. import lombok.Getter;
  5. @Getter
  6. public class OALScripts {
  7. // 解析出来的分析结果集合
  8. private List<AnalysisResult> metricsStmts;
  9. // 禁用表达式集合
  10. private DisableCollection disableCollection;
  11. public OALScripts() {
  12. metricsStmts = new LinkedList<>();
  13. disableCollection = new DisableCollection();
  14. }
  15. }

org.apache.skywalking.oal.rt.parser.ScriptParser 类读取 oal 文件,使用 Antlr 生成的 Java 类进行解析

  1. package org.apache.skywalking.oal.rt.parser;
  2. import java.io.IOException;
  3. import java.io.Reader;
  4. import org.antlr.v4.runtime.CharStreams;
  5. import org.antlr.v4.runtime.CommonTokenStream;
  6. import org.antlr.v4.runtime.tree.ParseTree;
  7. import org.antlr.v4.runtime.tree.ParseTreeWalker;
  8. import org.apache.skywalking.oal.rt.grammar.OALLexer;
  9. import org.apache.skywalking.oal.rt.grammar.OALParser;
  10. /**
  11. * Script reader and parser.
  12. */
  13. public class ScriptParser {
  14. private OALLexer lexer;
  15. private String sourcePackage;
  16. private ScriptParser() {
  17. }
  18. public static ScriptParser createFromFile(Reader scriptReader, String sourcePackage) throws IOException {
  19. ScriptParser parser = new ScriptParser();
  20. parser.lexer = new OALLexer(CharStreams.fromReader(scriptReader));
  21. parser.sourcePackage = sourcePackage;
  22. return parser;
  23. }
  24. public static ScriptParser createFromScriptText(String script, String sourcePackage) throws IOException {
  25. ScriptParser parser = new ScriptParser();
  26. parser.lexer = new OALLexer(CharStreams.fromString(script));
  27. parser.sourcePackage = sourcePackage;
  28. return parser;
  29. }
  30. public OALScripts parse() throws IOException {
  31. OALScripts scripts = new OALScripts();
  32. CommonTokenStream tokens = new CommonTokenStream(lexer);
  33. OALParser parser = new OALParser(tokens);
  34. ParseTree tree = parser.root();
  35. ParseTreeWalker walker = new ParseTreeWalker();
  36. walker.walk(new OALListener(scripts, sourcePackage), tree);
  37. return scripts;
  38. }
  39. public void close() {
  40. }
  41. }

相关技术文章

点击QQ咨询
开通会员
返回顶部
×
微信扫码支付
微信扫码支付
确定支付下载
请使用微信描二维码支付
×

提示信息

×

选择支付方式

  • 微信支付
  • 支付宝付款
确定支付下载