Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/en/changes/changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#### Project

* Move the DSL class-loading machinery under `core/dsl`. `core/classloader` held only DSL types — `RuleClassLoader`, `DSLClassLoaderManager`, `ClassLoaderGc`, `UnloadProbePayload` and `BytecodeClassDefiner` — so it is now `core/dsl/classloader`, and `Catalog` moves to `core/dsl` because a rule-file taxonomy is not a class-loading concern. Three copies of the "define a generated class into the right loader" dispatch (MAL, LAL, `MeterSystem`) collapse into a static `BytecodeClassDefiner.define`, which also gives the JDK 17 `--add-opens` rationale one home instead of four. Three of the four copies of the generated-class dump-directory lookup become `DslGeneratedFileWriter.resolveClassDumpDir`; OAL keeps its own, because its debug flag is settable independently of the environment variable and two tests rely on that. No behaviour change.
* Extend the `GET /inspect/entities` admin API to inspect a metric persisted by **any** OAP, even one this node does not define locally. When the metric is unknown to the local registry, the caller supplies `valueColumn` + `valueType` and the storage backend resolves the physical index/table/group from its own running config (no DB schema/table-metadata read): ES uses the merged `metrics-all` index + `metric_table` discriminator, JDBC probes the node's function tables by the `table_name` discriminator, and BanyanDB synthesizes a read-only measure schema. Scope is no longer required — the `entity_id` is decoded structurally (service / 2nd-level / relations) with a generic `name` leaf. Locally-defined metrics keep the exact field names, scope, and `mqeEntity` as before.
* Add the `POST /inspect/values` admin API — read the value series of a metric persisted by **another** OAP (one this node does not define locally) by supplying its `{valueColumn, valueType}`. The real MQE engine runs over a request-scoped `InspectQueryContext` overlay (provide-if-absent — the local catalog always wins) that makes the foreign metric look registered to every read path: `ValueColumnMetadata` resolves its value column / type / scope, and the storage location registries resolve where it lives (`MetadataRegistry` synthesizes a BanyanDB measure schema, `IndexController` resolves the ES `metrics-all` index, `TableHelper` probes the JDBC function tables), so the read returns the native MQE `ExpressionResult` with no per-DAO special-casing. Admin-only (a forced read this OAP cannot validate); not mirrored onto the public REST / GraphQL surface. See the [Inspect API](../setup/backend/admin-api/inspect.md).
* Remove the always-on alarm-to-event conversion (`EventHookCallback`). A triggered alarm is no longer synthesized into the events pipeline as an `Alarm`/`AlarmRecovery` event; events now originate only from real event sources (agents, SkyWalking CLI, Kubernetes Event Exporter). Alarms remain available through the alarm store (`getAlarm`/`queryAlarms`) and the configured alarm hooks. This drops a documented "Known Event" and removes 1-2 synthetic event records per alarm fire.
Expand Down Expand Up @@ -256,7 +257,7 @@

