This is an automated email from the ASF dual-hosted git repository. shushengzhou pushed a commit to branch build/graalvm-native-support in repository https://gitbox.apache.org/repos/asf/hertzbeat.git
commit b412308acbe5b449031d7b35a840c37f0207c176 Author: a-little-fool <[email protected]> AuthorDate: Mon Feb 16 09:52:10 2026 +0800 build(graalvm): add basic native image configuration Introduces necessary plugins and config files for GraalVM. Pending: Local verification and CI integration. --- .../alert/controller/AlertReportController.java | 15 +++--- .../impl/FeiShuAppAlertNotifyHandlerImpl.java | 7 --- .../notice/impl/SlackAlertNotifyHandlerImpl.java | 4 -- .../impl/WeComAppAlertNotifyHandlerImpl.java | 5 -- .../nativex/HertzbeatRuntimeHintsRegistrar.java | 54 ++++++++++++++++++++++ hertzbeat-startup/pom.xml | 54 ++++++++++++++++++++++ .../src/main/resources/application.yml | 1 + web-app/package.json | 2 +- 8 files changed, 119 insertions(+), 23 deletions(-) diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/controller/AlertReportController.java b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/controller/AlertReportController.java index cf81040abb..69e09c549d 100644 --- a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/controller/AlertReportController.java +++ b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/controller/AlertReportController.java @@ -19,6 +19,8 @@ package org.apache.hertzbeat.alert.controller; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; + +import java.math.BigInteger; import java.util.List; import lombok.extern.slf4j.Slf4j; import org.apache.hertzbeat.alert.service.ExternAlertService; @@ -39,7 +41,7 @@ import org.springframework.web.bind.annotation.RestController; @RestController @Slf4j public class AlertReportController { - + private final List<ExternAlertService> externAlertServiceList; public AlertReportController(List<ExternAlertService> externAlertServiceList) { @@ -48,7 +50,7 @@ public class AlertReportController { @PostMapping("/api/alerts/report/{source}") @Operation(summary = "Api for receive external alarm information") - public ResponseEntity<Message<Void>> receiveExternAlert(@PathVariable(value = "source") String source, + public ResponseEntity<Message<Void>> receiveExternAlert(@PathVariable(value = "source") String source, @RequestBody String content) { log.info("Receive extern alert from source: {}, content: {}", source, content); if (!StringUtils.hasText(source)) { @@ -58,10 +60,10 @@ public class AlertReportController { if (externAlertService.supportSource().equals(source)) { try { externAlertService.addExternAlert(content); - return ResponseEntity.ok(Message.success("Add extern alert success")); + return ResponseEntity.ok(Message.success("Add extern alert success")); } catch (Exception e) { return ResponseEntity.status(HttpStatus.BAD_REQUEST) - .body(Message.fail(CommonConstants.FAIL_CODE, + .body(Message.fail(CommonConstants.FAIL_CODE, "Add extern alert failed: " + e.getMessage())); } } @@ -80,16 +82,17 @@ public class AlertReportController { if (externAlertService != null) { try { externAlertService.addExternAlert(content); - return ResponseEntity.ok(Message.success("Add extern alert success")); + return ResponseEntity.ok(Message.success("Add extern alert success")); } catch (Exception e) { return ResponseEntity.status(HttpStatus.BAD_REQUEST) - .body(Message.fail(CommonConstants.FAIL_CODE, + .body(Message.fail(CommonConstants.FAIL_CODE, "Add extern alert failed: " + e.getMessage())); } } log.error("Not support default extern alert"); return ResponseEntity.status(HttpStatus.BAD_REQUEST) .body(Message.success("Not support the default source alert")); + BigInteger } @PostMapping("/api/v2/alerts") diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/notice/impl/FeiShuAppAlertNotifyHandlerImpl.java b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/notice/impl/FeiShuAppAlertNotifyHandlerImpl.java index 1c49c08af8..d53f53f58f 100644 --- a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/notice/impl/FeiShuAppAlertNotifyHandlerImpl.java +++ b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/notice/impl/FeiShuAppAlertNotifyHandlerImpl.java @@ -26,10 +26,8 @@ import lombok.Builder; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.apache.hertzbeat.alert.AlerterProperties; import org.apache.hertzbeat.alert.notice.AlertNoticeException; import org.apache.hertzbeat.common.entity.alerter.GroupAlert; import org.apache.hertzbeat.common.entity.alerter.NoticeReceiver; @@ -41,7 +39,6 @@ import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; -import org.springframework.web.client.RestTemplate; import java.util.ArrayList; import java.util.Arrays; @@ -54,7 +51,6 @@ import java.util.stream.Collectors; * FeiShu app alert notify impl */ @Component -@RequiredArgsConstructor @Slf4j public class FeiShuAppAlertNotifyHandlerImpl extends AbstractAlertNotifyHandlerImpl { @@ -84,9 +80,6 @@ public class FeiShuAppAlertNotifyHandlerImpl extends AbstractAlertNotifyHandlerI private static final byte PART_RECEIVE_TYPE = 2; private static final byte ALL_RECEIVE_TYPE = 3; - private final RestTemplate restTemplate; - private final AlerterProperties alerterProperties; - @Override public void send(NoticeReceiver receiver, NoticeTemplate noticeTemplate, GroupAlert alert) throws AlertNoticeException { var appId = receiver.getAppId(); diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/notice/impl/SlackAlertNotifyHandlerImpl.java b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/notice/impl/SlackAlertNotifyHandlerImpl.java index 8f782076cd..6e1b350951 100644 --- a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/notice/impl/SlackAlertNotifyHandlerImpl.java +++ b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/notice/impl/SlackAlertNotifyHandlerImpl.java @@ -21,7 +21,6 @@ import java.net.URI; import java.util.Objects; import lombok.Builder; import lombok.Data; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.hertzbeat.alert.notice.AlertNoticeException; import org.apache.hertzbeat.common.entity.alerter.GroupAlert; @@ -32,17 +31,14 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; -import org.springframework.web.client.RestTemplate; /** * Send alarm information by Slack Webhook */ @Component -@RequiredArgsConstructor @Slf4j final class SlackAlertNotifyHandlerImpl extends AbstractAlertNotifyHandlerImpl { private static final String SUCCESS = "ok"; - private final RestTemplate restTemplate; @Override public void send(NoticeReceiver receiver, NoticeTemplate noticeTemplate, GroupAlert alert) throws AlertNoticeException { diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/notice/impl/WeComAppAlertNotifyHandlerImpl.java b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/notice/impl/WeComAppAlertNotifyHandlerImpl.java index 2bb671f7fc..f6f413b555 100644 --- a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/notice/impl/WeComAppAlertNotifyHandlerImpl.java +++ b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/notice/impl/WeComAppAlertNotifyHandlerImpl.java @@ -23,7 +23,6 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.hertzbeat.alert.notice.AlertNoticeException; import org.apache.hertzbeat.common.entity.alerter.GroupAlert; @@ -34,13 +33,11 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; -import org.springframework.web.client.RestTemplate; /** * WeChat app alert notify impl */ @Component -@RequiredArgsConstructor @Slf4j public class WeComAppAlertNotifyHandlerImpl extends AbstractAlertNotifyHandlerImpl { @@ -59,8 +56,6 @@ public class WeComAppAlertNotifyHandlerImpl extends AbstractAlertNotifyHandlerIm */ private static final String DEFAULT_ALL = "@all"; - private final RestTemplate restTemplate; - @Override public void send(NoticeReceiver receiver, NoticeTemplate noticeTemplate, GroupAlert alert) throws AlertNoticeException { String corpId = receiver.getCorpId(); diff --git a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/nativex/HertzbeatRuntimeHintsRegistrar.java b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/nativex/HertzbeatRuntimeHintsRegistrar.java index 44d9b3a6a3..1f8846667c 100644 --- a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/nativex/HertzbeatRuntimeHintsRegistrar.java +++ b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/nativex/HertzbeatRuntimeHintsRegistrar.java @@ -20,7 +20,14 @@ package org.apache.hertzbeat.manager.nativex; import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.util.Arrays; import java.util.Set; +import org.apache.hertzbeat.common.entity.job.Configmap; +import org.apache.hertzbeat.common.entity.job.Job; +import org.apache.hertzbeat.common.entity.job.Metrics; +import org.apache.hertzbeat.common.entity.manager.ParamDefine; +import org.apache.hertzbeat.common.entity.plugin.PluginConfig; import org.apache.sshd.common.channel.ChannelListener; import org.apache.sshd.common.forward.PortForwardingEventListener; import org.apache.sshd.common.io.nio2.Nio2ServiceFactory; @@ -42,10 +49,19 @@ import org.springframework.util.ClassUtils; */ public class HertzbeatRuntimeHintsRegistrar implements RuntimeHintsRegistrar { + private static final MemberCategory[] YAML_MODEL_MEMBER_CATEGORIES = { + MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, + MemberCategory.INVOKE_DECLARED_METHODS, + MemberCategory.DECLARED_FIELDS + }; + private static final String SshConstantsClassName = "org.apache.sshd.common.SshConstants"; + private static final String JobProtocolPackageNamePrefix = "org.apache.hertzbeat.common.entity.job.protocol."; @Override public void registerHints(@NonNull RuntimeHints hints, ClassLoader classLoader) { + registerResourceHints(hints); + registerYamlModelHints(hints); // see: https://github.com/spring-cloud/spring-cloud-config/blob/main/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/ConfigServerRuntimeHints.java // TODO: move over to GraalVM reachability metadata if (ClassUtils.isPresent(SshConstantsClassName, classLoader)) { @@ -61,6 +77,44 @@ public class HertzbeatRuntimeHintsRegistrar implements RuntimeHintsRegistrar { } } + private void registerResourceHints(RuntimeHints hints) { + hints.resources().registerPattern("application*.yml"); + hints.resources().registerPattern("banner.txt"); + hints.resources().registerPattern("sureness.yml"); + hints.resources().registerPattern("logback-spring.xml"); + hints.resources().registerPattern("db/migration/**"); + hints.resources().registerPattern("define/*.yml"); + hints.resources().registerPattern("define/*.yaml"); + hints.resources().registerPattern("templates/**"); + hints.resources().registerPattern("grafana/*.json"); + hints.resources().registerPattern("dist/**"); + hints.resources().registerPattern("META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports"); + } + + private void registerYamlModelHints(RuntimeHints hints) { + registerTypeWithDeclaredMembers(hints, Job.class); + registerTypeWithDeclaredMembers(hints, Metrics.class); + registerTypeWithDeclaredMembers(hints, Metrics.Field.class); + registerTypeWithDeclaredMembers(hints, Configmap.class); + registerTypeWithDeclaredMembers(hints, ParamDefine.class); + registerTypeWithDeclaredMembers(hints, ParamDefine.Option.class); + registerTypeWithDeclaredMembers(hints, PluginConfig.class); + + Arrays.stream(Metrics.class.getDeclaredFields()) + .map(Field::getType) + .filter(this::isJobProtocolClass) + .forEach(type -> registerTypeWithDeclaredMembers(hints, type)); + } + + private boolean isJobProtocolClass(Class<?> type) { + return type.getName().startsWith(JobProtocolPackageNamePrefix); + } + + private void registerTypeWithDeclaredMembers(RuntimeHints hints, Class<?> clazz) { + hints.reflection().registerType(clazz, hint -> hint.withMembers(YAML_MODEL_MEMBER_CATEGORIES)); + registerConstructor(hints, clazz); + } + private void registerConstructor(RuntimeHints hints, Class<?> clazz) { Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors(); for (Constructor<?> declaredConstructor : declaredConstructors) { diff --git a/hertzbeat-startup/pom.xml b/hertzbeat-startup/pom.xml index f45a196a6b..e4782dfddb 100644 --- a/hertzbeat-startup/pom.xml +++ b/hertzbeat-startup/pom.xml @@ -201,6 +201,60 @@ </build> <profiles> + <profile> + <id>native</id> + <build> + <plugins> + <plugin> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-maven-plugin</artifactId> + <executions> + <execution> + <id>process-aot</id> + <goals> + <goal>process-aot</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.graalvm.buildtools</groupId> + <artifactId>native-maven-plugin</artifactId> + <configuration> + <mainClass>org.apache.hertzbeat.startup.HertzBeatApplication</mainClass> + <fallback>false</fallback> + <verbose>true</verbose> + <buildArgs> + <buildArg>-H:+ReportExceptionStackTraces</buildArg> + <buildArg>-H:TempDirectory=${project.build.directory}/native-temp</buildArg> + <buildArg>--initialize-at-build-time=org.apache.sshd.sftp.client.fs.SftpFileSystemProvider</buildArg> + <buildArg>--initialize-at-run-time=io.grpc.netty.shaded.io.netty.channel.epoll</buildArg> + <buildArg>--initialize-at-run-time=io.netty.channel.epoll</buildArg> + <buildArg>--initialize-at-run-time=io.grpc.netty.shaded.io.netty.channel.unix</buildArg> + <buildArg>--initialize-at-run-time=io.netty.channel.unix</buildArg> + </buildArgs> + <environment> + <TMPDIR>${project.build.directory}/native-temp</TMPDIR> + <TEMP>${project.build.directory}/native-temp</TEMP> + <TMP>${project.build.directory}/native-temp</TMP> + </environment> + <metadataRepository> + <enabled>true</enabled> + </metadataRepository> + </configuration> + <executions> + <execution> + <id>build-native</id> + <phase>package</phase> + <goals> + <goal>compile-no-fork</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> <profile> <id>release</id> <build> diff --git a/hertzbeat-startup/src/main/resources/application.yml b/hertzbeat-startup/src/main/resources/application.yml index 85ff831d59..e58ae512ec 100644 --- a/hertzbeat-startup/src/main/resources/application.yml +++ b/hertzbeat-startup/src/main/resources/application.yml @@ -14,6 +14,7 @@ # limitations under the License. server: port: 1157 + address: 0.0.0.0 spring: application: name: ${HOSTNAME:@hertzbeat@}${PID} diff --git a/web-app/package.json b/web-app/package.json index d750e6bcb3..a1ea6ee727 100644 --- a/web-app/package.json +++ b/web-app/package.json @@ -20,7 +20,7 @@ ], "scripts": { "ng": "ng", - "start": "ng serve --proxy-config proxy.conf.json", + "start": "ng serve --proxy-config proxy.conf.json --host 0.0.0.0", "build": "npm run ng-high-memory build", "watch": "ng build --watch --configuration development", "test": "ng test", --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
