chore: import upstream snapshot with attribution
MCP Bash Server CI / Test MCP Bash Server (dev) (push) Has been cancelled
MCP Bash Server CI / Test MCP Bash Server (release) (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:11:39 +08:00
commit c8cebdfeee
4654 changed files with 626756 additions and 0 deletions
@@ -0,0 +1,147 @@
/*
* 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 com.usthe.sureness.configuration;
import com.usthe.sureness.mgt.SecurityManager;
import com.usthe.sureness.processor.exception.DisabledAccountException;
import com.usthe.sureness.processor.exception.ExcessiveAttemptsException;
import com.usthe.sureness.processor.exception.ExpiredCredentialsException;
import com.usthe.sureness.processor.exception.IncorrectCredentialsException;
import com.usthe.sureness.processor.exception.NeedDigestInfoException;
import com.usthe.sureness.processor.exception.UnauthorizedException;
import com.usthe.sureness.processor.exception.UnknownAccountException;
import com.usthe.sureness.subject.SubjectSum;
import com.usthe.sureness.util.SurenessContextHolder;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import java.io.IOException;
import java.io.PrintWriter;
/**
* Override the default servlet filter
*/
public class SurenessJakartaServletFilter implements Filter {
private final SecurityManager securityManager;
public SurenessJakartaServletFilter(SecurityManager securityManager) {
this.securityManager = securityManager;
}
/** logger **/
private static final Logger logger = LoggerFactory.getLogger(SurenessJakartaServletFilter.class);
private static final String UPGRADE = "Upgrade";
private static final String WEBSOCKET = "websocket";
@Override
public void init(FilterConfig filterConfig) {
logger.info("servlet surenessFilter initialized");
}
@Override
public void destroy() {
logger.info("servlet surenessFilter destroyed");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain)
throws IOException, ServletException {
try {
SubjectSum subject = securityManager.checkIn(servletRequest);
// You can consider using SurenessContextHolder to bind subject in threadLocal
// if bind, please remove it when end
if (subject != null) {
SurenessContextHolder.bindSubject(subject);
}
} catch (IncorrectCredentialsException | UnknownAccountException | ExpiredCredentialsException e1) {
logger.debug("this request account info is illegal, {}", e1.getMessage());
responseWrite(ResponseEntity
.status(HttpStatus.UNAUTHORIZED)
.body("Username or password is incorrect or token expired"), servletResponse);
return;
} catch (DisabledAccountException | ExcessiveAttemptsException e2) {
logger.debug("the account is disabled, {}", e2.getMessage());
responseWrite(ResponseEntity
.status(HttpStatus.UNAUTHORIZED).body("Account is disabled"), servletResponse);
return;
} catch (NeedDigestInfoException e3) {
logger.debug("you should try once again with digest auth information");
responseWrite(ResponseEntity
.status(HttpStatus.UNAUTHORIZED)
.header("WWW-Authenticate", e3.getAuthenticate()).build(), servletResponse);
return;
} catch (UnauthorizedException e4) {
logger.debug("this account can not access this resource, {}", e4.getMessage());
responseWrite(ResponseEntity
.status(HttpStatus.FORBIDDEN)
.body("This account has no permission to access this resource"), servletResponse);
return;
} catch (RuntimeException e) {
logger.error("other exception happen: ", e);
responseWrite(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(),
servletResponse);
return;
}
try {
// if ok, doFilter and add subject in request
filterChain.doFilter(servletRequest, servletResponse);
} finally {
int statusCode = ((HttpServletResponse) servletResponse).getStatus();
String upgrade = ((HttpServletResponse) servletResponse).getHeader(UPGRADE);
if (statusCode != HttpStatus.SWITCHING_PROTOCOLS.value() || !WEBSOCKET.equals(upgrade)) {
SurenessContextHolder.clear();
}
}
}
/**
* write response json data
* @param content content
* @param response response
*/
private static void responseWrite(ResponseEntity content, ServletResponse response) {
response.setCharacterEncoding("UTF-8");
((HttpServletResponse) response).setStatus(content.getStatusCode().value());
content.getHeaders().forEach((key, value) ->
((HttpServletResponse) response).addHeader(key, value.get(0)));
try (PrintWriter printWriter = response.getWriter()) {
if (content.getBody() != null) {
printWriter.write(content.getBody().toString());
} else {
printWriter.flush();
}
} catch (IOException e) {
logger.error("responseWrite response error: ", e);
}
}
}
@@ -0,0 +1,176 @@
/*
* 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.manager.component.sd;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.hertzbeat.common.constants.CommonConstants;
import org.apache.hertzbeat.common.entity.arrow.RowWrapper;
import org.apache.hertzbeat.common.entity.manager.CollectorMonitorBind;
import org.apache.hertzbeat.common.entity.manager.Monitor;
import org.apache.hertzbeat.common.entity.manager.MonitorBind;
import org.apache.hertzbeat.common.entity.manager.Param;
import org.apache.hertzbeat.common.entity.message.CollectRep;
import org.apache.hertzbeat.common.queue.CommonDataQueue;
import org.apache.hertzbeat.common.support.exception.CommonDataQueueUnknownException;
import org.apache.hertzbeat.common.util.BackoffUtils;
import org.apache.hertzbeat.common.util.ExponentialBackoff;
import org.apache.hertzbeat.manager.dao.CollectorMonitorBindDao;
import org.apache.hertzbeat.manager.dao.MonitorBindDao;
import org.apache.hertzbeat.manager.dao.MonitorDao;
import org.apache.hertzbeat.manager.dao.ParamDao;
import org.apache.hertzbeat.manager.scheduler.ManagerWorkerPool;
import org.apache.hertzbeat.manager.service.MonitorService;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
/**
* Service Discovery Worker
*/
@Slf4j
@Component
public class ServiceDiscoveryWorker implements InitializingBean {
private static final String FILED_HOST = "host";
private static final String FILED_PORT = "port";
private final MonitorService monitorService;
private final ParamDao paramDao;
private final MonitorDao monitorDao;
private final MonitorBindDao monitorBindDao;
private final CollectorMonitorBindDao collectorMonitorBindDao;
private final CommonDataQueue dataQueue;
private final ManagerWorkerPool workerPool;
public ServiceDiscoveryWorker(MonitorService monitorService, ParamDao paramDao, MonitorDao monitorDao,
MonitorBindDao monitorBindDao, CollectorMonitorBindDao collectorMonitorBindDao,
CommonDataQueue dataQueue, ManagerWorkerPool workerPool) {
this.monitorService = monitorService;
this.paramDao = paramDao;
this.monitorDao = monitorDao;
this.monitorBindDao = monitorBindDao;
this.collectorMonitorBindDao = collectorMonitorBindDao;
this.dataQueue = dataQueue;
this.workerPool = workerPool;
}
@Override
public void afterPropertiesSet() {
workerPool.executeLongRunning(new SdUpdateTask());
}
private class SdUpdateTask implements Runnable {
@Override
public void run() {
ExponentialBackoff backoff = new ExponentialBackoff(50L, 1000L);
while (!Thread.currentThread().isInterrupted()) {
try (final CollectRep.MetricsData metricsData = dataQueue.pollServiceDiscoveryData()) {
if (metricsData == null) {
continue;
}
backoff.reset();
Long monitorId = metricsData.getId();
final Monitor mainMonitor = monitorDao.findById(monitorId).orElse(null);
if (mainMonitor == null) {
log.warn("No monitor found for id {}", monitorId);
continue;
}
// collector
final Optional<CollectorMonitorBind> collectorBind = collectorMonitorBindDao.findCollectorMonitorBindByMonitorId(monitorId);
String collector = collectorBind.map(CollectorMonitorBind::getCollector).orElse(null);
// params
List<Param> mainMonitorParams = paramDao.findParamsByMonitorId(monitorId);
final Map<String, MonitorBind> subMonitorBindMap = monitorBindDao.findMonitorBindsByBizId(monitorId)
.stream().collect(Collectors.toMap(MonitorBind::getKeyStr, item -> item));
RowWrapper rowWrapper = metricsData.readRow();
Map<String, String> fieldsValue = Maps.newHashMapWithExpectedSize(8);
String defaultPort = mainMonitorParams.stream()
.filter(param -> FILED_PORT.equals(param.getField()))
.findFirst()
.map(Param::getParamValue)
.orElse("");
while (rowWrapper.hasNextRow()) {
rowWrapper = rowWrapper.nextRow();
fieldsValue.clear();
rowWrapper.cellStream().forEach(cell -> {
String value = cell.getValue();
fieldsValue.put(cell.getField().getName(), value);
});
final String host = fieldsValue.get(FILED_HOST);
final String port = Optional.ofNullable(fieldsValue.get(FILED_PORT))
.filter(p -> !p.isEmpty())
.orElse(defaultPort);
final String keyStr = host + ":" + port;
final String instance = port.isEmpty() ? host : host + ":" + port;
if (subMonitorBindMap.containsKey(keyStr)) {
subMonitorBindMap.remove(keyStr);
continue;
}
Monitor newMonitor = mainMonitor.clone();
newMonitor.setId(null);
newMonitor.setInstance(instance);
newMonitor.setName(newMonitor.getName() + "-" + host + ":" + port);
newMonitor.setScrape(CommonConstants.SCRAPE_STATIC);
newMonitor.setGmtCreate(LocalDateTime.now());
newMonitor.setGmtUpdate(LocalDateTime.now());
// replace host port
List<Param> newParams = new LinkedList<>();
for (Param param : mainMonitorParams) {
Param newParam = param.clone();
newParam.setId(null);
newParam.setGmtUpdate(null);
newParam.setGmtCreate(null);
if (FILED_HOST.equals(newParam.getField())) {
newParam.setParamValue(host);
} else if (FILED_PORT.equals(newParam.getField())) {
newParam.setParamValue(port);
}
newParams.add(newParam);
}
monitorService.addMonitor(newMonitor, newParams, collector, null);
MonitorBind monitorBind = MonitorBind.builder()
.bizId(monitorId)
.monitorId(newMonitor.getId())
.keyStr(keyStr)
.build();
monitorBindDao.save(monitorBind);
}
// hostMonitorMap only contains monitors which are already existed but not in service discovery data
// due to monitors that coincide with service discovery data are removed.
// Thus, all monitors still in hostMonitorMap need to be cancelled.
final Set<Long> needCancelMonitorIdSet = subMonitorBindMap.values().stream()
.map(MonitorBind::getMonitorId).collect(Collectors.toSet());
monitorService.deleteMonitors(needCancelMonitorIdSet);
} catch (CommonDataQueueUnknownException ue) {
if (!BackoffUtils.shouldContinueAfterBackoff(backoff)) {
break;
}
} catch (Exception exception) {
log.error(exception.getMessage(), exception);
}
}
}
}
}
@@ -0,0 +1,388 @@
/*
* 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.manager.component.status;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import jakarta.persistence.criteria.Predicate;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
import org.apache.hertzbeat.common.config.VirtualThreadProperties;
import org.apache.hertzbeat.common.constants.CommonConstants;
import org.apache.hertzbeat.common.entity.manager.Monitor;
import org.apache.hertzbeat.common.entity.manager.StatusPageComponent;
import org.apache.hertzbeat.common.entity.manager.StatusPageHistory;
import org.apache.hertzbeat.common.entity.manager.StatusPageOrg;
import org.apache.hertzbeat.manager.config.StatusProperties;
import org.apache.hertzbeat.manager.dao.MonitorDao;
import org.apache.hertzbeat.manager.dao.StatusPageComponentDao;
import org.apache.hertzbeat.manager.dao.StatusPageHistoryDao;
import org.apache.hertzbeat.manager.dao.StatusPageOrgDao;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
/**
* calculate component status for status page
*/
@Component
@Slf4j
public class CalculateStatus implements DisposableBean {
private static final int DEFAULT_CALCULATE_INTERVAL_TIME = 300;
private final StatusPageOrgDao statusPageOrgDao;
private final StatusPageComponentDao statusPageComponentDao;
private final StatusPageHistoryDao statusPageHistoryDao;
private final MonitorDao monitorDao;
private final int intervals;
private final ScheduledExecutorService calculateScheduler;
private final ScheduledExecutorService combineHistoryScheduler;
private final ExecutorService calculateExecutor;
private final ExecutorService combineHistoryExecutor;
private final ScheduledDispatchTask calculateTask;
private final ScheduledDispatchTask combineHistoryTask;
public CalculateStatus(StatusPageOrgDao statusPageOrgDao, StatusPageComponentDao statusPageComponentDao,
StatusProperties statusProperties, StatusPageHistoryDao statusPageHistoryDao,
MonitorDao monitorDao) {
this(statusPageOrgDao, statusPageComponentDao, statusProperties, statusPageHistoryDao, monitorDao,
VirtualThreadProperties.defaults(), true);
}
@Autowired
public CalculateStatus(StatusPageOrgDao statusPageOrgDao, StatusPageComponentDao statusPageComponentDao,
StatusProperties statusProperties, StatusPageHistoryDao statusPageHistoryDao,
MonitorDao monitorDao, VirtualThreadProperties virtualThreadProperties) {
this(statusPageOrgDao, statusPageComponentDao, statusProperties, statusPageHistoryDao, monitorDao,
virtualThreadProperties, true);
}
CalculateStatus(StatusPageOrgDao statusPageOrgDao, StatusPageComponentDao statusPageComponentDao,
StatusProperties statusProperties, StatusPageHistoryDao statusPageHistoryDao,
MonitorDao monitorDao, VirtualThreadProperties virtualThreadProperties, boolean autoStart) {
this.statusPageOrgDao = statusPageOrgDao;
this.monitorDao = monitorDao;
this.statusPageComponentDao = statusPageComponentDao;
this.statusPageHistoryDao = statusPageHistoryDao;
intervals = statusProperties.getCalculate() == null ? DEFAULT_CALCULATE_INTERVAL_TIME : statusProperties.getCalculate().getInterval();
this.calculateScheduler = createScheduler("status-page-calculate-%d", "Status calculate has uncaughtException.");
this.combineHistoryScheduler = createScheduler("status-page-history-%d", "History combine has uncaughtException.");
this.calculateExecutor = createVirtualExecutor(virtualThreadProperties, "status-page-calculate-vt-",
"Status calculate worker has uncaughtException.");
this.combineHistoryExecutor = createVirtualExecutor(virtualThreadProperties, "status-page-history-vt-",
"History combine worker has uncaughtException.");
this.calculateTask = new ScheduledDispatchTask(calculateExecutor, this::runCalculate);
this.combineHistoryTask = new ScheduledDispatchTask(combineHistoryExecutor, this::runCombineHistory);
if (autoStart) {
startCalculate();
startCombineHistory();
}
}
private void startCalculate() {
calculateScheduler.scheduleAtFixedRate(this::dispatchCalculate, 5, intervals, TimeUnit.SECONDS);
}
private void startCombineHistory() {
// combine history every day at 1:00 AM
LocalDateTime now = LocalDateTime.now();
LocalDateTime nextRun = now.withHour(1).withMinute(0).withSecond(0);
if (now.isAfter(nextRun)) {
nextRun = nextRun.plusDays(1);
}
long delay = Duration.between(now, nextRun).toMillis();
combineHistoryScheduler.scheduleAtFixedRate(this::dispatchCombineHistory, delay,
TimeUnit.DAYS.toMillis(1), TimeUnit.MILLISECONDS);
}
/**
* get calculate status intervals
* @return intervals
*/
public int getCalculateStatusIntervals() {
return intervals;
}
void dispatchCalculate() {
calculateTask.dispatch();
}
void dispatchCombineHistory() {
combineHistoryTask.dispatch();
}
@Override
public void destroy() {
calculateScheduler.shutdownNow();
combineHistoryScheduler.shutdownNow();
if (calculateExecutor != null) {
calculateExecutor.shutdownNow();
}
if (combineHistoryExecutor != null) {
combineHistoryExecutor.shutdownNow();
}
}
private void runCalculate() {
log.info("start to calculate status page state");
try {
// calculate component state from tag bind monitors status
List<StatusPageOrg> statusPageOrgList = statusPageOrgDao.findAll();
for (StatusPageOrg statusPageOrg : statusPageOrgList) {
long orgId = statusPageOrg.getId();
List<StatusPageComponent> pageComponentList = statusPageComponentDao.findByOrgId(orgId);
Set<Byte> stateSet = new HashSet<>(8);
for (StatusPageComponent component : pageComponentList) {
byte state;
if (component.getMethod() == CommonConstants.STATUS_PAGE_CALCULATE_METHOD_MANUAL) {
state = component.getConfigState();
} else {
Map<String, String> labels = component.getLabels();
if (labels == null || labels.isEmpty()) {
continue;
}
Specification<Monitor> specification = (root, query, criteriaBuilder) -> {
List<Predicate> predicates = new ArrayList<>();
// create every label condition
labels.forEach((key, value) -> {
String pattern = String.format("%%\"%s\":\"%s\"%%", key, value);
predicates.add(criteriaBuilder.like(root.get("labels"), pattern));
});
// use or connect them
return criteriaBuilder.or(predicates.toArray(new Predicate[0]));
};
List<Monitor> monitorList = monitorDao.findAll(specification);
state = CommonConstants.STATUS_PAGE_COMPONENT_STATE_UNKNOWN;
for (Monitor monitor : monitorList) {
if (monitor.getStatus() == CommonConstants.MONITOR_DOWN_CODE) {
state = CommonConstants.STATUS_PAGE_COMPONENT_STATE_ABNORMAL;
break;
} else if (monitor.getStatus() == CommonConstants.MONITOR_UP_CODE) {
state = CommonConstants.STATUS_PAGE_COMPONENT_STATE_NORMAL;
}
}
}
stateSet.add(state);
component.setState(state);
statusPageComponentDao.save(component);
// insert component state history
StatusPageHistory statusPageHistory = StatusPageHistory.builder()
.componentId(component.getId())
.state(state)
.timestamp(System.currentTimeMillis())
.build();
statusPageHistoryDao.save(statusPageHistory);
}
stateSet.remove(CommonConstants.STATUS_PAGE_COMPONENT_STATE_UNKNOWN);
if (stateSet.remove(CommonConstants.STATUS_PAGE_COMPONENT_STATE_ABNORMAL)) {
if (stateSet.contains(CommonConstants.STATUS_PAGE_COMPONENT_STATE_NORMAL)) {
statusPageOrg.setState(CommonConstants.STATUS_PAGE_ORG_STATE_SOME_ABNORMAL);
} else {
statusPageOrg.setState(CommonConstants.STATUS_PAGE_ORG_STATE_ALL_ABNORMAL);
}
} else {
statusPageOrg.setState(CommonConstants.STATUS_PAGE_ORG_STATE_ALL_NORMAL);
}
statusPageOrg.setGmtUpdate(LocalDateTime.now());
statusPageOrgDao.save(statusPageOrg);
}
} catch (Exception e) {
log.error("status page calculate component state error: {}", e.getMessage(), e);
}
}
private void runCombineHistory() {
try {
// combine pre day status history to one record
LocalDateTime nowTime = LocalDateTime.now();
ZoneOffset zoneOffset = ZoneId.systemDefault().getRules().getOffset(Instant.now());
LocalDateTime midnight = nowTime.withHour(0).withMinute(0).withSecond(0).withNano(0);
LocalDateTime preNight = midnight.minusDays(1);
long midnightTimestamp = midnight.toInstant(zoneOffset).toEpochMilli();
long preNightTimestamp = preNight.toInstant(zoneOffset).toEpochMilli();
List<StatusPageHistory> statusPageHistoryList = statusPageHistoryDao
.findStatusPageHistoriesByTimestampBetween(preNightTimestamp, midnightTimestamp);
Map<Long, StatusPageHistory> statusPageHistoryMap = new HashMap<>(8);
for (StatusPageHistory statusPageHistory : statusPageHistoryList) {
statusPageHistory.setNormal(0);
statusPageHistory.setAbnormal(0);
statusPageHistory.setUnknowing(0);
if (statusPageHistoryMap.containsKey(statusPageHistory.getComponentId())) {
StatusPageHistory history = statusPageHistoryMap.get(statusPageHistory.getComponentId());
if (statusPageHistory.getState() == CommonConstants.STATUS_PAGE_COMPONENT_STATE_ABNORMAL) {
history.setAbnormal(history.getAbnormal() + intervals);
} else if (statusPageHistory.getState() == CommonConstants.STATUS_PAGE_COMPONENT_STATE_UNKNOWN) {
history.setUnknowing(history.getUnknowing() + intervals);
} else {
history.setNormal(history.getNormal() + intervals);
}
statusPageHistoryMap.put(statusPageHistory.getComponentId(), history);
} else {
if (statusPageHistory.getState() == CommonConstants.STATUS_PAGE_COMPONENT_STATE_ABNORMAL) {
statusPageHistory.setAbnormal(intervals);
} else if (statusPageHistory.getState() == CommonConstants.STATUS_PAGE_COMPONENT_STATE_UNKNOWN) {
statusPageHistory.setUnknowing(intervals);
} else {
statusPageHistory.setNormal(intervals);
}
statusPageHistoryMap.put(statusPageHistory.getComponentId(), statusPageHistory);
}
}
statusPageHistoryDao.deleteAll(statusPageHistoryList);
for (StatusPageHistory history : statusPageHistoryMap.values()) {
double total = history.getNormal() + history.getAbnormal() + history.getUnknowing();
double uptime = 0;
if (total > 0) {
uptime = (double) history.getNormal() / total;
}
history.setUptime(uptime);
if (history.getAbnormal() > 0) {
history.setState(CommonConstants.STATUS_PAGE_COMPONENT_STATE_ABNORMAL);
} else if (history.getNormal() > 0) {
history.setState(CommonConstants.STATUS_PAGE_COMPONENT_STATE_NORMAL);
} else {
history.setState(CommonConstants.STATUS_PAGE_COMPONENT_STATE_UNKNOWN);
}
statusPageHistoryDao.save(history);
}
} catch (Exception e) {
log.error("status page combine history error: {}", e.getMessage(), e);
}
}
private ScheduledExecutorService createScheduler(String threadNameFormat, String errorMessage) {
ThreadFactory threadFactory = new ThreadFactoryBuilder()
.setUncaughtExceptionHandler((thread, throwable) -> {
log.error(errorMessage);
log.error(throwable.getMessage(), throwable);
})
.setDaemon(true)
.setNameFormat(threadNameFormat)
.build();
return Executors.newSingleThreadScheduledExecutor(threadFactory);
}
private ExecutorService createVirtualExecutor(VirtualThreadProperties virtualThreadProperties, String threadPrefix,
String errorMessage) {
VirtualThreadProperties properties =
virtualThreadProperties == null ? VirtualThreadProperties.defaults() : virtualThreadProperties;
if (!properties.enabled()) {
return null;
}
return Executors.newThreadPerTaskExecutor(Thread.ofVirtual()
.name(threadPrefix, 0)
.uncaughtExceptionHandler((thread, throwable) -> {
log.error(errorMessage);
log.error(throwable.getMessage(), throwable);
})
.factory());
}
private static final class ScheduledDispatchTask {
private final ExecutorService executorService;
private final Runnable task;
private final Object lock = new Object();
private boolean running;
private int pendingRuns;
private ScheduledDispatchTask(ExecutorService executorService, Runnable task) {
this.executorService = executorService;
this.task = task;
}
private void dispatch() {
if (executorService == null) {
task.run();
return;
}
synchronized (lock) {
if (running) {
pendingRuns++;
return;
}
running = true;
}
submit();
}
private void submit() {
boolean submitted = false;
try {
executorService.execute(() -> {
try {
task.run();
} finally {
onComplete();
}
});
submitted = true;
} finally {
if (!submitted) {
synchronized (lock) {
running = false;
pendingRuns = 0;
}
}
}
}
private void onComplete() {
boolean shouldRunAgain;
synchronized (lock) {
if (pendingRuns > 0) {
pendingRuns--;
shouldRunAgain = true;
} else {
running = false;
shouldRunAgain = false;
}
}
if (shouldRunAgain) {
submit();
}
}
}
}
@@ -0,0 +1,44 @@
/*
* 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.manager.component.validator;
import org.apache.hertzbeat.manager.pojo.dto.MonitorParam;
import org.apache.hertzbeat.manager.pojo.dto.ParamDefineInfo;
/**
* Parameter validator interface
*/
public interface ParamValidator {
/**
* Check if the validator supports the given parameter type
*
* @param type parameter type
* @return true if supported
*/
boolean support(String type);
/**
* Validate the parameter
*
* @param paramDefine parameter definition
* @param param parameter actual value
* @throws IllegalArgumentException if validation fails
*/
void validate(ParamDefineInfo paramDefine, MonitorParam param) throws IllegalArgumentException;
}
@@ -0,0 +1,48 @@
/*
* 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.manager.component.validator;
import org.apache.hertzbeat.manager.pojo.dto.MonitorParam;
import org.apache.hertzbeat.manager.pojo.dto.ParamDefineInfo;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* Parameter validator manager
*/
@Component
public class ParamValidatorManager {
private final List<ParamValidator> validators;
public ParamValidatorManager(List<ParamValidator> validators) {
this.validators = validators;
}
public void validate(ParamDefineInfo paramDefine, MonitorParam param) {
for (ParamValidator validator : validators) {
if (validator.support(paramDefine.getType())) {
validator.validate(paramDefine, param);
return;
}
}
// No validator found for the given type.
throw new IllegalArgumentException("ParamDefine type " + paramDefine.getType() + " is invalid.");
}
}
@@ -0,0 +1,46 @@
/*
* 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.manager.component.validator.impl;
import org.apache.hertzbeat.manager.component.validator.ParamValidator;
import org.apache.hertzbeat.manager.pojo.dto.MonitorParam;
import org.apache.hertzbeat.manager.pojo.dto.ParamDefineInfo;
import org.springframework.stereotype.Component;
/**
* Array parameter validator
*/
@Component
public class ArrayParamValidator implements ParamValidator {
@Override
public boolean support(String type) {
return "array".equals(type);
}
@Override
public void validate(ParamDefineInfo paramDefine, MonitorParam param) {
String[] arrays = param.getParamValue().split(",");
if (arrays.length == 0) {
throw new IllegalArgumentException("Param field " + paramDefine.getField() + " value "
+ param.getParamValue() + " is invalid arrays value");
}
if (param.getParamValue().startsWith("[") && param.getParamValue().endsWith("]")) {
param.setParamValue(param.getParamValue().substring(1, param.getParamValue().length() - 1));
}
}
}
@@ -0,0 +1,43 @@
/*
* 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.manager.component.validator.impl;
import org.apache.hertzbeat.manager.component.validator.ParamValidator;
import org.apache.hertzbeat.manager.pojo.dto.MonitorParam;
import org.apache.hertzbeat.manager.pojo.dto.ParamDefineInfo;
import org.springframework.stereotype.Component;
/**
* Boolean parameter validator
*/
@Component
public class BooleanParamValidator implements ParamValidator {
@Override
public boolean support(String type) {
return "boolean".equals(type);
}
@Override
public void validate(ParamDefineInfo paramDefine, MonitorParam param) {
String booleanValue = param.getParamValue();
if (!"true".equalsIgnoreCase(booleanValue) && !"false".equalsIgnoreCase(booleanValue)) {
throw new IllegalArgumentException("Params field " + paramDefine.getField() + " value "
+ booleanValue + " is invalid boolean value.");
}
}
}
@@ -0,0 +1,49 @@
/*
* 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.manager.component.validator.impl;
import org.apache.hertzbeat.manager.component.validator.ParamValidator;
import org.apache.hertzbeat.manager.pojo.dto.MonitorParam;
import org.apache.hertzbeat.manager.pojo.dto.ParamDefineInfo;
import org.springframework.stereotype.Component;
/**
* Host parameter validator that delegates to the common HostParamValidator
*/
@Component
public class HostParamValidatorAdapter implements ParamValidator {
private final org.apache.hertzbeat.common.support.valid.HostParamValidator hostValidator;
public HostParamValidatorAdapter() {
this.hostValidator = new org.apache.hertzbeat.common.support.valid.HostParamValidator();
}
@Override
public boolean support(String type) {
return "host".equals(type);
}
@Override
public void validate(ParamDefineInfo paramDefine, MonitorParam param) {
if (!hostValidator.isValid(param.getParamValue(), null)) {
throw new IllegalArgumentException("Params field " + paramDefine.getField() + " value "
+ param.getParamValue() + " is invalid host value.");
}
}
}
@@ -0,0 +1,45 @@
/*
* 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.manager.component.validator.impl;
import tools.jackson.core.type.TypeReference;
import org.apache.hertzbeat.common.util.JsonUtil;
import org.apache.hertzbeat.manager.component.validator.ParamValidator;
import org.apache.hertzbeat.manager.pojo.dto.MonitorParam;
import org.apache.hertzbeat.manager.pojo.dto.ParamDefineInfo;
import org.springframework.stereotype.Component;
/**
* JSON parameter validator
*/
@Component
public class JsonParamValidator implements ParamValidator {
@Override
public boolean support(String type) {
return "metrics-field".equals(type) || "key-value".equals(type);
}
@Override
public void validate(ParamDefineInfo paramDefine, MonitorParam param) {
if (JsonUtil.fromJson(param.getParamValue(), new TypeReference<>() {
}) == null) {
throw new IllegalArgumentException("Params field " + paramDefine.getField() + " value "
+ param.getParamValue() + " is invalid key-value value");
}
}
}
@@ -0,0 +1,53 @@
/*
* 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.manager.component.validator.impl;
import org.apache.hertzbeat.common.constants.CommonConstants;
import org.apache.hertzbeat.common.util.IntervalExpressionUtil;
import org.apache.hertzbeat.manager.component.validator.ParamValidator;
import org.apache.hertzbeat.manager.pojo.dto.MonitorParam;
import org.apache.hertzbeat.manager.pojo.dto.ParamDefineInfo;
import org.springframework.stereotype.Component;
/**
* Number parameter validator
*/
@Component
public class NumberParamValidator implements ParamValidator {
@Override
public boolean support(String type) {
return "number".equals(type);
}
@Override
public void validate(ParamDefineInfo paramDefine, MonitorParam param) {
Double doubleValue = org.apache.hertzbeat.common.util.CommonUtil.parseStrDouble(param.getParamValue());
if (doubleValue == null) {
throw new IllegalArgumentException("Params field " + paramDefine.getField() + " type "
+ paramDefine.getType() + " is invalid.");
}
if (paramDefine.getRange() != null) {
if (!IntervalExpressionUtil.validNumberIntervalExpress(doubleValue,
paramDefine.getRange())) {
throw new IllegalArgumentException("Params field " + paramDefine.getField() + " type "
+ paramDefine.getType() + " over range " + paramDefine.getRange());
}
}
param.setType(CommonConstants.PARAM_TYPE_NUMBER);
}
}
@@ -0,0 +1,54 @@
/*
* 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.manager.component.validator.impl;
import org.apache.hertzbeat.manager.component.validator.ParamValidator;
import org.apache.hertzbeat.manager.pojo.dto.MonitorParam;
import org.apache.hertzbeat.manager.pojo.dto.ParamDefineInfo;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* Option parameter validator for radio and checkbox types
*/
@Component
public class OptionParamValidator implements ParamValidator {
@Override
public boolean support(String type) {
return "radio".equals(type) || "checkbox".equals(type);
}
@Override
public void validate(ParamDefineInfo paramDefine, MonitorParam param) {
List<ParamDefineInfo.OptionInfo> options = paramDefine.getOptions();
boolean invalid = true;
if (options != null) {
for (ParamDefineInfo.OptionInfo option : options) {
if (param.getParamValue().equalsIgnoreCase(option.getValue())) {
invalid = false;
break;
}
}
}
if (invalid) {
throw new IllegalArgumentException("Params field " + paramDefine.getField() + " value "
+ param.getParamValue() + " is invalid option value");
}
}
}
@@ -0,0 +1,46 @@
/*
* 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.manager.component.validator.impl;
import org.apache.hertzbeat.common.constants.CommonConstants;
import org.apache.hertzbeat.common.util.AesUtil;
import org.apache.hertzbeat.manager.component.validator.ParamValidator;
import org.apache.hertzbeat.manager.pojo.dto.MonitorParam;
import org.apache.hertzbeat.manager.pojo.dto.ParamDefineInfo;
import org.springframework.stereotype.Component;
/**
* Password parameter validator
*/
@Component
public class PasswordParamValidator implements ParamValidator {
@Override
public boolean support(String type) {
return "password".equals(type);
}
@Override
public void validate(ParamDefineInfo paramDefine, MonitorParam param) {
String passwordValue = param.getParamValue();
if (!AesUtil.isCiphertext(passwordValue)) {
passwordValue = AesUtil.aesEncode(passwordValue);
param.setParamValue(passwordValue);
}
param.setType(CommonConstants.PARAM_TYPE_PASSWORD);
}
}
@@ -0,0 +1,43 @@
/*
* 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.manager.component.validator.impl;
import org.apache.hertzbeat.manager.component.validator.ParamValidator;
import org.apache.hertzbeat.manager.pojo.dto.MonitorParam;
import org.apache.hertzbeat.manager.pojo.dto.ParamDefineInfo;
import org.springframework.stereotype.Component;
/**
* Text parameter validator
*/
@Component
public class TextParamValidator implements ParamValidator {
@Override
public boolean support(String type) {
return "text".equals(type) || "textarea".equals(type);
}
@Override
public void validate(ParamDefineInfo paramDefine, MonitorParam param) {
Short limit = paramDefine.getLimit();
if (limit != null && param.getParamValue().length() > limit) {
throw new IllegalArgumentException("Params field " + paramDefine.getField() + " type "
+ paramDefine.getType() + " over limit " + limit);
}
}
}
@@ -0,0 +1,145 @@
/*
* 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.manager.config;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.Collections;
import java.util.EnumMap;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider;
import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProviders;
import org.springframework.boot.autoconfigure.web.WebProperties;
import org.springframework.boot.webmvc.autoconfigure.error.ErrorViewResolver;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.lang.NonNull;
import org.springframework.util.Assert;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.View;
/**
* Solve the front-end routing problem of angular static website resources with DefaultErrorViewResolver and route the 404 website request to the angular front-end
*/
@Configuration
@Slf4j
public class AngularErrorViewResolver implements ErrorViewResolver, Ordered {
private static final Map<HttpStatus.Series, String> SERIES_VIEWS;
private static final String NOT_FOUND_CODE = "404";
static {
Map<HttpStatus.Series, String> views = new EnumMap<>(HttpStatus.Series.class);
views.put(HttpStatus.Series.CLIENT_ERROR, "4xx");
views.put(HttpStatus.Series.SERVER_ERROR, "5xx");
SERIES_VIEWS = Collections.unmodifiableMap(views);
}
private final ApplicationContext applicationContext;
private final WebProperties.Resources resources;
private final TemplateAvailabilityProviders templateAvailabilityProviders;
private int order = Ordered.LOWEST_PRECEDENCE;
public AngularErrorViewResolver(ApplicationContext applicationContext, WebProperties webProperties) {
Assert.notNull(applicationContext, "ApplicationContext must not be null");
Assert.notNull(webProperties.getResources(), "Resources must not be null");
this.applicationContext = applicationContext;
this.resources = webProperties.getResources();
this.templateAvailabilityProviders = new TemplateAvailabilityProviders(applicationContext);
}
@Override
public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
ModelAndView modelAndView = resolve(String.valueOf(status.value()), model);
if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) {
modelAndView = resolve(SERIES_VIEWS.get(status.series()), model);
}
return modelAndView;
}
private ModelAndView resolve(String viewName, Map<String, Object> model) {
String errorViewName = "error/" + viewName;
if (NOT_FOUND_CODE.equals(viewName)) {
errorViewName = "index";
}
TemplateAvailabilityProvider provider = this.templateAvailabilityProviders.getProvider(errorViewName,
this.applicationContext);
if (provider != null) {
return new ModelAndView(errorViewName, model);
}
return resolveResource(errorViewName, model);
}
private ModelAndView resolveResource(String viewName, Map<String, Object> model) {
for (String location : this.resources.getStaticLocations()) {
try {
Resource resource = this.applicationContext.getResource(location);
resource = resource.createRelative(viewName + ".html");
if (resource.exists()) {
return new ModelAndView(new HtmlResourceView(resource), model);
}
} catch (Exception ex) {
log.error("Error resolving resource", ex);
}
}
return null;
}
@Override
public int getOrder() {
return this.order;
}
public void setOrder(int order) {
this.order = order;
}
/**
* {@link View} backed by an HTML resource.
*/
private static class HtmlResourceView implements View {
private final Resource resource;
HtmlResourceView(Resource resource) {
this.resource = resource;
}
@Override
public String getContentType() {
return MediaType.TEXT_HTML_VALUE;
}
@Override
public void render(Map<String, ?> model, @NonNull HttpServletRequest request, HttpServletResponse response)
throws Exception {
response.setContentType(getContentType());
FileCopyUtils.copy(this.resource.getInputStream(), response.getOutputStream());
}
}
}
@@ -0,0 +1,40 @@
/*
* 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.manager.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* Registers the managed API token validation interceptor after servlet filters.
*/
@Configuration
public class ApiTokenValidationConfiguration implements WebMvcConfigurer {
private final ApiTokenValidationFilter apiTokenValidationFilter;
public ApiTokenValidationConfiguration(ApiTokenValidationFilter apiTokenValidationFilter) {
this.apiTokenValidationFilter = apiTokenValidationFilter;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(apiTokenValidationFilter).addPathPatterns("/api/**");
}
}
@@ -0,0 +1,168 @@
/*
* 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.manager.config;
import com.usthe.sureness.subject.PrincipalMap;
import com.usthe.sureness.subject.SubjectSum;
import com.usthe.sureness.util.SurenessContextHolder;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.apache.hertzbeat.collector.dispatch.DispatchConstants;
import org.apache.hertzbeat.common.constants.NetworkConstants;
import org.apache.hertzbeat.common.util.JsonUtil;
import org.apache.hertzbeat.manager.service.AccountService;
import org.apache.hertzbeat.manager.service.impl.AccountServiceImpl;
import org.jspecify.annotations.NonNull;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
/**
* Interceptor to validate that managed API tokens have not been revoked (deleted).
* <p>
* This interceptor runs AFTER the Sureness authentication filter to ensure:
* 1. Only authenticated requests are checked (avoids unnecessary DB hits)
* 2. lastUsedTime is only updated for successfully authenticated requests
* <p>
* Responsibility split:
* - <b>Expiration</b>: handled by Sureness/JWT natively via the {@code exp} claim
* - <b>Revocation</b>: handled here by checking the token's status in the database
* - <b>Last used time</b>: updated here on each valid request (throttled)
* <p>
* Only tokens containing the "managed" claim (generated by the new token management system)
* are validated against the database. Legacy tokens without this claim are allowed to pass
* through for backward compatibility.
* </p>
*/
@Component
@Slf4j
public class ApiTokenValidationFilter implements HandlerInterceptor {
private static final String ROLES_CLAIM = "roles";
private static final String TOKEN_VALIDATION_UNAVAILABLE = "Token validation unavailable";
private final AccountService accountService;
public ApiTokenValidationFilter(AccountService accountService) {
this.accountService = accountService;
}
@Override
public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler)
throws IOException {
SubjectSum subject = SurenessContextHolder.getBindSubject();
if (subject == null || !isManagedToken(subject)) {
return true;
}
String authorization = request.getHeader(NetworkConstants.AUTHORIZATION);
if (authorization != null && authorization.startsWith(DispatchConstants.BEARER)) {
String token = authorization.substring(DispatchConstants.BEARER.length()).trim();
if (!token.isEmpty()) {
try {
String rejectReason = checkManagedToken(subject, token);
if (rejectReason != null) {
return writeError(response, HttpStatus.UNAUTHORIZED, rejectReason);
}
} catch (RuntimeException e) {
log.warn("Managed token validation failed", e);
return writeError(response, HttpStatus.SERVICE_UNAVAILABLE, TOKEN_VALIDATION_UNAVAILABLE);
}
}
}
return true;
}
/**
* Check if a managed token should be rejected.
* <p>
* Returns a rejection reason string if the token should be rejected, null if allowed.
* Checks:
* 1. Only managed tokens (with "managed" claim) are validated — legacy tokens pass through
* 2. Token must exist and be active in the database (not deleted/revoked)
* 3. Token owner must still exist, remain active, and still own the claimed roles
* If the token is valid, updates the last used time.
* </p>
*/
private String checkManagedToken(SubjectSum subject, String token) {
String rejectReason = accountService.checkTokenStatus(token);
if (rejectReason != null) {
return rejectReason;
}
rejectReason = accountService.checkManagedTokenAccess(getCurrentUserId(subject), extractClaimedRoles(subject));
if (rejectReason != null) {
return rejectReason;
}
try {
accountService.touchTokenLastUsedTime(token);
} catch (RuntimeException e) {
log.debug("Failed to update token last used time", e);
}
return null;
}
private boolean isManagedToken(SubjectSum subject) {
PrincipalMap principalMap = subject.getPrincipalMap();
if (principalMap == null) {
return false;
}
Object managed = principalMap.getPrincipal(AccountServiceImpl.CLAIM_MANAGED);
return managed instanceof Boolean ? (Boolean) managed : Boolean.parseBoolean(String.valueOf(managed));
}
@SuppressWarnings("unchecked")
private List<String> extractClaimedRoles(SubjectSum subject) {
Object roles = subject.getRoles();
if (roles instanceof List<?>) {
return (List<String>) roles;
}
PrincipalMap principalMap = subject.getPrincipalMap();
if (principalMap == null) {
return Collections.emptyList();
}
Object claimedRoles = principalMap.getPrincipal(ROLES_CLAIM);
if (claimedRoles instanceof List<?>) {
return (List<String>) claimedRoles;
}
return Collections.emptyList();
}
private String getCurrentUserId(SubjectSum subject) {
Object principal = subject.getPrincipal();
return principal == null ? null : String.valueOf(principal);
}
private boolean writeError(HttpServletResponse response, HttpStatus status, String message) throws IOException {
response.setStatus(status.value());
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
try (PrintWriter writer = response.getWriter()) {
writer.write(JsonUtil.toJson(Map.of("code", status.value(), "msg", message)));
}
return false;
}
}
@@ -0,0 +1,189 @@
/*
* 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.manager.config;
import com.usthe.sureness.util.JsonWebTokenUtil;
import jakarta.annotation.Resource;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.TimeZone;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.apache.hertzbeat.common.constants.CommonConstants;
import org.apache.hertzbeat.common.entity.manager.GeneralConfig;
import org.apache.hertzbeat.common.util.AesUtil;
import org.apache.hertzbeat.common.util.JsonUtil;
import org.apache.hertzbeat.common.util.TimeZoneUtil;
import org.apache.hertzbeat.base.dao.GeneralConfigDao;
import org.apache.hertzbeat.manager.pojo.dto.MuteConfig;
import org.apache.hertzbeat.manager.pojo.dto.SystemConfig;
import org.apache.hertzbeat.manager.pojo.dto.SystemSecret;
import org.apache.hertzbeat.manager.pojo.dto.TemplateConfig;
import org.apache.hertzbeat.manager.service.AppService;
import org.apache.hertzbeat.manager.service.impl.MuteGeneralConfigServiceImpl;
import org.apache.hertzbeat.manager.service.impl.SystemGeneralConfigServiceImpl;
import org.apache.hertzbeat.manager.service.impl.SystemSecretServiceImpl;
import org.apache.hertzbeat.manager.service.impl.TemplateConfigServiceImpl;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.SmartLifecycle;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
* Config Initializer
*/
@Component
@Order(value = Ordered.HIGHEST_PRECEDENCE + 2)
public class ConfigInitializer implements SmartLifecycle {
private boolean running = false;
private static final String DEFAULT_JWT_SECRET = "CyaFv0bwq2Eik0jdrKUtsA6bx3sDJeFV643R "
+ "LnfKefTjsIfJLBa2YkhEqEGtcHDTNe4CU6+9 "
+ "8tVt4bisXQ13rbN0oxhUZR73M6EByXIO+SV5 "
+ "dKhaX0csgOCTlCxq20yhmUea6H6JIpSE2Rwp";
@Value("${sureness.jwt.secret:" + DEFAULT_JWT_SECRET + "}")
private String currentJwtSecret;
@Value("${common.secret:" + AesUtil.DEFAULT_ENCODE_RULES + "}")
private String currentAesSecret;
@Resource
private SystemGeneralConfigServiceImpl systemGeneralConfigService;
@Resource
private SystemSecretServiceImpl systemSecretService;
@Resource
private TemplateConfigServiceImpl templateConfigService;
@Resource
private MuteGeneralConfigServiceImpl muteGeneralConfigService;
@Resource
private AppService appService;
@Resource
protected GeneralConfigDao generalConfigDao;
@SneakyThrows
public void initConfig() {
// for system config
SystemConfig systemConfig = systemGeneralConfigService.getConfig();
if (systemConfig != null) {
TimeZoneUtil.setTimeZoneAndLocale(systemConfig.getTimeZoneId(), systemConfig.getLocale());
final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
simpleDateFormat.setTimeZone(TimeZone.getDefault());
} else {
// init system config data
systemConfig = SystemConfig.builder().timeZoneId(TimeZone.getDefault().getID()).theme("default")
.locale(Locale.getDefault().getLanguage() + CommonConstants.LOCALE_SEPARATOR
+ Locale.getDefault().getCountry())
.build();
String contentJson = JsonUtil.toJson(systemConfig);
GeneralConfig generalConfig2Save = GeneralConfig.builder()
.type(systemGeneralConfigService.type())
.content(contentJson)
.build();
generalConfigDao.save(generalConfig2Save);
}
// for template config, flush the template config in db to memory
TemplateConfig templateConfig = templateConfigService.getConfig();
appService.updateCustomTemplateConfig(templateConfig);
// for system jwt secrets and aes secret
boolean needUpdate = false;
SystemSecret.SystemSecretBuilder systemSecretBuilder = SystemSecret.builder();
SystemSecret systemSecret = systemSecretService.getConfig();
if (systemSecret != null) {
systemSecretBuilder.jwtSecret(systemSecret.getJwtSecret());
systemSecretBuilder.aesSecret(systemSecret.getAesSecret());
}
if (DEFAULT_JWT_SECRET.equals(currentJwtSecret)) {
// use the random jwt secret
if (systemSecret == null || StringUtils.isBlank(systemSecret.getJwtSecret())) {
currentJwtSecret = randomizeSecret(DEFAULT_JWT_SECRET);
systemSecretBuilder.jwtSecret(currentJwtSecret);
needUpdate = true;
} else {
currentJwtSecret = systemSecret.getJwtSecret();
}
}
// else use the user custom jwt secret, set the jwt secret token in util
JsonWebTokenUtil.setDefaultSecretKey(currentJwtSecret);
// Aes secret config
if (AesUtil.DEFAULT_ENCODE_RULES.equals(currentAesSecret)) {
// use the random aes secret
if (systemSecret == null || StringUtils.isBlank(systemSecret.getAesSecret())) {
currentAesSecret = randomizeSecret(AesUtil.DEFAULT_ENCODE_RULES);
systemSecretBuilder.aesSecret(currentAesSecret);
needUpdate = true;
} else {
currentAesSecret = systemSecret.getAesSecret();
}
}
AesUtil.setDefaultSecretKey(currentAesSecret);
if (needUpdate) {
systemSecretService.saveConfig(systemSecretBuilder.build());
}
// init web-app mute config
MuteConfig muteConfig = muteGeneralConfigService.getConfig();
if (muteConfig == null) {
muteConfig = MuteConfig.builder().mute(true).build();
muteGeneralConfigService.saveConfig(muteConfig);
}
}
@Override
public void start() {
initConfig();
running = true;
}
@Override
public void stop() {
running = false;
}
@Override
public boolean isRunning() {
return running;
}
@Override
public int getPhase() {
return Ordered.HIGHEST_PRECEDENCE;
}
private String randomizeSecret(String secret) {
SecureRandom random = new SecureRandom();
StringBuilder sb = new StringBuilder(secret.length());
for (int i = 0; i < secret.length(); i++) {
char ch;
do {
int codePoint = random.nextInt('z' - '0' + 1) + '0';
ch = (char) codePoint;
} while (!Character.isLetterOrDigit(ch));
sb.append(ch);
}
return sb.toString();
}
}
@@ -0,0 +1,62 @@
/*
* 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.manager.config;
import org.flywaydb.core.Flyway;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.flyway.autoconfigure.FlywayMigrationInitializer;
import org.springframework.boot.flyway.autoconfigure.FlywayProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
/**
* Flyway database migration config.
* Delays Flyway execution until after Hibernate has created/updated the schema.
*/
@Configuration
@ConditionalOnProperty(prefix = "spring.flyway", name = "enabled", havingValue = "true")
public class FlywayConfiguration {
/**
* Disable the default FlywayMigrationInitializer by providing an empty callback.
*/
@Bean
public FlywayMigrationInitializer flywayInitializer(Flyway flyway) {
return new FlywayMigrationInitializer(flyway, (f) -> {
// Empty callback - we'll run migrations manually after Hibernate
});
}
/**
* Delayed Flyway migration that runs after EntityManagerFactory is initialized.
* This ensures Hibernate's ddl-auto runs first to create/update tables,
* then Flyway can perform additional migrations if needed.
*/
@Bean
@DependsOn("entityManagerFactory")
Dummy delayedFlywayInitializer(Flyway flyway, FlywayProperties flywayProperties) {
if (flywayProperties.isEnabled()) {
flyway.migrate();
}
return new Dummy();
}
static class Dummy {
}
}
@@ -0,0 +1,45 @@
/*
* 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.manager.config;
import java.io.IOException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.lang.NonNull;
/**
* Rest Template interceptor adds request header information
*/
public class HeaderRequestInterceptor implements ClientHttpRequestInterceptor {
@Override
public ClientHttpResponse intercept(HttpRequest request, @NonNull byte[] body, @NonNull ClientHttpRequestExecution execution)
throws IOException {
// Send json by default
if (request.getHeaders().getContentType() == null) {
request.getHeaders().setContentType(MediaType.APPLICATION_JSON);
}
// Use short links
request.getHeaders().add(HttpHeaders.CONNECTION, "close");
return execution.execute(request, body);
}
}
@@ -0,0 +1,48 @@
/*
* 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.manager.config;
import org.springframework.boot.jackson.autoconfigure.JsonMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import tools.jackson.databind.DeserializationFeature;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
/**
* Jackson config.
*/
@Configuration
public class JacksonConfig {
@Bean
public JsonMapperBuilderCustomizer jsonMapperBuilderCustomizer() {
return builder -> {
final String dateTimeFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSX";
final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateTimeFormat);
simpleDateFormat.setTimeZone(TimeZone.getDefault());
builder.defaultTimeZone(TimeZone.getDefault());
builder.defaultDateFormat(simpleDateFormat);
builder.disable(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES);
builder.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
};
}
}
@@ -0,0 +1,44 @@
/*
* 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.manager.config;
import com.usthe.sureness.subject.SubjectSum;
import com.usthe.sureness.util.SurenessContextHolder;
import java.util.Optional;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.domain.AuditorAware;
/**
* generate auditor for jpa auditing
*/
@Configuration
public class JpaAuditorConfig implements AuditorAware<String> {
@Override
public Optional<String> getCurrentAuditor() {
SubjectSum subjectSum = SurenessContextHolder.getBindSubject();
String username = null;
if (subjectSum != null) {
Object principal = subjectSum.getPrincipal();
if (principal != null) {
username = String.valueOf(principal);
}
}
return Optional.ofNullable(username);
}
}
@@ -0,0 +1,34 @@
/*
* 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.manager.config;
import org.apache.hertzbeat.common.constants.ConfigConstants;
import org.apache.hertzbeat.common.constants.SignConstants;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
/**
* Manager auto configuration.
*/
@AutoConfiguration
@ComponentScan(basePackages = ConfigConstants.PkgConstant.PKG
+ SignConstants.DOT
+ ConfigConstants.FunctionModuleConstants.MANAGER)
public class ManagerAutoConfiguration {
}
@@ -0,0 +1,98 @@
/*
* 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.manager.config;
import lombok.extern.slf4j.Slf4j;
import org.apache.hertzbeat.common.constants.ManagerEventTypeEnum;
import org.apache.hertzbeat.common.entity.dto.ImportTaskMessage;
import org.apache.hertzbeat.common.entity.dto.ManagerMessage;
import org.apache.hertzbeat.common.util.JsonUtil;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.io.IOException;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
/**
* Manager SSE
*/
@Slf4j
@Component
public class ManagerSseManager {
private final Map<Long, SseEmitter> emitters = new ConcurrentHashMap<>();
public SseEmitter createEmitter(Long clientId) {
SseEmitter emitter = new SseEmitter(Long.MAX_VALUE);
emitter.onCompletion(() -> removeEmitter(clientId));
emitter.onTimeout(() -> removeEmitter(clientId));
emitters.put(clientId, emitter);
return emitter;
}
@Async
public void broadcast(String eventName, String data) {
emitters.forEach((clientId, emitter) -> {
try {
emitter.send(SseEmitter.event()
.id(String.valueOf(System.currentTimeMillis()))
.name(eventName)
.data(data));
} catch (IOException | IllegalStateException e) {
tryCompleteAndClean(clientId, emitter);
} catch (Exception exception) {
log.error("Failed to broadcast manager message data to client: {}", exception.getMessage());
tryCompleteAndClean(clientId, emitter);
}
});
}
private void tryCompleteAndClean(Long clientId, SseEmitter emitter) {
try {
Optional.ofNullable(emitter).ifPresent(ResponseBodyEmitter::complete);
} catch (Throwable e) {
log.debug("Failed to complete emitter for client {}: {}", clientId, e.getMessage());
}
// execute clear
removeEmitter(clientId);
}
public void broadcastImportTaskInProgress(String taskName, Integer progress){
ManagerMessage managerMessage = ImportTaskMessage.createInProgressMessage(taskName, progress);
broadcast(ManagerEventTypeEnum.IMPORT_TASK_EVENT.getValue(), JsonUtil.toJson(managerMessage));
}
public void broadcastImportTaskSuccess(String taskName){
ManagerMessage managerMessage = ImportTaskMessage.createCompletedMessage(taskName);
broadcast(ManagerEventTypeEnum.IMPORT_TASK_EVENT.getValue(), JsonUtil.toJson(managerMessage));
}
public void broadcastImportTaskFail(String taskName, String errMsg){
ManagerMessage managerMessage = ImportTaskMessage.createFailedMessage(taskName, errMsg);
broadcast(ManagerEventTypeEnum.IMPORT_TASK_EVENT.getValue(), JsonUtil.toJson(managerMessage));
}
private void removeEmitter(Long clientId) {
emitters.remove(clientId);
}
}
@@ -0,0 +1,81 @@
/*
* 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.manager.config;
import jakarta.annotation.PostConstruct;
import org.apache.hertzbeat.warehouse.store.history.tsdb.greptime.GreptimeProperties;
import org.apache.hertzbeat.warehouse.store.history.tsdb.vm.VictoriaMetricsProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* Configuration class for Prometheus Proxy.
* This class determines whether to use PrometheusProxyCollectImpl or PrometheusAutoCollectImpl
* based on the presence of GreptimeDB or VictoriaMetrics properties.
*/
@Component
public class PrometheusProxyConfig {
private static GreptimeProperties staticGreptimeProperties;
private static VictoriaMetricsProperties staticVictoriaMetricsProperties;
private final GreptimeProperties greptimeProperties;
private final VictoriaMetricsProperties victoriaMetricsProperties;
/**
* Constructs the factory and injects warehouse properties.
* Uses @Autowired(required = false) to allow these properties to be optional,
* in case they are not configured or enabled in the warehouse module.
*
* @param greptimeProperties GreptimeDB configuration properties.
* @param victoriaMetricsProperties VictoriaMetrics configuration properties.
*/
@Autowired
public PrometheusProxyConfig(
@Autowired(required = false) GreptimeProperties greptimeProperties,
@Autowired(required = false) VictoriaMetricsProperties victoriaMetricsProperties) {
this.greptimeProperties = greptimeProperties;
this.victoriaMetricsProperties = victoriaMetricsProperties;
}
/**
* Initializes static fields with the injected properties after construction.
* This allows the static getCollector method to access these configurations.
*/
@PostConstruct
private void initStatic() {
staticGreptimeProperties = this.greptimeProperties;
staticVictoriaMetricsProperties = this.victoriaMetricsProperties;
}
/**
* Judges whether to use PrometheusProxyCollectImpl or PrometheusAutoCollectImpl
*/
public boolean isPrometheusProxy() {
if (staticGreptimeProperties != null && staticGreptimeProperties.enabled()) {
return true;
}
if (staticVictoriaMetricsProperties != null && staticVictoriaMetricsProperties.enabled()) {
return true;
}
return false;
}
}
@@ -0,0 +1,60 @@
/*
* 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.manager.config;
import java.net.http.HttpClient;
import java.time.Duration;
import java.util.Collections;
import org.apache.hertzbeat.common.constants.NetworkConstants;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.JdkClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
/**
* RestTemplate configuration using JDK native HttpClient for Spring 7.0.
*/
@Configuration
public class RestTemplateConfig {
/**
* Create RestTemplate with JDK native request factory and custom interceptors.
*/
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
RestTemplate restTemplate = new RestTemplate(factory);
restTemplate.setInterceptors(Collections.singletonList(new HeaderRequestInterceptor()));
return restTemplate;
}
@Bean
public ClientHttpRequestFactory clientHttpRequestFactory() {
HttpClient httpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(NetworkConstants.HttpClientConstants.CONNECT_TIME_OUT))
.followRedirects(HttpClient.Redirect.NORMAL)
.build();
JdkClientHttpRequestFactory factory = new JdkClientHttpRequestFactory(httpClient);
factory.setReadTimeout(Duration.ofSeconds(NetworkConstants.HttpClientConstants.READ_TIME_OUT));
return factory;
}
}
@@ -0,0 +1,40 @@
/*
* 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.manager.config;
import lombok.extern.slf4j.Slf4j;
import org.apache.hertzbeat.manager.scheduler.ConsistentHash;
import org.apache.hertzbeat.manager.scheduler.SchedulerProperties;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* scheduler config
*/
@Configuration
@AutoConfigureAfter(value = {SchedulerProperties.class})
@Slf4j
public class SchedulerConfig {
@Bean
public ConsistentHash consistentHasInstance() {
return new ConsistentHash();
}
}
@@ -0,0 +1,49 @@
/*
* 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.manager.config;
import java.util.Collections;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
/**
* SecurityCorsConfiguration class
*/
@Configuration
public class SecurityCorsConfiguration {
@Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowCredentials(true);
corsConfiguration.setAllowedOriginPatterns(Collections.singletonList(CorsConfiguration.ALL));
corsConfiguration.addAllowedHeader(CorsConfiguration.ALL);
corsConfiguration.addAllowedMethod(CorsConfiguration.ALL);
source.registerCorsConfiguration("/**", corsConfiguration);
FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>();
bean.setOrder(Integer.MIN_VALUE);
bean.setFilter(new CorsFilter(source));
bean.addUrlPatterns("/*");
return bean;
}
}
@@ -0,0 +1,55 @@
/*
* 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.manager.config;
import lombok.Getter;
import lombok.Setter;
import org.apache.hertzbeat.common.constants.ConfigConstants;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* status page properties
*/
@Getter
@Setter
@Component
@ConfigurationProperties(prefix = ConfigConstants.FunctionModuleConstants.STATUS)
public class StatusProperties {
/**
* calculate component status properties
*/
private CalculateProperties calculate;
/**
* calculate component status properties
*/
@Getter
@Setter
public static class CalculateProperties {
/**
* the component status calculate interval(s)
*/
private Integer interval = 300;
}
}
@@ -0,0 +1,60 @@
/*
* 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.manager.config;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.ExternalDocumentation;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* swagger config
* url: /swagger-ui/index.html
*/
@Configuration
public class SwaggerConfig {
private static final String SECURITY_SCHEME_NAME = "BearerAuth";
@Bean
public OpenAPI springOpenApi() {
return new OpenAPI()
.info(new Info()
.title("HertzBeat")
.description("An Open-Source Real-time Monitoring Tool.")
.termsOfService("https://hertzbeat.apache.org/")
.contact(new Contact().name("tom").url("https://github.com/tomsun28").email("tomsun28@outlook.com"))
.version("v1.0")
.license(new License().name("Apache 2.0").url("https://www.apache.org/licenses/LICENSE-2.0")))
.externalDocs(new ExternalDocumentation()
.description("HertzBeat Docs").url("https://hertzbeat.apache.org/docs/"))
.addSecurityItem(new SecurityRequirement().addList(SECURITY_SCHEME_NAME))
.components(new Components().addSecuritySchemes(SECURITY_SCHEME_NAME,
new SecurityScheme()
.name(SECURITY_SCHEME_NAME)
.type(SecurityScheme.Type.HTTP)
.scheme("Bearer")
.bearerFormat("JWT")));
}
}
@@ -0,0 +1,75 @@
/*
* 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.manager.controller;
import static org.apache.hertzbeat.common.constants.CommonConstants.LOGIN_FAILED_CODE;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import io.jsonwebtoken.ExpiredJwtException;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import java.util.Map;
import javax.naming.AuthenticationException;
import lombok.extern.slf4j.Slf4j;
import org.apache.hertzbeat.common.entity.dto.Message;
import org.apache.hertzbeat.common.util.ResponseUtil;
import org.apache.hertzbeat.manager.pojo.dto.LoginDto;
import org.apache.hertzbeat.manager.pojo.dto.RefreshTokenResponse;
import org.apache.hertzbeat.manager.pojo.dto.TokenDto;
import org.apache.hertzbeat.manager.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Authentication registration TOKEN management API
*/
@Tag(name = "Auth Manage API")
@RestController
@RequestMapping(value = "/api/account/auth", produces = {APPLICATION_JSON_VALUE})
@Slf4j
public class AccountController {
@Autowired
private AccountService accountService;
@PostMapping("/form")
@Operation(summary = "Account password login to obtain associated user information", description = "Account password login to obtain associated user information")
public ResponseEntity<Message<Map<String, String>>> authGetToken(@Valid @RequestBody LoginDto loginDto) {
return ResponseUtil.handle(() -> accountService.authGetToken(loginDto));
}
@PostMapping("/refresh")
@Operation(summary = "Use refresh TOKEN to re-acquire TOKEN", description = "Use refresh TOKEN to re-acquire TOKEN")
public ResponseEntity<Message<RefreshTokenResponse>> refreshToken(@Valid @RequestBody TokenDto tokenDto) {
try {
return ResponseEntity.ok(Message.success(accountService.refreshToken(tokenDto.getToken())));
} catch (AuthenticationException e) {
return ResponseEntity.ok(Message.fail(LOGIN_FAILED_CODE, e.getMessage()));
} catch (ExpiredJwtException expiredJwtException) {
log.warn("{}", expiredJwtException.getMessage());
return ResponseEntity.ok(Message.fail(LOGIN_FAILED_CODE, "Refresh Token Expired"));
} catch (Exception e) {
log.error("Exception occurred during token refresh: {}", e.getClass().getName(), e);
return ResponseEntity.ok(Message.fail(LOGIN_FAILED_CODE, "Refresh Token Error"));
}
}
}
@@ -0,0 +1,181 @@
/*
* 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.manager.controller;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.apache.hertzbeat.common.entity.dto.Message;
import org.apache.hertzbeat.common.entity.job.Job;
import org.apache.hertzbeat.common.util.ResponseUtil;
import org.apache.hertzbeat.manager.pojo.dto.Hierarchy;
import org.apache.hertzbeat.manager.pojo.dto.MonitorDefineDto;
import org.apache.hertzbeat.manager.pojo.dto.ParamDefineInfo;
import org.apache.hertzbeat.manager.service.AppService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* Monitoring Type Management API
*/
@Tag(name = "Monitor Type Manage API")
@RestController
@RequestMapping(path = "/api/apps", produces = {APPLICATION_JSON_VALUE})
public class AppController {
private static final String[] RISKY_STR_ARR = {"ScriptEngineManager", "URLClassLoader", "!!",
"ClassLoader", "AnnotationConfigApplicationContext", "FileSystemXmlApplicationContext",
"GenericXmlApplicationContext", "GenericGroovyApplicationContext", "GroovyScriptEngine",
"GroovyClassLoader", "GroovyShell", "ScriptEngine", "ScriptEngineFactory", "XmlWebApplicationContext",
"ClassPathXmlApplicationContext", "MarshalOutputStream", "InflaterOutputStream", "FileOutputStream"};
@Autowired
private AppService appService;
@GetMapping(path = "/{app}/params")
@Operation(summary = "The structure of the input parameters required to specify the monitoring type according to the app query",
description = "The structure of the input parameters required to specify the monitoring type according to the app query")
public ResponseEntity<Message<List<ParamDefineInfo>>> queryAppParamDefines(
@Parameter(description = "en: Monitoring type name", example = "api") @PathVariable("app") final String app) {
return ResponseUtil.handle(() -> appService.getAppParamDefines(app.toLowerCase()));
}
@GetMapping(path = "/{monitorId}/pushdefine")
@Operation(summary = "The definition structure of the specified monitoring type according to the push query",
description = "The definition structure of the specified monitoring type according to the push query")
public ResponseEntity<Message<Job>> queryPushDefine(
@Parameter(description = "en: Monitoring type name", example = "api") @PathVariable("monitorId") final Long monitorId) {
return ResponseUtil.handle(() -> appService.getPushDefine(monitorId));
}
@GetMapping(path = "/{monitorId}/define/dynamic")
@Operation(summary = "The definition structure of the specified monitoring type according to the push query",
description = "The definition structure of the specified monitoring type according to the push query")
public ResponseEntity<Message<Job>> queryAutoGenerateDynamicAppDefine(
@Parameter(description = "Monitoring id", example = "5435345") @PathVariable("monitorId") final Long monitorId) {
return ResponseUtil.handle(() -> appService.getAutoGenerateDynamicDefine(monitorId));
}
@GetMapping(path = "/{app}/define")
@Operation(summary = "The definition structure of the specified monitoring type according to the app query",
description = "The definition structure of the specified monitoring type according to the app query")
public ResponseEntity<Message<Job>> queryAppDefine(
@Parameter(description = "en: Monitoring type name", example = "api") @PathVariable("app") final String app) {
return ResponseUtil.handle(() -> appService.getAppDefine(app.toLowerCase()));
}
@GetMapping(path = "/{app}/define/yml")
@Operation(summary = "The definition yml of the specified monitoring type according to the app query",
description = "The definition yml of the specified monitoring type according to the app query")
public ResponseEntity<Message<String>> queryAppDefineYml(
@Parameter(description = "en: Monitoring type name", example = "api") @PathVariable("app") final String app) {
return ResponseUtil.handle(() -> appService.getMonitorDefineFileContent(app));
}
@DeleteMapping(path = "/{app}/define/yml")
@Operation(summary = "Delete monitor define yml", description = "Delete the definition YML for the specified monitoring type according to the app")
public ResponseEntity<Message<Void>> deleteAppDefineYml(
@Parameter(description = "en: Monitoring type name", example = "api") @PathVariable("app") final String app) {
return ResponseUtil.handle(() -> appService.deleteMonitorDefine(app));
}
@PostMapping(path = "/define/yml")
@Operation(summary = "Add new monitoring type define yml", description = "Add new monitoring type define yml")
public ResponseEntity<Message<Void>> newAppDefineYml(@Valid @RequestBody MonitorDefineDto defineDto) {
return ResponseUtil.handle(() -> {
for (String riskyToken : RISKY_STR_ARR) {
if (defineDto.getDefine().contains(riskyToken)) {
throw new RuntimeException("can not has malicious remote script");
}
}
appService.applyMonitorDefineYml(defineDto.getDefine(), false);
});
}
@PutMapping(path = "/define/yml")
@Operation(summary = "Update monitoring type define yml", description = "Update monitoring type define yml")
public ResponseEntity<Message<Void>> updateAppDefineYml(@Valid @RequestBody MonitorDefineDto defineDto) {
return ResponseUtil.handle(() -> {
for (String riskyToken : RISKY_STR_ARR) {
if (defineDto.getDefine().contains(riskyToken)) {
throw new RuntimeException("can not has malicious remote script");
}
}
appService.applyMonitorDefineYml(defineDto.getDefine(), true);
});
}
@GetMapping(path = "/hierarchy")
@Operation(summary = "Query all monitor metrics level, output in a hierarchical structure", description = "Query all monitor metrics level, output in a hierarchical structure")
public ResponseEntity<Message<List<Hierarchy>>> queryAppsHierarchy(
@Parameter(description = "en: language type",
example = "zh-CN")
@RequestParam(name = "lang", required = false) String lang) {
String newLang = getLang(lang);
return ResponseUtil.handle(() -> appService.getAllAppHierarchy(newLang));
}
@GetMapping(path = "/hierarchy/{app}")
@Operation(summary = "Query all monitor metrics level, output in a hierarchical structure", description = "Query all monitor metrics level, output in a hierarchical structure")
public ResponseEntity<Message<List<Hierarchy>>> queryAppsHierarchyByApp(
@Parameter(description = "en: language type",
example = "zh-CN")
@RequestParam(name = "lang", required = false) String lang,
@Parameter(description = "en: Monitoring type name", example = "api") @PathVariable("app") final String app) {
String newLang = getLang(lang);
return ResponseUtil.handle(() -> appService.getAppHierarchy(app, newLang));
}
@GetMapping(path = "/defines")
@Operation(summary = "Query all monitor types", description = "Query all monitor types")
public ResponseEntity<Message<Map<String, String>>> getAllAppDefines(
@Parameter(description = "en: language type",
example = "zh-CN")
@RequestParam(name = "lang", required = false) String lang) {
String newLang = getLang(lang);
return ResponseUtil.handle(() -> appService.getI18nApps(newLang));
}
private String getLang(@RequestParam(name = "lang", required = false) @Parameter(description = "en: language type", example = "zh-CN") String lang) {
if (lang == null || lang.isEmpty()) {
lang = "zh-CN";
}
if (lang.contains(Locale.ENGLISH.getLanguage())) {
lang = "en-US";
} else if (lang.contains(Locale.CHINESE.getLanguage())) {
lang = "zh-CN";
} else {
lang = "en-US";
}
return lang;
}
}
@@ -0,0 +1,118 @@
/*
* 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.manager.controller;
import static org.apache.hertzbeat.common.constants.CommonConstants.FAIL_CODE;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import com.usthe.sureness.subject.SubjectSum;
import com.usthe.sureness.util.SurenessContextHolder;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.apache.hertzbeat.common.entity.dto.Message;
import org.apache.hertzbeat.common.entity.manager.AuthToken;
import org.apache.hertzbeat.manager.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* API Token Management Controller
*/
@Tag(name = "API Token Management")
@RestController
@RequestMapping(value = "/api/account/token", produces = {APPLICATION_JSON_VALUE})
@Slf4j
public class AuthTokenController {
@Autowired
private AccountService accountService;
@PostMapping("/generate")
@Operation(summary = "Generate a new API token", description = "Generate a new API token for integrations, optionally with expiration")
public ResponseEntity<Message<Map<String, String>>> generateToken(
@RequestParam(value = "name", required = false) @Parameter(description = "Token name/description") String name,
@RequestParam(value = "expireSeconds", required = false) @Parameter(description = "Expiration time in seconds, null means never expire") Long expireSeconds) {
SubjectSum subjectSum = SurenessContextHolder.getBindSubject();
if (subjectSum == null) {
return ResponseEntity.ok(Message.fail(FAIL_CODE, "No login user"));
}
if (!subjectSum.hasRole("admin")) {
return ResponseEntity.ok(Message.fail(FAIL_CODE, "No permission"));
}
try {
String token = accountService.generateToken(name, expireSeconds);
Map<String, String> rep = Collections.singletonMap("token", token);
return ResponseEntity.ok(Message.success(rep));
} catch (Exception e) {
log.error("generate token error", e);
return ResponseEntity.ok(Message.fail(FAIL_CODE, "Generate token error"));
}
}
@GetMapping
@Operation(summary = "List all API tokens", description = "List all active non-expiring API tokens")
public ResponseEntity<Message<List<AuthToken>>> listTokens() {
SubjectSum subjectSum = SurenessContextHolder.getBindSubject();
if (subjectSum == null) {
return ResponseEntity.ok(Message.fail(FAIL_CODE, "No login user"));
}
if (!subjectSum.hasRole("admin")) {
return ResponseEntity.ok(Message.fail(FAIL_CODE, "No permission"));
}
try {
List<AuthToken> tokens = accountService.listTokens();
return ResponseEntity.ok(Message.success(tokens));
} catch (Exception e) {
log.error("list tokens error", e);
return ResponseEntity.ok(Message.fail(FAIL_CODE, "List tokens error"));
}
}
@DeleteMapping("/{id}")
@Operation(summary = "Delete/revoke an API token", description = "Delete an API token to revoke its access")
public ResponseEntity<Message<Void>> deleteToken(
@PathVariable("id") @Parameter(description = "Token ID") Long id) {
SubjectSum subjectSum = SurenessContextHolder.getBindSubject();
if (subjectSum == null) {
return ResponseEntity.ok(Message.fail(FAIL_CODE, "No login user"));
}
if (!subjectSum.hasRole("admin")) {
return ResponseEntity.ok(Message.fail(FAIL_CODE, "No permission"));
}
try {
accountService.deleteToken(id);
return ResponseEntity.ok(Message.success(null));
} catch (javax.naming.AuthenticationException e) {
return ResponseEntity.ok(Message.fail(FAIL_CODE, "No permission"));
} catch (Exception e) {
log.error("delete token error", e);
return ResponseEntity.ok(Message.fail(FAIL_CODE, "Delete token error"));
}
}
}
@@ -0,0 +1,117 @@
/*
* 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.manager.controller;
import static org.apache.hertzbeat.common.constants.CommonConstants.FAIL_CODE;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import jakarta.validation.Valid;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.apache.hertzbeat.common.entity.dto.Message;
import org.apache.hertzbeat.common.entity.manager.Bulletin;
import org.apache.hertzbeat.manager.pojo.dto.BulletinMetricsData;
import org.apache.hertzbeat.common.util.ResponseUtil;
import org.apache.hertzbeat.manager.service.BulletinService;
import org.apache.hertzbeat.warehouse.store.realtime.RealTimeDataReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* Bulletin Controller
*/
@Slf4j
@RestController
@RequestMapping(value = "/api/bulletin", produces = {APPLICATION_JSON_VALUE})
public class BulletinController {
@Autowired
private BulletinService bulletinService;
@Autowired
private RealTimeDataReader realTimeDataReader;
@Operation(summary = "New a bulletin", description = "Add new bulletin")
@PostMapping
public ResponseEntity<Message<Void>> addNewBulletin(@Valid @RequestBody Bulletin bulletin) {
try {
bulletinService.validate(bulletin);
bulletinService.addBulletin(bulletin);
} catch (Exception e) {
return ResponseEntity.ok(Message.fail(FAIL_CODE, "Add failed! " + e.getMessage()));
}
return ResponseEntity.ok(Message.success("Add success!"));
}
@Operation(summary = "Update a bulletin", description = "Update the bulletin")
@PutMapping
public ResponseEntity<Message<Void>> editBulletin(@Valid @RequestBody Bulletin bulletin) {
try {
bulletinService.validate(bulletin);
bulletinService.editBulletin(bulletin);
} catch (Exception e) {
return ResponseEntity.ok(Message.fail(FAIL_CODE, "Edit failed! " + e.getMessage()));
}
return ResponseEntity.ok(Message.success("Add success!"));
}
@Operation(summary = "Query One Bulletin", description = "Query One Bulletin")
@GetMapping("/{id}")
public ResponseEntity<Message<Bulletin>> getBulletin(@Valid @PathVariable Long id) {
return ResponseEntity.ok(Message.success(bulletinService.getBulletinById(id).orElse(null)));
}
@Operation(summary = "Query Bulletins", description = "Query All Bulletin")
@GetMapping
public ResponseEntity<Message<Page<Bulletin>>> queryBulletins(
@Parameter(description = "Search", example = "tom") @RequestParam(required = false) final String search,
@Parameter(description = "List current page", example = "0") @RequestParam(defaultValue = "0") Integer pageIndex,
@Parameter(description = "Number of list pagination", example = "8") @RequestParam(required = false) Integer pageSize) {
return ResponseUtil.handle(() -> bulletinService.getBulletins(search, pageIndex, pageSize));
}
@Operation(summary = "Delete Bulletins", description = "Delete Bulletin by ids")
@DeleteMapping
public ResponseEntity<Message<Void>> deleteBulletin(@Parameter(description = "Bulletin ids") @RequestParam List<Long> ids) {
bulletinService.deleteBulletins(ids);
return ResponseEntity.ok(Message.success("Delete success!"));
}
@GetMapping("/metrics")
@Operation(summary = "Query All Bulletin Real Time Metrics Data", description = "Query All Bulletin real-time metrics data of monitoring indicators")
public ResponseEntity<Message<?>> getAllMetricsData(@RequestParam(name = "id") Long id) {
if (!realTimeDataReader.isServerAvailable()) {
return ResponseEntity.ok(Message.fail(FAIL_CODE, "real time store not available"));
}
BulletinMetricsData data = bulletinService.buildBulletinMetricsData(id);
return ResponseEntity.ok(Message.success(data));
}
}
@@ -0,0 +1,98 @@
/*
* 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.manager.controller;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import java.util.Map;
import org.apache.hertzbeat.common.entity.dto.Message;
import org.apache.hertzbeat.common.util.ResponseUtil;
import org.apache.hertzbeat.manager.pojo.dto.CollectorSummary;
import org.apache.hertzbeat.manager.service.CollectorService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* collector API
*/
@Tag(name = "Collector Manage API")
@RestController()
@RequestMapping(value = "/api/collector", produces = {APPLICATION_JSON_VALUE})
public class CollectorController {
@Autowired
private CollectorService collectorService;
@GetMapping
@Operation(summary = "Get a list of collectors based on query filter items",
description = "Get a list of collectors based on query filter items")
public ResponseEntity<Message<Page<CollectorSummary>>> getCollectors(
@Parameter(description = "collector name", example = "tom") @RequestParam(required = false) final String name,
@Parameter(description = "List current page", example = "0") @RequestParam(defaultValue = "0") int pageIndex,
@Parameter(description = "Number of list pagination", example = "8") @RequestParam(required = false) Integer pageSize) {
return ResponseUtil.handle(() -> collectorService.getCollectors(name, pageIndex, pageSize));
}
@PutMapping("/online")
@Operation(summary = "Online collectors")
public ResponseEntity<Message<Void>> onlineCollector(
@Parameter(description = "collector name", example = "demo-collector")
@RequestParam(required = false) List<String> collectors) {
collectorService.makeCollectorsOnline(collectors);
return ResponseEntity.ok(Message.success("Online success"));
}
@PutMapping("/offline")
@Operation(summary = "Offline collectors")
public ResponseEntity<Message<Void>> offlineCollector(
@Parameter(description = "collector name", example = "demo-collector")
@RequestParam(required = false) List<String> collectors) {
collectorService.makeCollectorsOffline(collectors);
return ResponseEntity.ok(Message.success("Offline success"));
}
@DeleteMapping
@Operation(summary = "Delete collectors")
public ResponseEntity<Message<Void>> deleteCollector(
@Parameter(description = "collector name", example = "demo-collector")
@RequestParam(required = false) List<String> collectors) {
this.collectorService.deleteRegisteredCollector(collectors);
return ResponseEntity.ok(Message.success("Delete success"));
}
@PostMapping("/generate/{collector}")
@Operation(summary = "Generate deploy collector info")
public ResponseEntity<Message<Map<String, String>>> generateCollectorDeployInfo(
@Parameter(description = "collector name", example = "demo-collector")
@PathVariable() String collector) {
return ResponseUtil.handle(() -> collectorService.generateCollectorDeployInfo(collector));
}
}
@@ -0,0 +1,117 @@
/*
* 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.manager.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j;
import org.apache.hertzbeat.common.entity.dto.Message;
import org.apache.hertzbeat.common.util.CommonUtil;
import org.apache.hertzbeat.common.util.ResponseUtil;
import org.apache.hertzbeat.manager.pojo.dto.TemplateConfig;
import org.apache.hertzbeat.manager.service.ConfigService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.TextStyle;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
/**
* Generate Configuration API
*/
@RestController
@RequestMapping(value = "/api/config", produces = {APPLICATION_JSON_VALUE})
@Tag(name = "Generate Configuration API")
@Slf4j
public class GeneralConfigController {
private static final Set<String> ZONE_IDS = ZoneId.getAvailableZoneIds();
@Resource
private ConfigService configService;
@PostMapping(path = "/{type}")
@Operation(summary = "Save or update common config", description = "Save or update common config")
public ResponseEntity<Message<String>> saveOrUpdateConfig(
@Parameter(description = "Config Type", example = "email")
@PathVariable("type") @NotNull final String type,
@RequestBody Object config) {
configService.saveConfig(type, config);
return ResponseEntity.ok(Message.success("Update config success"));
}
@GetMapping(path = "/{type}")
@Operation(summary = "Get the sender config", description = "Get the sender config")
public ResponseEntity<Message<Object>> getConfig(
@Parameter(description = "Config Type", example = "email")
@PathVariable("type") @NotNull final String type) {
return ResponseUtil.handle(() -> configService.getConfig(type));
}
@PutMapping(path = "/template/{app}")
@Operation(summary = "Update the app template config")
public ResponseEntity<Message<Void>> updateTemplateAppConfig(
@PathVariable("app") @NotNull final String app,
@RequestBody TemplateConfig.AppTemplate template) {
return ResponseUtil.handle(() -> configService.updateTemplateAppConfig(app, template));
}
@GetMapping(path = "/timezones")
@Operation(summary = "Get all available timezones and their current UTC offset", description = "Get all available timezones and their current UTC offset")
public ResponseEntity<Message<List<Map<String, String>>>> getTimezones() {
List<Map<String, String>> timezones = ZONE_IDS.stream()
.map(id -> {
try {
ZoneId zoneId = ZoneId.of(id);
ZonedDateTime now = ZonedDateTime.now(zoneId);
int totalSeconds = now.getOffset().getTotalSeconds();
String offset = String.format("UTC%+03d:%02d", totalSeconds / 3600, Math.abs((totalSeconds / 60) % 60));
String displayName = zoneId.getDisplayName(TextStyle.FULL, Locale.getDefault());
return Map.of("zoneId", id, "offset", offset, "displayName", displayName);
} catch (Exception e) {
String errorMsg = CommonUtil.getMessageFromThrowable(e);
log.warn("Query Timezone failed. {} ", errorMsg);
return null;
}
})
.filter(t -> Objects.nonNull(t) && Objects.nonNull(t.get("zoneId")))
.sorted(Comparator.comparing(m -> m.get("zoneId")))
.collect(Collectors.toList());
return ResponseEntity.ok(Message.success(timezones));
}
}
@@ -0,0 +1,58 @@
/*
* 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.manager.controller;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.Map;
import org.apache.hertzbeat.common.entity.dto.Message;
import org.apache.hertzbeat.manager.service.AppService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Internationalization I18N
*/
@Tag(name = "I18N International Resource API")
@RestController
@RequestMapping(path = "/api/i18n", produces = {APPLICATION_JSON_VALUE})
public class I18nController {
@Autowired
private AppService appService;
@GetMapping("/{lang}")
@Operation(summary = "Query total i 18 n internationalized text resources", description = "Query total i18n internationalized text resources")
public ResponseEntity<Message<Map<String, String>>> queryI18n(
@Parameter(description = "en: language type", example = "zh-CN")
@PathVariable(name = "lang", required = false) String lang) {
if (lang == null || lang.isEmpty()) {
lang = "zh-CN";
}
lang = "zh-cn".equalsIgnoreCase(lang) || "zh_cn".equalsIgnoreCase(lang) ? "zh-CN" : lang;
lang = "en-us".equalsIgnoreCase(lang) || "en_us".equalsIgnoreCase(lang) ? "en-US" : lang;
Map<String, String> i18nResource = appService.getI18nResources(lang);
return ResponseEntity.ok(Message.success(i18nResource));
}
}
@@ -0,0 +1,87 @@
/*
* 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.manager.controller;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import java.util.HashSet;
import java.util.List;
import org.apache.hertzbeat.common.entity.dto.Message;
import org.apache.hertzbeat.common.entity.manager.Label;
import org.apache.hertzbeat.base.service.LabelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* Label management API
*/
@Tag(name = "Label Manage API")
@RestController
@RequestMapping(path = "/api/label", produces = {APPLICATION_JSON_VALUE})
public class LabelController {
@Autowired
private LabelService labelService;
@PostMapping
@Operation(summary = "Add Label", description = "Add Label")
public ResponseEntity<Message<Void>> addNewLabels(@Valid @RequestBody Label label) {
labelService.addLabel(label);
return ResponseEntity.ok(Message.success("Add success"));
}
@PutMapping
@Operation(summary = "Modify an existing Label", description = "Modify an existing Label")
public ResponseEntity<Message<Void>> modifyLabel(@Valid @RequestBody Label label) {
if (label.getId() == null) {
throw new IllegalArgumentException("ID cannot be null.");
}
labelService.modifyLabel(label);
return ResponseEntity.ok(Message.success("Modify success"));
}
@GetMapping()
@Operation(summary = "Get labels information", description = "Obtain label information based on conditions")
public ResponseEntity<Message<Page<Label>>> getLabels(
@Parameter(description = "Label content search", example = "status") @RequestParam(required = false) String search,
@Parameter(description = "Label type", example = "0") @RequestParam(required = false) Byte type,
@Parameter(description = "List current page", example = "0") @RequestParam(defaultValue = "0") int pageIndex,
@Parameter(description = "Number of list pagination", example = "8") @RequestParam(defaultValue = "8") int pageSize) {
return ResponseEntity.ok(Message.success(labelService.getLabels(search, type, pageIndex, pageSize)));
}
@DeleteMapping()
@Operation(summary = "Delete Label based on ID", description = "Delete Label based on ID")
public ResponseEntity<Message<Void>> deleteLabels(
@Parameter(description = "Label id ", example = "6565463543") @RequestParam(required = false) List<Long> ids) {
labelService.deleteLabels(new HashSet<>(ids));
return ResponseEntity.ok(Message.success("Delete success"));
}
}
@@ -0,0 +1,50 @@
/*
* 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.manager.controller;
import org.apache.hertzbeat.common.util.SnowFlakeIdGenerator;
import org.apache.hertzbeat.manager.config.ManagerSseManager;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import static org.springframework.http.MediaType.TEXT_EVENT_STREAM_VALUE;
/**
* SSE controller for manager
*/
@RestController
@RequestMapping(path = "/api/manager/sse", produces = {TEXT_EVENT_STREAM_VALUE})
public class ManagerSseController {
private final ManagerSseManager emitterManager;
public ManagerSseController(ManagerSseManager emitterManager) {
this.emitterManager = emitterManager;
}
@GetMapping(path = "/subscribe")
public SseEmitter subscribe() {
Long clientId = SnowFlakeIdGenerator.generateId();
return emitterManager.createEmitter(clientId);
}
}
@@ -0,0 +1,55 @@
/*
* 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.manager.controller;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.HashMap;
import java.util.Map;
import org.apache.hertzbeat.common.entity.dto.Message;
import org.apache.hertzbeat.common.queue.CommonDataQueue;
import org.apache.hertzbeat.common.queue.impl.InMemoryCommonDataQueue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* hertzbeat metrics exporter
*/
@Tag(name = "Inner Metrics Exporter API")
@RestController
@RequestMapping(path = "/api/metrics", produces = {APPLICATION_JSON_VALUE})
public class MetricsController {
@Autowired
private CommonDataQueue commonDataQueue;
@GetMapping()
@Operation(summary = "Get Hertzbeat Metrics Data")
public ResponseEntity<Message<Map<String, Object>>> getMetricsInfo() {
Map<String, Object> metricsInfo = new HashMap<>(8);
if (commonDataQueue instanceof InMemoryCommonDataQueue dataQueue) {
Map<String, Integer> queueInfo = dataQueue.getQueueSizeMetricsInfo();
metricsInfo.putAll(queueInfo);
}
return ResponseEntity.ok(Message.success(metricsInfo));
}
}
@@ -0,0 +1,105 @@
/*
* 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.manager.controller;
import com.usthe.sureness.subject.SubjectSum;
import com.usthe.sureness.util.SurenessContextHolder;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.hertzbeat.common.entity.dto.Message;
import org.apache.hertzbeat.manager.service.MetricsFavoriteService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Set;
import static org.apache.hertzbeat.common.constants.CommonConstants.LOGIN_FAILED_CODE;
/**
* Metrics Favorite Controller
*/
@Tag(name = "Metrics Favorite API")
@RestController
@RequestMapping(path = "/api/metrics/favorite")
@RequiredArgsConstructor
@Slf4j
public class MetricsFavoriteController {
private final MetricsFavoriteService metricsFavoriteService;
@PostMapping("/{monitorId}/{metricsName}")
@Operation(summary = "Add metrics to favorites", description = "Add specific metrics to user's favorites")
public ResponseEntity<Message<Void>> addMetricsFavorite(
@Parameter(description = "Monitor ID", example = "6565463543") @PathVariable Long monitorId,
@Parameter(description = "Metrics name", example = "cpu") @PathVariable String metricsName) {
String user = getCurrentUser();
if (user == null) {
return ResponseEntity.ok(Message.fail(LOGIN_FAILED_CODE, "User not authenticated"));
}
metricsFavoriteService.addMetricsFavorite(user, monitorId, metricsName);
return ResponseEntity.ok(Message.success("Metrics added to favorites successfully"));
}
@DeleteMapping("/{monitorId}/{metricsName}")
@Operation(summary = "Remove metrics from favorites", description = "Remove specific metrics from user's favorites")
public ResponseEntity<Message<Void>> removeMetricsFavorite(
@Parameter(description = "Monitor ID", example = "6565463543") @PathVariable Long monitorId,
@Parameter(description = "Metrics name", example = "cpu") @PathVariable String metricsName) {
String user = getCurrentUser();
if (user == null) {
return ResponseEntity.ok(Message.fail(LOGIN_FAILED_CODE, "User not authenticated"));
}
metricsFavoriteService.removeMetricsFavorite(user, monitorId, metricsName);
return ResponseEntity.ok(Message.success("Metrics removed from favorites successfully"));
}
@GetMapping("/{monitorId}")
@Operation(summary = "Get user's all favorited metrics", description = "Get all favorited metrics for current user")
public ResponseEntity<Message<Set<String>>> getUserFavoritedMetrics(@Parameter(description = "Monitor ID", example = "6565463543") @PathVariable Long monitorId) {
String user = getCurrentUser();
if (user == null) {
return ResponseEntity.ok(Message.fail(LOGIN_FAILED_CODE, "User not authenticated"));
}
Set<String> favoritedMetrics = metricsFavoriteService.getUserFavoritedMetrics(user, monitorId);
return ResponseEntity.ok(Message.success(favoritedMetrics));
}
/**
* Get current user ID for favorite status
*
* @return user id
*/
private String getCurrentUser() {
try {
SubjectSum subjectSum = SurenessContextHolder.getBindSubject();
return String.valueOf(subjectSum.getPrincipal());
} catch (Exception e) {
log.error("No user found, favorites will be disabled");
return null;
}
}
}
@@ -0,0 +1,117 @@
/*
* 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.manager.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.apache.hertzbeat.common.entity.dto.Message;
import org.apache.hertzbeat.common.entity.manager.Monitor;
import org.apache.hertzbeat.manager.pojo.dto.MonitorDto;
import org.apache.hertzbeat.manager.service.MonitorService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import static org.apache.hertzbeat.common.constants.CommonConstants.FAIL_CODE;
import static org.apache.hertzbeat.common.constants.CommonConstants.MONITOR_NOT_EXIST_CODE;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
/**
* Monitoring management API
*/
@Tag(name = "Monitor Manage API")
@RestController
@RequestMapping(path = "/api/monitor", produces = {APPLICATION_JSON_VALUE})
public class MonitorController {
@Autowired
private MonitorService monitorService;
@PostMapping
@Operation(summary = "Add a monitoring application", description = "Add a monitoring application")
public ResponseEntity<Message<Void>> addNewMonitor(@Valid @RequestBody MonitorDto monitorDto) {
// Verify request data
monitorService.validate(monitorDto, false);
monitorService.addMonitor(monitorDto.getMonitor(), monitorDto.getParams(), monitorDto.getCollector(), monitorDto.getGrafanaDashboard());
return ResponseEntity.ok(Message.success("Add success"));
}
@PutMapping
@Operation(summary = "Modify an existing monitoring application", description = "Modify an existing monitoring application")
public ResponseEntity<Message<Void>> modifyMonitor(@Valid @RequestBody MonitorDto monitorDto) {
// Verify request data
monitorService.validate(monitorDto, true);
monitorService.modifyMonitor(monitorDto.getMonitor(), monitorDto.getParams(), monitorDto.getCollector(), monitorDto.getGrafanaDashboard());
return ResponseEntity.ok(Message.success("Modify success"));
}
@GetMapping(path = "/{id}")
@Operation(summary = "Obtain monitoring information based on monitoring ID", description = "Obtain monitoring information based on monitoring ID")
public ResponseEntity<Message<MonitorDto>> getMonitor(
@Parameter(description = "Monitoring task ID", example = "6565463543") @PathVariable("id") final long id) {
// Get monitoring information
MonitorDto monitorDto = monitorService.getMonitorDto(id);
if (monitorDto == null) {
return ResponseEntity.ok(Message.fail(MONITOR_NOT_EXIST_CODE, "Monitor not exist."));
} else {
return ResponseEntity.ok(Message.success(monitorDto));
}
}
@DeleteMapping(path = "/{id}")
@Operation(summary = "Delete monitoring application based on monitoring ID", description = "Delete monitoring application based on monitoring ID")
public ResponseEntity<Message<Void>> deleteMonitor(
@Parameter(description = "en: Monitor ID", example = "6565463543") @PathVariable("id") final long id) {
// delete monitor
Monitor monitor = monitorService.getMonitor(id);
if (monitor == null) {
return ResponseEntity.ok(Message.success("The specified monitoring was not queried, please check whether the parameters are correct"));
}
monitorService.deleteMonitor(id);
return ResponseEntity.ok(Message.success("Delete success"));
}
@PostMapping(path = "/detect")
@Operation(summary = "Perform availability detection on this monitoring based on monitoring information",
description = "Perform availability detection on this monitoring based on monitoring information")
public ResponseEntity<Message<Void>> detectMonitor(@Valid @RequestBody MonitorDto monitorDto) {
monitorService.validate(monitorDto, null);
monitorService.detectMonitor(monitorDto.getMonitor(), monitorDto.getParams(), monitorDto.getCollector());
return ResponseEntity.ok(Message.success("Detect success."));
}
@PostMapping("/copy/{id}")
@Operation(summary = "Copy Monitor", description = "Copy an existing monitor")
public ResponseEntity<Message<Void>> copyMonitor(@PathVariable("id") final Long id) {
try {
monitorService.copyMonitor(id);
return ResponseEntity.ok(Message.success("Copy monitor success"));
} catch (Exception e) {
return ResponseEntity.ok(Message.fail(FAIL_CODE, "Copy monitor failed: " + e.getMessage()));
}
}
}
@@ -0,0 +1,144 @@
/*
* 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.manager.controller;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import org.apache.hertzbeat.common.entity.dto.Message;
import org.apache.hertzbeat.common.entity.manager.Monitor;
import org.apache.hertzbeat.manager.pojo.dto.MonitorInfo;
import org.apache.hertzbeat.manager.service.MonitorService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
/**
* Monitor and manage batch API
*/
@Tag(name = "Monitor Manage Batch API")
@RestController
@RequestMapping(path = "/api/monitors", produces = {APPLICATION_JSON_VALUE})
public class MonitorsController {
@Autowired
private MonitorService monitorService;
@GetMapping
@Operation(summary = "Obtain a list of monitoring information based on query filter items",
description = "Obtain a list of monitoring information based on query filter items")
public ResponseEntity<Message<Page<MonitorInfo>>> getMonitors(
@Parameter(description = "Monitor ID", example = "6565463543") @RequestParam(required = false) final List<Long> ids,
@Parameter(description = "Monitor Type", example = "linux") @RequestParam(required = false) final String app,
@Parameter(description = "Monitor Status 0:no monitor,1:usable,2:disabled,9:all status", example = "1") @RequestParam(required = false) final Byte status,
@Parameter(description = "Monitor Host support fuzzy query", example = "127.0.0.1") @RequestParam(required = false) final String search,
@Parameter(description = "Monitor labels ", example = "env:prod,instance:22") @RequestParam(required = false) final String labels,
@Parameter(description = "Sort Field ", example = "name") @RequestParam(defaultValue = "gmtCreate") final String sort,
@Parameter(description = "Sort mode eg:asc desc", example = "desc") @RequestParam(defaultValue = "desc") final String order,
@Parameter(description = "List current page", example = "0") @RequestParam(defaultValue = "0") int pageIndex,
@Parameter(description = "Number of list pagination ", example = "8") @RequestParam(defaultValue = "8") int pageSize) {
Page<Monitor> monitorPage = monitorService.getMonitors(ids, app, search, status, sort, order, pageIndex, pageSize, labels);
Page<MonitorInfo> responsePage = monitorPage == null ? Page.empty() : monitorPage.map(MonitorInfo::fromEntity);
return ResponseEntity.ok(Message.success(responsePage));
}
@GetMapping(path = "/{app}")
@Operation(summary = "Filter all acquired monitoring information lists of the specified monitoring type according to the query",
description = "Filter all acquired monitoring information lists of the specified monitoring type according to the query")
public ResponseEntity<Message<List<MonitorInfo>>> getAppMonitors(
@Parameter(description = "en: Monitoring type", example = "linux") @PathVariable(required = false) final String app) {
List<Monitor> monitors = monitorService.getAppMonitors(app);
List<MonitorInfo> response = monitors == null ? Collections.emptyList()
: monitors.stream().map(MonitorInfo::fromEntity).toList();
return ResponseEntity.ok(Message.success(response));
}
@DeleteMapping
@Operation(summary = "Delete monitoring items in batches according to the monitoring ID list",
description = "Delete monitoring items in batches according to the monitoring ID list")
public ResponseEntity<Message<Void>> deleteMonitors(
@Parameter(description = "Monitoring ID List", example = "6565463543") @RequestParam(required = false) List<Long> ids
) {
if (ids != null && !ids.isEmpty()) {
monitorService.deleteMonitors(new HashSet<>(ids));
}
return ResponseEntity.ok(Message.success());
}
@DeleteMapping("manage")
@Operation(summary = "Unmanaged monitoring items in batches according to the monitoring ID list",
description = "Unmanaged monitoring items in batches according to the monitoring ID list")
public ResponseEntity<Message<Void>> cancelManageMonitors(
@Parameter(description = "Monitoring ID List", example = "6565463543") @RequestParam(required = false) List<Long> ids
) {
if (ids != null && !ids.isEmpty()) {
monitorService.cancelManageMonitors(new HashSet<>(ids));
}
return ResponseEntity.ok(Message.success());
}
@GetMapping("manage")
@Operation(summary = "Start the managed monitoring items in batches according to the monitoring ID list",
description = "Start the managed monitoring items in batches according to the monitoring ID list")
public ResponseEntity<Message<Void>> enableManageMonitors(
@Parameter(description = "Monitor ID List", example = "6565463543") @RequestParam(required = false) List<Long> ids
) {
if (ids != null && !ids.isEmpty()) {
monitorService.enableManageMonitors(new HashSet<>(ids));
}
return ResponseEntity.ok(Message.success());
}
@GetMapping("/export")
@Operation(summary = "export monitor config", description = "export monitor config")
public void export(
@Parameter(description = "Monitor ID List", example = "6565463543") @RequestParam List<Long> ids,
@Parameter(description = "Export Type:JSON,EXCEL") @RequestParam(defaultValue = "JSON") String type,
HttpServletResponse res) throws Exception {
monitorService.export(ids, type, res);
}
@GetMapping("/export/all")
@Operation(summary = "export all monitor config", description = "export all monitor config")
public void exportAll(
@Parameter(description = "Export Type:JSON,EXCEL,YAML") @RequestParam(defaultValue = "JSON") String type,
HttpServletResponse res) throws Exception {
monitorService.exportAll(type, res);
}
@PostMapping("/import")
@Operation(summary = "import monitor config", description = "import monitor config")
public ResponseEntity<Message<Void>> export(MultipartFile file) throws Exception {
monitorService.importConfig(file);
return ResponseEntity.ok(Message.success("Import success"));
}
}
@@ -0,0 +1,105 @@
/*
* 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.manager.controller;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import jakarta.validation.Valid;
import java.util.HashSet;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.apache.hertzbeat.common.entity.dto.Message;
import org.apache.hertzbeat.common.entity.manager.PluginMetadata;
import org.apache.hertzbeat.manager.pojo.dto.PluginUpload;
import org.apache.hertzbeat.manager.pojo.dto.PluginParam;
import org.apache.hertzbeat.manager.pojo.dto.PluginParametersVO;
import org.apache.hertzbeat.manager.service.PluginService;
import org.springframework.data.domain.Page;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* plugin management API
*/
@io.swagger.v3.oas.annotations.tags.Tag(name = "Plugin Manage API")
@RestController
@RequestMapping(path = "/api/plugin", produces = {APPLICATION_JSON_VALUE})
@RequiredArgsConstructor
public class PluginController {
private final PluginService pluginService;
@PostMapping
@Operation(summary = "upload plugin", description = "upload plugin")
public ResponseEntity<Message<Void>> uploadNewPlugin(@Valid PluginUpload pluginUpload) {
pluginService.savePlugin(pluginUpload);
return ResponseEntity.ok(Message.success("Add success"));
}
@GetMapping()
@Operation(summary = "Get Plugins information", description = "Obtain plugins information based on conditions")
public ResponseEntity<Message<Page<PluginMetadata>>> getPlugins(
@Parameter(description = "plugin name search", example = "status") @RequestParam(required = false) String search,
@Parameter(description = "List current page", example = "0") @RequestParam(defaultValue = "0") int pageIndex,
@Parameter(description = "Number of list pagination", example = "8") @RequestParam(defaultValue = "8") int pageSize) {
Page<PluginMetadata> alertPage = pluginService.getPlugins(search, pageIndex, pageSize);
return ResponseEntity.ok(Message.success(alertPage));
}
@DeleteMapping()
@Operation(summary = "Delete plugins based on ID", description = "Delete plugins based on ID")
public ResponseEntity<Message<Void>> deletePlugins(
@Parameter(description = "Plugin IDs ", example = "6565463543") @RequestParam(required = false) List<Long> ids) {
if (ids != null && !ids.isEmpty()) {
pluginService.deletePlugins(new HashSet<>(ids));
}
return ResponseEntity.ok(Message.success("Delete success"));
}
@PutMapping()
@Operation(summary = "Update enable status", description = "Delete plugins based on ID")
public ResponseEntity<Message<Void>> updatePluginStatus(@RequestBody PluginMetadata plugin) {
pluginService.updateStatus(plugin);
return ResponseEntity.ok(Message.success("Update success"));
}
@GetMapping("/params/define")
@Operation(summary = "get param define", description = "get param define by jar path")
public ResponseEntity<Message<PluginParametersVO>> getParamDefine(@RequestParam Long pluginMetadataId) {
PluginParametersVO plugins = pluginService.getParamDefine(pluginMetadataId);
return ResponseEntity.ok(Message.success(plugins));
}
@PostMapping("/params")
@Operation(summary = "get param define", description = "get param define by jar path")
public ResponseEntity<Message<Boolean>> saveParams(@RequestBody List<PluginParam> pluginParams) {
pluginService.savePluginParam(pluginParams);
return ResponseEntity.ok(Message.success(true));
}
}
@@ -0,0 +1,146 @@
/*
* 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.manager.controller;
import io.swagger.v3.oas.annotations.Parameter;
import org.springframework.data.domain.Page;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import jakarta.validation.Valid;
import org.apache.hertzbeat.common.constants.CommonConstants;
import org.apache.hertzbeat.common.entity.dto.Message;
import org.apache.hertzbeat.manager.pojo.dto.StatusPageComponentInfo;
import org.apache.hertzbeat.manager.pojo.dto.StatusPageIncidentInfo;
import org.apache.hertzbeat.manager.pojo.dto.StatusPageOrgInfo;
import org.apache.hertzbeat.manager.service.StatusPageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* status page endpoint controller
*/
@Tag(name = "Status Page API")
@RestController()
@RequestMapping(value = "/api/status/page", produces = {APPLICATION_JSON_VALUE})
public class StatusPageController {
@Autowired
private StatusPageService statusPageService;
@GetMapping("/org")
@Operation(summary = "Query Status Page Organization")
public ResponseEntity<Message<StatusPageOrgInfo>> queryStatusPageOrg() {
StatusPageOrgInfo statusPageOrg = statusPageService.queryStatusPageOrg();
if (statusPageOrg == null) {
return ResponseEntity.ok(Message.fail(CommonConstants.FAIL_CODE, "Status Page Organization Not Found"));
}
return ResponseEntity.ok(Message.success(statusPageOrg));
}
@PostMapping("/org")
@Operation(summary = "Save and Update Query Status Page Organization")
public ResponseEntity<Message<StatusPageOrgInfo>> saveStatusPageOrg(@Valid @RequestBody StatusPageOrgInfo statusPageOrg) {
StatusPageOrgInfo org = statusPageService.saveStatusPageOrg(statusPageOrg);
return ResponseEntity.ok(Message.success(org));
}
@GetMapping("/component")
@Operation(summary = "Query Status Page Components")
public ResponseEntity<Message<List<StatusPageComponentInfo>>> queryStatusPageComponent() {
return ResponseEntity.ok(Message.success(statusPageService.queryStatusPageComponents()));
}
@PostMapping("/component")
@Operation(summary = "Save Status Page Component")
public ResponseEntity<Message<Void>> newStatusPageComponent(@Valid @RequestBody StatusPageComponentInfo statusPageComponent) {
statusPageService.newStatusPageComponent(statusPageComponent);
return ResponseEntity.ok(Message.success("Add success"));
}
@PutMapping("/component")
@Operation(summary = "Update Status Page Component")
public ResponseEntity<Message<Void>> updateStatusPageComponent(@Valid @RequestBody StatusPageComponentInfo statusPageComponent) {
statusPageService.updateStatusPageComponent(statusPageComponent);
return ResponseEntity.ok(Message.success("Update success"));
}
@DeleteMapping("/component/{id}")
@Operation(summary = "Delete Status Page Component")
public ResponseEntity<Message<Void>> deleteStatusPageComponent(@PathVariable("id") final long id) {
statusPageService.deleteStatusPageComponent(id);
return ResponseEntity.ok(Message.success("Delete success"));
}
@GetMapping("/component/{id}")
@Operation(summary = "Query Status Page Component")
public ResponseEntity<Message<StatusPageComponentInfo>> queryStatusPageComponent(@PathVariable("id") final long id) {
return ResponseEntity.ok(Message.success(statusPageService.queryStatusPageComponent(id)));
}
@PostMapping("/incident")
@Operation(summary = "Save Status Page Incident")
public ResponseEntity<Message<Void>> newStatusPageIncident(@Valid @RequestBody StatusPageIncidentInfo incident) {
statusPageService.newStatusPageIncident(incident);
return ResponseEntity.ok(Message.success("Add success"));
}
@PutMapping("/incident")
@Operation(summary = "Update Status Page Incident")
public ResponseEntity<Message<Void>> updateStatusPageIncident(@Valid @RequestBody StatusPageIncidentInfo incident) {
statusPageService.updateStatusPageIncident(incident);
return ResponseEntity.ok(Message.success("Update success"));
}
@DeleteMapping("/incident/{id}")
@Operation(summary = "Delete Status Page Incident")
public ResponseEntity<Message<Void>> deleteStatusPageIncident(@PathVariable("id") final long id) {
statusPageService.deleteStatusPageIncident(id);
return ResponseEntity.ok(Message.success("Delete success"));
}
@GetMapping("/incident/{id}")
@Operation(summary = "Get Status Page Incident")
public ResponseEntity<Message<StatusPageIncidentInfo>> queryStatusPageIncident(@PathVariable("id") final long id) {
return ResponseEntity.ok(Message.success(statusPageService.queryStatusPageIncident(id)));
}
@GetMapping("/incident")
@Operation(summary = "Query Status Page Incidents")
public ResponseEntity<Message<Page<StatusPageIncidentInfo>>> queryStatusPageIncident(
@Parameter(description = "Search-Target", example = "x") @RequestParam(required = false) String search,
@Parameter(description = "Start Time", example = "1756384301907") @RequestParam(required = false) Long startTime,
@Parameter(description = "End Time", example = "1756384301907") @RequestParam(required = false) Long endTime,
@Parameter(description = "List current page", example = "0") @RequestParam(defaultValue = "0") int pageIndex,
@Parameter(description = "Number of list pages", example = "8") @RequestParam(defaultValue = "8") int pageSize) {
Page<StatusPageIncidentInfo> incidents = statusPageService.queryStatusPageIncidents(search, startTime, endTime, pageIndex, pageSize);
return ResponseEntity.ok(Message.success(incidents));
}
}
@@ -0,0 +1,88 @@
/*
* 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.manager.controller;
import io.swagger.v3.oas.annotations.Parameter;
import org.springframework.data.domain.Page;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import org.apache.hertzbeat.common.constants.CommonConstants;
import org.apache.hertzbeat.common.entity.dto.Message;
import org.apache.hertzbeat.manager.pojo.dto.ComponentStatus;
import org.apache.hertzbeat.manager.pojo.dto.StatusPageIncidentInfo;
import org.apache.hertzbeat.manager.pojo.dto.StatusPageOrgInfo;
import org.apache.hertzbeat.manager.service.StatusPageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* status page public endpoint controller
*/
@Tag(name = "Status Page Public API")
@RestController()
@RequestMapping(value = "/api/status/page/public", produces = {APPLICATION_JSON_VALUE})
public class StatusPagePublicController {
@Autowired
private StatusPageService statusPageService;
@GetMapping("/org")
@Operation(summary = "Query Status Page Organization")
public ResponseEntity<Message<StatusPageOrgInfo>> queryStatusPageOrg() {
StatusPageOrgInfo statusPageOrg = statusPageService.queryStatusPageOrg();
if (statusPageOrg == null) {
return ResponseEntity.ok(Message.fail(CommonConstants.FAIL_CODE, "Status Page Organization Not Found"));
}
return ResponseEntity.ok(Message.success(statusPageOrg));
}
@GetMapping("/component")
@Operation(summary = "Query Status Page Components")
public ResponseEntity<Message<List<ComponentStatus>>> queryStatusPageComponent() {
List<ComponentStatus> componentStatusList = statusPageService.queryComponentsStatus();
return ResponseEntity.ok(Message.success(componentStatusList));
}
@GetMapping("/component/{id}")
@Operation(summary = "Query Status Page Component")
public ResponseEntity<Message<ComponentStatus>> queryStatusPageComponent(@PathVariable("id") final long id) {
ComponentStatus componentStatus = statusPageService.queryComponentStatus(id);
return ResponseEntity.ok(Message.success(componentStatus));
}
@GetMapping("/incident")
@Operation(summary = "Query Status Page Incidents")
public ResponseEntity<Message<Page<StatusPageIncidentInfo>>> queryStatusPageIncident(
@Parameter(description = "Search-Target", example = "x") @RequestParam(required = false) String search,
@Parameter(description = "Start Time", example = "1756384301907") @RequestParam(required = false) Long startTime,
@Parameter(description = "End Time", example = "1756384301907") @RequestParam(required = false) Long endTime,
@Parameter(description = "List current page", example = "0") @RequestParam(defaultValue = "0") int pageIndex,
@Parameter(description = "Number of list pages", example = "10") @RequestParam(defaultValue = "10") int pageSize) {
Page<StatusPageIncidentInfo> incidents = statusPageService.queryStatusPageIncidents(search, startTime, endTime, pageIndex, pageSize);
return ResponseEntity.ok(Message.success(incidents));
}
}
@@ -0,0 +1,52 @@
/*
* 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.manager.controller;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import org.apache.hertzbeat.common.entity.dto.Message;
import org.apache.hertzbeat.manager.pojo.dto.AppCount;
import org.apache.hertzbeat.manager.pojo.dto.Dashboard;
import org.apache.hertzbeat.manager.service.MonitorService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* System Summary Statistics API
*/
@Tag(name = "Summary Statistics API")
@RestController
@RequestMapping(path = "/api/summary", produces = {APPLICATION_JSON_VALUE})
public class SummaryController {
@Autowired
private MonitorService monitorService;
@GetMapping
@Operation(summary = "Query all application category monitoring statistics", description = "Query all application category monitoring statistics")
public ResponseEntity<Message<Dashboard>> appMonitors() {
List<AppCount> appsCount = monitorService.getAllAppMonitorsCount();
Message<Dashboard> message = Message.success(new Dashboard(appsCount));
return ResponseEntity.ok(message);
}
}
@@ -0,0 +1,58 @@
/*
* 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.manager.dao;
import org.apache.hertzbeat.common.entity.manager.AuthToken;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.List;
/**
* AuthToken DAO
*/
public interface AuthTokenDao extends JpaRepository<AuthToken, Long>, JpaSpecificationExecutor<AuthToken> {
/**
* Find all active tokens (status = 0)
*/
List<AuthToken> findByStatus(Byte status);
/**
* Find active tokens created by the given user
*/
List<AuthToken> findByStatusAndCreator(Byte status, String creator);
/**
* Check if an active token exists with the given hash
*/
boolean existsByTokenHashAndStatus(String tokenHash, Byte status);
/**
* Update last used time for a token identified by its hash
*/
@Modifying
@Transactional
@Query("UPDATE AuthToken t SET t.lastUsedTime = :lastUsedTime WHERE t.tokenHash = :tokenHash")
void updateLastUsedTime(@Param("tokenHash") String tokenHash, @Param("lastUsedTime") LocalDateTime lastUsedTime);
}
@@ -0,0 +1,46 @@
/*
* 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.manager.dao;
import java.util.List;
import org.apache.hertzbeat.common.entity.manager.Bulletin;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* BulletinDao
*/
public interface BulletinDao extends JpaRepository<Bulletin, Long>, JpaSpecificationExecutor<Bulletin> {
/**
* Delete Bulletin by name
*/
void deleteByNameIn(List<String> names);
/**
* Get Bulletin by name
*/
Bulletin findByName(String name);
/**
* Count Bulletin by name
*/
int countByName(String name);
}
@@ -0,0 +1,52 @@
/*
* 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.manager.dao;
import java.util.List;
import java.util.Optional;
import org.apache.hertzbeat.common.entity.manager.Collector;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
/**
* Collector repository
*/
public interface CollectorDao extends JpaRepository<Collector, Long>, JpaSpecificationExecutor<Collector> {
/**
* find collector by name
* @param name name
* @return collector
*/
Optional<Collector> findCollectorByName(String name);
/**
* find collectors by names
* @param names collector name list
* @return collector list
*/
List<Collector> findCollectorsByNameIn(List<String> names);
/**
* delete collector by name
* @param collector collector name
*/
@Modifying
void deleteCollectorByName(String collector);
}
@@ -0,0 +1,61 @@
/*
* 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.manager.dao;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import org.apache.hertzbeat.common.entity.manager.CollectorMonitorBind;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
/**
* CollectorMonitorBind repository
*/
public interface CollectorMonitorBindDao extends JpaRepository<CollectorMonitorBind, Long>, JpaSpecificationExecutor<CollectorMonitorBind> {
/**
* find monitors by collector
* @param collector collector
* @return monitor bind
*/
List<CollectorMonitorBind> findCollectorMonitorBindsByCollector(String collector);
/**
* find monitor collector bind by monitor ids
* @param monitorIds monitor ids
* @return binds
*/
List<CollectorMonitorBind> findCollectorMonitorBindsByMonitorIdIn(Set<Long> monitorIds);
/**
* find bind collector by monitor id
* @param monitorId monitor id
* @return collector bind
*/
Optional<CollectorMonitorBind> findCollectorMonitorBindByMonitorId(Long monitorId);
/**
* delete bind by monitor id
* @param monitorId monitor id
*/
@Modifying
void deleteCollectorMonitorBindsByMonitorId(Long monitorId);
}
@@ -0,0 +1,28 @@
/*
* 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.manager.dao;
import org.apache.hertzbeat.common.entity.manager.Define;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* monitor define repository
*/
public interface DefineDao extends JpaRepository<Define, String>, JpaSpecificationExecutor<Define> {
}
@@ -0,0 +1,75 @@
/*
* 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.manager.dao;
import org.apache.hertzbeat.common.entity.manager.MetricsFavorite;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;
import java.util.Optional;
import java.util.Set;
/**
* MetricsFavorite dao
*/
public interface MetricsFavoriteDao extends JpaRepository<MetricsFavorite, Long> {
/**
* Find metrics favorite by creator and monitor id and metrics name
*
* @param creator user id
* @param monitorId monitor id
* @param metricsName metrics name
* @return optional metrics favorite
*/
Optional<MetricsFavorite> findByCreatorAndMonitorIdAndMetricsName(String creator, Long monitorId, String metricsName);
/**
* Find all metrics favorites by user id and monitor id
*
* @param creator user id
* @param monitorId monitor id
* @return list of metrics favorites
*/
List<MetricsFavorite> findByCreatorAndMonitorId(String creator, Long monitorId);
/**
* Delete metrics favorite by user id and monitor id and metrics name
*
* @param creator user id
* @param monitorId monitor id
* @param metricsName metrics name
*/
@Modifying
@Query("DELETE FROM MetricsFavorite mf WHERE mf.creator = :creator AND mf.monitorId = :monitorId AND mf.metricsName = :metricsName")
void deleteByUserIdAndMonitorIdAndMetricsName(@Param("creator") String creator,
@Param("monitorId") Long monitorId,
@Param("metricsName") String metricsName);
/**
* Delete metrics favorites by monitor ids
*
* @param monitorIds monitor ids
*/
@Modifying
@Query("DELETE FROM MetricsFavorite mf WHERE mf.monitorId IN :monitorIds")
void deleteFavoritesByMonitorIdIn(@Param("monitorIds") Set<Long> monitorIds);
}
@@ -0,0 +1,47 @@
/*
* 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.manager.dao;
import java.util.List;
import java.util.Set;
import org.apache.hertzbeat.common.entity.manager.MonitorBind;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.transaction.annotation.Transactional;
/**
* MonitorBind database operation
*/
public interface MonitorBindDao extends JpaRepository<MonitorBind, Long>, JpaSpecificationExecutor<MonitorBind> {
List<MonitorBind> findMonitorBindsByBizId(Long bizId);
List<MonitorBind> findMonitorBindsByBizIdIn(Set<Long> bizIds);
void deleteByMonitorId(Long monitorId);
@Modifying
@Transactional
void deleteMonitorBindByBizIdAndMonitorId(Long bizId, Long monitorId);
@Modifying
void deleteMonitorBindByBizIdIn(Set<Long> bizIds);
}
@@ -0,0 +1,85 @@
/*
* 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.manager.dao;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import org.apache.hertzbeat.common.entity.manager.Monitor;
import org.apache.hertzbeat.manager.pojo.dto.AppCount;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
/**
* AuthResources database operation
*/
public interface MonitorDao extends JpaRepository<Monitor, Long>, JpaSpecificationExecutor<Monitor> {
/**
* Delete monitor based on monitor ID list
* @param monitorIds Monitoring ID List
*/
void deleteAllByIdIn(Set<Long> monitorIds);
/**
* Query monitoring based on monitoring ID list
* @param monitorIds Monitoring ID List
* @return Monitor List
*/
List<Monitor> findMonitorsByIdIn(Set<Long> monitorIds);
/**
* Query monitoring by monitoring type
* @param app Monitor Type
* @return Monitor List
*/
List<Monitor> findMonitorsByAppEquals(String app);
/**
* Querying Monitoring of Sent Collection Tasks
* @param status Monitor Status
* @return Monitor List
*/
List<Monitor> findMonitorsByStatusNotInAndJobIdNotNull(List<Byte> status);
/**
* Query monitoring by monitoring name
* @param name monitoring name
* @return monitoring list
*/
Optional<Monitor> findMonitorByNameEquals(String name);
/**
* Query the monitoring category - the number of monitoring corresponding to the status
* @return Monitoring Category-Status and Monitoring Quantity Mapping
*/
@Query("select new org.apache.hertzbeat.manager.pojo.dto.AppCount(mo.app, mo.status, COUNT(mo.id)) from Monitor mo group by mo.app, mo.status")
List<AppCount> findAppsStatusCount();
/**
* Update the status of the specified monitor
* @param id Monitor ID
* @param status Monitor Status
*/
@Modifying(clearAutomatically = true)
@Query("update Monitor set status = :status where id = :id")
void updateMonitorStatus(@Param(value = "id") Long id, @Param(value = "status") byte status);
}
@@ -0,0 +1,48 @@
/*
* 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.manager.dao;
import java.util.List;
import java.util.Set;
import org.apache.hertzbeat.common.entity.manager.Param;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* ParamDao database operations
*/
public interface ParamDao extends JpaRepository<Param, Long> {
/**
* Query the list of parameters associated with the monitoring ID'
* @param monitorId Monitor ID
* @return list of parameter values
*/
List<Param> findParamsByMonitorId(Long monitorId);
/**
* Remove the parameter list associated with the monitoring ID based on it
* @param monitorId Monitor Id
*/
void deleteParamsByMonitorId(long monitorId);
/**
* Remove the parameter list associated with the monitoring ID list based on it
* @param monitorIds Monitoring ID List
*/
void deleteParamsByMonitorIdIn(Set<Long> monitorIds);
}
@@ -0,0 +1,35 @@
/*
* 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.manager.dao;
import java.util.List;
import org.apache.hertzbeat.common.entity.manager.ParamDefine;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* Param Define Database Operations
*/
public interface ParamDefineDao extends JpaRepository<ParamDefine, Long> {
/**
* Query the parameter definitions under it according to the monitoring type
* @param app Monitoring type
* @return parameter definition list
*/
List<ParamDefine> findParamDefinesByApp(String app);
}
@@ -0,0 +1,31 @@
/*
* 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.manager.dao;
import java.util.List;
import org.apache.hertzbeat.common.entity.manager.PluginItem;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* plugin metadata repository
*/
public interface PluginItemDao extends JpaRepository<PluginItem, Long>, JpaSpecificationExecutor<PluginItem> {
int countPluginItemByClassIdentifierIn(List<String> classIdentifiers);
}
@@ -0,0 +1,44 @@
/*
* 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.manager.dao;
import java.util.List;
import org.apache.hertzbeat.common.entity.manager.PluginMetadata;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* plugin metadata repository
*/
public interface PluginMetadataDao extends JpaRepository<PluginMetadata, Long>, JpaSpecificationExecutor<PluginMetadata> {
/**
* count by name
*
* @param name name
* @return count
*/
int countPluginMetadataByName(String name);
/**
* find enabled plugins
* @return plugins
*/
List<PluginMetadata> findPluginMetadataByEnableStatusTrue();
}
@@ -0,0 +1,48 @@
/*
* 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.manager.dao;
import java.util.List;
import java.util.Set;
import org.apache.hertzbeat.manager.pojo.dto.PluginParam;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* PluginParamDao database operations
*/
public interface PluginParamDao extends JpaRepository<PluginParam, Long> {
/**
* Query the list of parameters associated with the monitoring ID'
* @param pluginMetadataId Monitor ID
* @return list of parameter values
*/
List<PluginParam> findParamsByPluginMetadataId(Long pluginMetadataId);
/**
* Remove the parameter list associated with the pluginMetadata ID based on it
* @param pluginMetadataId Monitor Id
*/
void deletePluginParamsByPluginMetadataId(long pluginMetadataId);
/**
* Remove the parameter list associated with the pluginMetadata ID list based on it
* @param pluginMetadataIds Monitoring ID List
*/
void deletePluginParamsByPluginMetadataIdIn(Set<Long> pluginMetadataIds);
}
@@ -0,0 +1,36 @@
/*
* 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.manager.dao;
import java.util.List;
import org.apache.hertzbeat.common.entity.manager.StatusPageComponent;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* StatusPageComponent DAO interface.
*/
public interface StatusPageComponentDao extends JpaRepository<StatusPageComponent, Long>, JpaSpecificationExecutor<StatusPageComponent> {
/**
* find by org id.
* @param orgId org id
* @return StatusPageComponent list
*/
List<StatusPageComponent> findByOrgId(long orgId);
}
@@ -0,0 +1,46 @@
/*
* 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.manager.dao;
import java.util.List;
import org.apache.hertzbeat.common.entity.manager.StatusPageHistory;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* StatusPageOrg DAO interface.
*/
public interface StatusPageHistoryDao extends JpaRepository<StatusPageHistory, Long>, JpaSpecificationExecutor<StatusPageHistory> {
/**
* find status page history by timestamp between start and end.
* @param start start timestamp
* @param end end timestamp
* @return status page history list
*/
List<StatusPageHistory> findStatusPageHistoriesByTimestampBetween(long start, long end);
/**
* find status page history by component id and timestamp between start and end.
* @param componentId component id
* @param start start timestamp
* @param end end timestamp
* @return status page history list
*/
List<StatusPageHistory> findStatusPageHistoriesByComponentIdAndTimestampBetween(long componentId, long start, long end);
}
@@ -0,0 +1,35 @@
/*
* 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.manager.dao;
import org.apache.hertzbeat.common.entity.manager.StatusPageIncidentComponentBind;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* StatusPageComponent DAO interface.
*/
public interface StatusPageIncidentComponentBindDao extends JpaRepository<StatusPageIncidentComponentBind, Long>, JpaSpecificationExecutor<StatusPageIncidentComponentBind> {
/**
* count by component id
* @param componentId component id
* @return count
*/
long countByComponentId(long componentId);
}
@@ -0,0 +1,29 @@
/*
* 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.manager.dao;
import org.apache.hertzbeat.common.entity.manager.StatusPageIncident;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* StatusPageIncident DAO interface.
*/
public interface StatusPageIncidentDao extends JpaRepository<StatusPageIncident, Long>, JpaSpecificationExecutor<StatusPageIncident> {
}
@@ -0,0 +1,29 @@
/*
* 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.manager.dao;
import org.apache.hertzbeat.common.entity.manager.StatusPageOrg;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* StatusPageOrg DAO interface.
*/
public interface StatusPageOrgDao extends JpaRepository<StatusPageOrg, Long>, JpaSpecificationExecutor<StatusPageOrg> {
}
@@ -0,0 +1,70 @@
/*
* 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.manager.nativex;
import java.lang.reflect.Constructor;
import java.util.Set;
import org.apache.sshd.common.channel.ChannelListener;
import org.apache.sshd.common.forward.PortForwardingEventListener;
import org.apache.sshd.common.io.nio2.Nio2ServiceFactory;
import org.apache.sshd.common.io.nio2.Nio2ServiceFactoryFactory;
import org.apache.sshd.common.session.SessionListener;
import org.apache.sshd.common.util.security.bouncycastle.BouncyCastleSecurityProviderRegistrar;
import org.apache.sshd.common.util.security.eddsa.EdDSASecurityProviderRegistrar;
import org.springframework.aot.hint.ExecutableMode;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.aot.hint.TypeReference;
import org.springframework.lang.NonNull;
import org.springframework.util.ClassUtils;
/**
* Derived from SpringCloud org.springframework.cloud.config.server.config.ConfigServerRuntimeHints
* @see <a href="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">ConfigServerRuntimeHints</a>
*/
public class HertzbeatRuntimeHintsRegistrar implements RuntimeHintsRegistrar {
private static final String SshConstantsClassName = "org.apache.sshd.common.SshConstants";
@Override
public void registerHints(@NonNull RuntimeHints hints, ClassLoader classLoader) {
// 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)) {
hints.reflection().registerTypes(Set.of(TypeReference.of(BouncyCastleSecurityProviderRegistrar.class),
TypeReference.of(EdDSASecurityProviderRegistrar.class), TypeReference.of(Nio2ServiceFactory.class),
TypeReference.of(Nio2ServiceFactoryFactory.class)),
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS));
hints.reflection().registerTypes(Set.of(TypeReference.of(PortForwardingEventListener.class)),
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.DECLARED_FIELDS));
hints.proxies().registerJdkProxy(TypeReference.of(ChannelListener.class),
TypeReference.of(PortForwardingEventListener.class), TypeReference.of(SessionListener.class));
}
}
private void registerConstructor(RuntimeHints hints, Class<?> clazz) {
Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
hints.reflection().registerConstructor(declaredConstructor, ExecutableMode.INVOKE);
}
}
}
@@ -0,0 +1,32 @@
/*
* 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.manager.pojo.dto;
import lombok.Data;
/**
* AiControllerRequestParam
*/
@Data
public class AiControllerRequestParam {
/**
* required parameter
*/
String text;
}
@@ -0,0 +1,41 @@
/*
* 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.manager.pojo.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* ai message
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class AiMessage {
/**
* role
*/
private String role;
/**
* content
*/
private String content;
}
@@ -0,0 +1,120 @@
/*
* 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.manager.pojo.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* Alibaba Ai Request param
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class AliAiRequestParamDTO {
/**
* ai version
*/
private String model;
/**
* Enter information about the model
*/
private Input input;
/**
* Parameters used to control model generation
*/
private Parameters parameters;
/**
* Input
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public static class Input {
/**
* request message
*/
private List<AiMessage> messages;
}
/**
* Parameters
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public static class Parameters {
/**
* The model outputs the maximum tokens, with a maximum output of 8192 and a default value of 1024
*/
@JsonProperty("max_tokens")
private Integer maxTokens;
/**
* Used to control the degree of randomness and variety. Specifically, the temperature value controls the
* degree to which the probability distribution for each candidate word is smoothed when text is generated.
* A higher temperature will reduce the peak value of the probability distribution, so that more low-probability
* words will be selected and the results will be more diversified. A lower temperature will increase the peak of the probability distribution,
* making it easier for high-probability words to be selected and producing more certain results.
*/
private float temperature;
/**
* The Internet search service is built into the model, and this parameter controls whether the model refers
* to the Internet search results when generating text. The value can be:
* true: If Internet search is enabled, the model uses the search results as reference information in the text
* generation process, but the model "decides" whether to use the Internet search results based on its internal logic.
* false: Turn off Internet search.
*/
@JsonProperty("enable_search")
private boolean enableSearch;
/**
* Set return format,default message
*/
@JsonProperty("result_format")
private String resultFormat;
/**
* Control whether incremental output is enabled in stream output mode, that is, whether the subsequent output content contains
* the output content. If the value is set to True, the incremental output mode will be enabled, and the subsequent output will
* not contain the output content, you need to splice the overall output by yourself. Set to False to contain the output.
*/
@JsonProperty("incremental_output")
private boolean incrementalOutput;
}
}
@@ -0,0 +1,112 @@
/*
* 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.manager.pojo.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* AliAiResponse
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class AliAiResponse {
/**
* response
*/
private AliAiOutput output;
/**
* Returns the number of tokens invoked by the model at the end.
*/
private Tokens usage;
/**
* AliAiOutput
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class AliAiOutput {
/**
* response message
*/
private List<Choice> choices;
}
/**
* Choice
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class Choice {
/**
* Stop cause:
* null: being generated
* stop: stop token causes the end
* length: indicates that the generation length ends
*/
@JsonProperty("finish_reason")
private String finishReason;
/**
* response message
*/
private AiMessage message;
}
/**
* Tokens
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Tokens {
/**
* The number of tokens of the model output content
*/
@JsonProperty("output_tokens")
private Integer outputTokens;
/**
* The number of tokens entered this request.
* When enable_search is set to true, the number of tokens entered is greater than the number of
* tokens you entered the request because you need to add search related content.
*/
@JsonProperty("input_tokens")
private Integer inputTokens;
/**
* usage.output_tokens and usage.input_tokens sum
*/
@JsonProperty("total_tokens")
private Integer totalTokens;
}
}
@@ -0,0 +1,72 @@
/*
* 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.manager.pojo.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* AppCount class
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
public class AppCount {
public AppCount(String app, byte status, Long size) {
this.app = app;
this.status = status;
this.size = size;
}
/**
* monitor category
*/
private String category;
/**
* monitor type
*/
private String app;
/**
* task status
*/
private transient byte status;
/**
* monitor count
*/
private long size;
/**
* number of available tasks
*/
private long availableSize;
/**
* number of tasks with unmonitored status
*/
private long unManageSize;
/**
* number of tasks with unavailable status
*/
private long unAvailableSize;
}
@@ -0,0 +1,135 @@
/*
* 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.manager.pojo.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* Bulletin Metrics Data
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Schema(description = "Bulletin Metrics Data")
public class BulletinMetricsData {
/**
* Bulletin Name
*/
@Schema(title = "Bulletin Name")
private String name;
/**
* Content Data
*/
@Schema(description = "Content Data")
private List<Data> content;
/**
* Bulletin Metrics Data
*/
@lombok.Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class Data {
/**
* Monitor Name
*/
@Schema(title = "Monitor name")
private String monitorName;
/**
* Monitor ID
*/
@Schema(title = "Monitor ID")
private Long monitorId;
/**
* Monitor IP
*/
@Schema(title = "Monitor IP")
private String host;
/**
* Monitor Metrics
*/
@Schema(title = "Monitor Metrics")
private List<Metric> metrics;
}
/**
* Metrics Data
*/
@lombok.Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Schema(description = "Metrics Data")
public static class Metric{
/**
* Metric type
*/
@Schema(title = "Metric type")
private String name;
/**
* Metric fields
*/
@Schema(title = "Metric fields")
private List<List<Field>> fields;
}
/**
* Metrics field
*/
@lombok.Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Schema(description = "Metrics field")
public static class Field{
/**
* Field name
*/
@Schema(title = "Field name")
private String key;
/**
* Field unit
*/
@Schema(title = "Field unit")
private String unit;
/**
* Field value
*/
@Schema(title = "Field value")
private String value;
}
}
@@ -0,0 +1,82 @@
/*
* 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.manager.pojo.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import java.time.LocalDateTime;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.hertzbeat.common.entity.manager.Collector;
/**
* Collector info view.
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Schema(description = "collector info")
public class CollectorInfo {
@Schema(title = "primary id", example = "2")
private Long id;
@Schema(title = "collector identity name", description = "collector identity name")
private String name;
@Schema(title = "collector ip", description = "collector remote ip")
private String ip;
@Schema(title = "collector version", description = "collector version")
private String version;
@Schema(title = "collector status: 0-online 1-offline")
private byte status;
@Schema(title = "collector mode: public or private")
private String mode;
@Schema(title = "The creator of this record", example = "tom")
private String creator;
@Schema(title = "This record was last modified by")
private String modifier;
@Schema(title = "This record creation time (millisecond timestamp)")
private LocalDateTime gmtCreate;
@Schema(title = "Record the latest modification time (timestamp in milliseconds)")
private LocalDateTime gmtUpdate;
public static CollectorInfo fromEntity(Collector collector) {
return CollectorInfo.builder()
.id(collector.getId())
.name(collector.getName())
.ip(collector.getIp())
.version(collector.getVersion())
.status(collector.getStatus())
.mode(collector.getMode())
.creator(collector.getCreator())
.modifier(collector.getModifier())
.gmtCreate(collector.getGmtCreate())
.gmtUpdate(collector.getGmtUpdate())
.build();
}
}
@@ -0,0 +1,44 @@
/*
* 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.manager.pojo.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* Collector summary view.
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Schema(description = "collector summary")
public class CollectorSummary {
@Schema(description = "the collector info")
private CollectorInfo collector;
@Schema(description = "the number of monitors pinned in this collector")
private int pinMonitorNum;
@Schema(description = "the number of monitors dispatched in this collector")
private int dispatchMonitorNum;
}
@@ -0,0 +1,83 @@
/*
* 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.manager.pojo.dto;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;
import org.apache.hertzbeat.common.entity.manager.StatusPageComponent;
import org.apache.hertzbeat.common.entity.manager.StatusPageHistory;
import java.util.Objects;
/**
* status page's component status dto
*/
@Schema(description = "Status Page's Component Status")
public class ComponentStatus {
private StatusPageComponentInfo componentInfo;
private List<StatusPageHistoryInfo> historyItems;
@Schema(description = "Component Info")
@JsonProperty("info")
public StatusPageComponentInfo getComponentInfo() {
return componentInfo;
}
@JsonProperty("info")
public void setComponentInfo(StatusPageComponentInfo componentInfo) {
this.componentInfo = componentInfo;
}
@Schema(description = "Component History")
@JsonProperty("history")
public List<StatusPageHistoryInfo> getHistoryItems() {
return historyItems;
}
@JsonProperty("history")
public void setHistoryItems(List<StatusPageHistoryInfo> historyItems) {
this.historyItems = historyItems;
}
@JsonIgnore
public StatusPageComponent getInfo() {
return componentInfo == null ? null : componentInfo.toEntity();
}
public void setInfo(StatusPageComponent info) {
this.componentInfo = StatusPageComponentInfo.fromEntity(info);
}
@JsonIgnore
public List<StatusPageHistory> getHistory() {
return historyItems == null ? null : historyItems.stream()
.filter(Objects::nonNull)
.map(StatusPageHistoryInfo::toEntity)
.toList();
}
public void setHistory(List<StatusPageHistory> history) {
this.historyItems = history == null ? null : history.stream()
.filter(Objects::nonNull)
.map(StatusPageHistoryInfo::fromEntity)
.toList();
}
}
@@ -0,0 +1,37 @@
/*
* 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.manager.pojo.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* Large screen dashboard statistics
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Schema(description = "Dashboard App Count Info")
public class Dashboard {
List<AppCount> apps;
}
@@ -0,0 +1,36 @@
/*
* 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.manager.pojo.dto;
import java.io.InputStream;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* File storage
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class FileDTO {
private String name;
private InputStream inputStream;
}
@@ -0,0 +1,85 @@
/*
* 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.manager.pojo.dto;
import static io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_WRITE;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* Hierarchical structure
* eg: Monitoring Type metrics Information Hierarchy Relationship
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
@Schema(description = "Monitor Hierarchy")
public class Hierarchy {
/**
* Category value
*/
@Schema(description = "Category Value", example = "os", accessMode = READ_WRITE)
String category;
/**
* Attribute value
*/
@Schema(description = "Attribute value", example = "linux", accessMode = READ_WRITE)
String value;
/**
* Attribute internationalization tag
*/
@Schema(description = "Attribute internationalization tag", example = "Linux system", accessMode = READ_WRITE)
String label;
/**
* Is it a leaf node
*/
@Schema(description = "Is it a leaf node", example = "true", accessMode = READ_WRITE)
Boolean isLeaf = false;
/**
* Is hide this app type in main menus layout
*/
@Schema(description = "Is hide this app in main menus layout, only for app type, default true.", example = "true")
Boolean hide = true;
/**
* For leaf metric
* metric type 0-number: number 1-string: string
*/
@Schema(description = "metric type 0-number: number 1-string: string")
private Byte type;
/**
* metric unit
*/
@Schema(description = "metric unit")
private String unit;
/**
* Next level of association
*/
@Schema(description = "Next Hierarchy", accessMode = READ_WRITE)
private List<Hierarchy> children;
}
@@ -0,0 +1,63 @@
/*
* 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.manager.pojo.dto;
import static io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_ONLY;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* Login registered account information transfer body username phone email
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Schema(description = "Account information transfer body")
public class LoginDto {
/**
* type
* 1. Account (email username and mobile phone number) password login 2. github login 3. WeChat login
*/
@Schema(description = "type", example = "1", accessMode = READ_ONLY)
@Max(value = 4, message = "1. Account (email username and mobile phone number) password login 2. github login 3. WeChat login")
private Byte type;
/**
* User ID
*/
@Schema(description = "user identification", example = "1", accessMode = READ_ONLY)
@NotBlank(message = "Identifier can not null")
private String identifier;
/**
* key
*/
@Schema(description = "Secret key", example = "1", accessMode = READ_ONLY)
@NotBlank(message = "Credential can not null")
@Size(max = 512, message = "credential max length 512")
private String credential;
}
@@ -0,0 +1,41 @@
/*
* 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.manager.pojo.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* Metrics Information with favorite status
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Schema(description = "Metrics information with favorite status")
public class MetricsInfo {
@Schema(description = "Metrics name", example = "cpu")
private String name;
@Schema(description = "Whether the metrics is favorited by current user")
private Boolean favorited;
}
@@ -0,0 +1,42 @@
/*
* 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.manager.pojo.dto;
import static io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_ONLY;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* monitor define
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Schema(description = "Monitor Define transfer body")
public class MonitorDefineDto {
@Schema(description = "Define content", example = "1", accessMode = READ_ONLY)
@NotBlank(message = "define can not null")
private String define;
}
@@ -0,0 +1,126 @@
/*
* 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.manager.pojo.dto;
import static io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_ONLY;
import static io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_WRITE;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import java.util.List;
import org.apache.hertzbeat.common.entity.grafana.GrafanaDashboard;
import org.apache.hertzbeat.common.entity.manager.Monitor;
import org.apache.hertzbeat.common.entity.manager.Param;
import java.util.Objects;
/**
* Monitoring Information External Interaction Entities
*/
@Schema(description = "Monitoring information entities")
public class MonitorDto {
@NotNull
@Valid
private MonitorInfo monitorInfo;
@NotEmpty
@Valid
private List<MonitorParam> paramInfos;
private List<MetricsInfo> metrics;
private String collector;
private GrafanaDashboard grafanaDashboard;
@Schema(description = "monitor content", accessMode = READ_WRITE)
@JsonProperty("monitor")
public MonitorInfo getMonitorInfo() {
return monitorInfo;
}
@JsonProperty("monitor")
public void setMonitorInfo(MonitorInfo monitorInfo) {
this.monitorInfo = monitorInfo;
}
@Schema(description = "monitor params", accessMode = READ_WRITE)
@JsonProperty("params")
public List<MonitorParam> getParamInfos() {
return paramInfos;
}
@JsonProperty("params")
public void setParamInfos(List<MonitorParam> paramInfos) {
this.paramInfos = paramInfos;
}
@JsonIgnore
public Monitor getMonitor() {
return monitorInfo == null ? null : monitorInfo.toEntity();
}
public void setMonitor(Monitor monitor) {
this.monitorInfo = MonitorInfo.fromEntity(monitor);
}
@JsonIgnore
public List<Param> getParams() {
return paramInfos == null ? null : paramInfos.stream()
.filter(Objects::nonNull)
.map(MonitorParam::toEntity)
.toList();
}
public void setParams(List<Param> params) {
this.paramInfos = params == null ? null : params.stream()
.filter(Objects::nonNull)
.map(MonitorParam::fromEntity)
.toList();
}
@Schema(description = "Monitor Metrics", accessMode = READ_ONLY)
public List<MetricsInfo> getMetrics() {
return metrics;
}
public void setMetrics(List<MetricsInfo> metrics) {
this.metrics = metrics;
}
@Schema(description = "pinned collector, default null if system dispatch", accessMode = READ_WRITE)
public String getCollector() {
return collector;
}
public void setCollector(String collector) {
this.collector = collector;
}
@Schema(description = "grafana dashboard")
public GrafanaDashboard getGrafanaDashboard() {
return grafanaDashboard;
}
public void setGrafanaDashboard(GrafanaDashboard grafanaDashboard) {
this.grafanaDashboard = grafanaDashboard;
}
}
@@ -0,0 +1,134 @@
/*
* 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.manager.pojo.dto;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.Size;
import java.time.LocalDateTime;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.hertzbeat.common.entity.manager.Monitor;
import org.apache.hertzbeat.common.support.valid.HostValid;
/**
* Manager-side monitor DTO detached from JPA annotations.
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class MonitorInfo {
private Long id;
private Long jobId;
@Size(max = 100)
private String name;
@Size(max = 100)
private String app;
@Size(max = 100)
private String scrape;
@Size(max = 100)
@HostValid
private String instance;
@Min(10)
private Integer intervals;
@Size(max = 20)
private String scheduleType;
@Size(max = 100)
private String cronExpression;
@Min(0)
@Max(4)
private byte status;
private byte type;
private Map<String, String> labels;
private Map<String, String> annotations;
@Size(max = 255)
private String description;
private String creator;
private String modifier;
private LocalDateTime gmtCreate;
private LocalDateTime gmtUpdate;
public static MonitorInfo fromEntity(Monitor monitor) {
if (monitor == null) {
return null;
}
MonitorInfo info = new MonitorInfo();
info.setId(monitor.getId());
info.setJobId(monitor.getJobId());
info.setName(monitor.getName());
info.setApp(monitor.getApp());
info.setScrape(monitor.getScrape());
info.setInstance(monitor.getInstance());
info.setIntervals(monitor.getIntervals());
info.setScheduleType(monitor.getScheduleType());
info.setCronExpression(monitor.getCronExpression());
info.setStatus(monitor.getStatus());
info.setType(monitor.getType());
info.setLabels(monitor.getLabels());
info.setAnnotations(monitor.getAnnotations());
info.setDescription(monitor.getDescription());
info.setCreator(monitor.getCreator());
info.setModifier(monitor.getModifier());
info.setGmtCreate(monitor.getGmtCreate());
info.setGmtUpdate(monitor.getGmtUpdate());
return info;
}
public Monitor toEntity() {
Monitor monitor = new Monitor();
monitor.setId(id);
monitor.setJobId(jobId);
monitor.setName(name);
monitor.setApp(app);
monitor.setScrape(scrape);
monitor.setInstance(instance);
monitor.setIntervals(intervals);
monitor.setScheduleType(scheduleType);
monitor.setCronExpression(cronExpression);
monitor.setStatus(status);
monitor.setType(type);
monitor.setLabels(labels);
monitor.setAnnotations(annotations);
monitor.setDescription(description);
monitor.setCreator(creator);
monitor.setModifier(modifier);
monitor.setGmtCreate(gmtCreate);
monitor.setGmtUpdate(gmtUpdate);
return monitor;
}
}
@@ -0,0 +1,81 @@
/*
* 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.manager.pojo.dto;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import java.time.LocalDateTime;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.hertzbeat.common.entity.manager.Param;
/**
* Manager-side monitor param DTO detached from JPA annotations.
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class MonitorParam {
private Long id;
private Long monitorId;
@Size(max = 100)
@NotBlank(message = "field can not null")
private String field;
@Size(max = 8126)
private String paramValue;
@Min(0)
private byte type;
private LocalDateTime gmtCreate;
private LocalDateTime gmtUpdate;
public static MonitorParam fromEntity(Param param) {
if (param == null) {
return null;
}
MonitorParam monitorParam = new MonitorParam();
monitorParam.setId(param.getId());
monitorParam.setMonitorId(param.getMonitorId());
monitorParam.setField(param.getField());
monitorParam.setParamValue(param.getParamValue());
monitorParam.setType(param.getType());
monitorParam.setGmtCreate(param.getGmtCreate());
monitorParam.setGmtUpdate(param.getGmtUpdate());
return monitorParam;
}
public Param toEntity() {
Param param = new Param();
param.setId(id);
param.setMonitorId(monitorId);
param.setField(field);
param.setParamValue(paramValue);
param.setType(type);
param.setGmtCreate(gmtCreate);
param.setGmtUpdate(gmtUpdate);
return param;
}
}
@@ -0,0 +1,39 @@
/*
* 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.manager.pojo.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* Mute Configuration
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class MuteConfig {
/**
* mute
*/
private boolean mute;
}
@@ -0,0 +1,35 @@
/*
* 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.manager.pojo.dto;
import java.util.UUID;
import lombok.Getter;
import org.springframework.context.ApplicationEvent;
/**
* Object store configuration change event.
*/
@Getter
public class ObjectStoreConfigChangeEvent extends ApplicationEvent {
private final ObjectStoreDTO<?> config;
public ObjectStoreConfigChangeEvent(ObjectStoreDTO<?> config) {
super(UUID.randomUUID());
this.config = config;
}
}
@@ -0,0 +1,81 @@
/*
* 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.manager.pojo.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* file storage container
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ObjectStoreDTO<T> {
/**
* file storage service type
*/
private Type type;
/**
* Configuration item
*/
private T config;
/**
* file storage service type
*/
public enum Type {
/**
* local file
*/
FILE,
/**
* local database
*/
DATABASE,
/**
* <a href="https://support.huaweicloud.com/obs/index.html">Huawei Cloud OBS</a>
*/
OBS
}
/**
* file storage configuration
*/
@Data
public static class ObsConfig {
private String accessKey;
private String secretKey;
private String bucketName;
private String endpoint;
/**
* Save path
*/
private String savePath = "hertzbeat";
}
}
@@ -0,0 +1,36 @@
/*
* 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.manager.pojo.dto;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* Parameters define transfer entities
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ParamDefineDto {
private String app;
private List<ParamDefineInfo> param;
}
@@ -0,0 +1,144 @@
/*
* 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.manager.pojo.dto;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.hertzbeat.common.entity.job.RuntimeParamDefine;
import org.apache.hertzbeat.common.entity.manager.ParamDefine;
/**
* Manager-side parameter definition DTO detached from JPA annotations.
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ParamDefineInfo {
private Long id;
private String app;
private Map<String, String> name;
private String field;
private String type;
private boolean required;
private String defaultValue;
private String placeholder;
private String range;
private Short limit;
private List<OptionInfo> options;
private String keyAlias;
private String valueAlias;
private boolean hide;
private String creator;
private String modifier;
private LocalDateTime gmtCreate;
private LocalDateTime gmtUpdate;
private Map<String, List<Object>> depend;
public static ParamDefineInfo fromEntity(ParamDefine paramDefine) {
if (paramDefine == null) {
return null;
}
ParamDefineInfo info = new ParamDefineInfo();
info.setId(paramDefine.getId());
info.setApp(paramDefine.getApp());
info.setName(paramDefine.getName());
info.setField(paramDefine.getField());
info.setType(paramDefine.getType());
info.setRequired(paramDefine.isRequired());
info.setDefaultValue(paramDefine.getDefaultValue());
info.setPlaceholder(paramDefine.getPlaceholder());
info.setRange(paramDefine.getRange());
info.setLimit(paramDefine.getLimit());
info.setOptions(paramDefine.getOptions() == null ? null
: paramDefine.getOptions().stream().map(OptionInfo::fromEntity).toList());
info.setKeyAlias(paramDefine.getKeyAlias());
info.setValueAlias(paramDefine.getValueAlias());
info.setHide(paramDefine.isHide());
info.setCreator(paramDefine.getCreator());
info.setModifier(paramDefine.getModifier());
info.setGmtCreate(paramDefine.getGmtCreate());
info.setGmtUpdate(paramDefine.getGmtUpdate());
info.setDepend(paramDefine.getDepend());
return info;
}
public static ParamDefineInfo fromRuntime(RuntimeParamDefine runtimeParamDefine) {
if (runtimeParamDefine == null) {
return null;
}
ParamDefineInfo info = new ParamDefineInfo();
info.setApp(runtimeParamDefine.getApp());
info.setName(runtimeParamDefine.getName());
info.setField(runtimeParamDefine.getField());
info.setType(runtimeParamDefine.getType());
info.setRequired(runtimeParamDefine.isRequired());
info.setDefaultValue(runtimeParamDefine.getDefaultValue());
info.setPlaceholder(runtimeParamDefine.getPlaceholder());
info.setRange(runtimeParamDefine.getRange());
info.setLimit(runtimeParamDefine.getLimit());
info.setOptions(runtimeParamDefine.getOptions() == null ? null
: runtimeParamDefine.getOptions().stream().map(OptionInfo::fromRuntime).toList());
info.setKeyAlias(runtimeParamDefine.getKeyAlias());
info.setValueAlias(runtimeParamDefine.getValueAlias());
info.setHide(runtimeParamDefine.isHide());
info.setDepend(runtimeParamDefine.getDepend());
return info;
}
/**
* DTO version of parameter options.
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class OptionInfo {
private String label;
private String value;
public static OptionInfo fromEntity(ParamDefine.Option option) {
return option == null ? null : new OptionInfo(option.getLabel(), option.getValue());
}
public static OptionInfo fromRuntime(RuntimeParamDefine.Option option) {
return option == null ? null : new OptionInfo(option.getLabel(), option.getValue());
}
}
}
@@ -0,0 +1,115 @@
/*
* 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.manager.pojo.dto;
import static io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_ONLY;
import static io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_WRITE;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Index;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import java.time.LocalDateTime;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
/**
* PluginParam
*/
@Entity
@Table(
name = "hzb_plugin_param",
indexes = {@Index(name = "idx_hzb_plugin_param_plugin_metadata_id", columnList = "plugin_metadata_id")},
uniqueConstraints = @UniqueConstraint(name = "uk_hzb_plugin_param_metadata_field", columnNames = {"plugin_metadata_id", "field"})
)
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Schema(description = "Parameter Entity")
@EntityListeners(AuditingEntityListener.class)
public class PluginParam {
/**
* Parameter primary key index ID
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Schema(title = "Parameter primary key index ID", example = "87584674384", accessMode = READ_ONLY)
private Long id;
/**
* Monitor ID
*/
@NotNull
@Column(name = "plugin_metadata_id")
@Schema(title = "Plugin task ID", example = "875846754543", accessMode = READ_WRITE)
private Long pluginMetadataId;
/**
* Parameter Field Identifier
*/
@Schema(title = "Parameter identifier field", example = "port", accessMode = READ_WRITE)
@Size(max = 100)
@NotNull
@Column(name = "field")
private String field;
/**
* Param Value
*/
@Schema(title = "parameter values", example = "8080", accessMode = READ_WRITE)
@Size(max = 8126)
@Column(length = 8126)
private String paramValue;
/**
* Parameter type 0: number 1: string 2: encrypted string 3: json string mapped by map
*/
@Schema(title = "Parameter types 0: number 1: string 2: encrypted string 3:map mapped json string 4:arrays string",
accessMode = READ_WRITE)
@Min(0)
private byte type;
/**
* Record create time
*/
@Schema(title = "Record create time", example = "1612198922000", accessMode = READ_ONLY)
@CreatedDate
private LocalDateTime gmtCreate;
/**
* Record the latest modification time
*/
@Schema(title = "Record modify time", example = "1612198444000", accessMode = READ_ONLY)
@LastModifiedDate
private LocalDateTime gmtUpdate;
}
@@ -0,0 +1,42 @@
/*
* 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.manager.pojo.dto;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* Popup rendering and parameter values
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PluginParametersVO {
/**
* Stencil rendering
*/
private List<ParamDefineInfo> paramDefines;
/**
* specific parameter
*/
private List<PluginParam> pluginParams;
}
@@ -0,0 +1,42 @@
/*
* 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.manager.pojo.dto;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.web.multipart.MultipartFile;
/**
* Manager-side plugin upload request.
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PluginUpload {
@NotNull
private MultipartFile jarFile;
@NotNull(message = "Plugin name is required")
private String name;
@NotNull(message = "Enable status is required")
private Boolean enableStatus;
}
@@ -0,0 +1,40 @@
/*
* 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.manager.pojo.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* Refresh Token Response
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(description = "flash token response")
public class RefreshTokenResponse {
@Schema(title = "Access Token")
private String token;
@Schema(title = "Refresh Token")
private String refreshToken;
}
@@ -0,0 +1,95 @@
/*
* 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.manager.pojo.dto;
import java.time.LocalDateTime;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.hertzbeat.common.entity.manager.StatusPageComponent;
/**
* Public status-page component DTO.
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class StatusPageComponentInfo {
private Long id;
private Long orgId;
private String name;
private String description;
private Map<String, String> labels;
private byte method;
private byte configState;
private byte state;
private String creator;
private String modifier;
private LocalDateTime gmtCreate;
private LocalDateTime gmtUpdate;
public static StatusPageComponentInfo fromEntity(StatusPageComponent component) {
if (component == null) {
return null;
}
StatusPageComponentInfo info = new StatusPageComponentInfo();
info.setId(component.getId());
info.setOrgId(component.getOrgId());
info.setName(component.getName());
info.setDescription(component.getDescription());
info.setLabels(component.getLabels());
info.setMethod(component.getMethod());
info.setConfigState(component.getConfigState());
info.setState(component.getState());
info.setCreator(component.getCreator());
info.setModifier(component.getModifier());
info.setGmtCreate(component.getGmtCreate());
info.setGmtUpdate(component.getGmtUpdate());
return info;
}
public StatusPageComponent toEntity() {
StatusPageComponent component = new StatusPageComponent();
component.setId(id);
component.setOrgId(orgId);
component.setName(name);
component.setDescription(description);
component.setLabels(labels);
component.setMethod(method);
component.setConfigState(configState);
component.setState(state);
component.setCreator(creator);
component.setModifier(modifier);
component.setGmtCreate(gmtCreate);
component.setGmtUpdate(gmtUpdate);
return component;
}
}
@@ -0,0 +1,94 @@
/*
* 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.manager.pojo.dto;
import java.time.LocalDateTime;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.hertzbeat.common.entity.manager.StatusPageHistory;
/**
* Public status-page history DTO.
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class StatusPageHistoryInfo {
private Long id;
private Long componentId;
private byte state;
private Long timestamp;
private Double uptime;
private Integer abnormal;
private Integer unknowing;
private Integer normal;
private String creator;
private String modifier;
private LocalDateTime gmtCreate;
private LocalDateTime gmtUpdate;
public static StatusPageHistoryInfo fromEntity(StatusPageHistory history) {
if (history == null) {
return null;
}
StatusPageHistoryInfo info = new StatusPageHistoryInfo();
info.setId(history.getId());
info.setComponentId(history.getComponentId());
info.setState(history.getState());
info.setTimestamp(history.getTimestamp());
info.setUptime(history.getUptime());
info.setAbnormal(history.getAbnormal());
info.setUnknowing(history.getUnknowing());
info.setNormal(history.getNormal());
info.setCreator(history.getCreator());
info.setModifier(history.getModifier());
info.setGmtCreate(history.getGmtCreate());
info.setGmtUpdate(history.getGmtUpdate());
return info;
}
public StatusPageHistory toEntity() {
StatusPageHistory history = new StatusPageHistory();
history.setId(id);
history.setComponentId(componentId);
history.setState(state);
history.setTimestamp(timestamp);
history.setUptime(uptime);
history.setAbnormal(abnormal);
history.setUnknowing(unknowing);
history.setNormal(normal);
history.setCreator(creator);
history.setModifier(modifier);
history.setGmtCreate(gmtCreate);
history.setGmtUpdate(gmtUpdate);
return history;
}
}
@@ -0,0 +1,84 @@
/*
* 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.manager.pojo.dto;
import jakarta.validation.constraints.NotBlank;
import java.time.LocalDateTime;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.hertzbeat.common.entity.manager.StatusPageIncidentContent;
/**
* Manager-side status-page incident content DTO detached from JPA annotations.
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class StatusPageIncidentContentInfo {
private Long id;
private Long incidentId;
@NotBlank
private String message;
private byte state;
private Long timestamp;
private String creator;
private String modifier;
private LocalDateTime gmtCreate;
private LocalDateTime gmtUpdate;
public static StatusPageIncidentContentInfo fromEntity(StatusPageIncidentContent content) {
if (content == null) {
return null;
}
StatusPageIncidentContentInfo info = new StatusPageIncidentContentInfo();
info.setId(content.getId());
info.setIncidentId(content.getIncidentId());
info.setMessage(content.getMessage());
info.setState(content.getState());
info.setTimestamp(content.getTimestamp());
info.setCreator(content.getCreator());
info.setModifier(content.getModifier());
info.setGmtCreate(content.getGmtCreate());
info.setGmtUpdate(content.getGmtUpdate());
return info;
}
public StatusPageIncidentContent toEntity() {
StatusPageIncidentContent content = new StatusPageIncidentContent();
content.setId(id);
content.setIncidentId(incidentId);
content.setMessage(message);
content.setState(state);
content.setTimestamp(timestamp);
content.setCreator(creator);
content.setModifier(modifier);
content.setGmtCreate(gmtCreate);
content.setGmtUpdate(gmtUpdate);
return content;
}
}
@@ -0,0 +1,115 @@
/*
* 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.manager.pojo.dto;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import java.time.LocalDateTime;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.hertzbeat.common.entity.manager.StatusPageIncident;
/**
* Manager-side status-page incident DTO detached from JPA annotations.
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class StatusPageIncidentInfo {
private Long id;
private Long orgId;
@NotBlank
private String name;
private byte state;
private Long startTime;
private Long endTime;
private String creator;
private String modifier;
private LocalDateTime gmtCreate;
private LocalDateTime gmtUpdate;
@Valid
private List<StatusPageComponentInfo> components;
@Valid
private List<StatusPageIncidentContentInfo> contents;
public static StatusPageIncidentInfo fromEntity(StatusPageIncident incident) {
if (incident == null) {
return null;
}
StatusPageIncidentInfo info = new StatusPageIncidentInfo();
info.setId(incident.getId());
info.setOrgId(incident.getOrgId());
info.setName(incident.getName());
info.setState(incident.getState());
info.setStartTime(incident.getStartTime());
info.setEndTime(incident.getEndTime());
info.setCreator(incident.getCreator());
info.setModifier(incident.getModifier());
info.setGmtCreate(incident.getGmtCreate());
info.setGmtUpdate(incident.getGmtUpdate());
info.setComponents(incident.getComponents() == null ? null : incident.getComponents().stream()
.filter(Objects::nonNull)
.map(StatusPageComponentInfo::fromEntity)
.toList());
info.setContents(incident.getContents() == null ? null : incident.getContents().stream()
.filter(Objects::nonNull)
.map(StatusPageIncidentContentInfo::fromEntity)
.toList());
return info;
}
public StatusPageIncident toEntity() {
StatusPageIncident incident = new StatusPageIncident();
incident.setId(id);
incident.setOrgId(orgId);
incident.setName(name);
incident.setState(state);
incident.setStartTime(startTime);
incident.setEndTime(endTime);
incident.setCreator(creator);
incident.setModifier(modifier);
incident.setGmtCreate(gmtCreate);
incident.setGmtUpdate(gmtUpdate);
incident.setComponents(components == null ? null : components.stream()
.filter(Objects::nonNull)
.map(StatusPageComponentInfo::toEntity)
.toList());
incident.setContents(contents == null ? null : contents.stream()
.filter(Objects::nonNull)
.map(StatusPageIncidentContentInfo::toEntity)
.collect(Collectors.toCollection(LinkedHashSet::new)));
return incident;
}
}
@@ -0,0 +1,99 @@
/*
* 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.manager.pojo.dto;
import jakarta.validation.constraints.NotBlank;
import java.time.LocalDateTime;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.hertzbeat.common.entity.manager.StatusPageOrg;
/**
* Manager-side status-page org DTO detached from JPA annotations.
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class StatusPageOrgInfo {
private Long id;
@NotBlank
private String name;
@NotBlank
private String description;
@NotBlank
private String home;
@NotBlank
private String logo;
private String feedback;
private String color;
private byte state;
private String creator;
private String modifier;
private LocalDateTime gmtCreate;
private LocalDateTime gmtUpdate;
public static StatusPageOrgInfo fromEntity(StatusPageOrg statusPageOrg) {
if (statusPageOrg == null) {
return null;
}
StatusPageOrgInfo info = new StatusPageOrgInfo();
info.setId(statusPageOrg.getId());
info.setName(statusPageOrg.getName());
info.setDescription(statusPageOrg.getDescription());
info.setHome(statusPageOrg.getHome());
info.setLogo(statusPageOrg.getLogo());
info.setFeedback(statusPageOrg.getFeedback());
info.setColor(statusPageOrg.getColor());
info.setState(statusPageOrg.getState());
info.setCreator(statusPageOrg.getCreator());
info.setModifier(statusPageOrg.getModifier());
info.setGmtCreate(statusPageOrg.getGmtCreate());
info.setGmtUpdate(statusPageOrg.getGmtUpdate());
return info;
}
public StatusPageOrg toEntity() {
StatusPageOrg statusPageOrg = new StatusPageOrg();
statusPageOrg.setId(id);
statusPageOrg.setName(name);
statusPageOrg.setDescription(description);
statusPageOrg.setHome(home);
statusPageOrg.setLogo(logo);
statusPageOrg.setFeedback(feedback);
statusPageOrg.setColor(color);
statusPageOrg.setState(state);
statusPageOrg.setCreator(creator);
statusPageOrg.setModifier(modifier);
statusPageOrg.setGmtCreate(gmtCreate);
statusPageOrg.setGmtUpdate(gmtUpdate);
return statusPageOrg;
}
}
@@ -0,0 +1,48 @@
/*
* 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.manager.pojo.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* System Configuration
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SystemConfig {
/**
* system time zone
*/
private String timeZoneId;
/**
* system locale language region
*/
private String locale;
/**
* layout ui theme
*/
private String theme;
}
@@ -0,0 +1,43 @@
/*
* 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.manager.pojo.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* System Secret Config
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SystemSecret {
/**
* secret key for jwt
*/
private String jwtSecret;
/**
* secret key for aes
*/
private String aesSecret;
}
@@ -0,0 +1,57 @@
/*
* 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.manager.pojo.dto;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* App Template Config
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TemplateConfig {
/**
* app template config map
* key: app name
* value: app template config
*/
private Map<String, AppTemplate> apps;
/**
* app template
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class AppTemplate {
/**
* Is hide this app in main menus layout, only for app type, default true
*/
@Builder.Default
private boolean hide = true;
}
}

Some files were not shown because too many files have changed in this diff Show More