woozoo73/adonistrack

GitHub: woozoo73/adonistrack

一款轻量级的 Java 方法调用追踪与性能分析工具,无需编写代码即可记录调用栈的参数、返回值、异常和执行耗时。

Stars: 4 | Forks: 2

= AdonisTrack image:https://img.shields.io/badge/License-Apache%202.0-blue.svg["许可证", link="https://opensource.org/licenses/Apache-2.0"] image:https://img.shields.io/maven-central/v/com.woozooha/adonistrack.svg["Maven Central", link="https://central.sonatype.com/search?q=g:com.woozooha%20a:adonistrack"] 简单的 Java 性能分析工具。('hazin-tracer' 的轻量级版本) * 可以立即跟踪调用栈。 * 无需编写代码即可跟踪方法调用。 * 提供方法调用信息(参数、返回值、错误和执行时间)。 * 兼容 Spring Framework。 * 并发调用时的信息不会相互混淆。 * 提供扩展点以供自定义。 * ... == 用法 === 1. 将此库添加到您的项目中 image:https://img.shields.io/maven-central/v/com.woozooha/adonistrack.svg["Maven Central", link="https://central.sonatype.com/search?q=g:com.woozooha%20a:adonistrack"] === 2. 将 AdonistrackFilter 添加到您的应用程序中 * 如果您的应用程序不是 Web 应用程序,请跳过此部分。 ## .Application.java [source,java,indent=0] package com.woozooha.adonistrack.test.spring; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import com.woozooha.adonistrack.filter.AdonistrackFilter; @SpringBootApplication public class Application { ``` public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Bean public FilterRegistrationBean profileFilter() { FilterRegistrationBean registrationBean = new FilterRegistrationBean(); registrationBean.setFilter(new AdonistrackFilter()); registrationBean.addUrlPatterns("/*"); return registrationBean; } ``` ## } === 3. 配置您的 aspect 进行分析 * 通过扩展 `ProfileAspect` 创建一个 aspect,例如 `AdonisTrackAspect.java` * 使用 pointcut 表达式配置该 aspect 的 `profilePointcut` 和 `executionPointcut`。 * 您可以使用 pointcut 表达式设置分析目标。 如果您遇到问题,可能需要更改此 @Pointcut 表达式。 以下页面会对您有所帮助。 https://howtodoinjava.com/spring-aop/aspectj-pointcut-expressions/ ## .AdonisTrackAspect.java [source,java,indent=0] package com.woozooha.adonistrack.test.spring; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; import com.woozooha.adonistrack.aspect.ProfileAspect; @Aspect @Component public class AdonisTrackAspect extends ProfileAspect { ``` /** * Fix this @Pointcut expression according to your situation. For * example, modify "com.woozooha.adonistrack.test.spring" to your application's * top-level package name "com.yourcompany.killerapp". */ @Pointcut("execution(* *(..)) && (within(com.woozooha.adonistrack.test.spring..*) || within(com.woozooha.adonistrack.test.spring..*+))") public void executionPointcut() { } ``` ## } === 4. 使用上述 aspect `AdonistrackFilter` 配置和 `AdonisTrackAspect.java` 运行您的应用程序 ## .运行应用程序日志 [indent=0] . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.1.3.RELEASE) ## 2019-04-17 13:45:18.014 INFO 254732 --- [ main] com.woozooha.hello.Application : Starting Application ... 2019-04-17 13:45:33.663 INFO 254732 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 10 ms === 5. 调用您的应用程序并检查日志 当您的应用程序通过 `GET /greeting?name=hello HTTP/1.1` 被调用时 * 这是执行成功时的日志。 ## .输出日志 [indent=0] ## ----> [REQUEST] GET http://localhost:8080/greeting/1 (230.83ms:100.00%) ----> com.woozooha.adonistrack.test.spring.GreetingController.greeting(1) (29.40ms:100.00%) ----> com.woozooha.adonistrack.test.spring.GreetingService.greeting(1) (25.33ms:100.00%) ----> com.sun.proxy.$Proxy87.findById(1) (19.92ms:100.00%) <---- Optional[Greeting(id=1, content=Hello\nfoo)] <---- Greeting(id=1, content=Hello\nfoo) <---- Greeting(id=1, content=Hello\nfoo) <---- [RESPONSE] 200 * 上面的日志表示如下的时序图。 image:diagram-happy.png["图表", link="https://github.com/francoislaberge/diagrams"] * 这是执行失败时的日志。 ## .输出日志 [indent=0] ## ----> [REQUEST] GET http://localhost:8080/greeting/2 (21.97ms:100.00%) ----> com.woozooha.adonistrack.test.spring.GreetingController.greeting(2) (5.60ms:100.00%) ----> com.woozooha.adonistrack.test.spring.GreetingService.greeting(2) (1.66ms:100.00%) ----> com.sun.proxy.$Proxy87.findById(2) (0.71ms:100.00%) <---- Optional.empty <<<<< java.util.NoSuchElementException: No value present <<<<< java.util.NoSuchElementException: No value present <---- [RESPONSE] 200 * 上面的日志表示如下的时序图。 image:diagram-unhappy.png["图表", link="https://github.com/francoislaberge/diagrams"] === 6. 更多选项 要将默认的 "ToStringFormat" 替换为自定义格式,您需要设置属性 "adonistrack.to-string.class"。 ## .Application.java [source,java,indent=0] @SpringBootApplication public class Application { ``` public static void main(String[] args) { System.setProperty("adonistrack.to-string.class", YourCustomToStringFormat.class.getName()); SpringApplication.run(Application.class, args); } ... ``` ## } Adonistrack 支持 load-time-weaving,以实现更强大的分析功能。 如果您想分析 JDBC 查询,请执行以下操作。 * 将 aop.xml 文件添加到您的应用程序项目中。 ## ./META-INF/aop.xml [source,xml,indent=0] ---- * 运行您的应用程序时添加 VM 参数。 ## .VM 参数 ## -javaagent:/{your-home-path}/.m2/repository/org/aspectj/aspectjweaver/1.9.2/aspectjweaver-1.9.2.jar 现在您可以看到 JDBC 查询已进行分析,如下所示。 ## .输出日志 [indent=0] ## ----> [REQUEST] GET http://localhost:8080/greeting/1 (227.91ms:100.00%) ----> com.woozooha.adonistrack.test.spring.GreetingController.greeting(1) (36.04ms:100.00%) ----> com.woozooha.adonistrack.test.spring.GreetingService.greeting(1) (31.40ms:100.00%) ----> com.sun.proxy.$Proxy88.findById(1) (26.41ms:100.00%) | [JDBC] [sql=select greeting0_.id as id1_0_0_, greeting0_.content as content2_0_0_ from greeting greeting0_ where greeting0_.id=?, parameterMap={1=1}] <---- Optional[Greeting(id=1, content=Hello\nfoo)] <---- Greeting(id=1, content=Hello\nfoo) <---- Greeting(id=1, content=Hello\nfoo) <---- [RESPONSE] 200 == 7. 已知问题 === 1. 使用 `AdonisTrackFilter` 时可能会发生 HTTP 状态码不匹配的错误 * 要修复此错误: * 1. 移除 `AdonisTrackFilter`。 ## .Application.java [source,java,indent=0] package com.woozooha.adonistrack.test.spring; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import com.woozooha.adonistrack.filter.AdonistrackFilter; @SpringBootApplication public class Application { ``` public static void main(String[] args) { SpringApplication.run(Application.class, args); } ``` ## } * 2. 根据具体情况,您可以通过创建如下的一点代码来纠正 HTTP 状态码。 ## .AdonistrackInterceptor.java [source,java,indent=0] package com.woozooha.adonistrack.test.spring; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.lang.Nullable; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import com.woozooha.adonistrack.aspect.ProfileAspect; import com.woozooha.adonistrack.domain.Event; import com.woozooha.adonistrack.domain.Invocation; import com.woozooha.adonistrack.domain.RequestInfo; import com.woozooha.adonistrack.domain.RequestInfoEvent; import com.woozooha.adonistrack.domain.ResponseInfo; import com.woozooha.adonistrack.domain.ResponseInfoEvent; public class AdonistrackInterceptor implements HandlerInterceptor { ``` private static ThreadLocal CONTEXT = new ThreadLocal(); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (request.getRequestURI().startsWith("/adonistrack")) { return true; } Invocation invocation = CONTEXT.get(); if (invocation == null) { invocation = before(request); CONTEXT.set(invocation); } return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { if (request.getRequestURI().startsWith("/adonistrack")) { return; } Invocation invocation = CONTEXT.get(); if (invocation != null) { after(invocation, request, response); CONTEXT.set(null); } } private Invocation before(HttpServletRequest request) { Event event = new RequestInfoEvent(new RequestInfo(request)); return ProfileAspect.before(event); } private void after(Invocation invocation, HttpServletRequest request, HttpServletResponse response) { Event event = new ResponseInfoEvent(new ResponseInfo(response)); ProfileAspect.after(invocation, event); } ``` ## } * 3. 添加您的 `AdonisTrackInterceptor`。 ## .WebConfig.java [source,java,indent=0] package com.woozooha.adonistrack.test.spring; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfig implements WebMvcConfigurer { ``` @Override public void addInterceptors(InterceptorRegistry registry) { AdonistrackInterceptor adonistrackInterceptor = new AdonistrackInterceptor(); registry.addInterceptor(adonistrackInterceptor).addPathPatterns("/**/*"); } ``` ## } * 4. 现在,RESPONSE 状态码变为了 `500`。 ## .输出日志 [indent=0] ## ----> [REQUEST] GET http://localhost:8080/greeting/2 (134.97ms:100.00%) ----> com.woozooha.adonistrack.test.spring.GreetingController.greeting(2) (29.34ms:100.00%) ----> com.woozooha.adonistrack.test.spring.GreetingService.greeting(2) (9.78ms:100.00%) ----> com.sun.proxy.$Proxy96.findById(2) (6.15ms:100.00%) | [JDBC] [sql=select greeting0_.id as id1_0_0_, greeting0_.content as content2_0_0_ from greeting greeting0_ where greeting0_.id=?, parameterMap={1=2}] <---- Optional.empty <<<<< java.util.NoSuchElementException: No value present <<<<< java.util.NoSuchElementException: No value present <---- [RESPONSE] 500 == 许可证 AdonisTrack 是开源软件,基于 Apache 2.0 许可证发布。 == 关于 AdonisTrack? 侧金盏花(Adonis)的花语在西方是“悲伤的回忆”,而在东方则是“永恒的幸福”。 image:adonis-flower-01.jpg["Adonis amurensis", link="https://en.wikipedia.org/wiki/Adonis_amurensis", width=42%] image:adonis-flower-02.jpg["Adonis amurensis", link="https://en.wikipedia.org/wiki/Adonis_amurensis", width=42%] image:adonis-flower-03.jpg["Adonis amurensis", link="https://en.wikipedia.org/wiki/Adonis_amurensis", width=42%] image:adonis-flower-04.jpg["Adonis amurensis", link="https://en.wikipedia.org/wiki/Adonis_amurensis", width=42%]
标签:JS文件枚举, SOC Prime, Spring, 域名枚举, 开发工具, 性能分析, 方法跟踪