目录
长生剑 - SAPGUI Where Used List
碧玉刀 - ABAP调试器观察点
霸王枪 - ABAP调试器动态断点
多情环 - ABAP代码静态扫描
孔雀翎 - SAT
离别钩 - ST05
拳头 - 迷之方法???
Jerry在2018年开始用中文在微信公众号平台上写作之前,在SAP官方社区上总共写了639篇英文博客。
其中有一篇写于2013年介绍ABAP调试技巧的博客:
Six kinds of debugging tips to find the source code where the message is raised
从2016年至今,在SAP社区上有超过十五万的阅读量。
实际的阅读量远远大于这个数字,因为2016年社区改版之后,文章阅读量清零了。
SAP社区在2016年改版前,有一个所谓的Gamification游戏化机制,博客每收到一个赞之后,作者会得到2点积分。这篇博客当时给Jerry赢得了不少社区积分。
该博客以一个实际例子,向大家介绍了Jerry多年ABAP编程生涯积累的6种错误消息调试方法。事实上Jerry实际工作中靠着这六种方法,对于我遇到形形色色的错误消息,几乎没有遇到调试不出抛出消息准确代码位置的情况,个人觉得这些方法还是相当管用的。
具体场景:在SE38里随便输入一个并不存在的程序名,点击Display按钮,显示一个提示消息。我们的任务是通过调试或者使用Netweaver提供的其他工具找到抛出这个消息的ABAP代码的准确位置。
古龙的代表作之一《七种武器》,介绍了七件令人闻风丧胆的精妙兵器,央视的《天下足球》系列也曾用这七种武器来类比足坛上那些绝世神锋们。作为古龙的粉丝,Jerry也将这七种方法用古大师的七种武器来命名,算是向他致敬。
方法1:长生剑 - 使用SAPGUI自带的Where Used List功能
在我国古代,剑被称作“百兵之君”,常常被当作一种高贵的装饰品,从皇帝到文人都喜欢佩剑以显示身份。在金庸和古龙的名著里,大多数江湖人物使用的兵器都是剑。
下面是Jerry用来镇bug的龙泉剑:
正如剑是江湖儿女使用得最多的兵器一样,我想每一位ABAP从业人员应该都用过SAPGUI里自带的Where Used List功能。
鼠标单击SE38里显示的提示消息,查看这条消息的技术明细:DS017,其中DS代表Message Class的ID,017是这条消息在Message Class里的编号。
事务码SE91, 打开DS message class,定位到第17条消息,点击这个图标使用Where Used List功能。
结果发现SAP标准程序里抛出这个消息的地方太多了。。。
这种情况下只得一条一条看了。注意我们在SE38里看到的消息显示前面有个绿灯,因此说明ABAP代码抛出这条消息时,是以类型S(Successful)投递的。这样我们只看结果列表里MESSAGE s017这种记录,对于MESSAGE E017直接忽略,因为后者抛出的消息前面显示的是红灯。
很快找到了这一条记录,但我还不能100%确认。此时双击进去,设置一个断点,然后回到SE38,再点一次Display按钮。
此时断点触发,说明ABAP include LWBABAPF00的第813行就是我要找的抛出这个提示消息的准确位置。
方法2:碧玉刀 - 使用ABAP调试器的watch point(观察点)功能
刀同样是一件历史非常悠久的武器,早在原始社会,古人类就用石头、蚌壳、兽骨打制成各种形状的刀。古人不仅将刀作为劳动工具,还随身携带,作为防身自卫的武器。
方法2介绍的watch point是和刀同样具有悠久历史的工具。有多古老?它伴随着SAPGUI问世的时候,Jerry的有些同事还没出生。
金庸古龙小说里,使用刀的名家也不少。金毛狮王谢逊从崆峒派那里偷了一本《七伤拳:从入门到精通》,除了七伤拳外,使用的武器就是屠龙刀。古龙小说里使刀的宗师就更多了,白天羽,傅红雪,以及手持圆月弯刀,能释放“小楼一夜听春雨”终极大招的丁鹏:
通过ABAP的关键字MESSAGE抛出消息时,系统变量SY-MSGID会自动被填充消息所属的Message Class,在Jerry这个例子里为DS,而SY-MSGNO被填充为抛出消息的编号,这个例子里为017. 因此,通过在调试器里创建watch point并维护相应的触发条件。在程序运行时,一旦触发条件满足,watch point触发,此时执行到的ABAP语句即为消息弹出的准确位置。
在命令输入栏里键入/h打开调试模式,点击Display按钮,弹出调试器:
在调试器的此处创建一个watch point:
条件维护如下,然后按F8继续程序的执行,之后调试器会自动在抛出消息的ABAP代码处停下来。
Jerry每次使用ABAP调试器里的观察点定位到我想查找的消息出处时,会感觉到丁鹏用圆月弯刀施展出“小楼一夜听春雨”将对手劈成两半的快感。
方法3:霸王枪 - 使用ABAP调试器里类型为ABAP命令的动态断点
枪,百兵之王,枪长而锋利尖锐,使用灵便,枪头刃可刺可斩,可刺穿盔甲。枪在十八般武艺中比较难学,不易掌握,俗语:“年棍,月刀,久练枪”。
“一寸长,一寸强”,正因为枪的威力比棍棒等钝器强,所以我国古代很多名将都用枪,比如《三国演义》中的赵云,马超,姜维等等:
枪在这些高武力值的武将手中施展开来,小兵们望风披靡;ABAP动态断点一出,错误消息则无所遁形。
在调试器此处创建类型为ABAP Commands的动态断点,命令设置为MESSAGE. 这样,ABAP调试器会自动在所有出现了MESSAGE关键字的地方停下来。
也可以在菜单Breakpoints->Breakpoint at处创建很多其他类型的断点,相当有用。
从方法4开始介绍的消息定位方法,已经不再局限于使用ABAP调试器,而是灵活运用SAP Netweaver里提供的各种有用工具。
方法4:多情环 - ABAP源代码静态扫描
这双环不论套住了什么,就立刻紧紧地缠住绝不脱手,就好像一个多情的女人一样,所以名叫多情环。
Jerry在学会ABAP代码静态扫描的技能后,也被代码扫描工具深深迷住了,再也摆脱不了对它的依赖。
事务码SE93里输入SE38,找到SE38实现的ABAP程序名和所处的开发包名称。
方法4的理论依据是,既然我们在SE38里看到了DS017这条消息,那么SE38的实现代码里,必定会出现MESSAGE S017这行代码。因此在方法4里我们改变思路,不再采用动态调试的办法,而选择和它相反的思路。
使用源代码扫描工具程序RS_ABAP_SOURCE_SCAN查找SE38实现代码里所有出现了MESSAGE S017的ABAP代码位置:
不到一秒钟,就找到了准确的位置:
另一个事务码CODE_SCANNER也提供了类似的ABAP代码扫描功能,界面和RS_ABAP_SOURCE_SCAN略微有点差异。
方法5:孔雀翎 - 使用ABAP应用性能分析工具SAT
《孔雀翎》是《七种武器》系列里Jerry最喜欢的一部,而使用SAT进行ABAP消息定位也是Jerry最喜欢的方法。
孔雀翎是个由纯金铸成、闪闪发光的圆筒,上面有两道枢纽,按下枢纽,筒里的暗器便飞射而出,据说这些暗器发出来时,美丽得就像孔雀开屏一样,辉煌灿烂,然而,就在你被这种惊人的生灵感动得目瞪神迷时,它已经要了你的性命。
李寻欢手中的小李飞刀,号称“例不虚发”,然而还是有miss的时候,在对决大欢喜女菩萨之时,没能做到一击必杀。孔雀翎则不同,在古龙笔下的设定里,它是一件命中率100%的暗器,孔雀翎面前没有任何人能逃生。
可惜最后被主人弄丢了,囧。
Jerry回忆自己的消息分析排错生涯,似乎想不起一种我使用了SAT但没能成功找到消息出处的情况出现,这说明SAT同孔雀翎一样,在查找ABAP消息抛出位置的领域里威力极大。
进入事务码SAT,创建一个新的跟踪Variant,Aggregation(聚合)记得设置为None,否则后续查看结果时将得不到期望看到的完整树形结构。
在Transaction字段里输入SE38,点击Execute按钮,这样就在跟踪模式下启动了SE38.
接着和以前一样,点击Display按钮,看到提示消息后,返回到SAT界面。这样SE38从启动到弹出提示消息,再到退出这整个过程所执行的ABAP代码都被SAT记录下来了。此时会看到一个进度条,表明SAT在格式化所记录内容的进度:
等到100%完成后,来到SAT的结果展示页面里,点击Call Hierarchy标签页,SE38执行的所有ABAP statement罗列如下。使用SAT自带的搜索按钮,输入MESSAGE S017, 执行即可得到结果。双击后就能进入对应的ABAP代码。
虽然SAT最主要的用途是用来做应用性能分析和优化的,但在Jerry介绍的这个场景里,它也起到了辅助消息定位的作用。
除此之外说句题外话,SAT的Processing Blocks界面以树形结构显示了ABAP代码的一层层调用关系,对于我们分析和学习复杂应用的执行逻辑也非常有帮助。
方法6:离别钩 - 使用ABAP数据库执行跟踪和性能分析工具ST05
看下古龙原文对离别钩的介绍。
“离别钩也是种武器,也是钩。”
“既然是钩,为什么要叫做离别?”
“因为这柄钩,无论钩住什么都会造成离别。如果它钩住你的手,你的手就要和腕离别;如果它钩住你的脚,你的脚就要和腿离别。”
“如果它钩住我的咽喉,我就和这个世界离别了?”
“是的。”
“你为什么要用如此残酷的武器?”
“因为我不愿被人强迫与我所爱的人离别。”
“我明白你的意思了。”
“你真的明白?”
“你用离别钩,只不过为了要相聚。”
“是的。”
Jerry想提醒大家的是,ST05虽然同离别钩一样,能有效帮助大家的消息定位工作,但如果你在客户生产系统里打开了ST05的性能分析开关,之后忘记了关掉,那说不定你可能不得不同你的工作离别了。
ABAP从业人员在怀疑应用程序的性能瓶颈出现在数据库层面时,往往都会在事务码ST05里将数据库跟踪开关打开,在跟踪模式下重新运行应用,拿到跟踪结果以此来分析数据库的性能。
在这个例子里,Jerry用ST05跟踪SE38这个事务码的执行,能得到过程中访问过的所有数据库表的名称,和访问它们的性能。
为什么Jerry要弄清楚SE38到底访问了哪些数据库表?根据经验推断,我们在SE38里输入程序的名称点击Display按钮后,SE38的实现必定会从某个数据库表(即Netweaver里存储所有ABAP程序名称的数据库表)里根据该名称进行搜索,如果搜索未命中,说明该程序并不存在,从而抛一条消息给用户。
换言之,SE38里根据用户输入去数据库表里使用OPEN SQL进行查询,和抛出提示消息,这两处代码的位置一定相邻。因此我们只要找到了SE38里查询报表名称的数据库表的位置,那么距离抛出提示消息的代码位置也不远了。
对于SE38里访问数据库表的性能,Jerry是毫不关心的,直接忽略。在ST05的结果列表里,我只盯着Object Name里显示的数据库表名称,PROGDIR在里面太显眼了。这张表存放的就是所有ABAP程序的名称,右边的就是访问该表的ABAP OPEN SQL:
SELECT WHERE ''NAME" = 'ASDASDD' AND "STATE" = 'A'.
我之前在ST05跟踪模式下随便输了个程序名ASDASDD, 所以SE38试图到表PROGDIR里查找一个名叫ASDASDD且状态为激活状态(A-Activated)的程序。
点击上图的Display按钮,就能看到访问数据库表PRODDIR的代码了,位于第774行:
鼠标稍稍往下滑动一下,第813行就是我们要找到抛出提示消息的代码位置。两个挨得确实够近吧?
方法7:拳头 - 使用搜索引擎根据关键字DS 017查找,或者直接向认识的专家求助
其他六种武器都是金属制成,唯独拳头,乃血肉之躯构成。可能因为这种原因,拳在金庸的小说里出镜率不高,七伤拳算是比较著名的拳术之一。
五行之气调阴阳,损心伤肺摧肝肠。 藏离精失意恍惚,三焦齐逆兮魂魄飞扬!
人体内有阴阳二气、肺属金、肝属木、肾属水、心属火、脾属土五行,所谓「七伤」,便是这七种伤害。
掌握了七伤拳的人,可以同时发出或刚猛或阴柔的不同劲力,摧伤敌人脏腑,拳力复杂,吞吐闪烁,变幻万端,威力惊人。但这套神妙的拳法,伤敌力强,伤己也重,每练一次,内脏便受一次损伤,这就是“一练七伤,七者皆伤。先伤己,后伤敌”的来历。
同样,当遇到我们难以定位的消息时,我们可以直接使用搜索引擎,或者向自己认识的专家求助。
Jerry试着在百度里搜索DS 017,还真找到一篇相关文章:
来自简书社区名叫“三月行者”的朋友,真的很感谢他不辞辛劳地把我那篇英文博客翻译成了中文:
这是他的简书地址:https://www.jianshu.com/p/4aae58102043
使用七伤拳的武者,固然可以发出或刚猛、或阴柔、或刚中有柔,或柔中有刚,或横出,或直送,或内缩这七种不同的内劲,达到迅速克敌制胜的效果,然而自身也会受到七伤拳的反噬。
同样,使用搜索引擎或者求助专家,固然可以迅速解决眼前的问题,但可能失去了利用这个问题提升自己能力的机会,所以大家使用这种方法之前一定要慎重考虑。
总结
《宋史·岳飞传》:“阵而后战,兵法之常;运用之妙,存乎一心。” ABAP Netweaver里给我们提供了大量的工具,祝愿大家都能够灵活运用这些工具,充分挖掘它们的潜力,来解决实际问题。感谢大家阅读。
更多阅读
要获取更多Jerry的原创文章,请关注公众号"汪子熙":