干货:手把手搭建ElasticSearch日志监控告警
前言
去年做了一年的战略项目,今年终于成功上线了,该系统使用的是ElasticSearch日志存储,运行几个月下来,我发现ERROR的日志数量比较多,有些问题不能及时发现,导致运维比较被动且成本较高,所以我们要做ElasticSearch日志监控告警,能够及时发现问题与解决问题,提高系统的稳定性。
基本思路
监控(定时任务检查ES) -> 条件匹配 -> 发送告警(发送邮件、钉钉等)
代码实战
1. 依赖引入:引用ES的标准SDK,特别注意-->ES客户端的版本一定要与服务端的版本一致,否则会报错
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>6.8.18</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>6.8.18</version>
</dependency>
2.编写检查代码
以下是ES检查错误日志数据的验证代码,其中异常告警部分未补充具体的代码,大家可以根据项目情况自行集成即可。另外,可以集成xxl-job实现定时,常用参数也可以实现配置化(如集成apollo),不用写死在代码中。
创建 Elasticsearch 客户端-->构建布尔查询-->配置搜索请求-->执行查询-->发送告警
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import java.io.IOException;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
/**
* @Author 八零后琐话
* @Date 2025/4/13 10:00 AM
* @Version 1.0
*/
public class ElasticSearchErrorLogNotice {
// Elasticsearch 配置:IP、端口、账号、密码、索引模式、字段名等
private static final String ES_HOST = "127.0.0.1";
private static final int ES_PORT = 9200;
private static final String ES_USER_NAME = "esusername";
private static final String ES_PASSWORD = "espassword";
private static final String INDEX_PATTERN = "log-*";
private static final String LOG_LEVEL_FIELD = "level";
private static final String TIMESTAMP_FIELD = "@timestamp";
public static void main(String[] args) {
// 查询最近 1 小时内的错误日志数量
long startTime = Instant.now().minus(1, ChronoUnit.HOURS).toEpochMilli();
long endTime = Instant.now().toEpochMilli();
try (RestHighLevelClient client = createClient()) {
// 查询错误日志数量
long errorCount = getErrorLogCount(client, startTime, endTime);
if (errorCount > 100) {
// TODO 错误日志数量最近一小时超过100条,发送告警
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 查询错误日志数量
*/
private static long getErrorLogCount(RestHighLevelClient client, long startTime, long endTime) throws IOException {
// 1. 构建布尔查询
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery()
.must(QueryBuilders.matchQuery(LOG_LEVEL_FIELD, "ERROR"))
.must(QueryBuilders.rangeQuery(TIMESTAMP_FIELD).gte(startTime).lte(endTime));
// 2. 配置搜索请求
SearchRequest searchRequest = new SearchRequest(INDEX_PATTERN);
searchRequest.source(new SearchSourceBuilder().query(boolQuery).size(0)
);
// 3. 执行查询
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
return hits.getTotalHits();
}
/**
* 创建 Elasticsearch 客户端
*/
private static RestHighLevelClient createClient() {
// 创建凭据提供者
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(ES_USER_NAME, ES_PASSWORD));
// 配置HttpClientBuilder以使用凭据提供者
RestClientBuilder builder = RestClient.builder(new HttpHost(ES_HOST, ES_PORT, "http"))
.setHttpClientConfigCallback(httpClientBuilder -> {
httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
return httpClientBuilder;
});
return new RestHighLevelClient(builder);
}
}
赶紧复制上面的代码,进行测试验证吧
ES常用命令参考
在上面代码实现过程中,你可能会遇到如下几个问题,接下来我提供几个对应的ES常用命令供大家使用。
1.ES服务端的版本是什么,我该引用哪个版本的jar包?
curl -X GET "http://127.0.0.1:9200/" -u esusername:espassword
如图所示,可以看到ES的版本是 6.8.18
2.ES的日志索引模式是什么样的,我该使用哪个?
curl -X GET "http://127.0.0.1:9200/_cat/indices?v" -u esusername:espassword
3.ES的索引映射是什么,我要使用哪个字段呢?
其中log-*就是上面查询到的日志索引模式,多个以log-开头的索引,就使用log-*即可。
curl -X GET "http://127.0.0.1:9200/log-*/_mapping?pretty" -u esusername:espassword
4.查询索引中的一条文档
curl -X GET "http://127.0.0.1:9200/log-*/_search?size=1&pretty" -u esusername:espassword
5.指定条件查询 q=<字段名>:<值>
curl -X GET "http://127.0.0.1:9200/log-*/_count?pretty" -u esusername:espassword -H 'Content-Type: application/json' -d'
{
"query": {
"match": {
"level": "ERROR"
}
}
}'
其他方案
除了集成使用ES的标准SDK方案外,还可以通过集成ElastAlert或者使用frostmourne,大家可以自行搜索集成资料。
- ElastAlert:一个开源的警报框架,由 Yelp 开发,它可以从 Elasticsearch 中提取数据并根据预定义的规则生成警报。ElastAlert 可用于监控您的日志和时间序列数据,以便在发生异常、错误或其他有趣的模式时立即采取行动。ElastAlert 能够与许多通知服务(如电子邮件、Slack、PagerDuty、钉钉等)集成,这样在触发警报时可以发送通知。
- Frostmourne:Frostmourne 是由汽车之家(Autohome)开源的一款企业级监控告警系统,专注于解决日志、指标等数据的实时监控与告警需求。它基于 Elasticsearch 和 ClickHouse 等存储引擎,支持灵活的告警规则配置和多渠道通知(如邮件、钉钉、企业微信等),是运维和开发团队快速搭建监控体系的利器。
总结
本文从 0到1 拆解了ES日志监控告警的实战方案,无论是自研还是集成开源工具,核心目标都是 “早发现-早定位-早解决”。
技术足以变革世界,知识能够扭转命运!诚邀关注小编,一同砥砺奋进,相互激励!