toffentoffen opened a new issue, #13917:
URL: https://github.com/apache/skywalking/issues/13917

   ### Search before asking
   
   - [x] I had searched in the 
[issues](https://github.com/apache/skywalking/issues?q=is%3Aissue) and found no 
similar issues.
   
   ### Apache SkyWalking Component
   
   OAP server (apache/skywalking)
   
   ### What happened
   
   The **v2 MAL compiler** 
(`org.apache.skywalking.oap.meter.analyzer.v2.compiler`) cannot compile a MAL 
expression that references a **custom layer** via `Layer.nameOf('NAME')`, even 
though this is the documented way to reference a layer declared through a 
`layerDefinitions:` block.
   
   A custom layer registered via `layerDefinitions:` (or `layer-extensions.yml` 
/ the `LayerExtension` SPI) has **no generated `Layer.*` static field**, so 
`Layer.nameOf('NAME')` is the only way to name it. 
`docs/en/concepts-and-designs/mal.md` documents exactly this form:
   
   ```yaml
   layerDefinitions:
     - name: IOT_FLEET
       ordinal: 1000
       normal: true
   
   metricsRules:
     - name: device_battery_percentage
       exp: iot_device_battery_level.tagAverage(['service'], ['host'])
   expSuffix: instance(['host'], ['service'], Layer.nameOf('IOT_FLEET'))
   ```
   
   The v1 (Groovy) compiler evaluates `Layer.nameOf('IOT_FLEET')` natively as a 
static method call, so it works there. The v2 compiler fails: its ANTLR grammar 
models only the static-**field** form of an enum reference (`enumRef : 
IDENTIFIER DOT IDENTIFIER`, e.g. `Layer.GENERAL`). The static-**method** form 
`Layer.nameOf('IOT_FLEET')` is instead mis-parsed as a metric named `Layer` 
with a `.nameOf("...")` method chain, and code generation then emits 
`_Layer.nameOf("...")` against `SampleFamily`, which has no such method.
   
   ### What you expected to happen
   
   `Layer.nameOf('NAME')` should compile under the v2 compiler exactly as it 
does under v1, resolving the custom layer by name at the call site. Builtin 
layers (`Layer.GENERAL`, etc.) already work.
   
   Instead, compilation fails with:
   
   ```
   javassist.CannotCompileException: [source error] nameOf(java.lang.String) 
not found in
     org.apache.skywalking.oap.meter.analyzer.v2.dsl.SampleFamily
   ```
   
   Root cause locations:
   - Grammar: 
`oap-server/analyzer/meter-analyzer/src/main/antlr4/org/apache/skywalking/mal/rt/grammar/MALParser.g4`
 — `enumRef : IDENTIFIER DOT IDENTIFIER;` (only `Layer.GENERAL`-style field 
refs).
   - Parser: `MALScriptParser.convertArgument(...)` falls back to treating 
`Layer.nameOf('X')` as a metric reference + method chain.
   - Codegen: `MALMethodChainCodegen.generateArgument(...)` emits 
`<var>.nameOf("X")` against `SampleFamily`.
   
   For comparison, LAL already resolves custom layers by name 
(`Layer.valueOf(String)` registry lookup, type-directed codegen in 
`LALBlockCodegen`), so this gap is specific to the MAL v2 path.
   
   ### How to reproduce
   
   Minimal reproduction against the v2 compiler 
(`oap-server/analyzer/meter-analyzer`):
   
   ```java
   Layer.register("REPRO_LAYER", 1500, true);
   MALClassGenerator generator = new MALClassGenerator(new ClassPool(true));
   
   // Builtin static-field form — compiles fine
   generator.compile("m1",
       "metric.sum(['service']).service(['service'], Layer.GENERAL)");
   
   // Custom-layer static-method form (documented in mal.md) — FAILS
   generator.compile("m2",
       "metric.sum(['service']).service(['service'], 
Layer.nameOf('REPRO_LAYER'))");
   ```
   
   The second `compile(...)` throws:
   
   ```
   javassist.CannotCompileException: [source error] nameOf(java.lang.String) 
not found in
     org.apache.skywalking.oap.meter.analyzer.v2.dsl.SampleFamily
   ```
   
   End-to-end, the same failure occurs when a MAL rule file ships a 
`layerDefinitions:` block and references the declared layer via 
`Layer.nameOf('NAME')` in its `expSuffix`/`exp` while the v2 compiler is active.
   
   ### Anything else
   
   Happens every time the v2 compiler compiles an expression whose argument is 
`Layer.nameOf('<custom-layer>')`. No bundled rule currently uses this form 
(they all use builtin `Layer.GENERAL`-style fields), which is why CI has not 
caught it; the existing `RulesLayerDefinitionsTest` only verifies layer 
**registration**, never **compilation** of a `Layer.nameOf(...)` reference.
   
   The fix is contained to the parser → AST → codegen layer (not the grammar, 
to avoid the unsolvable `ID.ID(STRING)` ambiguity between `Layer.nameOf('x')` 
and a real `metric.method('x')` — only the known-enum-type set distinguishes 
them).
   
   ### Are you willing to submit a pull request to fix on your own?
   
   - [x] Yes I am willing to submit a pull request on my own!
   
   ### Code of Conduct
   
   - [x] I agree to follow this project's [Code of 
Conduct](https://www.apache.org/foundation/policies/conduct)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: 
[email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to