Compare commits
7 Commits
main
...
dev-lensfr
Author | SHA1 | Date |
---|---|---|
lensfrex | 0ceb65be05 | 7 months ago |
lensfrex | 3fb9308f95 | 7 months ago |
lensfrex | c82c6d5799 | 7 months ago |
lensfrex | 41221a4bca | 7 months ago |
lensfrex | 91e03bee52 | 7 months ago |
lensfrex | 1152e9b42c | 7 months ago |
lensfrex | 5070304883 | 7 months ago |
@ -0,0 +1,36 @@ |
|||||||
|
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); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,39 @@ |
|||||||
|
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; |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
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; |
||||||
|
} |
@ -0,0 +1,29 @@ |
|||||||
|
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; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,54 @@ |
|||||||
|
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; |
||||||
|
} |
@ -0,0 +1,46 @@ |
|||||||
|
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,18 +1,138 @@ |
|||||||
package rition.backend.api.v1.panel; |
package rition.backend.api.v1.panel; |
||||||
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping; |
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.RequestBody; |
import org.springframework.web.bind.annotation.RequestBody; |
||||||
import org.springframework.web.bind.annotation.RequestMapping; |
import org.springframework.web.bind.annotation.RequestMapping; |
||||||
import org.springframework.web.bind.annotation.RestController; |
import org.springframework.web.bind.annotation.RestController; |
||||||
import rition.backend.api.v1.dto.request.MetricDataRequest; |
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.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 |
@RestController |
||||||
@RequestMapping("/panel/metrics") |
@RequestMapping("/panel/metrics") |
||||||
public class MetricsViewController { |
public class MetricsViewController { |
||||||
|
|
||||||
@GetMapping("/list") |
private final MetricService metricService; |
||||||
public Response<Object> getMetrics(@RequestBody MetricDataRequest metricDataRequest) { |
private final RedisTemplate<String, Object> redisTemplate; |
||||||
return Response.success(); |
|
||||||
|
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; |
||||||
} |
} |
||||||
} |
} |
||||||
|
@ -1,10 +0,0 @@ |
|||||||
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 { |
|
||||||
|
|
||||||
} |
|
@ -0,0 +1,35 @@ |
|||||||
|
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); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,7 @@ |
|||||||
|
package rition.backend.service.panel; |
||||||
|
|
||||||
|
import org.springframework.stereotype.Service; |
||||||
|
|
||||||
|
@Service |
||||||
|
public class PanelMetricService { |
||||||
|
} |
@ -0,0 +1,39 @@ |
|||||||
|
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())); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,21 @@ |
|||||||
|
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,4 +1,4 @@ |
|||||||
package rition.service.collector.dao; |
package rition.common.data.dao; |
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.injector.AbstractMethod; |
import com.baomidou.mybatisplus.core.injector.AbstractMethod; |
||||||
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector; |
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector; |
@ -0,0 +1,9 @@ |
|||||||
|
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> { |
||||||
|
} |
@ -0,0 +1,7 @@ |
|||||||
|
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> { |
||||||
|
} |
@ -0,0 +1,35 @@ |
|||||||
|
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 |
||||||
|
); |
||||||
|
} |
@ -0,0 +1,9 @@ |
|||||||
|
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> { |
||||||
|
} |
@ -0,0 +1,54 @@ |
|||||||
|
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; |
||||||
|
} |
||||||
|
} |
||||||
|
|
@ -0,0 +1,54 @@ |
|||||||
|
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,5 +1,5 @@ |
|||||||
|
|
||||||
package rition.common.data.dto; |
package rition.common.data.dto.service; |
||||||
|
|
||||||
import lombok.AllArgsConstructor; |
import lombok.AllArgsConstructor; |
||||||
import lombok.Builder; |
import lombok.Builder; |
@ -0,0 +1,36 @@ |
|||||||
|
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; |
||||||
|
} |
@ -0,0 +1,36 @@ |
|||||||
|
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; |
||||||
|
} |
@ -0,0 +1,17 @@ |
|||||||
|
package rition.common.data.dto.service.panel; |
||||||
|
|
||||||
|
import lombok.Data; |
||||||
|
|
||||||
|
@Data |
||||||
|
public class ContractAddDto { |
||||||
|
|
||||||
|
/** |
||||||
|
* 联系方式 |
||||||
|
*/ |
||||||
|
private String contract; |
||||||
|
|
||||||
|
/** |
||||||
|
* 联系方式类型 |
||||||
|
*/ |
||||||
|
private Integer type; |
||||||
|
} |
@ -0,0 +1,79 @@ |
|||||||
|
<?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> |
@ -0,0 +1,7 @@ |
|||||||
|
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) |
@ -1,8 +0,0 @@ |
|||||||
package rition.service.collector.configure; |
|
||||||
|
|
||||||
import org.springframework.context.annotation.Configuration; |
|
||||||
|
|
||||||
@Configuration |
|
||||||
public class MybatisPlusConfigure { |
|
||||||
|
|
||||||
} |
|
@ -1,12 +0,0 @@ |
|||||||
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); |
|
||||||
} |
|
@ -1,5 +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.service.collector.dao.mapper.MetricRecordMapper"> |
|
||||||
|
|
||||||
</mapper> |
|
@ -0,0 +1,48 @@ |
|||||||
|
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; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,78 @@ |
|||||||
|
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; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,64 @@ |
|||||||
|
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); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,52 @@ |
|||||||
|
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); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -1,7 +0,0 @@ |
|||||||
package rition.service.panel; |
|
||||||
|
|
||||||
import org.springframework.stereotype.Service; |
|
||||||
|
|
||||||
@Service |
|
||||||
public class PanelService { |
|
||||||
} |
|
@ -0,0 +1,6 @@ |
|||||||
|
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