#### OAP Server
* Fix LAL's `segmentId` and `spanId` extractor statements, which the grammar accepted and the parser never implemented. `LALParser.g4` declares `traceIdStatement`, `segmentIdStatement` and `spanIdStatement`, and the codegen already carried `setSegmentId`/`setSpanId` in its setter table, but `LALScriptParser.visitExtractorStatement` had a branch for only the first of the three. The remaining alternatives fell through to a line that assumed whatever was left had to be an `ifStatement`, so a rule writing `segmentId ...` failed at boot with a `NullPointerException` naming `IfStatementContext` — for a rule line containing no `if`. Both statements now work, and an unhandled extractor statement reports its own rule line instead of throwing. Existing log records are unaffected: `LogBuilder` copies trace id, segment id and span id straight from the log's metadata, and only skips that copy when a rule has set them — which no shipped rule did, which is why the gap went unnoticed. Dedicated execution tests now cover reading all three fields from `log.traceContext.*` and writing all three from an extractor.
* Remove dead code from the DSL subsystem and correct the shared kernel's own documentation. Deleted `DslContentHash` (a byte-identical, zero-caller twin of the live `ContentHash`), the unused `oal-rt` metrics-function registry, `LogAnalyzerFactory`, `LALCodegenHelper.METADATA_GETTER_ALIASES` (a permanently empty map whose reader branch could never execute — the DSL-name-to-getter mismatch it existed for no longer exists, since `LogMetadata.TraceContext` names the field `traceSegmentId` directly), and three unreferenced members. Three kernel classes carried javadoc asserting consumers that do not exist — `DSLClassLoaderManager` claimed the MAL and LAL compile paths reach for its singleton, `LogDataDebugDump` claimed core renders through it, and `DslContentHash` instructed the reader to consolidate toward the dead copy; a false rationale in a shared kernel is an instruction to the next contributor, so those are now what the call sites actually support. `OALDebug`, `OALDebugRecorder` and `DebugHolderProvider` now record why they sit in core while MAL's and LAL's equivalents do not: `dsl-debugging` declares no `oal-rt` dependency, so they cannot move. `dsl-debugging` also now declares its `server-core` dependency directly instead of inheriting it transitively.
* Remove dead code from the DSL subsystem and correct the shared kernel's own documentation. Deleted `DslContentHash` (a byte-identical, zero-caller twin of the live `ContentHash`), the unused `oal-rt` metrics-function registry, `LogAnalyzerFactory`, `LALCodegenHelper.METADATA_GETTER_ALIASES` (a permanently empty map whose reader branch could never execute — the DSL-name-to-getter mismatch it existed for no longer exists, since `LogMetadata.TraceContext` names the field `traceSegmentId` directly), and three unreferenced members. Three kernel classes carried javadoc asserting consumers that do not exist — `DSLClassLoaderManager` claimed the MAL and LAL compile paths reach for its singleton, `LogDataDebugDump` claimed core renders through it, and `DslContentHash` instructed the reader to consolidate toward the dead copy; a false rationale in a shared kernel is an instruction to the next contributor, so those are now what the call sites actually support. `OALDebug`, `OALDebugRecorder` and `DebugHolderProvider` now record why they sit in core while MAL's and LAL's equivalents do not: `dsl-debugging` declares no `oal-rt` dependency, so they cannot move.
* Unify source attribution for every generated DSL class, so a stack frame from OAL, MAL, LAL or Hierarchy code leads back to the rule that produced it.
- `SourceFile` now names the RULE and its line, then the generated class file: `(otel-rules/activemq/activemq-broker.yaml:32)otel_rules_activemq_activemq_broker_L32_service_meter.java`. The `.java` generated source file is written only under `SW_DYNAMIC_CLASS_ENGINE_DEBUG`, so in a default deployment naming it named nothing; the class name cannot substitute because sanitising maps `/`, `-` and `.` all to `_` and drops the extension.
- The `_L<n>_` segment was the rules-list index rather than a line, so every file's first rule reported as `L0`. It now carries the rule's real line, resolved by the loaders themselves — including Zabbix and Hierarchy, which supplied no coordinate at all, and the runtime-rule hot-update paths for MAL and LAL, which disagreed with their own boot loaders.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@
import javassist.CtNewConstructor;
import javassist.CtNewMethod;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.oap.server.core.WorkPath;
import org.apache.skywalking.oap.server.core.config.v2.compiler.hierarchy.rule.rt.HierarchyRulePackageHolder;
import org.apache.skywalking.oap.server.library.util.StringUtil;
import org.apache.skywalking.oap.server.core.query.type.Service;
import org.apache.skywalking.oap.server.core.dsl.DslJavaSourceText;

