1. 说明

ApiBoot Logging是ApiBoot提供单应用、微服务应用下的请求日志分析框架。在微服务的链路调用过程中,可以记录下每次调用的链路信息。信息可以以日志的形式保存在数据库中,或者也可以自己通过代码将日志保存在其他地方,比如kafka中。

日志的格式大致如下:

[

{

"endTime":1564368219907,

"httpStatus":200,

"parentSpanId":"d9ed5130-b72c-4282-8d18-4a6f7a08275a",

"requestBody":"",

"requestHeaders":{

"api-boot-x-trace-id":"855b0f4d-7667-4e14-ac8d-6b63fb4ef64e",

"host":"localhost:9099",

"connection":"keep-alive",

"api-boot-x-parent-span-id":"d9ed5130-b72c-4282-8d18-4a6f7a08275a",

"accept":"*/*",

"user-agent":"Java/1.8.0_201"

},

"requestIp":"127.0.0.1",

"requestMethod":"GET",

"requestUri":"/levelone",

"responseBody":"levelone",

"responseHeaders":{},

"serviceId":"ahhx_jcpt",

"serviceIp":"192.168.21.101",

"servicePort":"9099",

"spanId":"d1597b46-ec21-4a37-8f40-d39d95d533a8",

"startTime":1564368219904,

"timeConsuming":3,

"traceId":"855b0f4d-7667-4e14-ac8d-6b63fb4ef64e"

}

]

1.1 traceId(链路ID)和spanId(跨度ID)

如果一个请求的header信息内包含traceId(链路ID)则加入该链路,如果不存在则生成新的链路信息

如果一个请求的header信息内包含spanId(跨度ID),则使用该spanId作为parent spanId,对两个请求进行上下级关联。

简单的理解,通过traceId,可以分析出来,如果几个日志的traceId是一样的,那么这几个调用是属于一条链路的。然后再通过spanId和parentSpanId就可以分析出来这个几个请求的上下级关系,是哪个调用的哪个。

1.2 体系

项目结构主要分为两个部分,一个是ApiBoot Logging,另一个是ApiBoot Logging Admin。

ApiBoot Logging是日志采集端,就是集成了ApiBoot Logging的项目,这个项目中的接口被请求时,就会采集到日志。

ApiBoot Logging Admin是日志收集端,所有ApiBoot Logging的项目采集到的日志都会上报到ApiBoot Logging Admin。

2. 项目中导入ApiBoot Logging

2.1 引入依赖

org.minbox.framework

api-boot-starter-logging

2.1.2.RELEASE

2.2 修改配置文件

logging:

level:

org.minbox.framework.api.boot.plugin.logging: debug

root: info

com.base.web: info

api:

boot:

logging:

admin:

server-address: 127.0.0.1:20004

# 格式化上报日志

format-console-log-json: true

number-of-request-log: 2

# 显示上报日志

show-console-report-log: true

server-address是Logging Admin的地址,Logging Admin是独立的项目,是Logging项目的日志上报地址。这里可以先不管,等到Logging Admin创建完毕,在修改为对于的ip和port

2.3 测试接口

@Controller

public class ApiBootContorller {

@ResponseBody

@GetMapping("/levelone")

public String levelone(){

return "levelone";

}

}

通过postman调用这个接口,就可以在控制台中看到打印的日志。

集成ApiBoot Logging 的步骤只有这些,但是可能会遇到一些问题

spring boot版本问题:

我的项目使用的是spring boot 2.0.1 但是ApiBoot 需要2.1.6,直接引入,启动就会报错。

10:16:58 [localhost-startStop-1] ERROR o.a.c.c.C.[Tomcat].[localhost].[/] - Exception starting filter [apiBootLoggingFilter]

java.lang.AbstractMethodError: null

at org.apache.catalina.core.ApplicationFilterConfig.initFilter(ApplicationFilterConfig.java:285)

at org.apache.catalina.core.ApplicationFilterConfig.(ApplicationFilterConfig.java:112)

at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4598)

at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5241)

at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)

at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1421)

at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1411)

at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)

at java.util.concurrent.FutureTask.run(FutureTask.java)

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)

at java.lang.Thread.run(Thread.java:748)

于是我将项目升级到2.1.6版本,之后还是无法启动,因为项目原先依赖的kafka无法启动,之后又去升级kafka依赖,以及修改kafka接收数据的代码。

