提交 c58479a4 编写于 作者: H haoxr

feat:添加控制台IP统计数据

上级 174d78a9
......@@ -6,7 +6,6 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import com.youlai.common.redis.utils.RedisUtils;
import com.youlai.common.web.util.BeanMapperUtils;
import com.youlai.mall.pms.api.ProductFeignService;
import com.youlai.mall.sms.pojo.domain.SmsSeckillSession;
import com.youlai.mall.sms.pojo.domain.SmsSeckillSkuRelation;
import com.youlai.mall.sms.pojo.to.SeckillSkuRedisTO;
......@@ -48,8 +47,6 @@ public class SeckillServiceImpl implements SeckillService {
@Autowired
private RedisUtils redisUtils;
@Resource
private ProductFeignService productFeignService;
@Autowired
private RedissonClient redissonClient;
......
......@@ -13,6 +13,7 @@ import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
......@@ -39,10 +40,43 @@ public class DashboardController {
ElasticSearchService elasticSearchService;
@ApiOperation(value = "登录次数统计", httpMethod = "GET")
@GetMapping("/login_counts")
public Result loginCounts() {
int days = 10; //统计天数
@ApiOperation(value = "控制台数据", httpMethod = "GET")
@GetMapping
public Result data() {
Map<String, Object> data = new HashMap<>();
// 今日IP数
long todayIpCount = getTodayIpCount();
data.put("todayIpCount", todayIpCount);
// 总IP数
long totalIpCount = getTotalIpCount();
data.put("totalIpCount", totalIpCount);
// 登录统计
int days = 10; // 统计天数
Map loginCount = getLoginCount(days);
data.put("loginCount", loginCount);
return Result.success(data);
}
private long getTodayIpCount() {
String date = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("date", date);
String indexName = ESConstants.LOGIN_INDEX_PATTERN + date; //索引名称
long todayIpCount = elasticSearchService.countDistinct(termQueryBuilder, "clientIP.keyword", indexName);
return todayIpCount;
}
private long getTotalIpCount() {
long totalIpCount = elasticSearchService.countDistinct(null, "clientIP.keyword", ESConstants.LOGIN_INDEX_PATTERN);
return totalIpCount;
}
private Map getLoginCount(int days) {
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
......@@ -62,16 +96,17 @@ public class DashboardController {
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery()
.must(rangeQueryBuilder);
// 总数统计
Map<String, Long> totalCountMap = elasticSearchService.dateHistogram(
boolQueryBuilder,
"date", // 根据date字段聚合统计登录数 logback-spring.xml 中的自定义扩展字段 date
DateHistogramInterval.days(1),
indices);
boolQueryBuilder,
"date", // 根据date字段聚合统计登录数 logback-spring.xml 中的自定义扩展字段 date
DateHistogramInterval.days(1),
indices);
// 当前用户统计
HttpServletRequest request = RequestUtils.getRequest();
String clientIP = IPUtils.getClientIP(request);
String clientIP = IPUtils.getIpAddr(request);
boolQueryBuilder.must(QueryBuilders.termQuery("clientIP", clientIP));
Map<String, Long> myCountMap = elasticSearchService.dateHistogram(boolQueryBuilder, "date", DateHistogramInterval.days(1), indices);
......@@ -79,7 +114,7 @@ public class DashboardController {
// 组装echarts数据
Long[] totalCount = new Long[days];
Long[] myCount= new Long[days];
Long[] myCount = new Long[days];
Arrays.sort(xData);// 默认升序
for (int i = 0; i < days; i++) {
......@@ -93,7 +128,7 @@ public class DashboardController {
map.put("totalCount", totalCount); // 总数
map.put("myCount", myCount); // 我的
return Result.success(map);
return map;
}
......
......@@ -18,9 +18,6 @@ import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
/**
......@@ -36,7 +33,6 @@ public class LoginRecordController {
ElasticSearchService elasticSearchService;
@ApiOperation(value = "列表分页", httpMethod = "GET")
@ApiImplicitParams({
@ApiImplicitParam(name = "page", value = "页码", defaultValue = "1", paramType = "query", dataType = "Long"),
......
......@@ -180,7 +180,7 @@
<entryPoint>["java","-jar","${project.build.finalName}.jar"]</entryPoint>
<!-- 指定远程 Docker API地址 -->
<dockerHost>https://f.youlai.store:2376</dockerHost>
<dockerHost>http://f.youlai.store:2375</dockerHost>
<!-- 指定tls证书的目录 -->
<dockerCertPath>C:\cert\docker\f.youlai.store</dockerCertPath>
......
......@@ -28,6 +28,8 @@ import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;
import org.elasticsearch.search.aggregations.bucket.histogram.Histogram;
import org.elasticsearch.search.aggregations.bucket.histogram.ParsedDateHistogram;
import org.elasticsearch.search.aggregations.metrics.CardinalityAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.ParsedCardinality;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.springframework.stereotype.Service;
......@@ -52,12 +54,35 @@ public class ElasticSearchService {
// 构造请求
CountRequest countRequest = new CountRequest(indices);
countRequest.query(queryBuilder);
// 执行请求
CountResponse countResponse = client.count(countRequest, RequestOptions.DEFAULT);
long count = countResponse.getCount();
return count;
}
@SneakyThrows
public long countDistinct(QueryBuilder queryBuilder, String field, String... indices) {
String distinctKey = "distinctKey"; // 自定义计数去重key,保证上下文一致
// 构造计数聚合 cardinality:集合中元素的个数
CardinalityAggregationBuilder aggregationBuilder = AggregationBuilders
.cardinality(distinctKey).field(field);
// 构造搜索源
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(queryBuilder).aggregation(aggregationBuilder);
// 构造请求
SearchRequest searchRequest = new SearchRequest(indices);
searchRequest.source(searchSourceBuilder);
// 执行请求
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
ParsedCardinality result = searchResponse.getAggregations().get(distinctKey);
return result.getValue();
}
/**
* 日期统计
*
......@@ -70,15 +95,17 @@ public class ElasticSearchService {
@SneakyThrows
public Map<String, Long> dateHistogram(QueryBuilder queryBuilder, String field, DateHistogramInterval interval, String... indices) {
// 构造AggregationBuilder
String dateHistogramKey = "dateHistogramKey"; // 自定义日期聚合key,保证上下文一致
// 构造聚合
AggregationBuilder aggregationBuilder = AggregationBuilders
.dateHistogram("dateHistogram") //自定义统计名,和下文获取需一致
.dateHistogram(dateHistogramKey) //自定义统计名,和下文获取需一致
.field(field) // 日期字段名
.format("yyyy-MM-dd") // 时间格式
.calendarInterval(interval) // 日历间隔,例: 1s->1秒 1d->1天 1w->1周 1M->1月 1y->1年 ...
.minDocCount(0); // 最小文档数,比该值小就忽略
// 构造SearchSourceBuilder
// 构造搜索源
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder
.query(queryBuilder)
......@@ -101,7 +128,7 @@ public class ElasticSearchService {
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
// 处理结果
ParsedDateHistogram dateHistogram = searchResponse.getAggregations().get("dateHistogram");
ParsedDateHistogram dateHistogram = searchResponse.getAggregations().get(dateHistogramKey);
Iterator<? extends Histogram.Bucket> iterator = dateHistogram.getBuckets().iterator();
......@@ -119,14 +146,6 @@ public class ElasticSearchService {
return list;
}
@SneakyThrows
public <T extends BaseDocument> List<T> search(QueryBuilder queryBuilder, Integer page, Integer size, Class<T> clazz, String... indices) {
List<T> list = this.search(queryBuilder, null, 1, ESConstants.DEFAULT_PAGE_SIZE, clazz, indices);
return list;
}
@SneakyThrows
public <T extends BaseDocument> List<T> search(QueryBuilder queryBuilder, SortBuilder sortBuilder, Integer page, Integer size, Class<T> clazz, String... indices) {
// 构造SearchSourceBuilder
......
......@@ -73,9 +73,9 @@ public class LoginLogAspect {
JSONObject jsonObject = JSONUtil.parseObj(result);
token = jsonObject.getStr("value");
}
String clientIP = IPUtils.getClientIP(request); // 客户端请求IP(注意:如果使用Nginx代理需配置)
log.info("222. {}",clientIP);
String region = IPUtils.ip2region(clientIP); // IP对应的城市信息
String clientIP = IPUtils.getIpAddr(request); // 客户端请求IP(注意:如果使用Nginx代理需配置)
String region = IPUtils.getCityInfo(clientIP); // IP对应的城市信息
// MDC 扩展logback字段,具体请看logback-spring.xml的自定义日志输出格式
MDC.put("elapsedTime", StrUtil.toString(elapsedTime));
......
......@@ -2,6 +2,7 @@ package com.youlai.common.web.util;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.logging.log4j.util.Strings;
import org.lionsoul.ip2region.DataBlock;
import org.lionsoul.ip2region.DbConfig;
......@@ -10,21 +11,25 @@ import org.lionsoul.ip2region.Util;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* IP工具类
*/
@Slf4j
public class IPUtils {
private static String LOCAL_IP="127.0.0.1";
private static String LOCAL_IP = "127.0.0.1";
/**
* 获取IP地址
* 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址
* 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址
*/
public static String getClientIP(HttpServletRequest request) {
public static String getIpAddr(HttpServletRequest request) {
String ip = null;
try {
if (request == null) {
......@@ -81,34 +86,61 @@ public class IPUtils {
/**
* 解析IP获取城市区域信息
*
* 根据IP获取城市信息
* @param ip
* @return
*/
public static String ip2region(String ip) {
public static String getCityInfo(String ip) {
return getCityInfo(ip, DbSearcher.BTREE_ALGORITHM);
}
public static String getCityInfo(String ip, Integer algorithm) {
if (Util.isIpAddress(ip) == false) {
return Strings.EMPTY;
}
log.info("1. {}",ip);
if(LOCAL_IP.equals(ip)){
if (LOCAL_IP.equals(ip)) {
return "本地访问";
}
log.info("2. {}",ip);
String filePath = IPUtils.class.getResource("/data/ip2region.db").getPath();
File file = new File(filePath);
String dbPath = IPUtils.class.getResource("/ip2region.db").getPath();
File file = new File(dbPath);
// 打成jar包时,ip2region.db文件路径发生变化,导致File无法读取,通过stream流方式复制生成临时的ip2region.db文件
if (file.exists() == false) {
return Strings.EMPTY;
String tmpdir = System.getProperties().getProperty("java.io.tmpdir");
dbPath = tmpdir + "/ip2region.db";
file = new File(dbPath);
if (file.exists() == false) {
try {
FileUtils.copyInputStreamToFile(IPUtils.class.getClassLoader()
.getResourceAsStream("classpath:ip2region.db"), file);
} catch (IOException e) {
e.printStackTrace();
}
}
}
log.info("3. {}",ip);
try {
DbConfig config = new DbConfig();
DbSearcher searcher = new DbSearcher(config, filePath);
log.info("4. {}",ip);
Method method = searcher.getClass().getMethod("btreeSearch", String.class);
DbSearcher searcher = new DbSearcher(config, dbPath);
Method method;
switch (algorithm) {
case DbSearcher.BTREE_ALGORITHM:
method = searcher.getClass().getMethod("btreeSearch", String.class);
break;
case DbSearcher.BINARY_ALGORITHM:
method = searcher.getClass().getMethod("binarySearch", String.class);
break;
case DbSearcher.MEMORY_ALGORITYM:
method = searcher.getClass().getMethod("memorySearch", String.class);
break;
default:
method = searcher.getClass().getMethod("memorySearch", String.class);
break;
}
DataBlock dataBlock = (DataBlock) method.invoke(searcher, ip);
log.info("5. {}",ip);
searcher.close();
return dataBlock.getRegion();
} catch (Exception e) {
......@@ -117,6 +149,4 @@ public class IPUtils {
return Strings.EMPTY;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册