Elasticsearch学习(九)搭建日志系统,在Java代码中获取日志信息

2021-03-02 14:47:34 浏览数 (1)

搭建日志系统

绝大多数项目在后台管理中都有日志管理。以前的日志信息是存储在MySQL中,日志随着项目运行时间会越来越多,一直存储在MySQL会导致查询降低。现在的日志信息通过ELK技术栈进行操作。存储在Elasticsearch中,可以更好的分析日志内容及更快查询效率。

给定简单需求: 搭建日志系统,提供查询Elasticsearch中日志信息的接口。

1 创建项目

2 添加依赖

搭建最基本的环境,实现需求,没有考虑Spring Cloud相关环境,如果考虑Spring Cloud还需要配置Eureka等信息。

代码语言:javascript复制
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.6.RELEASE</version>
</parent>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.12</version>
    </dependency>
</dependencies>

3创建配置文件

在resources下新建application.yml配置文件。 配置Elasticsearch相关配置信息。

代码语言:javascript复制
spring:
  data:
    elasticsearch:
      cluster-name: elasticsearch
      cluster-nodes: 192.168.8.140:9300

4新建实体

根据kibana中查看到日志信息可以得出看出,除了message是类类型,里面包含一些其他属性外,其他的属性都是简单类型属性。

代码语言:javascript复制
@Data
@Document(indexName = "test_log",type = "doc")
public class Log {
    @Id
    private String id;
    @Field(type= FieldType.Text)
    private String host;
    @Field(type= FieldType.Text)
    private String message;
    @Field(type= FieldType.Long)
    private Long port;
    @Field(type = FieldType.Date)
    @JsonProperty("@timestamp")
    private Date timestamp;
    @Field(type = FieldType.Text)
    @JsonProperty("@version")
    private String version;
}

5新建service及实现类

代码语言:javascript复制
新建com.service.LogService及实现类
public interface LogService {
    List<Log> selectByPage(int page,int size);
}
@Service
public class LogServiceImpl implements LogService {
    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;
    @Override
    public List<Log> selectByPage(int page, int size) {
        SearchQuery sq = new NativeSearchQuery(QueryBuilders.matchAllQuery());
        sq.setPageable(PageRequest.of(page-1,size));
        return elasticsearchTemplate.queryForList(sq,Log.class);
    }
}

6新建控制器

代码语言:javascript复制
新建com.controller.LogController
@Controller
public class LogController {
    @Autowired
    private LogService logService;

    @RequestMapping("/page")
    @ResponseBody
    public List<Log> showPage(int page,int size){
        return logService.selectByPage(page,size);
    }
}

在Java代码中获取日志信息

上面搭建日志系统时完成了从ES中取出日志信息的功能。但是所有真实日志的信息都存储在String message中。默认没有做任何处理,处理过程应该交给客户端做字符串JSON转换,最终显示在页面中。如果在服务器端必须要获取日志内容(message)或日志级别(level)或线程名(thread_name)等日志信息就需要在服务器端做JSON转换。 下面代码演示如果在服务器端把String message转换为实体类并获取日志信息的步骤。

所有的操作都在上面代码基础进行操作。

1新建实体类

新建com.pojo.Message /**

  • 不对应ES中DOcument,所以没有@Document注解
  • 作用:为了对应message属性,把字符串message属性转换为实体类类型,可以方便取出里面一些属性。 */
代码语言:javascript复制
@Data
public class Message {
    @JsonProperty("@timestamp")
    private Date timestamp;
    @JsonProperty("@version")
    private String version;
    private String message;
    private String logger_name;
    private String thread_name;
    private String level;
    private Integer level_value;
}

2修改Log实体类

修改com.bjsxt.pojo.Log。添加一个属性

代码语言:javascript复制
@Data
@Document(indexName = "test_log",type = "doc")
public class Log {
    @Id
    private String id;

    @Field(type = FieldType.Text)
    private String host;

    @Field(type=FieldType.Text)
    private String message;

    @Field(type=FieldType.Integer)
    private Integer port;

    @Field(type=FieldType.Text)
    @JsonProperty("@version")
    private String version;

    @Field(type=FieldType.Date)
    @JsonProperty("@timestamp")
    private Date timestamp;
    // 这个属性没有和Elasticsearch中属性对应的。所以没有@Field注解
    // 主要目的就是为了返回Log时包含转换好的Message信息。
    // 为了演示这么做的。绝大多数情况把字符串message返回给客户端,由客户端做json转换。
    private Message msgPojo;
}

3修改service实现类

修改com.bjsxt.service.impl.LogServiceImpl。 使用Jacksong把Log类中message转换为Message类型,并设置到Log类中msgPojo属性内容。 转换完成后的Message类型中就存储了日志所有相关信息。通过操作Message获取所有的日志内容。

代码语言:javascript复制
@Service
public class LogServiceImpl implements LogService {

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    @Override
    public List<Log> selectByPage(int page, int size) {
        ObjectMapper objectMapper = new ObjectMapper();
        SearchQuery sq = new NativeSearchQuery(QueryBuilders.matchAllQuery());
        sq.setPageable(PageRequest.of(page-1,size));
        List<Log> list = elasticsearchTemplate.queryForList(sq, Log.class);
        try {
            for(Log log : list){
                Message msg = objectMapper.readValue(log.getMessage(), Message.class);
                System.out.println("在Java代码获取日志内容的实现方案:" msg.getMessage());
                log.setMsgPojo(msg);
            }
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return list;
    }
}

0 人点赞