总之,如果一个项目比较复杂,升级spring boot版本还是比较容易碰到坑的。

3. 创建Logging Admin 项目

Logging Admin 项目用来接口日志采集端发送过来的数据,而且一个Logging Admin可以接受多个数据采集端,可以理解为一对多的关系。

3.1 导入依赖

org.minbox.framework

api-boot-starter-logging-admin

ApiBoot Mybatis Enhance

org.minbox.framework

api-boot-starter-mybatis-enhance

MySQL驱动

mysql

mysql-connector-java

Hikari数据源

com.zaxxer

HikariCP

如果不指定依赖的version的话,需要添加依赖管理,如果指定了依赖的具体版本,就不需要添加依赖管理了,上面的ApiBoot Logging引入时也是一样。

依赖管理:

org.minbox.framework

api-boot-dependencies

2.1.2.RELEASE

import

pom

3.2 配置文件

server.port=20004

logging.level.org.minbox.framework.api.boot.plugin.logging=debug

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

spring.datasource.type=com.zaxxer.hikari.HikariDataSource

spring.datasource.username=root

spring.datasource.password=ahhx@123

spring.datasource.url=jdbc:mysql://192.168.220.46:3306/apiboot

# 格式化上报日志

api.boot.logging.admin.format-console-log-json=true

# 显示上报日志

api.boot.logging.admin.show-console-report-log=true

3.3 在数据库中运行sql文件

上面的配置文件中用到了数据库,需要初始化数据库,创建一些表。

表结构如下,将如下语句在对应的数据库中跑一次,即可。

SET NAMES utf8mb4 ;

--

-- Table structure for table `logging_request_logs`

--

DROP TABLE IF EXISTS `logging_request_logs`;

SET character_set_client = utf8mb4 ;

