Skip to content

Commit

Permalink
feat: add influx support
Browse files Browse the repository at this point in the history
  • Loading branch information
liumeng committed Jul 11, 2024
1 parent b4cb335 commit 6b9151a
Show file tree
Hide file tree
Showing 19 changed files with 1,683 additions and 117 deletions.
6 changes: 6 additions & 0 deletions sentinel-dashboard/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<resource.delimiter>@</resource.delimiter>
<spring.boot.version>2.5.12</spring.boot.version>
<curator.version>4.0.1</curator.version>
<influxdb-java.version>2.24</influxdb-java.version>
</properties>

<dependencies>
Expand Down Expand Up @@ -96,6 +97,11 @@
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>org.influxdb</groupId>
<artifactId>influxdb-java</artifactId>
<version>${influxdb-java.version}</version>
</dependency>

<!-- for Nacos rule publisher sample -->
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,12 @@
*/
package com.alibaba.csp.sentinel.dashboard.controller;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;

import com.alibaba.csp.sentinel.dashboard.datasource.entity.MetricEntity;
import com.alibaba.csp.sentinel.dashboard.domain.Result;
import com.alibaba.csp.sentinel.dashboard.domain.vo.MetricVo;
import com.alibaba.csp.sentinel.dashboard.repository.metric.MetricsRepository;
import com.alibaba.csp.sentinel.util.StringUtil;
import org.apache.commons.lang.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -34,22 +29,19 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.csp.sentinel.util.StringUtil;

