干货:手把手搭建ElasticSearch日志监控告警

干货:手把手搭建ElasticSearch日志监控告警

精选文章moguli202025-04-23 15:46:4821A+A-

前言

去年做了一年的战略项目,今年终于成功上线了,该系统使用的是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日志监控告警的实战方案,无论是自研还是集成开源工具,核心目标都是 “早发现-早定位-早解决”

技术足以变革世界,知识能够扭转命运!诚邀关注小编,一同砥砺奋进,相互激励!

点击这里复制本文地址 以上内容由莫古技术网整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!
qrcode

莫古技术网 © All Rights Reserved.  滇ICP备2024046894号-2