17网站一起做网店河北,桂林生活网发布信息,1000倍爆率传奇,泉州seo技术文章目录一、 ELK二、 Elasticsearch简介三、 Linux安装Elasticsearch四、SpringData Elasticsearchpom.xmlapplication.yml创建实体创建索引 设置映射简单增删改查搜索五、 LogStash六、 使用Logback向Logstash中输出日志七、 在Kibana中查看日志信息八、 搭建日志系统九、 在…
文章目录一、 ELK二、 Elasticsearch简介三、 Linux安装Elasticsearch四、SpringData Elasticsearchpom.xmlapplication.yml创建实体创建索引 设置映射简单增删改查搜索五、 LogStash六、 使用Logback向Logstash中输出日志七、 在Kibana中查看日志信息八、 搭建日志系统九、 在Java代码中获取日志信息一、 ELK Elasticsearch官网中提供了很多技术其中一些技术是可以配合使用的里面比较出名的就是ELK技术栈。 ELK是Elasticsearch、Logstash、Kibana三个软件首字母。 Elasticsearch 全文检索工具。 Kibana页面管理工具。可以通过Kibana的管理界面操作Elasticsearch Logstash日志收集的工具通过此工具可以实现日志内容收集及格式转换。 二、 Elasticsearch简介 Elasticsearch是一个基于Lucene的搜索服务器。它提供了一个分布式的全文搜索引擎其对外服务是基于RESTful web接口发布的。Elasticsearch是用Java开发的应用并作为Apache许可条款下的开放源码发布是当前流行的企业级搜索引擎。设计用于云计算中能够达到近实时搜索稳定可靠快速安装使用方便。 1 功能分类 Elasticsearch具备两个主要功能 搜索。功能和Solr类似。代替目前海量数据的MySQL模糊查询。 分析。结合LogStash使用。 2 相关概念 2.1 cluster 集群。Elasticsearch集群由一或多个节点组成其中有一个主节点这个主节点是可以通过选举产生的主从节点是对于集群内部来说的。Elasticsearch的一个概念就是去中心化字面上理解就是无中心节点这是对于集群外部来说的因为从外部看Elasticsearch集群在逻辑上是个整体你与集群中的任何一个节点通信和与整个Elasticsearch集群通信是等价的。也就是说主节点的存在不会产生单点安全隐患、并发访问瓶颈等问题。 2.2 Index 索引。相当于关系型数据库中的表。其中存储若干相似结构的Document数据。如客户索引订单索引商品索引等。Elasticsearch中的索引不像数据库表格一样有强制的数据结构约束在理论上可以存储任意结构的数据。但了为更好的为业务提供搜索数据支撑还是要设计合适的索引体系来存储不同的数据。 2.3 shards primary shard代表索引的主分片Elasticsearch可以把一个完整的索引分成多个primary shard这样的好处是可以把一个大的索引拆分成多个分片分布存储在不同的Elasticsearch节点上从而形成分布式存储并为搜索访问提供分布式服务提高并发处理能。primary shard的数量只能在索引创建时指定并且索引创建后不能再更改primary shard数量。 2.4 replicas replica shard代表索引主分片的副本Elasticsearch可以设置多个replica shard。replica shard的作用一是提高系统的容错性当某个节点某个primary shard损坏或丢失时可以从副本中恢复。二是提高Elasticsearch的查询效率Elasticsearch会自动对搜索请求进行负载均衡将并发的搜索请求发送给合适的节点增强并发处理能力。 2.5 Type 类型。每个索引中都必须有唯一的一个TypeType是Index中的一个逻辑分类。Elasticsearch中的数据Document是存储在索引下的Type中的。 注意Elasticsearch5.x及更低版本中一个Index中可以有多个Type。Elasticsearch6.x版本之后type概念被弱化一个index中只能有唯一的一个type。且在7.x版本之后删除type定义。 2.6 Document 文档。Elasticsearch中的最小数据单元。一个Document就是一条数据一般使用JSON数据结构表示。每个Index下的Type中都可以存储多个Document。一个Document中可定义多个fieldfield就是数据字段。如学生数据{“name”:“张三”, “age”:20, “gender”:“男”}。 2.7 元数据 在Elasticsearch中所有以“_”开头的属性都成为元数据都有着自己特定的含义。 例如:_index:表示索引 2.8 倒排索引Elasticsearch搜索原理面试题反向索引 对数据进行分析抽取出数据中的词条以词条作为key对应数据的存储位置作为value实现索引的存储。这种索引称为倒排索引。倒排索引是Document写入Elasticsearch时分析维护的。 3 Elasticsearch常见使用场景 维基百科全文检索高亮显示搜索推荐The Guardian国外的一个新闻网站此平台可以对用户的行为点击、浏览、收藏、评论、社区网络数据对新闻的评论等进行数据分析为新闻的发布者提供相关的公众反馈。 Stack Overflow国外的程序异常讨论论坛 Github开源代码管理在千亿级别的代码行中搜索信息电子商务平台等。 三、 Linux安装Elasticsearch
使用的Elasticsearch的版本是7.6.2。Elasticsearch7.x要求Linux内核必须是4版本以上。 在linux操作系统中查看内核版本的命令是 uname -a 课堂使用的Linux是CentOS8。内核使用的是4.18。
1 基于Docker安装 1.1.1 拉取Elasticsearch镜像 如果docker还没有开启。需要先开始docker软件 systemctl start docker 拉取Elasticsearch镜像 docker pull elasticsearch:7.6.2 1.1.2 创建并启动容器 docker run --nameelasticsearch -d -p 9200:9200 -p 9300:9300 -e discovery.typesingle-node elasticsearch:7.6.2 discovery.typesingle-node 集群模式单机版 1.1.3 查看日志 docker logs -f elasticsearch 如果日志中出现started状态说明启动成功 1.1.4 测试结果 curl http://localhost:9200 1.2 基于Docker的Kibana Kibana的版本必须和ES的版本对应。 1.2.1 拉取镜像 docker pull kibana:7.6.2 1.2.2 新建并启动容器 docker run -d --name kibana --link elasticsearch:elasticsearch -p 5601:5601 kibana:7.6.2 1.2.3 修改Kibana参数 # docker exec -it kibana /bin/bash # cd config # vi kibana.yml 选中部分修改成Docker的IP 重启docker容器 # docker restart kibana 1.2.4 访问 在浏览器输入 http://192.168.8.137:5601 四、SpringData Elasticsearch
pom.xml
?xml version1.0 encodingUTF-8?
project xsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xmlnshttp://maven.apache.org/POM/4.0.0modelVersion4.0.0/modelVersiongroupIdcom.bjsxt/groupIdartifactIdol_data_elasticsearch/artifactIdversion1.0-SNAPSHOT/versionparentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.3.5.RELEASE/version/parentdependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-elasticsearch/artifactId/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactId/dependencydependencygroupIdnet.logstash.logback/groupIdartifactIdlogstash-logback-encoder/artifactIdversion6.6/version/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependency/dependencies
/projectapplication.yml
spring:elasticsearch:rest:uris: http://192.168.8.132:9200创建实体
package com.bjsxt.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;import java.io.Serializable;/*** 商品类型** Document - 描述当前类型对应一个Elasticsearch中的索引。* 必要属性* indexName - 对应的索引命名* 可选属性* shards - 主分片数量 默认1.* replicas - 副本分片数量默认1.*/
Data
NoArgsConstructor
AllArgsConstructor
Document(indexName java_item, shards 1, replicas 0)
public class Item implements Serializable {/*** Id - 当前的属性对应Elasticsearch中索引的_id元数据。代表主键。* 且当前属性会在Elasticsearch保存的数据结构中。{id:, title:, remark:}*/IdField(name id, type FieldType.Keyword)private String id; // 主键/*** Field - 描述Java类型中的属性的映射* name - 对应的ES索引中的字段名。默认和属性同名。* type - 对应的字段类型默认是FieldType.Auto。建议定义正确的映射类型。避免可能发生的映射错误。* index - 是否创建索引text类型创建倒排索引其他类型创建正排索引。默认true*/Field(name title, type FieldType.Text, analyzer ik_max_word)private String title; // 标题Field(name remark, type FieldType.Text, analyzer ik_smart)private String remark; // 详情Field(name price, type FieldType.Long)private Long price; // 单价 单位是分Field(name number, type FieldType.Integer, index false)private int num; // 库存数量
}
创建索引 设置映射
SpringBootTest(classes {MyDataElasticsearchApplication.class})
RunWith(SpringRunner.class)
public class TestDataElasticsearch {// 基于HTTP协议9200端口的RestAPI访问客户端。Autowiredprivate ElasticsearchRestTemplate elasticsearchRestTemplate;Testpublic void createAndPutMapping(){// 创建索引elasticsearchRestTemplate.indexOps(Item.class).create();// 设置映射elasticsearchRestTemplate.indexOps(Item.class).putMapping(elasticsearchRestTemplate.indexOps(Item.class).createMapping());}简单增删改查
SpringBootTest(classes {MyDataElasticsearchApplication.class})
RunWith(SpringRunner.class)
public class TestDataElasticsearch {// 基于HTTP协议9200端口的RestAPI访问客户端。Autowiredprivate ElasticsearchRestTemplate elasticsearchRestTemplate;Testpublic void testGet(){// 主键查询数据Item item elasticsearchRestTemplate.get(001, Item.class);System.out.println(item);}Testpublic void testDeleteDocument(){// 主键删除String result elasticsearchRestTemplate.delete(-P8E8XcBBxUhJQR7_GTO, Item.class);System.out.println(result);}/*** 使用覆盖方式实现更新。就是使用save方法。参数对象的主键有数据且对应ES中的主键则是覆盖。*/Testpublic void testSave(){// 保存单条数据。 返回值就是保存的对象。 如果参数对象中Id主键属性值是null则返回的对象中Id值是ES生成的主键。Item item elasticsearchRestTemplate.save(new Item(001, 华为P40, 2020年生产高端手机, 429900L, 999));System.out.println(item);item elasticsearchRestTemplate.save(new Item(null, 华为P40 Pro, 华为P40增强版手机, 589900L, 999));System.out.println(item);// 批量新增返回值特性和保存单条数据一致。ListItem items new ArrayList();items.add(new Item(003, 华为P40 Pro Plus, 华为P40Pro增强版手机, 629900L, 999));items.add(new Item(004, 小米10, 很贵的暖手宝, 229900L, 999));items.add(new Item(005, 三星, 可以自卫容易误伤, 329900L, 999));IterableItem results elasticsearchRestTemplate.save(items);for(Item i : results){System.out.println(i);}}Testpublic void deleteIndex(){// 所有针对索引的操作都封装在IndexOperations类型中。IndexOperations indexOps elasticsearchRestTemplate.indexOps(Item.class);indexOps.delete();}搜索
package com.bjsxt.test;import com.bjsxt.MyDataElasticsearchApplication;
import com.bjsxt.pojo.Item;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
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.IndexOperations;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.Query;
import org.springframework.test.context.junit4.SpringRunner;import java.util.ArrayList;
import java.util.List;SpringBootTest(classes {MyDataElasticsearchApplication.class})
RunWith(SpringRunner.class)
public class TestDataElasticsearch {// 基于HTTP协议9200端口的RestAPI访问客户端。Autowiredprivate ElasticsearchRestTemplate elasticsearchRestTemplate;// 高亮搜索Testpublic void testHighlight(){// 定义高亮字段HighlightBuilder.Field titleField new HighlightBuilder.Field(title);titleField.preTags(span stylecolor:red);titleField.postTags(/span);titleField.fragmentSize(2);titleField.numOfFragments(1);// withHighlightFields(Field... 高亮字段数组)Query query new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchQuery(title, 华为)).withHighlightFields(titleField).build();SearchHitsItem hits elasticsearchRestTemplate.search(query, Item.class);// 注意 Item对象中不包含高亮数据需要手工处理。for(SearchHitItem hit : hits){Item item hit.getContent();// 处理高亮的方式// 根据高亮字段名称获取高亮数据集合。返回结果是ListStringListString hlList hit.getHighlightField(title);if(hlList ! null hlList.size() 0){// 有高亮数据item.setTitle(hlList.get(0));}System.out.println(item);}}// 排序和分页// withPageable(Pageable) 设置分页排序// Pageable接口有实现类类型是PageRequest静态方法of.// of(int page, int size[, Sort sort]) ; page 第几页从0开始计数 size 每页查询多少条数据// Sort 排序类型 静态方法 Sort.by(Direction 升降序, String... 按照哪一个字段排序)// Sort.by(Sort.Order... 多字段排序方案) Sort.Order.desc(降序字段名) Sort.Order.asc(升序字段名)Testpublic void testSortAndPageable(){Query query new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchAllQuery()).withPageable(PageRequest.of(1, 2,Sort.by(Sort.Order.desc(price),Sort.Order.asc(title)))).build();SearchHitsItem hits elasticsearchRestTemplate.search(query, Item.class);for(SearchHitItem hit : hits){System.out.println(hit.getContent());}}// 搜索数据 search// DSL boolTestpublic void testBool(){// 创建一个bool搜索条件。 bool:{ must:[{match:{field:value}}], must_not:[], should:[] }BoolQueryBuilder queryBuilder QueryBuilders.boolQuery();// 获取bool搜索条件中的Must条件集合。增加到集合中的条件就是必要条件。ListQueryBuilder must queryBuilder.must();must.add(QueryBuilders.rangeQuery(price).gt(100000L));// 其他的搜索条件集合获取方式相似。ListQueryBuilder mustNot queryBuilder.mustNot();ListQueryBuilder should queryBuilder.should();// 简化设置搜索条件的方式是,下述代码相当于 queryBuilder.should().add(QueryBuilders.matchAllQuery());queryBuilder.should(QueryBuilders.matchAllQuery());Query query new NativeSearchQueryBuilder().withQuery(queryBuilder).build();SearchHitsItem hits elasticsearchRestTemplate.search(query, Item.class);for(SearchHitItem hit : hits){System.out.println(hit.getContent());}}// DSL match allTestpublic void testMatchAll(){SearchHitsItem hits elasticsearchRestTemplate.search(new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchAllQuery()).build(),Item.class);for(SearchHitItem hit : hits){System.out.println(hit.getContent());}}// DSL match phraseTestpublic void testMatchPhrase(){SearchHitsItem hits elasticsearchRestTemplate.search(new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchPhraseQuery(title, 华为P40 Pro)).build(),Item.class);for(SearchHitItem hit : hits){System.out.println(hit.getContent());}}// DSL rangeTestpublic void testRangeQuery(){SearchHitsItem hits elasticsearchRestTemplate.search(new NativeSearchQueryBuilder().withQuery(QueryBuilders.rangeQuery(price).gt(200000L).lt(500000L)).build(),Item.class);for(SearchHitItem hit : hits){System.out.println(hit.getContent());}}// DSL matchTestpublic void testMatchQuery(){SearchHitsItem hits elasticsearchRestTemplate.search(new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchQuery(title, 小米)).build(),Item.class);System.out.println(数据数量 hits.getTotalHits());for(SearchHitItem hit : hits){System.out.println(hit.getContent());}}// query string search。 在所有的字段中搜索。Testpublic void testQueryString(){// 所有的搜索逻辑都是通过search实现的。/** SearchHitsT search(Query query, ClassT clazz)* 返回值就是在Kibana控制台上搜索的结果JSON转换的Java对象。* 泛型就是搜索结果数据转换的Java对象类型。* 参数query就是搜索条件。* 搜索条件建议使用构建器来创建。** QueryBuilder - 用来描述搜索条件的。在DSL和querystring两种搜索中有什么搜索方式就有对应的实现类型。* 如querystring - QueryStringQueryBuilder* 如DSL中的match - MatchQueryBuilder* 如DSL中的range - RangeQueryBuilder*/QueryBuilder queryBuilder QueryBuilders.queryStringQuery(华为);Query query new NativeSearchQueryBuilder().withQuery(queryBuilder).build();SearchHitsItem hits elasticsearchRestTemplate.search(query, Item.class);System.out.println(总计数据行数: hits.getTotalHits());System.out.println(elasticsearchRestTemplate.indexOps(Item.class));// SearchHits类型本身实现了集合接口|可迭代接口。for(SearchHitItem hit : hits){Item item hit.getContent();System.out.println(SearchHits.toString() - hits.toString());System.out.println(SearchHit.toString() - hit.toString());System.out.println(_id - hit.getId());System.out.println(查询到的商品对象 - item);}System.out.println();for(SearchHitItem hit : hits.getSearchHits()){System.out.println(查询到的商品 - hit.getContent());}}五、 LogStash
1 什么是LogStash 官方文字说明Logstash 是开源的服务器端数据处理管道能够同时从多个来源采集数据转换数据然后将数据发送到您最喜欢的“存储库”中。 通俗说明Logstash是一款强大的数据处理工具常用作日志处理。 到目前为止Logstash已经有超过200个可用的插件以及创建和贡献自己的灵活性。社区生态非常完善对于我们可以放心的使用。 2 为什么使用Logstash 通常当系统发生故障时工程师需要登录到各个服务器上使用 grep / sed / awk 等 Linux 脚本工具去日志里查找故障原因。在没有日志系统的情况下首先需要定位处理请求的服务器如果这台服务器部署了多个实例则需要去每个应用实例的日志目录下去找日志文件。每个应用实例还会设置日志滚动策略如每天生成一个文件还有日志压缩归档策略等。 这样一系列流程下来对于我们排查故障以及及时找到故障原因造成了比较大的麻烦。因此如果我们能把这些日志集中管理并提供集中检索功能不仅可以提高诊断的效率同时对系统情况有个全面的理解避免事后救火的被动。 所以日志集中管理功能就可以使用ELK技术栈进行实现。Elasticsearch只有数据存储和分析的能力Kibana就是可视化管理平台。还缺少数据收集和整理的角色这个功能就是Logstash负责的。 3 Logstash工作原理 3.1 Data Source Logstash 支持的数据源有很多。例如对于日志功能来说只能能有日志记录和日志传递功能的日志都支持Spring Boot中默认推荐logback支持日志输出功能输出到数据库、数据出到文件。 我们就使用logback进行日志输出给Logstash。 3.2 Logstash Pipeline 整个整体就是Logstash的功能。 在Logstash中包含非常重要的三个功能 a) Input 输入源一般配置为自己监听的主机及端口。DataSource向指定的ip及端口输出日志Input 输入源监听到数据信息就可以进行收集。 b) Filter 过滤功能对收集到的信息进行过滤额外处理也可以省略这个配置不做处理 c) Output 把收集到的信息发送给谁。在ELK技术栈中都是输出给Elasticsearch后面数据检索和数据分析的过程就给Elasticsearch了。 最终效果通过整体步骤就可以把原来一行日志信息转换为Elasticsearch支持的Document形式键值对形式的数据进行存储。 4 安装Logstash 4.1 安装Logstash docker pull logstash:7.6.2
4.2 启动容器 docker run -it -p 4560:4560 --name logstash -d logstash:7.6.2
4.3 修改配置 进入容器 docker exec -it logstash /bin/bash 修改配置文件 vi /usr/share/logstash/config/logstash.yml 把ip修改成elasticsearch访问地址IP
4.4 修改输入输出配置 继续在容器命令行输入 vi /usr/share/logstash/pipeline/logstash.conf
配置解释说明 input:接收日志输入配置 tcp: 协议 mode: logstash服务 port端口自己指定。默认4560 output日志处理输出 elasticsearch: 交给es处理 actiones中index命令。也就是新增命令。 hostses的主机 index:存储日志的索引。如果不存在可以自动创建。默认的type名称为doc 一定要先启动编辑状态点击键盘i键在粘贴如果没启用第一行是nput{少个i。 input {tcp {mode serverport 4560}
}
filter {
}
output {elasticsearch {action indexhosts 192.168.8.128:9200index test_log}
}4.5 重启容器 退出容器命令行进入到Linux终端重启logstash容器。 docker restart logstash
4.6 查看日志 docker logs -f logstash
六、 使用Logback向Logstash中输出日志
pom.xml
parentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.3.3.RELEASE/version
/parent
dependenciesdependencygroupIdnet.logstash.logback/groupIdartifactIdlogstash-logback-encoder/artifactIdversion6.3/version/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency
/dependencies
logback.xml
?xml version1.0 encodingUTF-8?
!--该日志将日志级别不同的log信息保存到不同的文件中 --
configurationinclude resourceorg/springframework/boot/logging/logback/defaults.xml /springProperty scopecontext namespringAppNamesourcespring.application.name /!-- 日志在工程中的输出位置 --property nameLOG_FILE value${BUILD_FOLDER:-build}/${springAppName} /!-- 控制台的日志输出样式 --property nameCONSOLE_LOG_PATTERNvalue%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}} /!-- 控制台输出 --appender nameconsole classch.qos.logback.core.ConsoleAppenderfilter classch.qos.logback.classic.filter.ThresholdFilterlevelINFO/level/filter!-- 日志输出编码 --encoderpattern${CONSOLE_LOG_PATTERN}/patterncharsetutf8/charset/encoder/appender!-- logstash远程日志配置--appender namelogstash classnet.logstash.logback.appender.LogstashTcpSocketAppenderdestination192.168.8.132:4560/destinationencoder charsetUTF-8 classnet.logstash.logback.encoder.LogstashEncoder //appender!-- 日志输出级别 --root levelDEBUGappender-ref refconsole /appender-ref reflogstash //root
/configuration
启动类
SpringBootApplication
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class,args);}
}
七、 在Kibana中查看日志信息
1 使用命令方式查看 可以直接在Dev Tools中输入命令查看日志信息。 输入 GET test_log/_search 查看全部。
八、 搭建日志系统
pom.xml
parentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.3.3.RELEASE/version
/parent
dependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-elasticsearch/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdversion1.18.12/version/dependency
/dependencies
application.yml
spring:elasticsearch:rest:uris: http://192.168.8.132:9200
新建实体
/*** 对应Elasticsearch中的logstash_log_index索引。*/
Data
Document(indexName logstash_log_index)
public class MyLogMessage implements Serializable {Idprivate String id;Field(name host, type FieldType.Text)private String host;Field(name version, type FieldType.Text)private String version;Field(name port, type FieldType.Long)private Long port;Field(name timestamp, type FieldType.Date, format DateFormat.date_time)private Date timestamp;Field(name message, type FieldType.Text)private String message;
}
MyLogMessageDao
public interface MyLogMessageDao {/*** 在Message字段中做搜索。 分页处理。* param page 从0开始的页码* param rows 每页多少行* param query 关键字* return* key value* total 总计数据行数* ListMyLogMessage 当前页面显示的数据集合对象中的message高亮处理。*/MapString, Object searchByPage(int page, int rows, String query);
}
MyLogMessageDaoImpl
Repository
public class MyLogMessageDaoImpl implements MyLogMessageDao {Autowiredprivate ElasticsearchRestTemplate restTemplate;Overridepublic MapString, Object searchByPage(int page, int rows, String query) {HighlightBuilder.Field f new HighlightBuilder.Field(message);f.preTags(span stylecolor:red);f.postTags(/span);f.fragmentSize(Integer.MAX_VALUE);f.numOfFragments(1);SearchHitsMyLogMessage hits restTemplate.search(new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchQuery(message, query)) // 搜索条件.withPageable(PageRequest.of(page, rows)) // 分页.withHighlightFields(f) // 高亮.build(),MyLogMessage.class);ListMyLogMessage contents new ArrayList();for(SearchHitMyLogMessage hit : hits){MyLogMessage logMessage hit.getContent();// 处理高亮ListString hl hit.getHighlightField(message);if(hl ! null hl.size() 0){// 有高亮logMessage.setMessage(hl.get(0));}contents.add(logMessage);}MapString, Object result new HashMap();result.put(total, hits.getTotalHits());result.put(datas, contents);return result;}
}
新建service及实现类
package com.bjsxt.service;import java.util.Map;public interface MyLogService {MapString, Object searchByPage(int page, int rows, String query);
}
Service
public class MyLogServiceImpl implements MyLogService {Autowiredprivate MyLogMessageDao logMessageDao;private final ObjectMapper objectMapper new ObjectMapper();Overridepublic MapString, Object searchByPage(int page, int rows, String query) {MapString, Object result logMessageDao.searchByPage(page, rows, query);return result;}
}
新建控制器
RestController
public class MyLogController {Autowiredprivate MyLogService logService;RequestMapping(/find)public MapString, Object findByPage(RequestParam(name page, defaultValue 0) int page,RequestParam(name rows, defaultValue 10) int rows,RequestParam(name query, defaultValue level) String query){return logService.searchByPage(page, rows, query);}
}
启动类
SpringBootApplication
public class MyLogManagerApplication {public static void main(String[] args) {SpringApplication.run(MyLogManagerApplication.class, args);}
}测试结果 在浏览器输入: http://localhost:8080/ ?page1,rows2
九、 在Java代码中获取日志信息
新建实体类
MessageBody
/*** 是MyLogMessage类型对象中message字符串属性转换后的Java对象类型。*/
Data
public class MessageBody implements Serializable {// 使用Jackson把Json字符串转成Java对象默认是同名转换。如果JSON中的属性名和Java对象的属性名不同// 用JsonProperty注解定义JSON中的属性名称。JsonProperty(timestamp)private Date timestamp;JsonProperty(version)private String version;private String message;JsonProperty(logger_name)private String loggerName;JsonProperty(thread_name)private String threadName;private String level;JsonProperty(level_value)private String levelValue;
}
修改实体类 添加MessageBody
/*** 对应Elasticsearch中的logstash_log_index索引。*/
Data
Document(indexName logstash_log_index)
public class MyLogMessage implements Serializable {Idprivate String id;Field(name host, type FieldType.Text)private String host;Field(name version, type FieldType.Text)private String version;Field(name port, type FieldType.Long)private Long port;Field(name timestamp, type FieldType.Date, format DateFormat.date_time)private Date timestamp;Field(name message, type FieldType.Text)private String message;private MessageBody body;
}
修改service实现类
Service
public class MyLogServiceImpl implements MyLogService {Autowiredprivate MyLogMessageDao logMessageDao;private final ObjectMapper objectMapper new ObjectMapper();Overridepublic MapString, Object searchByPage(int page, int rows, String query) {MapString, Object result logMessageDao.searchByPage(page, rows, query);for(MyLogMessage message : (ListMyLogMessage)result.get(datas)){// 获取JSON格式字符串String jsonMessage message.getMessage();MessageBody messageBody null;try {// 转换字符串为Java对象messageBody objectMapper.readValue(jsonMessage, MessageBody.class);} catch (JsonProcessingException e) {e.printStackTrace();}// 设置对象message.setBody(messageBody);}return result;}
}