import com.alibaba.csp.sentinel.dashboard.datasource.entity.MetricEntity;
import com.alibaba.csp.sentinel.dashboard.domain.vo.MetricVo;
import java.sql.Date;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
* @author leyou
*/
@Controller
@RequestMapping(value = "/metric", produces = MediaType.APPLICATION_JSON_VALUE)
@RequestMapping(value = "/metric", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public class MetricController {

private static Logger logger = LoggerFactory.getLogger(MetricController.class);

private static final long maxQueryIntervalMs = 1000 * 60 * 60;

@Autowired
private MetricsRepository<MetricEntity> metricStore;

Expand All @@ -59,7 +51,9 @@ public Result<?> queryTopResourceMetric(final String app,
Integer pageIndex,
Integer pageSize,
Boolean desc,
Long startTime, Long endTime, String searchKey) {
Long startTime, Long endTime,
String searchKey) {

if (StringUtil.isEmpty(app)) {
return Result.ofFail(-1, "app can't be null or empty");
}
Expand All @@ -78,14 +72,13 @@ public Result<?> queryTopResourceMetric(final String app,
if (endTime == null) {
endTime = System.currentTimeMillis();
}
if (startTime == null) {
if (startTime == null || startTime >= endTime) {
startTime = endTime - 1000 * 60 * 5;
}
if (endTime - startTime > maxQueryIntervalMs) {
return Result.ofFail(-1, "time intervalMs is too big, must <= 1h");
}
List<String> resources = metricStore.listResourcesOfApp(app);
logger.debug("queryTopResourceMetric(), resources.size()={}", resources.size());
if (logger.isDebugEnabled()) {
logger.debug("queryTopResourceMetric(), resources.size()={}", resources.size());
}

if (resources == null || resources.isEmpty()) {
return Result.ofSuccess(null);
Expand All @@ -111,6 +104,14 @@ public Result<?> queryTopResourceMetric(final String app,
final Map<String, Iterable<MetricVo>> map = new ConcurrentHashMap<>();
logger.debug("topResource={}", topResource);
long time = System.currentTimeMillis();

if (logger.isDebugEnabled()) {
logger.debug("queryByAppAndResourceBetween {} and {}",
DateFormatUtils.format(new Date(startTime),
"yyyy-MM-dd HH:mm:ss", Locale.CHINA),
DateFormatUtils.format(new Date(endTime),
"yyyy-MM-dd HH:mm:ss", Locale.CHINA));
}
for (final String resource : topResource) {
List<MetricEntity> entities = metricStore.queryByAppAndResourceBetween(
app, resource, startTime, endTime);
Expand Down Expand Up @@ -147,14 +148,12 @@ public Result<?> queryByAppAndResource(String app, String identity, Long startTi
if (endTime == null) {
endTime = System.currentTimeMillis();
}
if (startTime == null) {
startTime = endTime - 1000 * 60;
}
if (endTime - startTime > maxQueryIntervalMs) {
return Result.ofFail(-1, "time intervalMs is too big, must <= 1h");
if (startTime == null || startTime >= endTime) {
startTime = endTime - 1000 * 60 * 5;
}

List<MetricEntity> entities = metricStore.queryByAppAndResourceBetween(
app, identity, startTime, endTime);
app, identity, startTime, endTime);
List<MetricVo> vos = MetricVo.fromMetricEntities(entities, identity);
return Result.ofSuccess(sortMetricVoAndDistinct(vos));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.alibaba.csp.sentinel.dashboard.metric;

import com.alibaba.csp.sentinel.dashboard.datasource.entity.MetricEntity;

/**
* 监控数据发送器
*
* @author <a href="mailto:shiyindaxiaojie@gmail.com">gyl</a>
* @since 1.8.2
*/
public interface MetricSender {

void send(Iterable<MetricEntity> iterable);
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import com.alibaba.csp.sentinel.dashboard.datasource.entity.MetricEntity;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.csp.sentinel.util.TimeUtil;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
Expand All @@ -37,6 +38,7 @@
* @author Eric Zhao
*/
@Component
@ConditionalOnProperty(name = "sentinel.metrics.type", havingValue = "inmemory")
public class InMemoryMetricsRepository implements MetricsRepository<MetricEntity> {

private static final long MAX_METRIC_LIVE_TIME_MS = 1000 * 60 * 5;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package com.alibaba.csp.sentinel.dashboard.repository.metric.influxdb;

import okhttp3.OkHttpClient;
import org.influxdb.InfluxDB;
import org.influxdb.InfluxDBFactory;
import org.influxdb.dto.*;
import org.influxdb.impl.InfluxDBResultMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Component
@ConditionalOnProperty(name = "sentinel.metrics.type", havingValue = "influxdb")
public class InfluxDBConnect {
private static final Logger log = LoggerFactory.getLogger(InfluxDBConnect.class);

private final InfluxDBMetricsProperties influxDBMetricsProperties;
private final OkHttpClientProperties okHttpClientProperties;
private InfluxDB influxDB;
private InfluxDBResultMapper resultMapper = new InfluxDBResultMapper();

public InfluxDBConnect(InfluxDBMetricsProperties influxDBMetricsProperties, OkHttpClientProperties okHttpClientProperties) {
this.influxDBMetricsProperties = influxDBMetricsProperties;
this.okHttpClientProperties = okHttpClientProperties;
build();
}

private void build() {

OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder()
.connectTimeout(okHttpClientProperties.getConnectTimeout(), TimeUnit.SECONDS)
.readTimeout(okHttpClientProperties.getReadTimeout(), TimeUnit.SECONDS)
.writeTimeout(okHttpClientProperties.getWriteTimeout(), TimeUnit.SECONDS)
.retryOnConnectionFailure(okHttpClientProperties.getRetryOnConnectionFailure());
if (influxDBMetricsProperties.getUsername() == null || influxDBMetricsProperties.getPassword() == null) {
influxDB = InfluxDBFactory.connect(influxDBMetricsProperties.getUrl(), okHttpClient);
} else {
influxDB = InfluxDBFactory.connect(influxDBMetricsProperties.getUrl(),
influxDBMetricsProperties.getUsername(), influxDBMetricsProperties.getPassword(), okHttpClient);
}
Pong pong = influxDB.ping();
if (pong != null) {
log.info("pong:" + pong + ",连接成功!");
} else {
log.info("连接失败");
}

}

public void insert(String dbName, Point point) {
influxDB.write(dbName, influxDBMetricsProperties.getRetentionPolicy(), point);
}

public void insert(BatchPoints batchPoints) {
influxDB.write(batchPoints);
}

public <T> List<T> queryList(String database, String query, Class<T> clazz) {
QueryResult queryResult = influxDB.query(new Query(query, database));
return resultMapper.toPOJO(queryResult, clazz);
}

public <T> List<T> queryList(String database, String query, Map<String, Object> paramMap, Class<T> clazz) {
BoundParameterQuery.QueryBuilder queryBuilder = BoundParameterQuery.QueryBuilder.newQuery(query);
queryBuilder.forDatabase(database);

if (paramMap != null && !paramMap.isEmpty()) {
Set<Map.Entry<String, Object>> entries = paramMap.entrySet();
for (Map.Entry<String, Object> entry : entries) {
queryBuilder.bind(entry.getKey(), entry.getValue());
}
}

QueryResult queryResult = influxDB.query(queryBuilder.create());
return resultMapper.toPOJO(queryResult, clazz);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.alibaba.csp.sentinel.dashboard.repository.metric.influxdb;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@ConditionalOnProperty(name = "sentinel.metrics.type", havingValue = "influxdb")
@EnableConfigurationProperties({InfluxDBMetricsProperties.class, OkHttpClientProperties.class})
@Configuration(proxyBeanMethods = false)
public class InfluxDBMetricsAutoConfiguration {
private static final Logger log= LoggerFactory.getLogger(InfluxDBMetricsAutoConfiguration.class);

public static final String AUTOWIRED_INFLUX_DB_METRICS_ENTITY_REPOSITORY = "Autowired InfluxDBMetricsEntityRepository";

private final InfluxDBMetricsProperties influxDBMetricsProperties;

private final InfluxDBConnect influxDBClient;

public InfluxDBMetricsAutoConfiguration(InfluxDBMetricsProperties influxDBMetricsProperties,
InfluxDBConnect influxDBClient) {
this.influxDBMetricsProperties=influxDBMetricsProperties;
this.influxDBClient=influxDBClient;
}

@Bean
public InfluxDBMetricsEntityRepository influxDBMetricsEntityRepository() {
log.debug(AUTOWIRED_INFLUX_DB_METRICS_ENTITY_REPOSITORY);
return new InfluxDBMetricsEntityRepository(influxDBMetricsProperties, influxDBClient);
}
}
Loading

0 comments on commit 6b9151a

Please sign in to comment.