zhangzhiqiang
2 years ago
11 changed files with 411 additions and 32 deletions
@ -0,0 +1,95 @@ |
|||||
|
package org.nl.config; |
||||
|
|
||||
|
import com.alibaba.druid.filter.FilterChain; |
||||
|
import com.alibaba.druid.filter.FilterEventAdapter; |
||||
|
import com.alibaba.druid.proxy.jdbc.JdbcParameter; |
||||
|
import com.alibaba.druid.proxy.jdbc.PreparedStatementProxy; |
||||
|
import com.alibaba.druid.proxy.jdbc.ResultSetProxy; |
||||
|
import com.alibaba.druid.proxy.jdbc.StatementProxy; |
||||
|
import com.alibaba.druid.sql.SQLUtils; |
||||
|
import com.alibaba.druid.util.JdbcUtils; |
||||
|
import com.mysql.cj.jdbc.result.ResultSetImpl; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.apache.commons.lang3.StringUtils; |
||||
|
import org.slf4j.MDC; |
||||
|
|
||||
|
import java.sql.SQLException; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.Collection; |
||||
|
import java.util.List; |
||||
|
|
||||
|
/* |
||||
|
* @author ZZQ |
||||
|
* @Date 2023/2/10 11:27 上午 |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
public class DruidFilter extends FilterEventAdapter { |
||||
|
|
||||
|
@Override |
||||
|
public int preparedStatement_executeUpdate(FilterChain chain, PreparedStatementProxy statement) throws SQLException { |
||||
|
|
||||
|
return super.preparedStatement_executeUpdate(chain, statement); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql) throws SQLException { |
||||
|
|
||||
|
return super.statement_executeUpdate(chain, statement, sql); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void statementExecuteAfter(StatementProxy statement, String sql, boolean result) { |
||||
|
String traceId = MDC.get("traceId"); |
||||
|
int size = statement.getParametersSize(); |
||||
|
String executeSql = sql; |
||||
|
int count = 0; |
||||
|
try { |
||||
|
count=statement.getUpdateCount(); |
||||
|
}catch (Exception ex){ } |
||||
|
if (StringUtils.isNotEmpty(traceId) && count>0) { |
||||
|
if (size > 0) { |
||||
|
Collection<JdbcParameter> values = statement.getParameters().values(); |
||||
|
List<Object> params = new ArrayList<>(); |
||||
|
for (JdbcParameter value : values) { |
||||
|
params.add(value.getValue()); |
||||
|
} |
||||
|
executeSql = SQLUtils.format(executeSql, JdbcUtils.MYSQL, params); |
||||
|
} |
||||
|
log.info("[----SQL----][update][ SQL: {} ]", executeSql); |
||||
|
} |
||||
|
super.statementExecuteAfter(statement, sql, result); |
||||
|
} |
||||
|
@Override |
||||
|
public ResultSetProxy statement_getResultSet(FilterChain chain, StatementProxy statement) throws SQLException { |
||||
|
ResultSetProxy rs = super.statement_getResultSet(chain, statement); |
||||
|
String executeSql = statement.getLastExecuteSql(); |
||||
|
String traceId = MDC.get("traceId"); |
||||
|
if (StringUtils.isNotEmpty(traceId)){ |
||||
|
int result = 0; |
||||
|
if (rs != null) { |
||||
|
ResultSetImpl rss = rs.getResultSetRaw().unwrap(ResultSetImpl.class); |
||||
|
result = rss.getRows().size(); |
||||
|
} |
||||
|
try { |
||||
|
int size = statement.getParametersSize(); |
||||
|
if (size>0){ |
||||
|
Collection<JdbcParameter> values = statement.getParameters().values(); |
||||
|
List<Object> params = new ArrayList<>(); |
||||
|
for (JdbcParameter value : values) { |
||||
|
params.add(value.getValue()); |
||||
|
} |
||||
|
executeSql = SQLUtils.format(executeSql, JdbcUtils.MYSQL, params); |
||||
|
} |
||||
|
}catch (Exception ex){ |
||||
|
log.warn("[-SQL解析异常-][{}]",ex.getMessage()); |
||||
|
} |
||||
|
log.info("[----SQL----][select][执行结果:{}][ SQL: {} ]",result, executeSql); |
||||
|
} |
||||
|
return rs; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
} |
@ -0,0 +1,37 @@ |
|||||
|
package org.nl.monitor.controller.log; |
||||
|
|
||||
|
import io.swagger.annotations.ApiOperation; |
||||
|
import lombok.RequiredArgsConstructor; |
||||
|
import org.nl.monitor.server.LogService; |
||||
|
import org.nl.monitor.server.log.dto.LogQuery; |
||||
|
import org.springframework.http.HttpStatus; |
||||
|
import org.springframework.http.ResponseEntity; |
||||
|
import org.springframework.web.bind.annotation.*; |
||||
|
|
||||
|
/** |
||||
|
* @author ldjun |
||||
|
* @version 1.0 |
||||
|
* @date 2023年01月29日 18:55 |
||||
|
* @desc desc |
||||
|
*/ |
||||
|
|
||||
|
@RestController |
||||
|
@RequiredArgsConstructor |
||||
|
@RequestMapping("/api/esLog") |
||||
|
public class LogController { |
||||
|
private final LogService esLogService; |
||||
|
|
||||
|
|
||||
|
@GetMapping("/labels/{type}") |
||||
|
@ApiOperation("获取标签") |
||||
|
public ResponseEntity<Object> labelsValues(@PathVariable String type) { |
||||
|
return new ResponseEntity<>(esLogService.getLabelsValues(type), HttpStatus.OK); |
||||
|
} |
||||
|
|
||||
|
@PostMapping("/query") |
||||
|
@ApiOperation("日志查询") |
||||
|
public ResponseEntity<Object> queryAll(@RequestBody LogQuery query) { |
||||
|
return new ResponseEntity<>(esLogService.query(query), HttpStatus.OK); |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,26 @@ |
|||||
|
package org.nl.monitor.server; |
||||
|
|
||||
|
import com.alibaba.fastjson.JSONArray; |
||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
||||
|
import org.nl.monitor.server.log.dto.LogQuery; |
||||
|
|
||||
|
/** |
||||
|
* @author ldjun |
||||
|
* @version 1.0 |
||||
|
* @date 2023年02月07日 14:34 |
||||
|
* @desc desc |
||||
|
*/ |
||||
|
public interface LogService { |
||||
|
/** |
||||
|
* 获取labels和values树 |
||||
|
* @return |
||||
|
*/ |
||||
|
JSONArray getLabelsValues(String type); |
||||
|
|
||||
|
/** |
||||
|
* 日志查询 |
||||
|
* @param logQuery |
||||
|
* @return |
||||
|
*/ |
||||
|
Page query(LogQuery logQuery); |
||||
|
} |
@ -0,0 +1,46 @@ |
|||||
|
package org.nl.monitor.server.log.dto; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
|
||||
|
import java.util.Date; |
||||
|
|
||||
|
/* |
||||
|
* @author ZZQ |
||||
|
* @Date 2023/2/8 5:18 下午 |
||||
|
*/ |
||||
|
@Data |
||||
|
public class LogQuery { |
||||
|
/** |
||||
|
* 创建时间范围查询 |
||||
|
*/ |
||||
|
private Date startTime; |
||||
|
private Date endTime; |
||||
|
/** |
||||
|
* 追踪id |
||||
|
*/ |
||||
|
private String traceId; |
||||
|
/** |
||||
|
* 日志内容模糊匹配 |
||||
|
*/ |
||||
|
private String message; |
||||
|
/** |
||||
|
* 日志级别 |
||||
|
*/ |
||||
|
private String logLevel; |
||||
|
/** |
||||
|
* 系统标签 |
||||
|
*/ |
||||
|
private String system; |
||||
|
/** |
||||
|
* 是否只查询Http相关请求 |
||||
|
*/ |
||||
|
private Boolean isRequest = Boolean.TRUE; |
||||
|
/** |
||||
|
* 是否过滤wql日志 |
||||
|
*/ |
||||
|
private Boolean filterSql = Boolean.TRUE; |
||||
|
|
||||
|
private Integer size = 20; |
||||
|
|
||||
|
private Integer page = 1; |
||||
|
} |
@ -0,0 +1,28 @@ |
|||||
|
package org.nl.monitor.server.log.dto; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
import org.springframework.data.annotation.Id; |
||||
|
import org.springframework.data.elasticsearch.annotations.Document; |
||||
|
|
||||
|
/* |
||||
|
* @author ZZQ |
||||
|
* @Date 2023/2/8 4:06 下午 |
||||
|
*/ |
||||
|
@Document(indexName = "lms_log", type = "lms_log") |
||||
|
@Data |
||||
|
public class LogRepositoryDTO { |
||||
|
|
||||
|
private String message; |
||||
|
private String host; |
||||
|
private String logLevel; |
||||
|
private String logger; |
||||
|
private String requestTime; |
||||
|
private String requestIp; |
||||
|
@Id |
||||
|
private String id; |
||||
|
private String traceId; |
||||
|
private String requestMethod; |
||||
|
private String thread; |
||||
|
private String system; |
||||
|
|
||||
|
} |
@ -0,0 +1,115 @@ |
|||||
|
package org.nl.monitor.server.log.impl; |
||||
|
|
||||
|
import com.alibaba.fastjson.JSONArray; |
||||
|
import com.alibaba.fastjson.JSONObject; |
||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
||||
|
import lombok.RequiredArgsConstructor; |
||||
|
import org.apache.commons.lang3.StringUtils; |
||||
|
import org.apache.poi.ss.formula.functions.T; |
||||
|
import org.elasticsearch.action.search.SearchResponse; |
||||
|
import org.elasticsearch.index.query.BoolQueryBuilder; |
||||
|
import org.elasticsearch.index.query.QueryBuilders; |
||||
|
import org.elasticsearch.script.Script; |
||||
|
import org.elasticsearch.search.aggregations.AggregationBuilders; |
||||
|
import org.elasticsearch.search.aggregations.Aggregations; |
||||
|
import org.elasticsearch.search.aggregations.bucket.terms.Terms; |
||||
|
import org.nl.monitor.server.LogService; |
||||
|
import org.nl.monitor.server.log.dto.LogQuery; |
||||
|
import org.nl.monitor.server.log.dto.LogRepositoryDTO; |
||||
|
import org.nl.monitor.server.log.repository.LogRepository; |
||||
|
import org.springframework.data.domain.PageRequest; |
||||
|
import org.springframework.data.domain.Sort; |
||||
|
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; |
||||
|
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl; |
||||
|
import org.springframework.data.elasticsearch.core.query.FetchSourceFilter; |
||||
|
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
import org.springframework.util.CollectionUtils; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
/** |
||||
|
* @author ldjun |
||||
|
* @version 1.0 |
||||
|
* @date 2023年02月07日 14:35 |
||||
|
* @desc desc |
||||
|
*/ |
||||
|
@Service |
||||
|
@RequiredArgsConstructor |
||||
|
public class LogServiceImpl implements LogService { |
||||
|
|
||||
|
private final LogRepository esLogRepository; |
||||
|
|
||||
|
private final ElasticsearchRestTemplate elasticsearchRestTemplate; |
||||
|
|
||||
|
@Override |
||||
|
public Page query(LogQuery logQuery){ |
||||
|
Page<T> page = new Page<>(); |
||||
|
if (logQuery != null){ |
||||
|
BoolQueryBuilder query = QueryBuilders.boolQuery(); //requestMethod
|
||||
|
extractedParam(logQuery, query); |
||||
|
Iterable<LogRepositoryDTO> all = esLogRepository.search(query, PageRequest.of(logQuery.getPage()-1,logQuery.getSize(), Sort.by("@timestamp").descending())); |
||||
|
page.setRecords(((AggregatedPageImpl) all).getContent()); |
||||
|
page.setTotal(((AggregatedPageImpl) all).getTotalElements()); |
||||
|
page.setPages(logQuery.getPage()); |
||||
|
page.setSize(logQuery.getSize()); |
||||
|
} |
||||
|
return page; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
private void extractedParam(LogQuery logQuery, BoolQueryBuilder query) { |
||||
|
if (StringUtils.isNotEmpty(logQuery.getLogLevel())){ |
||||
|
query.must().add(QueryBuilders.matchQuery("logLevel", logQuery.getLogLevel())); |
||||
|
} |
||||
|
if (StringUtils.isNotEmpty(logQuery.getSystem())){ |
||||
|
query.must().add(QueryBuilders.matchQuery("system", logQuery.getSystem())); |
||||
|
} |
||||
|
if (logQuery.getIsRequest()){ |
||||
|
query.must().add(QueryBuilders.existsQuery("requestMethod")); |
||||
|
} |
||||
|
if (logQuery.getFilterSql()){ |
||||
|
query.mustNot().add(QueryBuilders.wildcardQuery("logger","org.nl.modules.wql.core.engine.*")); |
||||
|
} |
||||
|
query.mustNot().add(QueryBuilders.matchPhraseQuery("logger","org.elasticsearch.client.RestClient")); |
||||
|
if (StringUtils.isNotEmpty(logQuery.getTraceId())){ |
||||
|
query.must().add(QueryBuilders.matchQuery("traceId", logQuery.getTraceId())); |
||||
|
} |
||||
|
if (StringUtils.isNotEmpty(logQuery.getMessage())){ |
||||
|
query.must().add(QueryBuilders.matchQuery("message", logQuery.getMessage()).minimumShouldMatch("80%")); |
||||
|
} |
||||
|
if (logQuery.getEndTime()!=null ){ |
||||
|
String script = "doc['@timestamp'].value.millis < " + logQuery.getEndTime().getTime() + "L"; |
||||
|
query.must().add(QueryBuilders.scriptQuery(new Script(script))); |
||||
|
} |
||||
|
if (logQuery.getStartTime()!=null){ |
||||
|
String script = "doc['@timestamp'].value.millis > " + logQuery.getStartTime().getTime() + "L"; |
||||
|
query.must().add(QueryBuilders.scriptQuery(new Script(script))); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
@Override |
||||
|
public JSONArray getLabelsValues(String type) { |
||||
|
JSONArray result = new JSONArray(); |
||||
|
FetchSourceFilter fetchSourceFilter = new FetchSourceFilter(new String[]{type}, null); |
||||
|
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder(); |
||||
|
queryBuilder.withCollapseField(type+".keyword"); |
||||
|
queryBuilder.withSourceFilter(fetchSourceFilter); |
||||
|
queryBuilder.addAggregation(AggregationBuilders.terms(type).field(type+".keyword").size(100)); |
||||
|
Aggregations agg = elasticsearchRestTemplate.query(queryBuilder.build(), SearchResponse::getAggregations); |
||||
|
Terms terms = agg.get(type); |
||||
|
List<? extends Terms.Bucket> buckets = terms.getBuckets(); |
||||
|
if (!CollectionUtils.isEmpty(buckets)){ |
||||
|
buckets.stream().map(Terms.Bucket::getKeyAsString).forEach(v-> { |
||||
|
JSONObject item = new JSONObject(); |
||||
|
item.put("label", v); |
||||
|
item.put("value", v); |
||||
|
result.add(item); |
||||
|
}); |
||||
|
} |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,14 @@ |
|||||
|
package org.nl.monitor.server.log.repository; |
||||
|
|
||||
|
import org.nl.monitor.server.log.dto.LogRepositoryDTO; |
||||
|
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; |
||||
|
import org.springframework.stereotype.Repository; |
||||
|
|
||||
|
/* |
||||
|
* @author ZZQ |
||||
|
* @Date 2023/2/8 4:11 下午 |
||||
|
*/ |
||||
|
@Repository |
||||
|
public interface LogRepository extends ElasticsearchRepository<LogRepositoryDTO, String> { |
||||
|
|
||||
|
} |
@ -0,0 +1 @@ |
|||||
|
druid.filters.DruidFilter=org.nl.config.DruidFilter |
Loading…
Reference in new issue