From 2c50211f0dc027a6b067d5e42fb32697d65b91c8 Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Tue, 11 Sep 2018 17:29:02 +0800 Subject: [PATCH] update site --- Home.html | 384 ++++++++++++++++ README.html | 232 ++++++++++ README_EN.html | 232 ++++++++++ SUMMARY.html | 263 +++++++++++ _images/dashboard.png | Bin 0 -> 172443 bytes _sources/Home.md.txt | 135 ++++++ _sources/README.md.txt | 1 + _sources/README_EN.md.txt | 1 + _sources/SUMMARY.md.txt | 18 + _sources/advanced-use.md.txt | 75 +++ _sources/advice-class.md.txt | 53 +++ _sources/arthas3.md.txt | 112 +++++ _sources/arthas_3_0/home.md.txt | 109 +++++ _sources/arthas_3_0/new_feature.md.txt | 196 ++++++++ _sources/async.md.txt | 65 +++ _sources/auto_structify.md.txt | 245 ++++++++++ _sources/batch-support.md.txt | 39 ++ _sources/classloader.md.txt | 131 ++++++ _sources/commands.md.txt | 37 ++ _sources/dashboard.md.txt | 61 +++ _sources/dump.md.txt | 40 ++ _sources/getstatic.md.txt | 25 + _sources/groovy.md.txt | 170 +++++++ _sources/index.md.txt | 32 +- _sources/install-detail.md.txt | 38 ++ _sources/jad.md.txt | 155 +++++++ _sources/jvm.md.txt | 97 ++++ _sources/keymap.md.txt | 78 ++++ _sources/manual-install.md.txt | 25 + _sources/monitor.md.txt | 51 ++ _sources/options.md.txt | 26 ++ _sources/quick-start.md.txt | 142 ++++++ _sources/redefine.md.txt | 24 + _sources/release-notes.md.txt | 130 ++++++ _sources/reset.md.txt | 54 +++ _sources/roadmap.md.txt | 10 + _sources/save-log.md.txt | 33 ++ _sources/sc.md.txt | 68 +++ _sources/sm.md.txt | 88 ++++ _sources/stack.md.txt | 110 +++++ _sources/start-arthas.md.txt | 72 +++ _sources/sysprop.md.txt | 122 +++++ _sources/thread.md.txt | 165 +++++++ _sources/trace.md.txt | 112 +++++ _sources/tt.md.txt | 221 +++++++++ _sources/usercase.md.txt | 5 + _sources/watch.md.txt | 307 +++++++++++++ _static/add_badges.js | 29 ++ _static/center_page.js | 47 ++ _static/documentation_options.js | 2 +- _static/overrides.css | 250 ++++++++++ advanced-use.html | 344 ++++++++++++++ advice-class.html | 273 +++++++++++ arthas3.html | 334 ++++++++++++++ arthas_3_0/home.html | 412 +++++++++++++++++ arthas_3_0/new_feature.html | 406 ++++++++++++++++ async.html | 344 ++++++++++++++ auto_structify.html | 450 ++++++++++++++++++ batch-support.html | 305 ++++++++++++ classloader.html | 419 +++++++++++++++++ commands.html | 299 ++++++++++++ dashboard.html | 332 +++++++++++++ dump.html | 325 +++++++++++++ genindex.html | 50 +- getstatic.html | 284 ++++++++++++ groovy.html | 424 +++++++++++++++++ index.html | 83 +++- install-detail.html | 282 ++++++++++++ jad.html | 438 ++++++++++++++++++ jvm.html | 367 +++++++++++++++ keymap.html | 401 ++++++++++++++++ manual-install.html | 263 +++++++++++ monitor.html | 368 +++++++++++++++ objects.inv | Bin 236 -> 974 bytes options.html | 332 +++++++++++++ quick-start.html | 385 ++++++++++++++++ redefine.html | 303 ++++++++++++ release-notes.html | 397 ++++++++++++++++ reset.html | 286 ++++++++++++ roadmap.html | 243 ++++++++++ save-log.html | 296 ++++++++++++ sc.html | 363 +++++++++++++++ search.html | 41 +- searchindex.js | 2 +- sm.html | 372 +++++++++++++++ stack.html | 396 ++++++++++++++++ start-arthas.html | 310 +++++++++++++ sysprop.html | 394 ++++++++++++++++ thread.html | 454 ++++++++++++++++++ trace.html | 402 ++++++++++++++++ tt.html | 508 ++++++++++++++++++++ usercase.html | 240 ++++++++++ watch.html | 613 +++++++++++++++++++++++++ 93 files changed, 18628 insertions(+), 29 deletions(-) create mode 100644 Home.html create mode 100644 README.html create mode 100644 README_EN.html create mode 100644 SUMMARY.html create mode 100644 _images/dashboard.png create mode 100644 _sources/Home.md.txt create mode 100644 _sources/README.md.txt create mode 100644 _sources/README_EN.md.txt create mode 100644 _sources/SUMMARY.md.txt create mode 100644 _sources/advanced-use.md.txt create mode 100644 _sources/advice-class.md.txt create mode 100644 _sources/arthas3.md.txt create mode 100644 _sources/arthas_3_0/home.md.txt create mode 100644 _sources/arthas_3_0/new_feature.md.txt create mode 100644 _sources/async.md.txt create mode 100644 _sources/auto_structify.md.txt create mode 100644 _sources/batch-support.md.txt create mode 100644 _sources/classloader.md.txt create mode 100644 _sources/commands.md.txt create mode 100644 _sources/dashboard.md.txt create mode 100644 _sources/dump.md.txt create mode 100644 _sources/getstatic.md.txt create mode 100644 _sources/groovy.md.txt create mode 100644 _sources/install-detail.md.txt create mode 100644 _sources/jad.md.txt create mode 100644 _sources/jvm.md.txt create mode 100644 _sources/keymap.md.txt create mode 100644 _sources/manual-install.md.txt create mode 100644 _sources/monitor.md.txt create mode 100644 _sources/options.md.txt create mode 100644 _sources/quick-start.md.txt create mode 100644 _sources/redefine.md.txt create mode 100644 _sources/release-notes.md.txt create mode 100644 _sources/reset.md.txt create mode 100644 _sources/roadmap.md.txt create mode 100644 _sources/save-log.md.txt create mode 100644 _sources/sc.md.txt create mode 100644 _sources/sm.md.txt create mode 100644 _sources/stack.md.txt create mode 100644 _sources/start-arthas.md.txt create mode 100644 _sources/sysprop.md.txt create mode 100644 _sources/thread.md.txt create mode 100644 _sources/trace.md.txt create mode 100644 _sources/tt.md.txt create mode 100644 _sources/usercase.md.txt create mode 100644 _sources/watch.md.txt create mode 100644 _static/add_badges.js create mode 100644 _static/center_page.js create mode 100644 _static/overrides.css create mode 100644 advanced-use.html create mode 100644 advice-class.html create mode 100644 arthas3.html create mode 100644 arthas_3_0/home.html create mode 100644 arthas_3_0/new_feature.html create mode 100644 async.html create mode 100644 auto_structify.html create mode 100644 batch-support.html create mode 100644 classloader.html create mode 100644 commands.html create mode 100644 dashboard.html create mode 100644 dump.html create mode 100644 getstatic.html create mode 100644 groovy.html create mode 100644 install-detail.html create mode 100644 jad.html create mode 100644 jvm.html create mode 100644 keymap.html create mode 100644 manual-install.html create mode 100644 monitor.html create mode 100644 options.html create mode 100644 quick-start.html create mode 100644 redefine.html create mode 100644 release-notes.html create mode 100644 reset.html create mode 100644 roadmap.html create mode 100644 save-log.html create mode 100644 sc.html create mode 100644 sm.html create mode 100644 stack.html create mode 100644 start-arthas.html create mode 100644 sysprop.html create mode 100644 thread.html create mode 100644 trace.html create mode 100644 tt.html create mode 100644 usercase.html create mode 100644 watch.html diff --git a/Home.html b/Home.html new file mode 100644 index 000000000..bbebbeca5 --- /dev/null +++ b/Home.html @@ -0,0 +1,384 @@ + + + + + + + + + + + Arthas 用户文档 — Arthas 3.0.1-RC-SNAPSHOT 文档 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +
+

Arthas 用户文档

+
+

Arthas(阿尔萨斯) 能为你做什么?

+

当你遇到以下类似问题而束手无策时,你看到了这篇文档,看到了 Arthas,那么恭喜你,你朝正确的方向又迈了一大步。

+
    +
  1. 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
  2. +
  3. 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
  4. +
  5. 遇到问题无法在预发 debug 一下,难道只能通过加日志再重新预发布吗?
  6. +
  7. 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
  8. +
  9. 是否有一个全局视角来查看系统的运行状况?
  10. +
  11. 有什么办法可以监控到容器和中间件(AliTomcat、HSF、Notify 等)的实时运行状态?
  12. +
+

Arthas 是全新的在线诊断工具,采用命令行交互模式,支持web端在线诊断,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。

+
+ +
+

Arthas 安装及使用

+
+

1. 在线诊断

+

TODO

+
+
+

2. 通过脚本使用Arthas

+
    +
  • 下载脚本
  • +
+
+

MAC/Linux

+
curl -L TODO /install.sh | sh
+
+
+
+
+

Windows

+

点击 下载 最新zip包

+
+
如遇无法下载,请参考这里
+
    +
  • 启动 Arthas
  • +
+

./as.sh

+

执行该脚本的用户需要和目标进程具有相同的权限。比如以admin用户来执行:

+

sudo su admin && ./as.shsudo -u admin -EH ./as.sh

+

详细的启动脚本说明,请参考这里

+

如果attatch不上目标进程,可以查看~/logs/arthas/ 目录下的日志。

+
+
+
+

3. 开启诊断之旅

+

为了使你快速找到适合你分析、诊断问题的命令,我们将 Arthas 的命令按问题的类型做了一个大的分类,如下:

+
+

想快速了解系统、应用运行状况

+
+
    +
  • dashboard——当前系统的实时数据面板
  • +
  • thread——查看当前 JVM 的线程堆栈信息
  • +
  • jvm——查看当前 JVM 的信息
  • +
  • sysprop——查看和修改JVM的系统属性
  • +
  • New! getstatic——查看类的静态属性
  • +
+
+
+

类、方法冲突、class文件、classloader继承问题等

+
+
    +
  • sc——查看JVM已加载的类信息
  • +
  • sm——查看已加载类的方法信息
  • +
  • dump——dump 已加载类的 byte code 到特定目录
  • +
  • redefine——加载外部的.class文件,redefine到JVM里
  • +
  • jad——反编译指定已加载类的源码
  • +
  • classloader——查看classloader的继承树,urls,类加载信息,使用classloader去getResource
  • +
+
+
+

查看方法执行参数、异常、返回值、调用路径等

+
+
非常重要,请注意,这些命令,都通过字节码增强技术来实现的,会在指定类的方法中插入一些切面来实现数据统计和观测,因此在线上、预发使用时,请尽量明确需要观测的类、方法以及条件,诊断结束要执行 shutdown 或将增强过的类执行 reset 命令。
+
    +
  • monitor——方法执行监控
  • +
  • watch——方法执行数据观测
  • +
  • trace——方法内部调用路径,并输出方法路径上的每个节点上耗时
  • +
  • stack——输出当前方法被调用的调用路径
  • +
  • tt——方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测
  • +
+
+
+

options

+
    +
  • options——查看或设置Arthas全局开关
  • +
+
+
+

Arthas 基础命令

+
    +
  • help——查看命令帮助信息
  • +
  • cls——清空当前屏幕区域
  • +
  • session——查看当前会话的信息
  • +
  • reset——重置增强类,将被 Arthas 增强过的类全部还原,Arthas 服务端关闭时会重置所有增强过的类
  • +
  • version——输出当前目标 Java 进程所加载的 Arthas 版本号
  • +
  • quit——退出当前 Arthas 客户端,其他 Arthas 客户端不受影响
  • +
  • shutdown——关闭 Arthas 服务端,所有 Arthas 客户端全部退出
  • +
  • keymap——Arthas快捷键列表及自定义快捷键
  • +
+
+
+

管道

+

Arthas支持使用管道对上述命令的结果进行进一步的处理,如sm org.apache.log4j.Logger | grep <init>

+
    +
  • grep——搜索满足条件的结果
  • +
  • plaintext——将命令的结果去除颜色
  • +
  • wc——按行统计输出结果
  • +
+
+
+

后台异步任务

+

当线上出现偶发的问题,比如需要watch某个条件,而这个条件一天可能才会出现一次时,异步后台任务就派上用场了,详情请参考这里

+
    +
  • 使用 > 将结果重写向到日志文件,使用 & 指定命令是后台运行,session断开不影响任务执行(生命周期默认为1天)
  • +
  • jobs——列出所有job
  • +
  • kill——强制终止任务
  • +
  • fg——将暂停的任务拉到前台执行
  • +
  • bg——将暂停的任务放到后台执行
  • +
+
+
+
+

4. 常见问题及FAQ

+

TODO

+
+ +
+

6. 用户使用案例

+ +

钉钉交流群号: TODO

+
+
+
+ + +
+ +
+
+ + +
+ +
+

+ © Copyright 2018, Alibaba Middleware Group, and contributors. + +

+
+ Built with Sphinx using a theme provided by Read the Docs. + +
+ +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/README.html b/README.html new file mode 100644 index 000000000..ef13f0cff --- /dev/null +++ b/README.html @@ -0,0 +1,232 @@ + + + + + + + + + + + <no title> — Arthas 3.0.1-RC-SNAPSHOT 文档 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Arthas 是一款线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方法执行耗时,类加载信息等,大大提升线上问题排查效率

+ + +
+ +
+
+ + +
+ +
+

+ © Copyright 2018, Alibaba Middleware Group, and contributors. + +

+
+ Built with Sphinx using a theme provided by Read the Docs. + +
+ +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/README_EN.html b/README_EN.html new file mode 100644 index 000000000..a53dd8ead --- /dev/null +++ b/README_EN.html @@ -0,0 +1,232 @@ + + + + + + + + + + + <no title> — Arthas 3.0.1-RC-SNAPSHOT 文档 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

This is home.

+ + +
+ +
+
+ + +
+ +
+

+ © Copyright 2018, Alibaba Middleware Group, and contributors. + +

+
+ Built with Sphinx using a theme provided by Read the Docs. + +
+ +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/SUMMARY.html b/SUMMARY.html new file mode 100644 index 000000000..a354fc03d --- /dev/null +++ b/SUMMARY.html @@ -0,0 +1,263 @@ + + + + + + + + + + + <no title> — Arthas 3.0.1-RC-SNAPSHOT 文档 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+ +
+ + +
+ +
+

+ © Copyright 2018, Alibaba Middleware Group, and contributors. + +

+
+ Built with Sphinx using a theme provided by Read the Docs. + +
+ +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/_images/dashboard.png b/_images/dashboard.png new file mode 100644 index 0000000000000000000000000000000000000000..973187731aed18e7b8a37d8f02210688a340245c GIT binary patch literal 172443 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

14~XscBJ1e)oEmoW-j;4l{?a8@icEFo_^0csh$q zfz^_L0pokpsBd4m@K9R0CfznAW4~yNen8BYh=9QydJe3P9ZKZB?$Npr8a*AEKZCG;=m3Sb+PIioWhS9F&>TYpBiy3rXgae?p zQOI5PC-(zqveT~~{oeW&{Pdph>`patt(Syn0=$9UhNxb*5L1**zN~2#7cz`ZfnT&E z5%(NLhtQfZ)>X6?^x?NvYTmj}`Xwt_X64l(Fa7Vb`$uzK8m*}TtKHoGHJ`e+TZ&QX zfM!CtIT4|J6)Nthw^0j6K%aONa4`u((!1%=5#yFqq$L)!wbo#VK}IsrnvU zp8(1aB(}c0!Eb>7;GgmXt$>FM{gLHI`C)cJm22N1f(l)G03oNQ%@~nkAMYmY4~{f4 z?!73$$@IeA5wszIZpX9_hnt(A6Fg}`bZBHZc-_*%&3>93Ey5zqgN$VCHpotu+B$`x zw)>tVyGWZ)Q7tW~eJen!fo>ov49SUbDimwfhbUBDBv0S}87-^j8oOK96d*{u5$G;pDO( z%gZRm5-6gD#;Dnk?+=L;=q0K=!?Yd5{*dLOLgN;{Ws)?pf} zRQFm0>#)1(-U@G%dqqJmOIWrG+8qkWjJ0X)qIpQLSLNxoFn3!fN1DZEADnUoQPhHc z+3uNoaUwej3yB4<+&&epj}|F8w)FqRs3~>X<8IR@9B5-?!}~Q_B|M>&M=7xqCr*X` zBLESuQPbpVv|PQ>hS$m!=|Vvkby|<{8An%G-yeu9T6$oFPaD=zW;)=O3!1@L4e2}B zyg)><%dho|yEv16ot}i5pzCY)&B)j1>dd>jBSosUN#Xy+T*J(MUF{!F;_-t0*1RL( zGlJGQZaOMurQ=Wn8_7=uQ8#bEnkq!dIpe1$HbB1c83UaW8i~!!^rZx)Bd7E~)7shF z+nNG1YtfH2%tb^(f?-yJ8pwS3^qjK9NXLdHm-r11=qo}GNz9MrD5#7>S??g{_22%{ zQ8xxFd8S6Pt@O+#d%TIMVFzcOS?1bUcWhh?)I1nystebr;fI@(UT6B*q%HTAv6`*TNQQDMU`V_Y+aJ zBDw+`-12dL*uV^ofJrHIQR?);wZG%8{9P^V{cTJ;?);kg#46}T+AKvB!Ne9GoPt(&ETaH0)L?eW5)GI&_Z%Hcfw9yy? zU+1s2W7q_X66P=!AP=I7NlFSxs+jaqi35>JYyBflk}L|mx!3Oz7@s`TCY2*M%#~51 zK&f~%&0tJv>1?7cU;;Iw43qk~>trz8IP{&ketaG2RImi^5K&My^@J*?slN003}yon zUu%Jh-<9M)a-An2QS<^AefQ?@L`M?Hs%cKsl4_ynNb7R&87n>;Kxv_e0F)Nh>kE~+ zAc1H{-f=jtCHxF9x5OJeB{?V&2E?oNfBW zHfuaKwbNb*+JV1x+_PrTKat{_0Bt)o17zkHiLWOcYwf1za00W7)gibzks%ip!p)Rf zq9Tz!bAF9jei-n=Y23#r*bv|k1F{`qKXZ`8G~x;xh5&Ip@7U|T5a zYM^6Sw9oq=pw_m(U5s+M(_yKOU_=8J9grqQYny(-B1SkDRWu;C7T<*RHlk#DH{sTy zWwYmNiL5{C9T$Z83ZGM)ct$ukW&96P>o}iq1TRe%;iUbv=iUVTV3Q1GTV+LqM_bEJ z#X<6}+XmE%Q*E$2;F93JGR~S{xci1`IRq!-vKAdX*aMr=SkbL$w7V7(5GVntJ|Iz( zV!sZG)a|ztGIev=pM}v^=Ar^UTeKJ+QHbp3#IA<9_1c2gWPvJuf%gnygU&4>|B=MB z7bPTurcnk966x|2daRQAEyJ6*O$^DKM@Z{lhC^Uqh2}Hpd*2W1UaK&~6FofPj0pA5nU(Avz= z{@+hsExc}rK~&6oJ+9#6ZD0DTRN8$-vMV>~q`YyM_pGMzZGs8ak-iaEbir2qwpvrq zyQ-AV9a)GafOW{F*K8`X*IRFKjhlegnqwupiCFxW-ElbHn$x81kH;)fqSkdkxv7L$ zs8N6VN|sRWp?MYhrd;$hu-@3k>w@A7xJmAKZ_cEGuZlOl~M zt$9`EqgG56Xmwm7apZHv=L_HVh_f(4q-a&alhYg}wxw-v#~jFA4+Tg)_~!O2exx4a zWubb%(NmG=XWuyBiq>KWzQdV5wc*slPHDYP(@l*3wkzL%v!nQvCVu#NsZ3lXWNide zM(L*y*%zF*Ie8j7~u~2=`T{OyWr3r zTmCQKR^sol5v@8>mYOv9#Ud<<^RVJ zy3GX+=Rcid)?}&SRTCGN5Ls8Y)BU$63}uM$)PI0qHl*YjhIC;ETXL#EHSYe2@qIP8M5I4$mxKRND@Gxz7XDIiOH+Gu>yX@j?r+{i{J2?~Ah ztT6Dp)4?}5!SS+T(MN=^E8 zg@DHCmEF7yy!1<(tX%?55au;x;BU9EWn6f(&W)QJXNs+`*S>62?{{sa?m3o5s(<8( zS&A5M--1)e{~ZzIS9$86eg=rR^BwB`cy9$bX-c+_yP@#Z~ z!?QxkzycVOhel1{hNYYP^SXv7X*d=@!!3E*VA!Kkam9H$y6X1C0&UpFSu0rwFk(5u zyzYrrzMww-%Ypw2iR~XYJ|Ho!MIl2^eH2cjdVD%_L0NMMdG13r%0N3BGu6wA33>pR z(^*fIJfh4kL$s%uF@JcNpotwA<`91lNFn{jzaU_j;e39>q=D6Ul> zlNe+853r&A`j!QKo&rn?UBCInPGN42)4s3MeC!GTa$;bWsb>Q-F-h}v-2WpxT#r}I zc`8DWS3AW5hvWP+A4oAljp*~(AX^H!g#?!56=>wk11Q9O$Qe1e-9j#h?GI`3r=RL0 z16ipRn+T?+=OW4m@NDHnzC&?AG{@Lwj_zI>XiTFS{a;>nJYJ&0W2eF>U&Vld&z2hy z*gVFm`Zh90Ld2qqDtFJX47B8BgLIj=lWpLE`nx z`4xd7RFJHRHXNe$;*HnDIy)`h3y*Ife$C(orjVpk)d0#@oplpc+3MxnB=hVyw;(l@ zccFm5AC*IfiyB^^C@~f;+uz>dnwdN_kUIKG&VVYKSg1=|1X0foJdGI#*v?2Yg!I+b zQ@=;q)7-z3SC6}~aFibHZs~IVZ?HTig*7cjxB(MQd?(e}$NatFS}B2UTM97CZpvYm zZ{>3SM?rT_`8PBbqrq)Yz;h~AsGAn!-M6N)3+zTbweUUh?ngR6%h5} zy|(JF#^ySiQ;pNs^<9~DK(&!j`+jD+7Fwuw2xCPXznuNJLdlr8iWK~!e3rWNiBS6U z^{B&{BS2jH5xdZ7UZ&;D<8=!MtaDbTVQz+Xe3EPR1i9z@Cf~H9{$T=cOnj1FX%b{ zHCV%CICz@wu0WJ7g#dxVCv-!5n85R8j>yvuh#y`Hi6MoROm{NMbsedtlL)T)+5Uw* zfUn7m^gCa`SBfnsx!e{kyNs4(Pz~|v&7Of6=CH+0LAy4i*k-*`J)I2+VzOKMwQcFa zTTl6hP>Y_}Odne7j2Xe1%Sa`IgYrU70(8lC;b%f-UBHR2k+mq}wl|3SOw&vMGb4zG zWq=54dIb<+E&e6K?uq?=K!Ukq<7v$2T>l6#{9uE8dkbZGX(Y$fq8({A!X9_T7bU|{ z&t$w1zv}%R0`I(W(PbWDSi2g@IOeBW5Q&pE&NFT5h|*g38^!KUocaWg7DV9!621K~8OtWo&Zz|6NfVueAbgmxmVn>_+1Bjx-1x-p%}ilt z1>c&f{Ug^Jb_Aebq>{vZRi5Er&kNWC{4)S=GB4Wk!k~cu;mI#8!hQ;o;kV0tt}Cb0 z(%II%6TJo_li}Y1WW-rW(;`j?)-fQVmFhik7B;*df$S*y|Iz_|2=vjqyoF&)7XN!o z6&MVtvXB!(a@UB54EXPx3k;~hiWhj$L|Alx2ggZ)fg%CL1(2u9q2a#^BY!jb1GunPR-zv6OX|2UBiTR-x82~vaqQ5*0N=GVQ+(i&?^NIz@>g$6f`2B@D+>43 zFFwPwF{P=ee)pFLxlfov*p_^*pA4hhBj-mH^+9SZ`MR`~S})cFZl5E1L}jAEy`G9U z6uh*jy?k_i+i>@QC!N2P(2m4Gf-(S;+oLP)uLt6gzr34T-d?vO|GF6|kpcxq0s`S% zcYVL#+X%9W7TFe97qj%90V5V&JL1NDn~6yX%;c_vB>xFTz731ZHHnGYR>Iz$ziuSP z|Ez2xgkIv68r~H0#;Nl`q{AnUOamSNfu%nyXqB@D4$?S1!&iy9Y^kzXlzgx{^c75Pw3@F;Z*Ii-s$X4d1M|? z&H`b$Mk}UJzwG>*{2w&Cuc(~{EhD0J>@Z{-vvI0jr^i<~7<>kod3wf>@*$zy>+90c z#lZ+=v7qXA+?LcvVn?$>TY1Q>CTuJA5XywS$8aAY3o5TjWv_iL*5oD=Yb=^ls@E}w zhZ!CTBY1<>{-6soR}Uq;QF%Ls00M$~JN6 zOkKGv+jv})8daFaetzYaG#?*4quCr%v+6?AH_^U!W=HR<*)b9fQPZ3S+;H>IA&fw` z7gw$WEGya*-HF7hj@}JDPg59bC zEh}x*IfV?cNfmnH*xes2FzEI9*m)~II?B*eJxMV$7sBuB0UGJjrNLLMg4hRp6zgsT zrXQ0Ey8iEFHUmuz5NpoR^f-xQ13-Xw@VGlz+Q?1gfp2q&ZC#G74!P*rOy~!RhO~*s z4N+Wh4LgQUJI6loJUnZ;hzGH~NxSb9=fNKL?DGKe;T6JnvK;E|)$tQRK`yy--Zh?m zH>+D!hz?0sQoiBP_O_1zqPw<^v$U;{|}F}#{Azs((Jx}5?WOd zT+`KiU?#PqnUVhhfAB;HeM9{i)fCRT@CkstETI3-gxZcbfN0bJNXKxbtXBl2b0;ub zz(M1uMkhfs5i|A zz6gtiZTJx={*1napvnn$`#0wAtZJcl#=k7l8=&^j$JORjR~`G=aA{B$Y_tO_=hD6h zEJOi?t@JgWyRL--b8BaP4|%}Ki8R7A$4joJ1YtDPac)OEB;Hl3%i;K*o&oRFim1b?e-ci76Y9YsIn9sv^GuO|3SG; z0{t(_EzwDf8m;)+?is1JrSn>QtE$NW^(}h>}FeW{7vG#T>%O;k>cjIXx z|5%vcZ2f-w_P4uV$|ynS3`CvMFQksteUjTtjW>ZNC0Q?!)n}J`fV~4p`H*T4hRBuU z&wCtU2!tiw=%`wFd!`jzy?5;()!)sDkaOKA>&}IH_$s=14kgM8!~D?UKGa^4wPKKj zINul2_@wz1r`a>~HZf4e+OghpBu5#;*x~q12ut!=ROiDu6TindQt1~l6t+a>pBAu9 zQ=c4Md(3@fDv6{3;5+eP14ZMbMj@T z(u5wlMd;frji|_Ty{5T5?CW5KQCxCer;{j}-wAZ#^0ElSxS+r;<|#1Z?nP`1EyRJUOmg?sR2->M|N7BHt%yu+T-o6$Ez1vx+FgVEB&MP`4H@#-%| ze0^mXY_pBB{98BGNe5-a|I%?QzyAaD^1Rh5XL>7SU2qoXvj&Bul8;@gUQGI0-?&C< z$Yjuew`3vi&P7D~9nG&i%Mn23;c9D0P67D*^~>%#7>k2WE8&@zlyFjaz$c~ugFdY)ZCl)>*z zqFVNXIiYBEqh3ZaiUmcFu zA(g(&Y~%qMNF;?EX$K0B%~SaiTz_z_!GtN}-WX+2`4Joqv?rYN*Dw(-dFizRVCdct zTASQrRQyE9)?N)%d!_>m0;W3$TiI68Mxb;627sfA0Vc9!MEd&36@W*VcoVZTkGQLR zm0MLtL1)zNtq!pjm!Ch%S{*;{nLv;Cg)BC*Z7d~WG3=2YClsZP zP4}Out9DS`%%ko{#A-k2p8DxO7x_ONq5hef0>Qki4SB|x7w;((MJ_P-Erp0sQVHGsU5#X?3M<16E6VlS zzjgECEA)$RhuvEaWGlsnq<1IsM#fa< zVFCNT@1k2f+FN`9+os_>t2FIHY>84`EzYh$wFqQP$?2d`bq|c84OmV!TOCVpLsCtm zpBssJC*~tU;W>zKO<5Qre&8HQOw=b~h%XuW{cRR|M0G272buIc^x|zt#n*OZ6Talg z+Lfn0vzuwxez+8OytkR8#vzEeJ}zVp!|JZj_)G2?z8jh)Jr*|$-V77_8U?mP5U+Ma zmtbFv{Z#YYn^0(1f&rpE$6SfkIeoRX{>|Z++^BRecy0Ikp6Q|$h2o0T(yuAdRfQaQ zjjQf_Dh*FyG_1BauX5hfdf9bnZ620 zCezsvU9EUKAd_GhY~bDTpDlpbQ%=bwQz4nmjg`daqsh@3l8gZ>$maOfd=Xh)S|=gny>IL9hr!1sK8TcdCm`nP? zTM0yn)LgG=z+YU~v^|W2t7M9Rr%W5ktfoI7-yAZGgPXO()Y-=o`9}G8Zhz;#WT*a) zj%{~~<}EbV!nc_sX4ypIAf5Ho>GJp;23QXFyPyWP!d%rol*Rm527oE5Q|q2tZzOPEh46K!N<~MM?EZ5d)bKg?``g zzEk7q$si%H%*vEj=G&xZg>$S=HycD}l=9N&2m9Y);ukZo9qnSW=wrXs4{2-)7$kNZ zD&qR$M{mVa=-Gg!`;Qii_0?^oI;3+jQJgf%E@lm`ut+juP5A@o4SWK9QeJYKTqP5R zo8uTSGB{q_`m*77Nl3DDu%=^U&jyF;w+|P_R|lcHv$=4ga>fMiVZoFb**dX7+Wta0 zVT>kdC`KUD--g?3Z)wU?I38-gUpy~Bh`7Y=UGjAM+FEP|$(PND$tBat{l`?zS$gZ) zbB~EJ1)&pc zcE=o+!WL-u(xs8gYb*IHv0-O4yK@|9XW9a#UPSZapj(jCC~>Rb4vC}ryuPDn<7OJ_ z3XD9%s!^&?Zn@;l5O|6t0PBHH{&mN@ig@x@dmG#^C^;pIdiCc_p2weE+cs6x=j__= zeR1#pPN~;a0dk3UPv{cna8oR}&PFIBC=ScjZc`m^Dro#4HF{9D1ZMm(HP zuh6BU8>wkzUq0t{xsI1F`d;J$B8%zOf|Ng^Ekh=+RONNo3sD`P<`UOhjoDFbcrp=ML8n@z1TZf{E{x*tx&r z3=6>ZjL1Z`cW&B~O}I;zDR9; zjxg_K=afX0I-4C3=YDq2dRDdFQzR|GE5Wx#Tukyoj-U4AhP+wfX&dy{rs#hJV zVSy}b#3*_S3?g^ut225=CfL`79o0x}jBU0v$W1HaE5LUl-_u>=6Z z0>X_{&fIjTew$l=^#=xw|^A8_(Ym@@K^*bn1Msc31N z{Y03?&GN|6cM#FngJlDOiloQB<^soqd@?qGiR+tsKH=Nf55iT8l0G$Iz@oSJ*y4<= z8=5o5jub(nO+7lUCyb_$U6zr<`s!B7XXnz`xrUhS(ytu73 zg)5$%ln9`tyoJ|zV;ri6YUH8r9g2lvBAoiN;q^H>m!>7v-&b!R=1__U=~l8la^y#+ zXT3{gXPU^9;)Q!&t`i#am%?g}sbf-8qPA!cC8O}hxGry~94WgsQ?kSA|A%VsFkSuY zp#B^R;_Y?ac0Qhr%W#^{3mi^d4rgjZ$>(1#s5CK-H)-32Hjcwwp5Xr?fx&-~z*`oT zXqsnh9JV*`=RKa_Zx!(SSFe+*od~)f>{ve^ZeHkY+BP!4u`%F|H1r{VFj>j7tl)94 zl$FWzcvcELW7W$uTtfgpNZ|96+v6^L3D;RHT{cwYLFX`<$ZiOy!j9!pvhCDw;!TRp zMn!B2n#%r0hmRrFo)9>iY4P|>>7vWK{etDZv`>C_t$L(BWXHA&hz!Xwef}pk%zZeD zN$|7f?ggFY#Ti%Yct8`rhGZaM=j6%}rKW*;lmXKSW`RiI`($;37Y=ZB4qIO}h>F4z zD;YHO*Nu}9s{$R95e}MuvMn7Ft#m_Qvz^kTCAI{s_qwjQ(gS9*x|@l(8bnvRFS@rm z(+4+Vtb+EmzU27tDDa<}$NfRq8AF1bs!6g}QiATIMg=iPEXft8{o; zE3=dm6OTXy9h5&Kj8$fRz*eV_YITdY(-Ec(JdHNdPUK-iWQ(_e{(*CTK}j}>ND2?v z2`lbJRfXw=L@w}MG#~u;Ue5PMNGTv}5iFNwz8=QR>lO+rua(B%CY0JrJd? zPlrCrSN-&$unhTQ#y`0O=QW=D-fbJZ0_r#_{4xLn??e9-7y~(eYt&EH7WW9&aQ#%t zzg%FZcAMKN>Ipp-B5Nv$93?UF%yT$pdbxH6Z-72{cDXH=+l4d6IU!z2mx9R*hz+>8 zf=ec?F-z8}WKVMAxrd))*X{BH63MN`%k90Mobvd+6y=3eaY4z<1(&Vo=`NjZOEz$+ z3ecI(HGO~e1?IKEmfS55sgW*VfIdnF4|Y30Q-?m^!?c?lYe`H1D*272@e?8~7+IO) zJbMSz1Q==exp_J2pxq6Jh_V#0o_CAXyA2kT{*V^bYj#n_}nD zQNtOyk(vDm@$|z1s&x18PyHs5{#S$*+n2g>PrybQ)^tfTFjG9++4R>p*#BU%B$ywe z0Y8GMvXs9Ubv-;mcf!sW2ITh$|DK)#egfq~)J8B#Df!>OK$igU0xwTkBl!P#v;V3R zF!&)&K15X_uSKyL%lC2JbM1@j+t77}e^XWG_@zFWpaEJSa`?N}!zF zXyYr32^9y`(WqOem;6|A1f9!|$9S*Rr5Q7=CNf!bv7FEbi$>^(1YabJ1pHQhL?S)$ z?LyZAGtZRIA&~7pc@N>qoriRKbMzLfL3Oy?9S=@g?qHo-UI!qSTI~wo2r@pc@ELE8Awet`2IG{sGM+~;_paL!+=BeggiVt zBJl(b-si|r9TG5#u?*C}12P-z*PVQ_B?)~kL7>qxFTI$ za(5j;A`JJJpDRqq7DH+Wdt^)n=@K>_O@1*K^(eMb%lB3pXgHHxr9$9%pEFNfdJ3ew zAf)OGIA%`h1#3)DC$piEzhE6c;L2@0hduM2$X|i|sKTcwL=sczkC8NCW9z?{?QxxE z@K}QRTJbiU1|Xnp3tVyaF1B5=9^PN4^lI|t2!P)V_H0@@{6JRp87jMMtcpW?K=APR zUvA`2h-GN89keShwR1U1MxT+dtVtridza?YKYZt>%L1fS<#eG$xh(<1&pI%o>2v~z zz8ov0rH2e$MO4|q_Nxr?b_Y8IFo-U9jH!1PqV#j^ZFbClD=VwYaXJiqdNaZ3`2Hy> z<63B*jDZA{%ai1>Sa>Ta5A^PMP)czKW>xLvgBPxjnwA3_K{7QZ_W!deAfA0c{RuxV zKY&tjY3M24}69>IO-u1?(BMUiB{z3TvVeA{DG})GIyUVuOU0t?q+qP{RUAAr8 zwr$&8_{uh3?Q_n4cb_}nkN0bh9655W9J!DYGiJ<4$RseqG^VZc*FUijiz1Qp-~Osr zSqcn(MYh!&43imd63f3$UXic58mWN75%>(3)Wh4WQnRWS@w2GBoi6E49v ztGuPEA7`lC@I7!fGEv*CB)0}(5Byx9f#_D9Qz*ANzZUE>P9uUtqUje48}1_LWv@J= zpn73f{?)Y3zsR%*|3ju_8*q#ezdOL%1_r*77;gs!BYtUIK=hPaQH=AmgA-TZ-JSZ* zH+ja{iNJ(R2A1O>3}e%F4H(YXI7S_TFy6XuHePAHGpMc$z)E^GaY41clML)79MIQ=aN>4Jla4904{t*!9 zNbzBKQ@@n6Q~Mkeia_)?`pIsPq0)p4J+)rjJ|7Y+zn9?mV7MQyn$R9=$8=IB=kblj zKC$~BvIUg&w=>)*YRas^UXh%@0oYA>KIErhG6C;)8oudAe5vXd zv5UO+iZ6s&SIVLLrBcHZ{0^EurO;wOSC8hFQ!F57Fil`z;rJ(~wy@=&oLW>hgGy(s zfxi%D!D`^nVs8G}&fHHo?AxH@dH>U&U(zi9;w)==ok}p?AwC&wj~#=&rF^NYoE7h! zvUzU?_!uzj>>5-dgwrCcxCcV+zMK$fOOW*x{ZPI>4YXii^`p7UQ*rJ9$Hhtf9C`8? zSf{jscF-K*n6^)ZLH+Eu$N5sC`2XV2s-xn;ots0df4V(xNh`wbxed<;N&^5(Mx*5Zf8*R*Y8Q(bHklozOHWnf z{(vhQzo;_0$%^rIvul$;Sg-_6dR&@MN4kZ3@&Bbokm@6F+Iy6Us;evrUgrHQ;s_VA z;CnE=oXg<}Ro8qb;ys4auw=KWa=OX$!|H1LF5^@_lP&6u9 zc%6fz)@d31I1(fHxK>}-jj}2%1<2vQX|hz2dSDfsO=zX{MLF;O>~DI*+*6k2K+KY$ zuGB23vztDAi*590R?fQ0UkGUh{{&cHRSOhdDCWqYTecP#nl%pr1SaJPv(rT(v6K5R zbPk1pKwoY8e@h$?O!wqWBcE1sZ2A2n0HT{k9-#r~S^Wzjb$kO&U#{#wEX#b#IbhAG z?4d}amN_>u=B*eXUBm1v{Cy@g>>_fuMk54M-hjM?{^{P@ou05-{296)?B9tOsfyy97fD*GR8$cV-lADJcL4A~pa*FBT zt>%TaT5UI?43}*V4-^ z=>7{jm6cwVp`+-4y|2vBkH!cO_0N~UC)j~DMy`sKdvR7od4?#yCd#C+p3#zmz9M`M zFGxWM82AFblcFteuvWtdUZ=pf7EYh4hW!DzU+b`%`?6>=yR%& zxaye(HUg#{5scciXfC6DNfk!YqCQbih}t6|g-7oV9s}94jdlaf7$<>>KFfcAQGfZM zk##?>(?dO>M!$NtFQk>NzwOO+q%9;tz34CC(mM>(QV?{UK{9=eGd_62!ElBIZrUB? zIz!iG@*?^#u>&WvC^Ox6T=}x-d*?=EAx(eG5-U5j5BXj zo+~JAvk#cqV3%KHbjU0PlzmOY_oJ>Ja4+|ciL5Oha~sc^ue5*DcL!UObrK9m$QLW1 z$+gJe{BIR4O5dv&Rc`Rg=Pj3?>y6EVLYb=@c|_aMU=VG3{-a>985jBw1%s+(6?Jpj zzcm;rD*1-a7vu7+HNCn9B? z(0n65!D|(l8=%`z`OWp1)i+LbxxD_jnB?L;uey@=x+UTTrk^iCAiZ`x@!_D~R3q#o=zYVTM9gUw}-NDPp#*K!C zO^|$f*uXqG+LHIQ=Qkyo<Y{EMP z%D-)diV1Dre)>@zeK_3g&!Iyf`wDt=E&WWB-dzoU?Y{g&SC-2@*FBK%6e^f!34WW2{g8Z9$5+eCt|ap;qLo@-DTyYjLOr zGX9FRZD`e{=y+q1)PhRtv@((h%*1cg@Xy)8>Snmr8!gY_9ZJa46F|3?*S0 zWGWx^Q6;UPi+AZOX8f+l#~g@rDarn>!q!|z&LGk0V}7EgW319*!=)@1Bkl-b7o8{q z2{-uOkq$>OEi8WtBqXeQ3Cjhey}8<4?mXjUpAghxkJaEx8fbmY+Cgz2un`>Rr+wtP zX_GOez74nK+B2Os5Qn3}r(g2%=V2T`jr;U=k+EQFDaE*A2*&l0n=W zr2moVb{e{Ozg|1+97@PS^7961Sv^O&%zO1J7^eZ5VjGrgwo7`B*!`+ceDtR}6bP_= z1@@r-JXqDw(CCG4d{;VKt~K(w+Ty>;eeWKI+9CNFpBd=(X`aZ6E%heU z%Ek!qaKny}pTXL$37(p+Jk%*(0Q9Q0CK6!MObPwse$pk}hgXYU`$!Zp5Au>zY2l{! zwV$kZ9Xyky&VfO&TZr{v2x>~}Zx5N!M1{`lCqFhmK2rNR7^#8*e*im4ngaw<(prpB zSg!%*2}wa4pwnPkWF$nU?@KMg_Uvde<=XT+Qfu65*CXt~k1$Xyw$tUoLb&qS6ah!c zI7~AJlO1q2&ZmezPbDEXZstwQtGnk&rbl}fRhu3UpS3CAF>yIOZdh#lLHf$i+dp5F z*nFxl#?luj_Q;ZKi-!%d2prvDE_ZuhW-R~u1IOINd%2o<*L^K-a&XEEBWY9XIK`?D z7n!^NME<<3VulT7GO>7TQA20eVtJjLJ=|x>?DpMA=;pNzO&ZE6$30~m1Kq)k+9Bqh zS*d=z?Ge?)O$S%NDYCtrg5>_>z=(tPcL#PR1crlbn;IjJVS z&*Oo83k9nIc-I1y`=SKYh}w;$UvLR0hmaF}0rKT1PH!0;uEjS4hgey)9kSOh_wTk} zh0MI^MUQ^tnKQ?f@@{wWgQ1Ik4Ji z5em>VJ`xQu_4RTx_)|&4rV|&!Qq7UsJzB=ft+5WO0^veok3!n8}o$0_x z=1IVmE#_U87X$m;!frjH{TDk{)d|0E9K~0-UCty7e2N-c@~n_1@7iPf$4@o^Hl>@H zF7}L8GSr~alP&_8jewTZW42+iC+xHIN1V9U-znqHtN+GKQ~RIU8WjJj5j&dqZ|Q|8 z6b~-op6E813XQ*TRGb7e91=Md<&rFjWrU|YGd-?AEO{9 z`ag{>y>{~2E;>Hp^KyP*d=ixiGRBztlNI?x7P0F$##FZT3ajx)v?#U}d>Nz#v6az6 z=lk*0D{ra>q@0UwaR|xc>SD8m@~V(2rYK0VBVqg~42Up5-=Asv-@T?g8Tw&1Jor!y zcQVi?Hd>D^AH6=jr`aAgua_$4e%)o}WT4e4CGkNi0TfEBN@}S|sLhSE!@?KwSU_x6 z`C(N+PsFa3#vzkFrkKT`$fR;6Ls5eCD6Q|xx6}ugwS!Izp2kYMCQ!@gH*A4AAties zy?{$(U}-e~&{4Yeeff08B5(YJJts?6<(cFZ*J*iCiCOd z3p3St&;(+&X$Ja$$O?FheMTGR>zCv9)`ib62rP4aj896lKIJ^Q=Ay+gwS{3F+W++K z)k6Us<>@(ajj%HJCMMkEebrvIq{ki=3cfYZL&p&oCa=zEV2s@JubI9Zs0VuUDF?aB zd$wyde2iP4M-LhsNuTlFFl4PD@g8B%e7Bg`$h!tvZybmO^7E$ka80_lrEnH48ole! z9tDWLC!IpRvPc^fb%}gR%OICT_M!~S{{pL;TahyIOtOO+v>MJsZFuKe^ zHMgtfaEE!djXEpqN-Qt^;$F4X-QHOE;@dsFO zZq)>mFz);a{mqYBIwz)Y_x}(zQN&d9k%;v{Iz^sfT*dNEI;%@s!Su-6oeJaN^d- zpCEPy8j!%}yo-3o{Zscg0maAVbL$2z*oJN;e1F*Mrvq=pw7nH6HoB7v5$gKy6kTJa zt&^gJIgz;zB>smxt`kV^CIHcdnqo=Ev1OQS(~v*u_`!zvuU94hJ#}ws=<>s)}*E+~}$99)<4y z<4IrS8aW`(!DV5FD3bL5>hnKc=lFmas(8v^!?PUgAZ(zL^g!AIWqkWz4J{`mrFI8~ zL6FIuYuW$2)_=PASL5d);7if<81xH1@c%W8ZVFP&<_V|d{8;=TWQ06WW(g%Z|0$!* zgiEoCirsuTuZa~=Sk;2)D=Q}2z6sJRVy9Qi0!DH36q3w*Jm;A4<5V1DX` zg}5S0?K8M77} zBdBbW47;utDBB0Y<2IreEjO@BA5Abb`E@vj&SbsD>R^nULHK!D!|rd;nbiCBVZzs2 zE#T;S&JI7jPSPUpd&ehUoKFWS3$iQw6;1_cvnh6mHuiKL{dq0i;O2NLYe~Z+N7&!E zVR&5OK54g6S;XyQZd>u1rJ&jNjdiU|eH-HWbMeIN8TTe?qisu@P>HM0HVvBe)h%pt zni|0@vnt9Tu=N`t0HiFP5Zp`ghHZ|zGD61m1 zjlJ1ytE!>jWjw{K(AXV>O0(2q%20Ju_J-n8N`Slt5-LnCwCYoYkNF6n8pCmG-zEGe z1O4|7(ftKt2;ZD{O{TF?_}v21dgkC6X&#NA8N_BF`0^lb&LY~4=Pq~}2Aom*9YifL z^O&(Ax3dY#YM-R1svL2!;4Uhg7L4Bk77GhHCQCy6a;4POJ&=bJAH#obPP0RYfUGqW z7uU3!oUrf_4e#zQ;MbsIdnNGpZ5l-GJ-Pij(PDZK&{IPWR9^}}cb~_a)$dho$64bS zNG`CHWIsdN;kuS7TC?zsZ%0hR7M;R%KPtu5m#zohelFS2qUeG9z}QpiFA+Im@#^^q zx0$Dj+E&zwFa?sBcm-1Fl*UtN06ThXYwHL_{t=Pl8jz9?in{U%ohDJ?vQZQZ<5s;c ziDRyup;Z74N21AC>g#9ansC|3QLQDJ=6PGr=O0pP=B=LE2>vu)$3A*&Id{xwzh%@$ z&r2iRQDC|4gCh(@Tu0R-HT@vQBRGFDp3|WmupnjI4D=Mlx_BI~SY;cnOhd+TWu4fF2^Cwr5XoZ{p zs-N?%u9utB$8-2RUL6pZht9jF9iO?VSRQY*j!dR_S;}$v11>iBd{(n;j?}8X7cse& z+7!%l4=2)wTID^H*ZXu%xoGeiJV7=xNBQ#<-wZ6Eb4VsVPv*m)cA1bEKiqU6MIA(L zP(z8MRoB|mWTp0PyPvzR(rAd9>g8MUoc7qsO|ypGw(3=nhQazPTiid$E8SM3)UGy! zXS5MAmnQ*k(UX16h3;mH z?&K7-za5)~YQ!03VE$f{x*i~gs5->L=$WBy$FYzz$&G#9hsY^RO`-`?-W_)!HAnS& zs`^~iBC~Sx_Fs(MvoqQ(>6F@)@8a(+$d%vawyA>zPt_v}V4^YMNnWU4uzqD{ly<4N zB;omg{6X}bC(_->5PBO>j{W)BatSiPM^V`4nkH}I#=YYIT^_U82A(It`c5Ff3nV+^ z8E9J>bw58(U+Gx)b?Z=T%8?nI-=m| zpl0a3YU)*_bD~JI(GGmGbZ;zMNEl z|DAYwATdN>JGHP)pO+SGV6(KYDYJBTrKe5AZf~5UDN*24%UJDD4(?#|Ei9O^s(wIP9ZQb86$aB;13vH+kb%qa3nn@zsq0%P;Qa4O@5A$yMun zXruTwiH2V%pdN3J(-4Yypzlqe{c-s5Ory*(Ez9hTXvaOl7SGF1>JtmPD7esD9YSsx z-lk?cy)Jt$EEeT7%@^`+h(t%$rQMD4Jvb;iY{npK3LVSNverMy#~K=P8fw28h*)U5 z@vZzax<&9Z1#=tsH-?GswD;j-KUSLwf*#gh@L1REq^gU78-qR%ZO57Io60=hJ09gQ zLE1|p;5-m76g#jaWOh(E0(ylfcu&LByUM@TA3JkJjMRNUrwPYKk(S~mdX1H0^PrNg zT`>46m$0)|V<4+Cp;fJUryZgYda%zbo^phn{{Jbh6P7lZZnoP z?hm)_7gHSmq$-BV#^KNpVl`M|rK4@PTjCQ>Uu~mZ@&bK3>Wto~lgIIDR=hL$^krG1 zvO}+~^h)(-(viHs?+=*6X=t4qe(S+yFgg9C9I8vLMI$hu)E_;GT!bYH>hWjY9hV~e5J%7*FcVl zuv9fhns|Y$s%Q?AJEYcBm}p%Ww8`sLP>gw@8ui!Ed!GWyWjp_FVm>kxw zo5-lDLVnAIOS=54k=A3FKH}1G&fLZddZ<;JfE&%JtGbD|cROS^FUBZejk~dpU^uX~ zTk75%=bW@B01{(eJ)k)nrGL$vfymYG^f>3SV!VUx~WS)Z|}@);W;v zfCY8M3HL7-B#6sz==U#H^))Dw<<(@- z$l-6vJzgu1mQB3L#j$@I`50;-7y9M5BS5`{|LxiQ$3wz!13_tKkLHwX75tx9_=g*l zpXj@H8X-)9K+W>^@%@jx89gHeJ*eBUiP@T1f4f`%<=5bW{6W?ERQ;1ZDN^ABzx+n> z)yW9b%-{u|xI4Ri+(VDf&|p@AV?n&v9A0K)Ww-QQau$k(mk;9`)?{7zK{XV5qx~U% zI$=_6LIIwUBo(!_311Jsn4-vIfcnN>^1oiW1VPp!K9yy#ONU6(`mY7&FX7ucHS(h4 zqO4may1ef#e|+yTz_I>nfnmLhu{xbM4{HPa2PAOF%M~AWu-6Wqx+- zU}3Xo+*z3B3#p06)KX}NBz`87N$C2OVG&__>BLwfdc0P(%}II1Netw-MZPrg6KWf- zG2NF!;{0*xTv9Sc$L8XazzZkH=Z=Alkoo35FTA@znpoM!Ok$&?zWqV9yCTo~#M`x$YpM|; zfz2{txZm?_15hg5=m)YhlV6%6%{hJCt?PtHi6c3FP)73yk{d58lRqhZ9M2K?Fs0hX z;n%e#47|}clL2AJ)$={8X<#P=8$(M*n-on|Jduw|!%X@^ie&=KM_A}*B4Mb*Zb}m& zhlC0<&dE@pos|#5jmQq<)1TS_XW2pM3`(o1Z+A2r+7ZtBTE}jc$aD4eftJ@i3ZgPR z6jFjtnuuy6L1F-1Bl&DR3d3btwo_7qu2sc$5WcczuKk_vLgx?%40SkmKdH~gKc^8^ zKaO}B-d=Yqmx#+B-n{}S)~D=v`pGZd@K)W^2^Df9!ffQ+yJie=zOt&7AUz~ganlGC z8&iYowfOrB9ibs=`wH8b?GSpwPPDYZ__9lp`BzWS$i6)@(wfB%HT=#6#4VPg(X7zB z>FG~(Q;n@$9W)e+s*APpi(8l$HO!H9I}j+&xXhIll?#bJ2FECxt6SwMu`9fn#42+* ztrjhE`bSm@V;TYCKu)x;mEtlFD9GpmVs}=GQB)|~vAsfK+{Eoz=%@5HYE$$=v{FM4 zY)hKnApKJHdlndIMq*OVWS2s6?uqCYtBWt82^5x}fks@hWd3_mMbtmj*AzcJ%c_IG za-$Z7(gNh6J#5b%`Q@a-YqtxG{V*7{=v2z2(koszwme@>Y#t4D5ZNQn zVZ@}zy1R6|YTI}k9mgV}A0XYu1x+%|>?Ps^MB;D^dNg(ds(kpa{Dg@siwgt#;+ zLJFxASOvrGP2@|LAUSQp<&tsjp_^&mHO|bQpCf1IS*`1+mf^74lQm`@AFcNX}VeDq3&Yc<}}s=#2-QCvIuUy zl-IGs9%OOpt1QF(OPFV^N)?qx0h%=gFblpI)#qdoJLw5lz%Q;t zUT2l5xSM$Dj81tH#*{?;arSwy%B}6VHyA~e$QWr3**S)3D0iszM0}^O?M_xa&zdVB z_ke?5AW`pwhV1?)DUybLHLP|>HCKcZ_L_+M;%!}Z$KiuZU$sg4hROEyZB=wrP;xg1 zna{>KZZbM1{18}cxgQtF(3!wsRNbw3*iN>+kY(6<$v*6&TtA)!L$zaZc-A1pqwXV5I5rt@?vVTJB7v2b@d3~Fn=MV{H*@!%ejb#b{Ih(@BK5s1kema%$d&)9ReF ztIAG0)K3uY-4% zJ!{-?=l1433KIVWH0b8Tn%Csdvbw99fjZ}EjM2tXulx5$a%()eYWNNqm=c%~S0q%O zaTCu%zp$AEn&TU(b?U*7(YM~FIigSr1*%O7b>YBPjq5_Vo(`qq7SPF#L^)#I4!^Eq zSjOrf{)$5p<&IiXo8mMER8~5~T+IoUf5h!1DC}Vyj3%GXEJ)V%F~}2`L&1?n_`_PP*6hDAiPmkzvx}Su)*2n3oT0$PnM&5@bff)rXpcMF%y6d& zn)@-+)T(-@W^*uI01}flpD&5gN}9l67Gs3Kj%l)A5LN)g0y*hu@ii-C9{2}?8z!nZ z^<8Mwg?UOEx4HI1kc7%GM&mhjk`B11<_I@t`eCVgs;4zlPA)ZFg-U$Ad(U2Cc1R>% z5%Dvd@uTk&=><>ZkIn3BX%?-EtwPz`(WpA?;k={&o|K4EMeo8*Dw9DH?gIb!g(0lC zJqiZl-0J`=nMK;gHEz`BfwrZ^eOi7yb-`op>%?R}atqCC+zNJ=={_aX zc%@hGM*E@j34=n9B#{gT{@_CBj5e9iV8ru{xt&|C!+R8WY?8IV+BFu@Se}VUbS*$0asVpaHSJ!gJZZ;~ zn&E$rd=@D`%*$W;_Np8K*Ea-ZWW06_91pv+9V8bZ4(Bf|(Z@Y_&rhFSmZ;UR%k)>- zR(pk!o|-)*gUNRHH%5xy@2FLqv}1OsVC3U8yG!ImtI2AkB#n&9&ARKF6-EHEZ0TA_ zTI#Wbv+_3SI(%S{cIS@A_&~?Xet5i`p?hawRh<6V)W)-ugM&RMB>u?&balH#Y(y>yv(jM%7=8-yO(MXL?0KCw*M|kgAIaDlPUT-_*A1 z;x~q#7{EHPdql|zLL2?HZ5&d_(d}`-OC| zt5jMeV?Wqp2xBpM)LxF3A47fZ(<_!9w~GgEOxeCm_x$F)T>Um5R{ad3W)`H4pkfkV zfc(Yq;pAdggn%uKr=wAVOg^pwn|~-Pl33*z_fBjP3ZKkro^|LTZl_4~I5u3jSx)2fiEhKDILVMS~0q@0v#b#zCP z8h@NwjEyymt|Ydb~uKp zcuHybt(IAcKcG5vlX3N*(_p{@iiU~iKr^Y6Hc%i7S2x>#{b?zAXl|hDsLBn?5{XP) zL)$mN^5W(xJCR|_ENU2ugf8&ByWHB;Z#1vwT%xUh8jFxya4QQKT_b-<-XC2fD)gki z|9*z5&+g;%vru&Ha!y%1`0l)wFsZ(1&hh8yT?zCi;!5D7{T7gZ1{KQ*1Q4RB? z;3^39%QB`qF|NKLSUso9`eqcjx{#H65_IzFQrQ=QN&+%*BoR=QzTLQ~rm|2?)m_wb zIq6bjJDNvjI-48@pu2Crl0h=3d?Zr%NINfyjM>jy+nzhkm^eDX97n{hq%3&)8g2~b zX0kf?Bx_{ccp9ku37L(wNWo20ch7`9rNVy-@vl`8W&pcL7sf6#NE>-xi6i6mtgGzY zZkL5h!kBuaK8VN7g2ha%FT$g0<?UZ1p)U?SuiYHU^(b-@gjgiI^H0YFg+v^~pOWbJa6vRz#pE+M>oN-;??7}~jc z)ckri3bzuYIAzP_`pv8^JhS9XrriC5Qfdei2tWn3Y5y{BewoE} z7ZjlVZem0I4zN+{sP!m;XX*0KNc2BrcP^-l0F*J@#@(8z1trXpu~66C6?;~4F2&r= z^JJOpJsg^0M#p(xk!01@4$OC}aPZi!l6}6LHL5Ugw~q%Iy*%C1?&Zxr-g;sQKQl_c z0BI8kRY<}}3ATBf3H1>-o8O4fmj60Jbu>MJJ(^&f$LUu|4Dg>u6kq3FqNnX+x_Pn#SVxI!W7tl=QF=h z^=ZYDF4y@V||#-p#1~@$#PFPYR`8DT+H_fe8DGv)<6dBG{N(Wl5ec0sGMTpqLLIi(vbURyC4;iu0lU=GhtJV z?O5muAUsqo`O}EOT5UjkXD!jA(8C#Oi0P%<1b|}~KG7j%Na}$-tEs{2n}&O_3qv4R zA~^Gv?))f0Jb*>CA$fmODTa0#vWyi*a{IC(RS+1EFb`zX`iF$b2(8G=G$i2i^%Q}$ zRS)`AAoc``k)~gU*Y+o@N~&X0uZ4iTF>g$3X7#aD2~Ehr8RS>m0?H-t{Gt0zj2LI1 zb}Drxo7x~tIgMx(D|`^I%^-A6__|JF8y{I#_}(RFs#7u0j7LGXm%T*`Zp8P##m&@m33PIMnNOFyoSfAprI7R%b zYp`IrzMH2`oN(%&8h#e&&x&YUzrz{_k0)quUiS2<%`BBiI#?Xp=PvIK4Rd^h)vypKU(~vNr-&av}U@IvHf+u*D)ge6vvI5)VxvZ5A4O~W)?Lf&%*}wB> zbVAG@b29{`gRV3Qn`mdsOSTZhjIQehL}OzQH0Kk1YFVzBr)e$gFMr2Pnsfn|NZ!?b5H zD(L~v^Lcr5CKNXgJrCJ=pN$88zf6*YTxs3b5a76~OBT=6rc9eHs8>9L`fV zW>&A^#`cixvd$J^WYG=A$RukQq8{xQ1!g!HpxbRn=|B+4wxpkbJctLaQuTcf$@Jca zZDX*^*mqJAG%;H?L5qN&;;U|ytywW9wTMXVRQTgK&5jNDqyFc|xagD{G&JGxUU31= zIy3r#Cktd*Phf=&GP$HT%D7pLyG0fDyJ_zM^u6m{@kBMOtsEJ$mxCTXdHNwXk?87n z{h|t~KQeKD=-Nf~LpJYWg3r)xJ(u0Fl#HGHPeT^6iN`_5N1vz#;Re~x61ME17}F)5 zvO5YWGu#Sp&C>0JG}(f(I!<;s>XOkRRTfx&{^PW?+mkqy3|>b1ZC5<$AZLt|DFYYnTsKOT#Ehs! zgYsFnW%P?6D8oMszkZCMmvDyqK&}SaCpHM4y|O&bDF-o(cK0kLTtpRA)1u$eaZ^l) z@`{QfpDRL%xbg!@SA`0@97BPIZ7cuyv8`R+Yyx$T6baq(1ta_QlF$lMLmh=O(%Rne z%07`xmOTSK7cSaftA;J_^^dfo@lC(#slN*06rh&*mkwVGJ;O4NgBm)?g#XzVikn-H zqErVRCoKs+nzKEFHc*JtcIA3^0Ve+j32BVxd30aO(zmp`XNsF1jbn;;aiB>Xs) z1kKp+tf3B4URR8)gE^_QFa>iaNt#NBdoLcg`;$+jYir+o7m7Tvk_Z3xy|>^_IXibT z_>VuU_aQm^FdYRGrXunfl~ssu5SS(1cf1BJ7U0=DBnc>LsRGZK#K4S=d59b5T+~9A z7}5L)5w4;*xQgL(RPY!Hii~2wC$PM|zo@nyb65fnx(#{p-K!c^`L794CjK_Ok8JU} z`UDXoo8V>zF8R-WuZ=n+qUeMz#=5Ylji4(fZJrf6-kd3B9rxAV@d?qkWr*h9l0q(JZEllXMJ~H z5~8xA{xrjHbD!G1Yh$Eh`=ZKRvO0)7zC4qUpiz^N)IbhUYed+DBOG|gWFh57i%#QF zVAmjzG8lXjJAA@+r``kCSw}UfBIazRNY5;5Ap2!=icTCO6rP;vDrkA7Aod8cZM)2hC$pnZI;!kT zBZbD-pHc$)f?7xuA(^Pl3JER+-ili~pCP2tRC;#yq7HVe=c9;dX45@A-B#{Sv@^vHs5NsOe<9jb+RA-(PX#L2d?J^wxGt^74+q|F4tXcs; zAUXnMe@n4^2X~y_~WB{3zzTTss{0R-2;N9*{J;ra@6U$+w4h(P4)A0Pj#lx zPYTm*)u1K>PF3%4wh{lwsgMfR!yL%6!}W-oR&ckqRFtIOy!e#*gDmg<~IuU5P#&P}LG&MhO!kc}@pV(`f`dVF~a_V|IK zwUo5#Wd?TTR|_Xc06ITb(!t~wHpF$P`Is0taj1rO@;dH{V$@djD|uZ4XHpT;=GB!inT zm0&P%%nPwM05i^Ac$|K--q{cBN+oYkS@pv4Ta5)~QV%MFCZ%-A$za^s?j)hhFj%iJMuiW zuf?}f;xCV;X9r1E>zYZVa#okQlALi#!H76MxenOk4d9#DDI%-63goi=L(t_?iQc2W z!_+zsYc<|(PO{W&h*8%8h%Nq1^0lzD?*mdB1wZmL_hK4DAR1G`z%*(0vF)N62CdFx z!Wj2NRgylaC^W2xvkA9eAZ_0W;B^(-+PQa<4Abd(jorle1H!Bu%6ET~p)+Ai8^9y? z8>%TfX0l%Dx$L<)j@eF!mTY(D&}piolNK(sV(&+VU4OQ3M@@ona&v3fRRK~s z^f<(LLbLC=n@p>ZNR(JU+%)yI`(dBt10^UL1*jJYjNdspBythf`S;|+V5c%bvj`~C z|L9XAdo2fhqrZ3DT&RTJ-x(s}*F%L)2W&TBC7i6!dfzkd?KzS%t?XY5NiO1v=Wl%0 zDw5t)xFqn0dq+HY+P(x!4Wa@N5N zyY0D-XTQBfL1?O+4^soM2WAppT*^z_8zhvS-@w0o(+vk8OGKgGh{DCyA0XW9=$|-z z!80=!`10_xCqTI5cBC(m863_DaEanQ-ovY|;mYm0_l6ReKcJE8bGLUQ584z38;Eyq z)8}*EiyKqq+%SADbT>n}Jedc7NS+2o_Rdjos2?|_byu3W5BFb`KoGedD}cGJ(wO>$ z{7{$r2!1lnamM>#6HU8z$l@Eb-qn#+?F5tX`emz|47@ef8q}I*LJO~>tMR+;Oylw} zLD=p3dGjaX4r(0?9^$^~-BLF|9FH6S6Mp6D-57@}#ka$rMv$ljf;ob0 zl4OzS+CovmE9G%N88NOE6BN4X3v~aqs%8ydci^O5>cw>9_`tRMyru1u9`7kQHW4Zv z5E%-V?eY^Ygj}uq@hV2Bp5(?Z#d4IXyMTI8?7zDrUyc5oe`W3gMlvt#?D#AwCI>+s zC>bohX{wNxPUq+L?Uj$q*~QSNe>l2TVRTM0PU%^6s4A550Jfu;a~AB9`Kv=VRL-;KIP-Tr_+j zm)*p|d0F=>qJn9uo~h#OoW-s4t2&misult*8xm$#%7D*>S5&j&5K8n~!qGFp=J*;&iqpZ1=J_9vU{rYt!i$wPtJ(a{BCj)7Zow*_>3*pbY-E%n z(9Q2R6km`A1|<+Vdmh&t^8oKg;)XY}+9*dMRfsmD0oyP*c2mt~rhXgDz0uRFjx;Ye zQs5v1&VY$p1=5CG;KTsqoBQSC6>(=Uqvw$ZM6zezjy(g^BgxP0Pgr>@e*`fDZ7)9V zGCUn|0iC9a!n0{|xPAD!L;#a0?ul8hU1S`L>Mc-U&JT}WpWG*rZola{UBS5Wu{TOa zDj45oNtPF-sLJZjKw!w&D>w)d&2O6o^YRb4Uc{th)a-ls%o4hXFz9sWS>yg64 zRJfwq#`-V(p|8QLbT;{eQA3NmQ0%a!e~>uP9l9MifrPGS4`N#nkPN{GjeQEU zDOsl<{YDA&Y?gIT-Qj9UD4r4AKe_CmX2H13U`{Gd5`Vjw{f@>}yT#m6k_1`!GBbIw zt7g5|v^_c`kX-=80J{AM`-6H2EZI8DDFRPqRxpr!p&L?^OXz|k+JJ$>S?iXiv=Qu5wEvUYF~&JAUDlisiw_{5?#NHw(I6;dmHqEx7zX9VK1Ifv^suoT$nb~YR(zAHuL|mbxvWDblbY_vbt>Bwr#V^wr$(CZQHhOqsz9dPW@}` zz0R}G*%x_{F*9aHMoz{1eRGV09q7p{Ju0oT5~F9_`nt^K%buGK*G$!(r4R5Z^VG)K zQnuziG-(nly$;tSiPN}%{j>H{o^KpHKb%YE#dSB134S+Cy55&I)}Q8e!V17?PyXOo z6~z6##sUW= z#Dq)~Q55Jx5|F9+k!=NkGY{PF;)kheO8l~Z{BQZC%oCHmKw#?a98i2A`qJ^B-q&)LF$E~Z&$LnM@WN^AYtdu6zC2K|$p!mC5JChsEB zl&=Q^`_CP|cj<^txr^_&Ggj(>+V1WK?*<>PrG6zclVTxxH>iK@MtQ#2k%qZ?&|s(L z-%x~a2rpJTKm8--;|=R0K30ptNIpcA(lS}aLI!BDQWcU@0wq1Zke8d$PMVz9zyEyg z?WdkGohq5gaC2qr=9 zR(5pjp9hMbaD_!@nZOmUC!7~^EKjqlrHyV zQr>RFbFjB+Gme)_q$<3Pg?B&+*0YLAW#`aUtnYoeCL_I>{{DWVkvQ`GDXN2Vp*?oNi#EsX)N()^?~bN;T{GAOn6V~ypW=8|&aJ%8x;A3Jmp#SE||AQfC z`f>qOzl=NVx%{t;SOnY;zUIYTKtDF~g9A`hEZB}dm>htXx}Sgm4!&PD;5TeM2z6t> zAJtoylW%p$g!T_`wND@xvS`0v^N$3QHW2bGw+(MK#12okGH9Fw6EZHN_cP>mPmPkG zNjKdCQpB!%LAlrN*lLGKyKsPkU`is=a2{kRJDQ=C7-b4Fcq_gUAnOc$VKVUgb=?W(Te*RJHkF&xA*zLnoNK@M`CvmnK@@Jm&%$y^tXSD6%ZpZ z_@%GzjYwO)1DcWW37=*Y6|;b6Q1z*vuH+vM8r0cn{|5hqLOW(%pfaDpdX=0sxHug^WAGltBKubBsjt{b$$ovYb za(xzKBndyv1(KFdxQ*GXpsOmvK_0Hhe@{v&*}wi5yCr6K8y%$-(p}`a*xZfC#s0=r zOm@%R-Ieitd{74Nd5Kw-&mE!#+LRZ+7LPjc3ZgpeYhU9B;1ru0)D@-&9LNg4p0OKf z1yK~uwQR;$P&gI6NwW-@xW4Q)IG>2C;tfTPu^B8X{2nx*Jzfun<4VfxB_qP?SW-ib z^Ucg;8Wge=b)P1mr9i2l-{+@P$%hD+;VZu7Y2Zw1o3ShzmK)1K)47rtN^40qtD|Lv z8k1LulphndbJStV*Oo1MUd<|g$P_TP|J^p$2Nt4VnZG!{OOg_Vj21PysYoOW<6W|$ z8^?pv9L_5dK=On2(+?;5{4Vv5*#0gc7&WW3%OzVv!)%BA@Ta$6R->uZ!=zX|{s5dPE9(Ar`6=c?ar8laQ6+?b6x~+|p zgxU+gH$zQ^+j3t;AQYaiMfLUbUvlI}B}8zZNQvg8`$ zvi-I=5rm3TUUP1C9qCicF%9+tojserff;C5dUsF41Z_Yg5>)Uz#36cUMMCn^Q5+!v zO+Uf4w6sjycopzC&_E zKC5{Oglt=q;u6HFE%`TNbRlKu0ldDt(@Sef7u}$85A7>xWzc77A@u;fNs$jvma{aT zHpHo|1plYLiZivDA06CsCH-CoL+h7X9{w+Kjeyp4u=gCRkM z;KN#PS10?v3k#`}YW$-I+XfZ26;N1sOcz}}(#k8kLM|pQ4zOcJDS%ZU1A@a8wekT$ z-qlmY25WE_thj%dv%+hIThDY8`ZHGUPD6}RbWbCa4vdWf@iQIplpR6+O;H{gG9cHE zFoDed4=CO2Km}8bIf%H!G`(W9Hu9N9EEyQHV<6#l0b_8hhr&r^Jy@6`}D}=jYJN73%6l*|0MdxMaBRsX)c^f{c#FN$SC@O1J!2S2l7O%Dy(NouI8G| zavp@7=zW3ga2ic^Ujovq1y6o#WA9QaX7SrKXEDQ?@h&Y&pJw`?SE75Q9L-LEhLsY# zMl==E#sPm;h?sER24kGTd1vmdBApjnI&>J=HMfWgXl{&De)}qPx3b`600VZl!&N`K z0%xqz;NT0*C$YH`BF7AI_D-7KUPenKB?~*VxK^AAuY&}P@`$bA@Ql6l^T~tF<&hI@ z&{>k3T?y8osbC=`?@;#K2_%9+2U%oBz4-t7L5^9 z5!VgjtL6(XdeFR>C9{8Cf1Ry4f-j`pg{6OL&UgQLd$`PoWB2WZ<3#b}&*frToCD-85wTc4!nP>;6)TK?l&jN`R~{3DNF_RW@CC zlnyW_N(J}ENnSLmiQ+?zYlSw?#8_w0_@>_s4Qp1gjgHa_O=IUo|Q zv@m<6k$np+b3ZoHQd+i9xc!{?dfbizRz1N7 zZ`YuzAXvLno_p4hstZUN+zAn8HxK<+jJ3ww3>Q&8#;qlD;e|D)WF)*tpClcm*|!=@ zf9;r%8VynjD2lOY=x@=Qxp@5sKSQ$$H9JK>hVZl~R~k3meO^VyxO8`5 z(g;djTf33Fn-zH37{Jsh63B0p0N8cPXoH2U3wGt(5(vp&?e+c5YThuPH6&5_L%oFx z4>JYDn0eYr%(6=pT?1>Fd4znbbvK7{(8qpWV&s^GNlS;@Yx+4ad}W%gFn0{ahyYUs zP#-3%-@kV{L&6+#1XNeuxtLubNv5=RYM9Wiv;9AXT)0@cHGey7PF{z74WgJvLgBc8 zA*^tLxIn(!>fkfT3NW*L5Q%E8ot1lI@`~HQd9fQ^4N=wC%)F{dxnGc1dY<_R*4O=3 z>OK5RpSp(~l(D$BWBn@AX!tg;`udG(bzR-dmWO^#?b18$70>%KgbSiOofw$B=yhBZ z&E;iHz{bY&(nN@v)OPp% zlN5(z`#)+-3wNeUoM)S|UUfSjrAu>)0IV}BOR zwlxr?WZggbISd*h)h=1tk|WJLJ%smare7Lkl6I#S) zxHntavL~9MAx0okyQnL@dSP$uio9s(Li;M8cI{A&mm|U$C0A5LAX_RICcppYQe}&r znLYiKWU9X7HRzzKm2L2HldlcL@j=s>(QS7Jh?EZzt_SKlz{?9jAEn1XA*t}_?H^D~ zYd6$#xlYO^%dypYD7j~UPH;!d0?kzozo+g{!M%P7|yzcsn64!((3 z>6{%IFrhUe;|Q#6WO|!Np;h4>G8d6NxSHPF9LBaEZD?oZ;+1t+FIaZYXM*y3aV?N|Q|N zg|FYD#`CkCMPZ3v9DxB}N%Q(o1P*y*9fgf0*z zdi)E5qse=j(eRwMzOz|T11oYT&wF7X+uzxd@Zug%NXWU@Npxw8ZpJu zL0a8Oy^iBtj!!5{>i$r4)~7g?OdkH(E_OJ>*#qMRqevz-K;8TtqBLF`)Tp%z^F0oF zHKmnGX8{pE7-H}azMh?2EKInIQna!tJMCn`eSpSg+6X=689+iu*8Svu8(oUwJXT}H zuvL4zNp2_XzTS?N*|b_$kvPreu8ig!jb^eE2HSZcN4ct3k2y3i=NEoWl&$lntq#Fl z6}m2~6Q+*LX)xc><4$+p9NVKXNyw?L#_Dl9@*z${$KB(hm?@42WzZe+6M$`U()!f@ zK}(WQI#|qwh@7}P+4|*i7M|_nPGT~Z0Rr*VuB*t$8$tU4y#Mn2o6!+sm)`D2Bf&Kp6&=j(sutGyksMQ5YUNU@BdS9`EP-N^HbXoLn)limbf7Ks&xMd93}DwxUN%NLiy%cudH`~^BQf{ed;)E4{4 zVqZ4`a7%5uaL^=iqtVmWO5de0pfUpc(N&?_65n$V-|wR@6PyCa*|dGaN4raA)JRUZhK~R1g_Mn(p|m)s60t39%~Nm7q$Zh5b*gP3nB5m zHL*rFx$Ua|mIxHx621smBiw=ho1QZl>U4vQgyita%{sfTVcNcKLMYA(-f3-6l+i)$ z-^ay!fqZw}%G(JiO@SQT*qpc-n(G-`2}#RyIJT?WD+bP6I#0$K3jA#F!k4i+8mN_G zakll*gVj%{pG$1_UsM3%*=*P5Vk@i8gG>{zD=qSSukdLze!#m#VtBne*HAK!ioTnv zvzmx@{Ze4*N@;;Ct0+27z&6Qvvp<|Ai_qQ44kYL05JA*2s5Mmyaok13z9~$c_HtVp zyj-U9lr%ZK9!OiKq4(ElWbk&K^4Kqsj_FzFy9R?1HZ`THr~R{sfQ?aPOj;!8mq!0u zU-{?G^f`xetb~xjd|KdG_L_?3jna6owBl1ARDXICkCT(@wP(R>o3kO!C%g>_cWFd^?llH*;rei64{ns&?W@;j27BWTfsDSBX`In zOO0gjfnII$7hNUr@H44InDEsj1P;9x((bwvVW^arGkT?2Jb=Ea@we&|Gp!sJWF^!$ z)DZ6*v}ZCX;rwWknclBX<9dE!_U7&<6c{3*eoj0rI{$-3Y!n zSvL5ZjSRWF^>*S~_T#+Q0DgCg1#As(?>7YlE8FbYR6(l>VLdn$z4@fem=kneGQ?4T zaGXCN89|w19x7+KV7HR->@XY1>N9Yg2VeT++_20@iBR@G#Unw{L(CrL!ez><6}oWq zCPkQ2$X~i`ek~yz7zndh)3W(b4U4iH%jkuxaAH&@`<*7wadAyZdv+S!J&+e`?6<`C zq%mp=dCVO4%^OgN=v*Qz)(Exb*ov~u6urCX9jp|-hR{3QM{{DdlgtsKa(sYYBNS;WivFT4AaJ-aVn5?!|#cq@QFj=NsBs^g438EoK?2C~(`P?+4 z#BLRy20pMRoP+h!M75~lrm6aXRdTuT-zcEubLUK_MJ-rb08_+u7jhgYl4q#=+Gy|- zzQSO;V2ha6im2sif)MBBC`*-@)D$|sG3nANro=8U z*a_S?I3N7VqGxn{g@by903Q~IYbkG#d)kXB(Z8)Awhr}t)^Y}NR7PhN6z6+JSgz6z zbm|uoW9JJgBeoe#-^`N&j*0jIo>z&#GWZ%dxe4D^L~sQ(Z?Fu9y24$$t#i@c{;#e8 z({g2znd?HtfapaA)puXm7yMtc0ue=~{g;$=lOO*>{K#*#0LHCu-W_dqV0Q)CRdxQm z$K)Q9d{7DxAJylfp$KIU)KE2f{tK#wGZ3p?z;vEc!J)9utK$uKlI-tp3&8YVxDVZC zC=P2aL5X#^n9OUAN3LHox}o5%W^jKyel1{c*i{ihCp+MImHhOofqzK}Z*xQyz$L;$ zi<*hV#SiCoXi2_TVM#uvFpRK2ncdXe2KELWoO?J4tSxoc!S=^NE@-xw?|EJe*(S{r;LAswQB*!?^R7 ztYL4wTimGTo&2k+0a}qN`o%G5E}mC4L%6(5-bQKs)wtd<4)xeI9%xkl@~8_BUc}M1 z_zWTC&>mKBu5JH1aot;rz z8C2c5l~>!@6}>i#0gtgsawBCNQeN|oT%uZ0*`Bc!nC+Z@XaeZ?ANH@Sin!Xs9Jf8? zfvAN@GWULpZCmjsNz}u(z3+IyDf<<~cr532&%o1dd+aS*0XuEkc*K?RPwXoZM1Zxb z=>mvfDM>%?ero!k{%>7F#8|Cc>@@<1)BmsRpHKdrUi}hXym?e_|DU)^|IrQTAR%mr zT#$@8P}BbZy8Y&ae7k_Wjz3XWDd~RqxavVSs#74vmjU8o(P8j1BZoOpzZu%+7lj5F5O|sei{pb$hm(DTU#}E93Ps z-*@uVrnlb^krw;y+*uFV5_6cVzguhQW$vF3_c@WXcN+F*6!Ro?l=3&kEv>Abkl=g;^6sLJM3`VYbPHrFxC;JA?{g zXFY1W{0M7+@$>?bE<<0G0;wN`B-h}9EhS>bO6d(~OyQE>z6thD4M9V$mxgqgpW+6j zk|Xrp!Wiun4(ic3(+h6nx|lU+CVy0pK-x#V4R^!KPiSX3ANa;|msJEhY;>ddD8HMUcS&86FTXd3ce~@- z@4!ROlWUvuD=uefeFOr!tA@{2YDSt{4fJ2QHl&-gfTVXVqX#BMPvn^(?tB z{tcZCUz=G>@D4}sy)zqN70WdPeL6P1U-0u_kD?zPc7!WWs=+1y*yGPuDH)vg1+kix zF^ZnnO=Yv+Ar}}ty{CTG1ui1Gs$|`65E-?p!-MH3O0zG}Rpks!1y$Il*PT^o;TraU zf`b3{oc}+%#igH^BxQdGScSav9pc})R2mL;fIc38(7DWE)#jCcGals-SA5zi=$HPR zNlzAEGrxPSNS$DjBkw_d1#4&}wXxM0r`nsseoI!{lV9XrrGtH`m#eY?gS~J%jq?>t z{i1-3%rwvvhr}>;L4M(ybYuKVkTxh-BOb>#y7>WvZyAg$a7cWsA(HHh30wJ&5ABl^ z10AC2^zw}-e2NQ(9|k}ETZ=N$Aca&%A8zt45HOehijo$Bmm#0QXh3Rj^xf$315WrK z%Xy4;*&*vyEMEoyn$7)I8)Np(y`Mpo=RsDh8_2XNGg+s}p-hAq?qHwG9rfRmVZEPR zcGwEnd!2Of7AZsmh)7W@-sq7xEzy9qRYTqy*%2rB``q7Ui%+T|LK0WbEE&?p3!XY< zT_i=Vyn5*ad#FFGgbwZ>>PJEVaEs3vo1_f56Kk?}Wf-H8^ty^&|3@9n>Va0#`z{cSI3aP=tWTLL_m8N6%KOXd2Zs84m zqnd|;jU2+M(B{ULf+J51fqb)O9mL?jm$dyOQRJAHrK3Kmn9cR?@@yE_F^py)uJ)f8 zuC1#DMeS(s%Od+U9VkUYckj(oxm-XUE{;%idwr+-G3EB_v&!1m%(k{@6U*Mvrsi}` z{!gl{_Rz7(zpNhYTO*dner4bSF#!IT_~P?zM0DI41VVs(5CX|4z1X9dT>zj)kDot3 z;h70X3fj0z=H6mwT&^iYmW(RB=ng^yEKKOne;@fcW8NJ$R^+Mwe*EJnt3fKBV({(ByJ|-S`Q4DZY%lKm| z?S#v!#hiI{LsRM6kQe{_1AbnEG^zWrCqH(o%HE8T<>0j^!`Z-Ke+Cct7fLC6uqV*6 zKug^(^xxKevaHL+9p~MNo~vLQde|QotnSVkr{2cwrr%z6Rgu%R;ibp)c><(PmNkO^ z(`Nm8*}(lC+3i6XP zLM-q4IwFldikpV%A$6i4;n+W&I?`zYk0`LZtgMDcJZ}qpZq)O@jcpD%H}7Y3Som97 zM)W+Uh@VCE7V7maB0+0Q@`}2eK3|pfgnR_3mc3=r(jN&Nn8-9oQ*0YZO0@eIquhY| z?;&p#@SEjKBO4s zz)+2|Q$=`Rj_LA~J`H9e=&%JJxkH1L;ym z#x{c|2+KU~qeD!=eIw3^4jmoj@kSFP+DlK{kQKgK=8DMUe^}i~YE6JYSV?t-`2;Jv z{_(6={o`4$7crnp7ka~^gkopQMIs@uvUPhXlBh9vq1@i_xxa%S^N!as_#pWfj+s|MwW!i zOk;~fnv42fwLeAR?{(VwqU*D}{stJab zSSBQ+g|>L{bWVmVz&~3k>kB1w(_{e#8oG+_YH;3dA@BQvE!y(|DvzCis$9rz zwe3ChaPZ+38M_<85~zn%Hd)nP1Pn*1O36~)WDCoz;XO5$r0#g?ylMf=ftDtn#qz)n zq$V({C@EK6YSQxvy${C5P0ex-=zwTAytm?UeDZhN$lq2Z5qE^ZJU zO!;!LfR*{Z{woE20e>#mU;el(Q-)+`AtoX7jY>#^tcz-~yZ>TkwaSzC%ds9K^(cz( zpfJ61x8SQ-V8h@qLQ*I8w#=j0XUwx%`gDJ3<4Uf=PLB5i0h9OGKXZ}TKYsTh`TzLc zq30Fp-JS;Wlh{)2)5F`CM7Yz$7~AJM=2i~yd-q*w<%)nkzGzr6s(IY9xNgdR zJf%7I{jQFz?e~XE+0*SlPa&ZPe(*YX#fp_@EH*fCq3q8$B;(6z_|9O$)>P} z_Y|MgaC;E+RMiY7d}rjZahn7uxy+bmPQmHjG*Q-tj*3ND5UXCGTOg6d4ev?wP4?9> zBw&dPbI3?<#Fcb%U>K|DKEsmep%zJNk9WlKJuaAlr{+K`geUuEh@nE=gnxSjed%z? zC6lGvUDN^Ap^#vm#$cR*s1EE!ygx3Ji?0LYT)5l)i|(tUa10A>Eb%CuHo? zwHCnb@w6|eN6tip1FrqVp>{dTS;4!+I1l>e5=gs#ventBp>c>s<>iJ5U0W{yU{uyj zvK}*XzourW3vbmhby~c>?P#N6l>`ThI_s;ZwJlSxq#pCvFkKL%0|~z0ybSEhxOvaM zU_&!Bsm4e!Ql1sXdc@-03L$6bdItYnc$Oy*{|A06>8Qzn-uJh~IA zQ4zw9l)Uwh$NUo|JtJlKSj=FN1HFYZmPA?SAybUQa;4f`4_A(&YD=YhK-CECSmtE0 zU06T)P2d#IIB;a{BP@mmnY5${p|qXVITtk|z_gF3vAAtuhSS7lHT+8?x*s1#ZbYt( z@!mA9frWa#_r!_*P!(ME0`m zzDN{61LSm+yrPsH^X1BCfP_iOLr^Az+i{l~oO;}%QEn6#ekFWuZB7-$=lK75$Vv59#jL%gV&JJJlsiizz05dslDvO|&H^~>9v(_JW|M~Q zjk&;{ z*p;x7PLW!bP&7sK*mhZP4t^VI%%DlMehlNI@|afX9$gg1#s87|nJ)c{uX)-4ezHB> z&Lqv~RxCX~Dl%P)?;Lk8x&3`e>+L1hRXnih-9HWyFJw0@U9e`2P3Q!L3NXgEUeHEL zW*r#dMXIwSA(;pcEe2a`XOHrC_EgSP*{gC$CM` zWSwc>Nhz(~BM7k`r}hbc*?HL5pS-OW>3F8F@P5aNI13LhJWhGPtK`)fF}ndW*OyS5 zpD+-dpq!8iG_AXXD!`QIWD-$-TP9cVAh`0lCU5L4vdkn`QhnC>2jMeJO@#(Um}L=_ z)p2BqilnNr*h|r3=1IhOD|xGu?;(IG2R7kQ*6E5DZ$c*dCt8+zx*p~{JY74a@EJ>E z7Po(3AR1C!+GQ7Pu&VgpJ4ew(n{{`r5hm$+d!37PTixVVB1>kyu4-X5&{X0Me7j~; z4iRVq_V1q0{DNKSdTY@RRf(h@4&}E^~m-m65rmS9u0@oQ!@=s z-#|eT0<=Xd4{?W5Uhdzvgj~B?r(3bNPk7 zSL^Of3#l)u1)U7$@H_qqw}+zp+lDKTJCDw8;T;obb2a#y$P^jsrD?o8_0YxB|0hUJ zJu1zTn9l#lplRX~7!({g{`C89GcnC-Cp|*Kouv!c13>R|B94_CCt}pFvg(1YTIT5j zY%;Me(@wFRmVI=`UE5C*2Ifr|->&Q@VM)wv!V=-F(glNSsC%*xf*{Gvx$tD-M7F(L zMIDMm_fVo=c>!nL=wPM_vloJyG!v7~yuw9O9ErC->T#sV+%&ORR(xm^Zz})#wrlAH z^UH-Rt^D)6SN)PQ{x|MujbcCH1je2q$sV#vcd<#4K$};~+|zYRLqV@pij&duI* z=XXZw#xw8M-rzas!sFNaSf}YzG%IMWq=`G+8Y`7d`tm~r7SH;NM>ZwGXD8gG+bbDW zT{SUsScgoH*J1|!o`b-ty^nCU_%myScmy!@016t+49!(RmRWiE^4nwGp|0W|HAyvP zWt77`-*#|*dUL7F+w$4p2FYnpkcBo;L(Lw}dPAMBVyoObPt}w>zA7qd&W3?Z=g~v7 zT|xr`MWuv&&%4V+e?hy%p?%1d<#^SzQX;}Vj^$k1yE4wzhB<|9{SRFYW&KxJwgOsA zdlro>T6EKzkw!TUyuxVWDw?Cc%cBz}rg2v!b^Bd0y6}&YJ5^cMR!SC>&q8UVU1QN1 zFQde~-Akr7A`UfZ^;a143xpi#$`+D~H=gA!81wp&&zIzKgmzw@JRs?5gT_g;?Sr>~ zZWJ_sF&%={o;es9Z!93xdLK)5wng?|qhJHrI|+-0vW3oCVo;r&Pg>f#k*kz-hi;oh z1ExGK#)S`feci+HeY=ycGzgWO$Ufz}8y8%>$!ujIZW%3Tv%0|xc$xjGVz;$B#bo;rTj4p z*xZhxsi72T+r-o`fPFUCGQ~=k& z*PF821BUOLCt)mBE%2k0O#wS)ODyP_x$F2;t9sEoy{JqwtS9vsVyiQtGm>z9Bnnzb z1j}Z2WMp7U-Mc5Z#9i5e?w*pj-%WdhvRE~@EM~oh=(&N5QLM7cMj12Iwq|5&n`9HM z{2x4l&eDM$1&Q1CVhfa+zoK|n=)Px6Cp5(GtL@wCNu2W18AnTLFGwo?9Sb0#4dL!y zUVt{Sk~*(cETTYq@NpoO0ytQzq}q{M!c65g`*@hhz;hJX5>DVIoy%o4?mTLwXJ9oCcRl%D{X6@WfN4!;<7Pn zm;0`MdF4c2Xg-^~oul6qiz^q!ns1UDR|*^tO&xqQyqTgFw{dT!|He4*GGbC7UuPsd2Xr7SSyCQXHNvFYCB|GG?wZal_EJ1X z+mQ@pLgmqN=_aEuYvHE?Ux-Z^KqgLj3u;<6*GSUN&7a8rG2c;&$;C#=ejcaScTg(y z-u{@wGH4<416X#qlgF!FU#PAnr76a#4MV^`twt9RD7v@GwBk(=)4PLGK*vzooeRpx z=a`m^%>gtd<^z|ax}`_i8-RFGRK4r1=T>hSwFQ$~CkBG^XW55FW%~(x?x+jA&=8NTvfy96>4{O>fYvUVa^z(+3!#!^ICaZ&_%Fv zf}2RSqybD88Wva1gru!V94BT7o>9h4ZWN3;vz2_jOa!~)z!Jej7*H#PpL)w=$Jqw5TX=|L=&>3IxBU|QKV^I@cUy@ZKECbVx+Pa z#uj^*qt_`{cF}JmQCtoDBr*E2E}Bzie?y7a(%IU>4#$7K$hi%w>ay8oIRmn}qG)l^ zkeq}plp~&B!8iz99NXd*U6pz%oGeRP!8~%=$4LPpC~7X7v}Qqkzmv?Po~ZpV!Bt)N zJbBBIFe~0{H4jPLk*tKQY|6Lzg7JlIh>3)|U9mDs=sQG8l<-~FMJ_-rUVF<}iN@iM z^vKsd?^VatF`H&NoKts`7>$QixjK! zW31?N$Q6KUAWg7Vn1^x>U1G+)Qw0l?hQy3?O6F7doUAJ3c@Zrj)ND<@FZ&$fD@P^l zg{az%@DfB%D5QBI*LtP7^6N8aiN_Mfs4U&eWSN!bacso7vD1r1v9kv>a!pfMG2781 z8HENK-t^)H` z{!Bh^?V3ePI3tE<%z^1Vg;Di=!lW-O*c+v`xQ@R$n(%&O?0EMQYjw9tx4WF04|F9n zErIr_ERtckHO{3>60^)2hcZeAC%021PMuXfAN|yl!;;=^2hwEkLk-Me?8t~_#vE^qp|ei~ zYQn*UfsqR@n;>71NM!MrUT6UFryT&B!Oe<-&`+#nEpeb_95B9eG2Y-=m{E#S^Whq< zP3j?fj!9CuY@a)~3-cHM3y~j5gw5i%kw@z@llucc@gv8!B(pK=^B1Q5 zUG4LwPeBxclq%ZKWl5)+!Y&$pLK0qigU9eZ=#;LI7QZhm;Rb)&!ftXKqo0w{29RzV z!0$hOVHvZ6FMok;JW}Bbf~~1VU5lO8pKAcqWKs(s7C|mDg=0Xoy?=wA5e2DE{33L|-ii5q zZ@6(X0-`e|yYhOYj&-BZpQo(#)do$v=G5J*paukCvLasBeiT++FZS+L5O^zZO`TV~A3${{Wq z_@9`yOEYOmg!LSV;+RLpjw9{K&m=hsN0V`dySX&qIa8fA8x{$(l;RFJR|qPFDePYE zEw?tJuP+$OXR*jr#YSD~Ra(8Gib>Us_e9)^aqF`) z-|%X=i#$2Daw!!T#H2xHHnXwq3LER_>_#%vNuW9pjoR50Pg4-K>RMb>B0eOsN|b@3 zJS9=5s{~tNl>k+(4MOX5}tOOh8_&LNFw)aw(Bb9D{<`*MUU{1iukkpy&6aTbN{n@dyC-RY`SQ#=I7{RSi+Y5S|+U3t@@4G9(pFX z1L)y#&rn-L`yH#ckefLBsgPgy^x?)j48;)M>PFMvC+(fkxsBY8|eE)u&&v~ z7*e)`9zOOmcP2V7a!39*N{MAqrZa!$--B#~e}r51TY^DY@3tMpYVHwg%YBAv#q<*WQ=ZlOPohex^M5DRJru^TGd*)8~rV>{pW zu@aTGetT=u#hQ480kOriVIk&XlV;0lW_(!#oeGb4PmO*zmM*E&mu>SOMiUmNudl0; zsdl0ji?*jUpV+b@?>HRA7~>|p938hm_KGvn6a)Lp{fRpd?d$C_lym9UuMQb!4Q4#< zo|XX-rv$EV`x*B1nt~?f=IyP2a*hR_smk~|ekF8YV7U8)n_=h=i}{e{?0q?v<IF=!9fS>&uWa!e?}IFxgB|p=DmH8eQGGZ6Gtq1Aa5<2c~0vqN+INLpWBetR;O@Rswj1qKcr_t@W1 zIEEozUWNEhaLbwSMro4sp@=%g=kN$2)J^BhB+b9K`eF%A0&6iG7C`HGI1hGp8D&UM zMglSCS8&>WJnOaNNhto<*1A`bP-_}Y_TIGYR!@LOecRU4{cC}Ql*^d;=w&9?q!Qyj z+bu8RP=4hcg1U~^9z`U6jG2?f_8fe&>i~wRtdlMY1+?kRl)p&}899`ea>PaD@Xu8x zXam<;g5v_sA3dWrwM?@m8T2}-03XJG9-2T2{LWE5JpigwH{ClQYbm3@$6;U}^Kl}j z`%+q~xV$hhdpc%=b~(3Q48{T>w5HExR}nn3F2VX{+}LpJ(WB7^f+wQ1ti6DunVEBo z7T#8efd)bbjAG^aRziyA^gm1kDgDdly64OK;3Y^)y5X0wMf9{P<*@&90Ln&UgzY^& zy)?Ih;I8P1=q(_7IV1NBoh`z){vMDTzm_sFar;|zGmh-Jwi-xV!&IPk)`;Q4;)Da5 zQEBPbn&%gZLF@){alADmkXRyK&~xAUri??6#7Fy3;@=y|7e2)5xNMok$lo zF!J9WF%f(6hLpmfWXFSyrt zCWs7|7&$a@7Kk>>O}3B2tFmR(q5R-$Xbfp>r|M0j;3r$ysiMvhV9l=k*AE9SrcDr^ zu8?LlbS5z$_4lngzvFK9pu{tCu03Zkp1a#TuL4tKbi`*+t#jNzDK`y@L#B#w&4Oa7 z-Y)5^BGAYU93AcD$tYBLFJQD0ZCgh)_uZ#xXQr8l91PENIF5G1V9zhQp$P?8t!+)v z{?}*;4=vfeA*hnw%(9W*(pVRvGdQg~m6fnZ*d~1~P~<#)|9+U}#>Ydcoy>1G9}eYo zN6^F!294Rthemmq=N^O(FHjZ|}nH`M%<`7`tQt*WL0Z(8b?+sH!*V zk*IKsZo{lGe!lV~)#)@%?t9nNqBjeb_eIR+Clo;oWWDW(Y|PPN-dN7&nDg$zecg=c z+4P8U%2Oc{g5I(CKWx2oU?yJ@?>!USwkEcnOst7*P51;8+jb_lZQHhO+xE@;c4v3* zd*45k?x(v?AM~kDeXB}a;qtw0W|TRldt|z8drMF25cO*j!v{8GZwG1kt?0wpA<^xy z=~P`h)WqeN()3A7G%Moz>!5A)>L1? zrHCo!I5TVVKyLkEo9nqZAMC!m?ONUo5iG{X#ga{71+#tdJ6K&CAK?kL!=EAN?Jb=t z1KsYvx1VNdAuK1@#?Ug`DXdz${#uIAEv0$gCrR2-ieFw3y-Ft5VrrcXw>zsSXu|%W zL!_578ha-Vk(;9Ac;u=6_WslxTuq=lJsBipZa(QeXR=H!O0dNiJz7OLnj;QO-5pd} zJ6o*gGKJ?jysS7Aqn9JPgHEEF(yY!H`OYwY@k?(=p?#+*wasdE9fBiD(lQ z+>p1TO)+fAoPfsxAP3S6)Bx+*uG$}U)MQ3aY!TW-{yT3_AYQ%lSNx(uki=V#Z;ESHw#&m)jv$mTY5%!6V3HpIU^qsY;5D`CfYEX4|kmq+#!|~MI znMAm6;Wk^q@OEm6JBIE&MyM#+;$)idVIZ?SGefs(7lqMj;yLphb7tr#*58=Q&m2?C zt^F&pl{EpXYT>m09cyRdeaQVM3SBGA67HGxXm`vXL&?}|Qs%rKmBmn)DCg!#>1igi zTN+pfrd zJ0zg}c|5Acv{80-nCTvYk-Yp@zULh0kITEh#`-7SklEK=zf#VyyN&*v)n$@_^lpbf zOkttrOP7|GlH4Bmylru@92dRKe(2=&;kpN6kEKawak4noGsYNlz1@I`_EZk(^6nFJ@@vXo0gR1#J$Y`m0*>%?m-ekkBkUmHSCzf9k{E^$SyN_P6~+(+N4*am zd&lG;c~}<9IaWzX^lt|qfFeXFl*kGCN;GR_@s3vsRYP{?{Bkkd+!`JEHwT@@ox_6= zwdQp@$rbgjSc`WY6DhC_RJuXDf0ii^sZBKKcH~RdLpP`B)VUIn4M=z*yLUI3ktTPa zibBEe)g{GCREuPcRLvVox}h65{OW?4ro(RmAdKWEm)h6_c69 z-TPTQ?6)zMV|ono6G6zc%3soDSEcud?Rx!F=D+q+l=nb$rKjcv^UrzHIBJeK-mWYe z!BuR!VP4*f&A5N;ueqR0?~gl&|3uK><1u3VLO2zYa51xbcw$p*l6w*1Rh0D{QYZ^Z zZb6~&z8aKHgunSYdPq5z$DWhbhAZdS=sc2jk=%Pe*r{KQvGKCaO>%!1(Lh5htG8Cp zr z+wbz}d9V8N0gr#WocUY-*YD4Mg(@DH;bOXgC254_fuK-4F zILq4cAx6@PHo;jX4cmBhKb6$|Mjh(>w9M&L$u0?(e3N=3tuZyIo|aSa{vlU}7x(YlN6K}KWr{F)GP+lzeN_PwMLr0Uxh zF7L!*s9z&GgZVsl=~@gp%#DbN8$?u$uj9jcpZ1d{yu&&77qwQ)@<5V$8Hc0*P(5Zc zDTnApo*xiC_nBqkFWw6KNcYboNG`b1Ew(fau86KTlv|jsK-k>@W>zC#_VgQ%JgS1w zi3xULWCRaSoc#UPo4c8*vs~(F8jvh`Z=#X-iZ1ApeF;S)be90|#e0e~xKiuT^{<9V z68MCRb-sSuFE*!P8UlBwkn@(yex=Z)TQttob?JmzY>~$s>qKOuFH16Cl&C#;CV=?qkMVrih|DtnrO+K19n!Vvf@D&6#XZhyJy6 zF@D9y(m~ZnUf3D>B9qo%47=BKK?K-ycoZ%de7&*V;+3+~NtUzQ#HH5BC>6vCvggvj z9At(M>NV9OhRU+_h+ahdV0vs0h4a9cplE}TsBkSvMJE8kb|~uX|++uu&DSN0v$D#4&S?+hR zA4N;$uCs9Yv59`w-L^j10dg8wG;36F|Cy+pMEPPJb^_Qi!^3&FZd+>NC+ob zmWH#YN$H77)C2K}yA0D6A`RNM>(A5@Th%zZ1xL#gk#GOn7xGK$Mj-_);(B)LBe_sT z;&s+raQ)gmRI`KlNtpDR`9dGBpE;vD{l|)RVIwT>jf$=cfWW!<(&hLh@nFY$n2zZ( z@>Wx==i9>pVvvPZDM3~PEGAb2Ax#CGwr#wgZLS0bbihrBvo}7gXDym->j3}T($~|s zg@j2M+pfed!M(=eD?cX&n45TieW^EbLmZkudPf~@T(V*7w4qe>_6%^3c=BPZO4X65J9wL#`s z+TWi5Sh=CHFE>>?m$|`7wtaC_>~6@TQ@z4(*=#XK)nrN5`GoVOH#D#HdcvJ1C-)u89G4tWZHAr zK`;kG%5WhOdRGEUTbw9gZ(twu#I+_V&?_-LaU!$!(Ed&9=(PbcoyQc{rc5yUg_eI_ zwb2-Sdn7pj{KZlbcnA9v(pVliJ)3@8s?0=>#%GyTs6E^LyS*9enPI+rrG-J)&15t4 zyQ~`X6In^utNUJDD}awGruu~+W`!zA&-9w4>mq4UtBG=@L)eaB@UC=B)y5 zLZy21Av|k~;I|Sakw;^0L;F2NAG5=cSLBx>ehcx+!^O^cgc<<7{?VaISzqwWrDO5F z_j3&G2j7nA%s1k2*Z^f|zl#kn2VSdxR+N|w^-iU}hS#O_W@bnFPB+w@R#VABgTB3=h7I%(tXM0i&b{?p>i zp6GsIDso;_24>om*s)UfvtZw=%0`-GxN$mmMbfvo#tF# zSyV4%+2N~5h8s%Sw=v%nj8!iAphm3JQ6zziDab1$pO#DDRp59%NdX|Fc@ciQD+{TI z*dE_o%xpmb4V?m6h=@oyGqSC`7Rj@G1X=fDOwkG<~)Yd`>vg^bBY#Fa8RX`F%1Qn@tZ|KfIj8}=h{?}3h^}VMLqf!3N!l^{T5{}T1 zj~XJJhuh=@Y}&kLsJ`52R`!=J_H9>u?$og5bFQIRwN&3BoL#2y@JH;vHbj-x)ewOh zrNSS6+Es0{5uy7lcv=f}pR!R@p)Z`n@On>7CCzrp3vc@zSg(ZPzqtpq+k7y7nejYO zv=cS;b2-6jV#yFb%!WfgEyO)&V2XQ7j?ZJXHk#5wO~icj+Q*q@{YH?$&OX^W(7A^c z^mF2A*wNrPJ2EQzEwvO>h38W`saBM@O`gvn)k)`pD+M(UQz|w-VC|gV4D3fJ-BBS4 zbyxeUS$3Mkdn-zBn3n7T+O;yUo-glXzm2Y9r%q9 z3VmlrsuRpR22EL2-%AM~YmjVTZvIYWNzbCd?<_=7;OZ=aNLY-T(!_q*Lv5mAPJ zNG&2!*{2@!Y(2|QP4y=&`U$f9tMYK@0STehf}S63zK$JAtGEQM#lkqWQiyS5RFhH} zwdlGSFYJ+nZIo2_s*LF`XeQAW#Ju~-QMF#=eVLMx;j5OS+%g2qNdiFne)tb<$L|0d z=J5TxWwp_~H}oVmPrWSnIg$3d4E>aBh~=Dz$G3Op?M&3Mf~Mx}*VCoK-0^M#PL_F_ zJEL&FpzRsu2A<~m)ew$Wjq}L`Bm+QITWlU?(o{o%XqK4sPrTIPNPTftl`M2a=SzCE z?}`WSzRk<~<6n&{FQ8d~OytsGY znz8H}o$on}mghTN?&|l9F?U8C@9c(wRf@+ooJ=oSu3B?D6@;Kyq9VMel*r{N5HR{3E(Ld;D z@7BNg!reiPhwhQ#Lm|0s>Z!=6#~TaFV!!H7JLhPMLj=5b^}78?Ftiz zIQ(MFTHm#hMnOrD#sAD}%A!IM?KFj7Y@WYI_?8vYK7`W#}^)dARwN%be>NWZS+z zJD)!~Q86}9GEZ|_$|9{Rk5f>;JUY?!TPJEFh0FSBoY#ruI~(q&9;k^PTag@-1EgGO z@!nZpC{nH-}VzZDMxbV~Vc~bB8AZE~_VIIEL=O^9guPuhYitNqWcOa!fLu zzd5!YS*8-9pp!;Wr?$g~(#7Ch68@3mY`T&W81hh+gHY+L`QQdqZ8BM5BJG>{GNbGC z7x$_HT8z<^M^hsG)^2`AHg5wv*(*UMIi-KMoJ=9157Y;}vzm2oDr|Iwv$tKQ(1g-n zv4daF=8;G!Tl4v8BL#asuK8V8mDwoVF;>vDBKHMQ!T&suve!!eh7IL;tMNFlMr}Sk zY|AvsY>TIe?1xxqgV{`8MNvD+SZlvHUO=nD_WJF<%RRDw(s{k7knLi~Y&;%)UY4_i zlBQ=}lEo3idiLESt(Q}KD8^aWFh;ZDy_g}Iv+m^Ziu=nJbFDk>2bqqGEAL>MXz-}c8to2 z!LHfy3CbcbqI#3-JL`v)VB0*Af~WmbbEmfv22^MW^Rl2Kd-9W{G_bl=$plx5rWrUf zqdsrEaOq^6LQBH&Jd!cDSc7|~O_n#3Z%%tnrKeLgU_#P(b=xf=^G78 zH#m^3Xme^E%$uT~K#-*JQ3t<|IR)rWSQW|ToX~Da=RkPi>kq-l6Vi^O+xOLy6OXik zHM?0`fW&9eb{WI3S^)x!c*fg4c>U5}vG8ZrnSo+&4VZCF8y?oyw0G5~QD;&;JQK+F zBc|H8?20@^%!5?ROQz2JIsQ@EWo95EI20H<<(w*h3I(O#!j^CH28Rlyeb$SB5VwVK zAL8Y4Mj1F{-n|KH^NsAW{1?Dk-;|?2?2fM&vTq5>%Eh&-S{TJbPxZ0HTvz{*OTyX| z%WDI4BGKmMDFqj(l2eb8WsoPdo!Jx5^Wn>`j|Gi-^!Zk+=ao?!>Q_;0w>0E7DFg#P z3rSK<=@5#$8uy{mHVmd+yLu^GvLwg6wPge86@*w#&9N_?Lp)9~ao7)&G_td9L#rPx z9G7Ib2!UmGP}0M6-IfEas6}i-e2yeK_5`qY#5`v`l7T`=1N{~dgm~zK8&ipC*Tl=c ztNXq)sNujc`@Geg-Ddl|h3Dh=Pq|vo$}Ltn=IR0k-QmO z(g$LNgxKnck!mTIFVu;^4^-hMOY!%-9RV`bY6mz(c>dJ`HX;J)f7=T?;%(eGi%2IE zv`_;7aWy65Sxx$=t1oo=own0tVE5cLmkX&3HXrLDKxOS2sTL4gEZU3V{h z?^RpxzG=mS1wt~tj8k$qe}RfHpbgq)C+XO+i{|) z_itAX;3kZ$4(jS_r!91SYUn}(b&42dx>FK)xxyk-vjIgf3{pXo)rS4vBbmM~h ze9m^+tf$|1ap;)QFZw={h=D<5U9}*vZLD0jlplWaXm#UxQ{Gk!z{Py?O}eW-xJ|jn zv@DME?JN{}wN(3(dh22DAM|nswF}Zu%%#_U)w-T>Z==KINC7w>HNV45@n>OfH%z;8 z5wZ~Ls^&dy7=-h|L*5|K4b#{TYLS@ZXn`C z=f*?BD%M|8ih)Xn4s%Ia4{ZuP$;?On3cVTROD z>kH25(8^CNw81SQ1|kO6WN7!5o+dtS&QBbR&*Ag4hNn(kEbx;46QaNmJ@8l><8AJT9^|}vrQ)=^6F^#TB1#MayAfLl*OcmQd*` zTt}3wlzj>inR?-5*BZQ@o}HB7OB`8DR^2;HSAZ7PWz=w*$oU>1SM-v`{hAjeC zO3;VuC4mS$@|vM~cn2qZ30nUqlqm$OU%05qu=ryj4;=ip74<~lb7dUok0hI90auii zMm!lXr(F6FdYNv-Bz*i ztw(x;LC`%8X<$dX5|DW~K?i%cXACz}{`?X|KnA{BgevZ^<@cA%ZJeq@kZz5($n{oy zz7}d4^lKzFQ_vp#-PRoI+R_n&ADe2=MV zOc}nSe#*3=2qOPiRzJmdJKN4EWSMi%y--dv3nK$=&Qwrsc$K1PY?{t36VwC-!W*`~ z%l+ls(u;i)+y_KYYXb=F(Z(5~jkt6$HzRO28%?fJLM=W`Ww0a6Cl5e;Opez@YV zQ4eQ@r}GOi%T#9T?lC}WEu48D#-`dlkq-|`yU2cOm-QQ03mA(IytJ@}L32F;Z~~+4 zW*K*pfmEa;vn{N|2NXrt{u zJcC8$paMZXMJyrdk}{iQ@6Q1cDF{2eFEJNcSi%xi&+w2pzD_{N;yoO5G4%@5g}?02 z;TU&rqrr8Kha-xsiZ0-3rf%5#d4Q{S(q0HbozD;5|Q?7F9KV5TPPTwxM-| zz*?DUpEDXmy~4zaIcC0w^$8@|gAcEyRr6Geogt$(tIciQkudUs_kq`sN5bO?!XD4UX56|k8vlpM?h!_^3$H)#(P7+M@!fm ze3w$3KEmvRj&8K0O|tFJie+x!Gwr^$jeo_Dwnp%nqKle@M!C=uUf#MB)9e68m#VLf z0rl3)q4ziR7t|1k#%aM*=lSwYy1bkm_NH6E(&otpMd4u5VmhsU<~Fns2+8H-lemRV zOGxK)3{*)XBDUaCV*i}f4(ChapMdyeNj~Y&RwRaJf)Zw6^WzV{i9^8>=E+B{b^2bxxu%`}3BOV)fnC zZH{ty)ms3Y`vsZF{AU6ff7&JXPH|29)cmi{zsDEZWHk>Nif2yf9|N?i-lxw1d{Aa@hk zyQ9OpBU(kF@4{k*6&jmkZY9S5#PgC&n!GJT95(}>4kg#ZjMd52+w8 zb-cuBWKI`2FCulXetTY-`X1)=<6o@i>ffwpx&{~v#hG&uYomR9RC&ptK|+TvV=P3{ zH`;2lTlwDJIVk7pGH}>*k&FPybz2a2YW@=^HOg^S(df5rrIrEj8IMBe0A_2lo+wmN zkp<_mV(Nw((uDg5bb6RJIjAA4?1k_DG28#y5Is|VE%B+)#OTpy#x=?3{miirxsqIq zbe;uL#;Q^=m)5Y_s9(Y=6pD#FAugcnK%cvVjtgofZ)sm^-m^zi(bb))7KAJSVjsl) zDu{?p1|vq3nt@LmZIqi;j<%LZ(Y#>rDHw_Vk|g_(38O`H1xcF8Pmr;HSgwlo-F7*F zn9vI9RV2p0yXl7gMym~HM`F&ogaOwY?4@0H#KT^A=}|FJ_#6o9}*YYuDy|BBgKx;XMXN#}XTRbcgu? zJvdNY2}@p(aJzfdjJZjI!6${hR$}|%jpENtEwkd%Z`NF7{C|huf?y?5PA~4PgR5QF z?T&W*E2!slVFd>o_Nfp*+BL0e-biRLns(wwz^MV3BlNhuf&P9PV6li`fg2H8S~AD_p1c#>T6D=fffo7upk0v3tWYQ_O+`l zm=@S$D5RYr0fO9AwE78%5{5%-UE==Z{FaUtnF7y9T)|f-zI&kF?Xlv?PlJADy?$EW z`77052q7l$x93OW740}fL_h?0E-PhKS2SNy z2cRN*-B{#`YaPZ_SawD9qFyF7z(C&Y8k+J=jo3vk{=lr&dy0XylO&)=h(^4rq86An z+p2x>vHa!@C)WR*#&kuR?@L%6UkJ{$BU;XZN6Qe5wJB>^ifk#{A4& zr~frG-bFhjLP$_x7q%23V3MS@9@Jy;Mvt2J{6cEmW<+!L+$e0We^T(bix5~i`yDfL zF5La5?BI7=6HiNCzF{wfM!;x+h72VmCf@pa%BvHJ6jOUk@tHTkPcFLNu{pKWS-aOk zlyxMt zL4R97pkmy9L;=4N-jgb>4IaH{Kdc-G^IE^gU7j-5CGp zoqQ#oJb+YXu|NNj*DRYF*_{o|F5W`%FL3(Tg8m!aU|j~{($@c=4&A%;cfI+)PDw`6o8-&>W-}t=0EgJ)fiF|L0LY4PgJz$h-xC(4Nnf8vp#_ z@4f#R{~5%SpNbST`>(w3kMw5GI3nZp|7rDqPrg+KQa*UBPhE~|%SZ{$5FB{kE|3}Z zn}gt?)q;kquAbV$1@Vl`($bGZck`EIK^kY~4wEa_YJCFv_r*SEZsu3~)*ASPZ|1_) zz7yF8Tb?T`0xM^=b*cZ-HvTc5-Mzh(IPT2?1FkIthxlN+>=KkypSEpLbSQhhV;r}J zj@YK5bcBNlO8SZj3;KZ{7v$sTb3ZJ!qv-n$&aap4f|s;ZC7^_(@% zMQC8#+N8@I9&$%Q{iFle7+d(i_iOw*-*lBO=g^IMdw*dFhb+lO&TZYc_#d7&hQ$A- z&h=3C4@`&bVOBF;@d|t3_1gC)yYf2#&CT`jH?6r48HyIrJR-STGNl&iPWLh&6P~SA z+@k!pu4W5oRtL>Iy9kee5-i6a{2+fb^}V}(Eh^Z_=1TJz&Sb49@*$hw794C&IkRsZ zwVf&TN=XlN^VI*c06#!bl7si106by&P# z6qcy*XgUX!iVQ3N@8u~H5>+ihr#&+==CW-es^vU16c2TXmMnuUo?_I#+^x6LOfZEJ zcp@FEiM(;qc=Z%)l?_l;W_OtL_7Utm7URtJRRZXN=T-+3^(keA??9f-OV^ z&YtRv`HF6Vdo#(VWrR+DI$r1v5nBQE;rxB?9fTeE$m4jtPO|pk#S$Ub+U-KnjQ6La zps?I6()V482QF@Exgx-ITX}&NwKKEtHGlU^lL?TEQE=Z-ErO1S`JOaa(2Mh z;KW#oy2t0hC+MyVCTSWIThT4ba1-BmKWk}JJ$$?H4e(nlpuv*+2pq`TQ3PFoOEt7m z$gZBdQ{}#yp>WFJKI;eDDtJKKTsxIsjKe3(Lbtwlf@n8bv!1gcl|K8xi32V8GI5k& zbjk2{8u1EmDvq-;9|9ur1L(XYc2^CkX*+7rSwIJ-js!Z+N*ls`HKezpkzCFOJ`iLk z;taZH6hNDl@>#h3CS3zJh}LHF(2(*UhJnY|>So-b@QmaCJrBGZ&HE-c=~8>1m4$-B)7AYN{u`YVeVY`B|mLTl7eXG8$hls7l`= z)g>DUx1@P;j_(3=&>rPmH_tM(VR0-|rD74rF}UtDD*AW)J`;Jv!D3RZH0hNR-Uu={ z`{9}mG8PYg3OvmWI08mM45ZwVSmv_Va6-JW)hh%uu>MP2xIh39?aUtzv+Sd#)a&y|&=ZadlB59oU^G6zPtC3MKS;uPtG57b;8<-!fIvb! ztv15NO+t0Zg_A3>sP07EzpwUPnBR;@gTftq#Ty!y1O^^Upp1MBQrQIi?h6*(>{m1( zOM4|QXRhg9k}`9SxH5|#+^~A(g*oXHy5Wt#O>?36y7KY}1v#UKh4*Px=3=?sigRcV zMCQgINnA^2(hl+;7YL+KrB+SNzO#Cmq0djgqv_wo#bgMq351%&X7oYt&NMVfxR#$-GTHkSPo- z2G=tJ10vvJ@p-(U%!JbNM-QjBlk3AVIC0aZNzhdc4L+ujn3-oYUw7qj^6&4ob zBRy@9EINFe{^kPM1H~u4yOFfnS}_w7n{PT_F?ARFm!jkI>on;Ip^EAT&Xu?V6$zaf zc}22NpElM7E;ai zLEqDXcRaO>F_@rwCg8P{+7OqUB+@1{(ZRQ`fESif|D@*3J7fGVpl#Mm=Ha4mz3nC1 z^B!qgN~HV;(t+UL&sbY>Cqc~pNS6VvPwRzOem=y@x;y$(UxJ=zAbh&VqM#*W+=>V| z_w}u27?zaLR9}YvM*G{~I9-23o|1LiJAJ>rtH&OIw;Gym$l{UQOn$}u&d18}%&ww; zAnEVi&lKZVB}}0--18ERz>y2fd@#v83#JF)XxdY8olHC&w)obzv5aAya{6pzgD&Is z)nOF^!?LiDxWM-X$(555RnK+0{r>y0*&v*p@=A7L?84#(%F(PS8#^Vipu-f>D-?EJ zvB372SvhL=O|c#R7t?u*>?~EQ**$7l`1W|uhoedKx7mMt{BxN;v;y(lENQ?zxB9tr z{eNv7{{9gKS-Cla>ir))@!yaCGt1W!Telbc;3n(;x#HjB^qCNq{f_)=mbBFWo+1C; zJ?L&C>UKG9uG!N5U6}so82_JR|N33y6NnlwNOAM? z4d&nWxQFvkn(g9^^c`nvM_nb7;BdtUV_>U6$_xt&3nMD8K-i9He@`a7m{_t<4e%NC3S2)R<4A7I@3G5Q&=lu-`sJslB7JRKc|ixiv@;ELHoEXZj? zA{cVVl-`mw;cD_qE0IxN@-nfAYSrkl8-UW|T;>^qqW_!C{0U;EQYNB?m{m3K?g zptj}#W2O!*a$+s{WkfTn#2FVN!DfUq*FbzL;9zw%!AG!k|&%j^7T`B!Xn5iLV%$14%fZ?>-z?vHxa=lLu z{Ii|y7;2`{?_OlZE)#=x{Zqgxvt33BH8FlAWFUv7P12zzsolHm*O6VD0>~|u5;4Wz ztYHVsLUCBbp3q~)y86ETY^h((_Sv}&>7C@OY)iN^1(D5n3ENck-s@7C`Qa{8NXzE2 zjHV}QReJ@o>ESmPXS)dRPSaD7wg=^b-B1+kKZl| zQ??@Jjkrq!5LplW9h`1 zW+h^2Mw`s6{xLoe1wd*46yJUrD%P68EEF$jNv2fZwfa@82j%9HF(d-PUOWAch>1>3 z4V#-?K$T|5*iF!$3Q@Kvoen*=Um)?$BGQT&z?aITL$=nOy?d&;D_y*mq!BbWM&_9r zm@IYOXZcZJkxZXbjs3LBz^v8}Jt4%Ec5-^!d+zsf^gF)nV4m4x#NY>6+OJffLxRn9 zSJ7#B$O6W7!RKk$!$&Bjfr;;|n93ij-yT3VPalAS+h(zw#+^{&aFH8LL10KBVzckr z>9w=rD(%?a15t3%DB9Xjh?ici6966<%d5)Ds#-dDoHA1r}~&SUpKz;UryIdnK!`g5|;de-L&o;x09_7ulo>CC(}` zZg95-j*(Tj**{c^2n+kYjqE7yij)JG4`0-}1>mj!v{Y}Sl6(LN zgrE;>CrwDiZFj!{@_#x#9G(lih0vaht~7f#+=jjsxIWmZl^3O}&Zo3LbJa)?uYj<| z;l})qQOGm+StswVRt&;e5IY9BQj&X{YgklRF9@gdnQnoQdqLN1aY>U9HFj>q)r0*sDU>`u(=i;o zT%Av9y}0Zo?WaVBKSZf%GC_kEFKTJt-gxJh74?k!k5p+r=BM^XoYGu60}vI1UkF68 zSfLaKmrW1m@0RJcs}x0O^fGl<^bxO0CI z6hhk8AM;mzT83<`;sQGJU%6V2);-n!ju##JS)5JrUkttL>3^i4!9=WFr1aJhlbvQy zSKMKcm!gL!*z{d(z{1XEkB==qrt#s%qjYG{Zkn@R3F86R4W@sXX ziCmKc87B$j!fOFqPDT-I0y@h+qIf)BIy5>Pz-4sS?b%6+13i=T%FxR9$zS*J-@?C` z8hS9hATV#VMQ$miGf-){#DO^&R$aC4U<~ro;Rq=mv|!-gWa}Pp@<9k7j6}KgX4EV%9rtDK#lgs1IRP?P^wB_7# z4N%ZQf3uF%e#K9iK zpe0w;#8*-9ebN;JS)iHeZBuy__cd3m>75g(nIuy^>AkTD2-3%C$EUiY)%&2ySs!G z6Lj<|Gc@k06#Zs*#U2# zilOBxE;l%BctMnFu{iDfW!3Nm#uC-g*nXZ>xQv@jVz4o?g*xE^hPGg!h@R8Qa2|yE zZ!d0prd79n1NYX%rj>97;hiO~DH{T^2VFqu@z6?M3iDD56y401hBvXbTOvqjI*2S4c9;Gk^TXILXEM)vV^;lI#D<;)Loz#S4eQ++ zB)1_rV%t-5(z0H4t%K1hyv<_;hY1b4(UVk2g8_j#xbJ+f7r^NDaTgyQFhDzzw3Lp~ zgM19MsH7IY{;mdS%Dyza3yt|dL?T9pwVR1g#v5#u@d5ns?PzvyRer0Bm(`WO$L7?V z5K;a3T6OgxQ7J7*O0#ogAxd7S6&ydlF(fqYjIV;G{*~@38M##?S!Om~=Q9x>q3*(Eo)y!b=S)#jk}r(oOY_vIIXY%5 z|IhD8**$3A6Pl3i$9OKGl?6($ZQ?4#F_v2DzgNl`Pawgl8YeazBty^l5_(|`?}c`^ zMk5FZG-A-^6kx~O1<=O$Yeb8r96(?n-oA;JjvY!)SV`&XBU<+(p1x-bm)eQGX}j4> zDSlA2Pg_VGYJTjUH>rS@)cJz-XuALE7)|}*oyl>_HTA3cgH$fOy& zKk%Y?SEnnqKLFZ3$t0iqd+|ZQx?pD(bA;}vE4ee))#r?ga|qcEdI`PTdP0#gz|_Jj z=jk_n{!e6(4m!z7WXJss0dw&7_ek+XA?%sNkF?eV)oPB}&lLPN(6(&AK7Q%hrk=u$ z&Ig?!{g~d~7NfKLy%L-NDikVIW5U{FNU5BC%Tqv}B$r9&A*)pL8SCo&1K&~oP|&)b zxCPH)!i3Axd32A%Nn@+u0h$0k-f^wR?nD)^_hSNi-QKDtd6)M%Jc(^n!-@jgOUG|2|j%5!7 za`JrrY8SXtYsH3TI@2_E#7X{=zE(0z-GhTQ$~kAPDm(BiGc7ykZEdpNldYQS?r|jD zsFMcaBb}%$)W9332gLFh5Z8Ns%C(Thw?<*x!h zQ2~r5PLDgbRq?j^trVi>wOaf`v>82wZ3m$aVp`$Gi>I1JVJ?L-^*f~D4jzB2P-ODy zDq5qg?%nX0>>o}BbCj)$vJn*`g#~JO9ZcR=LY?(*OXgJj&72V_ARPrdJ(5=H{^uIUI2{*DlYoVnz_#^Dd2QW*(x zc~op0Dw~uxM3lN;+TpKV=NL<1_V%^(U)KfFlxQt1>l$3Ftg^dPBhtAfu&+*s7UYu$ z*HiUxM7V3aq+LQDrQ``a>aDFV*4<$9rY84QV>8l4DQA9L);6IgHMB7*NnC)x-7YPp zpgP)PA1#*f=`eXpzw)xSLw}x7N2VvpuHlXunIW~`cZ)xGTm~2!N32Mu>`leQKOY&Flvt;>r+8@GAGs>UZ{)TgAV0K_(imh) z@fvG4ygCw`hOf`m-W6LkPHWTF$N5y0Vy{D7C9LpWz#=aPHa3mNX`j?^A-njC+J`*l zZj)OrV(Z)`*AG?4FIJaaEVUvvL*VF?R9of}@3N-j3CIj9&;l%H`cl-^t~Ug?T>CzH z4CsZhW6Y=`wgGGnNE-X7%U?uI($ni%QO?K_Kz<_Pds9WJQ6F?56~*j zE=Q&!L@jLXj25-V5p2^|@kg#K({8VAyAIB8?ZDlev6ud}_=ZqI&offA;j6LA>Nq96 zwTw+b?~YSw`)6e2u;p=(U356{f5jdTsnaHAG2^T4bGyghES;8z}&y8YQBO#OPDhz;S6s& zU*?ZFaLRaob)V|ofHar?Opz`11tMo@y-=<5ijFF}&Y%KSTop)Le$vK2LZUVGr|nv@ zK8UEEm=i@vJSvXp-iTW5b-kx`VQ3U}n2~Fa;b9}8%l$&=L}F(m(Pm*8L>vZ!Xg`Iv z&MWckn<$LO$Da73|Cee;d}nu;DN22oNR6I;Ph4G=zeCwM4=@ zwxWWQ`BL!N9$hh@TJ<2{|1b1l3+>E$1D{-W_{?T;Xk^;C$LM_}<7MnN@L@d4V)*|g zM3gcC;@;uP;`1o~f72!Ez9Q@PIKF!JYyO91{e7y$PCwGlfD6C($ENH5{O=#x>mNzq zl}x8|tBPFtG$Ad3(qX_#;K-?hdLa@L<~u){cqCr(&x0vJ!QGe;JlG`pyyQ&wOZr!r@_J#80n$iI?7LJZ_OM-O6!YjtT<}}m=5nMx z(61wZ*}&(V0zERKc|+CW9I4SjTFOqFbvYfMfrWha@jSTl5~(IMe1Mkt1pFC(a>#GQ znE4LkiwvL7?tdi7l%nvX?cR`Yig+e6OELA*46H7ba8lPllzaH0w1`#n9cNIf-~DLo=Yn5)XcX2RYjgD5DG4ameLqw(ww)nZJrI%58A;KFa-us356kZ$wL3J_v`iGdVRi z%EtzUan8bfV5iCe%hxQ6-&5w6DM{a8XIbOo>nUpY;)}Tte=}9pl)|OIXDudHfExaC z3JF`6X8gS%m!f@p%1Ki22Kr+M3r!^ga+L@q_gSPSgn2MUOr!#VHl>0P>1k!~(B4cW z{alS&{g(PS6I0be?l*5=U=HP?!9$BOgcoZqZP-mzzd0-pwKn3@4cyq?grrU<(#^>^ zwQ}k2+sA#EzmS{P@MixHU+)}W*Ve9oH*9R%R@1n#Z8vFb+qR8HjqS#^ZQDs>^Ih59 z-OoPH`JMOAd{)+6bFMY#7}xi@uW^s0XH+uJZj_1^M9q1q!uZK`1l=8r(( zBj-1QJ48Jr>O?;2D}h=TlPBEBz>zlKrgoliUkyv87w4-%e`0OZRNDKJ1s0#a8AZv3Ku;3lDsC%gvjfP;r8WBw0CH$5@&~=MEonh~gLVV{r{ilZl#~S(Z z*ZhcsOtaL|xvO7a_M*4tzjsKHYJ2sm#01k`AfBH-fCqeMFEnN#V4%W#PzR$d@wRn= zFvMu%!;6sLMNQlo?mL^LRf`bE;WYGC;RUt#h4?g3wH2b>aEl{gQU=Uk(Gxdm#;f)X zF4UA`10O4lhPl=fiY~68gWQ=^x9i2aAse_%nB3XLSvK6C&M0c@r_9~P1|%`3k?S^` zocwy2{tG8V?g^VMDmg$Ybi2!1e<5zQhrIT#kaPF`R=KX6A=4$Gd2g%gj$ms*1HK9YtXv0MX>Zx zLr*q%1gXew9w;})8RdJC*u(Hrt(2mCdr>{4!( zmui?l>+r<(QP9G#Syh?4ZYcvbQQ~cvotNg9*n28ujB(HtthSU{C@is4UcPH}{bT4# zlTmy*8Dc4*C^|pw&`@F(%jr)^OIAXTR7f>Nkw)Q<2fKS-k`e2$VJap))Qn0nz9zQy zmQIA3-vS9ZELY#~*38&KkM4#i#fwhiqfUouTQFr4Faz(UT#OGHvU5r#!tDwr^bqA) zNeQ1i;CHSd)9PcG6kq&vxui%{TZr()n3`9$bKMZ?J@bD?FmdYx>jiaa?jWH`M3m9p zDdDsb9C$QpEn|pDm8%=>2Hl4pthFGcI!H0NJ`!>|ex6e5s(}7T#sCD##(syNh8h$o zX%W|if6x7lQ(bphAp|DYFjS0+BFOwAp|g(4Q1s()Yk}(g zoxJHCrPJ-O-7J87R@}Ql$-se{11rKRSthKJU;$mR3VDQyClp#XW#GE4_7byTxgny| zqJGUjRZ>fcoW=_HFTtFcFm`-44q>a#Q*VnND(sJ3QNMpou4}x24C$S#Vag@#kG5aR zo#Heg9Z{~0*YjieE)^_s!E=91mL9_aCvAiBMt!;<71#P-XSVN7~hjkb|HefK9P4ESKaS?L?1>di?3CVWB zwo5=FDGD{MlpMLi5>&%~@@sbo5Jgt2`f`5i9nHu?6?NonJfYp{_CTf@p54G&CAiLb zepY^-h(`U76t?S?7f=H|bv@!u9J9u|~U0Kmz9y=aYf-X3{ zpna5p@0R{SX98v4{$3rh)@ZeD#@?-IV1v}|CjsQ7PFUvfN(hIkyJx4kaT)hWq6P^3 z)Y?Nl$TiH|cWBw&C4Xp?j~<4 zq9>nE&7mT6sJuk){nCkT&4ipYKj9Y9ZuGPrWbGll=sZl-sTD?3GKzJOMxL*@Ni4Zq z`zzMhF@HW600_^K5%|Tn?Tf1)vnI4vmY;H8rx%=Y)fV|iwGr@u>zGWg%T0=wKu;kX z`@v?KtXp1YF@Qb&azxP|+K!G%0CvdrU1~x~h1S~?p<I1KXX* z)bgxhmP5Bo`9H(b6Yg!9SqhFb6_aTU^9(Wfq7&RhE$i3;BPYWWD9%lULQHxM&=Tx* zMc&)nef$#Z#J5z5`B>xiG%6cPt&W^=KGjuX1u|XCMj`B!wkpoRk#Ab=)i+FHHeJ4` z>K9J@S+DFZMXf)+yu4IC-c9CrUViTYq(9~}%x27D?5w!Ah_j>XxWr2(LXoC#cO zpb_6JB)iam(?a)I*eMG}t-zGC>#51=7b@|76=AYwiKok_^>nYaeQ~uVH|r2{6?M*2 zd^ujJn3Aq)cHC|fxdG6BYmgI+nJd+qo)!uR zR&fD!lv*VBT5^@Ed0j9)AK`*ABNgo>WKaYV5M|dl)tD0^nep0&5 z%Ec`l@lyd49d-Ngb-==f%R-(sFw!-*H&}>m2|0^KmC?xr@?i6WGWqRbd2W9GO}q>#OTPA zqRAW>zkVEiB1kQR_|nfvL9{=e((TAJnS=e9WK8a|PHLiwv+pPPLSk!!f{gJK^k3ZO zS~6)?JTb8JD_DPMM;3fMsJ;ZKAO6_H=qXzm!k>c|Wnk;zy zG?^xPyxqr2XEFw12vO`dymX~9kqz};6h$6P;o}Cx>E^wHSSkn-0bd0OMnil|BxInNyq25XQ4k8 z>;J^n7<_D`HtK9Nzm((rH^u=zLDCu6{9gLL;seP4erLE9;I+uJ@g%eUe->8!siY^L zg9cVLCcrFRkKWHdOWZqqP5T3psT@Yv&_N}wt^0*297A4R*b4nZ%kAEKl-4stX# z^Tg{btMkG(3YAC`VWMP2`1O9}dH-19^H!>jWLQbx?=wS=@xGc!cva!V!UC;GL?h7K z_}LdY#-*&_PZPo`n~B|~;+>(uschEiDkJzm*$f8Shlmb@zCW;|mfqpy$Y6pCFDk3; zaj3`rARCy*fU`CiG^#?XHth>%CiY1ePk;9hyk%XuyE=M)Bvdxt?}mJU2cZuEsL>F+ zt`Bs{*j!LT^Ak&-3bBn97Vt>K6d9N{ZwMVskuHc5f##3kiN%cguHYtt(--+~vxAE8 zBaP$`gg$)1>K7!JEPdWT^6iyC*)Kqe8Dd|RdG%R;XoSJnmHW?s2$T{U3>HgeyITh- z9xssGXhOmW-2Cd@KaU&ueA45ZsC~QCyHF9G<5>9R?fB8Al7Y+`7E~V##VV>3CWjAY zYv+VfQpdJbK4x-R-Nz`&!q-XzZA#a#N}X85piZz^#j+1t|Jrc|b<^p>Mj-e7eCUQeBL_;&gY9)}8i&t01 zw8F(tEjl5=Xrz!O)0Xr&KQ;aPZ)vw5JX;w-ahZkg&r+0~n=sCWeoUs`@L~D3a>ywq z2f{82%_}!AnbWwDVB6-Q(Z70<>eiovzfcg=Uo7BgpqwBIPUt{_>FYG z_3rN8nINxvtzsTrC;di#No_?)HYRsw_Fm^lJQ<8|VT{A}R!?-rr4?=iqL>W)s33jr z8By4SPZ~Y*UO5d~Q==#EKu0#3UGp!V(=?;kqC%?1RZD`>M^9rby6&ATwNoW26 zsNz)c*NenmYvS$B1V8MCKR*TGpzQH@p%Zr!#&-1(sqym`92QcKJ4M|p6cxeWPr z%^abb8fW>1vfxYK|N4IRKV-OrXAWgs>P&=D&edNi;1qub zXQ%t+EJ0vEkzhZ;nb8%NVtANOPU_<`V0-Ai{AQ>BgA## z_A^LM_&96T-S<3~PCk0b2Xf`ZZ;-@!2g$VIZn`QoNUOxG{#p2{<&vt5B?$%0(MR>O zieKWkHu?PF=+?fv+qM}ZnP$+YDXt$_;YTV{yX|e(P7dQMz>?6cy4Q|O6{p`mKEhB? zy5=&HhHg`kF_1wtjAnXDZut2LTESv@)@zVliLx&&}me%UvY6nyJ*d zN@MFn2=3Bf8sBH4S!Xtk~KBBYfEP z{AHNwz1XHuXfZ0R=noTN5HLVp>~nmA&{9d=8+&bPpw4&+gp3gfs(~2Of;+qH0Fg53 zLv$I4;o8=Zu3!@3zK?lS0uG+#cU;sR7~y6U1NY_Fw(7z|U1DOsfc@kRe1QF8Rjp|Y zxWY`8g_D=$2Ozt>5zGq!UkM#TC}^kb>~ct986N+BOW~#=_n<=xVl5+pHQNA+gVm-C zbecVBmcfCX@MS_q}d)G^d2D$IObyYk~>rhcs)c6v8dGjnLk=4n>tp;%4>3`yMOUMz5VPb z4>=qdQ2>`!HyJRZOkC^~J$%hHxsq2SaOb7$lRtJHdjpIQSW3rW3Ti4BogQ&=0%IN; z)v2oqNz3t@h}A=Ak|8CTfV&yopNPM6NieXaf2uvJ)<6#W&@|ubKFP$IaywQqGy3=k zHN63-$y_b4d#ok?_F06nxmhyZR%nTcMqU5qoj3>IiBtGV)A3)$TKk+c^iu!1qnuSO zpyBTf0bkNBZ$|k7n>|bhS_{I$584>C^;gXOQga^CAy*)PRjyhUXkxnK)GZcEYWmWj z@&1B9tsC~MJQc|LjC?+PavA5wx@>JdBqa$zMYaZ6rr%^x#2XjUDCQvW|<#*<6c7%K%uigMY*H@v8(G2L_{-0kLFvPhI1EGQf;CBV;h|o^Q0OY-qa0NZ9x5 zpQ@ETwyh*36Qx=A*wcu^6LMjjF!a}wC9psc`rPf&+zj_U%68ae{Qyt9f?U@kX{6a8Zo`9Vl%Wn-ZvkATPh^Zd?IyMp%mLQ{IJP7$r>D8EXLyR$-L z(3wNXtsIq<+h2(*5CtsF;u^6C=LdEOoDKRzf;7Y`CIZu}0~lG7VcCG2zK;q>XQJj4 zwpAkYbgmV_jlmJ2seDMEGDzApzE9v%jAFwoi|xV-{;%7%g&!?xky%TTeo1Ab+=jr& zQ5^%1Uym+u?xru<^!4+2af>pa)JR#-`?{h!Smu;vI9oLI$QZ;y11*x$zmS$@j*4YI)ZJHKQ^#!FL z7FM?>0)JxUn_@Lw3!9%8B4BZ$*6pnkp20z^FG8AUxq&=*6CO^?AA{r{aoyxuj4#On z!f*d-8YhhrcGWp_b6m7-)iIbYu6R^C(8!8^fhZ@sj7OUP%b21wEVVGvHeKr5bQVFU zwVJ9Fox#U8@k6rfkj%`y+EW-gqLa~pLD-{y5|=W zT6khAPu22e6#zB$nn|)w?PMVW(6xDYF^*jnO$$JMABKAP53-F7>-_M(Uay~Rtoml_ z-1tO3@&qu#4QFWhAb81KPw>udG3NtO3IqB#h|T@A}BFZ$HYkKE?=l#;qI|E#EC@R1`#C|V4^ z*9uV3l6qoKB+(OEN6IOo3&&fmk1~utq`WSyn9%!0Rx;nOG`t1#2Z${{0pG%EeaB)i z5+6y~f)cocFZ5uAE_y6UTWam48an#Jr~u=82Wly5i^M{XRab=MGDH48yE+#ACUXA_ za{jM1PYiO93#{(sRIugm(ceGE|8sufUx4c)nz3yD-#fr9AZT~bgM$Nly8gr9e>YhH z6!3@vb<6uF$wuM-J|^JYv;}yb%`K}(8`A|aYYtN{N*^veC8$mok`;b29~!JYcZ-ft86D9qxJrv-Mj)Y)KyRi7*P(?2A{|{AAb~b;QN>=@tVjXv{2W~yW zT0pQAY0U^eCwvaG`MqA2g&;&!*CW!=ypN4yxR;sT>D^K2ykmxHZF3taqs@?CTi>y9 z2%mRZU~F~hpSn(SFW{4=vNd?XoJm9fQHUA$96mxQQGHMLBOnm=`!=zDffT(H`F|Di zf=$`N;|{O`!r`tK73t`X>(8Bzc=@symnDF9FA+u<-2GZcBzJz74m-zGStjnSy8y+I z{6VyBu(V99{$0)}-g&ecrkf9zc*%r(d{jUBAq>P(`sDy03`4LnaZWob)f*_48Xd0~ z90%UP$xJiP8Kh00sk2X(LMSC9Ox24mC2t47nD2@I!kFUU7_cw7A0d_6~~_tZdT7RyA;EaAQV@Sl@w} z9j-@7zYo+deidkew@!_0oc0Mdznq)O=SW+u9@qjQV*pgsg-!>n>;=@4o~YoyAyBzu z?gz3U@Mvq0e;c|>looN|GdLR);&rTaaZR8}brB7%+Z}z49?6G0n8L)#d;z#O5 zdlYp;AiEb)RP&U3F+(`R($o>4(f#Tq0`wrnLzSPlC6M?9>_@b!IV>W4Z<4efX<5>J z@ZXDdItmfbaf^A741Lsxs`xbYmxKKeL`s|3f~WT?tQS}xp&M~`K0}h7mF^R7%*grm z%*dOm?MyryT4H{Cb^z_to11>)sF^|8p7m#9@wA}0*z6(L*rG`;YPA{)V<~j0Z8?)O_fTU^ zwv55WKoidz;B5V*hF1|*!M4}D1$JV$c@_<{2*t-un{;U&t~~-k0n3tUdRZu+5zL4& zyw@6&YbVNJZgIk(+M0R_O((8WHu+D|#wV3G(=GT_^q@DqPr{Me4rjl?%A8m%@(L)1 zl0LQ|5r}jUvc|E>tB^+2_q;;Zq)Pk&!`C-q;;0xg&d`XU#Y>r64|qG2_t?bN?Dhu` zeSz|hg=BUUB?41_f@PFUj#zfS{6l1Ve)A0CKs-fc&igpd+mTgrrFJzUzy% zK%u!^hLGR?0U7=o7!2QoP`VQ1>uV$w7NL9rIf3`dTE0g!Er{^#sY%|Y1$N+wO<+t3 zAi2oqqceV=0T9r>U{s&igjeZbgEJ=*f(x$piW%*>5P-f{n23CljidiZKez27LI~{t zrJpr?j|~<@C1`9X!Wgv78r%^hTxo4jM@8HPQKsrdLJm2w#Lu_LxU!+QZ616po05cw zdsQ|{H;64zic9!^}($@##3=O<#^sPXvV9bAAq2y=8=65)h-Jkm4U3e>Taa zz*#ow5{5{(e=|9L(Z0)2X4Kk^X6)xtEhj|A&;*VXb+52Tq&g}81}`ATsAw_=CyiJH zx)dr)$?ndnT5Zpb8Gn86e=Boch;yLFtQvn4D(NHYh2_A#?mtyB3?a1Rt{ycRnLi~y zOp&g{@XpbHoqhu%sQ!FAPt#DF9430uAS~*H#C6W^Af5u=l8mgETLS9`R$$_!PEbn% zpzr(v=O1J=PRx0IJTr&ex82m=l?!X7sRp2Glk}H@oXY)|f)p+XLj7)5CFaFEchIoY zn*fNW{SjOL1j0TEceIsUEz&*5wRjqhUIt{f0+BYVi5lcMg?rSL()~XK9t7yg_&p=` zpXvI49CF*gqteL%kNjrW^pBqWGf4riw*&ND;ekGNG&cQ@cfJ4N6C&&lyB=~IV&?&n zF8_Md`ya^RAF$hyPeAsM{^-W&68nL{#qa?+K0-hBB!~#{Q{EdpmVB}Qq7tM5X7UXiSzYh;6@et^Xf%*cko^!2MOzWLg*q!(0 z3{l*(f-F9Ejz0pD4ZlU*SnJqsH5-}rHUtIoRaO{OCCdFwED~oM3u^SSY@HIMjD#dS z7S(Ggb1D>#%KiJrqzV9XeO7QzbP0b3VnEaMR>x0shjWC7P1vpc2~9SgA28^&uoQXJ zG|(_xr3(k$P#^iK-hBo{;Gt1xpYXNFCL+#eV?^6x^-WX^FpuoPpstYON%@42nzm$A zSTGO}Z_M_bl$^rc8p?nO-UjCS#q*)<>Teyskw^{@VgGjB|B+CJQ8NQ#?*gprIR;2d z$%@d>&m~_G+(MWt1L8ZZN>w5_lR}Gluv5HDxzM{2{~1f$oF{l@NF88jfK`XaZFuFw zL{*6WWKj5*OeD+;1EyR?I=^yzCRkBrn@snL5(<6b4bgXC2p=UC9bg^>rLM)iADs$F z-Xu$g`a3H2XwSG0h|yV_Ax_YEBrlnKUJI8IAg0B*_gfKBw64>|+`-4oV>2x)XyY}Y z^ccri4L$!*|Fs0T6c#x-6V$oS$=CB-!{YBpi5a3nG6VR>MnW*;UH4`vR1H@8#_lHH z5M}h0I45Q+c>L~eW???aYgW~O{IFne?eZ%!_27ZUsuusT!w4ESQO}-cHlq+^b|v z973irC;wrq+7sHV01kyD_DdlKiYy&`Crmf%!0?FRHyy|}^XH7cFm?u?uc_W)pFNr* z0Os{f_^=C}PdRO&Np=<{NP?id^YdSHH!V3Ms*m(>b78N+q?8^nM;@Q@n9G&1yxV&-PLm(^Zt1!L4`q_d#_C-???Ml1{lxn+K)a}t zM37%aKJAnun}HZ~2O(U+9Bdj|V5`rC4+O~7kmM(-BTvv=r8XKkU(6!{vPd#-#}o1j z;VQ^evSx9ifWT;(a7V8igM|mcgZ= zV7p4n4#Vu{L#juKM`G!C4-sGh?0IZytouCxT8AMbn9Jr|Oc9hdHB08}0o>0C5{oz9 zFa1#UYj3u98m_<21Sr2(w8!%q{aZD4(O3@B$u(*4qX)38lN5}LsO5V?F{<0s9FY4D z#G{++EqKT7fHEFG1r7O=c`|Mfp>D^Og?%86pFDnkys zzYN*_&c*y(HJ8JKtHInvM-j!=uFWj83RD(1yc6o=b>g4EN^i)&7{AEMAFcBrW`vy+ z86itLsh_Z_R+$he=kwHo<2qwST787s@l>VP$kWzzG3VGERe6(T; zS`*+_weldqnO%LFZ$2lNFWz~4Ok`|0=-w+D1*~qhgsPU`RTu6II+pq6v~6O#5;<&M zf8tRi#64a)IZx^`C#W9 zQGtu&`LSj$>I2sEI+<#)}Zk$$0ok}4h`&}3+JuuD~*bO=I?G2 z0zV>K?oq$GoT3`r=;lg5s(xPvWJ!i8t9ouuH-3zDr0XMz9gV_YdPnr58Jd9x4jHQ= zua-$k67x5<*muKCqV$8f#pgSjJ|oGEL}CJk!UH*>jE03pZ(y$G{dHS>1nM48aDesW z^Z|hzV2J-O6>=fuJ%1lrF&=03pKg@@5fC5{m78BaK)hFY{)oOmN9eeJf1>UmIU8C2 z*HHnr3U9!80^)s6`QL&9@W0{o?>UYC`y<)l+3*z#szsRU6^!}I<{PP~E zq6WDlFlfM~Z}cI`5=bL^2To~-aylIJ6?Kz-^7+KCUHGb86zNwVHi65^tEI>;Y}#uI zSRNp;0nRff3a2TIWBEpdUNqkstY~}{Q^(kGeTb17{VWOtzEZ9gBqQz9b;NYfnxq{Q ziYGY+Fpi7=#2CK5xMD>&I>TPq&7a^5*zSYsfnSV$@iTA->M}u zaQB%N^34+h^AidqdKt!L{g!eG=`ld`L-}Mqe*KOW;1wCvo~qQ$xJpCG$AYIs7lr9bnZcBm8;%68FwflG<24aoi^~0K=A!st>72x7o+|>r#+c1 zq+0(I(i(W|i?l23r_~1S4=_pentm{2L!g$RK4<4@i_*D=b0NQo8Y{uAp}iSD*#>v* zs^$^p)Yk%!%ezhO%5hf^l+F!M{!m;&&}C0~S6iam&M##&bYbD&$Y*w1hlJ0ho@*Ko zs)Tuq+am;DSr}c@Q(_9-5+ApXV$!~caFKtUlMCshrT)~t5ME|}4d>sz56D75u-Q8( zn|?k|&4d2b9YG@w)mMjQ9y-=TfAba+l-|}Ah>ET4_?%!?U1<=2@5t2-vrc)kE5Xa! zs5N$#0c~pAD5!~R6meen5{bl3nUX7A@gAIBkmjj z=@^PM^Hj$K!X^^zX@?nJm%&af^L&uBtMyLw0>dVoB}5j^yUAS%u>iP>1f!sX+UIRy z9SeeV+S|Z+G!Y{fGo%kp$^_=BozpOi+iQ*U1gkkPgfET72bgaTVw+SiFaAoikvx8F z+=GY6OkHJECrhGUk(Z~KWle$eztD$TB{vXVya9gJ{30iK7JTFT;ys3O zVn71Y3|hONzg<;`;Ow@-=c~WaV)nV~C2c}OA#hy%w1d8|&6k}HcLz>CqdP+n9Q30I zZ-J;l$~`efe<*qBi0#nHJXcmG;$Ie@F{$nVTSZA>M-=L2Zo$W*twPQx2j}>sjcu-o zOG=z-w4rSVZU_iJxu)R70}~40xs^?hQgvFSHJWZbO;Fu>m9V0ep^dU0mw_tmrZa%OrZ zj9*d+g2jg4L{)EhuA)Q7F6pk~T2q^?S= zfX90AuVlte*)TQe%qO_xNZ;@_M%cn3m~QY^7`0v~HYW$ZVoniL_4sf}pA?R+y;%L7rEnLHsovPA_es7Ip>lqG>^7ah z+}AQVlp(XN6ye9s3P=JYDE)~z-(-pJTPC&P6Z99;nyia3^)MQ40B&nvL#`OM2aC6S z|0*ms^>OplaaF4;zN5im;a60C$~8Ljd9iVAV@1XuS~vd{tJEq9d&I;cqjr+b;)xY;yTdn!)CV>L-&EBG+OrOzV3a0gO|zP}2wg zsWQAT#v8oFr@B64J4UPW(!v$ibMLmMAgfW)W$qD!zKd?wGov9Sg~GrzA!w2bWyca~ ze%=Rxxd4`V=Kz*E+oM7s%SjGJrn?Su67YbKYm0F3VA22K(klB$R9SASb1LV0h zp{ZI*6Ry-w2_jM|kWw`EQZaYUNj^=2%z!x~!IPE1?5aVNdQ6?@O1#KIrTBf6>N4v# zB}SEQLwJUzw(0u!Yi!B`4&1gxLB^F|66JGTn&&B`81-Xl?6y)kzyob9?s5|)<2`w{ z{sam~o~&Vt9Nju;`8rndDgP)S@$VO!NH=bS8%Sj( z%jd2GgDA`Y#t*8oe5+@%{&=@ZQK3piuHva4bzNMUUx}8gcxaqY|D5)4MTp9ZvzQhL z7+B6wh9fMmqG;bs+Sx?)5^~q!lym>t&8SZr|qK4KVdHE#(2=zFK1kTaRgvVw$xAm3#QEb9KY)$zu9G^tmw&~ z&I(9EcUyBQt@rCodb%rmhw84vR_}f1=%!U_2P7&tOc(RtjBiTWj-|ii$=mpH zzE?jqh=D>p?MT|^>t1EME;?S(t}zmCYF^uO_GqtDPf&{qvxb@HVt;=2u@M5uq_WX+ ze(G74jmdr9$e3tKe$c5V& zWn7a=)1x$ko>KJJxZdO6DgIf~Vy0RMvz)o^=0gR2)>{KyMlI4c%JP2bA%fENCZ&-X zwf4BR&y}C9zO}SPvdoLEg{mrq6tYjj>Z}(Jqf0icd^ge@hx%D9{B;(rWacCFd_}>r z)WJm36r8L2&Pr<3eK19?MHCXLBUAiFuaqm+<|*$#R&??|Ry4dRYl}~DB`riA=Be`% zXA=Oc3QnPWCFPLiU;u%Rpb^j|P?Z&$A^S4MZHpjADM~E4`$--D=$KW<4UbgZ=WDoQ zx}DFnDsat&aqr2xOvMg6k|(^Q~CA-uMzq1pMfFY#8@gM_QAc+5j!lNKX4z#7`%Kui|2b;TY0i_gLwfh~D_riNaj z&xsuZM3u+*gqDbBWS=CWhsg8eC(X~EG1=4`juFO$(TQ3Pri|enmWFP)$_CiCE_oi}E&p6N~~PA~k@c>%AQsII@(H@p+qB z5>LxhbC{U|*S{8MHY!0X2(=IXWI-(j7FEjmHR8dU2Fdz)HQ}%PKfu%Gj0DEwtcI1h zsXP2D8x;dE^;s)6?_7DkO2WgscLJdfK01D5F_k#hjf;i{AUUApTnqX(UYbF@j6+(8 z-g_-Z3OF|KY{Pd~bWp6rJgNxd{LY8rtC?ER7q(AYjbflEAj{h9~U&M;R?NgF* zf!k&*{r5Ju|9TBDF>UMt)_dRWd4ZR{M`ZrzYXF@<1hi}f9HIM(W(g6fUaTA6tzltV z0^ZiP0kS@asPFk^d4SN1u{6z<{ATMpA*5et#4B3kzgXHj4&oeZJr#6K!`#Z4VuOYg z)fuC6A?$4IZeuuuF1Ox2sQBl8V2sHL`GZ%!O!pg&s&qCjPQeZ_{In&eA9$>ev^~h^4mMV+bD(li@MzCd1#_{Z!i}J5zdUdin&7o#`vvA(2mCJ`TiO;%WKP*hq*7d8EQczZ>pCL6e{7g&t((O@ zuNO%3-AHva4{nUqfAAq(&i7-XEv7?tx^a*wJnA}*YS{kpBF(w8;go%UjY^aL>9FY~ zk>rFUbcB4Lmw~89+r0NI%_ubR&g@71c0jFUE_%bQV|h{zwtbv3GQ)2m8K?7&{*V;X7BMw)7YD!P=qQGcs58RG71FyIMh&_Z z=_!iqWa*`Ml)IgF)_2+tzYQINEDeqpZbVy5^QEFW00bAGfpM3&IwcHJJM!dO{pR;| zF1vK_31yvWTR{3;i#ToR>}>4;&ib-bqPN6*{zxciexXSw{OK4GB+ZaUaDJaYCX#rR z6__k70FsRW(B&tg-#~jDkIUXBWTDmwzqq7CE?*`nTPB#yh}F@^Bx_M4*aJmHvlYIV z9qW^Fxpe1g8|Un-TP3ZWg+dL?5)9XEsEfb5Tb4}J=icGjfkjQSL{bfUCanThK(3@0 z?fdM4N}9o>5S6qzdJ%`{U`^3TAx_58X`dG!&)V7BIJxx3#G=>K*^>5KVNLV?mX;;{ zxCaYx;C!Z}m2rDFdbtDd{Nu0~jhl=iGd#byL+1_8SI z21`5nLBj_yFfiwkQ^L_s12xnp<01+A8z2?Bv@SCb#NGnB4Soss(Btt?8~*2Bh2H!H zB``LJ&IP9zs4>sxVVcM_t*-iC=+*&Kcemd<6R3r2P{^-)$u~--xjbyFe8@t2DnkvO z%QX)9XUoSY1>9&L3^1G90@&w^eJiZ9&YB3WuJ^$_E)N`4h@?fCR%c`5;gdTEfbSaD zbue+z!G~HkHNf*4)zD9BrHWW+F9Dh8VnzGA;sg%u%H-rgXV&cmksPAlF;<=2iBrU3exUtbluraRDh@K2L3)#D*1rZ z2b&ev%@IupXAo)-c`9Mygw7=OR{3?{df7?@F~XgjvD>gF&QQ{8j~!L$7m|R7V_rmh z*rN5ZU7jN%Up7FY=hQWe0PbnnT);#Od(yawT@(#Cbjt z@io)MICA^e@8Kki|D=g~i|^pK72|?niIVRomA9zo#Cf>`=uiF%Co(qP(SmtZxw{Ok zZ?GEHHOrT5Uj%#hHvh5VsmREBy=&H(zM`|{&1KGJC6*>uQpcVwUaGoc`*<)c$-27V z{!WM5F*FXDQ-gf@8-LO!@EB&qOF1MtIX%=*JDk3cKu;D|yqVi9w5UnO(Z+f_Rq29Q zqB8dxQe7SrziLL;Jwqy9xk1)GpY`KZm{f8QD4^NSJ1$s`TG(mJZ9Tx<8<=+_p!=Td z2bl2hX{>sAd&bIU5Ro(l(;qs_7m;AGeTh07lj=)XSRv>Zy$T7qghpw~09+1IH+uRn zvn0(j$W_3OTY!{Pqyr)G3JUlfMl>2r*sAGJBG*3=#!JZsqI(`PK$ z)>XrT1CFEIHy4-6?qfeD*-e*J2Zb{5C8m;u9q7*CMNH_Gm0rEg-5?3{i@U4+-dY^~ zwqBl;P`A~Ub3pf4?n90+EZ2J2pJdIthfMS|M4JBC0Tphp=eO_{JB;KoH{X5JcARA& z`0(az{V~v|UiKC8Lqp0ZPDi`Izk%E!?kGArrhrZ!cQm=LIY_VEs9{jt_s&p4yiG<; zNPWhdB`LWyCtspVJ)(p_V4;T0xx~wXt>HY_+r{VFzaShfhyFPt0OnM%OyG3aA&`OB zus#YRLYIbq!<@vU_8!a!!rg$f0H4yw+RE`EKqJ`;bn9_ES%* zs~32PokMsmQhChgY}uSOf;3nZR|;FAF1f9Dp|oq8VWpU`$J$|gUTR>d(zkWPSU{3Zl#zM=d39zy!Qbzq4B5c*4v96QiY-birIg%BCijorkttsTj zc|)kGWm?5}Za$w$Z<$-YLL`+D3a|r1(pf8orkCEH$=A{p0pTVk6pey4Jv;E{c#Vu7x%gRg?d3u@+X2q8p7{RNA}JL=tN|D> z&&%6&&b;BZjsR%6*N{2~l>!T{gRW~^v6P9vg%yMF5^Vj!g4@9*aJ$lSSvKrZj|(E+ zr5nFYclvn~e@^uiax0+CLSH7J$3PWxk2~rC%CFjYhbR!;3)km7`R2MEj+VLCnVAr_ z)*5GjOLDbAK(i3$qXUAtlSYP8eX4_fxFZuDM&wdBK@xp()EA9XPdz!U*-byVya5A3uuy@i-QDp=MRcls-8XImt7Dl;;wa!%06A;^K-}@V;;(xhjhS_;k z#&M=6YH9sQ*7;-aTgT6JmW>z3IJ&cmksBOFjE~^xwmM7HZ$*cUfMsvRrCq!p;HO6# z_i;ZqzD+IS0P{S-z`Hna(cewMUs!ZWw0#TzdW8zmsOeA$RhAEVFbQSeW{0?BY;X6sCL2L_3}&YSq1 z9k0d`mQC+_Ph`CIoj!2&cHaAS z+CB)w_hh3R9sgU+YMj|)m^@9m=|hbq$cp#&-q4X#yCUL6!tdE)r^KSiwwBkHSl)|$J6My)Ew5poP?H~-l zibGh~{bQLFNpGT4?4bXHvE(Wzbdy2@Qp~$Q>~E!o6{y8Rf>+bf2A-{+(?-@7)q$;G zoDId6U6#f{89*Jr$Xl*sY)kOl$jx&+i$ z=ePH}ahU8-9O@|UgD=8@O%p+HR+l!<@D{46c)YLH9FwvkyM1(P~-sS`?NbUrgiLcmvI(dJ$ z-+R2?edMxvpL?oU_rOf7>)_<5xPrMSjG^Xdr4WQz<#@z?HP0_c@g2k?a54 zQQ!jvfx{`M^|Uo>rfo@@wW)Ldbe<5RKcw5GT=4<nuc~;idqZ5FS5jcvMF9Go-2dSrAjg=CJ@zF?L3J z_4Y@_fUGKNYgwh->J$F)hBpHzu?lD7zs1FfUk4=5rF*8Bx3TSI3CHB@p@618qRevC`EEjw>o(=@P@3Rs4y_2GCM9Jt27f=HYMA)HtA zUfPQ0Bv|=Cuc<+pAF0z8+bEi{FFBd=wrqu``BpCAr0KZ=Dh*VkpB7}8SM2Iz% zKwUNi62~2@PNYrru!W4S=uc6!SPDU0I?PAi z__t;eiP78MP)clEOfbD@4PxZ7a4;3N0URmQEbja=6nv3PzEb7v14 z3+d9ep~#+wA!GQ;Xb=hNjcFn%P-7$I#X=L&v8)#XH{uFF1`6Q|0*YfuXA1f$ z9=9RmQD%&}rJakzOJLItQI3GAodnD%lzDa)$(PaXE4En8dtn^a`m{PnH=py8^>XUy zn6t&3Af`_$Rj@(WpW;Arbs6MdB)hHFJP2}6Ro7{xSj#Hj#N?LqMeCY0Wn}9sREI6n za@_Q9>OjLxVm=Kvk8o>ivafkQEY082ZO8?-tOj)1JW2#&rFQDuifASrahDB|Vu3>~ z@CMd-jm_|jICQaYdjRlu>%N^3M%&7gi2;b$LHKc~jD~LL4bRF9q7D-Dd4e=~X&Z@= zpErwkHX@B9|Hocps49QerN?m_}GCe%ay>#P! z>+}cQ+O%PKH@maL-0LtNUYovN&JW{zI!&y8k2G*xw>Lu#=O4Zyo=qD9N9?v5acy@a z-qHENLawACicj*<6w&l@kKy;9J-7H)D?#*EO1TAcJ<_j{!I$fCdci3rt5W7T(FMMi zM?Z*$#nU7NJ*u$dPjKg>M(zp$yLE>LsSR0QpYd#7iI-KzZz5hNd>nxIl~y%(5(v^;4v*U~QFMLLB>&fbE~p*GSIBg6p{KM@d<;p}9e@Ih+OO8v6{Sk-6kXGW9u@OGGyHz)kqM{$7 zBs7$58o3J0%|!}sS!n$@cq%jY_`@*R}>;YEenR75@q{`)^8XZ2#0kK2duVL#W9r#^MzGs9lEf+@KS@zKdb*S(9%gNOsxp4#;3>i+6LBhK^uUogVOcTXAbTZCf_}}iNy6E%IU)_n` z1@mY1Q^>q65Xp2~%ylRnA4fQGzC)t#y~5B}RR%uq@Q}7*yHa0+HcrFQ@~DlUm6A*q zyy&Q+GeRi=-V5LEK3BTS7y6zjB~kG|LC%F8RjO{3cQW_$Uk0^#k-wc822yt1Zz3bO z(dIWl+3*8ywaq{^?SR+`nyt#;EWzYI$3&3F1)gQA)+RLPTH4pifY@5LV#S!OZm+cc ziPRV?l7o+ zE2DF$ek-pOnbOwN7I|71lMDMJ3N_}#BoMAtTKeTx3}X)kFYI=0ZRg0yv#L3ACEZ8D z&OVzzFuw@*15T~k4b3ci<*S-OQy}7FZKdSX8M08q1eGPz%p1EMHRHM)4rdl?Fc;13 z-8VhO%Lx6d0T2#G%tiU@{+zP2wz1E^k7$R!fEwp&%}nTK18QVHP#@s!X@OGwY0X^m z+4l{*DQrmdGZEvyG>M`qW_+k{wwEy%bhII$NGI-!uY-Otq>Qfv zl2DJ`>NCy=^W^ey^O|E&9|X-k^)*O!QsHFjQ{6i^>%C6AsuKmYb94;W-!JKJKRaL^ z$TSaV&Ir(-f4G}1cp*_6n_r7lCuAUimiab|lvre?}>_%#tj?tV%Ykt=4P(9d_SUz=b zQ5yTOp1~d3RA*6Oa;})_7f1|nvWv4AYEtCHo4?|?e5I`j%#>s1uI=;siO@+;8>{sA z5693by~{T36nQTD$%qrZ!D4ZIy0WYet(`YTFI9=+8OxQl#BxazUV>SLZw_loHhfJ# zkZTV~;w?+`lH}uPOufKp%f^Xi`CKfkT1KQMI>QuEf%d$Ms(uaD%2B9TuzGhz-^u=B z)@soa`+D9gf~aMg;3H+kfaT@5(#)$ok-JM|0i|fNJX$W}vlv9_7}PY3)R-i&!q;+-7FLfqg(a5xo5~08}ww0a7 z0O87kZRtdB9@2871<#NI;kB_jKpn26mc(JSG0NEF;ip`n?as)cZMiazfh9dxD!6X}QvP2BR z=u3v<8;pc~Ljt)DyE$!^AuxwIl5M@};2@YrvQFa0vS4O9e8|5NP;X6UI6G5}v~Gki z4VHjHqW@*{87Yw3@EHu(cC1{|YfD$F8u!pMFICKaO^Z)i%=^Y$)ClfZS!Ai<=k-cd zuvl_7=%Ve0N!!Se4%MWj(j~QcfOSuYBCIJUOza zmHUTNNA$)pjlT5m%2Gp{$C-gY<4t}vG)`X^w$N*6TRw>eAE<%ft^jnA@wsUN5BPXw zsj9IF%D;K@NHFn+LzDCzc{~RN3)b55D2@6u6{F-QC{H_Gy{>I z=M)tJ)J#|xV$WTzWay?!y&$!jbopStzpux4h=Np6b1EhwN<-^HkTIZ#|;Q&w6g7PP2g z(i(TB_r7NTPX9LdnAw{COQE-sMu0f>aJ2%Vks8iZ^sMI^A!;$;lCb%hDumHx$F&1M z@R%$UU%ujDhuzS$u-|gw3p71evmNc~`P( zI%}p3S8F3hFA=LFon9UHXXHlH7pIj2%^7!S3*t69#H8~}hRR)^wY|?|nUr?~^-Oi% zDGZZ4pXnj>hUWY3hu&VwG_NdAn@;FpZqX}uF+YeWsY^&S&CI;AFF8Gf7by6~!L5@& z`d$JVvsG-}rH2obMpFimSy}`}4@VsMOq-I@F(;AAXD_OHeXY)Yk2vWiNEQ^)(9(XW z0xi&L77Js_Zme{I0Ba_kD_;#dhW-wC01e6LaGCK1PZM+tEm&NxhSveq#y`sjZB$uD z9_tXKd1r5EFnUA~8wo7a?0E#&J=-DXa}pEf9gK~T>MR12xPo&nYyVxP{3gD^Eg_}> z>x+My{fT&02^6YY5EwbfN=H~fi)XdY0cg-R)IAOD(&Xuw-pKiVSlDe^lW1%|MyWG3 z`^!N*W*n4v$qN%@_K#Y@eAeGvCZoA|r;uy; zQIfRLp&`9t*$N}TOhICKUq*3&jIK?nhfZUa4RaaNx&&rol91cjp#cmu+tMmkUX7{T~Cx>}p7CiiAyC-+o=Xu|`V6D*}ADu$mgQs0;o!GOdq_hn6@rxoCNoUWOnNnzAw+;uM|S zKX++ImW|k5s?IuDPszOBYz2?Y@Lf_1u!JmzC1Q3MJu~oq zs5ln)tJwOxlq(YQg2H@Mh*ODf-339d876rjDxknA*=h5HI&z}Oy;tTo|)8H=Ac<+bDYvj*r zoY5FPZcEVH*cJibgkR7t9X2A@;=f2Qldg)0@Fm1H2Igi>b_9Q9FmP*mf+gq7C$~-F zIzn6*+n91wcjlZ1)(kD>OO1wAeq$I{8f+WlE-7asC$0*3PMz*e{v&ll5jzwFYt#6K z16ef0%$?)*;QKkCTwb|;m>L`}7pSwZ=P9@s5Qn0qIPXL6L{@ibtrD@c6h=)8C*_Mj z@2n;q^AUX_=JA`7+-5l7cJdj=e67z_5|SBBS<9(iWpvO~GeX8&*}HAdullC%eQ|;I zo4w*5YvA;Hn_s>3w7iKlLwA5Em3K0gbND20NkQZf!tv@5lmeNT?McJ8F%!=h8GPI! zN~Xah{BMuJRCR)3)-7*e2>jnyfiZVO8gh|cRNWr zg88w&xhKKX1IfCXk#yvE32q&#ODCp@zCZ~$0LSZ_8G;M!{REp z<;~*B<-))K@XCswS)pCb3J@sb5fEUxDIOpGx>D~# z7*t)&B263v;BBC{A-OwQ^uGn=&^1;T=MybFYCz5=hp+rm>l>gl`ZU{0eX5?ON)8Gl zv$80h(XhA2R^bvK3R{g^H=He9kHMY{x-`)*M`bPHd+mbo{MPZCbE*!Ps-O!!U3T1P zvt}C@q_J~C#I`?a{5OOBWJ1-N9PWnqV0TIThmEk0b+gBIIOV1)H`yH%) zMIj7jyO)t*Q|Q`#XWAZ@k-aJ3w-<=?nYt(jL?1Crj&wjR%ej3;nYRbDCB)^#gScVw zkjF&pKX$yThA@a9s>|LnW%H1bau9wQu$9djyv=dH!I&KEGfh5p2zcPDanSTTYEEXm z`~-#+LxkD&UNy+ZYL#3kaS&}AvRIJ~6h`|pi3p6&dT6US=^(UAz4d3hrZS+fiq8$4 zUTD%7pLp*@#x*3XhAI$Q`NweTX1j~h$| z|IBIl{D~)7fYs)Rp{LV-83eYrxhZno7oXzGT5AoVf=}XU(^h1jpx%239aaLupw+1(Q&mB4M z?p~JqQT(*G=9*!=GNs_%4jZ0nC$9(LxR>Gv(^JOl&UXt;6=(@oYr17)r7Ujv%Nj}& zgJRLFcI}2ZwfUE;YxVsG#lDupxuX_wrm=7dUmm1^&F_DcSXuiC7AV2bdfXRj5K}TL4lh1e||5kXzuS0Q$cCW z6!xA1Le}z27nJeaF{cslNQko#iXfP7PT~cgLHM6#-}{h4yyFdWO`*^_7&S|4xZ}V2 z4VzNj;aMB^WW=%36LR}mPRjAW-cHHap*+EO<7%t^VjOPuMZ=e;?$s7B%TtL_O6g*h z73MD)hl4|II8uFg8}~M3$aG$w&_WXwdJurTsY68*SyLb0Qqc3C+`#)*x*m<>&3X>< zu~;4o87;0HFyx3I9@G5ersIYP!e6`zqkCyN_}tM+^=5ZdZd94(i}W18d}uEmg8kgDs$61wMNZpYu* z5g!fu?bs%Ql!w2IafN`$qw#AN^L?8s&Gih6tyrl4_CuSWX{=n!yoAFL zcn=nKpadtSiH4~}W1Z?a`P;GPCdk>?x^ijVtb^SyxTKgjt7l4$f68$JmtEn zC<z>F4~j^n8yyosYQIP7J6#NoD;2r8 z%Kw-s-i8Dh`_{xA-PMQImDJ}NW9wv!{tmWB>5}hSKwdslbsV>RSa=S%yvGY)4x%P8 zfLb3+78MI}P@Yt6iq;s!%s=~_g_1N*McRM|J{**;RI*s^hnut9yo)a#&n3euRZaUm z&Ln$UQ2Z*;Q}k@)L}l1NE%&uj&RQ50d>B$LIT~*K)F%K~re9<3!&WFdpnxs43&jn< z@xP((ctx3}F)COX)tYhrt=BqXU=w<_vVT1n+5dx{j!Y10nA+1!X#4DwE9UhMe>?k4 zh?!4BXMu((3#`!zfYE#JIP%wpW=+m_TISosSVK6j5$Gk!u7&M}v_{1=0qfzFkO?jV zsP)O0YR9j`0KR!0bz)AxOXTdZ^a-M%9Lo={@Kyu+%c=)<&mtwIWM?zF@lDTxrtwy= z+P~-TUWALk_y@wj(7<693{vo}y3mW1Ra+>qct6@=qH}%f@<6biZR7>36z%%OfaPRe z%$Ox*zQYT(BtumH>y3(NtjEPyCn^I^-k7hoNz?m0345nK zHXz3x%rWr4?pK~23+MV2tBtt(Y{k)8-Oa=D#Fh^|=%p;0KM-i8xLQr_?G%}y^1 zM0{l&@?=bt*M`yvvK5AZwMy9#i!#<+Cp6ZK%NlsuZlmXcI1nTHBTt!+h_735tJdcib^N-l~Qm+;RIh@#WliXjmRIp zLaD-BsFO^>H%{%CMzYpptDiggjOuL6Q4(?--OoVU*-MQQ*$^{m}EIivj+kqK*he=8gt zJk;!FV3`g&1c-X+P!$>F$>fUA?i6oSD>=%%dvsIdC6HE&hyvW;G}{>tY48TmcZLf# ztt|d&%8lx!Y6wW{)@a0pE5j+h}1Gh4ja+p*Sw_4ep`u^9{8b%pTx`KdZMv8 zLw5?6K)5Ts&>;4HwKYZJWy({%*%(1VGY`!iZi;j$mxUa#A&{^XoFz~sWpf(^N5|ji zNjOY>N7L>L+!@iiUs-)oY}}klo3*P*3cn+NVp+fM4xsF|6~6*yZJWl)Y8KCo<~_zm zT!yI^+Pe=LFk{iuV&K;;>0?#KoTLo)y7V(qt&tRh___Vn&qVGo4l$VueULgkap9Y; zN})(1Q+LG0S4UeJ4u1IKWZ)K5^|Jv{yi?pq(n4Vwp|1SZ=7?y9|F&MA6oUq8rDH1m ztY|Sokg&ud)+EHp3--oZ`IjU44IN~Ieg;vomWHLUw+LQThL zI5#9K(e5?1wg$Eu&BK9_e*+^2w2-Hnm#4H6&HCV_{ST1yzu)|e>JX8A)0IMS{9lXm z|8tQG5e$SlB&}l}|2Mif5m?jg5M1p@_Fo2W(uMYlwiHnPqkuxBP z@Gec(g-Z~ihv(;OqRsT50t=ohXC?fr7t})#Kn)UDpcQ;03}Dy zto19*ht49e7H6Gq>;^LA*t#~%W@6YEvB}!&BJz@Wl-GZq?T>|j27Xs5_+AG3|409R z*ulaV{j%_n#4{gzTcM?apa%WK<;0DLwEWmO7-*fzTroeA* zApaV12!R-?oY9PmKeo~PGAly3R?wD*c43&^%wgx7_SbUbS~{PTX2sIjSF9ixQZuFd zzw$C7>D%8RNPIL-%VPdL@^Nvd#m2RyH&HUX<}hunfp0%|`}z1cXA|~+Or-EVTD9GS z;D?aVwKRlmAUv)+q*iAKvTQR-FowBJ$0}a3_#HVE+mIV)I46=!8FugdY9JFwF897& zKt}=t<+173<$3g4aO}8O!S&tg6TG^ykn7F6p2VjFr7g~SViSu(ZWd8Eu7a|Fr3aCecZ`H_or#_C+1FXEg zYAe|{mO@$lr>fuv7P0|(eZqHQ*vM;=~oK(+z0eY(Ln&hjCz)f9GENTM|h?aPg`J#6y4boO-4LM@ch__jjz#_%7Y_(HhyjNR0|XoVX@OI03>>@3pR4Yhgk zhIH4=JrjuWpUMyc`L2ddIobBB&)@Dij5ck-n&^u+Zc+UhK&n13`b}+Z=nfbUc7O&5=Th9Cj=PWA2 zWw}}JfC0->CT}5OH_+?W(&)yfrh4C>vtG#oSHlu_dPu&i=Ot*M@&xEI{wa&q7vYaDKF+5_fSUVCb2 znNS>UL^l-^^%GC3ZQD|Rhsw5~qqYz(JKY;gi87?RixL*d;BByWJyg8#WRvLIGKl3o z=0d=%$Hrfva;2HWJjIpWuDKcCAmkh>O_@e;X-{y`G`N!8pF0N|)8PMtu#`Oe?$k)k zlzNT3^(%bvTX#90)Lk)Ab!1_gmjuyjYr1+3ujBFmkMjSDKrFr_jNrcPRZYhtjZjkW z_DD_~I$9BSSZR@w-kywMRs!Wk(Vvc(2*%3(rk3{(kI+ov$<}`q-SMu!K2v<({yD^4 z61@MHvPCP;9-0TB^&cadsh);&OPRKOoAF;sIA)IbwL=eVt!kRmfSOEE;^}12JlN31 z-HHR`WO_E~D_BILG^YUAo;<}c?w|p{!j!XetQw#5dZ>VIg~LMLdNeuKz&T|4^LDZO z`7p`ffBs|70q;l+$c6~^w{OH7^;l-WxJ^C@CB+6a_9Q|F2?d0yo1-AD1BIXWM|pdu zka+6*2+>{taDe###R0OaT2DciSwNK-V1!9uN=p-eo`%g~Vk90W!AZd!QYKRo&ygJNR_8@IqXC%Y;m+Fm%I-)e}uB^ol?ca8h2UyZt zyJ{iL4WN=H7P~4_f@FO91H)08W@M%}y*66`*v6PI$5pX)`5VS`^y#N+*hirPIX zbGEl^jSkOsTPc6M*d`G}+=OzN+vRVlkl3=f991s3QLni%p>Eo6lC7vYuF0f%VaDkwwNVhU_wC@QfVpsP 如遇无法下载,请参考[这里](install-detail) + +* 启动 Arthas + +`./as.sh` + +执行该脚本的用户需要和目标进程具有相同的权限。比如以`admin`用户来执行: + +`sudo su admin && ./as.sh` 或 `sudo -u admin -EH ./as.sh` + +详细的启动脚本说明,请参考[这里](start-arthas) + +如果attatch不上目标进程,可以查看`~/logs/arthas/` 目录下的日志。 + +### 3. 开启诊断之旅 + +为了使你快速找到适合你分析、诊断问题的命令,我们将 Arthas 的命令按问题的类型做了一个大的分类,如下: + +#### 想快速了解系统、应用运行状况 +--- + +* [dashboard](dashboard)——当前系统的实时数据面板 +* [thread](thread)——查看当前 JVM 的线程堆栈信息 +* [jvm](jvm)——查看当前 JVM 的信息 +* [sysprop](sysprop)——查看和修改JVM的系统属性 +* **New!** [getstatic](getstatic)——查看类的静态属性 + +#### 类、方法冲突、class文件、classloader继承问题等 +--- + +* [sc](sc)——查看JVM已加载的类信息 +* [sm](sm)——查看已加载类的方法信息 +* [dump](dump)——dump 已加载类的 byte code 到特定目录 +* [redefine](redefine)——加载外部的`.class`文件,redefine到JVM里 +* [jad](jad)——反编译指定已加载类的源码 +* [classloader](classloader)——查看classloader的继承树,urls,类加载信息,使用classloader去getResource + +#### 查看方法执行参数、异常、返回值、调用路径等 + +> 非常重要,请注意,这些命令,都通过字节码增强技术来实现的,会在指定类的方法中插入一些切面来实现数据统计和观测,因此在线上、预发使用时,请尽量明确需要观测的类、方法以及条件,诊断结束要执行 `shutdown` 或将增强过的类执行 `reset` 命令。 + +* [monitor](monitor)——方法执行监控 +* [watch](watch)——方法执行数据观测 +* [trace](trace)——方法内部调用路径,并输出方法路径上的每个节点上耗时 +* [stack](stack)——输出当前方法被调用的调用路径 +* [tt](tt)——方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测 + +#### options + +* [options](options)——查看或设置Arthas全局开关 + +#### Arthas 基础命令 + +* help——查看命令帮助信息 +* cls——清空当前屏幕区域 +* session——查看当前会话的信息 +* [reset](reset)——重置增强类,将被 Arthas 增强过的类全部还原,Arthas 服务端关闭时会重置所有增强过的类 +* version——输出当前目标 Java 进程所加载的 Arthas 版本号 +* quit——退出当前 Arthas 客户端,其他 Arthas 客户端不受影响 +* shutdown——关闭 Arthas 服务端,所有 Arthas 客户端全部退出 +* [keymap](keymap)——Arthas快捷键列表及自定义快捷键 + +#### 管道 + +Arthas支持使用管道对上述命令的结果进行进一步的处理,如`sm org.apache.log4j.Logger | grep ` + +* grep——搜索满足条件的结果 +* plaintext——将命令的结果去除颜色 +* wc——按行统计输出结果 + +#### 后台异步任务 + +当线上出现偶发的问题,比如需要watch某个条件,而这个条件一天可能才会出现一次时,异步后台任务就派上用场了,详情请参考[这里](async.md) + +* 使用 > 将结果重写向到日志文件,使用 & 指定命令是后台运行,session断开不影响任务执行(生命周期默认为1天) +* jobs——列出所有job +* kill——强制终止任务 +* fg——将暂停的任务拉到前台执行 +* bg——将暂停的任务放到后台执行 + +### 4. 常见问题及FAQ + +TODO + +### 5. 其他特性说明 + +* [异步命令支持](async.md) +* [执行结果存日志](options.md) +* [批处理的支持](batch-support.md) +* [ognl表达式的用法说明](TODO/articles/92448) + +### 6. 用户使用案例 + +* [用户使用案例](usercase) +* [Arthas——码农的才思与浪漫] TODO + +钉钉交流群号: TODO \ No newline at end of file diff --git a/_sources/README.md.txt b/_sources/README.md.txt new file mode 100644 index 000000000..8451d95f0 --- /dev/null +++ b/_sources/README.md.txt @@ -0,0 +1 @@ +Arthas 是一款线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方法执行耗时,类加载信息等,大大提升线上问题排查效率 \ No newline at end of file diff --git a/_sources/README_EN.md.txt b/_sources/README_EN.md.txt new file mode 100644 index 000000000..8bde4809d --- /dev/null +++ b/_sources/README_EN.md.txt @@ -0,0 +1 @@ +This is home. \ No newline at end of file diff --git a/_sources/SUMMARY.md.txt b/_sources/SUMMARY.md.txt new file mode 100644 index 000000000..6b3dfbcb5 --- /dev/null +++ b/_sources/SUMMARY.md.txt @@ -0,0 +1,18 @@ +* 命令使用 + * [系统指标](dashboard) + * [线程堆栈](thread) + * [JVM信息](jvm) + * [查看类信息](sc) + * [查看方法信息](sm) + * [dump字节码](dump) + * [反编译类](jad) + * [查看类加载信息](classloader) + * [方法执行监控](monitor) + * [方法AOP观测](watch) + * [方法内部路径耗时](trace) + * [查看方法调用栈](stack) + * [方法执行记录与回放](tt) +* [启动脚本说明](start-arthas) +* [Release Notes](release-notes) +* 常见问题 + * [FAQ](TODO) \ No newline at end of file diff --git a/_sources/advanced-use.md.txt b/_sources/advanced-use.md.txt new file mode 100644 index 000000000..9eb68d54b --- /dev/null +++ b/_sources/advanced-use.md.txt @@ -0,0 +1,75 @@ +进阶使用 +=== + +## 基础命令 + + +* help——查看命令帮助信息 +* cls——清空当前屏幕区域 +* session——查看当前会话的信息 +* [reset](reset.md)——重置增强类,将被 Arthas 增强过的类全部还原,Arthas 服务端关闭时会重置所有增强过的类 +* version——输出当前目标 Java 进程所加载的 Arthas 版本号 +* quit——退出当前 Arthas 客户端,其他 Arthas 客户端不受影响 +* shutdown——关闭 Arthas 服务端,所有 Arthas 客户端全部退出 +* [keymap](keymap.md)——Arthas快捷键列表及自定义快捷键 + +## jvm相关 + + +* [dashboard](dashboard.md)——当前系统的实时数据面板 +* [thread](thread.md)——查看当前 JVM 的线程堆栈信息 +* [jvm](jvm.md)——查看当前 JVM 的信息 +* [sysprop](sysprop.md)——查看和修改JVM的系统属性 +* **New!** [getstatic](getstatic.md)——查看类的静态属性 + +## class/classloader相关 + + +* [sc](sc.md)——查看JVM已加载的类信息 +* [sm](sm.md)——查看已加载类的方法信息 +* [dump](dump.md)——dump 已加载类的 byte code 到特定目录 +* [redefine](redefine.md)——加载外部的`.class`文件,redefine到JVM里 +* [jad](jad.md)——反编译指定已加载类的源码 +* [classloader](classloader.md)——查看classloader的继承树,urls,类加载信息,使用classloader去getResource + +## monitor/watch/trace相关 + + +> 请注意,这些命令,都通过字节码增强技术来实现的,会在指定类的方法中插入一些切面来实现数据统计和观测,因此在线上、预发使用时,请尽量明确需要观测的类、方法以及条件,诊断结束要执行 `shutdown` 或将增强过的类执行 `reset` 命令。 + +* [monitor](monitor.md)——方法执行监控 +* [watch](watch.md)——方法执行数据观测 +* [trace](trace.md)——方法内部调用路径,并输出方法路径上的每个节点上耗时 +* [stack](stack.md)——输出当前方法被调用的调用路径 +* [tt](tt.md)——方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测 + +## options + +* [options](options.md)——查看或设置Arthas全局开关 + + +## 管道 + +Arthas支持使用管道对上述命令的结果进行进一步的处理,如`sm org.apache.log4j.Logger | grep ` + +* grep——搜索满足条件的结果 +* plaintext——将命令的结果去除颜色 +* wc——按行统计输出结果 + +## 后台异步任务 + +当线上出现偶发的问题,比如需要watch某个条件,而这个条件一天可能才会出现一次时,异步后台任务就派上用场了,详情请参考[这里](async.md) + +* 使用 > 将结果重写向到日志文件,使用 & 指定命令是后台运行,session断开不影响任务执行(生命周期默认为1天) +* jobs——列出所有job +* kill——强制终止任务 +* fg——将暂停的任务拉到前台执行 +* bg——将暂停的任务放到后台执行 + + +## 其他特性 + +* [异步命令支持](async.md) +* [执行结果存日志](save-log.md) +* [批处理的支持](batch-support.md) +* [ognl表达式的用法说明](TODO/articles/92448) diff --git a/_sources/advice-class.md.txt b/_sources/advice-class.md.txt new file mode 100644 index 000000000..d93dae0de --- /dev/null +++ b/_sources/advice-class.md.txt @@ -0,0 +1,53 @@ +表达式核心变量 +=== + +无论是匹配表达式也好、观察表达式也罢,他们核心判断变量都是围绕着一个 Arthas 中的通用通知对象 `Advice` 进行。 + +它的简略代码结构如下 + +```java +public class Advice { + + private final ClassLoader loader; + private final Class clazz; + private final ArthasMethod method; + private final Object target; + private final Object[] params; + private final Object returnObj; + private final Throwable throwExp; + private final boolean isBefore; + private final boolean isThrow; + private final boolean isReturn; + + // getter/setter +} +``` + + +这里列一个表格来说明不同变量的含义 + +|变量名|变量解释| +|---|---| +|loader|本次调用类所在的 ClassLoader| +|clazz|本次调用类的 Class 引用| +|method|本次调用方法反射引用| +|target|本次调用类的实例| +|params|本次调用参数列表,这是一个数组,如果方法是无参方法则为空数组| +|returnObj|本次调用返回的对象。当且仅当 `isReturn==true` 成立时候有效,表明方法调用是以正常返回的方式结束。如果当前方法无返回值 `void`,则值为 null| +|throwExp|本次调用抛出的异常。当且仅当 `isThrow==true` 成立时有效,表明方法调用是以抛出异常的方式结束。| +|isBefore|辅助判断标记,当前的通知节点有可能是在方法一开始就通知,此时 `isBefore==true` 成立,同时 `isThrow==false` 和 `isReturn==false`,因为在方法刚开始时,还无法确定方法调用将会如何结束。| +|isThrow|辅助判断标记,当前的方法调用以抛异常的形式结束。| +|isReturn|辅助判断标记,当前的方法调用以正常返回的形式结束。| + +所有变量都可以在表达式中直接使用,如果在表达式中编写了不符合 OGNL 脚本语法或者引入了不在表格中的变量,则退出命令的执行;用户可以根据当前的异常信息修正`条件表达式`或`观察表达式` + +> OGNL表达式官网:https://commons.apache.org/proper/commons-ognl/language-guide.html + +> 一些特殊的用法: + +TODO + +middleware-container/arthas/issues/263 + + + diff --git a/_sources/arthas3.md.txt b/_sources/arthas3.md.txt new file mode 100644 index 000000000..8fe7c5388 --- /dev/null +++ b/_sources/arthas3.md.txt @@ -0,0 +1,112 @@ +### Arthas3.0的新特性 + +#### 在线诊断功能 +Arthas3.0中最重要的特性,不需要登陆机器就可以对应用进行诊断,体验和本地诊断完全一致 + +##### 使用步骤 + +TODO + +##### 动图演示 + +TODO + +#### 管道支持 +Arthas 3.0开始支持管道, 率先提供了`grep`,`wc`,`plaintext`的支持。 + + +### 去groovy依赖 + +groovy表达式在arthas2.0中大量使用,例如watch表达式 + +```sh +watch com.alibaba.sample.petstore.web.store.module.screen.ItemList add "params + ' ' + returnObj" params.size()==2 +``` + +其中`"params + ' ' + returnObj"`以及`params.size()==2`背后其实都使用了groovy来进行表达式求值,如果反复大量的运行这些表达式,groovy会创建大量的classloader,打满perm区从而触发FGC。 + +为了避免这个问题,Arthas 3.0中使用了ognl这个更加轻量的表达式求值库来代替groovy,彻底解决了groovy引起的FGC风险。但由于这个替换,导致原来使用groovy脚本编写的自定义脚本失效。这个问题留待后续解决。 + +在3.0中,watch命令的表达式部分的书写有了一些改变,详见[这里](https://github.com/alibaba/arthas/wiki/watch) + +#### 提升rt统计精度 + +Arthas 2.0中,统计rt都是以`ms`为单位,对于某些比较小的方法调用,耗时在毫秒以下的都会被认为是0ms,造成trace总时间和各方法的时间相加不一致等问题(虽然这里面确实会有误差,主要Arthas自身的开销)。Arthas 3.0中所有rt的单位统一改为使用`ns`来统计,精准捕获你的方法耗时,让0ms这样无意义的统计数据不再出现! + +``` +$ tt -l + INDEX TIMESTAMP COST(ms) IS-RET IS-EXP OBJECT CLASS METHOD +------------------------------------------------------------------------------------------------------------------------------------------------------------ + 1000 2017-02-24 10:56:46 808.743525 true false 0x3bd5e918 TestTraceServlet doGet + 1001 2017-02-24 10:56:55 805.799155 true false 0x3bd5e918 TestTraceServlet doGet + 1002 2017-02-24 10:57:04 808.026935 true false 0x3bd5e918 TestTraceServlet doGet + 1003 2017-02-24 10:57:22 805.036963 true false 0x3bd5e918 TestTraceServlet doGet + 1004 2017-02-24 10:57:24 803.581886 true false 0x3bd5e918 TestTraceServlet doGet + 1005 2017-02-24 10:57:39 814.657657 true false 0x3bd5e918 TestTraceServlet doGet +``` + +#### watch/stack/trace命令支持按耗时过滤 + +我们在trace的时候,经常会出现某个方法间隙性的rt飙高,但是我们只想知道rt高的时候,是哪里慢了,对于正常rt的方法我们并不关心,Arthas 3.0支持了按`#cost`(方法执行耗时,单位为`ms`)进行过滤,只输出符合条件的trace路径,目前,这三个命令的相关文档已经做了更新,增加了该用法的示例,请在[这里](https://github.com/alibaba/arthas/wiki/home#%E6%9F%A5%E7%9C%8B%E6%96%B9%E6%B3%95%E6%89%A7%E8%A1%8C%E5%8F%82%E6%95%B0%E5%BC%82%E5%B8%B8%E8%BF%94%E5%9B%9E%E5%80%BC%E8%B0%83%E7%94%A8%E8%B7%AF%E5%BE%84%E7%AD%89)查看。 + +#### sysprop命令操作SystemProperty + +sysprop命令支持查看所有的系统属性,以及针对特定属性进行查看和修改。 + +``` +$ sysprop +... + os.arch x86_64 + java.ext.dirs /Users/wangtao/Library/Java/Extensions:/Library/Java/JavaVirtualMachines/jdk1. + 8.0_51.jdk/Contents/Home/jre/lib/ext:/Library/Java/Extensions:/Network/Library + /Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java + user.dir /Users/wangtao/work/ali-tomcat-home/ant-develop/output/build + catalina.vendor alibaba + line.separator + + java.vm.name Java HotSpot(TM) 64-Bit Server VM + file.encoding UTF-8 + org.apache.tomcat.util.http.ServerCookie.ALLOW_EQUA true + LS_IN_VALUE + com.taobao.tomcat.info Apache Tomcat/7.0.70.1548 + java.specification.version 1.8 +$ sysprop java.version +java.version=1.8.0_51 +$ sysprop production.mode true +Successfully changed the system property. +production.mode=true +``` + +#### thread命令支持指定采样时间 + +thread命令计算线程cpu占用的逻辑,默认是采样100ms内各个线程的cpu使用情况并计算cpu消耗占比。有时候100ms的时间间隔太短,看不出问题所在,Arthas3.0中thread命令支持设置采样间隔(以`ms`为单位),可以观察任意时间段内的cpu消耗占比情况。 + +``` +$ thread -i 1000 +Threads Total: 74, NEW: 0, RUNNABLE: 17, BLOCKED: 0, WAITING: 15, TIMED_WAITING: 42, TERMINATED: 0 +ID NAME GROUP PRIORITY STATE %CPU TIME INTERRUPTED DAEMON +78 com.taobao.config.client.timer main 5 TIMED_WAITING 22 0:0 false true +92 Abandoned connection cleanup thread main 5 TIMED_WAITING 15 0:2 false true +361 as-command-execute-daemon system 10 RUNNABLE 14 0:0 false true +67 HSF-Remoting-Timer-10-thread-1 main 10 TIMED_WAITING 12 0:2 false true +113 JamScheduleThread system 9 TIMED_WAITING 2 0:0 false true +14 Thread-3 main 5 RUNNABLE 2 0:0 false false +81 com.taobao.remoting.TimerThread main 5 TIMED_WAITING 2 0:0 false true +104 http-bio-7001-AsyncTimeout main 5 TIMED_WAITING 2 0:0 false true +123 nioEventLoopGroup-2-1 system 10 RUNNABLE 2 0:0 false false +127 nioEventLoopGroup-3-2 system 10 RUNNABLE 2 0:0 false false +345 nioEventLoopGroup-3-3 system 10 RUNNABLE 2 0:0 false false +358 nioEventLoopGroup-3-4 system 10 RUNNABLE 2 0:0 false false +27 qos-boss-1-1 main 5 RUNNABLE 2 0:0 false true +22 EagleEye-AsyncAppender-Thread-BizLog main 5 TIMED_WAITING 1 0:0 false true +``` + + +#### trace命令自动高亮显示最耗时方法调用 + +trace命令现在会自动显示 + +![Untitled2](TODO /Untitled2.gif) + + + diff --git a/_sources/arthas_3_0/home.md.txt b/_sources/arthas_3_0/home.md.txt new file mode 100644 index 000000000..c13dd2830 --- /dev/null +++ b/_sources/arthas_3_0/home.md.txt @@ -0,0 +1,109 @@ +Arthas 3.0使用说明 +=== + +## 命令行诊断 + +1. 安装Arthas 3.0启动脚本 + + ``` +curl -sLk http://TODO/arthas/install.sh | sh +``` + +2. 可以直接运行`./as.sh`,启动脚本会自动更新到最新版本 + +``` +➜ tmp ./as.sh +Found existing java process, please choose one and hit RETURN. +* [1]: 53090 org.apache.catalina.startup.Bootstrap + [2]: 50020 + [3]: 69893 org.jetbrains.idea.maven.server.RemoteMavenServer + [4]: 93320 org.jetbrains.jps.cmdline.Launcher +updating version 3.0.20170224142641 ... +######################################################################## 100.0% +Archive: /var/tmp/temp_3.0.20170224142641_35932/arthas-3.0.20170224142641-bin.zip + creating: /var/tmp/temp_3.0.20170224142641_35932/arthas/ + inflating: /var/tmp/temp_3.0.20170224142641_35932/arthas/arthas-agent.jar + inflating: /var/tmp/temp_3.0.20170224142641_35932/arthas/arthas-client.jar + inflating: /var/tmp/temp_3.0.20170224142641_35932/arthas/arthas-core.jar + inflating: /var/tmp/temp_3.0.20170224142641_35932/arthas/arthas-spy.jar + inflating: /var/tmp/temp_3.0.20170224142641_35932/arthas/as.bat + inflating: /var/tmp/temp_3.0.20170224142641_35932/arthas/as.sh + inflating: /var/tmp/temp_3.0.20170224142641_35932/arthas/install-local.sh +update completed. +Calculating attach excecution time... +Attaching to 53090... +real 0m0.336s +user 0m0.498s +sys 0m0.075s +Attach success. +Connecting to arthas server... current timestamp is 1488178414 +Trying 127.0.0.1... +Connected to localhost. +Escape character is '^]'. + ,---. ,------. ,--------.,--. ,--. ,---. ,---. + / O \ | .--. ''--. .--'| '--' | / O \ ' .-' +| .-. || '--'.' | | | .--. || .-. |`. `-. +| | | || |\ \ | | | | | || | | |.-' | +`--' `--'`--' '--' `--' `--' `--'`--' `--'`-----' +wiki: https://github.com/alibaba/arthas/wiki/ +version: 3.0.20170227131708 +pid: 53090 +timestamp: 1488178414548 +``` + +### telnet远程诊断 + +只要在上一步中启动了Arthas Server, 那么你可以直接在本地(针对日常环境的机器),或者是跳板机(针对预发和线上机器)上,通过telnet命令直接远程连上去诊断,使用上的体验完全一致。 + +``` +➜ telnet 11.164.45.24 3658 +Trying 11.164.45.24... +Connected to 11.164.45.24. +Escape character is '^]'. + ,---. ,------. ,--------.,--. ,--. ,---. ,---. + / O \ | .--. ''--. .--'| '--' | / O \ ' .-' +| .-. || '--'.' | | | .--. || .-. |`. `-. +| | | || |\ \ | | | | | || | | |.-' | +`--' `--'`--' '--' `--' `--' `--'`--' `--'`-----' + + +wiki: https://github.com/alibaba/arthas/wiki/home +version: 3.0.20170315140000 +pid: 1463 +timestamp: 1490938898194 + +$ + +``` + +## 新特性介绍 + +请参考[Arthas 3.0新特性](https://github.com/alibaba/arthas/wiki/arthas_3_0/new_feature) + +## FAQ + +首先请确保你的目标机器上,Arthas 2.0的server正常的shutdown了。否则,Arthas 3.0连上去之后不会正常启动。 + +### 关于web console中文本的复制粘贴 + +目前不同浏览器对复制粘贴的支持程度各不相同,mac下的Chrome是支持的最好的,目前的支持情况如下,我们正在想办法提供更好的复制粘贴体验 + +| 操作系统 | 浏览器 | 复制 | 粘贴 | +| ------- | ------- | -------------- | ---------------- | +| macOS | Chrome | COMMAND-C,鼠标右键-复制 | COMMAND-V,鼠标右键-粘贴 | +| macOS | Safari | 鼠标右键-复制 | 鼠标右键-粘贴 | +| macOS | Firefox | | | +| Windows | Chrome | Ctrl + C | Ctrl + Shift + V | +| Windows | Firefox | | | + +### 关于字体大小 + +如果觉得字体太小,可以通过浏览器内置的字体调整功能进行,web console支持自适应调整。 + +| 操作系统 | 浏览器 | 增大字体 | 减小字体 | +| ------- | ------- | -------------- | ---------------- | +| macOS | Chrome | COMMAND加= | COMMAND加- | +| macOS | Safari | COMMAND加= | COMMAND加- | | +| macOS | Firefox | | | +| Windows | Chrome | | | +| Windows | Firefox | | | \ No newline at end of file diff --git a/_sources/arthas_3_0/new_feature.md.txt b/_sources/arthas_3_0/new_feature.md.txt new file mode 100644 index 000000000..67f07f267 --- /dev/null +++ b/_sources/arthas_3_0/new_feature.md.txt @@ -0,0 +1,196 @@ +Arthas 3.0新特性介绍 +=== + +Arthas 3.0在架构上做了重大改造,通过引入`termd`完整的支持了telnet协议,并基于websocket封装了telnet协议实现了`Telnet over HTTP`,使得在线诊断成为了可能,并且保证了本地启动,telnet远程访问,在线诊断三种方式的体验完全一致。都支持自动补全,高亮显示等功能。并且支持`多人同时在线诊断`。 + +### 在线诊断 + +Arthas 3.0最重要的特性,通过Arthas在线诊断平台,无需再登陆目标机器,一键启动Arthas并开启诊断! + +![image](TODO image.png) + + +具体使用方法请参见[在线诊断使用说明](https://github.com/alibaba/arthas/wiki/arthas_3_0/home) + +### 管道支持 + +Arthas 3.0开始支持管道, 率先提供了`grep`,`wc`,`plaintext`的支持。 + +```sh + java.vendor.url http://java.oracle.com/ + java.vm.vendor Oracle Corporation + java.runtime.name Java(TM) SE Runtime Environment + sun.java.command org.apache.catalina.startup.Bootstrap start + java.class.path /Users/wangtao/work/ali-tomcat-home/ant-develop/output/build/bin/bootstrap.jar + java.vm.specification.name Java Virtual Machine Specification + java.vm.specification.version 1.8 + java.awt.headless true + java.io.tmpdir /Users/wangtao/work/ali-tomcat-home/ant-develop/output/build/temp + java.vendor.url.bug http://bugreport.sun.com/bugreport/ + java.awt.graphicsenv sun.awt.CGraphicsEnvironment + java.ext.dirs /Users/wangtao/Library/Java/Extensions:/Library/Java/JavaVirtualMachines/jdk1. + /Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java + java.vm.name Java HotSpot(TM) 64-Bit Server VM + java.specification.version 1.8 +$ sysprop | grep java | wc -l +36 +``` + + +### 启动自检 + +针对启动时经常出现的权限问题,在启动脚本中增加了自检逻辑,脚本会自动判断目标进程是否具备attach权限,并给出进一步的提示。 + +``` +[huxing.zhx@v125056161.bja /home/huxing.zhx] +$./as.sh 32260 +The current user (huxing.zhx) does not match with the owner of process 32260 (admin). +To solve this, choose one of the following command: + 1) sudo su admin && ./as.sh + 2) sudo -u admin -EH ./as.sh +``` + + +### 去groovy依赖 + +groovy表达式在arthas2.0中大量使用,例如watch表达式 + +```sh +watch com.alibaba.sample.petstore.web.store.module.screen.ItemList add "params + ' ' + returnObj" params.size()==2 +``` + +其中`"params + ' ' + returnObj"`以及`params.size()==2`背后其实都使用了groovy来进行表达式求值,如果反复大量的运行这些表达式,groovy会创建大量的classloader,打满perm区从而触发FGC。 + +为了避免这个问题,Arthas 3.0中使用了ognl这个更加轻量的表达式求值库来代替groovy,彻底解决了groovy引起的FGC风险。但由于这个替换,导致原来使用groovy脚本编写的自定义脚本失效。这个问题留待后续解决。 + +在3.0中,watch命令的表达式部分的书写有了一些改变,详见[这里](https://github.com/alibaba/arthas/wiki/watch) +### 提升rt统计精度 + +Arthas 2.0中,统计rt都是以`ms`为单位,对于某些比较小的方法调用,耗时在毫秒以下的都会被认为是0ms,造成trace总时间和各方法的时间相加不一致等问题(虽然这里面确实会有误差,主要Arthas自身的开销)。Arthas 3.0中所有rt的单位统一改为使用`ns`来统计,精准捕获你的方法耗时,让0ms这样无意义的统计数据不再出现! + +``` +$ tt -l + INDEX TIMESTAMP COST(ms) IS-RET IS-EXP OBJECT CLASS METHOD +------------------------------------------------------------------------------------------------------------------------------------------------------------ + 1000 2017-02-24 10:56:46 808.743525 true false 0x3bd5e918 TestTraceServlet doGet + 1001 2017-02-24 10:56:55 805.799155 true false 0x3bd5e918 TestTraceServlet doGet + 1002 2017-02-24 10:57:04 808.026935 true false 0x3bd5e918 TestTraceServlet doGet + 1003 2017-02-24 10:57:22 805.036963 true false 0x3bd5e918 TestTraceServlet doGet + 1004 2017-02-24 10:57:24 803.581886 true false 0x3bd5e918 TestTraceServlet doGet + 1005 2017-02-24 10:57:39 814.657657 true false 0x3bd5e918 TestTraceServlet doGet +``` + +### watch/stack/trace命令支持按耗时过滤 + +我们在trace的时候,经常会出现某个方法间隙性的rt飙高,但是我们只想知道rt高的时候,是哪里慢了,对于正常rt的方法我们并不关心,Arthas 3.0支持了按`#cost`(方法执行耗时,单位为`ms`)进行过滤,只输出符合条件的trace路径。 + +具体用法为: + +``` +trace/watch/stack class_name method cost_expression +``` + +例如: + +``` +$ trace test.arthas.TestTraceServlet doGet #cost>800 +Press Ctrl+C to abort. +Affect(class-cnt:1 , method-cnt:1) cost in 137 ms. +trace test.arthas.TestTraceServlet doGet #cost>800 +`---thread_name=http-bio-8080-exec-9;id=6e;is_daemon=true;priority=5;TCCL=org.apache.catalina.loader.WebappClassLoader + `---[816.880001ms] test.arthas.TestTraceServlet:doGet() + +---[min=0.019223ms,max=1.192115ms,total=1.211338ms,count=2] java.lang.System:currentTimeMillis() + +---[1.407006ms] test.arthas.TestTraceServlet:call1() + +---[381.970892ms] test.arthas.TestTraceServlet:callhsfL1() + +---[0.018866ms] test.arthas.TestPathTrace:() + +---[375.753301ms] test.arthas.TestPathTrace:callPathTrace() + +---[12.352252ms] test.arthas.TestTraceServlet:call3() + +---[2.758025ms] test.arthas.TestTraceServlet:call4() + +---[1.246057ms] test.arthas.TestTraceServlet:call5() + +---[10.306568ms] test.arthas.TestTraceServlet:call6() + +---[8.891933ms] test.arthas.TestTraceServlet:call7() + +---[4.030325ms] test.arthas.TestTraceServlet:call8() + +---[6.51316ms] test.arthas.TestTraceServlet:call9() + +---[0.059405ms] javax.servlet.http.HttpServletResponse:getWriter() + +---[0.013107ms] java.lang.StringBuilder:() + +---[min=0.004892ms,max=0.06357ms,total=0.100672ms,count=3] java.lang.StringBuilder:append() + +---[0.018255ms] java.lang.StringBuilder:toString() + `---[0.028812ms] java.io.PrintWriter:write() +``` + +上述命令只有当`test.arthas.TestTraceServlet#doGet`方法执行耗时大于800ms时才会输出。 + +### trace命令优化 + +#### 自动高亮显示最耗时方法调用 + +trace命令现在会自动显示 + +![image](TODO/image.png) + + +#### 带条件过滤的多级trace + +目前trace默认只输出一级方法调用耗时,有时候并不能完全看出问题。但是如果展开多级的话,每一个方法的耗时都统计,会造成方法数量迅速膨胀,大大增加trace的开销。 + +TODO + +#### 显示当前线程的信息及eagleeye的traceId + +``` +trace test.arthas.TestTraceServlet doGet +`---thread_name=http-bio-8080-exec-10;id=da;is_daemon=true;priority=5;TCCL=org.apache.catalina.loader.WebappClassLoader;trace_id=1e09489014879085429791006d969d +``` + + +### sysprop命令操作SystemProperty + +sysprop命令支持查看所有的系统属性,以及针对特定属性进行查看和修改。 + +``` +$ sysprop +... + os.arch x86_64 + java.ext.dirs /Users/wangtao/Library/Java/Extensions:/Library/Java/JavaVirtualMachines/jdk1. + 8.0_51.jdk/Contents/Home/jre/lib/ext:/Library/Java/Extensions:/Network/Library + /Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java + user.dir /Users/wangtao/work/ali-tomcat-home/ant-develop/output/build + catalina.vendor alibaba + line.separator + + java.vm.name Java HotSpot(TM) 64-Bit Server VM + file.encoding UTF-8 + org.apache.tomcat.util.http.ServerCookie.ALLOW_EQUA true + LS_IN_VALUE + com.taobao.tomcat.info Apache Tomcat/7.0.70.1548 + java.specification.version 1.8 +$ sysprop java.version +java.version=1.8.0_51 +$ sysprop production.mode true +Successfully changed the system property. +production.mode=true +``` + +### thread命令支持指定采样时间 + +thread命令计算线程cpu占用的逻辑,默认是采样100ms内各个线程的cpu使用情况并计算cpu消耗占比。有时候100ms的时间间隔太短,看不出问题所在,Arthas3.0中thread命令支持设置采样间隔(以`ms`为单位),可以观察任意时间段内的cpu消耗占比情况。 + +``` +$ thread -i 1000 +Threads Total: 74, NEW: 0, RUNNABLE: 17, BLOCKED: 0, WAITING: 15, TIMED_WAITING: 42, TERMINATED: 0 +ID NAME GROUP PRIORITY STATE %CPU TIME INTERRUPTED DAEMON +78 com.taobao.config.client.timer main 5 TIMED_WAITING 22 0:0 false true +92 Abandoned connection cleanup thread main 5 TIMED_WAITING 15 0:2 false true +361 as-command-execute-daemon system 10 RUNNABLE 14 0:0 false true +67 HSF-Remoting-Timer-10-thread-1 main 10 TIMED_WAITING 12 0:2 false true +113 JamScheduleThread system 9 TIMED_WAITING 2 0:0 false true +14 Thread-3 main 5 RUNNABLE 2 0:0 false false +81 com.taobao.remoting.TimerThread main 5 TIMED_WAITING 2 0:0 false true +104 http-bio-7001-AsyncTimeout main 5 TIMED_WAITING 2 0:0 false true +123 nioEventLoopGroup-2-1 system 10 RUNNABLE 2 0:0 false false +127 nioEventLoopGroup-3-2 system 10 RUNNABLE 2 0:0 false false +345 nioEventLoopGroup-3-3 system 10 RUNNABLE 2 0:0 false false +358 nioEventLoopGroup-3-4 system 10 RUNNABLE 2 0:0 false false +27 qos-boss-1-1 main 5 RUNNABLE 2 0:0 false true +22 EagleEye-AsyncAppender-Thread-BizLog main 5 TIMED_WAITING 1 0:0 false true +``` \ No newline at end of file diff --git a/_sources/async.md.txt b/_sources/async.md.txt new file mode 100644 index 000000000..92e971c7d --- /dev/null +++ b/_sources/async.md.txt @@ -0,0 +1,65 @@ +Arthas异步调用 +=== +arthas中的异步调用,使用了仿linux系统任务相关的命令。[linux任务相关介绍](https://ehlxr.me/2017/01/18/Linux-%E4%B8%AD-fg%E3%80%81bg%E3%80%81jobs%E3%80%81-%E6%8C%87%E4%BB%A4/)。 + + +## 1. 使用&在后台执行任务 +比如希望执行后台执行trace命令,那么调用下面命令 + +```sh +trace Test t & +``` +这时命令在后台执行,可以在console中继续执行其他命令。 + +## 2. 通过jobs查看任务 +如果希望查看当前有哪些arthas任务在执行,可以执行jobs命令,执行结果如下 +```sh +$ jobs +[10]* + Stopped watch com.taobao.container.Test test "params[0].{? #this.name == null }" -x 2 + execution count : 19 + start time : Fri Sep 22 09:59:55 CST 2017 + timeout date : Sat Sep 23 09:59:55 CST 2017 + session : 3648e874-5e69-473f-9eed-7f89660b079b (current) +``` +可以看到目前有一个后台任务在执行。 +* job id是10, `*` 表示此job是当前session创建 +* 状态是Stopped +* execution count是执行次数,从启动开始已经执行了19次 +* timeout date是超时的时间,到这个时间,任务将会自动超时退出 + +## 3. 任务暂停和取消 +当任务正在前台执行,比如直接调用命令`trace Test t`或者调用后台执行命令`trace Test t &`后又通过`fg`命令将任务转到前台。这时console中无法继续执行命令,但是可以接收并处理以下事件: + +* ‘ctrl + z’:将任务暂停。通过`jbos`查看任务状态将会变为Stopped,通过`bg `或者`fg `可让任务重新开始执行 +* ‘ctrl + c’:停止任务 +* ‘ctrl + d’:按照linux语义应当是退出终端,目前arthas中是空实现,不处理 + +## 4. fg、bg命令,将命令转到前台、后台继续执行 +* 任务在后台执行或者暂停状态(‘ctrl + z’暂停任务)时,执行fg 将可以把对应的任务转到前台继续执行。在前台执行时,无法在console中执行其他命令 +* 当任务处于暂停状态时(‘ctrl + z’暂停任务),执行bg 将可以把对应的任务在后台继续执行 +* 非当前session创建的job,只能由当前session fg到前台执行 + +## 5. 任务输出重定向 +可通过`>`或者`>>`将任务输出结果输出到指定的文件中,可以和`&`一起使用,实现arthas命令的异步调用。比如: + +```sh +$ trace Test t >> test.out & +``` +这时trace命令会在后台执行,并且把结果输出到~/logs/arthas-cache/test.out。可继续执行其他命令。并可查看文件中的命令执行结果。 + +当远程调用时,可能无法确定机器文件路径,arthas同时支持了自动重定向到缓存路径。使用方法如下: +```sh +$ trace Test t >> & +job id : 2 +cache location : /Users/gehui/logs/arthas-cache/28198/2 +``` +可以看到并没有指定重定向文件位置,arthas自动重定向到缓存中了,执行命令后会输出job id和cache location。cache location就是重定向文件的路径,在系统logs目录下,路径包括pid和job id,避免和其他任务冲突。命令输出结果到`/Users/gehui/logs/arthas-cache/28198/2`中,job id为2。 + +## 6. 停止命令 +异步执行的命令,如果希望停止,可执行kill + +## 7. 其他 + +* 最多同时支持8个命令使用重定向将结果写日志 +* 请勿同时开启过多的后台异步命令,以免对目标JVM性能造成影响 \ No newline at end of file diff --git a/_sources/auto_structify.md.txt b/_sources/auto_structify.md.txt new file mode 100644 index 000000000..676a02836 --- /dev/null +++ b/_sources/auto_structify.md.txt @@ -0,0 +1,245 @@ +AutoStructify Component +======================= +AutoStructify is a component in recommonmark that takes a parsed docutil AST by `CommonMarkParser`, +and transform it to another AST that introduces some of more. This enables additional features +of recommonmark syntax, to introduce more structure into the final generated document. + + +Configuring AutoStructify +------------------------- +The behavior of AutoStructify can be configured via a dict in document setting. +In sphinx, you can configure it by `conf.py`. The following snippet +is what is actually used to generate this document, see full code at [conf.py](conf.py). + +```python +github_doc_root = 'https://github.com/rtfd/recommonmark/tree/master/doc/' +def setup(app): + app.add_config_value('recommonmark_config', { + 'url_resolver': lambda url: github_doc_root + url, + 'auto_toc_tree_section': 'Contents', + }, True) + app.add_transform(AutoStructify) + +``` +All the features are by default enabled + +***List of options*** +* __enable_auto_toc_tree__: whether enable [Auto Toc Tree](#auto-toc-tree) feature. +* __auto_toc_tree_section__: when enabled, [Auto Toc Tree](#auto-toc-tree) will only be enabled on section that matches the title. +* __enable_auto_doc_ref__: whether enable [Auto Doc Ref](#auto-doc-ref) feature. **Deprecated** +* __enable_math__: whether enable [Math Formula](#math-formula) +* __enable_inline_math__: whether enable [Inline Math](#inline-math) +* __enable_eval_rst__: whether [Embed reStructuredText](#embed-restructuredtext) is enabled. +* __url_resolver__: a function that maps a existing relative position in the document to a http link + +Auto Toc Tree +------------- +One of important command in tools like sphinx is `toctree`. This is a command to generate table of contents and +tell sphinx about the structure of the documents. In markdown, usually we manually list of contents by a bullet list +of url reference to the other documents. + +AutoStructify will transforms bullet list of document URLs + +``` +* [Title1](doc1.md) +* [Title2](doc2.md) +``` +will be translated to the AST of following reStructuredText code +```rst +.. toctree:: + :maxdepth: 1 + + doc1 + doc2 +``` +You can also find the usage of this feature in `index.md` of this document. + +Auto Doc Ref +------------ + +```eval_rst +.. note:: **This option is deprecated.** + This option has been superseded by the default linking behavior, which + will first try to resolve as an internal reference, and then as an + external reference. +``` + +It is common to refer to another document page in one document. We usually use reference to do that. +AutoStructify will translate these reference block into a structured document reference. For example +``` +[API Reference](api_ref.md) +``` +will be translated to the AST of following reStructuredText code +``` +:doc:`API Reference ` +``` +And it will be rendered as [API Reference](api_ref) + +URL Resolver +------------ +Sometimes in a markdown, we want to refer to the code in the same repo. +This can usually be done by a reference by reference path. However, since the generated document is hosted elsewhere, +the relative path may not work in generated document site. URL resolver is introduced to solve this problem. + +Basically, you can define a function that maps an relative path of document to the http path that you wish to link to. +For example, the setting mentioned in the beginning of this document used a resolver that maps the files to github. +So `[parser code](../recommonmark/parser.py)` will be translated into [parser code](../recommonmark/parser.py) + +Note that the reference to the internal document will not be passed to url resolver, and will be linked to the internal document pages correctly, see [Auto Doc Ref](#auto-doc-ref). + + +Codeblock Extensions +-------------------- +In markdown, you can write codeblocks fenced by (at least) three backticks +(```` ``` ````). The following is an example of codeblock. + +```` +``` language +some code block +``` +```` + +Codeblock extensions are mechanism that specialize certain codeblocks to different render behaviors. +The extension will be trigger by the language argument to the codeblck + +### Syntax Highlight +You can highlight syntax of codeblocks by specifying the language you need. For example, + +```` +```python +def function(): + return True +``` +```` + +will be rendered as + +```python +def function(): + return True +``` + +### Math Formula +You can normally write latex math formula with `math` codeblock. See also [Inline Math](#inline-math). + +Example + +```` +```math +E = m c^2 +``` +```` + +will be rendered as + +```math +E = m c^2 +``` + +### Embed reStructuredText +Recommonmark also allows embedding reStructuredText syntax in the codeblocks. +There are two styles for embedding reStructuredText. The first is enabled by `eval_rst` codeblock. The content of codeblock will be parsed as reStructuredText and insert into the document. This can be used to quickly introduce some of reStructuredText command that not yet available in markdown. For example, + +```` +```eval_rst +.. autoclass:: recommonmark.transform.AutoStructify + :show-inheritance: +``` +```` + +will be rendered as + +```eval_rst +.. autoclass:: recommonmark.transform.AutoStructify + :show-inheritance: +``` + +This example used to use sphinx autodoc to insert document of AutoStructify class definition into the document. + +The second style is a shorthand of the above style. It allows you to leave off the eval_rst .. portion and directly render directives. For example, + +````rst +``` important:: Its a note! in markdown! +``` +```` + +will be rendered as + +``` important:: Its a note! in markdown! +``` + +#### An Advanced Example + +````rst +``` sidebar:: Line numbers and highlights + + emphasis-lines: + highlights the lines. + linenos: + shows the line numbers as well. + caption: + shown at the top of the code block. + name: + may be referenced with `:ref:` later. +``` + +``` code-block:: markdown + :linenos: + :emphasize-lines: 3,5 + :caption: An example code-block with everything turned on. + :name: Full code-block example + + # Comment line + import System + System.run_emphasis_line + # Long lines in code blocks create a auto horizontal scrollbar + System.exit! +``` +```` + +will be rendered as + +``` sidebar:: Line numbers and highlights + + emphasis-lines: + highlights the lines. + linenos: + shows the line numbers as well. + caption: + shown at the top of the code block. + name: + may be referenced with `:ref:` later. +``` + +``` code-block:: markdown + :linenos: + :emphasize-lines: 3,5 + :caption: An example code-block with everything turned on. + :name: Full code-block example + + # Comment line + import System + System.run_emphasis_line + # Long lines in code blocks create a auto horizontal scrollbar + System.exit! +``` + +The `

` line clears the sidebar for the next title. + +
+ + +Inline Math +----------- +Besides the [Math Formula](#math-formula), you can also write latex math in inline codeblock text. You can do so by inserting `$` +in the beginning and end of inline codeblock. + +Example + +``` +This formula `$ y=\sum_{i=1}^n g(x_i) $` +``` + +will be rendered as: + +This formula `$ y=\sum_{i=1}^n g(x_i) $` diff --git a/_sources/batch-support.md.txt b/_sources/batch-support.md.txt new file mode 100644 index 000000000..5d17473fb --- /dev/null +++ b/_sources/batch-support.md.txt @@ -0,0 +1,39 @@ +批处理功能 +=== + +> 通过批处理功能,arthas支持一次性批量运行多个命令,并取得命令执行的结果。 + +### 使用方法 + +#### 第一步: 创建你的批处理脚本 + +这里我们新建了一个`test.as`脚本,为了规范,我们采用了.as后缀名,但事实上任意的本文文件都ok。 + +> 注意事项 +> * 目前需要每个命令占一行 +> * dashboard务必开启批处理模式(`-b`),指定执行次数(`-n`),否则会导致批处理脚本无法终止 +> * watch/tt/trace/monitor/stack等命令务必指定执行次数(`-n`),否则会导致批处理脚本无法终止 +> * 可以使用异步后台任务,如 `watch c.t.X test returnObj > &`,让命令一直在后台运行,通过日志获取结果,[获取更多异步任务的信息](async.md) + +``` +➜ arthas git:(develop) cat /var/tmp/test.as +help +dashboard -b -n 1 +session +thread +sc -d org.apache.commons.lang.StringUtils +``` + +#### 第二步: 运行你的批处理脚本 + +通过`-b`开启批处理模式, `-f`执行脚本文件, 批处理脚本默认会输出到标准输出中,可以将结果重定向到文件中。 + +```sh +./as.sh -b -f /var/tmp/test.as 56328 > test.out +``` + +#### 第三步: 查看运行结果 + +```sh +cat test.out +``` \ No newline at end of file diff --git a/_sources/classloader.md.txt b/_sources/classloader.md.txt new file mode 100644 index 000000000..c463c8933 --- /dev/null +++ b/_sources/classloader.md.txt @@ -0,0 +1,131 @@ +classloader +=== + +> 查看classloader的继承树,urls,类加载信息 + +`classloader` 命令将 JVM 中所有的classloader的信息统计出来,并可以展示继承树,urls等。 + +可以让指定的classloader去getResources,打印出所有查找到的resources的url。对于`ResourceNotFoundException`比较有用。 + + +### 参数说明 + +|参数名称|参数说明| +|---:|:---| +|[l]|按类加载实例进行统计| +|[t]|打印所有ClassLoader的继承树| +|[a]|列出所有ClassLoader加载的类,请谨慎使用| +|`[c:]`|ClassLoader的hashcode| +|`[c: r:]`|用ClassLoader去查找resource| +### 使用参考 + +* 按类加载类型查看统计信息 + +```s +$ classloader + name numberOfInstances loadedCountTotal + com.taobao.pandora.service.loader.ModuleClassLoader 29 11659 + com.taobao.pandora.boot.loader.ReLaunchURLClassLoader 1 5308 + BootstrapClassLoader 1 3711 + com.taobao.arthas.agent.ArthasClassloader 2 2825 + sun.reflect.DelegatingClassLoader 332 332 + java.net.URLClassLoader 1 285 + sun.misc.Launcher$AppClassLoader 1 77 + sun.misc.Launcher$ExtClassLoader 1 46 + com.alibaba.fastjson.util.ASMClassLoader 2 3 + org.jvnet.hk2.internal.DelegatingClassLoader 2 2 + sun.reflect.misc.MethodUtil 1 1 +Affect(row-cnt:11) cost in 66 ms. +``` + +* 按类加载实例查看统计信息 + +```sh +$ classloader -l + name loadedCount hash parent + BootstrapClassLoader 3711 null null + com.alibaba.fastjson.util.ASMClassLoader@3bbaa1b8 2 3bbaa1b8 monitor's ModuleClassLoader + com.alibaba.fastjson.util.ASMClassLoader@5e255d0b 1 5e255d0b eagleeye-core's ModuleClassLoader + com.taobao.arthas.agent.ArthasClassloader@4fa2d7e6 1795 4fa2d7e6 sun.misc.Launcher$ExtClassLoader@a38d7a3 + com.taobao.arthas.agent.ArthasClassloader@522400c2 1033 522400c2 sun.misc.Launcher$ExtClassLoader@a38d7a3 + com.taobao.pandora.boot.loader.ReLaunchURLClassLoader@1817d444 5308 1817d444 sun.misc.Launcher$AppClassLoader@14dad5dc + tbsession's ModuleClassLoader 285 609cd4d8 null + pandora-qos-service's ModuleClassLoader 267 2f8dad04 null + pandora-framework's ModuleClassLoader 78 4009e306 null + filesync-client's ModuleClassLoader 4 4b8ee4de null + rocketmq-client's ModuleClassLoader 431 247bddad null + eagleeye-core's ModuleClassLoader 451 1ba9117e null + alimonitor-jmonitor's ModuleClassLoader 134 22fcf7ab null + metaq-client's ModuleClassLoader 35 41a2befb null + hsf-mock's ModuleClassLoader 3 2002fc1d null + monitor's ModuleClassLoader 1427 131ef10 null + spas-sdk-service's ModuleClassLoader 7 10d307f1 null + vipserver-client's ModuleClassLoader 137 7a419da4 null + metrics's ModuleClassLoader 146 696da30b null + mtop-uncenter's ModuleClassLoader 922 79d8407f null + spas-sdk-client's ModuleClassLoader 235 4944252c null + live-profiler-pandora's ModuleClassLoader 1 6913c1fb null + notify-tr-client's ModuleClassLoader 472 fba92d3 null + ons-sdk's ModuleClassLoader 70 23348b5d null + tair-plugin's ModuleClassLoader 1053 7c9d8e2 null + tddl-client's ModuleClassLoader 2354 4988d8b8 null + config-client's ModuleClassLoader 93 429bffaa null + diamond-client's ModuleClassLoader 360 3d5c822d null + pandolet's ModuleClassLoader 99 41e1e210 null + hsf's ModuleClassLoader 1796 3232a28a null + acl.plugin's ModuleClassLoader 379 67080771 null + buc.sso.client.plugin's ModuleClassLoader 195 13b6aecc null + unitrouter's ModuleClassLoader 64 7e5afaa6 null + switch's ModuleClassLoader 104 24313fcc null + hsf-notify-client's ModuleClassLoader 57 4d0f2471 null + java.net.URLClassLoader@7ec7ffd3 285 7ec7ffd3 sun.misc.Launcher$ExtClassLoader@a38d7a3 + javax.management.remote.rmi.NoCallStackClassLoader@53f65459 1 53f65459 null + javax.management.remote.rmi.NoCallStackClassLoader@2833cc44 1 2833cc44 null + org.jvnet.hk2.internal.DelegatingClassLoader@72cda8ee 1 72cda8ee monitor's ModuleClassLoader + org.jvnet.hk2.internal.DelegatingClassLoader@1f57f96d 1 1f57f96d monitor's ModuleClassLoader + sun.misc.Launcher$AppClassLoader@14dad5dc 77 14dad5dc sun.misc.Launcher$ExtClassLoader@a38d7a3 + sun.misc.Launcher$ExtClassLoader@a38d7a3 46 a38d7a3 null + sun.reflect.misc.MethodUtil@1201f221 1 1201f221 sun.misc.Launcher$AppClassLoader@14dad5dc +``` + +* 查看ClassLoader的继承树 + +```shell +$ classloader -t ++-BootstrapClassLoader ++-unitrouter's ModuleClassLoader ++-diamond-client's ModuleClassLoader ++-sun.misc.Launcher$ExtClassLoader@548a102f +| +-sun.misc.Launcher$AppClassLoader@14dad5dc +| +-com.taobao.arthas.agent.AgentLauncher$1@334e6bb8 +| | +-sun.reflect.DelegatingClassLoader@328b3a05 +| | +-sun.reflect.DelegatingClassLoader@73f44f24 +``` + +* 查看URLClassLoader实际的urls + +```shell +$ classloader -c 5ffe9775 +file:/Users/hello/soft/taobao-tomcat-7.0.64/deploy/taobao-hsf.sar/lib/commons-lang-2.6.jar +file:/Users/hello/soft/taobao-tomcat-7.0.64/deploy/taobao-hsf.sar/lib/log4j-1.2.16.jar +file:/Users/hello/soft/taobao-tomcat-7.0.64/deploy/taobao-hsf.sar/lib/logger.api-0.1.4.jar +file:/Users/hello/soft/taobao-tomcat-7.0.64/deploy/taobao-hsf.sar/lib/pandora.api-2.0.7-SNAPSHOT.jar +file:/Users/hello/soft/taobao-tomcat-7.0.64/deploy/taobao-hsf.sar/lib/pandora.container-2.0.7-SNAPSHOT.jar +file:/Users/hello/soft/taobao-tomcat-7.0.64/deploy/taobao-hsf.sar/lib/pandora.thirdcontainer-2.0.7-SNAPSHOT.jar +file:/Users/hello/soft/taobao-tomcat-7.0.64/deploy/taobao-hsf.sar/lib/picocontainer-2.14.3.jar +``` + +* 使用ClassLoader去查找resource + +```shell +$ classloader -c 226b143b -r META-INF/MANIFEST.MF + jar:file:/Users/hello/.m2/repository/javax/enterprise/cdi-api/1.0/cdi-api-1.0.jar!/META-INF/MANIFEST.MF + jar:file:/Users/hello/.m2/repository/javax/annotation/jsr250-api/1.0/jsr250-api-1.0.jar!/META-INF/MANIFEST.MF +``` + +也可以尝试查找类的class文件: + +```shell +$ classloader -c 1b6d3586 -r java/lang/String.class + jar:file:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/rt.jar!/java/lang/String.class +``` \ No newline at end of file diff --git a/_sources/commands.md.txt b/_sources/commands.md.txt new file mode 100644 index 000000000..012b65902 --- /dev/null +++ b/_sources/commands.md.txt @@ -0,0 +1,37 @@ +命令列表 +============= + +* [dashboard](dashboard.md) +* [thread](thread.md) +* [jvm](jvm.md) +* [sysprop](sysprop.md) +* [getstatic](getstatic.md) + + + +* [sc](sc.md) +* [sm](sm.md) +* [dump](dump.md) + +* [jad](jad.md) +* [classloader](classloader.md) +* [redefine](redefine.md) + +* [monitor](monitor.md) +* [watch](watch.md) +* [trace](trace.md) +* [stack](stack.md) +* [tt](tt.md) + +* [options](options.md) + +### Arthas 基础命令 + +* help——查看命令帮助信息 +* cls——清空当前屏幕区域 +* session——查看当前会话的信息 +* [reset](reset.md)——重置增强类,将被 Arthas 增强过的类全部还原,Arthas 服务端关闭时会重置所有增强过的类 +* version——输出当前目标 Java 进程所加载的 Arthas 版本号 +* quit——退出当前 Arthas 客户端,其他 Arthas 客户端不受影响 +* shutdown——关闭 Arthas 服务端,所有 Arthas 客户端全部退出 +* [keymap](keymap.md)——Arthas快捷键列表及自定义快捷键 \ No newline at end of file diff --git a/_sources/dashboard.md.txt b/_sources/dashboard.md.txt new file mode 100644 index 000000000..19b88575c --- /dev/null +++ b/_sources/dashboard.md.txt @@ -0,0 +1,61 @@ +dashboard +=== + +> 当前系统的实时数据面板,按 ctrl+c 退出。 + +当运行在Ali-tomcat时,会显示当前tomcat的实时信息,如HTTP请求的qps, rt, 错误数, 线程池信息等等。 + +### 使用参考 + +``` +$ dashboard +ID NAME GROUP PRIORITY STATE %CPU TIME INTERRUPTED DAEMON +889 RMI TCP Connection(15)-30.10.166. RMI Runtime 9 RUNNABLE 48 0:5 false true +1077 Timer-for-arthas-dashboard-0 system 9 RUNNABLE 24 0:0 false true +1074 as-selector-daemon system 9 RUNNABLE 12 0:0 false true +284 JMX server connection timeout 284 RMI Runtime 9 TIMED_WAITI 8 0:3 false true +16 Timer-1 main 5 TIMED_WAITI 5 0:9 false true +47 Pandora pandora-qos-reporter Pool main 5 TIMED_WAITI 0 0:0 false true +48 JmonitorClient-CheckThread Pool [ main 5 TIMED_WAITI 0 0:0 false true +49 JmonitorClient-HeartBeat Pool [Th main 5 TIMED_WAITI 0 0:0 false true +50 JmonitorClient-ReaderThread Pool main 5 TIMED_WAITI 0 0:0 false true +957 RMI TCP Connection(16)-30.10.166. RMI Runtime 9 RUNNABLE 0 0:2 false true +51 JmonitorClient-WriterThread Pool main 5 TIMED_WAITI 0 0:0 false true +52 ContainerBackgroundProcessor[Stan main 5 TIMED_WAITI 0 0:0 false true +53 http-bio-8080-Acceptor-0 main 5 RUNNABLE 0 0:2 false true +54 http-bio-8080-AsyncTimeout main 5 TIMED_WAITI 0 0:0 false true +11 GC Daemon system 2 TIMED_WAITI 0 0:0 false true +Memory used total max usage GC +heap 59M 223M 1820M 3.26% gc.ps_scavenge.count 118 +ps_eden_space 14M 114M 668M 2.11% gc.ps_scavenge.time(ms) 1890 +ps_survivor_space 6M 6M 6M 96.08% gc.ps_marksweep.count 5 +ps_old_gen 39M 103M 1365M 2.86% gc.ps_marksweep.time(ms) 1140 +nonheap 234M 240M 0M 97.46% +code_cache 46M 47M 240M 19.49% +metaspace 167M 172M 0M 97.36% +Runtime Tomcat +os.name Mac OS X connector http-bio-8080 +os.version 10.10.5 QPS 0.00 +java.version 1.8.0_60 RT(ms) 1.13 +java.home error/s 0.00 + received/s 0B +systemload.average 3.44 sent/s 0B +processors 4 threadpool http-bio-8080 +uptime 16020s busy 0 +``` + +### 数据说明 + +* ID: Java级别的线程ID,注意这个ID不能跟jstack中的nativeID一一对应 +* NAME: 线程名 +* GROUP: 线程组名 +* PRIORITY: 线程优先级, 1~10之间的数字,越大表示优先级越高 +* STATE: 线程的状态 +* CPU%: 线程消耗的cpu占比,采样100ms,将所有线程在这100ms内的cpu使用量求和,再算出每个线程的cpu使用占比。 +* TIME: 线程运行总时间,数据格式为`分:秒` +* INTERRUPTE: 线程当前的中断位状态 +* DAEMON: 是否是daemon线程 + +### 截图展示 + +![alt text](files/dashboard.png "dashboard") diff --git a/_sources/dump.md.txt b/_sources/dump.md.txt new file mode 100644 index 000000000..cc42a375d --- /dev/null +++ b/_sources/dump.md.txt @@ -0,0 +1,40 @@ +dump +=== + +> dump 已加载类的 bytecode 到特定目录 + +### 参数说明 + +|参数名称|参数说明| +|---:|:---| +|*class-pattern*|类名表达式匹配| +|`[c:]`|类所属 ClassLoader 的 hashcode| +|[E]|开启正则表达式匹配,默认为通配符匹配| + +### 使用参考 + +```shell +$ dump -E org\.apache\.commons\.lang\.StringUtils + HASHCODE CLASSLOADER LOCATION + 29505d69 +-tddl-client's ModuleClassLoader /Users/zhuyong/middleware/taobao-tomcat/output/build/bin/classdump/com.taobao.pandora + .service.loader.ModuleClassLoader-29505d69/org.apache.commons.lang.StringUtils.class + 6e51ad67 +-java.net.URLClassLoader@6e51ad67 /Users/zhuyong/middleware/taobao-tomcat/output/build/bin/classdump/java.net.URLClassL + +-sun.misc.Launcher$AppClassLoader@6951a712 oader-6e51ad67/org.apache.commons.lang.StringUtils.class + +-sun.misc.Launcher$ExtClassLoader@6fafc4c2 + 2bdd9114 +-pandora-qos-service's ModuleClassLoader /Users/zhuyong/middleware/taobao-tomcat/output/build/bin/classdump/com.taobao.pandora + .service.loader.ModuleClassLoader-2bdd9114/org.apache.commons.lang.StringUtils.class + 544dc9ba +-com.taobao.tomcat.container.context.loader.AliWebappClassLoader /Users/zhuyong/middleware/taobao-tomcat/output/build/bin/classdump/com.taobao.tomcat. + +-org.apache.catalina.loader.StandardClassLoader@2302e984 container.context.loader.AliWebappClassLoader-544dc9ba/org.apache.commons.lang.String + +-sun.misc.Launcher$AppClassLoader@6951a712 Utils.class + +-sun.misc.Launcher$ExtClassLoader@6fafc4c2 + 22880c2b +-java.net.URLClassLoader@22880c2b /Users/zhuyong/middleware/taobao-tomcat/output/build/bin/classdump/java.net.URLClassL + +-sun.misc.Launcher$AppClassLoader@6951a712 oader-22880c2b/org.apache.commons.lang.StringUtils.class + +-sun.misc.Launcher$ExtClassLoader@6fafc4c2 +Affect(row-cnt:5) cost in 156 ms. +$ dump -E org\.apache\.commons\.lang\.StringUtils -c 22880c2b + HASHCODE CLASSLOADER LOCATION + 22880c2b +-java.net.URLClassLoader@22880c2b /Users/zhuyong/middleware/taobao-tomcat/output/build/bin/classdump/java.net.URLClassLoader-22880c2b/org + +-sun.misc.Launcher$AppClassLoader@6951a712 .apache.commons.lang.StringUtils.class + +-sun.misc.Launcher$ExtClassLoader@6fafc4c2 +Affect(row-cnt:1) cost in 67 ms. +``` \ No newline at end of file diff --git a/_sources/getstatic.md.txt b/_sources/getstatic.md.txt new file mode 100644 index 000000000..d9a9ef94a --- /dev/null +++ b/_sources/getstatic.md.txt @@ -0,0 +1,25 @@ +getstatic +=== + +通过getstatic命令可以方便的查看类的静态属性。使用方法为`getstatic class_name field_name` + + +如果该静态属性是一个复杂对象,还可以支持在该属性上通过ognl表示进行遍历,过滤,访问对象的内部属性等操作。 + +例如,假设n是一个Map,Map的Key是一个Enum,我们想过滤出Map中Key为某个Enum的值,可以写如下命令 + +``` +$ getstatic com.alibaba.arthas.Test n 'entrySet().iterator.{? #this.key.name()=="STOP"}' +field: n +@ArrayList[ + @Node[STOP=bbb], +] +Affect(row-cnt:1) cost in 68 ms. + + +$ getstatic com.alibaba.arthas.Test m 'entrySet().iterator.{? #this.key=="a"}' +field: m +@ArrayList[ + @Node[a=aaa], +] +``` \ No newline at end of file diff --git a/_sources/groovy.md.txt b/_sources/groovy.md.txt new file mode 100644 index 000000000..3ab816b70 --- /dev/null +++ b/_sources/groovy.md.txt @@ -0,0 +1,170 @@ +groovy +=== + +> Arthas 支持 groovy 脚本增强,允许像 BTrace 一样编写脚本来解决问题,可以在 groovy 脚本中进行if/for/switch/while 等控制语句,不受限制,但相比 BTrace 而言拥有更多的限制范围。 + +### 限制内容 + +1. 禁止改变原有逻辑,与 watch 等命令一样,重点保证的是监听和观察。 +1. 只允许在方法的 before/success/exception/finish 四个环节进行监听。 + +### 参数说明 + +|参数名称|参数说明| +|---:|:---| +|*class-pattern*|类名表达式匹配| +|*method-pattern*|方法名表达式匹配| +|*script-filepath*|groovy 脚本的绝对路径| +|[S]|匹配所有的子类| +|[E]|开启正则表达式匹配,默认为通配符匹配| + +* 需要说明的是,第三个输入参数是脚本的绝对路径,比如 `/tmp/test.js`,不建议输入相对路径,比如 `./test.js` + +### 五个关键函数声明 + +```java +/** + * 增强脚本监听器 + */ +interface ScriptListener { + + /** + * 脚本创建 + * + * @param output 输出器 + */ + void create(Output output); + + /** + * 脚本销毁 + * + * @param output 输出器 + */ + void destroy(Output output); + + /** + * 方法执行前 + * + * @param output 输出器 + * @param advice 通知点 + */ + void before(Output output, Advice advice); + + /** + * 方法正常返回 + * + * @param output 输出器 + * @param advice 通知点 + */ + void afterReturning(Output output, Advice advice); + + /** + * 方法异常返回 + * + * @param output 输出器 + * @param advice 通知点 + */ + void afterThrowing(Output output, Advice advice); + +} +``` + +### 参数 `Advice` 说明 + +`Advice` 参数最主要是封装了通知节点的所有信息。参考[表达式核心变量](advice-class.md)中关于该节点的描述。 + +### 参数 `Output` 说明 + +`Output` 参数只拥有三个方法,主要的工作还是输出对应的文本信息 + +```java +/** + * 输出器 + */ +interface Output { + + /** + * 输出字符串(不换行) + * + * @param string 待输出字符串 + * @return this + */ + Output print(String string); + + /** + * 输出字符串(换行) + * + * @param string 待输出字符串 + * @return this + */ + Output println(String string); + + /** + * 结束当前脚本 + * + * @return this + */ + Output finish(); + +} +``` + +### 一个输出日志的 groovy 脚本示例 + +```groovy +import com.taobao.arthas.core.command.ScriptSupportCommand +import com.taobao.arthas.core.util.Advice + +import static java.lang.String.format + +/** + * 输出方法日志 + */ +public class Logger implements ScriptSupportCommand.ScriptListener { + + @Override + void create(ScriptSupportCommand.Output output) { + output.println("script create."); + } + + @Override + void destroy(ScriptSupportCommand.Output output) { + output.println("script destroy."); + } + + @Override + void before(ScriptSupportCommand.Output output, Advice advice) { + output.println(format("before:class=%s;method=%s;paramslen=%d;%s;", + advice.getClazz().getSimpleName(), + advice.getMethod().getName(), + advice.getParams().length, advice.getParams())) + } + + @Override + void afterReturning(ScriptSupportCommand.Output output, Advice advice) { + output.println(format("returning:class=%s;method=%s;", + advice.getClazz().getSimpleName(), + advice.getMethod().getName())) + } + + @Override + void afterThrowing(ScriptSupportCommand.Output output, Advice advice) { + output.println(format("throwing:class=%s;method=%s;", + advice.getClazz().getSimpleName(), + advice.getMethod().getName())) + } +} +``` + +使用示例: + +``` +$ groovy com.alibaba.sample.petstore.dal.dao.ProductDao getProductById /Users/zhuyong/middleware/arthas/scripts/Logger.groovy -S +script create. +Press Ctrl+C to abort. +Affect(class-cnt:1 , method-cnt:1) cost in 102 ms. +before:class=IbatisProductDao;method=getProductById;paramslen=1;[Ljava.lang.Object;@45df64fc; +returning:class=IbatisProductDao;method=getProductById; +before:class=IbatisProductDao;method=getProductById;paramslen=1;[Ljava.lang.Object;@5b0e2d00; +returning:class=IbatisProductDao;method=getProductById; +``` \ No newline at end of file diff --git a/_sources/index.md.txt b/_sources/index.md.txt index 0e095ddf6..020ca8375 100644 --- a/_sources/index.md.txt +++ b/_sources/index.md.txt @@ -1,2 +1,32 @@ -# Arthas +Arthas 用户文档 +=== + +## Arthas(阿尔萨斯) 能为你做什么? + +当你遇到以下类似问题而束手无策时,你看到了这篇文档,看到了 `Arthas`,那么恭喜你,你朝正确的方向又迈了一大步。 + +0. 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception? +0. 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了? +0. 遇到问题无法在预发 debug 一下,难道只能通过加日志再重新预发布吗? +0. 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现! +0. 是否有一个全局视角来查看系统的运行状况? +0. 有什么办法可以监控到容器和中间件(AliTomcat、HSF、Notify 等)的实时运行状态? + +`Arthas` 是全新的在线诊断工具,采用命令行交互模式,支持web端在线诊断,同时提供丰富的 `Tab` 自动补全功能,进一步方便进行问题的定位和诊断。 + + +Contents +-------- + +* [安装](install-detail.md) +* [快速入门](quick-start.md) +* [进阶使用](advanced-use.md) +* [命令列表](commands.md) +* [用户案例](https://github.com/alibaba/arthas/labels/user-case) +* [Release Notes](release-notes.md) +* [Questions and answers](https://github.com/alibaba/arthas/labels/question-answered) +* [Fork me at GitHub](https://github.com/alibaba/arthas) +* [参与贡献](https://github.com/alibaba/arthas/CONTRIBUTING.md) + + diff --git a/_sources/install-detail.md.txt b/_sources/install-detail.md.txt new file mode 100644 index 000000000..665b60fd8 --- /dev/null +++ b/_sources/install-detail.md.txt @@ -0,0 +1,38 @@ +Arthas Install +============= + + +## Linux/Unix/Mac + +Arthas 支持在 Linux/Unix/Mac 等平台上一键安装,请复制以下内容,并粘贴到命令行中,敲 `回车` 执行即可: + +```bash +curl -L https://alibaba.github.io/arthas/install.sh | sh +``` + +上述命令将会下载的启动脚本文件 `as.sh` 到当前目录,你可以放在任何地方或将其加入到 $PATH 中。 + + +## Windows + +下载最新的 zip 包,解压后运行 bin 目录下的 `as.bat`。 + +下载地址:[arthas-packaging-3.0.0-RC-bin.zip](https://search.maven.org/remotecontent?filepath=com/taobao/arthas/arthas-packaging/3.0.0-RC/arthas-packaging-3.0.0-RC-bin.zip) + +Windows用户如果在cmd里不能正常显示颜色,可以使用[conemu](https://sourceforge.net/projects/conemu)。 + +## 独立的帮助文档 + +下载地址:[arthas-packaging-3.0.0-RC-doc.zip](https://search.maven.org/remotecontent?filepath=com/taobao/arthas/arthas-packaging/3.0.0-RC/arthas-packaging-3.0.0-RC-doc.zip) + + +## 卸载 + +* 在 Linux/Unix/Mac 平台 + + 删除下面文件: + ```bash + rm -rf ~/.arthas/ ~/.arthas_history + ``` + +* Windows平台直接删除zip包和解压的文件 diff --git a/_sources/jad.md.txt b/_sources/jad.md.txt new file mode 100644 index 000000000..56ec3deaf --- /dev/null +++ b/_sources/jad.md.txt @@ -0,0 +1,155 @@ +jad +=== + +> 反编译指定已加载类的源码 + +`jad` 命令将 JVM 中实际运行的 class 的 byte code 反编译成 java 代码,便于你理解业务逻辑; + +* 在 Arthas Console 上,反编译出来的源码是带语法高亮的,阅读更方便 +* 当然,反编译出来的 java 代码可能会存在语法错误,但不影响你进行阅读理解 + +### 参数说明 + +|参数名称|参数说明| +|---:|:---| +|*class-pattern*|类名表达式匹配| +|`[c:]`|类所属 ClassLoader 的 hashcode| +|[E]|开启正则表达式匹配,默认为通配符匹配| + +### 使用参考 + +>当有多个 `ClassLoader` 都加载了这个类时,`jad` 命令会输出对应 `ClassLoader` 实例的 `hashcode`,然后你只需要重新执行 `jad` 命令,并使用参数 `-c ` 就可以反编译指定 ClassLoader 加载的那个类了; + +```java +$ jad org.apache.log4j.Logger + + Found more than one class for: org.apache.log4j.Logger, Please use jad -c hashcode org.apache.log4j.Logger + HASHCODE CLASSLOADER + 69dcaba4 +-monitor's ModuleClassLoader + 6e51ad67 +-java.net.URLClassLoader@6e51ad67 + +-sun.misc.Launcher$AppClassLoader@6951a712 + +-sun.misc.Launcher$ExtClassLoader@6fafc4c2 + 2bdd9114 +-pandora-qos-service's ModuleClassLoader + 4c0df5f8 +-pandora-framework's ModuleClassLoader + +Affect(row-cnt:0) cost in 38 ms. +$ jad org.apache.log4j.Logger -c 69dcaba4 + +ClassLoader: ++-monitor's ModuleClassLoader + +Location: +/Users/zhuyong/Downloads/taobao-hsf.sar/plugins/monitor/lib/log4j-1.2.14.jar + +package org.apache.log4j; + +import org.apache.log4j.spi.*; + +public class Logger extends Category +{ + private static final String FQCN; + + protected Logger(String name) + { + super(name); + } + + public static Logger getLogger(String name) + { + return LogManager.getLogger(name); + } + + public static Logger getLogger(Class clazz) + { + return LogManager.getLogger(clazz.getName()); + } + + public static Logger getRootLogger() + { + return LogManager.getRootLogger(); + } + + public static Logger getLogger(String name, LoggerFactory factory) + { + return LogManager.getLogger(name, factory); + } + + public void trace(Object message) + { + if (repository.isDisabled(5000)) + { + return; + } + if (Level.TRACE.isGreaterOrEqual(getEffectiveLevel())) + { + forcedLog(Logger.FQCN, Level.TRACE, message, null); + } + } + + public void trace(Object message, Throwable t) + { + if (repository.isDisabled(5000)) + { + return; + } + if (Level.TRACE.isGreaterOrEqual(getEffectiveLevel())) + { + forcedLog(Logger.FQCN, Level.TRACE, message, t); + } + } + + public boolean isTraceEnabled() + { + if (repository.isDisabled(5000)) + { + return false; + } + return Level.TRACE.isGreaterOrEqual(getEffectiveLevel()); + } + + static + { + Logger.FQCN = Logger.class.getName(); + } + +} + +Affect(row-cnt:1) cost in 190 ms. +``` + +反编译指定的方法: + +```sh +$ jad com.taobao.container.web.arthas.rest.MetricsController directMetrics + +ClassLoader: ++-com.taobao.pandora.boot.loader.ReLaunchURLClassLoader@1817d444 + +-sun.misc.Launcher$AppClassLoader@14dad5dc + +-sun.misc.Launcher$ExtClassLoader@a38d7a3 + +Location: +/Users/zhuyong/middleware/tomcat-web/tomcat-web-web/target/classes/ + +private Map directMetrics(String ip, String[] metrics) { + JSONObject obj; + HashMap result = new HashMap(); + result.put("success", false); + String metricUrl = "http://" + ip + ":8006/metrics/specific"; + String postBody = Arrays.stream(metrics).map(metric -> "metric=" + metric).collect(Collectors.joining("&")); + HttpClientUtils.Response resp = HttpClientUtils.sendPostRequest((String)metricUrl, (String)postBody); + if (resp.isSuccess() && (obj = JSON.parseObject(resp.getContent())).containsKey("success") && obj.getBoolean("success").booleanValue() && obj.containsKey("data")) { + JSONArray dataArray = obj.getJSONArray("data"); + HashMap metricMap = new HashMap(); + for (Object aDataArray : dataArray) { + JSONObject o = (JSONObject)aDataArray; + metricMap.put(o.getString("metric"), o.get("value")); + } + result.put("data", metricMap); + result.put("success", true); + return result; + } + return result; +} + +Affect(row-cnt:1) cost in 1508 ms. +``` \ No newline at end of file diff --git a/_sources/jvm.md.txt b/_sources/jvm.md.txt new file mode 100644 index 000000000..4c626f041 --- /dev/null +++ b/_sources/jvm.md.txt @@ -0,0 +1,97 @@ +jvm +=== + +> 查看当前JVM信息 + +### 使用参考 + +``` +$ jvm + CATEGORY INFO +------------------------------------------------------------------------------------------------------------------------------------ + + RUNTIME MACHINE-NAME hellodeMacBook-Air.local + JVM-START-TIME 2015-12-23 10:54:18 + MANAGEMENT-SPEC-VERSION 1.2 + SPEC-NAME Java Virtual Machine Specification + SPEC-VENDOR Oracle Corporation + SPEC-VERSION 1.8 + VM-NAME Java HotSpot(TM) 64-Bit Server VM + VM-VENDOR Oracle Corporation + VM-VERSION 25.60-b23 + INPUT-ARGUMENTS -Xbootclasspath/a:/Users/hello/.jenv/versions/1.8/lib/tools.jar + -Djava.util.logging.config.file=/Users/hello/code/java/crash/packaging/target/ + conf/logging.properties + + CLASS-PATH /Users/hello/.jenv/versions/1.8/lib/tools.jar:/Users/hello/code/java/cras + h/packaging/target/bin/crash.cli-1.3.2-SNAPSHOT.jar::/Users/hello/code/java/cr + ash/packaging/target/lib/bcpkix-jdk15on-1.51.jar:/Users/hello/code/java/crash/ + packaging/target/lib/bcprov-jdk15on-1.51.jar:/Users/hello/code/java/crash/pack + aging/target/lib/crash.connectors.ssh-1.3.2-SNAPSHOT-standalone.jar:/Users/hengyuna + bc/code/java/crash/packaging/target/lib/crash.connectors.telnet-1.3.2-SNAPSHOT-stan + dalone.jar:/Users/hello/code/java/crash/packaging/target/lib/crash.shell-1.3.2 + -SNAPSHOT.jar:/Users/hello/code/java/crash/packaging/target/lib/groovy-all-1.8 + .9.jar:/Users/hello/code/java/crash/packaging/target/lib/ivy-2.2.0.jar + BOOT-CLASS-PATH /Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/resources.j + ar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/rt.jar:/ + Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/sunrsasign.j + ar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/jsse.jar + :/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/jce.jar:/L + ibrary/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/charsets.jar: + /Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/jfr.jar:/Li + brary/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/classes:/Users/hen + gyunabc/.jenv/versions/1.8/lib/tools.jar + LIBRARY-PATH /Users/hello/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library + /Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:. + + CLASS-LOADING LOADED-CLASS-COUNT 4264 + TOTAL-LOADED-CLASS-COUNT 4264 + UNLOADED-CLASS-COUNT 0 + IS-VERBOSE false + + COMPILATION NAME HotSpot 64-Bit Tiered Compilers + TOTAL-COMPILE-TIME 5145(ms) + + GARBAGE-COLLECTORS PS Scavenge 6/74(ms) + [count/time] + PS MarkSweep 1/64(ms) + [count/time] + + MEMORY-MANAGERS CodeCacheManager Code Cache + + Metaspace Manager Metaspace + Compressed Class Space + + PS Scavenge PS Eden Space + PS Survivor Space + + PS MarkSweep PS Eden Space + PS Survivor Space + PS Old Gen + + + MEMORY HEAP-MEMORY-USAGE 186646528/134217728/1908932608/31245568 + [committed/init/max/used] + NO-HEAP-MEMORY-USAGE 35520512/2555904/-1/34584616 + [committed/init/max/used] + PENDING-FINALIZE-COUNT 0 + + OPERATING-SYSTEM OS Mac OS X + ARCH x86_64 + PROCESSORS-COUNT 4 + LOAD-AVERAGE 2.328125 + VERSION 10.10.5 + + THREAD COUNT 16 + DAEMON-COUNT 10 + LIVE-COUNT 18 + STARTED-COUNT 19 +Affect cost in 2 ms. +``` + +### THREAD相关 + +* COUNT: JVM当前活跃的线程数 +* DAEMON-COUNT: JVM当前活跃的守护线程数 +* LIVE-COUNT: 从JVM启动开始曾经活着的最大线程数 +* STARTED-COUNT: 从jvm启动开始总共启动过的线程次数 \ No newline at end of file diff --git a/_sources/keymap.md.txt b/_sources/keymap.md.txt new file mode 100644 index 000000000..b73cf621d --- /dev/null +++ b/_sources/keymap.md.txt @@ -0,0 +1,78 @@ +Arthas 3.0命令行快捷键 +=== + +keymap命令输出当前的快捷键映射表: + +默认的快捷键如下: + + + + + +| 快捷键 | 快捷键说明 | 命令名称 | 命令说明 | +| ------------- | ---------------- | -------------------- | ---------------- | +| `"\C-a"` | ctrl + a | beginning-of-line | 跳到行首 | +| ` "\C-e"` | ctrl + e | end-of-line | 跳到行尾 | +| `"\C-f"` | ctrl + f | forward-word | 向前移动一个单词 | +| `"\C-b"` | ctrl + b | backward-word | 向后移动一个单词 | +| `"\e[D"` | 键盘左方向键 | backward-char | 光标向前移动一个字符 | +| `"\e[C"` | 键盘右方向键 | forward-char | 光标向后移动一个字符 | +| `"\e[B"` | 键盘下方向键 | next-history | 上翻显示上一个命令 | +| `"\e[A"` | 键盘上方向键 | previous-history | 下翻显示下一个命令 | +| `"\C-h"` | ctrl + h | backward-delete-char | 向后删除一个字符 | +| `"\C-?"` | ctrl + shift + / | backward-delete-char | 向后删除一个字符 | +| `"\C-u"` | ctrl + u | undo | 撤销上一个命令,相当于清空当前行 | +| `"\C-d"` | ctrl + d | delete-char | 删除当前光标所在字符 | +| `"\C-k"` | ctrl + k | kill-line | 删除当前光标到行尾的所有字符 | +| `"\C-i"` | ctrl + i | complete | 自动补全,相当于敲`TAB` | +| `"\C-j"` | ctrl + j | accept-line | 结束当前行,相当于敲回车 | +| `"\C-m"` | ctrl + m | accept-line | 结束当前行,相当于敲回车 | +| `"\C-w"` | | backward-delete-word | | +| `"\C-x\e[3~"` | | backward-kill-line | | +| `"\e\C-?"` | | backward-kill-word | | + + +* 任何时候 `tab` 键,会根据当前的输入给出提示 +* 命令后敲 `-` 或 `--` ,然后按 `tab` 键,可以展示出此命令具体的选项 + + +#### 自定义快捷键 + +在当前用户目录下新建`$USER_HOME/.arthas/conf/inputrc`文件,加入自定义配置。 + +假设我是vim的重度用户,我要把`ctrl+h`设置为光标向前一个字符,则设置如下,首先拷贝默认配置 + +``` +"\C-a": beginning-of-line +"\C-e": end-of-line +"\C-f": forward-word +"\C-b": backward-word +"\e[D": backward-char +"\e[C": forward-char +"\e[B": next-history +"\e[A": previous-history +"\C-h": backward-delete-char +"\C-?": backward-delete-char +"\C-u": undo +"\C-d": delete-char +"\C-k": kill-line +"\C-i": complete +"\C-j": accept-line +"\C-m": accept-line +"\C-w": backward-delete-word +"\C-x\e[3~": backward-kill-line +"\e\C-?": backward-kill-word +``` + +然后把`"\C-h": backward-delete-char`换成`"\C-h": backward-char`,然后重新连接即可。 + +#### 后台异步命令相关快捷键 + +* ctrl + c: 终止当前命令 +* ctrl + z: 挂起当前命令,后续可以 bg/fg 重新支持此命令,或 kill 掉 +* ctrl + a: 回到行首 +* ctrl + e: 回到行尾 + + + + diff --git a/_sources/manual-install.md.txt b/_sources/manual-install.md.txt new file mode 100644 index 000000000..a7ff59425 --- /dev/null +++ b/_sources/manual-install.md.txt @@ -0,0 +1,25 @@ +手动安装Arthas +=== + +1. 从[这里](TODO)下载指定的版本, 以`3.0.20171103142340`这个版本为例。 +``` +wget TODO arthas-3.0.20171103142340-bin.zip +``` + +2. 解压缩arthas的压缩包 +``` +unzip arthas-3.0.20171103142340-bin.zip +``` + +3. 安装Arthas: 安装之前最好把所有老版本的Arthas全都删掉 +``` +sudo su admin +rm -rf /home/admin/.arthas/lib/* +cd arthas +./install-local.sh +``` +> 注意,这里根据你需要诊断的Java进程的所属用户进行切换,例如集团规范是admin用户,而阿里云的可能是tomcat用户。否则会安装到个人目录下,这样的安装是无效的。 +3. 启动Arthas: 启动之前,请确保老版本的Arthas已经shutdown. +``` +./as.sh +``` \ No newline at end of file diff --git a/_sources/monitor.md.txt b/_sources/monitor.md.txt new file mode 100644 index 000000000..8c7bca07e --- /dev/null +++ b/_sources/monitor.md.txt @@ -0,0 +1,51 @@ +monitor +=== + +> 方法执行监控 + +对匹配 `class-pattern`/`method-pattern`的类、方法的调用进行监控。 + +`monitor` 命令是一个非实时返回命令,实时返回命令是输入之后立即返回,而非实时返回的命令,则是不断的等待目标 Java 进程返回信息,直到用户输入 `Ctrl+C` 为止。服务端是以任务的形式在后台跑任务,植入的代码随着任务的中止而被不会被执行,所以任务关闭后,不会对原有性能产生太大影响,而且原则上,任何 Arthas 的命令也不会引起任何原有业务逻辑的改变。 + +### 监控的维度说明 + +|监控项|说明| +|---:|:---| +|timestamp|时间戳| +|class|Java类| +|method|方法(构造方法、普通方法)| +|total|调用次数| +|success|成功次数| +|fail|失败次数| +|rt|平均RT| +|fail-rate|失败率| + +### 参数说明 + +方法拥有一个命名参数 `[c:]`,意思是统计周期(cycle of output),拥有一个整形的参数值 + +|参数名称|参数说明| +|---:|:---| +|*class-pattern*|类名表达式匹配| +|*method-pattern*|方法名表达式匹配| +|[E]|开启正则表达式匹配,默认为通配符匹配| +|`[c:]`|统计周期,默认值为120秒| + +### 使用参考 + +```shell +$ monitor -c 5 com.alibaba.sample.petstore.web.store.module.screen.ItemList execute +Press Ctrl+C to abort. +Affect(class-cnt:1 , method-cnt:1) cost in 36 ms. + timestamp class method total success fail rt fail-rate +----------------------------------------------------------------------------------------------------------------------------------- + 2015-12-17 10:56:40 com.alibaba.sample.petstore.web.store.module.screen.ItemList execute 10 10 0 2.00 0.00% + + timestamp class method total success fail rt fail-rate +----------------------------------------------------------------------------------------------------------------------------------- + 2015-12-17 10:56:45 com.alibaba.sample.petstore.web.store.module.screen.ItemList execute 11 11 0 2.18 0.00% + + timestamp class method total success fail rt fail-rate +----------------------------------------------------------------------------------------------------------------------------------- + 2015-12-17 10:56:50 com.alibaba.sample.petstore.web.store.module.screen.ItemList execute 0 0 0 0.00 0.00% +``` \ No newline at end of file diff --git a/_sources/options.md.txt b/_sources/options.md.txt new file mode 100644 index 000000000..6ce8ae1cf --- /dev/null +++ b/_sources/options.md.txt @@ -0,0 +1,26 @@ +options +=== + +> 全局开关 + +| 名称 | 默认值 | 描述 | +| ------------------ | ----- | ---------------------------------------- | +| unsafe | false | 是否支持对系统级别的类进行增强,打开该开关可能导致把JVM搞挂,请慎重选择! | +| dump | false | 是否支持被增强了的类dump到外部文件中,如果打开开关,class文件会被dump到`/${application dir}/arthas-class-dump/`目录下,具体位置详见控制台输出 | +| batch-re-transform | true | 是否支持批量对匹配到的类执行retransform操作 | +| json-format | false | 是否支持json化的输出 | +| disable-sub-class | false | 是否禁用子类匹配,默认在匹配目标类的时候会默认匹配到其子类,如果想精确匹配,可以关闭此开关 | +| debug-for-asm | false | 打印ASM相关的调试信息 | +| save-result | false | 是否打开执行结果存日志功能,打开之后所有命令的运行结果都将保存到`/home/admin/logs/arthas/arthas.log`中 | +| job-timeout | 1d | 异步后台任务的默认超时时间,超过这个时间,任务自动停止;比如设置 1d, 2h, 3m, 25s,分别代表天、小时、分、秒 | + +### 使用说明 + +例如,想打开执行结果存日志功能,输入如下命令即可: + +``` +$ options save-result true + NAME BEFORE-VALUE AFTER-VALUE +---------------------------------------- + save-result false true +``` \ No newline at end of file diff --git a/_sources/quick-start.md.txt b/_sources/quick-start.md.txt new file mode 100644 index 000000000..33d748348 --- /dev/null +++ b/_sources/quick-start.md.txt @@ -0,0 +1,142 @@ +快速入门 +=== + +## 1. 启动Demo + +```java +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +public class Demo { + static class Counter { + private static AtomicInteger count = new AtomicInteger(0); + public static void increment() { + count.incrementAndGet(); + } + public static int value() { + return count.get(); + } + } + + public static void main(String[] args) throws InterruptedException { + while (true) { + Counter.increment(); + System.out.println("counter: " + Counter.value()); + TimeUnit.SECONDS.sleep(1); + } + } +} +``` + +把上面的内容保存到`Demo.java`里,然后在命令行下编绎启动: +```bash +javac Demo.java +java Demo +``` + +也可以把代码保存到IDE里,然后启动。 + +## 2. 启动arthas + +### Linux/Unix/Mac +在命令行下面执行: + +```bash +./as.sh +``` + +> 执行该脚本的用户需要和目标进程具有相同的权限。比如以`admin`用户来执行: +> `sudo su admin && ./as.sh` 或 `sudo -u admin -EH ./as.sh`。 +> 详细的启动脚本说明,请参考[这里](start-arthas.md)。 +> 如果attatch不上目标进程,可以查看`~/logs/arthas/` 目录下的日志。 + +选择应用java进程: + +``` +$ ./as.sh +Arthas script version: 3.0.2 +Found existing java process, please choose one and hit RETURN. +* [1]: 95428 + [2]: 22647 org.jetbrains.jps.cmdline.Launcher + [3]: 21736 + [4]: 13560 Demo +``` + +Demo进程是第4个,则输入4,再输入回车/enter。Arthas会attach到目标进程上,并输出日志: + +``` +Connecting to arthas server... current timestamp is 1536656867 +Trying 127.0.0.1... +Connected to 127.0.0.1. +Escape character is '^]'. + ,---. ,------. ,--------.,--. ,--. ,---. ,---. + / O \ | .--. ''--. .--'| '--' | / O \ ' .-' +| .-. || '--'.' | | | .--. || .-. |`. `-. +| | | || |\ \ | | | | | || | | |.-' | +`--' `--'`--' '--' `--' `--' `--'`--' `--'`-----' + + +doc: https://alibaba.github.io/arthas +version: 3.0.1-RC-SNAPSHOT +pid: 13560 +timestamp: 1536656867894 +``` + +### Windows + +打开Dos命令行窗口,在解压的arthas目录下执行`as.bat`。 + + +## 3. 查看dashboard + +输入[dashboard](dashboard.md),按enter/回车,会展示当前进程的信息,按`ctrl+c`可以中断执行。 + +``` +$ dashboard +ID NAME GROUP PRIORI STATE %CPU TIME INTERRU DAEMON +17 pool-2-thread-1 system 5 WAITIN 67 0:0 false false +27 Timer-for-arthas-dashb system 10 RUNNAB 32 0:0 false true +11 AsyncAppender-Worker-a system 9 WAITIN 0 0:0 false true +9 Attach Listener system 9 RUNNAB 0 0:0 false true +3 Finalizer system 8 WAITIN 0 0:0 false true +2 Reference Handler system 10 WAITIN 0 0:0 false true +4 Signal Dispatcher system 9 RUNNAB 0 0:0 false true +26 as-command-execute-dae system 10 TIMED_ 0 0:0 false true +13 job-timeout system 9 TIMED_ 0 0:0 false true +1 main main 5 TIMED_ 0 0:0 false false +14 nioEventLoopGroup-2-1 system 10 RUNNAB 0 0:0 false false +18 nioEventLoopGroup-2-2 system 10 RUNNAB 0 0:0 false false +23 nioEventLoopGroup-2-3 system 10 RUNNAB 0 0:0 false false +15 nioEventLoopGroup-3-1 system 10 RUNNAB 0 0:0 false false +Memory used total max usage GC +heap 32M 155M 1820M 1.77% gc.ps_scavenge.count 4 +ps_eden_space 14M 65M 672M 2.21% gc.ps_scavenge.time(m 166 +ps_survivor_space 4M 5M 5M s) +ps_old_gen 12M 85M 1365M 0.91% gc.ps_marksweep.count 0 +nonheap 20M 23M -1 gc.ps_marksweep.time( 0 +code_cache 3M 5M 240M 1.32% ms) +Runtime +os.name Mac OS X +os.version 10.13.4 +java.version 1.8.0_162 +java.home /Library/Java/JavaVir + tualMachines/jdk1.8.0 + _162.jdk/Contents/Hom + e/jre +``` + +## 4. watch + +通过[watch](watch.md)命令来查看`Counter.value()`函数的返回值: + +``` +$ watch Demo$Counter value returnObj +Press Ctrl+C to abort. +Affect(class-cnt:1 , method-cnt:1) cost in 29 ms. +ts=2018-09-10 17:53:11;result=@Integer[621] +ts=2018-09-10 17:53:12;result=@Integer[622] +ts=2018-09-10 17:53:13;result=@Integer[623] +ts=2018-09-10 17:53:14;result=@Integer[624] +ts=2018-09-10 17:53:15;result=@Integer[625] +``` + +更多的功能可以查看[进阶使用](advanced-use.md)。 \ No newline at end of file diff --git a/_sources/redefine.md.txt b/_sources/redefine.md.txt new file mode 100644 index 000000000..1e4f8e0fc --- /dev/null +++ b/_sources/redefine.md.txt @@ -0,0 +1,24 @@ +redefine +=== + +> 加载外部的`.class`文件,redefine jvm已加载的类。 + +参考:[Instrumentation#redefineClasses](https://docs.oracle.com/javase/8/docs/api/java/lang/instrument/Instrumentation.html#redefineClasses-java.lang.instrument.ClassDefinition...-) + +> 注意, redefine后的原来的类不能恢复,redefine有可能失败(比如增加了新的field),参考jdk本身的文档。 + +### 参数说明 + +|参数名称|参数说明| +|---:|:---| +|[c:]|ClassLoader的hashcode| +|[p:]|外部的`.class`文件的完整路径,支持多个| + + + +### 使用参考 + +``` + redefine -p /tmp/Test.class + redefine -c 327a647b -p /tmp/Test.class /tmp/Test\$Inner.class +``` \ No newline at end of file diff --git a/_sources/release-notes.md.txt b/_sources/release-notes.md.txt new file mode 100644 index 000000000..2b7a50b60 --- /dev/null +++ b/_sources/release-notes.md.txt @@ -0,0 +1,130 @@ + +Release Notes +=== + + +v2017-11-03 +---- + +* 增加getstatic方法获取静态变量 +* 修复arthas classloader加载到应用日志的问题 +* 增加ognl custom classloader便于调用静态方法 +* 优化termd输出大字符串的性能问题 +* classloader命令默认按类加载器类型分类编译 +* 修复wc命令统计错误的问题 +* 禁止增强特定JDK类,如Classloader, Method, Integer等 +* 支持OGNL表达式出错直接退出命令 +* 修复管道类命令单独出错的问题 +* 优化命令重定向功能,使用异步日志输出结果 +* trace命令增加过滤jdk方法调用的功能 + + +v2017-09-22 +---- + +* 优化agent server启动时的异常信息 +* 修复异步命令的一些bug + +v2017-09-11 +---- + +* 支持[异步后后命令](async.md) +* jad命令优化,支持JDK8及内部类 +* 修复中文乱码问题 + +v2017-05-11 +---- + +* tt命令默认只展开1层,防止对象过大造成卡顿 +* 修复中文无法展示的问题 + +v2017-05-12 +---- + +* Arthas 3.0 release + +v2016-12-09 +---- + +* as.sh支持-h输出帮助 +* [#121] 修复残留的临时文件导致arthas启动失败的问题 +* [#123] 修复反复attach/shutdown造成classloader泄露的问题 +* 优化命令中的帮助提示信息 +* [#126] 修复tm命令文档链接错乱的问题 +* [#122] classloader命令中过滤掉`sun.reflect.DelegatingClassLoader` +* [#129] 修复classloader层次展示的问题 +* [#125] arthas输出的log不主动换行,对于日志解析更加友好 +* [#96] sc等命令支持com/taobao/xxx/TestClass这样的格式,以后复制粘贴不需要在把'/'替换成'.'啦 +* [#124] 修复某些情况下trace的时间为负值的问题 +* [#128] tt命令的结果默认自动展开,不需要再增加`-x 2`来看到参数,异常的详细信息了。 +* [#130] 修复当端口冲突时,没有很好地打印错误,而是进入了一个出错的交互界面的问题 +* [#98] 修复Arthas启动时,如果下载更新失败,导致启动失败的问题 +* [#139] 修复某些特殊情况下agent attach失败的问题 +* [#156] jd-core-java延迟初始化,避免arthas启动时出错 +* 修复线程名重复的问题 +* [#150] trace命令支持按运行总耗时过滤 +* 修复sc查找SystemClassloader时可能出现的NPE +* [#180] 修复第一次Attach成功之后,删除之前Arthas的安装包,重新编译打包,再次attach失败的问题 + + +v2016-06-07 +---- + +* 修复以资源方式加载spy类时出现NPE的问题 +* 支持一键找出线程中获得锁并阻塞住其他线程的线程 +* 优化 Thread 输出,按线程名排序 +* 获取topN忙的线程时,支持指定刷新间隔 + +v2016-04-08 +---- + +* New feature: + * dashboard支持指定刷新频率,支持指定执行次数 + * 命令执行结果保存到日志文件,方便后续查看 + * 启动速度优化,第一次attach的速度提升一倍 + * 支持批处理功能,支持执行脚本文件 + * 优化启动逻辑,arthas脚本启动时交互式选择进程 + * 类默认启用继承关系查询,查找类时默认会查找子类,如果需要关闭,则通过全局开关 Options disable-sub-class 关闭 + * 支持在彩色模式和文本模式中切换 + +* UI Improvement: + * 合并exit和quit命令 + * 命令帮助信息增加wiki链接 + * 优化watch的逻辑,更加符合大家的直觉 + * thread命令增加example说明 + * 自动补全的时候,忽略大小写 + +* Bugfix: + * 修复trace命令遇到循环造成输出太长 + * 修复trace命令在方法调用中抛出了异常,会让trace的节点错位 + * 修正增强BootstrapClassLoader加载的类,找不到Spy的问题 + * 修复某些配色方案下,结果显示不友好的问题 + +v2016-03-07 +---- + +* 支持一键查看当前最忙的前N个线程及其堆栈 +* 修复openjdk下启动arthas失败的问题(需要重新安装as.sh) +* 一些体验优化 + + +v2016-01-18 +---- + +* 优化 jad,实时 dump 内存 byte array,并使用 jd-core-java 反编译,支持`行号显示` +* 修复 tt 命令在监控与线程上下文相关的方法调用时,显示/重做等场景下的 bug + +v2016-01-08 +---- + +* 修复一些 bug + * jad NPE + * watch/monitor NPE + * 不需要转义 + * 数据统计问题修复 + * sc 查看静态变量内部层次结构 + +v2015-12-29 +--- + +* Arthas 2.0 测试版本发布! \ No newline at end of file diff --git a/_sources/reset.md.txt b/_sources/reset.md.txt new file mode 100644 index 000000000..3c9b53681 --- /dev/null +++ b/_sources/reset.md.txt @@ -0,0 +1,54 @@ +reset命令 +=== + +> 重置增强类,将被 Arthas 增强过的类全部还原,Arthas 服务端关闭时会重置所有增强过的类 + +### 使用参考 + +``` +$ reset -h + USAGE: + reset [-h] [-E] [class-pattern] + + SUMMARY: + Reset all the enhanced classes + + EXAMPLES: + reset + reset *List + reset -E .*List + + OPTIONS: + -h, --help this help + -E, --regex Enable regular expression to match (wildcard matching by default) + Path and classname of Pattern Matching +``` + +### 还原指定类 + +``` +$ trace Test test +Press Ctrl+C to abort. +Affect(class-cnt:1 , method-cnt:1) cost in 57 ms. +`---ts=2017-10-26 17:10:33;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@14dad5dc + `---[0.590102ms] Test:test() + +`---ts=2017-10-26 17:10:34;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@14dad5dc + `---[0.068692ms] Test:test() + +$ reset Test +Affect(class-cnt:1 , method-cnt:0) cost in 11 ms. +``` + +### 还原所有类 + +``` +$ trace Test test +Press Ctrl+C to abort. +Affect(class-cnt:1 , method-cnt:1) cost in 15 ms. +`---ts=2017-10-26 17:12:06;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@14dad5dc + `---[0.128518ms] Test:test() + +$ reset +Affect(class-cnt:1 , method-cnt:0) cost in 9 ms. +``` \ No newline at end of file diff --git a/_sources/roadmap.md.txt b/_sources/roadmap.md.txt new file mode 100644 index 000000000..2a128c0dd --- /dev/null +++ b/_sources/roadmap.md.txt @@ -0,0 +1,10 @@ +![arthas-roadmap](TODO/arthas-roadmap.png) + +### 设计原则 + +* microservices envy: 理想状态下,所有数据通过 /metrics, /health, /config 暴露 +* endpoint 可扩展 +* endpoint 数据本身就应该可以判定子系统有无问题,而平台只是做展示和聚合。有无平台并不妨碍用户获取数据 (devops) +* 但是平台要成为开发的第一入口,因为其他方式太麻烦了 +* 集群数据、单机历史数据作为单机诊断的依据,单纯的展示没有意义 +* 场景优先,有助于曝光的场景优先实施 diff --git a/_sources/save-log.md.txt b/_sources/save-log.md.txt new file mode 100644 index 000000000..33fa4e898 --- /dev/null +++ b/_sources/save-log.md.txt @@ -0,0 +1,33 @@ +执行结果存日志 +=== + +> 将命令的结果完整保存在日志文件中,便于后续进行分析 + +* 默认情况下,该功能是关闭的,如果需要开启,请执行以下命令: + +```sh +$ options save-result true + NAME BEFORE-VALUE AFTER-VALUE +---------------------------------------- + save-result false true +Affect(row-cnt:1) cost in 3 ms. +``` + +看到上面的输出,即表示成功开启该功能; + +* 日志文件路径 + +结果会异步保存在:`{user.home}/logs/arthas-cache/result.log`,请定期进行清理,以免占据磁盘空间 + +### 使用新版本Arthas的异步后台任务将结果存日志文件 + +```sh +$ trace Test t >> & +job id : 2 +cache location : /Users/zhuyong/logs/arthas-cache/28198/2 +``` + +此时命令会在后台异步执行,并将结果异步保存在文件(~/logs/arthas-cache/${PID}/${JobId})中; + +* 此时任务的执行不受session断开的影响;任务默认超时时间是1天,可以通过全局 `options` 命令修改默认超时时间; +* 此命令的结果将异步输出到文件中;此时不管 `save-result` 是否为true,都不会再往~/logs/arthas-cache/result.log 中异步写结果 \ No newline at end of file diff --git a/_sources/sc.md.txt b/_sources/sc.md.txt new file mode 100644 index 000000000..cd82c72fe --- /dev/null +++ b/_sources/sc.md.txt @@ -0,0 +1,68 @@ +sc +=== + +> 查看JVM已加载的类信息 + +“Search-Class” 的简写,这个命令能搜索出所有已经加载到 JVM 中的 Class 信息,这个命令支持的参数有 `[d]`、`[E]`、`[f]` 和 `[x:]`。 + +参数说明 +--- + +### 参数说明 + +|参数名称|参数说明| +|---:|:---| +|*class-pattern*|类名表达式匹配| +|*method-pattern*|方法名表达式匹配| +|[d]|输出当前类的详细信息,包括这个类所加载的原始文件来源、类的声明、加载的ClassLoader等详细信息。
如果一个类被多个ClassLoader所加载,则会出现多次| +|[E]|开启正则表达式匹配,默认为通配符匹配| +|[f]|输出当前类的成员变量信息(需要配合参数-d一起使用)| +|[x:]|指定输出静态变量时属性的遍历深度,默认为 0,即直接使用 `toString` 输出| + +> class-pattern支持全限定名,如com.taobao.test.AAA,也支持com/taobao/test/AAA这样的格式,这样,我们从异常堆栈里面把类名拷贝过来的时候,不需要在手动把`/`替换为`.`啦。 + +> sc 默认开启了子类匹配功能,也就是说所有当前类的子类也会被搜索出来,想要精确的匹配,请打开`options disable-sub-class true`开关 + +### 使用参考 + +例如, 查看类的静态变量信息, 可以用`sc -df class-name` + +```shell +$ sc -df org.apache.commons.lang.StringUtils + + class-info org.apache.commons.lang.StringUtils + code-source /Users/zhuyong/middleware/citrus-sample/petstore/web/target/petstore/WEB-INF/lib/commons-lang-2.4.jar + name org.apache.commons.lang.StringUtils + isInterface false + isAnnotation false + isEnum false + isAnonymousClass false + isArray false + isLocalClass false + isMemberClass false + isPrimitive false + isSynthetic false + simple-name StringUtils + modifier public + annotation + interfaces + super-class +-java.lang.Object + class-loader +-com.taobao.tomcat.container.context.loader.AliWebappClassLoader + +-org.apache.catalina.loader.StandardClassLoader@1d44eef3 + +-sun.misc.Launcher$AppClassLoader@57a462c9 + +-sun.misc.Launcher$ExtClassLoader@6951a712 + fields modifier final,public,static + type java.lang.String + name EMPTY + value + + modifier final,public,static + type int + name INDEX_NOT_FOUND + value -1 + + modifier final,private,static + type int + name PAD_LIMIT + value 8192 +``` \ No newline at end of file diff --git a/_sources/sm.md.txt b/_sources/sm.md.txt new file mode 100644 index 000000000..d486f04af --- /dev/null +++ b/_sources/sm.md.txt @@ -0,0 +1,88 @@ +sm +=== + +> 查看已加载类的方法信息 + +“Search-Method” 的简写,这个命令能搜索出所有已经加载了 Class 信息的方法信息。 + +`sm` 命令只能看到由当前类所声明 (declaring) 的方法,父类则无法看到。 + +### 参数说明 + +|参数名称|参数说明| +|---:|:---| +|*class-pattern*|类名表达式匹配| +|*method-pattern*|方法名表达式匹配| +|[d]|展示每个方法的详细信息| +|[E]|开启正则表达式匹配,默认为通配符匹配| + +### 使用参考 + +``` +$ sm org.apache.catalina.connector.Connector +org.apache.catalina.connector.Connector-> +org.apache.catalina.connector.Connector->setProperty +org.apache.catalina.connector.Connector->getProperty +org.apache.catalina.connector.Connector->toString +org.apache.catalina.connector.Connector->resume +org.apache.catalina.connector.Connector->getScheme +org.apache.catalina.connector.Connector->getProtocol +org.apache.catalina.connector.Connector->getPort +org.apache.catalina.connector.Connector->setService +org.apache.catalina.connector.Connector->setPort +org.apache.catalina.connector.Connector->getService +org.apache.catalina.connector.Connector->getAttribute +org.apache.catalina.connector.Connector->setAttribute +org.apache.catalina.connector.Connector->getLocalPort +org.apache.catalina.connector.Connector->pause +org.apache.catalina.connector.Connector->setProtocol +org.apache.catalina.connector.Connector->initInternal +org.apache.catalina.connector.Connector->setSecure +org.apache.catalina.connector.Connector->getSecure +org.apache.catalina.connector.Connector->startInternal +org.apache.catalina.connector.Connector->stopInternal +org.apache.catalina.connector.Connector->setScheme +org.apache.catalina.connector.Connector->createRequest +org.apache.catalina.connector.Connector->getDomainInternal +org.apache.catalina.connector.Connector->getProtocolHandler +org.apache.catalina.connector.Connector->setURIEncoding +org.apache.catalina.connector.Connector->findSslHostConfigs +org.apache.catalina.connector.Connector->destroyInternal +org.apache.catalina.connector.Connector->getObjectNameKeyProperties +org.apache.catalina.connector.Connector->getAllowTrace +org.apache.catalina.connector.Connector->setAllowTrace +org.apache.catalina.connector.Connector->getAsyncTimeout +org.apache.catalina.connector.Connector->setAsyncTimeout +org.apache.catalina.connector.Connector->getEnableLookups +org.apache.catalina.connector.Connector->setEnableLookups +org.apache.catalina.connector.Connector->getMaxCookieCount +... + +``` + +```sh +$ sm org.apache.catalina.connector.Connector -d + declaring-class org.apache.catalina.connector.Connector + constructor-name + modifier public + annotation + parameters + exceptions + + declaring-class org.apache.catalina.connector.Connector + constructor-name + modifier public + annotation + parameters java.lang.String + exceptions + + declaring-class org.apache.catalina.connector.Connector + method-name setProperty + modifier public + annotation + parameters java.lang.String + java.lang.String + return boolean + exceptions + ...... +``` \ No newline at end of file diff --git a/_sources/stack.md.txt b/_sources/stack.md.txt new file mode 100644 index 000000000..8d0a1b6f5 --- /dev/null +++ b/_sources/stack.md.txt @@ -0,0 +1,110 @@ +stack +=== + +> 输出当前方法被调用的调用路径 + +很多时候我们都知道一个方法被执行,但这个方法被执行的路径非常多,或者你根本就不知道这个方法是从那里被执行了,此时你需要的是 stack 命令。 + +### 参数说明 + +|参数名称|参数说明| +|---:|:---| +|*class-pattern*|类名表达式匹配| +|*method-pattern*|方法名表达式匹配| +|*condition-express*|条件表达式| +|[E]|开启正则表达式匹配,默认为通配符匹配| +|`[n:]`|执行次数限制| + +这里重点要说明的是观察表达式,观察表达式的构成主要由 ognl 表达式组成,所以你可以这样写`"{params,returnObj}"`,只要是一个合法的 ognl 表达式,都能被正常支持。 + +观察的维度也比较多,主要体现在参数 `advice` 的数据结构上。`Advice` 参数最主要是封装了通知节点的所有信息。 + + +请参考[表达式核心变量](advice-class.md)中关于该节点的描述。 + +* 特殊用法请参考:TODO middleware-container/arthas/issues/263 +* OGNL表达式官网:https://commons.apache.org/proper/commons-ognl/language-guide.html + +### 使用例子 + +> 注意:如果表达式里面包含了引号,那么需要把整个表达式用引号括起来,如果表达式中没有包含引号,那么可以不用引号。当然,一个好的习惯是,不管表达式中有没有引号,都使用引号括起来。 + +``` +$ stack com.alibaba.sample.petstore.dal.dao.ProductDao getProductById 'params[0]=="K9-BD-01"' +Press Ctrl+C to abort. +Affect(class-cnt:1 , method-cnt:1) cost in 51 ms. +thread_name="http-bio-8080-exec-4" thread_id=0x4a;is_daemon=true;priority=5; + @com.alibaba.sample.petstore.dal.dao.ibatis.IbatisProductDao.getProductById() + at com.alibaba.sample.petstore.web.store.module.screen.ItemList.execute(ItemList.java:50) + at com.alibaba.sample.petstore.web.store.module.screen.ItemList$$FastClassByCGLIB$$40b2f45f.invoke(:-1) + at net.sf.cglib.reflect.FastMethod.invoke(FastMethod.java:53) + at com.alibaba.citrus.service.moduleloader.impl.adapter.MethodInvoker.invoke(MethodInvoker.java:70) + at com.alibaba.citrus.service.moduleloader.impl.adapter.DataBindingAdapter.executeAndReturn(DataBindingAdapter.java:41) + at com.alibaba.citrus.turbine.pipeline.valve.PerformScreenValve.performScreenModule(PerformScreenValve.java:111) + at com.alibaba.citrus.turbine.pipeline.valve.PerformScreenValve.invoke(PerformScreenValve.java:74) + at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invokeNext(PipelineImpl.java:157) + at com.alibaba.citrus.turbine.pipeline.valve.PerformActionValve.invoke(PerformActionValve.java:73) + at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invokeNext(PipelineImpl.java:157) + at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invoke(PipelineImpl.java:210) +...... + +thread_name="http-bio-8080-exec-2" thread_id=0x48;is_daemon=true;priority=5; + @com.alibaba.sample.petstore.dal.dao.ibatis.IbatisProductDao.getProductById() + at com.alibaba.sample.petstore.web.store.module.screen.ItemList.execute(ItemList.java:50) + at com.alibaba.sample.petstore.web.store.module.screen.ItemList$$FastClassByCGLIB$$40b2f45f.invoke(:-1) + at net.sf.cglib.reflect.FastMethod.invoke(FastMethod.java:53) + at com.alibaba.citrus.service.moduleloader.impl.adapter.MethodInvoker.invoke(MethodInvoker.java:70) + at com.alibaba.citrus.service.moduleloader.impl.adapter.DataBindingAdapter.executeAndReturn(DataBindingAdapter.java:41) + at com.alibaba.citrus.turbine.pipeline.valve.PerformScreenValve.performScreenModule(PerformScreenValve.java:111) + at com.alibaba.citrus.turbine.pipeline.valve.PerformScreenValve.invoke(PerformScreenValve.java:74) + at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invokeNext(PipelineImpl.java:157) + at com.alibaba.citrus.turbine.pipeline.valve.PerformActionValve.invoke(PerformActionValve.java:73) + at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invokeNext(PipelineImpl.java:157) + at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invoke(PipelineImpl.java:210) + at com.alibaba.citrus.service.pipeline.impl.valve.ChooseValve.invoke(ChooseValve.java:98) + at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invokeNext(PipelineImpl.java:157) +...... +``` + +按照耗时查询: + +``` +$ stack com.alibaba.sample.petstore.web.store.module.screen.ItemList execute #cost>30 +Press Ctrl+C to abort. +Affect(class-cnt:1 , method-cnt:1) cost in 123 ms. +stack com.alibaba.sample.petstore.web.store.module.screen.ItemList execute #cost>30 +thread_name=http-nio-8080-exec-10;id=31;is_daemon=true;priority=5;TCCL=com.taobao.pandora.boot.embedded.tomcat.TomcatEmbeddedWebappClassLoader + @com.alibaba.sample.petstore.web.store.module.screen.ItemList.execute() + at com.alibaba.sample.petstore.web.store.module.screen.ItemList$$FastClassByCGLIB$$40b2f45f.invoke(:-1) + at net.sf.cglib.reflect.FastMethod.invoke(FastMethod.java:53) + at com.alibaba.citrus.service.moduleloader.impl.adapter.MethodInvoker.invoke(MethodInvoker.java:70) + at com.alibaba.citrus.service.moduleloader.impl.adapter.DataBindingAdapter.executeAndReturn(DataBindingAdapter.java:41) + at com.alibaba.citrus.turbine.pipeline.valve.PerformScreenValve.performScreenModule(PerformScreenValve.java:111) + at com.alibaba.citrus.turbine.pipeline.valve.PerformScreenValve.invoke(PerformScreenValve.java:74) + at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invokeNext(PipelineImpl.java:157) + at com.alibaba.citrus.turbine.pipeline.valve.PerformActionValve.invoke(PerformActionValve.java:73) + at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invokeNext(PipelineImpl.java:157) + at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invoke(PipelineImpl.java:210) + at com.alibaba.citrus.service.pipeline.impl.valve.ChooseValve.invoke(ChooseValve.java:98) + at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invokeNext(PipelineImpl.java:157) + at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invoke(PipelineImpl.java:210) + at com.alibaba.citrus.service.pipeline.impl.valve.LoopValve.invokeBody(LoopValve.java:105) + at com.alibaba.citrus.service.pipeline.impl.valve.LoopValve.invoke(LoopValve.java:83) + at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invokeNext(PipelineImpl.java:157) + at com.alibaba.citrus.turbine.pipeline.valve.PageAuthorizationValve.invoke(PageAuthorizationValve.java:105) + at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invokeNext(PipelineImpl.java:157) + at com.alibaba.citrus.turbine.pipeline.valve.CheckCsrfTokenValve.invoke(CheckCsrfTokenValve.java:123) + at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invokeNext(PipelineImpl.java:157) + at com.alibaba.citrus.turbine.pipeline.valve.AnalyzeURLValve.invoke(AnalyzeURLValve.java:126) + at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invokeNext(PipelineImpl.java:157) + at com.alibaba.citrus.turbine.pipeline.valve.SetLoggingContextValve.invoke(SetLoggingContextValve.java:66) + at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invokeNext(PipelineImpl.java:157) + at com.alibaba.citrus.turbine.pipeline.valve.PrepareForTurbineValve.invoke(PrepareForTurbineValve.java:52) + at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invokeNext(PipelineImpl.java:157) + at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invoke(PipelineImpl.java:210) + at com.alibaba.citrus.webx.impl.WebxControllerImpl.service(WebxControllerImpl.java:43) + at com.alibaba.citrus.webx.impl.WebxRootControllerImpl.handleRequest(WebxRootControllerImpl.java:53) + at com.alibaba.citrus.webx.support.AbstractWebxRootController.service(AbstractWebxRootController.java:165) +......... +``` +>只会打印出耗时超过30ms的堆栈情况 \ No newline at end of file diff --git a/_sources/start-arthas.md.txt b/_sources/start-arthas.md.txt new file mode 100644 index 000000000..82624274e --- /dev/null +++ b/_sources/start-arthas.md.txt @@ -0,0 +1,72 @@ +启动 Arthas +- + +## 交互模式启动 + +> ./as.sh + +```sh +➜ bin git:(develop) ✗ ./as.sh +Found existing java process, please choose one and hit RETURN. + [1]: 3088 org.jetbrains.idea.maven.server.RemoteMavenServer +* [2]: 12872 org.apache.catalina.startup.Bootstrap + [3]: 2455 +Attaching to 12872... + ,---. ,------. ,--------.,--. ,--. ,---. ,---. + / O \ | .--. ''--. .--'| '--' | / O \ ' .-' +| .-. || '--'.' | | | .--. || .-. |`. `-. +| | | || |\ \ | | | | | || | | |.-' | +`--' `--'`--' '--' `--' `--' `--'`--' `--'`-----' +$ +``` + +## 非交互模式启动 + +启动脚本如下: + +> ./as.sh \[@IP:PORT] + + + +### 参数说明 + +* PID:目标 Java 进程 ID(请确保执行当前执行命令的用户必须有足够的权限操作对应的 Java 进程) +* IP:目标服务器 IP 地址,当 Arthas Server 启动后,其他人可以通过指定 IP 的形式加载到对应目标机器的 Java 进程中,从而实现远程协助。Arthas 允许多个用户同时访问,并且各自的命令不会相互干扰执行 +* PORT:目标服务器 Arthas Server 的端口号,默认的端口号是 3658 + +### 示例 + +* 如果不指定 IP 和 PORT,默认是 127.0.0.1 和 3658 + + > ./as.sh 12345 + + 上述命令等价于: + + > ./as.sh 12356@127.0.0.1:3658 + +### 远程诊断 + +服务器启动 Arthas Server 后,其他人可以使用 Arthas Console Client 远程连接上去进程诊断,请参考: + +> ./as.sh PID@RemoteIP:RemotePort + +其中 PID 为远程服务器上的 Java 进程 ID,RemoteIP 为远程服务器的 IP 地址,RemotePort 为远程服务器上 Arthas Server 的端口,默认为 3658。 + +### sudo 支持 + +成熟的线上管理环境一般都不会直接开放 JVM 部署用户权限给你,而是通过 sudo-list 来控制和监控用户的越权操作。由于 as.sh 脚本中会对当前用户的环境变量产生感知,所以需要加上 -H 参数 + + > sudo -u admin -H ./as.sh 12345 + +### telnet 的支持 + +Arthas 支持通过 telnet 来访问服务端,如果当你手头的机器没有安装 Arthas Console Client,你可以简单的通过 telnet 命令来进行访问。 + + > telnet 10.232.12.113 3658 + +当然了,telnet 命令没有 `Tab` 自动补全,各种操作体验也不如 Arthas Client Console。 + +### Windows 环境支持 + +* 目前 Arthas 提供了 `as.bat` 脚本,用于 Windows 环境下的诊断场景;此脚本暂时只接受一个参数 pid,即只能诊断本机上的 Java 进程; +* 另外,`as.bat` 脚本在体验方面还有一些问题,如果需要更好的体验,可以在本地使用 `as.bat pid` 启动 Arthas Server 后,然后在另外的 Linux/Mac 上使用 as.bat pid@ip:port 来远程诊断; \ No newline at end of file diff --git a/_sources/sysprop.md.txt b/_sources/sysprop.md.txt new file mode 100644 index 000000000..221f60284 --- /dev/null +++ b/_sources/sysprop.md.txt @@ -0,0 +1,122 @@ +sysprop +======================= + +> 查看当前JVM的系统属性(`System Property`) + +### 使用参考 + +``` + USAGE: + sysprop [-h] [property-name] [property-value] + + SUMMARY: + Display, and change all the system properties. + + EXAMPLES: + sysprop + sysprop file.encoding + sysprop production.mode true + + WIKI: + https://github.com/alibaba/arthas/wiki/sysprop + + OPTIONS: + -h, --help this help + property name + property value +``` + +#### 查看所有属性 + + +``` +$ sysprop + KEY VALUE +------------------------------------------------------------------------------------------------------------------------------------- + java.runtime.name Java(TM) SE Runtime Environment + sun.boot.library.path /Library/Java/JavaVirtualMachines/jdk1.8.0_51.jdk/Contents/Home/jre/lib + java.vm.version 25.51-b03 + user.country.format CN + gopherProxySet false + java.vm.vendor Oracle Corporation + java.vendor.url http://java.oracle.com/ + path.separator : + java.vm.name Java HotSpot(TM) 64-Bit Server VM + file.encoding.pkg sun.io + user.country US + sun.java.launcher SUN_STANDARD + sun.os.patch.level unknown + java.vm.specification.name Java Virtual Machine Specification + user.dir /private/var/tmp + java.runtime.version 1.8.0_51-b16 + java.awt.graphicsenv sun.awt.CGraphicsEnvironment + java.endorsed.dirs /Library/Java/JavaVirtualMachines/jdk1.8.0_51.jdk/Contents/Home/jre/lib/endors + ed + os.arch x86_64 + java.io.tmpdir /var/folders/2c/tbxwzs4s4sbcvh7frbcc7n000000gn/T/ + line.separator + + java.vm.specification.vendor Oracle Corporation + os.name Mac OS X + sun.jnu.encoding UTF-8 + java.library.path /Users/wangtao/Library/Java/Extensions:/Library/Java/Extensions:/Network/Libra + ry/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:. + sun.nio.ch.bugLevel + java.specification.name Java Platform API Specification + java.class.version 52.0 + sun.management.compiler HotSpot 64-Bit Tiered Compilers + os.version 10.12.6 + user.home /Users/wangtao + user.timezone Asia/Shanghai + java.awt.printerjob sun.lwawt.macosx.CPrinterJob + file.encoding UTF-8 + java.specification.version 1.8 + user.name wangtao + java.class.path . + java.vm.specification.version 1.8 + sun.arch.data.model 64 + java.home /Library/Java/JavaVirtualMachines/jdk1.8.0_51.jdk/Contents/Home/jre + sun.java.command Test + java.specification.vendor Oracle Corporation + user.language en + awt.toolkit sun.lwawt.macosx.LWCToolkit + java.vm.info mixed mode + java.version 1.8.0_51 + java.ext.dirs /Users/wangtao/Library/Java/Extensions:/Library/Java/JavaVirtualMachines/jdk1. + 8.0_51.jdk/Contents/Home/jre/lib/ext:/Library/Java/Extensions:/Network/Library + /Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java + sun.boot.class.path /Library/Java/JavaVirtualMachines/jdk1.8.0_51.jdk/Contents/Home/jre/lib/resour + ces.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_51.jdk/Contents/Home/jre/li + b/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_51.jdk/Contents/Home/jre/l + ib/sunrsasign.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_51.jdk/Contents/H + ome/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_51.jdk/Content + s/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_51.jdk/Conte + nts/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_51.jd + k/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_51. + jdk/Contents/Home/jre/classes + java.vendor Oracle Corporation + file.separator / + java.vendor.url.bug http://bugreport.sun.com/bugreport/ + sun.cpu.endian little + sun.io.unicode.encoding UnicodeBig + sun.cpu.isalist +``` + +#### 查看单个属性 + +> 支持通过`TAB`键自动补全 + +``` +$ sysprop java.version +java.version=1.8.0_51 +``` + +#### 修改单个属性 + +``` +$ sysprop user.country +user.country=US +$ sysprop user.country CN +Successfully changed the system property. +user.country=CN +``` \ No newline at end of file diff --git a/_sources/thread.md.txt b/_sources/thread.md.txt new file mode 100644 index 000000000..aa9c63c91 --- /dev/null +++ b/_sources/thread.md.txt @@ -0,0 +1,165 @@ +thread +=== + +> 查看当前线程信息,查看线程的堆栈 + + +### 参数说明 + +|参数名称|参数说明| +|---:|:---| +|*id*|线程id| +|[n:]|指定最忙的前N个线程并打印堆栈| +|[b]|找出当前阻塞其他线程的线程| +|[i ``]|指定cpu占比统计的采样间隔,单位为毫秒| + +> cpu占比是如何统计出来的? + +> 这里的cpu统计的是,一段采样间隔内,当前JVM里各个线程所占用的cpu时间占总cpu时间的百分比。其计算方法为: +> 首先进行一次采样,获得所有线程的cpu的使用时间(调用的是`java.lang.management.ThreadMXBean#getThreadCpuTime`这个接口),然后睡眠一段时间,默认100ms,可以通过`-i`参数指定,然后再采样一次,最后得出这段时间内各个线程消耗的cpu时间情况,最后算出百分比。 + +> 注意: 这个统计也会产生一定的开销(JDK这个接口本身开销比较大),因此会看到as的线程占用一定的百分比,为了降低统计自身的开销带来的影响,可以把采样间隔拉长一些,比如5000毫秒。 + +> 如果想看从Java进程启动开始到现在的cpu占比情况:可以使用[show-busy-java-threads](https://github.com/oldratlee/useful-scripts/blob/master/docs/java.md#-show-busy-java-threads)这个脚本 + +### 使用参考 + +#### 支持一键展示当前最忙的前N个线程并打印堆栈: + +```shell +$ thread -n 3 +"as-command-execute-daemon" Id=29 cpuUsage=75% RUNNABLE + at sun.management.ThreadImpl.dumpThreads0(Native Method) + at sun.management.ThreadImpl.getThreadInfo(ThreadImpl.java:440) + at com.taobao.arthas.core.command.monitor200.ThreadCommand$1.action(ThreadCommand.java:58) + at com.taobao.arthas.core.command.handler.AbstractCommandHandler.execute(AbstractCommandHandler.java:238) + at com.taobao.arthas.core.command.handler.DefaultCommandHandler.handleCommand(DefaultCommandHandler.java:67) + at com.taobao.arthas.core.server.ArthasServer$4.run(ArthasServer.java:276) + at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) + at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) + at java.lang.Thread.run(Thread.java:745) + + Number of locked synchronizers = 1 + - java.util.concurrent.ThreadPoolExecutor$Worker@6cd0b6f8 + + + +"as-session-expire-daemon" Id=25 cpuUsage=24% TIMED_WAITING + at java.lang.Thread.sleep(Native Method) + at com.taobao.arthas.core.server.DefaultSessionManager$2.run(DefaultSessionManager.java:85) + + + +"Reference Handler" Id=2 cpuUsage=0% WAITING on java.lang.ref.Reference$Lock@69ba0f27 + at java.lang.Object.wait(Native Method) + - waiting on java.lang.ref.Reference$Lock@69ba0f27 + at java.lang.Object.wait(Object.java:503) + at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133) +``` + +#### 当没有参数时,显示所有线程的信息。 + +```shell +$ thread +Threads Total: 16, NEW: 0, RUNNABLE: 7, BLOCKED: 0, WAITING: 5, TIMED_WAITING: 4, TERMINATED: 0 +ID NAME GROUP PRIORITY STATE %CPU TIME INTERRUPTE DAEMON +30 as-command-execute-daemon system 9 RUNNABLE 72 0:0 false true +23 as-session-expire-daemon system 9 TIMED_WAIT 27 0:0 false true +22 Attach Listener system 9 RUNNABLE 0 0:0 false true +11 pool-2-thread-1 main 5 TIMED_WAIT 0 0:0 false false +12 Thread-2 main 5 RUNNABLE 0 0:0 false true +13 pool-3-thread-1 main 5 TIMED_WAIT 0 0:0 false false +25 as-selector-daemon system 9 RUNNABLE 0 0:0 false true +14 Thread-3 main 5 TIMED_WAIT 0 0:0 false false +26 pool-5-thread-1 system 5 WAITING 0 0:0 false false +15 Thread-4 main 5 RUNNABLE 0 0:0 false false +1 main main 5 WAITING 0 0:2 false false +2 Reference Handler system 10 WAITING 0 0:0 false true +3 Finalizer system 8 WAITING 0 0:0 false true +4 Signal Dispatcher system 9 RUNNABLE 0 0:0 false true +20 NonBlockingInputStreamThread main 5 WAITING 0 0:0 false true +21 Thread-8 main 5 RUNNABLE 0 0:0 false true +``` + +#### thread id, 显示指定线程的运行堆栈 + +```shell +$ thread 1 +"main" Id=1 WAITING on java.util.concurrent.CountDownLatch$Sync@29fafb28 + at sun.misc.Unsafe.park(Native Method) + - waiting on java.util.concurrent.CountDownLatch$Sync@29fafb28 + at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) + at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836) + at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:997) + at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1304) + at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:231) +``` + +#### thread -b, 找出当前阻塞其他线程的线程 + +有时候我们发现应用卡住了, 通常是由于某个线程拿住了某个锁, 并且其他线程都在等待这把锁造成的。 为了排查这类问题, arthas提供了`thread -b`, 一键找出那个罪魁祸首。 + +```sh +$ thread -b +"http-bio-8080-exec-4" Id=27 TIMED_WAITING + at java.lang.Thread.sleep(Native Method) + at test.arthas.TestThreadBlocking.doGet(TestThreadBlocking.java:22) + - locked java.lang.Object@725be470 <---- but blocks 4 other threads! + at javax.servlet.http.HttpServlet.service(HttpServlet.java:624) + at javax.servlet.http.HttpServlet.service(HttpServlet.java:731) + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303) + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) + at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) + at test.filter.TestDurexFilter.doFilter(TestDurexFilter.java:46) + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) + at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) + at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) + at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505) + at com.taobao.tomcat.valves.ContextLoadFilterValve$FilterChainAdapter.doFilter(ContextLoadFilterValve.java:191) + at com.taobao.eagleeye.EagleEyeFilter.doFilter(EagleEyeFilter.java:81) + at com.taobao.tomcat.valves.ContextLoadFilterValve.invoke(ContextLoadFilterValve.java:150) + at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170) + at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) + at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) + at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:429) + at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1085) + at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:625) + at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318) + - locked org.apache.tomcat.util.net.SocketWrapper@7127ee12 + at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) + at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) + at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) + at java.lang.Thread.run(Thread.java:745) + + Number of locked synchronizers = 1 + - java.util.concurrent.ThreadPoolExecutor$Worker@31a6493e +``` + +> 注意, 目前只支持找出synchronized关键字阻塞住的线程, 如果是JUL的锁, 目前还不支持。 + + +#### thread -i, 指定采样时间间隔 + +```sh +$ thread -n 3 -i 1000 +"as-command-execute-daemon" Id=4759 cpuUsage=23% RUNNABLE + at sun.management.ThreadImpl.dumpThreads0(Native Method) + at sun.management.ThreadImpl.getThreadInfo(ThreadImpl.java:440) + at com.taobao.arthas.core.command.monitor200.ThreadCommand.processTopBusyThreads(ThreadCommand.java:133) + at com.taobao.arthas.core.command.monitor200.ThreadCommand.process(ThreadCommand.java:79) + at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.process(AnnotatedCommandImpl.java:96) + at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.access$100(AnnotatedCommandImpl.java:27) + at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:125) + at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:122) + at com.taobao.arthas.core.shell.system.impl.ProcessImpl$CommandProcessTask.run(ProcessImpl.java:332) + at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) + at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) + at java.lang.Thread.run(Thread.java:756) + + Number of locked synchronizers = 1 + - java.util.concurrent.ThreadPoolExecutor$Worker@546aeec1 +... +``` \ No newline at end of file diff --git a/_sources/trace.md.txt b/_sources/trace.md.txt new file mode 100644 index 000000000..9f45ad357 --- /dev/null +++ b/_sources/trace.md.txt @@ -0,0 +1,112 @@ +trace +=== + +> 方法内部调用路径,并输出方法路径上的每个节点上耗时 + +`trace` 命令能主动搜索 `class-pattern`/`method-pattern` 对应的方法调用路径,渲染和统计整个调用链路上的所有性能开销和追踪调用链路。 + +### 参数说明 + +|参数名称|参数说明| +|---:|:---| +|*class-pattern*|类名表达式匹配| +|*method-pattern*|方法名表达式匹配| +|*condition-express*|条件表达式| +|[E]|开启正则表达式匹配,默认为通配符匹配| +|`[n:]`|命令执行次数| +|`#cost`|方法执行耗时| + +这里重点要说明的是观察表达式,观察表达式的构成主要由 ognl 表达式组成,所以你可以这样写`"{params,returnObj}"`,只要是一个合法的 ognl 表达式,都能被正常支持。 + +观察的维度也比较多,主要体现在参数 `advice` 的数据结构上。`Advice` 参数最主要是封装了通知节点的所有信息。 + + +请参考[表达式核心变量](advice-class.md)中关于该节点的描述。 + +* 特殊用法请参考:TODO middleware-container/arthas/issues/263 +* OGNL表达式官网:https://commons.apache.org/proper/commons-ognl/language-guide.html + +很多时候我们只想看到某个方法的rt大于某个时间之后的trace结果,现在Arthas可以按照方法执行的耗时来进行过滤了,例如`trace *StringUtils isBlank '$cost>100'`表示当执行时间超过100ms的时候,才会输出trace的结果。 + +> 注意: +> 1. watch/stack/trace这个三个命令都支持$cost +> 2. 如果是Arthas 3.0,请把`$cost`改为`#cost` + +### 注意事项 + +`trace` 能方便的帮助你定位和发现因 RT 高而导致的性能问题缺陷,但其每次只能跟踪一级方法的调用链路。 + +### 使用参考 + +代码示例: + +```java + public static void main(String[] args) { + List list = new ArrayList(); + list.add("a"); + list.add("b"); + + List list2 = new ArrayList(); + list2.add("c"); + list2.add("d"); + + int len = add(list, list2); + } + + private static int add(List list, List list2) { + int i = 10; + while (i >= 0) { + try { + hehe(i); + } catch (Throwable t) { + t.printStackTrace(); + } + i--; + } + + list.addAll(list2); + return list.size(); + } + + private static void hehe(int i) { + if (i == 0) { + throw new RuntimeException("ZERO"); + } + } +``` + +监测 `add` 方法: + +```shell +$ trace com.alibaba.sample.petstore.web.store.module.screen.ItemList add params.length==2 +Press Ctrl+C to abort. +Affect(class-cnt:1 , method-cnt:1) cost in 144 ms. +`---Tracing... + `---[2ms]com.alibaba.sample.petstore.web.store.module.screen.ItemList:add() + +---[0,0,0ms,11]com.alibaba.sample.petstore.web.store.module.screen.ItemList:hehe() [throws Exception] + +---[1ms]java.lang.Throwable:printStackTrace() + +---[0ms]java.util.List:addAll() + `---[0ms]java.util.List:size() +``` + +按照耗时过滤: + +```shell +$ trace com.alibaba.sample.petstore.web.store.module.screen.ItemList execute #cost>4 +Press Ctrl+C to abort. +Affect(class-cnt:1 , method-cnt:1) cost in 159 ms. +trace com.alibaba.sample.petstore.web.store.module.screen.ItemList execute #cost>4 +`---thread_name=http-nio-8080-exec-5;id=2c;is_daemon=true;priority=5;TCCL=com.taobao.pandora.boot.embedded.tomcat.TomcatEmbeddedWebappClassLoader + `---[8.866586ms] com.alibaba.sample.petstore.web.store.module.screen.ItemList:execute() + +---[2.847106ms] com.alibaba.sample.petstore.biz.StoreManager:getAllProductItems() + +---[0.765544ms] com.alibaba.sample.petstore.dal.dao.ProductDao:getProductById() + +---[0.021204ms] com.alibaba.sample.petstore.dal.dataobject.Product:getCategoryId() + +---[1.341532ms] com.alibaba.sample.petstore.dal.dao.CategoryDao:getCategoryById() + `---[min=0.005428ms,max=0.094064ms,total=0.105228ms,count=3] com.alibaba.citrus.turbine.Context:put() +``` +> 只会展示耗时大于4ms的调用路径,有助于在排查问题的时候,只关注异常情况 + +- 是不是很眼熟,没错,在 JProfiler 等收费软件中你曾经见识类似的功能,这里你将可以通过命令就能打印出指定调用路径。 友情提醒下,`trace` 在执行的过程中本身是会有一定的性能开销,在统计的报告中并未像 JProfiler 一样预先减去其自身的统计开销。所以这统计出来有些许的不准,渲染路径上调用的类、方法越多,性能偏差越大。但还是能让你看清一些事情的。 +- [2ms] 的含义,`2` 的含义是:当前节点在当前步骤的耗时,单位为毫秒 +- [0,0,0ms,11]xxx:yyy() [throws Exception],对该方法中相同的方法调用进行了合并,`0,0,0ms,11` 表示方法调用耗时,`min,max,total,count`;`throws Exception` 表明该方法调用中存在异常返回 +- 这里存在一个统计不准确的问题,就是所有方法耗时加起来可能会小于该监测方法的总耗时,这个是由于 Arthas 本身的逻辑会有一定的耗时 \ No newline at end of file diff --git a/_sources/tt.md.txt b/_sources/tt.md.txt new file mode 100644 index 000000000..f1902bbb4 --- /dev/null +++ b/_sources/tt.md.txt @@ -0,0 +1,221 @@ +tt +=== + +> 方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测 + +`watch` 虽然很方便和灵活,但需要提前想清楚观察表达式的拼写,这对排查问题而言要求太高,因为很多时候我们并不清楚问题出自于何方,只能靠蛛丝马迹进行猜测。 + +这个时候如果能记录下当时方法调用的所有入参和返回值、抛出的异常会对整个问题的思考与判断非常有帮助。 + +于是乎,TimeTunnel 命令就诞生了。 + +### 记录方法的调用 + +- 基本用法 + + 对于一个最基本的使用来说,就是记录下当前方法的每次调用环境现场。 + + ```java + $ tt -t -n 3 *Test print + Press Ctrl+D or Ctrl+X to abort. + Affect(class-cnt:1 , method-cnt:1) cost in 115 ms. + +----------+----------------------+------------+----------+----------+-----------------+--------------------------------+--------------------------------+ + | INDEX | TIMESTAMP | COST(ms) | IS-RET | IS-EXP | OBJECT | CLASS | METHOD | + +----------+----------------------+------------+----------+----------+-----------------+--------------------------------+--------------------------------+ + | 1007 | 2015-07-26 12:23:21 | 138 | true | false | 0x42cc13a0 | GaOgnlUtilsTest | print | + +----------+----------------------+------------+----------+----------+-----------------+--------------------------------+--------------------------------+ + | 1008 | 2015-07-26 12:23:22 | 143 | true | false | 0x42cc13a0 | GaOgnlUtilsTest | print | + +----------+----------------------+------------+----------+----------+-----------------+--------------------------------+--------------------------------+ + | 1009 | 2015-07-26 12:23:23 | 130 | true | false | 0x42cc13a0 | GaOgnlUtilsTest | print | + +----------+----------------------+------------+----------+----------+-----------------+--------------------------------+--------------------------------+ + $ + ``` + +- 命令参数解析 + + - `-t` + + tt 命令有很多个主参数,`-t` 就是其中之一。这个参数的表明希望记录下类 `*Test` 的 `print` 方法的每次执行情况。 + + - `-n 3` + + 当你执行一个调用量不高的方法时可能你还能有足够的时间用 `CTRL+C` 中断 tt 命令记录的过程,但如果遇到调用量非常大的方法,瞬间就能将你的 JVM 内存撑爆。 + + 此时你可以通过 `-n` 参数指定你需要记录的次数,当达到记录次数时 Arthas 会主动中断tt命令的记录过程,避免人工操作无法停止的情况。 + +- 表格字段说明 + +|表格字段|字段解释| +|---|---| +|INDEX|时间片段记录编号,每一个编号代表着一次调用,后续tt还有很多命令都是基于此编号指定记录操作,非常重要。| +|TIMESTAMP|方法执行的本机时间,记录了这个时间片段所发生的本机时间| +|COST(ms)|方法执行的耗时| +|IS-RET|方法是否以正常返回的形式结束| +|IS-EXP|方法是否以抛异常的形式结束| +|OBJECT|执行对象的`hashCode()`,注意,曾经有人误认为是对象在JVM中的无力内存地址,但很遗憾他不是。但他能帮助你简单的标记当前执行方法的类实体| +|CLASS|执行的类名| +|METHOD|执行的方法名| + +- 条件表达式 + + 不知道大家是否有在使用过程中遇到以下困惑 + * Arthas 似乎很难区分出重载的方法 + * 我只需要观察特定参数,但是 tt 却全部都给我记录了下来 + + 条件表达式也是用 `OGNL` 来编写,核心的判断对象依然是 `Advice` 对象。除了 `tt` 命令之外,`watch`、`trace`、`stack` 命令也都支持条件表达式。 + +- 解决方法重载 + + `tt -t *Test print params[0].length==1` + + 通过制定参数个数的形式解决不同的方法签名,如果参数个数一样,你还可以这样写 + + `tt -t *Test print 'params[1] instanceof Integer'` + +- 解决指定参数 + + `tt -t *Test print params[0].mobile=="13989838402"` + +- 构成条件表达式的 `Advice` 对象 + + 前边看到了很多条件表达式中,都适用了 `params[0]`,有关这个变量的介绍,请参考[表达式核心变量](advice-class.md) + +### 检索调用记录 + +当你用 `tt` 记录了一大片的时间片段之后,你希望能从中筛选出自己需要的时间片段,这个时候你就需要对现有记录进行检索。 + +假设我们有这些记录 + +``` +$ tt -l ++----------+----------------------+------------+----------+----------+-----------------+--------------------------------+--------------------------------+ +| INDEX | TIMESTAMP | COST(ms) | IS-RET | IS-EXP | OBJECT | CLASS | METHOD | ++----------+----------------------+------------+----------+----------+-----------------+--------------------------------+--------------------------------+ +| 1000 | 2015-07-26 01:16:27 | 130 | true | false | 0x42cc13a0 | GaOgnlUtilsTest | print | ++----------+----------------------+------------+----------+----------+-----------------+--------------------------------+--------------------------------+ +| 1001 | 2015-07-26 01:16:27 | 0 | false | true | 0x42cc13a0 | GaOgnlUtilsTest | printAddress | ++----------+----------------------+------------+----------+----------+-----------------+--------------------------------+--------------------------------+ +| 1002 | 2015-07-26 01:16:28 | 119 | true | false | 0x42cc13a0 | GaOgnlUtilsTest | print | ++----------+----------------------+------------+----------+----------+-----------------+--------------------------------+--------------------------------+ +| 1003 | 2015-07-26 01:16:28 | 0 | false | true | 0x42cc13a0 | GaOgnlUtilsTest | printAddress | ++----------+----------------------+------------+----------+----------+-----------------+--------------------------------+--------------------------------+ +| 1004 | 2015-07-26 12:21:56 | 130 | true | false | 0x42cc13a0 | GaOgnlUtilsTest | print | ++----------+----------------------+------------+----------+----------+-----------------+--------------------------------+--------------------------------+ +| 1005 | 2015-07-26 12:21:57 | 138 | true | false | 0x42cc13a0 | GaOgnlUtilsTest | print | ++----------+----------------------+------------+----------+----------+-----------------+--------------------------------+--------------------------------+ +| 1006 | 2015-07-26 12:21:58 | 130 | true | false | 0x42cc13a0 | GaOgnlUtilsTest | print | ++----------+----------------------+------------+----------+----------+-----------------+--------------------------------+--------------------------------+ +Affect(row-cnt:7) cost in 2 ms. +$ +``` + +我需要筛选出 `printAddress` 方法的调用信息 + +``` +$ tt -s method.name=="printAddress" ++----------+----------------------+------------+----------+----------+-----------------+--------------------------------+--------------------------------+ +| INDEX | TIMESTAMP | COST(ms) | IS-RET | IS-EXP | OBJECT | CLASS | METHOD | ++----------+----------------------+------------+----------+----------+-----------------+--------------------------------+--------------------------------+ +| 1001 | 2015-07-26 01:16:27 | 0 | false | true | 0x42cc13a0 | GaOgnlUtilsTest | printAddress | ++----------+----------------------+------------+----------+----------+-----------------+--------------------------------+--------------------------------+ +| 1003 | 2015-07-26 01:16:28 | 0 | false | true | 0x42cc13a0 | GaOgnlUtilsTest | printAddress | ++----------+----------------------+------------+----------+----------+-----------------+--------------------------------+--------------------------------+ +Affect(row-cnt:2) cost in 55 ms. +$ +``` + +你需要一个 `-s` 参数。同样的,搜索表达式的核心对象依旧是 `Advice` 对象。 + +### 查看调用信息 + +对于具体一个时间片的信息而言,你可以通过 `-i` 参数后边跟着对应的 `INDEX` 编号查看到他的详细信息。 + +``` +$ +$ tt -i 1003 ++-----------------+------------------------------------------------------------------------------------------------------+ +| INDEX | 1003 | ++-----------------+------------------------------------------------------------------------------------------------------+ +| GMT-CREATE | 2015-07-26 01:16:28 | ++-----------------+------------------------------------------------------------------------------------------------------+ +| COST(ms) | 0 | ++-----------------+------------------------------------------------------------------------------------------------------+ +| OBJECT | 0x42cc13a0 | ++-----------------+------------------------------------------------------------------------------------------------------+ +| CLASS | GaOgnlUtilsTest | ++-----------------+------------------------------------------------------------------------------------------------------+ +| METHOD | printAddress | ++-----------------+------------------------------------------------------------------------------------------------------+ +| IS-RETURN | false | ++-----------------+------------------------------------------------------------------------------------------------------+ +| IS-EXCEPTION | true | ++-----------------+------------------------------------------------------------------------------------------------------+ +| PARAMETERS[0] | Address@53448f87 | ++-----------------+------------------------------------------------------------------------------------------------------+ +| THROW-EXCEPTION | java.lang.RuntimeException: test | +| | at GaOgnlUtilsTest.printAddress(Unknown Source) | +| | at GaOgnlUtilsTest.(Unknown Source) | +| | at GaOgnlUtilsTest.main(Unknown Source) | ++-----------------+------------------------------------------------------------------------------------------------------+ +Affect(row-cnt:1) cost in 1 ms. +$ +``` + +### 重做一次调用 + +当你稍稍做了一些调整之后,你可能需要前端系统重新触发一次你的调用,此时得求爷爷告奶奶的需要前端配合联调的同学再次发起一次调用。而有些场景下,这个调用不是这么好触发的。 + +`tt` 命令由于保存了当时调用的所有现场信息,所以我们可以自己主动对一个 `INDEX` 编号的时间片自主发起一次调用,从而解放你的沟通成本。此时你需要 `-p` 参数。 + +``` +$ tt -i 1003 -p ++-----------------+---------------------------------------------------------------------------------------------------------+ +| RE-INDEX | 1003 | ++-----------------+---------------------------------------------------------------------------------------------------------+ +| GMT-REPLAY | 2015-07-26 17:29:51 | ++-----------------+---------------------------------------------------------------------------------------------------------+ +| OBJECT | 0x42cc13a0 | ++-----------------+---------------------------------------------------------------------------------------------------------+ +| CLASS | GaOgnlUtilsTest | ++-----------------+---------------------------------------------------------------------------------------------------------+ +| METHOD | printAddress | ++-----------------+---------------------------------------------------------------------------------------------------------+ +| PARAMETERS[0] | Address@53448f87 | ++-----------------+---------------------------------------------------------------------------------------------------------+ +| IS-RETURN | false | ++-----------------+---------------------------------------------------------------------------------------------------------+ +| IS-EXCEPTION | true | ++-----------------+---------------------------------------------------------------------------------------------------------+ +| THROW-EXCEPTION | java.lang.RuntimeException: test | +| | at GaOgnlUtilsTest.printAddress(GaOgnlUtilsTest.java:78) | +| | at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) | +| | at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) | +| | at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) | +| | at java.lang.reflect.Method.invoke(Method.java:483) | +| | at com.github.ompc.Arthas.util.GaMethod.invoke(GaMethod.java:81) | +| | at com.github.ompc.Arthas.command.TimeTunnelCommand$6.action(TimeTunnelCommand.java:592) | +| | at com.github.ompc.Arthas.server.DefaultCommandHandler.execute(DefaultCommandHandler.java:175) | +| | at com.github.ompc.Arthas.server.DefaultCommandHandler.executeCommand(DefaultCommandHandler.java:83) | +| | at com.github.ompc.Arthas.server.GaServer$4.run(GaServer.java:329) | +| | at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) | +| | at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) | +| | at java.lang.Thread.run(Thread.java:745) | ++-----------------+---------------------------------------------------------------------------------------------------------+ +replay time fragment[1003] success. +Affect(row-cnt:1) cost in 3 ms. +$ +``` + +你会发现结果虽然一样,但调用的路径发生了变化,有原来的程序发起变成了 Arthas 自己的内部线程发起的调用了。 + +- 需要强调的点 + + 1. **ThreadLocal 信息丢失** + + 很多框架偷偷的将一些环境变量信息塞到了发起调用线程的 ThreadLocal 中,由于调用线程发生了变化,这些 ThreadLocal 线程信息无法通过 Arthas 保存,所以这些信息将会丢失。 + + 一些常见的 CASE 比如:鹰眼的 TraceId 等。 + + 2. **引用的对象** + + 需要强调的是,`tt` 命令是将当前环境的对象引用保存起来,但仅仅也只能保存一个引用而已。如果方法内部对入参进行了变更,或者返回的对象经过了后续的处理,那么在 `tt` 查看的时候将无法看到当时最准确的值。这也是为什么 `watch` 命令存在的意义。 \ No newline at end of file diff --git a/_sources/usercase.md.txt b/_sources/usercase.md.txt new file mode 100644 index 000000000..255029867 --- /dev/null +++ b/_sources/usercase.md.txt @@ -0,0 +1,5 @@ +## 用户使用arthas案例 + +收集典型的用户使用案例,可以参考。 + +* [如何使图片空间机器成本降低50%](TODO) \ No newline at end of file diff --git a/_sources/watch.md.txt b/_sources/watch.md.txt new file mode 100644 index 000000000..66deb5053 --- /dev/null +++ b/_sources/watch.md.txt @@ -0,0 +1,307 @@ +watch +=== + +> 方法执行数据观测 + +让你能方便的观察到指定方法的调用情况。能观察到的范围为:`返回值`、`抛出异常`、`入参`,通过编写 OGNL 表达式进行对应变量的查看。 + +### 参数说明 + +watch 的参数比较多,主要是因为它能在 4 个不同的场景观察对象 + +|参数名称|参数说明| +|---:|:---| +|*class-pattern*|类名表达式匹配| +|*method-pattern*|方法名表达式匹配| +|*express*|观察表达式| +|*condition-express*|条件表达式| +|[b]|在**方法调用之前**观察| +|[e]|在**方法异常之后**观察| +|[s]|在**方法返回之后**观察| +|[f]|在**方法结束之后**(正常返回和异常返回)观察| +|[E]|开启正则表达式匹配,默认为通配符匹配| +|[x:]|指定输出结果的属性遍历深度,默认为 1| + +这里重点要说明的是观察表达式,观察表达式的构成主要由 ognl 表达式组成,所以你可以这样写`"{params,returnObj}"`,只要是一个合法的 ognl 表达式,都能被正常支持。 + +观察的维度也比较多,主要体现在参数 `advice` 的数据结构上。`Advice` 参数最主要是封装了通知节点的所有信息。 + + +请参考[表达式核心变量](advice-class.md)中关于该节点的描述。 + +* 特殊用法请参考:TODO middleware-container/arthas/issues/263 +* OGNL表达式官网:https://commons.apache.org/proper/commons-ognl/language-guide.html + +**特别说明**: + +* watch 命令定义了4个观察事件点,即 `-b` 方法调用前,`-e` 方法异常后,`-s` 方法返回后和 `-f` 方法结束后 +* 4个观察事件点 `-b`、`-e`、`-s` 默认关闭,`-f` 默认打开,当指定观察点被打开后,在相应事件点会对观察表达式进行求值并输出 +* 这里要注意`方法入参`和`方法出参`的区别,有可能在中间被修改导致前后不一致,除了 `-b` 事件点 `params` 代表方法入参外,其余事件都代表方法出参 +* 当使用 `-b` 时,由于观察事件点是在方法调用前,此时返回值或异常均不存在 + +### 使用参考 + +代码示例: + +```java + public void execute() { + List list = new ArrayList(); + list.add("a"); + list.add("b"); + + List list2 = new ArrayList(); + list2.add("c"); + list2.add("d"); + + int len = add(list, list2); + } + + private static int add(List list, List list2) { + list.addAll(list2); + return list.size(); + } +``` +#### 观察方法出参和返回值 + +```shell +$ watch com.alibaba.sample.petstore.web.store.module.screen.ItemList add "{params,returnObj}" -x 2 +Press Ctrl+C to abort. +Affect(class-cnt:1 , method-cnt:1) cost in 44 ms. +@ArrayList[ + @Object[][ + @ArrayList[isEmpty=false;size=4], + @ArrayList[isEmpty=false;size=2], + ], + + @Integer[4], +] +``` + +#### 观察方法入参 + +```shell +$ watch com.alibaba.sample.petstore.web.store.module.screen.ItemList add "{params,returnObj}" -x 2 -b +Press Ctrl+C to abort. +Affect(class-cnt:1 , method-cnt:1) cost in 48 ms. +@ArrayList[ + @Object[][ + @ArrayList[isEmpty=false;size=2], + @ArrayList[isEmpty=false;size=2], + ], + + null, +] +``` + +> 对比前一个例子,params[0] 其size为2(入参),返回值为空(事件点为方法执行前,因此获取不到返回值) + + +#### 同时观察方法调用前和方法返回后 + +```shell +$ watch com.alibaba.sample.petstore.web.store.module.screen.ItemList add "{params,returnObj}" -x 2 -b -s +Press Ctrl+C to abort. +Affect(class-cnt:1 , method-cnt:1) cost in 59 ms. +@ArrayList[ + @Object[][ + @ArrayList[isEmpty=false;size=2], + @ArrayList[isEmpty=false;size=2], + ], + + null, +] +@ArrayList[ + @Object[][ + @ArrayList[isEmpty=false;size=4], + @ArrayList[isEmpty=false;size=2], + ], + + @Integer[4], +] +``` + +>这里输出结果中,第一次输出的是方法调用前的观察表达式的结果,第二次输出的是方法返回后的表达式的结果 + +>结果的顺序和命令中 `-s -b` 的顺序没有关系,只与事件本身的先后顺序有关 + +#### 调整`-x`的值,观察具体的方法参数值 + +```shell +$ watch com.alibaba.sample.petstore.web.store.module.screen.ItemList add "{params,returnObj}" -x 3 +Press Ctrl+C to abort. +Affect(class-cnt:1 , method-cnt:1) cost in 59 ms. +@ArrayList[ + @Object[][ + @ArrayList[ + @String[a], + + @String[b], + + @String[c], + + @String[d], + ], + @ArrayList[ + @String[c], + + @String[d], + ], + ], + + @Integer[4], +] +``` + +>`-x`表示遍历深度,可以调整来打印具体的参数和结果内容。 + +#### 条件表达式的例子 + +```shell +$ watch com.alibaba.sample.petstore.biz.impl.UserManagerImpl testAdd "{params, returnObj}" "params[0].equals('aaa')" -x 2 +Press Ctrl+C to abort. +Affect(class-cnt:1 , method-cnt:1) cost in 29 ms. +@ArrayList[ + @Object[][ + @String[aaa], + @String[bbb], + ], + + @Integer[6], +] +``` + +>只有满足条件的调用,才会有响应。 + +#### 观察异常信息的例子 + +```shell +$ watch com.alibaba.sample.petstore.biz.impl.UserManagerImpl testAdd "{params, throwExp}" -e -x 2 +Press Ctrl+C to abort. +Affect(class-cnt:1 , method-cnt:1) cost in 29 ms. +@ArrayList[ + @Object[][ + @String[aaa], + @String[bbb], + ], + + java.lang.NullPointerException + at com.alibaba.sample.petstore.biz.impl.UserManagerImpl.testAdd(UserManagerImpl.java:75) + at com.alibaba.sample.petstore.biz.impl.UserManagerImpl.register(UserManagerImpl.java:60) + at com.alibaba.sample.petstore.web.user.module.action.RegisterAction.doRegister(RegisterAction.java:45) + at com.alibaba.sample.petstore.web.user.module.action.RegisterAction$$FastClassByCGLIB$$ad5428f1.invoke() + at net.sf.cglib.reflect.FastMethod.invoke(FastMethod.java:53) + at com.alibaba.citrus.service.moduleloader.impl.adapter.MethodInvoker.invoke(MethodInvoker.java:70) + at com.alibaba.citrus.service.moduleloader.impl.adapter.AbstractModuleEventAdapter.executeAndReturn(AbstractModuleEventAdapter.java:100) + at com.alibaba.citrus.service.moduleloader.impl.adapter.AbstractModuleEventAdapter.execute(AbstractModuleEventAdapter.java:58) + at com.alibaba.citrus.turbine.pipeline.valve.PerformActionValve.invoke(PerformActionValve.java:63) + at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invokeNext(PipelineImpl.java:157) + at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invoke(PipelineImpl.java:210) + at com.alibaba.citrus.service.pipeline.impl.valve.ChooseValve.invoke(ChooseValve.java:98) + at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invokeNext(PipelineImpl.java:157) + at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invoke(PipelineImpl.java:210) + at com.alibaba.citrus.service.pipeline.impl.valve.LoopValve.invokeBody(LoopValve.java:105) + at com.alibaba.citrus.service.pipeline.impl.valve.LoopValve.invoke(LoopValve.java:83) + at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invokeNext(PipelineImpl.java:157) + at com.alibaba.citrus.turbine.pipeline.valve.PageAuthorizationValve.invoke(PageAuthorizationValve.java:105) + at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invokeNext(PipelineImpl.java:157) + at com.alibaba.citrus.turbine.pipeline.valve.CheckCsrfTokenValve.invoke(CheckCsrfTokenValve.java:123) + at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invokeNext(PipelineImpl.java:157) + at com.alibaba.citrus.turbine.pipeline.valve.AnalyzeURLValve.invoke(AnalyzeURLValve.java:126) + at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invokeNext(PipelineImpl.java:157) + at com.alibaba.citrus.turbine.pipeline.valve.SetLoggingContextValve.invoke(SetLoggingContextValve.java:66) + at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invokeNext(PipelineImpl.java:157) + at com.alibaba.citrus.turbine.pipeline.valve.PrepareForTurbineValve.invoke(PrepareForTurbineValve.java:52) + at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invokeNext(PipelineImpl.java:157) + at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invoke(PipelineImpl.java:210) + at com.alibaba.citrus.webx.impl.WebxControllerImpl.service(WebxControllerImpl.java:43) + at com.alibaba.citrus.webx.impl.WebxRootControllerImpl.handleRequest(WebxRootControllerImpl.java:53) + at com.alibaba.citrus.webx.support.AbstractWebxRootController.service(AbstractWebxRootController.java:165) + at com.alibaba.citrus.webx.servlet.WebxFrameworkFilter.doFilter(WebxFrameworkFilter.java:152) + at com.alibaba.citrus.webx.servlet.FilterBean.doFilter(FilterBean.java:148) + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) + at com.alibaba.citrus.webx.servlet.SetLoggingContextFilter.doFilter(SetLoggingContextFilter.java:61) + at com.alibaba.citrus.webx.servlet.FilterBean.doFilter(FilterBean.java:148) + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) + at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) + at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) + at com.taobao.tomcat.valves.ContextLoadFilterValve.invoke(ContextLoadFilterValve.java:152) + at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170) + at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) + at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) + at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:429) + at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1085) + at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:625) + at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1760) + at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1719) + at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) + at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) + at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) + at java.lang.Thread.run(Thread.java:745), +] +``` + +>express中,表示异常信息的变量是`throwExp` + +#### 按照耗时进行过滤 + +```shell +$ watch com.alibaba.sample.petstore.web.store.module.screen.ItemList add "{params,returnObj}" #cost>200 -x 3 +Press Ctrl+C to abort. +Affect(class-cnt:1 , method-cnt:1) cost in 59 ms. +@ArrayList[ + @Object[][ + @ArrayList[ + @String[a], + + @String[b], + + @String[c], + + @String[d], + ], + @ArrayList[ + @String[c], + + @String[d], + ], + ], + + @Integer[4], +] +``` + +>#cost>200(单位是`ms`)表示只有当耗时大于200ms时才会输出,过滤掉执行时间小于200ms的调用 + + +#### 观察当前对象中的全局属性 + +如果想查看方法运行前后,当前对象中的全局属性,可以使用`target`关键字,代表当前对象 + +``` +$ watch com.taobao.container.web.arthas.rest.MyAppsController myFavoriteApps 'target' +Press Ctrl+C to abort. +Affect(class-cnt:1 , method-cnt:1) cost in 128 ms. +ts=2017-10-31 18:45:55;result=@MyAppsController[ + myFavAppsMapper=@$Proxy131[org.apache.ibatis.binding.MapperProxy@563e97f3], + getAppNameAndIdByEmpId=@$Proxy135[HardCodedTarget(type=GetAppNameAndIdByEmpId, url=http://hello.com)], + enableWebConsoleAppsMapper=@$Proxy132[org.apache.ibatis.binding.MapperProxy@7d51e4a8], +] +``` + +然后使用`target.field_name`访问当前对象的某个全局属性 + +``` +$ watch com.taobao.container.web.arthas.rest.MyAppsController myFavoriteApps 'target.myFavAppsMapper' +Press Ctrl+C to abort. +Affect(class-cnt:1 , method-cnt:1) cost in 126 ms. +ts=2017-10-31 18:46:17;result=@$Proxy131[ + m1=@Method[public boolean java.lang.Object.equals(java.lang.Object)], + m2=@Method[public java.lang.String java.lang.Object.toString()], + m5=@Method[public abstract java.util.List com.taobao.container.dal.arthas.mapper.MyFavAppsMapper.listFavApps(java.util.Map)], + m3=@Method[public abstract int com.taobao.container.dal.arthas.mapper.MyFavAppsMapper.delete(java.lang.String,java.lang.String,java.lang.String)], + m4=@Method[public abstract long com.taobao.container.dal.arthas.mapper.MyFavAppsMapper.insert(com.taobao.container.dal.arthas.domain.MyFavAppsDO)], + m0=@Method[public native int java.lang.Object.hashCode()], +] +``` \ No newline at end of file diff --git a/_static/add_badges.js b/_static/add_badges.js new file mode 100644 index 000000000..92d1cb085 --- /dev/null +++ b/_static/add_badges.js @@ -0,0 +1,29 @@ + function addBadge(parent, src, href) { + var img = document.createElement('img'); + img.src = src; + var a = document.createElement('a'); + a.href = href; + a.appendChild(img); + parent.appendChild(a); + parent.appendChild(document.createElement('br')); + } + + function addBadges(parent) { + var li = document.createElement('li'); + li.className = 'toctree-l1'; + var div = document.createElement('div'); + div.className = 'project-badges'; + addBadge(div, 'https://img.shields.io/maven-central/v/com.taobao.arthas/arthas-packaging.svg?style=flat-square', + 'https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.taobao.arthas%22%20AND%20a%3A%22arthas-packaging%22'); + li.appendChild(div); + parent.appendChild(li); + } + + var menus = document.getElementsByClassName("wy-menu wy-menu-vertical"); + if (menus.length > 0) { + var menu = menus[0]; + var lists = menu.getElementsByTagName('ul'); + if (lists.length > 0) { + addBadges(lists[0]); + } + } \ No newline at end of file diff --git a/_static/center_page.js b/_static/center_page.js new file mode 100644 index 000000000..ae4d2bb31 --- /dev/null +++ b/_static/center_page.js @@ -0,0 +1,47 @@ +var head = document.head || document.getElementsByTagName('head')[0]; +var style = null; + +// Centers the page content dynamically. +function centerPage() { + if (style) { + head.removeChild(style); + style = null; + } + + var windowWidth = window.innerWidth; + if (windowWidth <= 768) { + return; + } + + var sideWidth = 300; + var contentWidth = 800; + var ribbonWidth = 150; + var leftMargin = Math.max(0, (windowWidth - sideWidth - contentWidth) / 2); + var scrollbarWidth = document.body ? windowWidth - document.body.clientWidth : 0; + var css = ''; + + css += '.wy-nav-side { left: ' + leftMargin + 'px; }'; + css += "\n"; + css += '.wy-nav-content-wrap { margin-left: ' + (sideWidth + leftMargin) + 'px; }'; + css += "\n"; + css += '.github-fork-ribbon-wrapper.right { left: ' + + (Math.min(windowWidth - scrollbarWidth, sideWidth + contentWidth + leftMargin) - ribbonWidth) + 'px; }'; + css += "\n"; + + var newStyle = document.createElement('style'); + newStyle.type = 'text/css'; + if (newStyle.styleSheet) { + newStyle.styleSheet.cssText = css; + } else { + newStyle.appendChild(document.createTextNode(css)); + } + + head.appendChild(newStyle); + style = newStyle; +} + +centerPage(); +window.addEventListener('resize', centerPage); +// Adjust the position of the 'fork me at GitHub' ribbon after document.body is available, +// so that we can calculate the width of the scroll bar correctly. +window.addEventListener('DOMContentLoaded', centerPage); diff --git a/_static/documentation_options.js b/_static/documentation_options.js index 1917f6b7a..a23d26df0 100644 --- a/_static/documentation_options.js +++ b/_static/documentation_options.js @@ -1,6 +1,6 @@ var DOCUMENTATION_OPTIONS = { URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), - VERSION: '3.0.0-SNAPSHOT', + VERSION: '3.0.1-RC-SNAPSHOT', LANGUAGE: 'zh_CN', COLLAPSE_INDEX: false, FILE_SUFFIX: '.html', diff --git a/_static/overrides.css b/_static/overrides.css new file mode 100644 index 000000000..bf8d988ad --- /dev/null +++ b/_static/overrides.css @@ -0,0 +1,250 @@ +@import url('https://cdnjs.cloudflare.com/ajax/libs/github-fork-ribbon-css/0.1.1/gh-fork-ribbon.min.css'); +@import url('https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,700,700i'); +@import url('https://fonts.googleapis.com/css?family=Inconsolata:400,700'); + +html, body, .wy-grid-for-nav { + font-family: 'Source Sans Pro', 'Helvetica', 'Arial', sans-serif; + font-weight: normal; + font-size: 15px; + line-height: 1.42857143; + background: #f0f0f0; + margin: 0; + word-break: break-word; +} + +.wy-nav-side { + font-size: 17px; +} + +.wy-nav-top { + line-height: 30px; +} + +.wy-nav-content-wrap { + background: #f0f0f0; +} + +.wy-nav-content { + background: white; + max-width: 800px; + margin: 0; +} + +.wy-nav-content p { + font-size: inherit; +} + +.wy-side-nav-search > a, .wy-side-nav-search .wy-dropdown > a { + font-weight: inherit; +} + +.wy-nav-top > a { + font-size: 125%; +} + +.wy-side-nav-search > a { + margin: 0; + display: block; +} + +.wy-side-nav-search > a img.logo { + max-width: 11.5em; + height: auto; + margin: 0 auto; + padding: 0; +} + +.wy-menu.wy-menu-vertical .slack-invitation, +.wy-menu.wy-menu-vertical .project-badges { + padding: 0.4em 1.45em 0 1.45em; + display: block; + position: relative; + line-height: 1em; +} + +.wy-menu.wy-menu-vertical .project-badges a { + display: inline; + padding: 0; +} + +.wy-menu.wy-menu-vertical .project-badges a:hover { + background: inherit; +} + +.wy-menu.wy-menu-vertical .project-badges img { + display: inline; + padding: 0; + height: 1.45em; +} + +/* Hide the Github fork ribbon on mobile view. */ +@media screen and (max-width: 768px) { + .github-fork-ribbon-wrapper { + display: none; + } +} + +/* Move the right-side breadcrumb a little bit left so that it does not overlap with the Github fork ribbom. */ +@media screen and (min-width: 769px) { + .wy-breadcrumbs-aside { + padding-right: 64px; + } +} + +.wy-breadcrumbs-aside { + margin-top: 0.225em; +} + +/* Make sure the invitation dialog appears on top of the menu whose z-index is 200. */ +.__slackin { + z-index: 1000; +} + +h1, h2, h3, h4, h5, h6 { + font-weight: inherit; +} + +/* Code blocks and literals */ +pre, code, kbd, var, samp, tt, +.rst-content div[class*='highlight'] pre, +.rst-content pre.literal-block, +.rst-content code.literal, +.rst-content tt.literal, +.wy-menu-vertical li code, +.wy-menu-vertical li tt { + font-family: 'Inconsolata', 'Consolas', 'Menlo', 'Monaco', 'Lucida Console', 'Liberation Mono', + 'DejaVu Sans Mono', monospace; + font-weight: inherit; + word-break: break-all; +} + +/* Code blocks */ +pre, +.rst-content div[class*='highlight'] pre, +.rst-content pre.literal-block { + padding: 8px 12px 12px 12px; + font-size: 90%; + overflow-x: auto; + overflow-y: hidden; + color: inherit; + + /* Not sure why, but horizontal scrollbar does not go away without this on Chrome Linux */ + width: 99.9%; +} + +/* Code block wrappers */ +.rst-content div[class*='highlight'] { + overflow: inherit; +} + +/* Literals */ +code, kbd, var, samp, tt, +tt.literal, .rst-content tt.literal, +code.literal, .rst-content code.literal { + padding-left: 0; + padding-right: 0; + background: rgba(0,0,0,0.05); + border-radius: 3px; + font-size: inherit; + color: inherit; + border: none; + white-space: pre-wrap; +} + +/* Literals in vertical menu */ +.wy-menu-vertical li tt, +.wy-menu-vertical li code { + padding-left: 0; + padding-right: 0; + font-size: inherit; + color: inherit; + border: none; + white-space: pre-wrap; +} + +/* Add small padding around a literal. */ +code::before, code::after, +kbd::before, kbd::after, +var::before, var::after, +samp::before, samp::after { + letter-spacing: -0.3em; + content: "\00a0"; +} + +/* Do not add small padding around a literal in vertical menu. */ +.wy-menu-vertical li tt::before, +.wy-menu-vertical li tt::after, +.wy-menu-vertical li code::before, +.wy-menu-vertical li code::after { + content: ""; +} + +h1, h2, h3, h4, h5, h6 { + font-family: 'Source Sans Pro', 'Helvetica', 'Arial', sans-serif; +} + +/* Use justify-align with hyphenation */ +p, .rst-content li { + text-align: justify; + word-wrap: break-word; + overflow-wrap: break-word; + hyphens: auto; +} + +/* Insert space for the nested list which comes after a paragraph. */ +.rst-content li > p + ul, +.rst-content li > p + ol { + padding-bottom: 1em; +} + +/* Do not insert bottom margin if it's the last child. */ +.rst-content li:last-child > .admonition:last-child { + margin-bottom: 0; +} + +/* Do not use monospace font for download links */ +.rst-content tt.download { + font-family: inherit; +} + +/* Adjust table width */ +.rst-content table.docutils, .rst-content table.field-list { + width: 100%; +} + +/* Adjust table padding */ +.rst-content table.docutils thead th, .rst-content table.docutils td, +.rst-content table.field-list thead th, .rst-content table.field-list td { + padding: 6px 10px; +} + +/* Adjust table header borders */ +.wy-table thead th, .rst-content table.docutils thead th, .rst-content table.field-list thead th { + border-left: solid 1px #e1e4e5; + border-right: solid 1px #e1e4e5; + border-bottom-width: 1px; +} + +/* Allow wrapping table content */ +.wy-table-responsive table td { + white-space: inherit; + word-wrap: break-word; + overflow-wrap: break-word; + hyphens: auto; + text-align: justify; +} + +/* Do not add left-margin for line-blocks */ +.rst-content .line-block { + margin-left: 0px; +} + +/* Adjust the height of the top navbar */ +.wy-nav-top { + line-height: 43px; +} + +/* Center the PlantUML diagrams */ +.plantuml { + text-align: center; +} diff --git a/advanced-use.html b/advanced-use.html new file mode 100644 index 000000000..889b9e8d3 --- /dev/null +++ b/advanced-use.html @@ -0,0 +1,344 @@ + + + + + + + + + + + 进阶使用 — Arthas 3.0.1-RC-SNAPSHOT 文档 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +
+

进阶使用

+
+

基础命令

+
    +
  • help——查看命令帮助信息
  • +
  • cls——清空当前屏幕区域
  • +
  • session——查看当前会话的信息
  • +
  • reset——重置增强类,将被 Arthas 增强过的类全部还原,Arthas 服务端关闭时会重置所有增强过的类
  • +
  • version——输出当前目标 Java 进程所加载的 Arthas 版本号
  • +
  • quit——退出当前 Arthas 客户端,其他 Arthas 客户端不受影响
  • +
  • shutdown——关闭 Arthas 服务端,所有 Arthas 客户端全部退出
  • +
  • keymap——Arthas快捷键列表及自定义快捷键
  • +
+
+
+

jvm相关

+
    +
  • dashboard——当前系统的实时数据面板
  • +
  • thread——查看当前 JVM 的线程堆栈信息
  • +
  • jvm——查看当前 JVM 的信息
  • +
  • sysprop——查看和修改JVM的系统属性
  • +
  • New! getstatic——查看类的静态属性
  • +
+
+
+

class/classloader相关

+
    +
  • sc——查看JVM已加载的类信息
  • +
  • sm——查看已加载类的方法信息
  • +
  • dump——dump 已加载类的 byte code 到特定目录
  • +
  • redefine——加载外部的.class文件,redefine到JVM里
  • +
  • jad——反编译指定已加载类的源码
  • +
  • classloader——查看classloader的继承树,urls,类加载信息,使用classloader去getResource
  • +
+
+
+

monitor/watch/trace相关

+
+
请注意,这些命令,都通过字节码增强技术来实现的,会在指定类的方法中插入一些切面来实现数据统计和观测,因此在线上、预发使用时,请尽量明确需要观测的类、方法以及条件,诊断结束要执行 shutdown 或将增强过的类执行 reset 命令。
+
    +
  • monitor——方法执行监控
  • +
  • watch——方法执行数据观测
  • +
  • trace——方法内部调用路径,并输出方法路径上的每个节点上耗时
  • +
  • stack——输出当前方法被调用的调用路径
  • +
  • tt——方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测
  • +
+
+
+

options

+
    +
  • options——查看或设置Arthas全局开关
  • +
+
+
+

管道

+

Arthas支持使用管道对上述命令的结果进行进一步的处理,如sm org.apache.log4j.Logger | grep <init>

+
    +
  • grep——搜索满足条件的结果
  • +
  • plaintext——将命令的结果去除颜色
  • +
  • wc——按行统计输出结果
  • +
+
+
+

后台异步任务

+

当线上出现偶发的问题,比如需要watch某个条件,而这个条件一天可能才会出现一次时,异步后台任务就派上用场了,详情请参考这里

+
    +
  • 使用 > 将结果重写向到日志文件,使用 & 指定命令是后台运行,session断开不影响任务执行(生命周期默认为1天)
  • +
  • jobs——列出所有job
  • +
  • kill——强制终止任务
  • +
  • fg——将暂停的任务拉到前台执行
  • +
  • bg——将暂停的任务放到后台执行
  • +
+
+ +
+ + +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/advice-class.html b/advice-class.html new file mode 100644 index 000000000..6ab26d0b5 --- /dev/null +++ b/advice-class.html @@ -0,0 +1,273 @@ + + + + + + + + + + + 表达式核心变量 — Arthas 3.0.1-RC-SNAPSHOT 文档 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +
+

表达式核心变量

+

无论是匹配表达式也好、观察表达式也罢,他们核心判断变量都是围绕着一个 Arthas 中的通用通知对象 Advice 进行。

+

它的简略代码结构如下

+
public class Advice {
+
+    private final ClassLoader loader;
+    private final Class<?> clazz;
+    private final ArthasMethod method;
+    private final Object target;
+    private final Object[] params;
+    private final Object returnObj;
+    private final Throwable throwExp;
+    private final boolean isBefore;
+    private final boolean isThrow;
+    private final boolean isReturn;
+    
+    // getter/setter  
+}  
+
+
+

这里列一个表格来说明不同变量的含义

+

|变量名|变量解释| +|—|—| +|loader|本次调用类所在的 ClassLoader| +|clazz|本次调用类的 Class 引用| +|method|本次调用方法反射引用| +|target|本次调用类的实例| +|params|本次调用参数列表,这是一个数组,如果方法是无参方法则为空数组| +|returnObj|本次调用返回的对象。当且仅当 isReturn==true 成立时候有效,表明方法调用是以正常返回的方式结束。如果当前方法无返回值 void,则值为 null| +|throwExp|本次调用抛出的异常。当且仅当 isThrow==true 成立时有效,表明方法调用是以抛出异常的方式结束。| +|isBefore|辅助判断标记,当前的通知节点有可能是在方法一开始就通知,此时 isBefore==true 成立,同时 isThrow==falseisReturn==false,因为在方法刚开始时,还无法确定方法调用将会如何结束。| +|isThrow|辅助判断标记,当前的方法调用以抛异常的形式结束。| +|isReturn|辅助判断标记,当前的方法调用以正常返回的形式结束。|

+

所有变量都可以在表达式中直接使用,如果在表达式中编写了不符合 OGNL 脚本语法或者引入了不在表格中的变量,则退出命令的执行;用户可以根据当前的异常信息修正条件表达式观察表达式

+
+
OGNL表达式官网:https://commons.apache.org/proper/commons-ognl/language-guide.html
+
+
一些特殊的用法:
+

TODO

+

middleware-container/arthas/issues/263

+
+ + +
+ +
+
+ + +
+ +
+

+ © Copyright 2018, Alibaba Middleware Group, and contributors. + +

+
+ Built with Sphinx using a theme provided by Read the Docs. + +
+ +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/arthas3.html b/arthas3.html new file mode 100644 index 000000000..e431b4048 --- /dev/null +++ b/arthas3.html @@ -0,0 +1,334 @@ + + + + + + + + + + + Arthas3.0的新特性 — Arthas 3.0.1-RC-SNAPSHOT 文档 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +
+

Arthas3.0的新特性

+
+

在线诊断功能

+

Arthas3.0中最重要的特性,不需要登陆机器就可以对应用进行诊断,体验和本地诊断完全一致

+
+

使用步骤

+

TODO

+
+
+

动图演示

+

TODO

+
+
+
+

管道支持

+

Arthas 3.0开始支持管道, 率先提供了grep,wc,plaintext的支持。

+
+
+
+

去groovy依赖

+

groovy表达式在arthas2.0中大量使用,例如watch表达式

+
watch com.alibaba.sample.petstore.web.store.module.screen.ItemList add "params + ' ' + returnObj" params.size()==2
+
+
+

其中"params + ' ' + returnObj"以及params.size()==2背后其实都使用了groovy来进行表达式求值,如果反复大量的运行这些表达式,groovy会创建大量的classloader,打满perm区从而触发FGC。

+

为了避免这个问题,Arthas 3.0中使用了ognl这个更加轻量的表达式求值库来代替groovy,彻底解决了groovy引起的FGC风险。但由于这个替换,导致原来使用groovy脚本编写的自定义脚本失效。这个问题留待后续解决。

+

在3.0中,watch命令的表达式部分的书写有了一些改变,详见这里

+
+

提升rt统计精度

+

Arthas 2.0中,统计rt都是以ms为单位,对于某些比较小的方法调用,耗时在毫秒以下的都会被认为是0ms,造成trace总时间和各方法的时间相加不一致等问题(虽然这里面确实会有误差,主要Arthas自身的开销)。Arthas 3.0中所有rt的单位统一改为使用ns来统计,精准捕获你的方法耗时,让0ms这样无意义的统计数据不再出现!

+
$ tt -l
+ INDEX     TIMESTAMP               COST(ms)    IS-RET    IS-EXP   OBJECT            CLASS                                METHOD
+------------------------------------------------------------------------------------------------------------------------------------------------------------
+ 1000      2017-02-24 10:56:46     808.743525  true      false    0x3bd5e918        TestTraceServlet                     doGet
+ 1001      2017-02-24 10:56:55     805.799155  true      false    0x3bd5e918        TestTraceServlet                     doGet
+ 1002      2017-02-24 10:57:04     808.026935  true      false    0x3bd5e918        TestTraceServlet                     doGet
+ 1003      2017-02-24 10:57:22     805.036963  true      false    0x3bd5e918        TestTraceServlet                     doGet
+ 1004      2017-02-24 10:57:24     803.581886  true      false    0x3bd5e918        TestTraceServlet                     doGet
+ 1005      2017-02-24 10:57:39     814.657657  true      false    0x3bd5e918        TestTraceServlet                     doGet
+
+
+
+
+

watch/stack/trace命令支持按耗时过滤

+

我们在trace的时候,经常会出现某个方法间隙性的rt飙高,但是我们只想知道rt高的时候,是哪里慢了,对于正常rt的方法我们并不关心,Arthas 3.0支持了按#cost(方法执行耗时,单位为ms)进行过滤,只输出符合条件的trace路径,目前,这三个命令的相关文档已经做了更新,增加了该用法的示例,请在这里查看。

+
+
+

sysprop命令操作SystemProperty

+

sysprop命令支持查看所有的系统属性,以及针对特定属性进行查看和修改。

+
$ sysprop
+...
+ os.arch                                              x86_64
+ java.ext.dirs                                        /Users/wangtao/Library/Java/Extensions:/Library/Java/JavaVirtualMachines/jdk1.
+                                                      8.0_51.jdk/Contents/Home/jre/lib/ext:/Library/Java/Extensions:/Network/Library
+                                                      /Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java
+ user.dir                                             /Users/wangtao/work/ali-tomcat-home/ant-develop/output/build
+ catalina.vendor                                      alibaba
+ line.separator
+
+ java.vm.name                                         Java HotSpot(TM) 64-Bit Server VM
+ file.encoding                                        UTF-8
+ org.apache.tomcat.util.http.ServerCookie.ALLOW_EQUA  true
+ LS_IN_VALUE
+ com.taobao.tomcat.info                               Apache Tomcat/7.0.70.1548
+ java.specification.version                           1.8
+$ sysprop java.version
+java.version=1.8.0_51
+$ sysprop production.mode true
+Successfully changed the system property.
+production.mode=true
+
+
+
+
+

thread命令支持指定采样时间

+

thread命令计算线程cpu占用的逻辑,默认是采样100ms内各个线程的cpu使用情况并计算cpu消耗占比。有时候100ms的时间间隔太短,看不出问题所在,Arthas3.0中thread命令支持设置采样间隔(以ms为单位),可以观察任意时间段内的cpu消耗占比情况。

+
$ thread -i 1000                                                                                                                                                                                                                     
+Threads Total: 74, NEW: 0, RUNNABLE: 17, BLOCKED: 0, WAITING: 15, TIMED_WAITING: 42, TERMINATED: 0                                                                                                                                   
+ID                 NAME                                                     GROUP                                  PRIORITY           STATE              %CPU               TIME               INTERRUPTED        DAEMON             
+78                 com.taobao.config.client.timer                           main                                   5                  TIMED_WAITING      22                 0:0                false              true               
+92                 Abandoned connection cleanup thread                      main                                   5                  TIMED_WAITING      15                 0:2                false              true               
+361                as-command-execute-daemon                                system                                 10                 RUNNABLE           14                 0:0                false              true               
+67                 HSF-Remoting-Timer-10-thread-1                           main                                   10                 TIMED_WAITING      12                 0:2                false              true               
+113                JamScheduleThread                                        system                                 9                  TIMED_WAITING      2                  0:0                false              true               
+14                 Thread-3                                                 main                                   5                  RUNNABLE           2                  0:0                false              false              
+81                 com.taobao.remoting.TimerThread                          main                                   5                  TIMED_WAITING      2                  0:0                false              true               
+104                http-bio-7001-AsyncTimeout                               main                                   5                  TIMED_WAITING      2                  0:0                false              true               
+123                nioEventLoopGroup-2-1                                    system                                 10                 RUNNABLE           2                  0:0                false              false              
+127                nioEventLoopGroup-3-2                                    system                                 10                 RUNNABLE           2                  0:0                false              false              
+345                nioEventLoopGroup-3-3                                    system                                 10                 RUNNABLE           2                  0:0                false              false              
+358                nioEventLoopGroup-3-4                                    system                                 10                 RUNNABLE           2                  0:0                false              false              
+27                 qos-boss-1-1                                             main                                   5                  RUNNABLE           2                  0:0                false              true               
+22                 EagleEye-AsyncAppender-Thread-BizLog                     main                                   5                  TIMED_WAITING      1                  0:0                false              true               
+
+
+
+
+

trace命令自动高亮显示最耗时方法调用

+

trace命令现在会自动显示

+

![Untitled2](TODO /Untitled2.gif)

+
+
+ + +
+ +
+
+ + +
+ +
+

+ © Copyright 2018, Alibaba Middleware Group, and contributors. + +

+
+ Built with Sphinx using a theme provided by Read the Docs. + +
+ +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/arthas_3_0/home.html b/arthas_3_0/home.html new file mode 100644 index 000000000..71ad3ce14 --- /dev/null +++ b/arthas_3_0/home.html @@ -0,0 +1,412 @@ + + + + + + + + + + + Arthas 3.0使用说明 — Arthas 3.0.1-RC-SNAPSHOT 文档 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +
+

Arthas 3.0使用说明

+
+

命令行诊断

+
    +
  1. 安装Arthas 3.0启动脚本

    +
    
    +
    +
    +
  2. +
+

curl -sLk http://TODO/arthas/install.sh | sh

+

+2. 可以直接运行`./as.sh`,启动脚本会自动更新到最新版本
+
+
+

➜ tmp ./as.sh +Found existing java process, please choose one and hit RETURN.

+
    +
  • [1]: 53090 org.apache.catalina.startup.Bootstrap +[2]: 50020 +[3]: 69893 org.jetbrains.idea.maven.server.RemoteMavenServer +[4]: 93320 org.jetbrains.jps.cmdline.Launcher +updating version 3.0.20170224142641 … +######################################################################## 100.0% +Archive: /var/tmp/temp_3.0.20170224142641_35932/arthas-3.0.20170224142641-bin.zip +creating: /var/tmp/temp_3.0.20170224142641_35932/arthas/ +inflating: /var/tmp/temp_3.0.20170224142641_35932/arthas/arthas-agent.jar +inflating: /var/tmp/temp_3.0.20170224142641_35932/arthas/arthas-client.jar +inflating: /var/tmp/temp_3.0.20170224142641_35932/arthas/arthas-core.jar +inflating: /var/tmp/temp_3.0.20170224142641_35932/arthas/arthas-spy.jar +inflating: /var/tmp/temp_3.0.20170224142641_35932/arthas/as.bat +inflating: /var/tmp/temp_3.0.20170224142641_35932/arthas/as.sh +inflating: /var/tmp/temp_3.0.20170224142641_35932/arthas/install-local.sh +update completed. +Calculating attach excecution time… +Attaching to 53090… +real 0m0.336s +user 0m0.498s +sys 0m0.075s +Attach success. +Connecting to arthas server… current timestamp is 1488178414 +Trying 127.0.0.1… +Connected to localhost. +Escape character is ‘^]’. +,—. ,——. ,——–.,–. ,–. ,—. ,—. +/ O \ | .–. ‘’–. .–’| ‘–’ | / O \ ‘ .-‘ +| .-. || ‘–’.’ | | | .–. || .-. |.-. +| | | || |\ \ | | | | | || | | |.-‘ | +--'–’--' '--'–’ --'–’--'–’`—–’ +wiki: https://github.com/alibaba/arthas/wiki/ +version: 3.0.20170227131708 +pid: 53090 +timestamp: 1488178414548
  • +
+

+### telnet远程诊断
+
+只要在上一步中启动了Arthas Server, 那么你可以直接在本地(针对日常环境的机器),或者是跳板机(针对预发和线上机器)上,通过telnet命令直接远程连上去诊断,使用上的体验完全一致。
+
+
+

➜ telnet 11.164.45.24 3658 +Trying 11.164.45.24… +Connected to 11.164.45.24. +Escape character is ‘^]’. +,—. ,——. ,——–.,–. ,–. ,—. ,—. +/ O \ | .–. ‘’–. .–’| ‘–’ | / O \ ‘ .-‘ +| .-. || ‘–’.’ | | | .–. || .-. |.-. +| | | || |\ \ | | | | | || | | |.-‘ | +--'–’--' '--'–’ --'–’--'–’`—–’

+

wiki: https://github.com/alibaba/arthas/wiki/home +version: 3.0.20170315140000 +pid: 1463 +timestamp: 1490938898194

+

$

+

+## 新特性介绍
+
+请参考[Arthas 3.0新特性](https://github.com/alibaba/arthas/wiki/arthas_3_0/new_feature)
+
+## FAQ
+
+首先请确保你的目标机器上,Arthas 2.0的server正常的shutdown了。否则,Arthas 3.0连上去之后不会正常启动。
+
+### 关于web console中文本的复制粘贴
+
+目前不同浏览器对复制粘贴的支持程度各不相同,mac下的Chrome是支持的最好的,目前的支持情况如下,我们正在想办法提供更好的复制粘贴体验
+
+<table border="1" class="docutils">
+<thead>
+<tr>
+<th>操作系统</th>
+<th>浏览器</th>
+<th>复制</th>
+<th>粘贴</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>macOS</td>
+<td>Chrome</td>
+<td>COMMAND-C,鼠标右键-复制</td>
+<td>COMMAND-V,鼠标右键-粘贴</td>
+</tr>
+<tr>
+<td>macOS</td>
+<td>Safari</td>
+<td>鼠标右键-复制</td>
+<td>鼠标右键-粘贴</td>
+</tr>
+<tr>
+<td>macOS</td>
+<td>Firefox</td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td>Windows</td>
+<td>Chrome</td>
+<td>Ctrl + C</td>
+<td>Ctrl + Shift + V</td>
+</tr>
+<tr>
+<td>Windows</td>
+<td>Firefox</td>
+<td></td>
+<td></td>
+</tr>
+</tbody>
+</table>
+
+### 关于字体大小
+
+如果觉得字体太小,可以通过浏览器内置的字体调整功能进行,web console支持自适应调整。
+
+<table border="1" class="docutils">
+<thead>
+<tr>
+<th>操作系统</th>
+<th>浏览器</th>
+<th>增大字体</th>
+<th>减小字体</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>macOS</td>
+<td>Chrome</td>
+<td>COMMAND加=</td>
+<td>COMMAND加-</td>
+</tr>
+<tr>
+<td>macOS</td>
+<td>Safari</td>
+<td>COMMAND加=</td>
+<td>COMMAND加-</td>
+</tr>
+<tr>
+<td>macOS</td>
+<td>Firefox</td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td>Windows</td>
+<td>Chrome</td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td>Windows</td>
+<td>Firefox</td>
+<td></td>
+<td></td>
+</tr>
+</tbody>
+</table>
+
+
+
+
+ + +
+ +
+
+ + +
+ +
+

+ © Copyright 2018, Alibaba Middleware Group, and contributors. + +

+
+ Built with Sphinx using a theme provided by Read the Docs. + +
+ +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/arthas_3_0/new_feature.html b/arthas_3_0/new_feature.html new file mode 100644 index 000000000..eca27cd44 --- /dev/null +++ b/arthas_3_0/new_feature.html @@ -0,0 +1,406 @@ + + + + + + + + + + + Arthas 3.0新特性介绍 — Arthas 3.0.1-RC-SNAPSHOT 文档 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +
+

Arthas 3.0新特性介绍

+

Arthas 3.0在架构上做了重大改造,通过引入termd完整的支持了telnet协议,并基于websocket封装了telnet协议实现了Telnet over HTTP,使得在线诊断成为了可能,并且保证了本地启动,telnet远程访问,在线诊断三种方式的体验完全一致。都支持自动补全,高亮显示等功能。并且支持多人同时在线诊断

+
+

在线诊断

+

Arthas 3.0最重要的特性,通过Arthas在线诊断平台,无需再登陆目标机器,一键启动Arthas并开启诊断!

+

![image](TODO image.png)

+

具体使用方法请参见在线诊断使用说明

+
+
+

管道支持

+

Arthas 3.0开始支持管道, 率先提供了grep,wc,plaintext的支持。

+
 java.vendor.url                                      http://java.oracle.com/
+ java.vm.vendor                                       Oracle Corporation
+ java.runtime.name                                    Java(TM) SE Runtime Environment
+ sun.java.command                                     org.apache.catalina.startup.Bootstrap start
+ java.class.path                                      /Users/wangtao/work/ali-tomcat-home/ant-develop/output/build/bin/bootstrap.jar
+ java.vm.specification.name                           Java Virtual Machine Specification
+ java.vm.specification.version                        1.8
+ java.awt.headless                                    true
+ java.io.tmpdir                                       /Users/wangtao/work/ali-tomcat-home/ant-develop/output/build/temp
+ java.vendor.url.bug                                  http://bugreport.sun.com/bugreport/
+ java.awt.graphicsenv                                 sun.awt.CGraphicsEnvironment
+ java.ext.dirs                                        /Users/wangtao/Library/Java/Extensions:/Library/Java/JavaVirtualMachines/jdk1.
+                                                      /Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java
+ java.vm.name                                         Java HotSpot(TM) 64-Bit Server VM
+ java.specification.version                           1.8
+$ sysprop | grep java | wc -l
+36
+
+
+
+
+

启动自检

+

针对启动时经常出现的权限问题,在启动脚本中增加了自检逻辑,脚本会自动判断目标进程是否具备attach权限,并给出进一步的提示。

+
[huxing.zhx@v125056161.bja /home/huxing.zhx]
+$./as.sh 32260
+The current user (huxing.zhx) does not match with the owner of process 32260 (admin).
+To solve this, choose one of the following command:
+  1) sudo su admin && ./as.sh
+  2) sudo -u admin -EH ./as.sh
+
+
+
+
+

去groovy依赖

+

groovy表达式在arthas2.0中大量使用,例如watch表达式

+
watch com.alibaba.sample.petstore.web.store.module.screen.ItemList add "params + ' ' + returnObj" params.size()==2
+
+
+

其中"params + ' ' + returnObj"以及params.size()==2背后其实都使用了groovy来进行表达式求值,如果反复大量的运行这些表达式,groovy会创建大量的classloader,打满perm区从而触发FGC。

+

为了避免这个问题,Arthas 3.0中使用了ognl这个更加轻量的表达式求值库来代替groovy,彻底解决了groovy引起的FGC风险。但由于这个替换,导致原来使用groovy脚本编写的自定义脚本失效。这个问题留待后续解决。

+

在3.0中,watch命令的表达式部分的书写有了一些改变,详见这里

+
+
+

提升rt统计精度

+

Arthas 2.0中,统计rt都是以ms为单位,对于某些比较小的方法调用,耗时在毫秒以下的都会被认为是0ms,造成trace总时间和各方法的时间相加不一致等问题(虽然这里面确实会有误差,主要Arthas自身的开销)。Arthas 3.0中所有rt的单位统一改为使用ns来统计,精准捕获你的方法耗时,让0ms这样无意义的统计数据不再出现!

+
$ tt -l
+ INDEX     TIMESTAMP               COST(ms)    IS-RET    IS-EXP   OBJECT            CLASS                                METHOD
+------------------------------------------------------------------------------------------------------------------------------------------------------------
+ 1000      2017-02-24 10:56:46     808.743525  true      false    0x3bd5e918        TestTraceServlet                     doGet
+ 1001      2017-02-24 10:56:55     805.799155  true      false    0x3bd5e918        TestTraceServlet                     doGet
+ 1002      2017-02-24 10:57:04     808.026935  true      false    0x3bd5e918        TestTraceServlet                     doGet
+ 1003      2017-02-24 10:57:22     805.036963  true      false    0x3bd5e918        TestTraceServlet                     doGet
+ 1004      2017-02-24 10:57:24     803.581886  true      false    0x3bd5e918        TestTraceServlet                     doGet
+ 1005      2017-02-24 10:57:39     814.657657  true      false    0x3bd5e918        TestTraceServlet                     doGet
+
+
+
+
+

watch/stack/trace命令支持按耗时过滤

+

我们在trace的时候,经常会出现某个方法间隙性的rt飙高,但是我们只想知道rt高的时候,是哪里慢了,对于正常rt的方法我们并不关心,Arthas 3.0支持了按#cost(方法执行耗时,单位为ms)进行过滤,只输出符合条件的trace路径。

+

具体用法为:

+
trace/watch/stack class_name method cost_expression
+
+
+

例如:

+
$ trace  test.arthas.TestTraceServlet doGet #cost>800
+Press Ctrl+C to abort.
+Affect(class-cnt:1 , method-cnt:1) cost in 137 ms.
+trace  test.arthas.TestTraceServlet doGet #cost>800
+`---thread_name=http-bio-8080-exec-9;id=6e;is_daemon=true;priority=5;TCCL=org.apache.catalina.loader.WebappClassLoader
+    `---[816.880001ms] test.arthas.TestTraceServlet:doGet()
+        +---[min=0.019223ms,max=1.192115ms,total=1.211338ms,count=2] java.lang.System:currentTimeMillis()
+        +---[1.407006ms] test.arthas.TestTraceServlet:call1()
+        +---[381.970892ms] test.arthas.TestTraceServlet:callhsfL1()
+        +---[0.018866ms] test.arthas.TestPathTrace:<init>()
+        +---[375.753301ms] test.arthas.TestPathTrace:callPathTrace()
+        +---[12.352252ms] test.arthas.TestTraceServlet:call3()
+        +---[2.758025ms] test.arthas.TestTraceServlet:call4()
+        +---[1.246057ms] test.arthas.TestTraceServlet:call5()
+        +---[10.306568ms] test.arthas.TestTraceServlet:call6()
+        +---[8.891933ms] test.arthas.TestTraceServlet:call7()
+        +---[4.030325ms] test.arthas.TestTraceServlet:call8()
+        +---[6.51316ms] test.arthas.TestTraceServlet:call9()
+        +---[0.059405ms] javax.servlet.http.HttpServletResponse:getWriter()
+        +---[0.013107ms] java.lang.StringBuilder:<init>()
+        +---[min=0.004892ms,max=0.06357ms,total=0.100672ms,count=3] java.lang.StringBuilder:append()
+        +---[0.018255ms] java.lang.StringBuilder:toString()
+        `---[0.028812ms] java.io.PrintWriter:write()
+
+
+

上述命令只有当test.arthas.TestTraceServlet#doGet方法执行耗时大于800ms时才会输出。

+
+
+

trace命令优化

+
+

自动高亮显示最耗时方法调用

+

trace命令现在会自动显示

+

image

+
+
+

带条件过滤的多级trace

+

目前trace默认只输出一级方法调用耗时,有时候并不能完全看出问题。但是如果展开多级的话,每一个方法的耗时都统计,会造成方法数量迅速膨胀,大大增加trace的开销。

+

TODO

+
+
+

显示当前线程的信息及eagleeye的traceId

+
trace  test.arthas.TestTraceServlet doGet
+`---thread_name=http-bio-8080-exec-10;id=da;is_daemon=true;priority=5;TCCL=org.apache.catalina.loader.WebappClassLoader;trace_id=1e09489014879085429791006d969d
+
+
+
+
+
+

sysprop命令操作SystemProperty

+

sysprop命令支持查看所有的系统属性,以及针对特定属性进行查看和修改。

+
$ sysprop
+...
+ os.arch                                              x86_64
+ java.ext.dirs                                        /Users/wangtao/Library/Java/Extensions:/Library/Java/JavaVirtualMachines/jdk1.
+                                                      8.0_51.jdk/Contents/Home/jre/lib/ext:/Library/Java/Extensions:/Network/Library
+                                                      /Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java
+ user.dir                                             /Users/wangtao/work/ali-tomcat-home/ant-develop/output/build
+ catalina.vendor                                      alibaba
+ line.separator
+
+ java.vm.name                                         Java HotSpot(TM) 64-Bit Server VM
+ file.encoding                                        UTF-8
+ org.apache.tomcat.util.http.ServerCookie.ALLOW_EQUA  true
+ LS_IN_VALUE
+ com.taobao.tomcat.info                               Apache Tomcat/7.0.70.1548
+ java.specification.version                           1.8
+$ sysprop java.version
+java.version=1.8.0_51
+$ sysprop production.mode true
+Successfully changed the system property.
+production.mode=true
+
+
+
+
+

thread命令支持指定采样时间

+

thread命令计算线程cpu占用的逻辑,默认是采样100ms内各个线程的cpu使用情况并计算cpu消耗占比。有时候100ms的时间间隔太短,看不出问题所在,Arthas3.0中thread命令支持设置采样间隔(以ms为单位),可以观察任意时间段内的cpu消耗占比情况。

+
$ thread -i 1000                                                                                                                                                                                                                     
+Threads Total: 74, NEW: 0, RUNNABLE: 17, BLOCKED: 0, WAITING: 15, TIMED_WAITING: 42, TERMINATED: 0                                                                                                                                   
+ID                 NAME                                                     GROUP                                  PRIORITY           STATE              %CPU               TIME               INTERRUPTED        DAEMON             
+78                 com.taobao.config.client.timer                           main                                   5                  TIMED_WAITING      22                 0:0                false              true               
+92                 Abandoned connection cleanup thread                      main                                   5                  TIMED_WAITING      15                 0:2                false              true               
+361                as-command-execute-daemon                                system                                 10                 RUNNABLE           14                 0:0                false              true               
+67                 HSF-Remoting-Timer-10-thread-1                           main                                   10                 TIMED_WAITING      12                 0:2                false              true               
+113                JamScheduleThread                                        system                                 9                  TIMED_WAITING      2                  0:0                false              true               
+14                 Thread-3                                                 main                                   5                  RUNNABLE           2                  0:0                false              false              
+81                 com.taobao.remoting.TimerThread                          main                                   5                  TIMED_WAITING      2                  0:0                false              true               
+104                http-bio-7001-AsyncTimeout                               main                                   5                  TIMED_WAITING      2                  0:0                false              true               
+123                nioEventLoopGroup-2-1                                    system                                 10                 RUNNABLE           2                  0:0                false              false              
+127                nioEventLoopGroup-3-2                                    system                                 10                 RUNNABLE           2                  0:0                false              false              
+345                nioEventLoopGroup-3-3                                    system                                 10                 RUNNABLE           2                  0:0                false              false              
+358                nioEventLoopGroup-3-4                                    system                                 10                 RUNNABLE           2                  0:0                false              false              
+27                 qos-boss-1-1                                             main                                   5                  RUNNABLE           2                  0:0                false              true               
+22                 EagleEye-AsyncAppender-Thread-BizLog                     main                                   5                  TIMED_WAITING      1                  0:0                false              true               
+
+
+
+
+ + +
+ +
+
+ + +
+ +
+

+ © Copyright 2018, Alibaba Middleware Group, and contributors. + +

+
+ Built with Sphinx using a theme provided by Read the Docs. + +
+ +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/async.html b/async.html new file mode 100644 index 000000000..1d5403c5d --- /dev/null +++ b/async.html @@ -0,0 +1,344 @@ + + + + + + + + + + + Arthas异步调用 — Arthas 3.0.1-RC-SNAPSHOT 文档 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +
+

Arthas异步调用

+

arthas中的异步调用,使用了仿linux系统任务相关的命令。linux任务相关介绍

+
+

1. 使用&在后台执行任务

+

比如希望执行后台执行trace命令,那么调用下面命令

+
trace Test t &  
+
+
+

这时命令在后台执行,可以在console中继续执行其他命令。

+
+
+

2. 通过jobs查看任务

+

如果希望查看当前有哪些arthas任务在执行,可以执行jobs命令,执行结果如下

+
$ jobs
+[10]*
+       Stopped           watch com.taobao.container.Test test "params[0].{? #this.name == null }" -x 2
+       execution count : 19
+       start time      : Fri Sep 22 09:59:55 CST 2017
+       timeout date    : Sat Sep 23 09:59:55 CST 2017
+       session         : 3648e874-5e69-473f-9eed-7f89660b079b (current)
+
+
+

可以看到目前有一个后台任务在执行。

+
    +
  • job id是10, * 表示此job是当前session创建
  • +
  • 状态是Stopped
  • +
  • execution count是执行次数,从启动开始已经执行了19次
  • +
  • timeout date是超时的时间,到这个时间,任务将会自动超时退出
  • +
+
+
+

3. 任务暂停和取消

+

当任务正在前台执行,比如直接调用命令trace Test t或者调用后台执行命令trace Test t &后又通过fg命令将任务转到前台。这时console中无法继续执行命令,但是可以接收并处理以下事件:

+
    +
  • ‘ctrl + z’:将任务暂停。通过jbos查看任务状态将会变为Stopped,通过bg <job-id>或者fg <job-id>可让任务重新开始执行
  • +
  • ‘ctrl + c’:停止任务
  • +
  • ‘ctrl + d’:按照linux语义应当是退出终端,目前arthas中是空实现,不处理
  • +
+
+
+

4. fg、bg命令,将命令转到前台、后台继续执行

+
    +
  • 任务在后台执行或者暂停状态(‘ctrl + z’暂停任务)时,执行fg <job-id>将可以把对应的任务转到前台继续执行。在前台执行时,无法在console中执行其他命令
  • +
  • 当任务处于暂停状态时(‘ctrl + z’暂停任务),执行bg <job-id>将可以把对应的任务在后台继续执行
  • +
  • 非当前session创建的job,只能由当前session fg到前台执行
  • +
+
+
+

5. 任务输出重定向

+

可通过>或者>>将任务输出结果输出到指定的文件中,可以和&一起使用,实现arthas命令的异步调用。比如:

+
$ trace Test t >> test.out &
+
+
+

这时trace命令会在后台执行,并且把结果输出到~/logs/arthas-cache/test.out。可继续执行其他命令。并可查看文件中的命令执行结果。

+

当远程调用时,可能无法确定机器文件路径,arthas同时支持了自动重定向到缓存路径。使用方法如下:

+
$ trace Test t >>  &
+job id  : 2
+cache location  : /Users/gehui/logs/arthas-cache/28198/2
+
+
+

可以看到并没有指定重定向文件位置,arthas自动重定向到缓存中了,执行命令后会输出job id和cache location。cache location就是重定向文件的路径,在系统logs目录下,路径包括pid和job id,避免和其他任务冲突。命令输出结果到/Users/gehui/logs/arthas-cache/28198/2中,job id为2。

+
+
+

6. 停止命令

+

异步执行的命令,如果希望停止,可执行kill <job-id>

+
+
+

7. 其他

+
    +
  • 最多同时支持8个命令使用重定向将结果写日志
  • +
  • 请勿同时开启过多的后台异步命令,以免对目标JVM性能造成影响
  • +
+
+
+ + +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/auto_structify.html b/auto_structify.html new file mode 100644 index 000000000..676dead3a --- /dev/null +++ b/auto_structify.html @@ -0,0 +1,450 @@ + + + + + + + + + + + AutoStructify Component — Arthas 3.0.1-RC-SNAPSHOT 文档 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +
+

AutoStructify Component

+

AutoStructify is a component in recommonmark that takes a parsed docutil AST by CommonMarkParser, +and transform it to another AST that introduces some of more. This enables additional features +of recommonmark syntax, to introduce more structure into the final generated document.

+
+

Configuring AutoStructify

+

The behavior of AutoStructify can be configured via a dict in document setting. +In sphinx, you can configure it by conf.py. The following snippet +is what is actually used to generate this document, see full code at conf.py.

+
github_doc_root = 'https://github.com/rtfd/recommonmark/tree/master/doc/'
+def setup(app):
+    app.add_config_value('recommonmark_config', {
+            'url_resolver': lambda url: github_doc_root + url,
+            'auto_toc_tree_section': 'Contents',
+            }, True)
+    app.add_transform(AutoStructify)
+
+
+
+

All the features are by default enabled

+

List of options

+
    +
  • enable_auto_toc_tree: whether enable Auto Toc Tree feature.
  • +
  • auto_toc_tree_section: when enabled, Auto Toc Tree will only be enabled on section that matches the title.
  • +
  • enable_auto_doc_ref: whether enable Auto Doc Ref feature. Deprecated
  • +
  • enable_math: whether enable Math Formula
  • +
  • enable_inline_math: whether enable Inline Math
  • +
  • enable_eval_rst: whether Embed reStructuredText is enabled.
  • +
  • url_resolver: a function that maps a existing relative position in the document to a http link
  • +
+
+
+

Auto Toc Tree

+

One of important command in tools like sphinx is toctree. This is a command to generate table of contents and +tell sphinx about the structure of the documents. In markdown, usually we manually list of contents by a bullet list +of url reference to the other documents.

+

AutoStructify will transforms bullet list of document URLs

+
* [Title1](doc1.md)
+* [Title2](doc2.md)
+
+
+

will be translated to the AST of following reStructuredText code

+
.. toctree::
+   :maxdepth: 1
+
+   doc1
+   doc2
+
+
+

You can also find the usage of this feature in index.md of this document.

+
+
+

Auto Doc Ref

+
+

注解

+

This option is deprecated. +This option has been superseded by the default linking behavior, which +will first try to resolve as an internal reference, and then as an +external reference.

+
+

It is common to refer to another document page in one document. We usually use reference to do that. +AutoStructify will translate these reference block into a structured document reference. For example

+
[API Reference](api_ref.md)
+
+
+

will be translated to the AST of following reStructuredText code

+
:doc:`API Reference </api_ref>`
+
+
+

And it will be rendered as API Reference

+
+
+

URL Resolver

+

Sometimes in a markdown, we want to refer to the code in the same repo. +This can usually be done by a reference by reference path. However, since the generated document is hosted elsewhere, +the relative path may not work in generated document site. URL resolver is introduced to solve this problem.

+

Basically, you can define a function that maps an relative path of document to the http path that you wish to link to. +For example, the setting mentioned in the beginning of this document used a resolver that maps the files to github. +So [parser code](../recommonmark/parser.py) will be translated into parser code

+

Note that the reference to the internal document will not be passed to url resolver, and will be linked to the internal document pages correctly, see Auto Doc Ref.

+
+
+

Codeblock Extensions

+

In markdown, you can write codeblocks fenced by (at least) three backticks +(```). The following is an example of codeblock.

+
``` language
+some code block
+```
+
+
+

Codeblock extensions are mechanism that specialize certain codeblocks to different render behaviors. +The extension will be trigger by the language argument to the codeblck

+
+

Syntax Highlight

+

You can highlight syntax of codeblocks by specifying the language you need. For example,

+
```python
+def function():
+    return True
+```
+
+
+

will be rendered as

+
def function():
+    return True
+
+
+
+
+

Math Formula

+

You can normally write latex math formula with math codeblock. See also Inline Math.

+

Example

+
```math
+E = m c^2
+```
+
+
+

will be rendered as

+
+\[E = m c^2 +\]
+
+
+

Embed reStructuredText

+

Recommonmark also allows embedding reStructuredText syntax in the codeblocks. +There are two styles for embedding reStructuredText. The first is enabled by eval_rst codeblock. The content of codeblock will be parsed as reStructuredText and insert into the document. This can be used to quickly introduce some of reStructuredText command that not yet available in markdown. For example,

+
```eval_rst
+.. autoclass:: recommonmark.transform.AutoStructify
+    :show-inheritance:
+```
+
+
+

will be rendered as

+
+
+class recommonmark.transform.AutoStructify(document, startnode=None)
+

基类:docutils.transforms.Transform

+

Automatically try to transform blocks to sphinx directives.

+

This class is designed to handle AST generated by CommonMarkParser.

+
+ +

This example used to use sphinx autodoc to insert document of AutoStructify class definition into the document.

+

The second style is a shorthand of the above style. It allows you to leave off the eval_rst .. portion and directly render directives. For example,

+
``` important:: Its a note! in markdown!
+```
+
+
+

will be rendered as

+

+
+
+
+

An Advanced Example

+
``` sidebar:: Line numbers and highlights
+
+     emphasis-lines:
+       highlights the lines.
+     linenos:
+       shows the line numbers as well.
+     caption:
+       shown at the top of the code block.
+     name:
+       may be referenced with `:ref:` later.
+```
+
+``` code-block:: markdown
+     :linenos:
+     :emphasize-lines: 3,5
+     :caption: An example code-block with everything turned on.
+     :name: Full code-block example
+
+     # Comment line
+     import System
+     System.run_emphasis_line
+     # Long lines in code blocks create a auto horizontal scrollbar
+     System.exit!
+```
+
+
+

will be rendered as

+

+    emphasis-lines:
+      highlights the lines.
+    linenos:
+      shows the line numbers as well.
+    caption:
+      shown at the top of the code block.
+    name:
+      may be referenced with `:ref:` later.
+
+
+
    :linenos:
+    :emphasize-lines: 3,5
+    :caption: An example code-block with everything turned on.
+    :name: Full code-block example
+
+    # Comment line
+    import System
+    System.run_emphasis_line
+    # Long lines in code blocks create a auto horizontal scrollbar
+    System.exit!
+
+
+

The <div style="clear: right;"></div> line clears the sidebar for the next title.

+
+
+
+
+

Inline Math

+

Besides the Math Formula, you can also write latex math in inline codeblock text. You can do so by inserting \(\) +in the beginning and end of inline codeblock.

+

Example

+
This formula `$ y=\sum_{i=1}^n g(x_i) $`
+
+
+

will be rendered as:

+

This formula \( y=\sum_{i=1}^n g(x_i) \)

+
+
+ + +
+ +
+
+ + +
+ +
+

+ © Copyright 2018, Alibaba Middleware Group, and contributors. + +

+
+ Built with Sphinx using a theme provided by Read the Docs. + +
+ +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/batch-support.html b/batch-support.html new file mode 100644 index 000000000..768235e40 --- /dev/null +++ b/batch-support.html @@ -0,0 +1,305 @@ + + + + + + + + + + + 批处理功能 — Arthas 3.0.1-RC-SNAPSHOT 文档 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +
+

批处理功能

+
+
通过批处理功能,arthas支持一次性批量运行多个命令,并取得命令执行的结果。
+
+

使用方法

+
+

第一步: 创建你的批处理脚本

+

这里我们新建了一个test.as脚本,为了规范,我们采用了.as后缀名,但事实上任意的本文文件都ok。

+
+

注意事项

+
    +
  • 目前需要每个命令占一行
  • +
  • dashboard务必开启批处理模式(-b),指定执行次数(-n),否则会导致批处理脚本无法终止
  • +
  • watch/tt/trace/monitor/stack等命令务必指定执行次数(-n),否则会导致批处理脚本无法终止
  • +
  • 可以使用异步后台任务,如 watch c.t.X test returnObj > &,让命令一直在后台运行,通过日志获取结果,获取更多异步任务的信息
  • +
+
+
➜  arthas git:(develop) cat /var/tmp/test.as
+help
+dashboard -b -n 1
+session
+thread
+sc -d org.apache.commons.lang.StringUtils
+
+
+
+
+

第二步: 运行你的批处理脚本

+

通过-b开启批处理模式, -f执行脚本文件, 批处理脚本默认会输出到标准输出中,可以将结果重定向到文件中。

+
./as.sh -b -f /var/tmp/test.as 56328 > test.out
+
+
+
+
+

第三步: 查看运行结果

+
cat test.out
+
+
+
+
+
+ + +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/classloader.html b/classloader.html new file mode 100644 index 000000000..df481afb4 --- /dev/null +++ b/classloader.html @@ -0,0 +1,419 @@ + + + + + + + + + + + classloader — Arthas 3.0.1-RC-SNAPSHOT 文档 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +
+

classloader

+
+
查看classloader的继承树,urls,类加载信息
+

classloader 命令将 JVM 中所有的classloader的信息统计出来,并可以展示继承树,urls等。

+

可以让指定的classloader去getResources,打印出所有查找到的resources的url。对于ResourceNotFoundException比较有用。

+
+

参数说明

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
参数名称参数说明
[l]按类加载实例进行统计
[t]打印所有ClassLoader的继承树
[a]列出所有ClassLoader加载的类,请谨慎使用
[c:]ClassLoader的hashcode
[c: r:]用ClassLoader去查找resource
### 使用参考
    +
  • 按类加载类型查看统计信息
  • +
+
$ classloader
+ name                                                   numberOfInstances  loadedCountTotal
+ com.taobao.pandora.service.loader.ModuleClassLoader    29                 11659
+ com.taobao.pandora.boot.loader.ReLaunchURLClassLoader  1                  5308
+ BootstrapClassLoader                                   1                  3711
+ com.taobao.arthas.agent.ArthasClassloader              2                  2825
+ sun.reflect.DelegatingClassLoader                      332                332
+ java.net.URLClassLoader                                1                  285
+ sun.misc.Launcher$AppClassLoader                       1                  77
+ sun.misc.Launcher$ExtClassLoader                       1                  46
+ com.alibaba.fastjson.util.ASMClassLoader               2                  3
+ org.jvnet.hk2.internal.DelegatingClassLoader           2                  2
+ sun.reflect.misc.MethodUtil                            1                  1
+Affect(row-cnt:11) cost in 66 ms.
+
+
+
    +
  • 按类加载实例查看统计信息
  • +
+
$ classloader -l
+ name                                                            loadedCount  hash      parent
+ BootstrapClassLoader                                            3711         null      null
+ com.alibaba.fastjson.util.ASMClassLoader@3bbaa1b8               2            3bbaa1b8  monitor's ModuleClassLoader
+ com.alibaba.fastjson.util.ASMClassLoader@5e255d0b               1            5e255d0b  eagleeye-core's ModuleClassLoader
+ com.taobao.arthas.agent.ArthasClassloader@4fa2d7e6              1795         4fa2d7e6  sun.misc.Launcher$ExtClassLoader@a38d7a3
+ com.taobao.arthas.agent.ArthasClassloader@522400c2              1033         522400c2  sun.misc.Launcher$ExtClassLoader@a38d7a3
+ com.taobao.pandora.boot.loader.ReLaunchURLClassLoader@1817d444  5308         1817d444  sun.misc.Launcher$AppClassLoader@14dad5dc
+ tbsession's ModuleClassLoader                                   285          609cd4d8  null
+ pandora-qos-service's ModuleClassLoader                         267          2f8dad04  null
+ pandora-framework's ModuleClassLoader                           78           4009e306  null
+ filesync-client's ModuleClassLoader                             4            4b8ee4de  null
+ rocketmq-client's ModuleClassLoader                             431          247bddad  null
+ eagleeye-core's ModuleClassLoader                               451          1ba9117e  null
+ alimonitor-jmonitor's ModuleClassLoader                         134          22fcf7ab  null
+ metaq-client's ModuleClassLoader                                35           41a2befb  null
+ hsf-mock's ModuleClassLoader                                    3            2002fc1d  null
+ monitor's ModuleClassLoader                                     1427         131ef10   null
+ spas-sdk-service's ModuleClassLoader                            7            10d307f1  null
+ vipserver-client's ModuleClassLoader                            137          7a419da4  null
+ metrics's ModuleClassLoader                                     146          696da30b  null
+ mtop-uncenter's ModuleClassLoader                               922          79d8407f  null
+ spas-sdk-client's ModuleClassLoader                             235          4944252c  null
+ live-profiler-pandora's ModuleClassLoader                       1            6913c1fb  null
+ notify-tr-client's ModuleClassLoader                            472          fba92d3   null
+ ons-sdk's ModuleClassLoader                                     70           23348b5d  null
+ tair-plugin's ModuleClassLoader                                 1053         7c9d8e2   null
+ tddl-client's ModuleClassLoader                                 2354         4988d8b8  null
+ config-client's ModuleClassLoader                               93           429bffaa  null
+ diamond-client's ModuleClassLoader                              360          3d5c822d  null
+ pandolet's ModuleClassLoader                                    99           41e1e210  null
+ hsf's ModuleClassLoader                                         1796         3232a28a  null
+ acl.plugin's ModuleClassLoader                                  379          67080771  null
+ buc.sso.client.plugin's ModuleClassLoader                       195          13b6aecc  null
+ unitrouter's ModuleClassLoader                                  64           7e5afaa6  null
+ switch's ModuleClassLoader                                      104          24313fcc  null
+ hsf-notify-client's ModuleClassLoader                           57           4d0f2471  null
+ java.net.URLClassLoader@7ec7ffd3                                285          7ec7ffd3  sun.misc.Launcher$ExtClassLoader@a38d7a3
+ javax.management.remote.rmi.NoCallStackClassLoader@53f65459     1            53f65459  null
+ javax.management.remote.rmi.NoCallStackClassLoader@2833cc44     1            2833cc44  null
+ org.jvnet.hk2.internal.DelegatingClassLoader@72cda8ee           1            72cda8ee  monitor's ModuleClassLoader
+ org.jvnet.hk2.internal.DelegatingClassLoader@1f57f96d           1            1f57f96d  monitor's ModuleClassLoader
+ sun.misc.Launcher$AppClassLoader@14dad5dc                       77           14dad5dc  sun.misc.Launcher$ExtClassLoader@a38d7a3
+ sun.misc.Launcher$ExtClassLoader@a38d7a3                        46           a38d7a3   null
+ sun.reflect.misc.MethodUtil@1201f221                            1            1201f221  sun.misc.Launcher$AppClassLoader@14dad5dc
+
+
+
    +
  • 查看ClassLoader的继承树
  • +
+
$ classloader -t
++-BootstrapClassLoader
++-unitrouter's ModuleClassLoader
++-diamond-client's ModuleClassLoader
++-sun.misc.Launcher$ExtClassLoader@548a102f
+| +-sun.misc.Launcher$AppClassLoader@14dad5dc
+|   +-com.taobao.arthas.agent.AgentLauncher$1@334e6bb8
+|   | +-sun.reflect.DelegatingClassLoader@328b3a05
+|   | +-sun.reflect.DelegatingClassLoader@73f44f24
+
+
+
    +
  • 查看URLClassLoader实际的urls
  • +
+
$ classloader -c 5ffe9775
+file:/Users/hello/soft/taobao-tomcat-7.0.64/deploy/taobao-hsf.sar/lib/commons-lang-2.6.jar
+file:/Users/hello/soft/taobao-tomcat-7.0.64/deploy/taobao-hsf.sar/lib/log4j-1.2.16.jar
+file:/Users/hello/soft/taobao-tomcat-7.0.64/deploy/taobao-hsf.sar/lib/logger.api-0.1.4.jar
+file:/Users/hello/soft/taobao-tomcat-7.0.64/deploy/taobao-hsf.sar/lib/pandora.api-2.0.7-SNAPSHOT.jar
+file:/Users/hello/soft/taobao-tomcat-7.0.64/deploy/taobao-hsf.sar/lib/pandora.container-2.0.7-SNAPSHOT.jar
+file:/Users/hello/soft/taobao-tomcat-7.0.64/deploy/taobao-hsf.sar/lib/pandora.thirdcontainer-2.0.7-SNAPSHOT.jar
+file:/Users/hello/soft/taobao-tomcat-7.0.64/deploy/taobao-hsf.sar/lib/picocontainer-2.14.3.jar
+
+
+
    +
  • 使用ClassLoader去查找resource
  • +
+
$ classloader -c 226b143b -r META-INF/MANIFEST.MF
+ jar:file:/Users/hello/.m2/repository/javax/enterprise/cdi-api/1.0/cdi-api-1.0.jar!/META-INF/MANIFEST.MF
+ jar:file:/Users/hello/.m2/repository/javax/annotation/jsr250-api/1.0/jsr250-api-1.0.jar!/META-INF/MANIFEST.MF
+
+
+

也可以尝试查找类的class文件:

+
$ classloader -c 1b6d3586 -r java/lang/String.class
+ jar:file:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/rt.jar!/java/lang/String.class
+
+
+
+
+ + +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/commands.html b/commands.html new file mode 100644 index 000000000..e7c1341b4 --- /dev/null +++ b/commands.html @@ -0,0 +1,299 @@ + + + + + + + + + + + 命令列表 — Arthas 3.0.1-RC-SNAPSHOT 文档 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +
+

命令列表

+ +
+

Arthas 基础命令

+
    +
  • help——查看命令帮助信息
  • +
  • cls——清空当前屏幕区域
  • +
  • session——查看当前会话的信息
  • +
  • reset——重置增强类,将被 Arthas 增强过的类全部还原,Arthas 服务端关闭时会重置所有增强过的类
  • +
  • version——输出当前目标 Java 进程所加载的 Arthas 版本号
  • +
  • quit——退出当前 Arthas 客户端,其他 Arthas 客户端不受影响
  • +
  • shutdown——关闭 Arthas 服务端,所有 Arthas 客户端全部退出
  • +
  • keymap——Arthas快捷键列表及自定义快捷键
  • +
+
+
+ + +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dashboard.html b/dashboard.html new file mode 100644 index 000000000..0b96807f5 --- /dev/null +++ b/dashboard.html @@ -0,0 +1,332 @@ + + + + + + + + + + + dashboard — Arthas 3.0.1-RC-SNAPSHOT 文档 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +
+

dashboard

+
+
当前系统的实时数据面板,按 ctrl+c 退出。
+

当运行在Ali-tomcat时,会显示当前tomcat的实时信息,如HTTP请求的qps, rt, 错误数, 线程池信息等等。

+
+

使用参考

+
$ dashboard
+ID         NAME                              GROUP                  PRIORITY   STATE       %CPU       TIME       INTERRUPTED DAEMON
+889        RMI TCP Connection(15)-30.10.166. RMI Runtime            9          RUNNABLE    48         0:5        false       true
+1077       Timer-for-arthas-dashboard-0      system                 9          RUNNABLE    24         0:0        false       true
+1074       as-selector-daemon                system                 9          RUNNABLE    12         0:0        false       true
+284        JMX server connection timeout 284 RMI Runtime            9          TIMED_WAITI 8          0:3        false       true
+16         Timer-1                           main                   5          TIMED_WAITI 5          0:9        false       true
+47         Pandora pandora-qos-reporter Pool main                   5          TIMED_WAITI 0          0:0        false       true
+48         JmonitorClient-CheckThread Pool [ main                   5          TIMED_WAITI 0          0:0        false       true
+49         JmonitorClient-HeartBeat Pool [Th main                   5          TIMED_WAITI 0          0:0        false       true
+50         JmonitorClient-ReaderThread Pool  main                   5          TIMED_WAITI 0          0:0        false       true
+957        RMI TCP Connection(16)-30.10.166. RMI Runtime            9          RUNNABLE    0          0:2        false       true
+51         JmonitorClient-WriterThread Pool  main                   5          TIMED_WAITI 0          0:0        false       true
+52         ContainerBackgroundProcessor[Stan main                   5          TIMED_WAITI 0          0:0        false       true
+53         http-bio-8080-Acceptor-0          main                   5          RUNNABLE    0          0:2        false       true
+54         http-bio-8080-AsyncTimeout        main                   5          TIMED_WAITI 0          0:0        false       true
+11         GC Daemon                         system                 2          TIMED_WAITI 0          0:0        false       true
+Memory                       used      total     max      usage     GC
+heap                         59M       223M      1820M    3.26%     gc.ps_scavenge.count              118
+ps_eden_space                14M       114M      668M     2.11%     gc.ps_scavenge.time(ms)           1890
+ps_survivor_space            6M        6M        6M       96.08%    gc.ps_marksweep.count             5
+ps_old_gen                   39M       103M      1365M    2.86%     gc.ps_marksweep.time(ms)          1140
+nonheap                      234M      240M      0M       97.46%
+code_cache                   46M       47M       240M     19.49%
+metaspace                    167M      172M      0M       97.36%
+Runtime                                                             Tomcat
+os.name                           Mac OS X                          connector                         http-bio-8080
+os.version                        10.10.5                           QPS                               0.00
+java.version                      1.8.0_60                          RT(ms)                            1.13
+java.home                                                           error/s                           0.00
+                                                                    received/s                        0B
+systemload.average                3.44                              sent/s                            0B
+processors                        4                                 threadpool                        http-bio-8080
+uptime                            16020s                            busy                              0
+
+
+
+
+

数据说明

+
    +
  • ID: Java级别的线程ID,注意这个ID不能跟jstack中的nativeID一一对应
  • +
  • NAME: 线程名
  • +
  • GROUP: 线程组名
  • +
  • PRIORITY: 线程优先级, 1~10之间的数字,越大表示优先级越高
  • +
  • STATE: 线程的状态
  • +
  • CPU%: 线程消耗的cpu占比,采样100ms,将所有线程在这100ms内的cpu使用量求和,再算出每个线程的cpu使用占比。
  • +
  • TIME: 线程运行总时间,数据格式为分:秒
  • +
  • INTERRUPTE: 线程当前的中断位状态
  • +
  • DAEMON: 是否是daemon线程
  • +
+
+
+

截图展示

+

alt text

+
+
+ + +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dump.html b/dump.html new file mode 100644 index 000000000..63ca43da4 --- /dev/null +++ b/dump.html @@ -0,0 +1,325 @@ + + + + + + + + + + + dump — Arthas 3.0.1-RC-SNAPSHOT 文档 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +
+

dump

+
+
dump 已加载类的 bytecode 到特定目录
+
+

参数说明

+ + + + + + + + + + + + + + + + + + + + + +
参数名称参数说明
class-pattern类名表达式匹配
[c:]类所属 ClassLoader 的 hashcode
[E]开启正则表达式匹配,默认为通配符匹配
+
+

使用参考

+
$ dump -E org\.apache\.commons\.lang\.StringUtils
+ HASHCODE  CLASSLOADER                                                        LOCATION
+ 29505d69  +-tddl-client's ModuleClassLoader                                  /Users/zhuyong/middleware/taobao-tomcat/output/build/bin/classdump/com.taobao.pandora
+                                                                              .service.loader.ModuleClassLoader-29505d69/org.apache.commons.lang.StringUtils.class
+ 6e51ad67  +-java.net.URLClassLoader@6e51ad67                                 /Users/zhuyong/middleware/taobao-tomcat/output/build/bin/classdump/java.net.URLClassL
+             +-sun.misc.Launcher$AppClassLoader@6951a712                      oader-6e51ad67/org.apache.commons.lang.StringUtils.class
+               +-sun.misc.Launcher$ExtClassLoader@6fafc4c2
+ 2bdd9114  +-pandora-qos-service's ModuleClassLoader                          /Users/zhuyong/middleware/taobao-tomcat/output/build/bin/classdump/com.taobao.pandora
+                                                                              .service.loader.ModuleClassLoader-2bdd9114/org.apache.commons.lang.StringUtils.class
+ 544dc9ba  +-com.taobao.tomcat.container.context.loader.AliWebappClassLoader  /Users/zhuyong/middleware/taobao-tomcat/output/build/bin/classdump/com.taobao.tomcat.
+             +-org.apache.catalina.loader.StandardClassLoader@2302e984        container.context.loader.AliWebappClassLoader-544dc9ba/org.apache.commons.lang.String
+               +-sun.misc.Launcher$AppClassLoader@6951a712                    Utils.class
+                 +-sun.misc.Launcher$ExtClassLoader@6fafc4c2
+ 22880c2b  +-java.net.URLClassLoader@22880c2b                                 /Users/zhuyong/middleware/taobao-tomcat/output/build/bin/classdump/java.net.URLClassL
+             +-sun.misc.Launcher$AppClassLoader@6951a712                      oader-22880c2b/org.apache.commons.lang.StringUtils.class
+               +-sun.misc.Launcher$ExtClassLoader@6fafc4c2
+Affect(row-cnt:5) cost in 156 ms.
+$ dump -E org\.apache\.commons\.lang\.StringUtils -c 22880c2b
+ HASHCODE  CLASSLOADER                                      LOCATION
+ 22880c2b  +-java.net.URLClassLoader@22880c2b               /Users/zhuyong/middleware/taobao-tomcat/output/build/bin/classdump/java.net.URLClassLoader-22880c2b/org
+             +-sun.misc.Launcher$AppClassLoader@6951a712    .apache.commons.lang.StringUtils.class
+               +-sun.misc.Launcher$ExtClassLoader@6fafc4c2
+Affect(row-cnt:1) cost in 67 ms.
+
+
+
+
+ + +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/genindex.html b/genindex.html index 1705d548c..d9a805f3b 100644 --- a/genindex.html +++ b/genindex.html @@ -9,7 +9,7 @@ - 索引 — Arthas 3.0.0-SNAPSHOT 文档 + 索引 — Arthas 3.0.1-RC-SNAPSHOT 文档 @@ -27,8 +27,12 @@ + - + + + + @@ -57,7 +61,7 @@
- 3.0.0-SNAPSHOT + 3.0.1-RC-SNAPSHOT
@@ -81,8 +85,18 @@ - -
+ + @@ -132,6 +146,10 @@
  • + + Edit on GitHub + +
  • @@ -147,8 +165,17 @@

    索引

    + A
    +

    A

    + + +
    + @@ -183,7 +210,7 @@ + + + + + + \ No newline at end of file diff --git a/getstatic.html b/getstatic.html new file mode 100644 index 000000000..5b090a45f --- /dev/null +++ b/getstatic.html @@ -0,0 +1,284 @@ + + + + + + + + + + + getstatic — Arthas 3.0.1-RC-SNAPSHOT 文档 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + +
    + + + + + +
    + +
    + + + + + + + + + + + + + + + + + +
    + + + + +
    +
    +
    +
    + +
    +

    getstatic

    +

    通过getstatic命令可以方便的查看类的静态属性。使用方法为getstatic class_name field_name

    +

    如果该静态属性是一个复杂对象,还可以支持在该属性上通过ognl表示进行遍历,过滤,访问对象的内部属性等操作。

    +

    例如,假设n是一个Map,Map的Key是一个Enum,我们想过滤出Map中Key为某个Enum的值,可以写如下命令

    +
    $ getstatic com.alibaba.arthas.Test n 'entrySet().iterator.{? #this.key.name()=="STOP"}'
    +field: n
    +@ArrayList[
    +    @Node[STOP=bbb],
    +]
    +Affect(row-cnt:1) cost in 68 ms.
    +
    +$ getstatic com.alibaba.arthas.Test m 'entrySet().iterator.{? #this.key=="a"}'
    +field: m
    +@ArrayList[
    +    @Node[a=aaa],
    +]
    +
    +
    +
    + + +
    + +
    + + +
    +
    + +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/groovy.html b/groovy.html new file mode 100644 index 000000000..680f9ef21 --- /dev/null +++ b/groovy.html @@ -0,0 +1,424 @@ + + + + + + + + + + + groovy — Arthas 3.0.1-RC-SNAPSHOT 文档 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + +
    + + + + + +
    + +
    + + + + + + + + + + + + + + + + + +
    + + + + +
    +
    +
    +
    + +
    +

    groovy

    +
    +
    Arthas 支持 groovy 脚本增强,允许像 BTrace 一样编写脚本来解决问题,可以在 groovy 脚本中进行if/for/switch/while 等控制语句,不受限制,但相比 BTrace 而言拥有更多的限制范围。
    +
    +

    限制内容

    +
      +
    1. 禁止改变原有逻辑,与 watch 等命令一样,重点保证的是监听和观察。
    2. +
    3. 只允许在方法的 before/success/exception/finish 四个环节进行监听。
    4. +
    +
    +
    +

    参数说明

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数名称参数说明
    class-pattern类名表达式匹配
    method-pattern方法名表达式匹配
    script-filepathgroovy 脚本的绝对路径
    [S]匹配所有的子类
    [E]开启正则表达式匹配,默认为通配符匹配
      +
    • 需要说明的是,第三个输入参数是脚本的绝对路径,比如 /tmp/test.js,不建议输入相对路径,比如 ./test.js
    • +
    +
    +
    +

    五个关键函数声明

    +
    /**
    + * 增强脚本监听器
    + */
    +interface ScriptListener {
    +
    +    /**
    +     * 脚本创建
    +     *
    +     * @param output 输出器
    +     */
    +    void create(Output output);
    +
    +    /**
    +     * 脚本销毁
    +     *
    +     * @param output 输出器
    +     */
    +    void destroy(Output output);
    +
    +    /**
    +     * 方法执行前
    +     *
    +     * @param output 输出器
    +     * @param advice 通知点
    +     */
    +    void before(Output output, Advice advice);
    +
    +    /**
    +     * 方法正常返回
    +     *
    +     * @param output 输出器
    +     * @param advice 通知点
    +     */
    +    void afterReturning(Output output, Advice advice);
    +
    +    /**
    +     * 方法异常返回
    +     *
    +     * @param output 输出器
    +     * @param advice 通知点
    +     */
    +    void afterThrowing(Output output, Advice advice);
    +
    +}
    +
    +
    +
    +
    +

    参数 Advice 说明

    +

    Advice 参数最主要是封装了通知节点的所有信息。参考表达式核心变量中关于该节点的描述。

    +
    +
    +

    参数 Output 说明

    +

    Output 参数只拥有三个方法,主要的工作还是输出对应的文本信息

    +
    /**
    + * 输出器
    + */
    +interface Output {
    +
    +    /**
    +     * 输出字符串(不换行)
    +     *
    +     * @param string 待输出字符串
    +     * @return this
    +     */
    +    Output print(String string);
    +
    +    /**
    +     * 输出字符串(换行)
    +     *
    +     * @param string 待输出字符串
    +     * @return this
    +     */
    +    Output println(String string);
    +
    +    /**
    +     * 结束当前脚本
    +     *
    +     * @return this
    +     */
    +    Output finish();
    +
    +}
    +
    +
    +
    +
    +

    一个输出日志的 groovy 脚本示例

    +
    import com.taobao.arthas.core.command.ScriptSupportCommand
    +import com.taobao.arthas.core.util.Advice
    +
    +import static java.lang.String.format
    +
    +/**
    + * 输出方法日志
    + */
    +public class Logger implements ScriptSupportCommand.ScriptListener {
    +
    +    @Override
    +    void create(ScriptSupportCommand.Output output) {
    +        output.println("script create.");
    +    }
    +
    +    @Override
    +    void destroy(ScriptSupportCommand.Output output) {
    +        output.println("script destroy.");
    +    }
    +
    +    @Override
    +    void before(ScriptSupportCommand.Output output, Advice advice) {
    +        output.println(format("before:class=%s;method=%s;paramslen=%d;%s;",
    +                advice.getClazz().getSimpleName(),
    +                advice.getMethod().getName(),
    +                advice.getParams().length, advice.getParams()))
    +    }
    +
    +    @Override
    +    void afterReturning(ScriptSupportCommand.Output output, Advice advice) {
    +        output.println(format("returning:class=%s;method=%s;",
    +                advice.getClazz().getSimpleName(),
    +                advice.getMethod().getName()))
    +    }
    +
    +    @Override
    +    void afterThrowing(ScriptSupportCommand.Output output, Advice advice) {
    +        output.println(format("throwing:class=%s;method=%s;",
    +                advice.getClazz().getSimpleName(),
    +                advice.getMethod().getName()))
    +    }
    +}
    +
    +
    +

    使用示例:

    +
    $ groovy com.alibaba.sample.petstore.dal.dao.ProductDao getProductById /Users/zhuyong/middleware/arthas/scripts/Logger.groovy -S
    +script create.
    +Press Ctrl+C to abort.
    +Affect(class-cnt:1 , method-cnt:1) cost in 102 ms.
    +before:class=IbatisProductDao;method=getProductById;paramslen=1;[Ljava.lang.Object;@45df64fc;
    +returning:class=IbatisProductDao;method=getProductById;
    +before:class=IbatisProductDao;method=getProductById;paramslen=1;[Ljava.lang.Object;@5b0e2d00;
    +returning:class=IbatisProductDao;method=getProductById;
    +
    +
    +
    +
    + + +
    + +
    +
    + + +
    + +
    +

    + © Copyright 2018, Alibaba Middleware Group, and contributors. + +

    +
    + Built with Sphinx using a theme provided by Read the Docs. + +
    + +
    +
    + +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/index.html b/index.html index c39e35ad0..3853b77ed 100644 --- a/index.html +++ b/index.html @@ -8,7 +8,7 @@ - Arthas — Arthas 3.0.0-SNAPSHOT 文档 + Arthas 用户文档 — Arthas 3.0.1-RC-SNAPSHOT 文档 @@ -26,8 +26,13 @@ + - + + + + + @@ -56,7 +61,7 @@
    - 3.0.0-SNAPSHOT + 3.0.1-RC-SNAPSHOT
    @@ -80,11 +85,18 @@ - - + @@ -128,13 +140,15 @@
  • Docs »
  • -
  • Arthas
  • +
  • Arthas 用户文档
  • - View page source + + Edit on GitHub +
  • @@ -148,7 +162,36 @@
    -

    Arthas

    +

    Arthas 用户文档

    +
    +

    Arthas(阿尔萨斯) 能为你做什么?

    +

    当你遇到以下类似问题而束手无策时,你看到了这篇文档,看到了 Arthas,那么恭喜你,你朝正确的方向又迈了一大步。

    +
      +
    1. 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
    2. +
    3. 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
    4. +
    5. 遇到问题无法在预发 debug 一下,难道只能通过加日志再重新预发布吗?
    6. +
    7. 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
    8. +
    9. 是否有一个全局视角来查看系统的运行状况?
    10. +
    11. 有什么办法可以监控到容器和中间件(AliTomcat、HSF、Notify 等)的实时运行状态?
    12. +
    +

    Arthas 是全新的在线诊断工具,采用命令行交互模式,支持web端在线诊断,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。

    +
    +
    @@ -157,6 +200,13 @@