This is an automated email from the ASF dual-hosted git repository.
wusheng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-graalvm-distro.git
The following commit(s) were added to refs/heads/main by this push:
new 9b68f0e Distro packaging: version, log4j2, alarm config, and
native-image readiness
9b68f0e is described below
commit 9b68f0e5cc62d6132315b5bda75aadc1c9068bb1
Author: Wu Sheng <[email protected]>
AuthorDate: Tue Feb 24 11:57:25 2026 +0800
Distro packaging: version, log4j2, alarm config, and native-image readiness
- version.properties: copy from submodule, replace -SNAPSHOT with short
commit ID, append -graal-distro suffix (e.g. 10.4.0-b537891-graal-distro).
Placed in config/ (first on classpath) to shadow any JAR copies.
- server-starter-for-graalvm: repackaged server-starter via shade plugin
with version.properties excluded, preventing classpath conflict in both
JVM distro and native-image builds. Original server-starter excluded
from assembly and marked provided in oap-graalvm-native.
- log4j2.xml and alarm-settings.yml now sourced from dist-material/
(production configs) instead of server-starter/ (dev configs), matching
upstream apm-dist packaging. dist-material log4j2 uses RollingFile
appender at INFO level with no custom %swversion plugin dependency.
- sw.version system property set in GraalVMOAPServerStartUp.main() before
log4j2 init, enabling ${sys:sw.version} in log patterns as a standard
log4j2 lookup replacement for the custom VersionLogConverter plugin.
- Makefile build-distro: add oap-libs-for-graalvm child module build
phase to ensure all for-graalvm shaded JARs are installed.
- StorageBuilder scan in precompiler for native-image reflection config.
- FieldsHelper same-FQCN replacement, NoneConfigurationProvider support,
native-image build args (AddAllCharsets, URL protocols).
---
Makefile | 1 +
.../server/buildtools/precompiler/Precompiler.java | 48 +++++
oap-graalvm-native/pom.xml | 10 ++
.../oap-graalvm-native/reflect-config.json | 44 +++++
oap-graalvm-server/pom.xml | 48 ++++-
.../src/main/assembly/distribution.xml | 29 +++-
.../server/graalvm/GraalVMOAPServerStartUp.java | 15 +-
.../oap/server/library/util/FieldsHelper.java | 193 +++++++++++++++++++++
.../src/main/resources/application.yml | 1 +
.../library-util-for-graalvm/pom.xml | 2 +
oap-libs-for-graalvm/pom.xml | 1 +
.../pom.xml | 19 +-
pom.xml | 5 +
13 files changed, 395 insertions(+), 21 deletions(-)
diff --git a/Makefile b/Makefile
index 1ef37aa..011cfb3 100644
--- a/Makefile
+++ b/Makefile
@@ -55,6 +55,7 @@ javadoc:
# Phase 2: package oap-graalvm-server and oap-graalvm-native with assembly.
build-distro:
$(MVN) clean install -pl oap-libs-for-graalvm -am -DskipTests
$(MVN_ARGS)
+ $(MVN) install -f oap-libs-for-graalvm -DskipTests $(MVN_ARGS)
$(MVN) package -pl oap-graalvm-server,oap-graalvm-native -DskipTests
$(MVN_ARGS)
# Show the distribution directory
diff --git
a/build-tools/precompiler/src/main/java/org/apache/skywalking/oap/server/buildtools/precompiler/Precompiler.java
b/build-tools/precompiler/src/main/java/org/apache/skywalking/oap/server/buildtools/precompiler/Precompiler.java
index 957a09a..766d785 100644
---
a/build-tools/precompiler/src/main/java/org/apache/skywalking/oap/server/buildtools/precompiler/Precompiler.java
+++
b/build-tools/precompiler/src/main/java/org/apache/skywalking/oap/server/buildtools/precompiler/Precompiler.java
@@ -191,6 +191,11 @@ public class Precompiler {
writeManifest(annotationScanDir.resolve("MeterFunction.txt"),
scanMeterFunctions(allClasses));
+ // StorageBuilder scan: extract builder() class from @Stream
annotations
+ // These are instantiated via getDeclaredConstructor().newInstance()
at runtime
+ writeManifest(annotationScanDir.resolve("StorageBuilders.txt"),
+ scanStorageBuilders(allClasses));
+
// ---- MAL pre-compilation ----
compileMAL(outputDir, allClasses);
@@ -745,6 +750,46 @@ public class Precompiler {
return result;
}
+ /**
+ * Scan @Stream-annotated classes for their builder() class reference, and
+ * @MeterFunction-annotated classes for their AcceptableValue.builder()
return type.
+ * These StorageBuilder classes are instantiated via
getDeclaredConstructor().newInstance()
+ * at runtime and need reflection registration for native image.
+ */
+ private static List<String> scanStorageBuilders(
+ ImmutableSet<ClassPath.ClassInfo> allClasses) {
+
+ List<String> result = new ArrayList<>();
+ for (ClassPath.ClassInfo classInfo : allClasses) {
+ try {
+ Class<?> aClass = classInfo.load();
+ // @Stream-annotated classes declare builder in annotation
+ if
(aClass.isAnnotationPresent(org.apache.skywalking.oap.server.core.analysis.Stream.class))
{
+ org.apache.skywalking.oap.server.core.analysis.Stream
stream =
+
aClass.getAnnotation(org.apache.skywalking.oap.server.core.analysis.Stream.class);
+ Class<?> builderClass = stream.builder();
+ if (builderClass != null && builderClass != void.class) {
+ result.add(builderClass.getName());
+ }
+ }
+ // @MeterFunction classes have StorageBuilder inner classes
+ if (aClass.isAnnotationPresent(MeterFunction.class)) {
+ for (Class<?> inner : aClass.getDeclaredClasses()) {
+ if
(org.apache.skywalking.oap.server.core.storage.type.StorageBuilder.class
+ .isAssignableFrom(inner)) {
+ result.add(inner.getName());
+ }
+ }
+ }
+ } catch (NoClassDefFoundError | Exception ignored) {
+ }
+ }
+ // Deduplicate (multiple @Stream classes may share the same builder)
+ result =
result.stream().distinct().sorted().collect(Collectors.toList());
+ log.info("Scanned StorageBuilder classes: {} unique entries",
result.size());
+ return result;
+ }
+
/**
* Serialize MAL config data (Rules and MeterConfigs) as JSON for runtime
loaders.
* At runtime, replacement loader classes deserialize from these JSON
files instead
@@ -884,6 +929,9 @@ public class Precompiler {
}
}
+ // StorageBuilder classes — constructor-only (instantiated via
getDeclaredConstructor().newInstance())
+ addConstructorEntries(entries,
annotationScanDir.resolve("StorageBuilders.txt"));
+
// OAL metrics and dispatchers — constructor-only
addConstructorEntries(entries,
metaInf.resolve("oal-metrics-classes.txt"));
addConstructorEntries(entries,
metaInf.resolve("oal-dispatcher-classes.txt"));
diff --git a/oap-graalvm-native/pom.xml b/oap-graalvm-native/pom.xml
index 6359a58..7f4de45 100644
--- a/oap-graalvm-native/pom.xml
+++ b/oap-graalvm-native/pom.xml
@@ -36,6 +36,14 @@
<groupId>org.apache.skywalking</groupId>
<artifactId>oap-graalvm-server</artifactId>
</dependency>
+ <!-- Override transitive server-starter (which contains a conflicting
+ version.properties) with provided scope. The repackaged
+ server-starter-for-graalvm (without version.properties) is used
instead. -->
+ <dependency>
+ <groupId>org.apache.skywalking</groupId>
+ <artifactId>server-starter</artifactId>
+ <scope>provided</scope>
+ </dependency>
<!-- Override transitive groovy (compile) from server-core to test
scope.
Runtime uses groovy-stubs instead. -->
<dependency>
@@ -70,6 +78,8 @@
<buildArg>--no-fallback</buildArg>
<buildArg>--verbose</buildArg>
<buildArg>-H:+ReportExceptionStackTraces</buildArg>
+ <buildArg>-H:+AddAllCharsets</buildArg>
+
<buildArg>--enable-url-protocols=https,http</buildArg>
</buildArgs>
</configuration>
<executions>
diff --git
a/oap-graalvm-native/src/main/resources/META-INF/native-image/org.apache.skywalking/oap-graalvm-native/reflect-config.json
b/oap-graalvm-native/src/main/resources/META-INF/native-image/org.apache.skywalking/oap-graalvm-native/reflect-config.json
new file mode 100644
index 0000000..2da0b03
--- /dev/null
+++
b/oap-graalvm-native/src/main/resources/META-INF/native-image/org.apache.skywalking/oap-graalvm-native/reflect-config.json
@@ -0,0 +1,44 @@
+[
+ {
+ "name": "org.apache.skywalking.oap.log.analyzer.provider.LALConfigs",
+ "allDeclaredFields": true,
+ "allDeclaredMethods": true,
+ "allDeclaredConstructors": true
+ },
+ {
+ "name": "org.apache.skywalking.oap.log.analyzer.provider.LALConfig",
+ "allDeclaredFields": true,
+ "allDeclaredMethods": true,
+ "allDeclaredConstructors": true
+ },
+ {
+ "name":
"org.apache.skywalking.oap.server.analyzer.provider.meter.config.MeterConfig",
+ "allDeclaredFields": true,
+ "allDeclaredMethods": true,
+ "allDeclaredConstructors": true
+ },
+ {
+ "name": "org.apache.skywalking.oap.meter.analyzer.prometheus.rule.Rule",
+ "allDeclaredFields": true,
+ "allDeclaredMethods": true,
+ "allDeclaredConstructors": true
+ },
+ {
+ "name":
"org.apache.skywalking.oap.meter.analyzer.prometheus.rule.MetricsRule",
+ "allDeclaredFields": true,
+ "allDeclaredMethods": true,
+ "allDeclaredConstructors": true
+ },
+ {
+ "name":
"org.apache.skywalking.oap.server.core.management.ui.menu.UIMenuInitializer$MenuData",
+ "allDeclaredFields": true,
+ "allDeclaredMethods": true,
+ "allDeclaredConstructors": true
+ },
+ {
+ "name":
"org.apache.skywalking.oap.server.core.management.ui.menu.UIMenuItemSetting",
+ "allDeclaredFields": true,
+ "allDeclaredMethods": true,
+ "allDeclaredConstructors": true
+ }
+]
diff --git a/oap-graalvm-server/pom.xml b/oap-graalvm-server/pom.xml
index 6e48d82..316bd19 100644
--- a/oap-graalvm-server/pom.xml
+++ b/oap-graalvm-server/pom.xml
@@ -117,6 +117,12 @@
<version>${skywalking.version}</version>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.skywalking</groupId>
+ <artifactId>server-starter</artifactId>
+ <version>${skywalking.version}</version>
+ <scope>provided</scope>
+ </dependency>
</dependencies>
</dependencyManagement>
@@ -340,10 +346,10 @@
<artifactId>ai-pipeline</artifactId>
</dependency>
- <!-- Server Starter (for ApplicationConfigLoader) -->
+ <!-- Server Starter (for ApplicationConfigLoader, version.properties
excluded) -->
<dependency>
<groupId>org.apache.skywalking</groupId>
- <artifactId>server-starter</artifactId>
+ <artifactId>server-starter-for-graalvm</artifactId>
</dependency>
<!-- Pre-compiled classes + manifests from build-time precompiler -->
@@ -462,6 +468,44 @@
</target>
</configuration>
</execution>
+ <!-- Copy version.properties from submodule, patch version
for graal-distro.
+ If version has -SNAPSHOT, replace it with the short
commit ID.
+ e.g. 10.4.0-SNAPSHOT -> 10.4.0-b537891-graal-distro
+ Release versions just get the suffix: 10.4.0 ->
10.4.0-graal-distro -->
+ <execution>
+ <id>copy-version-properties</id>
+ <phase>generate-resources</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ <configuration>
+ <target>
+ <copy
file="${project.basedir}/../skywalking/oap-server/server-starter/src/main/resources/version.properties"
+
tofile="${project.build.outputDirectory}/version.properties"
+ overwrite="true"/>
+ <!-- Load the commit id from the copied file
-->
+ <loadproperties
srcFile="${project.build.outputDirectory}/version.properties"
+ prefix="upstream."/>
+ <!-- Extract first 7 chars of commit id -->
+ <loadresource
property="upstream.git.commit.id.short">
+ <string value="${upstream.git.commit.id}"/>
+ <filterchain>
+ <replaceregex pattern="^(.{7}).*$"
replace="\1"/>
+ </filterchain>
+ </loadresource>
+ <!-- Replace -SNAPSHOT with -<short-commit>
(only matches if -SNAPSHOT exists) -->
+ <replaceregexp
file="${project.build.outputDirectory}/version.properties"
+
match="^(git\.build\.version=.*)-SNAPSHOT$"
+
replace="\1-${upstream.git.commit.id.short}"
+ byline="true"/>
+ <!-- Append -graal-distro suffix -->
+ <replaceregexp
file="${project.build.outputDirectory}/version.properties"
+
match="^(git\.build\.version=.+)$"
+ replace="\1-graal-distro"
+ byline="true"/>
+ </target>
+ </configuration>
+ </execution>
</executions>
</plugin>
<!-- Assemble distribution folder: bin/ + config/ + libs/ +
VERSION -->
diff --git a/oap-graalvm-server/src/main/assembly/distribution.xml
b/oap-graalvm-server/src/main/assembly/distribution.xml
index 3f4ae8a..8f64d58 100644
--- a/oap-graalvm-server/src/main/assembly/distribution.xml
+++ b/oap-graalvm-server/src/main/assembly/distribution.xml
@@ -50,10 +50,32 @@
<include>application.yml</include>
</includes>
</fileSet>
+ <!-- config/ — patched version.properties (graal-distro suffix).
+ Placed in config/ which is first on the classpath, ensuring it
takes
+ precedence over the original version.properties in server-starter
JAR. -->
+ <fileSet>
+ <directory>${project.build.outputDirectory}</directory>
+ <outputDirectory>config</outputDirectory>
+ <includes>
+ <include>version.properties</include>
+ </includes>
+ </fileSet>
+ <!-- config/ — production configs from dist-material (same as upstream
apm-dist).
+ These override server-starter versions: dist-material has
production-ready
+ logging (RollingFile, INFO level) and alarm rules. -->
+ <fileSet>
+
<directory>${project.basedir}/../skywalking/dist-material</directory>
+ <outputDirectory>config</outputDirectory>
+ <includes>
+ <include>log4j2.xml</include>
+ <include>alarm-settings.yml</include>
+ </includes>
+ </fileSet>
<!-- config/ — upstream resource files loaded at runtime.
OAL/MAL/LAL scripts are NOT included — they are pre-compiled at
build time
and loaded from manifests + pre-compiled .class files in JARs.
- Only runtime config files (loaded via ResourceUtils.read()) are
packaged. -->
+ Only runtime config files (loaded via ResourceUtils.read()) are
packaged.
+ log4j2.xml and alarm-settings.yml come from dist-material above.
-->
<fileSet>
<directory>${project.basedir}/../skywalking/oap-server/server-starter/src/main/resources</directory>
<outputDirectory>config</outputDirectory>
@@ -61,16 +83,12 @@
<!-- BanyanDB storage config (loaded by BanyanDBConfigLoader)
-->
<include>bydb.yml</include>
<include>bydb-topn.yml</include>
- <!-- Logging -->
- <include>log4j2.xml</include>
<!-- UI dashboard templates (loaded by UITemplateInitializer)
-->
<include>ui-initialized-templates/**</include>
<!-- Cilium rules (loaded by CiliumFetcherProvider) -->
<include>cilium-rules/**</include>
<!-- OpenAPI endpoint grouping definitions -->
<include>openapi-definitions/**</include>
- <!-- Alarm rules (loaded by AlarmModuleProvider) -->
- <include>alarm-settings.yml</include>
<!-- Component library definitions (loaded by
ComponentLibraryCatalogService) -->
<include>component-libraries.yml</include>
<!-- Endpoint name grouping (loaded by
EndpointNameGroupingRuleWatcher) -->
@@ -108,6 +126,7 @@
<useProjectArtifact>true</useProjectArtifact>
<excludes>
<exclude>org.apache.skywalking:server-core</exclude>
+ <exclude>org.apache.skywalking:server-starter</exclude>
<exclude>org.apache.skywalking:library-util</exclude>
<exclude>org.apache.skywalking:meter-analyzer</exclude>
<exclude>org.apache.skywalking:log-analyzer</exclude>
diff --git
a/oap-graalvm-server/src/main/java/org/apache/skywalking/oap/server/graalvm/GraalVMOAPServerStartUp.java
b/oap-graalvm-server/src/main/java/org/apache/skywalking/oap/server/graalvm/GraalVMOAPServerStartUp.java
index 0c2e825..96ddd8f 100644
---
a/oap-graalvm-server/src/main/java/org/apache/skywalking/oap/server/graalvm/GraalVMOAPServerStartUp.java
+++
b/oap-graalvm-server/src/main/java/org/apache/skywalking/oap/server/graalvm/GraalVMOAPServerStartUp.java
@@ -18,6 +18,7 @@
package org.apache.skywalking.oap.server.graalvm;
import lombok.extern.slf4j.Slf4j;
+import org.apache.skywalking.oap.server.core.version.Version;
import org.apache.skywalking.oap.server.core.CoreModule;
import org.apache.skywalking.oap.server.core.CoreModuleProvider;
import org.apache.skywalking.oap.server.core.RunningMode;
@@ -42,6 +43,7 @@ import
org.apache.skywalking.oap.server.cluster.plugin.standalone.ClusterModuleS
import
org.apache.skywalking.oap.server.cluster.plugin.kubernetes.ClusterModuleKubernetesProvider;
// Configuration
import org.apache.skywalking.oap.server.configuration.api.ConfigurationModule;
+import
org.apache.skywalking.oap.server.configuration.api.NoneConfigurationProvider;
import
org.apache.skywalking.oap.server.configuration.configmap.ConfigmapConfigurationProvider;
// Telemetry
import org.apache.skywalking.oap.server.telemetry.TelemetryModule;
@@ -128,6 +130,10 @@ import
org.apache.skywalking.oap.server.ai.pipeline.AIPipelineProvider;
public class GraalVMOAPServerStartUp {
public static void main(String[] args) {
+ // Expose version as system property so log4j2 patterns can use
${sys:sw.version}
+ // instead of the custom %swversion converter that requires plugin
discovery.
+ System.setProperty("sw.version", Version.CURRENT.toString());
+
// Ensure Log4j2 finds its config from the filesystem config/
directory.
// In JVM mode config/ is on the classpath; native images have no
classpath.
if (System.getProperty("log4j2.configurationFile") == null) {
@@ -189,8 +195,13 @@ public class GraalVMOAPServerStartUp {
}
// Storage: BanyanDB
manager.register(new StorageModule(), new BanyanDBStorageProvider());
- // Configuration: Kubernetes ConfigMap
- manager.register(new ConfigurationModule(), new
ConfigmapConfigurationProvider());
+ // Configuration: Kubernetes ConfigMap or None
+ ApplicationConfiguration.ModuleConfiguration configConfig =
configuration.getModuleConfiguration("configuration");
+ if (configConfig != null && configConfig.has("k8s-configmap")) {
+ manager.register(new ConfigurationModule(), new
ConfigmapConfigurationProvider());
+ } else {
+ manager.register(new ConfigurationModule(), new
NoneConfigurationProvider());
+ }
// Telemetry: Prometheus
manager.register(new TelemetryModule(), new
PrometheusTelemetryProvider());
diff --git
a/oap-graalvm-server/src/main/java/org/apache/skywalking/oap/server/library/util/FieldsHelper.java
b/oap-graalvm-server/src/main/java/org/apache/skywalking/oap/server/library/util/FieldsHelper.java
new file mode 100644
index 0000000..b9db45c
--- /dev/null
+++
b/oap-graalvm-server/src/main/java/org/apache/skywalking/oap/server/library/util/FieldsHelper.java
@@ -0,0 +1,193 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.skywalking.oap.server.library.util;
+
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+import com.google.protobuf.Struct;
+import com.google.protobuf.Value;
+import lombok.RequiredArgsConstructor;
+import lombok.experimental.Delegate;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.yaml.snakeyaml.Yaml;
+
+import java.io.InputStream;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.BiConsumer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+/**
+ * Same-FQCN replacement for native-image compatibility.
+ *
+ * <p>Upstream uses {@code LambdaMetafactory.metafactory()} to create setter
+ * wrappers at runtime, which fails in GraalVM native images (cannot define
+ * classes at runtime). This replacement uses {@link MethodHandle#invoke()}
+ * directly, which is supported by GraalVM.
+ */
+@Slf4j
+public class FieldsHelper {
+
+ private static final Map<Class<?>, FieldsHelper> HELPER_MAP = new
ConcurrentHashMap<>();
+
+ private final Class<?> targetClass;
+ private boolean initialized = false;
+ private Map<String, FieldFormat> fieldNameMapping;
+ private Map<String, BiConsumer<Object, String>> fieldSetterMapping;
+
+ public static FieldsHelper forClass(final Class<?> targetClass) {
+ return HELPER_MAP.computeIfAbsent(targetClass, FieldsHelper::new);
+ }
+
+ private FieldsHelper(Class<?> targetClass) {
+ this.targetClass = targetClass;
+ }
+
+ public void init(final String file) throws Exception {
+ init(ResourceUtils.readToStream(file));
+ }
+
+ public void init(final InputStream inputStream) {
+ if (initialized) {
+ return;
+ }
+
+ final Yaml yaml = new Yaml();
+ final Map<String, String> config = yaml.load(inputStream);
+
+ fieldNameMapping = new HashMap<>(config.size());
+ fieldSetterMapping = new HashMap<>(config.size());
+
+ for (final Map.Entry<String, String> entry : config.entrySet()) {
+ final String serviceMetaInfoFieldName = entry.getKey();
+ final String flatBuffersFieldName = entry.getValue();
+
+ final Pattern p = Pattern.compile("(\\$\\{(?<properties>.+?)})");
+ final Matcher m = p.matcher(flatBuffersFieldName);
+ final List<Property> flatBuffersFieldNames = new
ArrayList<>(m.groupCount());
+ final StringBuffer serviceNamePattern = new StringBuffer();
+ while (m.find()) {
+ final String properties = m.group("properties");
+ final List<Field> fields =
Splitter.on(',').omitEmptyStrings().splitToList(properties).stream().map(candidate
-> {
+ List<String> tokens =
Splitter.on('.').omitEmptyStrings().splitToList(candidate);
+
+ StringBuilder tokenBuffer = new StringBuilder();
+ List<String> candidateFields = new
ArrayList<>(tokens.size());
+ for (String token : tokens) {
+ if (tokenBuffer.length() == 0 &&
token.startsWith("\"")) {
+ tokenBuffer.append(token);
+ } else if (tokenBuffer.length() > 0) {
+ tokenBuffer.append(".").append(token);
+ } else {
+ candidateFields.add(token);
+ }
+
+ if (tokenBuffer.length() > 0 && token.endsWith("\"")) {
+
candidateFields.add(tokenBuffer.toString().replaceAll("\"", ""));
+ tokenBuffer.setLength(0);
+ }
+ }
+ return new Field(candidateFields);
+ }).collect(Collectors.toList());
+ flatBuffersFieldNames.add(new Property(fields));
+ m.appendReplacement(serviceNamePattern, "%s");
+ }
+
+ fieldNameMapping.put(
+ serviceMetaInfoFieldName,
+ new FieldFormat(serviceNamePattern.toString(),
flatBuffersFieldNames)
+ );
+
+ try {
+ final String setter = "set" +
StringUtils.capitalize(serviceMetaInfoFieldName);
+ final MethodHandles.Lookup lookup = MethodHandles.lookup();
+ final MethodHandle mh = lookup.findVirtual(
+ targetClass, setter, MethodType.methodType(void.class,
String.class));
+ // Wrap MethodHandle in a BiConsumer without LambdaMetafactory
+ fieldSetterMapping.put(serviceMetaInfoFieldName, (obj, val) ->
{
+ try {
+ mh.invoke(obj, val);
+ } catch (Throwable t) {
+ throw new RuntimeException("Failed to invoke " +
setter, t);
+ }
+ });
+ } catch (final Throwable e) {
+ throw new IllegalStateException("Initialize method error", e);
+ }
+ }
+ initialized = true;
+ }
+
+ public void inflate(final Struct metadata, final Object target) {
+ final Value empty = Value.newBuilder().setStringValue("-").build();
+ final Value root = Value.newBuilder().setStructValue(metadata).build();
+ for (final var entry : fieldNameMapping.entrySet()) {
+ final FieldFormat fieldFormat = entry.getValue();
+ final Object[] values = new String[fieldFormat.properties.size()];
+ for (int i = 0; i < fieldFormat.properties.size(); i++) {
+ values[i] = "-";
+ final Property property = fieldFormat.properties.get(i);
+ for (final Field field : property) {
+ Value value = root;
+ for (final String segment : field.dsvSegments) {
+ final var fieldMaps = new TreeMap<String,
Value>(String.CASE_INSENSITIVE_ORDER);
+
fieldMaps.putAll(value.getStructValue().getFieldsMap());
+ value = fieldMaps.getOrDefault(segment, empty);
+ }
+ if (Strings.isNullOrEmpty(value.getStringValue()) ||
"-".equals(value.getStringValue())) {
+ continue;
+ }
+ values[i] = value.getStringValue();
+ break;
+ }
+ }
+ final String value = Strings.lenientFormat(fieldFormat.format,
values);
+ if (!Strings.isNullOrEmpty(value)) {
+ fieldSetterMapping.get(entry.getKey()).accept(target, value);
+ }
+ }
+ }
+
+ @RequiredArgsConstructor
+ private static class FieldFormat {
+ private final String format;
+ private final List<Property> properties;
+ }
+
+ @RequiredArgsConstructor
+ private static class Property implements Iterable<Field> {
+ @Delegate
+ private final List<Field> candidateFields;
+ }
+
+ @RequiredArgsConstructor
+ private static class Field implements Iterable<String> {
+ @Delegate
+ private final List<String> dsvSegments;
+ }
+}
diff --git a/oap-graalvm-server/src/main/resources/application.yml
b/oap-graalvm-server/src/main/resources/application.yml
index eedc328..704fa98 100644
--- a/oap-graalvm-server/src/main/resources/application.yml
+++ b/oap-graalvm-server/src/main/resources/application.yml
@@ -315,6 +315,7 @@ telemetry:
configuration:
selector: ${SW_CONFIGURATION:k8s-configmap}
+ none:
k8s-configmap:
period: ${SW_CONFIG_CONFIGMAP_PERIOD:60}
namespace: ${SW_CLUSTER_K8S_NAMESPACE:default}
diff --git a/oap-libs-for-graalvm/library-util-for-graalvm/pom.xml
b/oap-libs-for-graalvm/library-util-for-graalvm/pom.xml
index bdc301c..ab03e5b 100644
--- a/oap-libs-for-graalvm/library-util-for-graalvm/pom.xml
+++ b/oap-libs-for-graalvm/library-util-for-graalvm/pom.xml
@@ -59,6 +59,8 @@
<excludes>
<exclude>org/apache/skywalking/oap/server/library/util/YamlConfigLoaderUtils.class</exclude>
<exclude>org/apache/skywalking/oap/server/library/util/ResourceUtils.class</exclude>
+
<exclude>org/apache/skywalking/oap/server/library/util/FieldsHelper.class</exclude>
+
<exclude>org/apache/skywalking/oap/server/library/util/FieldsHelper$*.class</exclude>
</excludes>
</filter>
</filters>
diff --git a/oap-libs-for-graalvm/pom.xml b/oap-libs-for-graalvm/pom.xml
index d20cb02..826a501 100644
--- a/oap-libs-for-graalvm/pom.xml
+++ b/oap-libs-for-graalvm/pom.xml
@@ -47,6 +47,7 @@
<module>cilium-fetcher-for-graalvm</module>
<module>status-query-for-graalvm</module>
<module>health-checker-for-graalvm</module>
+ <module>server-starter-for-graalvm</module>
</modules>
<build>
diff --git a/oap-libs-for-graalvm/library-util-for-graalvm/pom.xml
b/oap-libs-for-graalvm/server-starter-for-graalvm/pom.xml
similarity index 72%
copy from oap-libs-for-graalvm/library-util-for-graalvm/pom.xml
copy to oap-libs-for-graalvm/server-starter-for-graalvm/pom.xml
index bdc301c..02d013e 100644
--- a/oap-libs-for-graalvm/library-util-for-graalvm/pom.xml
+++ b/oap-libs-for-graalvm/server-starter-for-graalvm/pom.xml
@@ -27,18 +27,14 @@
<version>1.0.0-SNAPSHOT</version>
</parent>
- <artifactId>library-util-for-graalvm</artifactId>
- <name>Library Util for GraalVM</name>
- <description>Repackaged library-util with GraalVM-compatible
YamlConfigLoaderUtils</description>
+ <artifactId>server-starter-for-graalvm</artifactId>
+ <name>Server Starter for GraalVM</name>
+ <description>Repackaged server-starter with version.properties excluded
(provided by oap-graalvm-server)</description>
<dependencies>
<dependency>
<groupId>org.apache.skywalking</groupId>
- <artifactId>library-util</artifactId>
- </dependency>
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
+ <artifactId>server-starter</artifactId>
</dependency>
</dependencies>
@@ -50,15 +46,14 @@
<configuration>
<artifactSet>
<includes>
-
<include>org.apache.skywalking:library-util</include>
+
<include>org.apache.skywalking:server-starter</include>
</includes>
</artifactSet>
<filters>
<filter>
-
<artifact>org.apache.skywalking:library-util</artifact>
+
<artifact>org.apache.skywalking:server-starter</artifact>
<excludes>
-
<exclude>org/apache/skywalking/oap/server/library/util/YamlConfigLoaderUtils.class</exclude>
-
<exclude>org/apache/skywalking/oap/server/library/util/ResourceUtils.class</exclude>
+ <exclude>version.properties</exclude>
</excludes>
</filter>
</filters>
diff --git a/pom.xml b/pom.xml
index 2ec0877..9caf74d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -424,6 +424,11 @@
<artifactId>health-checker-for-graalvm</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.skywalking</groupId>
+ <artifactId>server-starter-for-graalvm</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>groovy-stubs</artifactId>