Compare commits
No commits in common. 'dev-lensfrex' and 'main' have entirely different histories.
dev-lensfr
...
main
@ -1,36 +0,0 @@ |
||||
package rition.backend.api.interceptor; |
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper; |
||||
import jakarta.annotation.Nonnull; |
||||
import jakarta.servlet.http.HttpServletRequest; |
||||
import jakarta.servlet.http.HttpServletResponse; |
||||
import org.springframework.http.HttpStatus; |
||||
import org.springframework.stereotype.Component; |
||||
import org.springframework.web.servlet.HandlerInterceptor; |
||||
import org.springframework.web.servlet.ModelAndView; |
||||
import rition.backend.api.v1.dto.response.Response; |
||||
import rition.common.exception.code.ServiceCode; |
||||
|
||||
@Component |
||||
public class NotFoundPathInterceptor implements HandlerInterceptor { |
||||
private final ObjectMapper objectMapper; |
||||
|
||||
public NotFoundPathInterceptor(ObjectMapper objectMapper) { |
||||
this.objectMapper = objectMapper; |
||||
} |
||||
|
||||
@Override |
||||
public void postHandle(@Nonnull HttpServletRequest request, |
||||
@Nonnull HttpServletResponse servletResponse, |
||||
@Nonnull Object handler, |
||||
ModelAndView modelAndView) throws Exception { |
||||
if (servletResponse.getStatus() == HttpStatus.NOT_FOUND.value()) { |
||||
var response = Response.error(ServiceCode.ApiNotImplement); |
||||
var json = objectMapper.writeValueAsString(response); |
||||
|
||||
servletResponse.setContentType("application/json"); |
||||
servletResponse.setCharacterEncoding("utf-8"); |
||||
servletResponse.getWriter().write(json); |
||||
} |
||||
} |
||||
} |
@ -1,39 +0,0 @@ |
||||
package rition.backend.api.v1.dto.response; |
||||
|
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Builder; |
||||
import lombok.Data; |
||||
import lombok.NoArgsConstructor; |
||||
|
||||
import java.time.Instant; |
||||
|
||||
@Data |
||||
@Builder |
||||
@NoArgsConstructor |
||||
@AllArgsConstructor |
||||
public class AlertResponse { |
||||
/** |
||||
* id |
||||
*/ |
||||
private Long id; |
||||
|
||||
/** |
||||
* 出现警告的实例id |
||||
*/ |
||||
private String instanceId; |
||||
|
||||
/** |
||||
* 触发的规则 |
||||
*/ |
||||
private Long rule; |
||||
|
||||
/** |
||||
* 触发时的数值 |
||||
*/ |
||||
private Double value; |
||||
|
||||
/** |
||||
* 警告出现的时间 |
||||
*/ |
||||
private Long time; |
||||
} |
@ -1,34 +0,0 @@ |
||||
package rition.backend.api.v1.dto.response; |
||||
|
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Builder; |
||||
import lombok.Data; |
||||
import lombok.NoArgsConstructor; |
||||
|
||||
import java.time.Instant; |
||||
|
||||
@Data |
||||
@Builder |
||||
@NoArgsConstructor |
||||
@AllArgsConstructor |
||||
public class ContractResponse { |
||||
/** |
||||
* id |
||||
*/ |
||||
private Long id; |
||||
|
||||
/** |
||||
* 联系方式 |
||||
*/ |
||||
private String contract; |
||||
|
||||
/** |
||||
* 联系方式类型 |
||||
*/ |
||||
private Integer type; |
||||
|
||||
/** |
||||
* create_time |
||||
*/ |
||||
private Long createTime; |
||||
} |
@ -1,29 +0,0 @@ |
||||
package rition.backend.api.v1.dto.response; |
||||
|
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Builder; |
||||
import lombok.Data; |
||||
import lombok.NoArgsConstructor; |
||||
|
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
@Data |
||||
@Builder |
||||
@NoArgsConstructor |
||||
@AllArgsConstructor |
||||
public class MetricDataResponse { |
||||
/** |
||||
* 监控指标值,使用json格式存储 |
||||
*/ |
||||
private Map<String, MetricDataResponseItem> metricData; |
||||
|
||||
@Data |
||||
@Builder |
||||
@NoArgsConstructor |
||||
@AllArgsConstructor |
||||
public static class MetricDataResponseItem { |
||||
private List<Long> time; |
||||
private List<Double> value; |
||||
} |
||||
} |
@ -1,54 +0,0 @@ |
||||
package rition.backend.api.v1.dto.response; |
||||
|
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Builder; |
||||
import lombok.Data; |
||||
import lombok.NoArgsConstructor; |
||||
|
||||
import java.time.Instant; |
||||
|
||||
@Data |
||||
@Builder |
||||
@AllArgsConstructor |
||||
@NoArgsConstructor |
||||
public class RuleResponse { |
||||
/** |
||||
* 规则id |
||||
*/ |
||||
private Long id; |
||||
|
||||
/** |
||||
* 需要计算的指标项或者表达式 |
||||
*/ |
||||
private String expression; |
||||
|
||||
/** |
||||
* 触发条件 |
||||
*/ |
||||
private Integer condition; |
||||
|
||||
/** |
||||
* 阈值 |
||||
*/ |
||||
private Double threshold; |
||||
|
||||
/** |
||||
* 触发方法,实时计算或定时计算 |
||||
*/ |
||||
private Integer trigger; |
||||
|
||||
/** |
||||
* 规则描述 |
||||
*/ |
||||
private String description; |
||||
|
||||
/** |
||||
* create_time |
||||
*/ |
||||
private Long createTime; |
||||
|
||||
/** |
||||
* update_time |
||||
*/ |
||||
private Long updateTime; |
||||
} |
@ -1,46 +0,0 @@ |
||||
package rition.backend.api.v1.panel; |
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping; |
||||
import org.springframework.web.bind.annotation.RequestMapping; |
||||
import org.springframework.web.bind.annotation.RequestParam; |
||||
import org.springframework.web.bind.annotation.RestController; |
||||
import rition.backend.api.v1.dto.response.AlertResponse; |
||||
import rition.backend.api.v1.dto.response.Response; |
||||
import rition.common.data.dto.PagingData; |
||||
import rition.common.data.entity.AlertEntity; |
||||
import rition.service.panel.AlertHistoryService; |
||||
|
||||
@RestController |
||||
@RequestMapping("/panel/alerts") |
||||
public class AlertHistoryController { |
||||
private final AlertHistoryService alertHistoryService; |
||||
|
||||
public AlertHistoryController(AlertHistoryService alertHistoryService) { |
||||
this.alertHistoryService = alertHistoryService; |
||||
} |
||||
|
||||
@GetMapping("/list") |
||||
public Response<PagingData<AlertResponse>> getContractList( |
||||
@RequestParam(value = "instance_id", required = false) String instanceId, |
||||
@RequestParam(value = "page", required = false, defaultValue = "1") Integer page, |
||||
@RequestParam(value = "page_size", required = false, defaultValue = "10") Integer pageSize |
||||
) { |
||||
|
||||
PagingData<AlertEntity> alertEntityPagingData = new PagingData<>(page, pageSize); |
||||
var result = alertHistoryService.getAlertHistory(instanceId, alertEntityPagingData); |
||||
|
||||
PagingData<AlertResponse> alertResponsePagingData = PagingData.copyOnlyPagingValues(result); |
||||
for (AlertEntity entity : result.getData()) { |
||||
alertResponsePagingData.getData().add(AlertResponse.builder() |
||||
.id(entity.getId()) |
||||
.instanceId(entity.getInstanceId()) |
||||
.rule(entity.getRule()) |
||||
.value(entity.getValue()) |
||||
.time(entity.getTime().toEpochMilli()) |
||||
.build() |
||||
); |
||||
} |
||||
|
||||
return Response.success(alertResponsePagingData); |
||||
} |
||||
} |
@ -1,138 +1,18 @@ |
||||
package rition.backend.api.v1.panel; |
||||
|
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.data.redis.core.RedisTemplate; |
||||
import org.springframework.web.bind.annotation.PostMapping; |
||||
import org.springframework.web.bind.annotation.GetMapping; |
||||
import org.springframework.web.bind.annotation.RequestBody; |
||||
import org.springframework.web.bind.annotation.RequestMapping; |
||||
import org.springframework.web.bind.annotation.RestController; |
||||
import rition.backend.api.v1.dto.request.MetricDataRequest; |
||||
import rition.backend.api.v1.dto.response.MetricDataResponse; |
||||
import rition.backend.api.v1.dto.response.Response; |
||||
import rition.common.data.dto.service.MetricDataDto; |
||||
import rition.common.data.entity.MetricRecordEntity; |
||||
import rition.common.data.enums.Constants; |
||||
import rition.service.panel.MetricService; |
||||
|
||||
import java.time.Instant; |
||||
import java.util.*; |
||||
|
||||
@Slf4j |
||||
@RestController |
||||
@RequestMapping("/panel/metrics") |
||||
public class MetricsViewController { |
||||
|
||||
private final MetricService metricService; |
||||
private final RedisTemplate<String, Object> redisTemplate; |
||||
|
||||
public MetricsViewController(MetricService metricService, RedisTemplate<String, Object> redisTemplate) { |
||||
this.metricService = metricService; |
||||
this.redisTemplate = redisTemplate; |
||||
} |
||||
|
||||
@PostMapping("/list") |
||||
public Response<MetricDataResponse> getMetrics(@RequestBody MetricDataRequest metricDataRequest) { |
||||
MetricDataResponse metricDataResponse = new MetricDataResponse(); |
||||
metricDataResponse.setMetricData(new HashMap<>(metricDataRequest.getMetricItems().size())); |
||||
|
||||
// 如果未给定范围参数,则使用最近一小时的数据
|
||||
if (metricDataRequest.getStart() == null || metricDataRequest.getEnd() == null) { |
||||
List<Object> recentMetricDataList = |
||||
redisTemplate.opsForList().range( |
||||
Constants.RedisKeys.RECENT_METRIC_CACHE, 0, Constants.MAX_METRIC_CACHE_NUM |
||||
); |
||||
if (recentMetricDataList == null) { |
||||
return Response.success(MetricDataResponse.builder().metricData(new HashMap<>()).build()); |
||||
} |
||||
|
||||
for (String metricItem : metricDataRequest.getMetricItems()) { |
||||
metricDataResponse.getMetricData().put(metricItem, MetricDataResponse.MetricDataResponseItem.builder() |
||||
.time(new ArrayList<>(recentMetricDataList.size())) |
||||
.value(new ArrayList<>(recentMetricDataList.size())) |
||||
.build() |
||||
); |
||||
} |
||||
|
||||
for (Object recentMetricData : recentMetricDataList) { |
||||
var metricDataDto = (MetricDataDto) recentMetricData; |
||||
Map<String, Double> data = metricDataDto.getData(); |
||||
for (String metric : data.keySet()) { |
||||
var metricResponseData = metricDataResponse.getMetricData().get(metric); |
||||
metricResponseData.getTime().add(metricDataDto.getTimestamp()); |
||||
metricResponseData.getValue().add(data.get(metric)); |
||||
} |
||||
} |
||||
|
||||
return Response.success(metricDataResponse); |
||||
} |
||||
|
||||
var entityResult = metricService.getMetricDataRange( |
||||
metricDataRequest.getInstanceId(), |
||||
this.filterMetricItems(metricDataRequest.getMetricItems()), |
||||
Instant.ofEpochMilli(metricDataRequest.getStart()), |
||||
Instant.ofEpochMilli(metricDataRequest.getEnd()) |
||||
); |
||||
|
||||
// 转换数据
|
||||
|
||||
for (String metricItem : metricDataRequest.getMetricItems()) { |
||||
metricDataResponse.getMetricData().put(metricItem, MetricDataResponse.MetricDataResponseItem.builder() |
||||
.time(new ArrayList<>(entityResult.size())) |
||||
.value(new ArrayList<>(entityResult.size())) |
||||
.build() |
||||
); |
||||
} |
||||
|
||||
for (MetricRecordEntity entity : entityResult) { |
||||
var data = entity.getMetricData(); |
||||
for (String metric : data.keySet()) { |
||||
var metricResponseData = metricDataResponse.getMetricData().get(metric); |
||||
metricResponseData.getTime().add(entity.getTime().toEpochMilli()); |
||||
metricResponseData.getValue().add(data.get(metric)); |
||||
} |
||||
} |
||||
|
||||
return Response.success(metricDataResponse); |
||||
} |
||||
|
||||
|
||||
private static final HashSet<String> allowedMetricItems = new HashSet<>(22); |
||||
|
||||
static { |
||||
allowedMetricItems.add("up"); |
||||
allowedMetricItems.add("node_load5"); |
||||
allowedMetricItems.add("node_sockstat_TCP_tw"); |
||||
allowedMetricItems.add("node_cpu_seconds_total"); |
||||
allowedMetricItems.add("node_memory_Cached_bytes"); |
||||
allowedMetricItems.add("node_memory_Buffers_bytes"); |
||||
allowedMetricItems.add("node_memory_MemFree_bytes"); |
||||
allowedMetricItems.add("node_disk_read_bytes_total"); |
||||
allowedMetricItems.add("node_filesystem_free_bytes"); |
||||
allowedMetricItems.add("node_filesystem_size_bytes"); |
||||
allowedMetricItems.add("node_memory_MemTotal_bytes"); |
||||
allowedMetricItems.add("node_netstat_Tcp_CurrEstab"); |
||||
allowedMetricItems.add("node_filesystem_avail_bytes"); |
||||
allowedMetricItems.add("node_disk_written_bytes_total"); |
||||
allowedMetricItems.add("node_disk_reads_completed_total"); |
||||
allowedMetricItems.add("node_network_receive_drop_total"); |
||||
allowedMetricItems.add("node_disk_writes_completed_total"); |
||||
allowedMetricItems.add("node_network_receive_bytes_total"); |
||||
allowedMetricItems.add("node_network_transmit_drop_total"); |
||||
allowedMetricItems.add("node_network_transmit_bytes_total"); |
||||
allowedMetricItems.add("node_network_receive_packets_total"); |
||||
allowedMetricItems.add("node_network_transmit_packets_total"); |
||||
} |
||||
|
||||
private List<String> filterMetricItems(List<String> metricItems) { |
||||
List<String> filteredMetricItems = new ArrayList<>(metricItems.size()); |
||||
for (String metricItem : metricItems) { |
||||
if (allowedMetricItems.contains(metricItem)) { |
||||
filteredMetricItems.add(metricItem); |
||||
} else { |
||||
log.warn("[MetricService]: 请求的指标值含有非允许的指标值:{}", metricItem); |
||||
} |
||||
} |
||||
|
||||
return filteredMetricItems; |
||||
@GetMapping("/list") |
||||
public Response<Object> getMetrics(@RequestBody MetricDataRequest metricDataRequest) { |
||||
return Response.success(); |
||||
} |
||||
} |
||||
|
@ -0,0 +1,10 @@ |
||||
package rition.backend.api.v1.panel; |
||||
|
||||
import org.springframework.web.bind.annotation.RequestMapping; |
||||
import org.springframework.web.bind.annotation.RestController; |
||||
|
||||
@RestController |
||||
@RequestMapping("/panel") |
||||
public class PanelController { |
||||
|
||||
} |
@ -1,35 +0,0 @@ |
||||
package rition.backend.configure; |
||||
|
||||
import io.swagger.v3.oas.models.OpenAPI; |
||||
import io.swagger.v3.oas.models.info.Info; |
||||
import io.swagger.v3.oas.models.servers.Server; |
||||
import lombok.Getter; |
||||
import org.springframework.beans.factory.annotation.Value; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
import java.util.ArrayList; |
||||
|
||||
@Getter |
||||
@Component |
||||
@Configuration |
||||
public class OpenAPIConfigure { |
||||
private String serverUrl; |
||||
|
||||
@Value("${wusthelper.docs.server-url:/}") |
||||
public void setServerUrl(String serverUrl) { |
||||
this.serverUrl = serverUrl; |
||||
} |
||||
|
||||
@Bean |
||||
public OpenAPI openAPI() { |
||||
var info = new Info() |
||||
.title("Rition-center") |
||||
.description("Rition-center api") |
||||
.version("v1"); |
||||
|
||||
return new OpenAPI() |
||||
.info(info); |
||||
} |
||||
} |
@ -1,7 +0,0 @@ |
||||
package rition.backend.service.panel; |
||||
|
||||
import org.springframework.stereotype.Service; |
||||
|
||||
@Service |
||||
public class PanelMetricService { |
||||
} |
@ -1,39 +0,0 @@ |
||||
package panel; |
||||
|
||||
import org.junit.jupiter.api.Test; |
||||
import org.mybatis.spring.boot.test.autoconfigure.AutoConfigureMybatis; |
||||
import org.mybatis.spring.boot.test.autoconfigure.MybatisTest; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; |
||||
import org.springframework.boot.test.context.SpringBootTest; |
||||
import org.springframework.test.context.ContextConfiguration; |
||||
import rition.backend.RitionBackendMain; |
||||
import rition.common.data.dao.mapper.MetricRecordMapper; |
||||
|
||||
import java.time.Instant; |
||||
import java.util.ArrayList; |
||||
import java.util.Arrays; |
||||
import java.util.List; |
||||
|
||||
@MybatisTest |
||||
@ContextConfiguration(classes = RitionBackendMain.class) |
||||
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) |
||||
public class MetricServiceTest { |
||||
@Autowired |
||||
MetricRecordMapper metricRecordMapper; |
||||
|
||||
@Test |
||||
public void testGetMetricRecord() { |
||||
List<String> metricItems = new ArrayList<>(); |
||||
metricItems.add("node_network_receive_packets_total"); |
||||
metricItems.add("node_sockstat_TCP_tw"); |
||||
var result = metricRecordMapper.getMetricDataGroupByHour( |
||||
"7273a1ea-0089-4674-b606-b1b8d809d866", |
||||
metricItems, |
||||
Instant.parse("2024-04-17T14:00:00.00Z"), |
||||
Instant.parse("2024-04-17T16:00:00.00Z") |
||||
); |
||||
|
||||
System.out.println(Arrays.toString(result.toArray())); |
||||
} |
||||
} |
@ -1,21 +0,0 @@ |
||||
package rition.common.configure; |
||||
|
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.core.io.ClassPathResource; |
||||
import org.springframework.core.io.Resource; |
||||
import org.springframework.data.redis.core.script.DefaultRedisScript; |
||||
import org.springframework.data.redis.core.script.RedisScript; |
||||
import org.springframework.scripting.support.ResourceScriptSource; |
||||
|
||||
@Configuration |
||||
public class RedisLuaConfigure { |
||||
@Bean(name = "constLenQueueRedisScript") |
||||
public RedisScript<Object> constLenQueueRedisScript() { |
||||
Resource luaResource = new ClassPathResource("redis/const_len_queue.lua"); |
||||
DefaultRedisScript<Object> redisScript = new DefaultRedisScript<>(); |
||||
redisScript.setScriptSource(new ResourceScriptSource(luaResource)); |
||||
|
||||
return redisScript; |
||||
} |
||||
} |
@ -1,9 +0,0 @@ |
||||
package rition.common.data.dao.mapper; |
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
||||
import org.apache.ibatis.annotations.Mapper; |
||||
import rition.common.data.entity.AlertEntity; |
||||
|
||||
@Mapper |
||||
public interface AlertMapper extends BaseMapper<AlertEntity> { |
||||
} |
@ -1,7 +0,0 @@ |
||||
package rition.common.data.dao.mapper; |
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
||||
import rition.common.data.entity.ContractEntity; |
||||
|
||||
public interface ContractMapper extends BaseMapper<ContractEntity> { |
||||
} |
@ -1,35 +0,0 @@ |
||||
package rition.common.data.dao.mapper; |
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
||||
import org.apache.ibatis.annotations.Mapper; |
||||
import org.apache.ibatis.annotations.Param; |
||||
import org.springframework.stereotype.Component; |
||||
import rition.common.data.entity.MetricRecordEntity; |
||||
|
||||
import java.time.Instant; |
||||
import java.util.List; |
||||
|
||||
@Mapper |
||||
@Component |
||||
public interface MetricRecordMapper extends BaseMapper<MetricRecordEntity> { |
||||
int insertBatchSomeColumn(List<MetricRecordEntity> entityList); |
||||
|
||||
List<MetricRecordEntity> getMetricDataGroupByHour( |
||||
@Param("instanceId") String instanceId, |
||||
@Param("metricItems") List<String> metricItems, |
||||
@Param("startTime") Instant startTime, @Param("endTime") Instant endTime |
||||
); |
||||
|
||||
List<MetricRecordEntity> getMetricDataGroupByMinute( |
||||
@Param("instanceId") String instanceId, |
||||
@Param("metricItems") List<String> metricItems, |
||||
@Param("startTime") Instant startTime, @Param("endTime") Instant endTime |
||||
); |
||||
|
||||
List<MetricRecordEntity> getMetricDataGroupBySomeMinute( |
||||
@Param("minutes") Integer minutes, |
||||
@Param("instanceId") String instanceId, |
||||
@Param("metricItems") List<String> metricItems, |
||||
@Param("startTime") Instant startTime, @Param("endTime") Instant endTime |
||||
); |
||||
} |
@ -1,9 +0,0 @@ |
||||
package rition.common.data.dao.mapper; |
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
||||
import org.apache.ibatis.annotations.Mapper; |
||||
import rition.common.data.entity.RuleEntity; |
||||
|
||||
@Mapper |
||||
public interface RuleMapper extends BaseMapper<RuleEntity> { |
||||
} |
@ -1,5 +1,5 @@ |
||||
|
||||
package rition.common.data.dto.service; |
||||
package rition.common.data.dto; |
||||
|
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Builder; |
@ -1,54 +0,0 @@ |
||||
package rition.common.data.dto; |
||||
|
||||
|
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Builder; |
||||
import lombok.Data; |
||||
import lombok.NoArgsConstructor; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Collection; |
||||
|
||||
@Data |
||||
@Builder |
||||
@NoArgsConstructor |
||||
@AllArgsConstructor |
||||
public class PagingData<T> { |
||||
private long currentPage; |
||||
private long pageSize; |
||||
private long totalPage; |
||||
|
||||
private long totalResult; |
||||
|
||||
private Collection<T> data; |
||||
|
||||
public PagingData(long currentPage, long pageSize) { |
||||
this.currentPage = currentPage; |
||||
this.pageSize = pageSize; |
||||
} |
||||
|
||||
public PagingData<T> copy() { |
||||
PagingData<T> pagingData = new PagingData<>(); |
||||
|
||||
pagingData.setCurrentPage(this.getCurrentPage()); |
||||
pagingData.setPageSize(this.getPageSize()); |
||||
pagingData.setTotalPage(this.getTotalPage()); |
||||
pagingData.setTotalResult(this.getTotalResult()); |
||||
pagingData.setData(this.getData()); |
||||
|
||||
return pagingData; |
||||
} |
||||
|
||||
public static <K> PagingData<K> copyOnlyPagingValues(PagingData<?> source) { |
||||
PagingData<K> pagingData = new PagingData<>(); |
||||
|
||||
pagingData.setCurrentPage(source.getCurrentPage()); |
||||
pagingData.setPageSize(source.getPageSize()); |
||||
pagingData.setTotalPage(source.getTotalPage()); |
||||
pagingData.setTotalResult(source.getTotalResult()); |
||||
pagingData.setData(new ArrayList<>(source.data.size())); |
||||
|
||||
return pagingData; |
||||
} |
||||
} |
||||
|
@ -1,54 +0,0 @@ |
||||
package rition.common.data.dto.service; |
||||
|
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Builder; |
||||
import lombok.Data; |
||||
import lombok.NoArgsConstructor; |
||||
|
||||
import java.time.Instant; |
||||
|
||||
@Data |
||||
@Builder |
||||
@AllArgsConstructor |
||||
@NoArgsConstructor |
||||
public class AlertRuleDto { |
||||
/** |
||||
* 规则id |
||||
*/ |
||||
private Long id; |
||||
|
||||
/** |
||||
* 规则对应的实例id |
||||
*/ |
||||
private String instanceId; |
||||
|
||||
/** |
||||
* 需要计算的指标项或者表达式 |
||||
*/ |
||||
private String expression; |
||||
|
||||
/** |
||||
* 触发条件 |
||||
*/ |
||||
private Integer condition; |
||||
|
||||
/** |
||||
* 阈值 |
||||
*/ |
||||
private Double threshold; |
||||
|
||||
/** |
||||
* 触发方法,实时计算或定时计算 |
||||
*/ |
||||
private Integer trigger; |
||||
|
||||
/** |
||||
* 规则描述 |
||||
*/ |
||||
private String description; |
||||
|
||||
/** |
||||
* create_time |
||||
*/ |
||||
private Instant createTime; |
||||
} |
@ -1,36 +0,0 @@ |
||||
package rition.common.data.dto.service.panel; |
||||
|
||||
import lombok.Data; |
||||
|
||||
@Data |
||||
public class AlertRuleAddDto { |
||||
/** |
||||
* 规则对应的实例id |
||||
*/ |
||||
private String instanceId; |
||||
|
||||
/** |
||||
* 需要计算的指标项或者表达式 |
||||
*/ |
||||
private String expression; |
||||
|
||||
/** |
||||
* 触发条件 |
||||
*/ |
||||
private Integer condition; |
||||
|
||||
/** |
||||
* 阈值 |
||||
*/ |
||||
private Double threshold; |
||||
|
||||
/** |
||||
* 触发方法,实时计算或定时计算 |
||||
*/ |
||||
private Integer trigger; |
||||
|
||||
/** |
||||
* 规则描述 |
||||
*/ |
||||
private String description; |
||||
} |
@ -1,36 +0,0 @@ |
||||
package rition.common.data.dto.service.panel; |
||||
|
||||
import lombok.Data; |
||||
|
||||
@Data |
||||
public class AlertRuleDto { |
||||
/** |
||||
* 规则对应的实例id |
||||
*/ |
||||
private String instanceId; |
||||
|
||||
/** |
||||
* 需要计算的指标项或者表达式 |
||||
*/ |
||||
private String expression; |
||||
|
||||
/** |
||||
* 触发条件 |
||||
*/ |
||||
private Integer condition; |
||||
|
||||
/** |
||||
* 阈值 |
||||
*/ |
||||
private Double threshold; |
||||
|
||||
/** |
||||
* 触发方法,实时计算或定时计算 |
||||
*/ |
||||
private Integer trigger; |
||||
|
||||
/** |
||||
* 规则描述 |
||||
*/ |
||||
private String description; |
||||
} |
@ -1,17 +0,0 @@ |
||||
package rition.common.data.dto.service.panel; |
||||
|
||||
import lombok.Data; |
||||
|
||||
@Data |
||||
public class ContractAddDto { |
||||
|
||||
/** |
||||
* 联系方式 |
||||
*/ |
||||
private String contract; |
||||
|
||||
/** |
||||
* 联系方式类型 |
||||
*/ |
||||
private Integer type; |
||||
} |
@ -1,79 +0,0 @@ |
||||
<?xml version="1.0" encoding="UTF-8" ?> |
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > |
||||
<mapper namespace="rition.common.data.dao.mapper.MetricRecordMapper"> |
||||
<resultMap id="metricDataEntity" type="rition.common.data.entity.MetricRecordEntity"> |
||||
<result property="metricData" column="metric_data" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/> |
||||
</resultMap> |
||||
|
||||
<select id="getMetricDataGroupByHour" resultMap="metricDataEntity" resultType="rition.common.data.entity.MetricRecordEntity"> |
||||
SELECT JSON_OBJECT( |
||||
<foreach collection="metricItems" item="metricItem" separator=","> |
||||
"${metricItem}", ${metricItem} |
||||
</foreach> |
||||
) AS metric_data, |
||||
t AS time |
||||
FROM ( |
||||
SELECT |
||||
<foreach collection="metricItems" item="metricItem"> |
||||
avg(JSON_EXTRACT(metric_data, "$.${metricItem}")) as ${metricItem}, |
||||
</foreach> |
||||
DATE_FORMAT(time,'%Y-%m-%d %H:00:00') as t |
||||
FROM record WHERE `time` BETWEEN #{startTime} and #{endTime} and `instance_id` = #{instanceId} |
||||
GROUP BY t ORDER BY t |
||||
) AS tab; |
||||
|
||||
<!-- |
||||
SELECT |
||||
JSON_OBJECT('node_sockstat_TCP_tw', node_sockstat_TCP_tw), |
||||
t AS time |
||||
FROM ( |
||||
SELECT |
||||
avg(JSON_EXTRACT(metric_data, "$.node_sockstat_TCP_tw")) node_sockstat_TCP_tw, |
||||
DATE_FORMAT(time,'%Y-%m-%d %H:00:00') as t |
||||
FROM record |
||||
WHERE `time` BETWEEN '2024-04-17 14:00:00' and '2024-04-17 15:00:00' |
||||
GROUP BY t ORDER BY t |
||||
) AS tab |
||||
--> |
||||
</select> |
||||
|
||||
<select id="getMetricDataGroupByMinute" resultMap="metricDataEntity" resultType="rition.common.data.entity.MetricRecordEntity"> |
||||
SELECT JSON_OBJECT( |
||||
<foreach collection="metricItems" item="metricItem" separator=","> |
||||
"${metricItem}", ${metricItem} |
||||
</foreach> |
||||
) AS metric_data, |
||||
t AS time |
||||
FROM ( |
||||
SELECT |
||||
<foreach collection="metricItems" item="metricItem"> |
||||
avg(JSON_EXTRACT(metric_data, "$.${metricItem}")) as ${metricItem}, |
||||
</foreach> |
||||
DATE_FORMAT(time,'%Y-%m-%d %H:%i:00') as t |
||||
FROM record WHERE `time` BETWEEN #{startTime} and #{endTime} and `instance_id` = #{instanceId} |
||||
GROUP BY t ORDER BY t |
||||
) AS tab; |
||||
</select> |
||||
|
||||
<select id="getMetricDataGroupBySomeMinute" resultMap="metricDataEntity" resultType="rition.common.data.entity.MetricRecordEntity"> |
||||
SELECT JSON_OBJECT( |
||||
<foreach collection="metricItems" item="metricItem" separator=","> |
||||
"${metricItem}", ${metricItem} |
||||
</foreach> |
||||
) AS metric_data, |
||||
t AS time |
||||
FROM ( |
||||
SELECT |
||||
<foreach collection="metricItems" item="metricItem"> |
||||
avg(JSON_EXTRACT(metric_data, "$.${metricItem}")) as ${metricItem}, |
||||
</foreach> |
||||
DATE_FORMAT( |
||||
concat( date( `time` ), ' ', HOUR ( `time` ), ':', floor( MINUTE ( `time` ) / #{minutes} ) * ${minutes} ), |
||||
'%Y-%m-%d %H:%i:00' |
||||
) as t |
||||
FROM record WHERE `time` BETWEEN #{startTime} and #{endTime} and `instance_id` = #{instanceId} |
||||
GROUP BY t ORDER BY t |
||||
) AS tab; |
||||
</select> |
||||
|
||||
</mapper> |
@ -1,7 +0,0 @@ |
||||
local key = KEYS[1] |
||||
local max_len = tonumber(ARGV[1]) |
||||
local val = ARGV[2] |
||||
if (redis.call('llen', key) > max_len) then |
||||
redis.call('lpop', key) |
||||
end |
||||
redis.call('rpush', key, val) |
@ -0,0 +1,8 @@ |
||||
package rition.service.collector.configure; |
||||
|
||||
import org.springframework.context.annotation.Configuration; |
||||
|
||||
@Configuration |
||||
public class MybatisPlusConfigure { |
||||
|
||||
} |
@ -1,4 +1,4 @@ |
||||
package rition.common.data.dao; |
||||
package rition.service.collector.dao; |
||||
|
||||
import com.baomidou.mybatisplus.core.injector.AbstractMethod; |
||||
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector; |
@ -0,0 +1,12 @@ |
||||
package rition.service.collector.dao.mapper; |
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
||||
import org.apache.ibatis.annotations.Mapper; |
||||
import rition.common.data.entity.MetricRecordEntity; |
||||
|
||||
import java.util.List; |
||||
|
||||
@Mapper |
||||
public interface MetricRecordMapper extends BaseMapper<MetricRecordEntity> { |
||||
int insertBatchSomeColumn(List<MetricRecordEntity> entityList); |
||||
} |
@ -0,0 +1,5 @@ |
||||
<?xml version="1.0" encoding="UTF-8" ?> |
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > |
||||
<mapper namespace="rition.service.collector.dao.mapper.MetricRecordMapper"> |
||||
|
||||
</mapper> |
@ -1,48 +0,0 @@ |
||||
package rition.service.panel; |
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
||||
import org.springframework.stereotype.Service; |
||||
import rition.common.data.dao.mapper.AlertMapper; |
||||
import rition.common.data.dto.PagingData; |
||||
import rition.common.data.entity.AlertEntity; |
||||
import rition.common.data.enums.Constants; |
||||
|
||||
@Service |
||||
public class AlertHistoryService { |
||||
private final AlertMapper alertMapper; |
||||
|
||||
public AlertHistoryService(AlertMapper alertMapper) { |
||||
this.alertMapper = alertMapper; |
||||
} |
||||
|
||||
/** |
||||
* 分页获取报警信息 |
||||
* |
||||
* @param instanceId 实例id |
||||
* @param pagingData 分页数据,查询完成后会对此对象进行修改 |
||||
* @return 分页数据,含结果,实际上与参数里的pagingData是同一个对象 |
||||
*/ |
||||
public PagingData<AlertEntity> getAlertHistory(String instanceId, PagingData<AlertEntity> pagingData) { |
||||
LambdaQueryWrapper<AlertEntity> query; |
||||
if (instanceId != null) { |
||||
query = new LambdaQueryWrapper<AlertEntity>() |
||||
.eq(AlertEntity::getInstanceId, instanceId) |
||||
.eq(AlertEntity::getStatus, Constants.EntityCommonStatus.NORMAL); |
||||
} else { |
||||
query = new LambdaQueryWrapper<AlertEntity>() |
||||
.eq(AlertEntity::getStatus, Constants.EntityCommonStatus.NORMAL); |
||||
} |
||||
|
||||
Page<AlertEntity> page = new Page<>(pagingData.getCurrentPage(), pagingData.getPageSize()); |
||||
var result = alertMapper.selectPage(page, query); |
||||
|
||||
pagingData.setData(result.getRecords()); |
||||
pagingData.setTotalResult(result.getTotal()); |
||||
pagingData.setTotalPage(result.getPages()); |
||||
pagingData.setCurrentPage(result.getCurrent()); |
||||
pagingData.setPageSize(result.getSize()); |
||||
|
||||
return pagingData; |
||||
} |
||||
} |
@ -1,78 +0,0 @@ |
||||
package rition.service.panel; |
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
||||
import com.github.yitter.idgen.YitIdHelper; |
||||
import org.springframework.data.redis.core.RedisTemplate; |
||||
import org.springframework.stereotype.Service; |
||||
import rition.common.data.dao.mapper.RuleMapper; |
||||
import rition.common.data.dto.service.AlertRuleDto; |
||||
import rition.common.data.dto.service.panel.AlertRuleAddDto; |
||||
import rition.common.data.entity.RuleEntity; |
||||
import rition.common.data.enums.Constants; |
||||
|
||||
import java.time.Instant; |
||||
import java.util.List; |
||||
|
||||
@Service |
||||
public class AlertRuleService { |
||||
|
||||
private final RuleMapper ruleMapper; |
||||
private final RedisTemplate<String, AlertRuleDto> redisTemplate; |
||||
|
||||
public AlertRuleService(RuleMapper ruleMapper, |
||||
RedisTemplate<String, AlertRuleDto> redisTemplate) { |
||||
this.ruleMapper = ruleMapper; |
||||
this.redisTemplate = redisTemplate; |
||||
} |
||||
|
||||
public void addAlertRule(AlertRuleAddDto alertRuleAddDto) { |
||||
RuleEntity ruleEntity = new RuleEntity(); |
||||
ruleEntity.setId(YitIdHelper.nextId()); |
||||
ruleEntity.setExpr(alertRuleAddDto.getExpression()); |
||||
ruleEntity.setCond(alertRuleAddDto.getCondition()); |
||||
ruleEntity.setThreshold(alertRuleAddDto.getThreshold()); |
||||
ruleEntity.setTrig(alertRuleAddDto.getTrigger()); |
||||
ruleEntity.setComment(alertRuleAddDto.getDescription()); |
||||
|
||||
var now = Instant.now(); |
||||
ruleEntity.setCreateTime(now); |
||||
ruleEntity.setUpdateTime(now); |
||||
ruleEntity.setStatus(Constants.EntityCommonStatus.NORMAL); |
||||
|
||||
ruleMapper.insert(ruleEntity); |
||||
|
||||
AlertRuleDto alertRuleDto = new AlertRuleDto(); |
||||
alertRuleDto.setId(ruleEntity.getId()); |
||||
alertRuleDto.setExpression(ruleEntity.getExpr()); |
||||
alertRuleDto.setCondition(ruleEntity.getCond()); |
||||
alertRuleDto.setThreshold(ruleEntity.getThreshold()); |
||||
alertRuleDto.setTrigger(ruleEntity.getTrig()); |
||||
alertRuleDto.setDescription(ruleEntity.getComment()); |
||||
alertRuleDto.setCreateTime(now); |
||||
|
||||
// 规则缓存到redis
|
||||
redisTemplate.opsForHash().put(Constants.RedisKeys.RULE_CACHE, alertRuleDto.getId().toString(), alertRuleDto); |
||||
} |
||||
|
||||
public List<RuleEntity> getRule() { |
||||
var query = new LambdaQueryWrapper<RuleEntity>() |
||||
.eq(RuleEntity::getStatus, Constants.EntityCommonStatus.NORMAL); |
||||
|
||||
return ruleMapper.selectList(query); |
||||
} |
||||
|
||||
public int deleteRule(Long ruleId) { |
||||
var query = new LambdaUpdateWrapper<RuleEntity>() |
||||
.set(RuleEntity::getStatus, Constants.EntityCommonStatus.DELETED) |
||||
.eq(RuleEntity::getId, ruleId) |
||||
.eq(RuleEntity::getStatus, Constants.EntityCommonStatus.NORMAL); |
||||
var updatedRows = ruleMapper.update(query); |
||||
// 删除相应的缓存
|
||||
if (updatedRows != 0) { |
||||
redisTemplate.opsForHash().delete(Constants.RedisKeys.RULE_CACHE, ruleId); |
||||
} |
||||
|
||||
return updatedRows; |
||||
} |
||||
} |
@ -1,64 +0,0 @@ |
||||
package rition.service.panel; |
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
||||
import com.github.yitter.idgen.YitIdHelper; |
||||
import org.springframework.stereotype.Service; |
||||
import rition.common.data.dao.mapper.ContractMapper; |
||||
import rition.common.data.dto.service.panel.ContractAddDto; |
||||
import rition.common.data.entity.ContractEntity; |
||||
import rition.common.data.enums.Constants; |
||||
import rition.common.exception.ServiceException; |
||||
import rition.common.exception.code.ServiceCode; |
||||
|
||||
import java.time.Instant; |
||||
import java.util.List; |
||||
|
||||
@Service |
||||
public class ContractService { |
||||
|
||||
private final ContractMapper contractMapper; |
||||
|
||||
public ContractService(ContractMapper contractMapper) { |
||||
this.contractMapper = contractMapper; |
||||
} |
||||
|
||||
public List<ContractEntity> getContractList() { |
||||
var query = new LambdaQueryWrapper<ContractEntity>() |
||||
.eq(ContractEntity::getStatus, Constants.EntityCommonStatus.NORMAL) |
||||
.last("limit 100"); |
||||
|
||||
return contractMapper.selectList(query); |
||||
} |
||||
|
||||
private static final int MAX_CONTRACT_NUM = 20; |
||||
|
||||
public void addContract(ContractAddDto contractAddDto) { |
||||
var countQuery = new LambdaQueryWrapper<ContractEntity>() |
||||
.eq(ContractEntity::getStatus, Constants.EntityCommonStatus.NORMAL); |
||||
var count = contractMapper.selectCount(countQuery); |
||||
if (count > MAX_CONTRACT_NUM) { |
||||
ServiceException.error(ServiceCode.ContractTooManyData); |
||||
} |
||||
|
||||
var now = Instant.now(); |
||||
var entity = ContractEntity.builder() |
||||
.id(YitIdHelper.nextId()) |
||||
.contract(contractAddDto.getContract()) |
||||
.type(contractAddDto.getType()) |
||||
.createTime(now) |
||||
.updateTime(now) |
||||
.status(Constants.EntityCommonStatus.NORMAL) |
||||
.build(); |
||||
|
||||
contractMapper.insert(entity); |
||||
} |
||||
|
||||
public void deleteContract(Long id) { |
||||
var query = new LambdaUpdateWrapper<ContractEntity>() |
||||
.set(ContractEntity::getStatus, Constants.EntityCommonStatus.DELETED) |
||||
.eq(ContractEntity::getId, id) |
||||
.eq(ContractEntity::getStatus, Constants.EntityCommonStatus.NORMAL); |
||||
contractMapper.update(query); |
||||
} |
||||
} |
@ -1,52 +0,0 @@ |
||||
package rition.service.panel; |
||||
|
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.stereotype.Service; |
||||
import rition.common.data.dao.mapper.MetricRecordMapper; |
||||
import rition.common.data.entity.MetricRecordEntity; |
||||
|
||||
import java.time.Instant; |
||||
import java.util.List; |
||||
|
||||
@Slf4j |
||||
@Service |
||||
public class MetricService { |
||||
|
||||
private final MetricRecordMapper metricRecordMapper; |
||||
|
||||
public MetricService(MetricRecordMapper metricRecordMapper) { |
||||
this.metricRecordMapper = metricRecordMapper; |
||||
} |
||||
|
||||
private static final long HOUR = 3600 * 1000; |
||||
private static final long DAY = 24 * 3600 * 1000; |
||||
private static final long MONTH = 30L * 24 * 3600 * 1000; |
||||
|
||||
/** |
||||
* 按时间范围获取监测数据 |
||||
* |
||||
* @param instanceId 实例id |
||||
* @param metricItems 监测指标项 |
||||
* @param start 开始时间 |
||||
* @param end 结束时间 |
||||
* @return 监测指标数据,指标数据为给定的指标平均统计 |
||||
*/ |
||||
public List<MetricRecordEntity> getMetricDataRange(String instanceId, |
||||
List<String> metricItems, |
||||
Instant start, Instant end) { |
||||
// 时间跨度小于6小时:时间粒度为1分钟
|
||||
// 时间跨度大于6小时:时间粒度为5分钟
|
||||
// 时间跨度大于12小时:时间粒度为10分钟
|
||||
// 时间跨度超过15天:时间粒度为小时
|
||||
var diff = end.minusMillis(start.toEpochMilli()).toEpochMilli(); |
||||
if (diff < HOUR * 6) { |
||||
return metricRecordMapper.getMetricDataGroupByMinute(instanceId, metricItems, start, end); |
||||
} else if (diff < HOUR * 12) { |
||||
return metricRecordMapper.getMetricDataGroupBySomeMinute(5, instanceId, metricItems, start, end); |
||||
} else if (diff < DAY * 15) { |
||||
return metricRecordMapper.getMetricDataGroupBySomeMinute(10, instanceId, metricItems, start, end); |
||||
} else { |
||||
return metricRecordMapper.getMetricDataGroupByHour(instanceId, metricItems, start, end); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,7 @@ |
||||
package rition.service.panel; |
||||
|
||||
import org.springframework.stereotype.Service; |
||||
|
||||
@Service |
||||
public class PanelService { |
||||
} |
@ -1,6 +0,0 @@ |
||||
spring: |
||||
datasource: |
||||
driver-class-name: com.mysql.cj.jdbc.Driver |
||||
url: jdbc:mysql://127.0.0.1:3306/rition?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true |
||||
username: root |
||||
password: Test2333! |
Loading…
Reference in new issue