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]
