This is an automated email from the ASF dual-hosted git repository.
zhaoqingran pushed a commit to branch udf
in repository https://gitbox.apache.org/repos/asf/hertzbeat.git
The following commit(s) were added to refs/heads/udf by this push:
new 840134c93 [feature]Hertzbeat custom plugin.
840134c93 is described below
commit 840134c93d03bf80ec592f44b0d266bc7e274935
Author: zqr10159 <[email protected]>
AuthorDate: Mon May 13 00:44:16 2024 +0800
[feature]Hertzbeat custom plugin.
---
.../org/apache/hertzbeat/common/util/UdfUtil.java | 87 -----------
manager/pom.xml | 2 +-
.../java/org/apache/hertzbeat/manager/Manager.java | 3 +
.../manager/component/alerter/DispatcherAlarm.java | 48 ++-----
.../hertzbeat/manager/config/PluginConfig.java | 160 +++++++++++++++++++++
plugin/pom.xml | 44 ++++++
.../java/org/apache/hertzbeat/plugin/Plugin.java | 6 +-
.../hertzbeat/plugin/impl/DemoPluginImpl1.java | 9 +-
pom.xml | 4 +-
9 files changed, 230 insertions(+), 133 deletions(-)
diff --git a/common/src/main/java/org/apache/hertzbeat/common/util/UdfUtil.java
b/common/src/main/java/org/apache/hertzbeat/common/util/UdfUtil.java
deleted file mode 100644
index b32b289c5..000000000
--- a/common/src/main/java/org/apache/hertzbeat/common/util/UdfUtil.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- *
- * * 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.hertzbeat.common.util;
-
-import java.io.File;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.Arrays;
-import java.util.List;
-import java.util.jar.JarFile;
-import java.util.jar.Manifest;
-import java.util.stream.Collectors;
-import lombok.extern.slf4j.Slf4j;
-
-/**
- * UdfUtil
- */
-@Slf4j
-public class UdfUtil {
- public static URLClassLoader getClassLoader(String path) {
- List<String> jars = getAllJars(path);
-
- if (jars == null) {
- return null;
- }
-
- URL[] urls = jars.stream().map(jar -> {
- try {
- return new File(jar).toURI().toURL();
- } catch (MalformedURLException e) {
- log.error("getClassLoader error", e);
- }
- return null;
- }).toArray(URL[]::new);
-
- ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
- try (URLClassLoader urlClassLoader = new URLClassLoader(urls,
systemClassLoader)) {
- return urlClassLoader;
- } catch (Exception e) {
- log.error("getClassLoader error", e);
- }
- return null;
- }
-
- private static List<String> getAllJars(String path) {
- File file = new File(path);
- File[] files = file.listFiles();
- if (files == null) {
- return null;
- }
- return Arrays.stream(files)
- .filter(f -> f.getName().endsWith(".jar"))
- .map(File::getAbsolutePath)
- .collect(Collectors.toList());
- }
-
- public static List<String> getAllClassNamesFromJar(String jarFilePath) {
- try (JarFile jarFile = new JarFile(jarFilePath)) {
- return jarFile.stream()
- .filter(jarEntry -> jarEntry.getName().endsWith(".class"))
- .filter(jarEntry ->
!jarEntry.getName().contains("org/apache/hertzbeat/udf/AfterAlertUdf"))
- .map(jarEntry -> jarEntry.getName().replace("/",
".").replace(".class", ""))
- .collect(Collectors.toList());
- } catch (Exception e) {
- log.error("getAllClassNamesFromJar error", e);
- }
- return null;
- }
-}
diff --git a/manager/pom.xml b/manager/pom.xml
index e39f10c69..d71203c7a 100644
--- a/manager/pom.xml
+++ b/manager/pom.xml
@@ -85,7 +85,7 @@
<!-- udf -->
<dependency>
<groupId>org.apache.hertzbeat</groupId>
- <artifactId>hertzbeat-udf</artifactId>
+ <artifactId>hertzbeat-plugin</artifactId>
</dependency>
<!-- spring -->
<dependency>
diff --git a/manager/src/main/java/org/apache/hertzbeat/manager/Manager.java
b/manager/src/main/java/org/apache/hertzbeat/manager/Manager.java
index e9aac8c0c..2e69b6414 100644
--- a/manager/src/main/java/org/apache/hertzbeat/manager/Manager.java
+++ b/manager/src/main/java/org/apache/hertzbeat/manager/Manager.java
@@ -18,12 +18,14 @@
package org.apache.hertzbeat.manager;
import javax.annotation.PostConstruct;
+import org.apache.hertzbeat.manager.config.PluginConfig;
import org.apache.hertzbeat.manager.nativex.HertzbeatRuntimeHintsRegistrar;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportRuntimeHints;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@@ -39,6 +41,7 @@ import
org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@ComponentScan(basePackages = {"org.apache.hertzbeat"})
@ConfigurationPropertiesScan(basePackages = {"org.apache.hertzbeat"})
@ImportRuntimeHints(HertzbeatRuntimeHintsRegistrar.class)
+@Import(PluginConfig.class)
public class Manager {
public static void main(String[] args) {
SpringApplication.run(Manager.class, args);
diff --git
a/manager/src/main/java/org/apache/hertzbeat/manager/component/alerter/DispatcherAlarm.java
b/manager/src/main/java/org/apache/hertzbeat/manager/component/alerter/DispatcherAlarm.java
index 768090b03..30160fadc 100644
---
a/manager/src/main/java/org/apache/hertzbeat/manager/component/alerter/DispatcherAlarm.java
+++
b/manager/src/main/java/org/apache/hertzbeat/manager/component/alerter/DispatcherAlarm.java
@@ -18,9 +18,6 @@
package org.apache.hertzbeat.manager.component.alerter;
import com.google.common.collect.Maps;
-
-import java.lang.reflect.Constructor;
-import java.net.URLClassLoader;
import java.util.List;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
@@ -30,11 +27,11 @@ import
org.apache.hertzbeat.common.entity.manager.NoticeReceiver;
import org.apache.hertzbeat.common.entity.manager.NoticeRule;
import org.apache.hertzbeat.common.entity.manager.NoticeTemplate;
import org.apache.hertzbeat.common.queue.CommonDataQueue;
-import org.apache.hertzbeat.common.util.UdfUtil;
+import org.apache.hertzbeat.manager.config.PluginConfig;
import org.apache.hertzbeat.manager.service.NoticeConfigService;
import org.apache.hertzbeat.manager.support.exception.AlertNoticeException;
import org.apache.hertzbeat.manager.support.exception.IgnoreException;
-import org.apache.hertzbeat.udf.AfterAlertUdf;
+import org.apache.hertzbeat.plugin.Plugin;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
@@ -51,22 +48,25 @@ public class DispatcherAlarm implements InitializingBean {
private final NoticeConfigService noticeConfigService;
private final AlertStoreHandler alertStoreHandler;
private final Map<Byte, AlertNotifyHandler> alertNotifyHandlerMap;
+ private final PluginConfig pluginConfig;
public DispatcherAlarm(AlerterWorkerPool workerPool,
CommonDataQueue dataQueue,
NoticeConfigService noticeConfigService,
AlertStoreHandler alertStoreHandler,
- List<AlertNotifyHandler> alertNotifyHandlerList) {
+ List<AlertNotifyHandler> alertNotifyHandlerList,
+ PluginConfig pluginConfig) {
this.workerPool = workerPool;
this.dataQueue = dataQueue;
this.noticeConfigService = noticeConfigService;
this.alertStoreHandler = alertStoreHandler;
alertNotifyHandlerMap =
Maps.newHashMapWithExpectedSize(alertNotifyHandlerList.size());
+ this.pluginConfig = pluginConfig;
alertNotifyHandlerList.forEach(r ->
alertNotifyHandlerMap.put(r.type(), r));
}
@Override
- public void afterPropertiesSet() throws Exception {
+ public void afterPropertiesSet() {
// Start alarm distribution
DispatchTask dispatchTask = new DispatchTask();
for (int i = 0; i < DISPATCH_THREADS; i++) {
@@ -118,35 +118,11 @@ public class DispatcherAlarm implements InitializingBean {
alertStoreHandler.store(alert);
// Notice distribution
sendNotify(alert);
- //execute udf
- URLClassLoader classLoader =
UdfUtil.getClassLoader("H:\\Java\\hertzbeat\\udf\\target\\");
-
Thread.currentThread().setContextClassLoader(classLoader);
- List<String> mainClassNameFromJar =
UdfUtil.getAllClassNamesFromJar("H:\\Java\\hertzbeat\\udf\\target\\hertzbeat-udf-2.0-SNAPSHOT.jar");
- if (mainClassNameFromJar != null) {
- for (String name : mainClassNameFromJar) {
- if (name == null || name.trim().isEmpty()) {
- log.error("class name is null or empty");
- continue;
- }
- AfterAlertUdf afterAlertUdf = null;
- if (classLoader != null) {
- try {
- Class<?> clazz =
classLoader.loadClass(name);
- Constructor<?> constructor =
clazz.getDeclaredConstructor();
- afterAlertUdf = (AfterAlertUdf)
constructor.newInstance();
- } catch (ClassNotFoundException e) {
- log.error("class not found : {}",
e.getLocalizedMessage());
- } catch (InstantiationException |
IllegalAccessException | NoSuchMethodException e) {
- log.error("class newInstance error :
{}", e.getLocalizedMessage());
- }
- }
- if (afterAlertUdf != null) {
- try {
- afterAlertUdf.execute(alert);
- } catch (Exception e) {
- log.error("execute udf error : {}",
e.getLocalizedMessage());
- }
- }
+ // Execute the plugin
+ List<Object> beans = pluginConfig.getBean();
+ for (Object bean : beans) {
+ if (bean instanceof Plugin) {
+ ((Plugin) bean).execute(alert);
}
}
}
diff --git
a/manager/src/main/java/org/apache/hertzbeat/manager/config/PluginConfig.java
b/manager/src/main/java/org/apache/hertzbeat/manager/config/PluginConfig.java
new file mode 100644
index 000000000..fe9c6b9a1
--- /dev/null
+++
b/manager/src/main/java/org/apache/hertzbeat/manager/config/PluginConfig.java
@@ -0,0 +1,160 @@
+package org.apache.hertzbeat.manager.config;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.jar.JarFile;
+import java.util.stream.Collectors;
+import lombok.extern.slf4j.Slf4j;
+import org.jetbrains.annotations.NotNull;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.beans.factory.support.BeanNameGenerator;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
+import org.springframework.core.type.AnnotationMetadata;
+import org.springframework.stereotype.Component;
+
+
+/**
+ * Plugin configuration
+ */
+@Slf4j
+@Component
+public class PluginConfig implements ImportBeanDefinitionRegistrar,
ApplicationContextAware {
+ @Autowired
+ private ApplicationContext applicationContext;
+ @Autowired
+ private DefaultListableBeanFactory defaultListableBeanFactory;
+
+ private static final String CLASS_SUFFIX = ".class";
+
+ private static final String BASE_PLUGIN_PATH =
"org/apache/hertzbeat/plugin/Plugin";
+
+ private static final String BASE_PATH = System.getProperty("user.dir") +
File.separator + "ext-lib";
+
+ private static final String PACKAGE = "org/hertzbeat/plugin";
+
+ private URLClassLoader getClassLoader() {
+ List<String> jars = getAllJars();
+ if (jars == null) {
+ return null;
+ }
+ List<URL> urlList = new ArrayList<>();
+ for (String jar : jars) {
+ try {
+ URL url = new File(jar).toURI().toURL();
+ urlList.add(url);
+ } catch (MalformedURLException e) {
+ log.error("Error converting jar to URL: {}", jar, e);
+ }
+ }
+ if (urlList.isEmpty()) {
+ return null;
+ }
+ URL[] urls = urlList.toArray(new URL[0]);
+ ClassLoader contextClassLoader =
Thread.currentThread().getContextClassLoader();
+ return new URLClassLoader(urls, contextClassLoader);
+ }
+
+
+ private List<String> getAllJars() {
+ log.info("BASE_PATH:{}", PluginConfig.BASE_PATH);
+ File file = new File(PluginConfig.BASE_PATH);
+ File[] files = file.listFiles();
+ if (files == null) {
+ return null;
+ }
+ return Arrays.stream(files)
+ .filter(f -> f.getName().endsWith(".jar"))
+ .map(File::getAbsolutePath)
+ .collect(Collectors.toList());
+ }
+
+ private List<String> getAllClassNamesFromJar() throws IOException {
+ List<String> jars = getAllJars();
+ if (jars == null || jars.isEmpty()) {
+ return null;
+ }
+ List<String> classNames = new ArrayList<>();
+ for (String jar : jars) {
+ List<String> collect;
+ try (JarFile file = new JarFile(jar)) {
+ collect = file.stream()
+ .filter(jarEntry ->
jarEntry.getName().endsWith(CLASS_SUFFIX))
+ .filter(jarEntry ->
jarEntry.getName().startsWith(PACKAGE))
+ .filter(jarEntry ->
!jarEntry.getName().contains(BASE_PLUGIN_PATH))
+ .map(jarEntry -> jarEntry.getName().replace("/",
".").replace(".class", ""))
+ .toList();
+ }
+ classNames.addAll(collect);
+ }
+ return classNames;
+ }
+
+ private void registerBean(Class<?> c, BeanDefinitionRegistry registry) {
+ String className = c.getName();
+ BeanDefinitionBuilder builder =
BeanDefinitionBuilder.genericBeanDefinition(c);
+ BeanDefinition beanDefinition = builder.getBeanDefinition();
+ registry.registerBeanDefinition(className, beanDefinition);
+ }
+
+ @Override
+ public void registerBeanDefinitions(@NotNull AnnotationMetadata
importingClassMetadata, @NotNull BeanDefinitionRegistry registry, @NotNull
BeanNameGenerator importBeanNameGenerator) {
+ URLClassLoader classLoader = getClassLoader();
+ List<String> allClassNamesFromJar;
+ try {
+ allClassNamesFromJar = getAllClassNamesFromJar();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ if (allClassNamesFromJar != null) {
+ for (String name : allClassNamesFromJar) {
+ if (name == null || name.trim().isEmpty()) {
+ log.error("class name is null or empty");
+ continue;
+ }
+ if (classLoader != null) {
+ Class<?> clazz = null;
+ try {
+ clazz = classLoader.loadClass(name);
+ } catch (ClassNotFoundException e) {
+ log.error("load class error:{}",
e.getLocalizedMessage());
+ }
+ if (clazz != null) {
+ registerBean(clazz, registry);
+ }
+ }
+ }
+ } }
+
+ public List<Object> getBean() throws IOException {
+ List<String> names = getAllClassNamesFromJar();
+ List<Object> beans = new ArrayList<>();
+ if (names != null) {
+ for (String name : names) {
+ Object bean = applicationContext.getBean(name);
+ beans.add(bean);
+ }
+ }
+ return beans;
+ }
+
+ @Override
+ public void setApplicationContext(@NotNull ApplicationContext
applicationContext) throws BeansException {
+ this.applicationContext = applicationContext;
+ ConfigurableApplicationContext configurableApplicationContext =
(ConfigurableApplicationContext) applicationContext;
+ this.defaultListableBeanFactory = (DefaultListableBeanFactory)
configurableApplicationContext.getBeanFactory();
+ }
+}
diff --git a/plugin/pom.xml b/plugin/pom.xml
new file mode 100644
index 000000000..461adca67
--- /dev/null
+++ b/plugin/pom.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>hertzbeat</artifactId>
+ <groupId>org.apache.hertzbeat</groupId>
+ <version>2.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>hertzbeat-plugin</artifactId>
+ <name>${project.artifactId}</name>
+ <properties>
+ <maven-jar-plugin.version>3.2.0</maven-jar-plugin.version>
+ <maven-assembly-plugin.version>3.3.0</maven-assembly-plugin.version>
+ </properties>
+
+ <dependencies>
+ <!-- common -->
+ <dependency>
+ <groupId>org.apache.hertzbeat</groupId>
+ <artifactId>hertzbeat-common</artifactId>
+ </dependency>
+ </dependencies>
+
+
+</project>
diff --git a/udf/src/main/java/org/apache/hertzbeat/udf/AfterAlertUdf.java
b/plugin/src/main/java/org/apache/hertzbeat/plugin/Plugin.java
similarity index 91%
rename from udf/src/main/java/org/apache/hertzbeat/udf/AfterAlertUdf.java
rename to plugin/src/main/java/org/apache/hertzbeat/plugin/Plugin.java
index 4a99938be..8fcdf40d2 100644
--- a/udf/src/main/java/org/apache/hertzbeat/udf/AfterAlertUdf.java
+++ b/plugin/src/main/java/org/apache/hertzbeat/plugin/Plugin.java
@@ -17,13 +17,13 @@
*
*/
-package org.apache.hertzbeat.udf;
+package org.apache.hertzbeat.plugin;
import org.apache.hertzbeat.common.entity.alerter.Alert;
/**
- * AfterAlertUdf
+ * Plugin
*/
-public interface AfterAlertUdf {
+public interface Plugin {
void execute(Alert alert);
}
diff --git
a/udf/src/main/java/org/apache/hertzbeat/udf/DemoAfterAlertUdfImpl.java
b/plugin/src/main/java/org/apache/hertzbeat/plugin/impl/DemoPluginImpl1.java
similarity index 81%
rename from
udf/src/main/java/org/apache/hertzbeat/udf/DemoAfterAlertUdfImpl.java
rename to
plugin/src/main/java/org/apache/hertzbeat/plugin/impl/DemoPluginImpl1.java
index 4852ca74c..f4a194c85 100644
--- a/udf/src/main/java/org/apache/hertzbeat/udf/DemoAfterAlertUdfImpl.java
+++ b/plugin/src/main/java/org/apache/hertzbeat/plugin/impl/DemoPluginImpl1.java
@@ -17,18 +17,19 @@
*
*/
-package org.apache.hertzbeat.udf;
+package org.apache.hertzbeat.plugin.impl;
import lombok.extern.slf4j.Slf4j;
import org.apache.hertzbeat.common.entity.alerter.Alert;
+import org.apache.hertzbeat.plugin.Plugin;
/**
- * DemoAfterAlertUdf
+ * DemoPlugin
*/
@Slf4j
-public class DemoAfterAlertUdfImpl implements AfterAlertUdf{
+public class DemoPluginImpl1 implements Plugin {
@Override
public void execute(Alert alert) {
- log.info("DemoAfterAlertUdfImpl execute alert: {}", alert);
+ log.info("DemoPluginImplsd;kjghsakdjghalskjdghjk execute alert: {}",
alert);
}
}
diff --git a/pom.xml b/pom.xml
index a5b4ff317..dc6b61e68 100644
--- a/pom.xml
+++ b/pom.xml
@@ -86,7 +86,7 @@
<module>warehouse</module>
<module>remoting</module>
<module>push</module>
- <module>udf</module>
+ <module>plugin</module>
</modules>
<properties>
@@ -181,7 +181,7 @@
<!-- udf -->
<dependency>
<groupId>org.apache.hertzbeat</groupId>
- <artifactId>hertzbeat-udf</artifactId>
+ <artifactId>hertzbeat-plugin</artifactId>
<version>${hertzbeat.version}</version>
</dependency>
<!-- spring -->
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]