Expand Down Expand Up @@ -79,9 +77,7 @@ public final class HierarchyRuleClassGenerator {

public HierarchyRuleClassGenerator() {
this(ClassPool.getDefault());
if (StringUtil.isNotEmpty(System.getenv("SW_DYNAMIC_CLASS_ENGINE_DEBUG"))) {
classOutputDir = new File(WorkPath.getPath().getParentFile(), "hierarchy-rt");
}
classOutputDir = DslGeneratedFileWriter.resolveClassDumpDir("hierarchy");
}

public HierarchyRuleClassGenerator(final ClassPool classPool) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@

import org.apache.skywalking.oap.server.core.dsl.DslGeneratedFileWriter;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtNewConstructor;
Expand All @@ -35,12 +35,10 @@
import org.apache.skywalking.oap.log.analyzer.v2.provider.LALConfigs;
import org.apache.skywalking.oap.server.core.dsl.DslClassNaming;
import org.apache.skywalking.oap.server.core.dsl.DslSourceRef;
import org.apache.skywalking.oap.server.core.classloader.BytecodeClassDefiner;
import org.apache.skywalking.oap.server.core.dsl.classloader.BytecodeClassDefiner;
import org.apache.skywalking.oap.server.core.dsl.debug.DSLDebugCodegenSwitch;
import org.apache.skywalking.oap.server.core.source.LogBuilder;
import org.apache.skywalking.oap.log.analyzer.v2.dsl.LalExpression;
import org.apache.skywalking.oap.server.core.WorkPath;
import org.apache.skywalking.oap.server.library.util.StringUtil;
import org.apache.skywalking.oap.server.core.dsl.DslJavaSourceText;

/**
Expand Down Expand Up @@ -219,9 +217,7 @@ void restoreProtoVarState(final Object[] state) {

public LALClassGenerator() {
this(ClassPool.getDefault(), null);
if (StringUtil.isNotEmpty(System.getenv("SW_DYNAMIC_CLASS_ENGINE_DEBUG"))) {
classOutputDir = new File(WorkPath.getPath().getParentFile(), "lal-rt");
}
classOutputDir = DslGeneratedFileWriter.resolveClassDumpDir("lal");
}

public LALClassGenerator(final ClassPool classPool) {
Expand Down Expand Up @@ -508,26 +504,12 @@ private String buildSourceText(final CtClass ctClass,
* (startup path: class lands in the OAP app loader alongside
* {@link LalExpressionPackageHolder}).
*
* <p>{@link BytecodeClassDefiner} loaders (the runtime-rule {@code RuleClassLoader})
* receive the {@code CtClass.toBytecode()} bytes via their public {@code defineClass}
* — bypasses Javassist's deprecated {@code toClass(loader, ProtectionDomain)} reflection
* path so we don't need {@code --add-opens java.base/java.lang} on the OAP container.
* Same shape as {@code MALClassGenerator}; both DSLs share the contract.
* <p>Which of the two definition paths applies, and why the
* {@link BytecodeClassDefiner} one exists at all, is documented on
* {@link BytecodeClassDefiner#define}.
*/
private Class<?> defineClass(final CtClass ctClass) throws javassist.CannotCompileException {
if (targetClassLoader != null) {
if (targetClassLoader instanceof BytecodeClassDefiner) {
try {
return ((BytecodeClassDefiner) targetClassLoader)
.defineClass(ctClass.getName(), ctClass.toBytecode());
} catch (final IOException e) {
throw new javassist.CannotCompileException(
"failed to serialise " + ctClass.getName() + " bytes", e);
}
}
return ctClass.toClass(targetClassLoader, null);
}
return ctClass.toClass(LalExpressionPackageHolder.class);
private Class<?> defineClass(final CtClass ctClass) throws CannotCompileException {
return BytecodeClassDefiner.define(ctClass, targetClassLoader, LalExpressionPackageHolder.class);
}

private static boolean hasParsedAccess(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,21 @@
import org.apache.skywalking.oap.server.core.dsl.DslGeneratedFileWriter;
import org.apache.skywalking.oap.server.core.dsl.DslSourceRef;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtNewConstructor;
import javassist.CtNewMethod;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.oap.meter.analyzer.v2.compiler.rt.MalExpressionPackageHolder;
import org.apache.skywalking.oap.server.core.classloader.BytecodeClassDefiner;
import org.apache.skywalking.oap.server.core.dsl.classloader.BytecodeClassDefiner;
import org.apache.skywalking.oap.meter.analyzer.v2.dsl.ExpressionMetadata;
import org.apache.skywalking.oap.meter.analyzer.v2.dsl.MalExpression;
import org.apache.skywalking.oap.meter.analyzer.v2.dsl.MalFilter;
import org.apache.skywalking.oap.server.core.WorkPath;
import org.apache.skywalking.oap.server.library.util.StringUtil;
import org.apache.skywalking.oap.server.core.dsl.DslJavaSourceText;

/**
Expand Down Expand Up @@ -76,10 +74,7 @@ public final class MALClassGenerator {

public MALClassGenerator() {
this(createClassPool(), null);
if (StringUtil.isNotEmpty(System.getenv("SW_DYNAMIC_CLASS_ENGINE_DEBUG"))) {
bytecodeHelper.setClassOutputDir(
new File(WorkPath.getPath().getParentFile(), "mal-rt"));
}
bytecodeHelper.setClassOutputDir(DslGeneratedFileWriter.resolveClassDumpDir("mal"));
}

private static ClassPool createClassPool() {
Expand Down Expand Up @@ -251,29 +246,12 @@ private static String wrapMalFilterSource(final CtClass ctClass, final String fi
* (startup path: class lands in the OAP app loader alongside
* {@link MalExpressionPackageHolder}).
*
* <p>When {@code targetClassLoader} implements
* {@link org.apache.skywalking.oap.server.core.classloader.BytecodeClassDefiner
* BytecodeClassDefiner} (the runtime-rule {@code RuleClassLoader} does), we hand
* the loader the {@code CtClass.toBytecode()} bytes and let it invoke its public
* {@code defineClass} directly — no Javassist {@code toClass(loader,
* ProtectionDomain)} reflection, no {@code --add-opens java.base/java.lang}
* requirement on JDK 17+. Otherwise we fall back to the legacy 2-arg toClass for
* back-compat, but no shipped loader uses that path today.
* <p>Which of the two definition paths applies, and why the
* {@link BytecodeClassDefiner} one exists at all, is documented on
* {@link BytecodeClassDefiner#define}.
*/
private Class<?> defineClass(final CtClass ctClass) throws javassist.CannotCompileException {
if (targetClassLoader != null) {
if (targetClassLoader instanceof BytecodeClassDefiner) {
try {
return ((BytecodeClassDefiner) targetClassLoader)
.defineClass(ctClass.getName(), ctClass.toBytecode());
} catch (final IOException e) {
throw new javassist.CannotCompileException(
"failed to serialise " + ctClass.getName() + " bytes", e);
}
}
return ctClass.toClass(targetClassLoader, null);
}
return ctClass.toClass(MalExpressionPackageHolder.class);
private Class<?> defineClass(final CtClass ctClass) throws CannotCompileException {
return BytecodeClassDefiner.define(ctClass, targetClassLoader, MalExpressionPackageHolder.class);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
import org.apache.skywalking.oap.server.admin.dsl.debugging.session.InstallOutcome;
import org.apache.skywalking.oap.server.admin.dsl.debugging.session.Sample;
import org.apache.skywalking.oap.server.admin.dsl.debugging.session.SessionLimits;
import org.apache.skywalking.oap.server.core.classloader.Catalog;
import org.apache.skywalking.oap.server.core.dsl.Catalog;
import org.apache.skywalking.oap.server.core.dsl.debug.RuleKey;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import org.apache.skywalking.oap.server.admin.dsl.debugging.session.DebugRecorderFactory;
import org.apache.skywalking.oap.server.admin.dsl.debugging.session.Granularity;
import org.apache.skywalking.oap.server.admin.dsl.debugging.session.SessionLimits;
import org.apache.skywalking.oap.server.core.classloader.Catalog;
import org.apache.skywalking.oap.server.core.dsl.Catalog;
import org.apache.skywalking.oap.server.core.dsl.debug.GateHolder;
import org.apache.skywalking.oap.server.core.dsl.debug.RuleKey;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import java.util.concurrent.ConcurrentHashMap;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.oap.server.admin.dsl.debugging.session.DebugHolderLookup;
import org.apache.skywalking.oap.server.core.classloader.Catalog;
import org.apache.skywalking.oap.server.core.dsl.Catalog;
import org.apache.skywalking.oap.server.core.dsl.debug.GateHolder;
import org.apache.skywalking.oap.server.core.dsl.debug.RuleKey;
import org.apache.skywalking.oap.server.library.module.Service;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import org.apache.skywalking.oap.server.admin.dsl.debugging.session.AbstractDebugRecorder;
import org.apache.skywalking.oap.server.admin.dsl.debugging.session.DebugRecorderFactory;
import org.apache.skywalking.oap.server.admin.dsl.debugging.session.SessionLimits;
import org.apache.skywalking.oap.server.core.classloader.Catalog;
import org.apache.skywalking.oap.server.core.dsl.Catalog;
import org.apache.skywalking.oap.server.core.dsl.debug.GateHolder;
import org.apache.skywalking.oap.server.core.dsl.debug.RuleKey;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import java.util.concurrent.ConcurrentHashMap;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.oap.server.admin.dsl.debugging.session.DebugHolderLookup;
import org.apache.skywalking.oap.server.core.classloader.Catalog;
import org.apache.skywalking.oap.server.core.dsl.Catalog;
import org.apache.skywalking.oap.server.core.dsl.debug.GateHolder;
import org.apache.skywalking.oap.server.core.dsl.debug.RuleKey;
import org.apache.skywalking.oap.server.library.module.Service;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
import org.apache.skywalking.oap.server.admin.server.cluster.AdminClusterChannelManager;
import org.apache.skywalking.oap.server.admin.server.module.AdminServerModule;
import org.apache.skywalking.oap.server.core.analysis.DispatcherManager;
import org.apache.skywalking.oap.server.core.classloader.Catalog;
import org.apache.skywalking.oap.server.core.dsl.Catalog;
import org.apache.skywalking.oap.server.core.server.GRPCHandlerRegister;
import org.apache.skywalking.oap.server.core.source.SourceReceiver;
import org.apache.skywalking.oap.server.core.source.SourceReceiverImpl;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import org.apache.skywalking.oap.server.admin.dsl.debugging.session.AbstractDebugRecorder;
import org.apache.skywalking.oap.server.admin.dsl.debugging.session.DebugRecorderFactory;
import org.apache.skywalking.oap.server.admin.dsl.debugging.session.SessionLimits;
import org.apache.skywalking.oap.server.core.classloader.Catalog;
import org.apache.skywalking.oap.server.core.dsl.Catalog;
import org.apache.skywalking.oap.server.core.dsl.debug.GateHolder;
import org.apache.skywalking.oap.server.core.dsl.debug.RuleKey;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import lombok.RequiredArgsConstructor;
import org.apache.skywalking.oap.server.admin.dsl.debugging.session.DebugHolderLookup;
import org.apache.skywalking.oap.server.core.analysis.DispatcherManager;
import org.apache.skywalking.oap.server.core.classloader.Catalog;
import org.apache.skywalking.oap.server.core.dsl.Catalog;
import org.apache.skywalking.oap.server.core.dsl.debug.DebugHolderProvider;
import org.apache.skywalking.oap.server.core.dsl.debug.GateHolder;
import org.apache.skywalking.oap.server.core.dsl.debug.RuleKey;
Expand Down
Loading
Loading