CREATE TABLE `logging_request_logs` (

`lrl_id` varchar(36) NOT NULL COMMENT '主键,UUID',

`lrl_service_detail_id` varchar(36) DEFAULT NULL COMMENT '服务详情编号,关联logging_service_details主键',

`lrl_trace_id` varchar(36) DEFAULT NULL COMMENT '链路ID',

`lrl_parent_span_id` varchar(36) DEFAULT NULL COMMENT '上级跨度ID',

`lrl_span_id` varchar(36) DEFAULT NULL COMMENT '跨度ID',

`lrl_start_time` mediumtext COMMENT '请求开始时间',

`lrl_end_time` mediumtext COMMENT '请求结束时间',

`lrl_http_status` int(11) DEFAULT NULL COMMENT '请求响应状态码',

`lrl_request_body` longtext COMMENT '请求主体内容',

`lrl_request_headers` text COMMENT '请求头信息',

`lrl_request_ip` varchar(30) DEFAULT NULL COMMENT '发起请求客户端的IP地址',

`lrl_request_method` varchar(10) DEFAULT NULL COMMENT '请求方式',

`lrl_request_uri` varchar(200) DEFAULT NULL COMMENT '请求路径',

`lrl_response_body` longtext COMMENT '响应内容',

`lrl_response_headers` text COMMENT '响应头信息',

`lrl_time_consuming` int(11) DEFAULT NULL COMMENT '请求耗时',

`lrl_create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '日志保存时间',

PRIMARY KEY (`lrl_id`),

KEY `logging_request_logs_LRL_SERVICE_DETAIL_ID_index` (`lrl_service_detail_id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='请求日志信息表';

--

-- Table structure for table `logging_service_details`

--

DROP TABLE IF EXISTS `logging_service_details`;

SET character_set_client = utf8mb4 ;

CREATE TABLE `logging_service_details` (

`lsd_id` varchar(36) NOT NULL,

`lsd_service_id` varchar(200) DEFAULT NULL COMMENT '上报服务的ID,对应spring.application.name配置值',

`lsd_service_ip` varchar(50) DEFAULT NULL COMMENT '上报服务的IP地址',

`lsd_service_port` int(11) DEFAULT NULL COMMENT '上报服务的端口号',

`lsd_last_report_time` timestamp NULL DEFAULT NULL COMMENT '最后一次上报时间,每次上报更新',

`lsd_create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '首次上报时创建时间',

PRIMARY KEY (`lsd_id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='上报日志的客户端服务详情';

3.4 测试

将ApiBoot Logging配置文件中的对应的server-address: 127.0.0.1:20004指定为Logging Admin的ip和port。

使用postman调用ApiBoot Logging中的接口,可以看到的结果是ApiBoot Logging本地的控制台打印出来了日志,同时Logging Admin也收到了日志打印在控制台上并且存储在了数据库中。

4. 链式调用

之前引入ApiBoot Logging 的项目叫做ahhx-jcpt

spring:

application:

name: ahhx-jcpt

再创建一个ApiBoot Logging项目叫做apiboot,项目中提供一个接口

@ResponseBody

@GetMapping(value = "/index")

public String hello(){

return getStringApi.getString();

}

在apiboot中的接口中调用ahhx-jcpt,就达成了链式调用。

需要注意的问题是,目前最新版2.1.2,只支持spring cloud openfeign调用,对于RestTemplate等方式调用,虽然也可以采集到日志,但是并不能正确得到traceId、spanId和parentSpanId。那么就无法分析出链路的调用关系。

关于spring cloud openfeign的简单使用将在后文描述。

使用postman调用apiboot的\index接口,查看ahhx-jcpt和apiboot的控制台,可以看到他们的traceId是一样的,并且ahhx-jcpt的parentSpanId就是apiboot的spanId。

5. spring cloud openfeign最简单使用

5.1 引入依赖

org.springframework.cloud

spring-cloud-starter-openfeign

2.1.0.RELEASE

5.2 代码

5.2.1 创建一个接口

@FeignClient(name = "ahhx-jcpt", url = "http://localhost:9099")

public interface GetStringApi {

@RequestMapping(value = "/levelone", method = RequestMethod.GET)

String getString();

}

5.2.2 调用

@Controller

public class IndexController {

@Autowired

private GetStringApi getStringApi;

@ResponseBody

@GetMapping(value = "/index")

public String hello(){

return getStringApi.getString();

}

}

当/index被调用,就会调用GetStringApi 的getString,而getString就会去调用http://localhost:9099/levelone接口

6. 在Logging Admin端用kafka存储日志,并关闭自带的存储数据库操作

6.1 关闭存储数据库操作

删除依赖

删除配置

#spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

#spring.datasource.type=com.zaxxer.hikari.HikariDataSource

#spring.datasource.username=root

#spring.datasource.password=ahhx@123

#spring.datasource.url=jdbc:mysql://192.168.220.46:3306/apiboot

这样admin端,在收到数据以后就只会在控制台打印,不会存数据库

6.2 存储kafka

继承SmartApplicationListener

@Component

public class LocalNoticeSample implements SmartApplicationListener {

@Autowired

private KafkaSender kafkaSender;

@Override

public boolean supportsEventType(Class extends ApplicationEvent> eventType) {

return eventType == ReportLogEvent.class;

}

@Override

public boolean supportsSourceType(Class> sourceType) {

return sourceType == LoggingEndpoint.class;

}

/**

* order 值越小执行越靠前

*

* @return

*/

@Override

public int getOrder() {

return 2;

}

@Override

public void onApplicationEvent(ApplicationEvent applicationEvent) {

System.out.println("onApplicationEvent");

ReportLogEvent reportLogEvent = (ReportLogEvent) applicationEvent;

ApiBootLogClientNotice notice = reportLogEvent.getLogClientNotice();

kafkaSender.sendMessage(notice.getLoggers().toString());

}

}

kafka发送代码:

@EnableBinding(Source.class)

@Component

public class KafkaSender {

private final Logger logger = LoggerFactory.getLogger(KafkaSender.class);

@Autowired

private Source source;

public void sendMessage(String msg){

try {

logger.info("准备发送数据到kafka->数据:【message:"+msg+"】");

source.output().send(MessageBuilder.withPayload(msg).build());

}catch (Exception e){

logger.info("准备发送数据到kafka->出错");

e.printStackTrace();

}

}

}

kafka接收代码

@Component

@EnableBinding(Sink.class)

public class KafkaReceive {

private final Logger logger = LoggerFactory.getLogger(KafkaReceive.class);

@StreamListener(Sink.INPUT)

public void process(Message message) throws Exception {

logger.info("监听到kafka数据->输入参数【message:"+message+"】");

String receivedString = message.getPayload();

logger.info("received kafka message : value:"+receivedString);

}

}

7. 追诉

7.1 提取日志

在admin端想要提取日志,需要写一个类集成SmartApplicationListener 即可。

在Logging端目前无法直接提取日志(2.1.2版本),根据作者说明,在下一版本将可以直接提取日志。

并且据说下一个版本admin端将提供可视界面,以及日志上报到admin可以关闭,让日志不上报。

8. 相关链接

smartadmin mysql_ApiBoot Logging 和Logging Admin使用总结相关推荐

  1. Py之logging:logging的简介、安装、使用方法之详细攻略

    Py之logging:logging的简介.安装.使用方法之详细攻略 目录 logging的简介 logging的安装 logging的使用方法 logging的简介 Python引入了logging ...

  2. Python2.7 logging.config logging.handlers

    为什么80%的码农都做不了架构师?>>>    之前了解过python的logging模块,最近整理笔记时发现还有一篇logging的配置遗漏在角落里没整理出来,在此把logging ...

  3. python logging logger_Python logging.Logger方法代码示例

    本文整理汇总了Python中logging.Logger方法的典型用法代码示例.如果您正苦于以下问题:Python logging.Logger方法的具体用法?Python logging.Logge ...

  4. java logging api_Java Logging API - Tutorial

    1.2. 创建一个logger 包 java.util.logging提供了日志的功能,可以使用类似于下面的代码来创建一个logger: import java.util.logging.Logger ...

  5. Python通过LDAP验证、查找用户(class,logging)

    定义一个类,用于初始化ldap连接,验证.查找用户等功能 # -*- coding: UTF-8 -*- import sys reload(sys) sys.setdefaultencoding(' ...

  6. pycharm console日志如何输出到txt_Django实战2-自动化运维之配置管理-04:知识扩展-logging日志模块...

    日志在程序开发中是非常重要的.在生产环境下,通过日志我们可以查看程序错误信息,处理程序异常.Django利用了python提供的logging模块来记录系统日志. 本节内容参考自Django官方文档, ...

  7. 《flask日志logging一》flask官网介绍logging

    官网地址:http://flask.pocoo.org/docs/dev/logging/ logging实例: @app.route('/login', methods=['POST']) def ...

  8. 关于使用python logging模块的几点总结

    关于使用python logging模块的几点总结 使用python的标准日志模块logging可以非常方便地记录日志.Python日志系统非常丰富.添加结构化或非结构化日志输出到python代码,写 ...

  9. Python中logging.config配置文件解读

    Python中logging.config配置文件解读 下面的函数用于配置logging模块,它们位于logging.config模块中.你可以使用这些函数来配置,也可以在logging或是loggi ...

  10. Python实战之logging模块使用详解

    用Python写代码的时候,在想看的地方写个print xx 就能在控制台上显示打印信息,这样子就能知道它是什么了,但是当我需要看大量的地方或者在一个文件中查看的时候,这时候print就不大方便了,所 ...

最新文章

  1. 11gR2 GI和DB安装目录权限属主被修改后的恢复方法
  2. python数组不同地方
  3. linux怎么查看一个文件夹的大小
  4. 终聚.net平台开发
  5. 【HNOI2019】部分题简要题解
  6. GMF 教程 Mindmap 6
  7. Java7并发编程指南——第六章:并发集合
  8. 麦克马斯特大学计算机科学硕士,2020年麦克马斯特大学硕士要上多久才能毕业...
  9. java.util.concurrent.*下的常见类你了解多少?
  10. 210页的《pandas官方文档中文版》.pdf
  11. mysql能上传程序吗_利用mysql上传和执行文件
  12. 平衡二叉树详解 通俗易懂
  13. android运行ios应用程序,Cider让你在安卓手机上运行iOS应用
  14. 计算机硬件知识调查表,计算机硬件的调研报告(精).docx
  15. 从百草园到三味书屋感想
  16. 制作一个简单的倒计时动画
  17. Unity实时GI与烘焙GI
  18. TFT和STN液晶区别
  19. [LOJ 5516]无聊的数对
  20. html怎么实现首行缩进两个字符

热门文章

  1. Head First 设计模式
  2. 从Java源代码生成类图
  3. VBA实战技巧精粹之按某列相同数据分入同一个sheet
  4. [Excel数据处理与分析实战技巧精粹].Excelhome.扫描版
  5. wmware 安装xp系统虚拟机
  6. 在VB中用DAO实现数据库编程Java教程
  7. EditPlus3破解版下载以及配置java使用教程
  8. 怎样用计算机制作思维导图,如何使用电脑制作成思维导图,这个方法简单又实在...
  9. java实现微博热搜榜_微博热搜数据
  10. JAVA—socket编程