test_plugin.py 84 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691
  1. import zipfile
  2. from io import BytesIO
  3. from uuid import uuid4
  4. import pytest
  5. from django.core.files.uploadedfile import SimpleUploadedFile
  6. from django.urls import reverse
  7. from sentry.models.debugfile import ProjectDebugFile
  8. from sentry.models.files.file import File
  9. from sentry.testutils.cases import TransactionTestCase
  10. from sentry.testutils.helpers.datetime import before_now, iso_format
  11. from sentry.testutils.helpers.options import override_options
  12. from sentry.testutils.relay import RelayStoreHelper
  13. from sentry.testutils.skips import requires_symbolicator
  14. from sentry.utils import json
  15. PROGUARD_UUID = "6dc7fdb0-d2fb-4c8e-9d6b-bb1aa98929b1"
  16. PROGUARD_SOURCE = b"""\
  17. org.slf4j.helpers.Util$ClassContextSecurityManager -> org.a.b.g$a:
  18. 65:65:void <init>() -> <init>
  19. 67:67:java.lang.Class[] getClassContext() -> a
  20. 69:69:java.lang.Class[] getExtraClassContext() -> a
  21. 68:68:java.lang.Class[] getContext() -> a
  22. 65:65:void <init>(org.slf4j.helpers.Util$1) -> <init>
  23. org.slf4j.helpers.Util$ClassContext -> org.a.b.g$b:
  24. 65:65:void <init>() -> <init>
  25. """
  26. PROGUARD_INLINE_UUID = "d748e578-b3d1-5be5-b0e5-a42e8c9bf8e0"
  27. PROGUARD_INLINE_SOURCE = b"""\
  28. # compiler: R8
  29. # compiler_version: 2.0.74
  30. # min_api: 16
  31. # pg_map_id: 5b46fdc
  32. # common_typos_disable
  33. $r8$backportedMethods$utility$Objects$2$equals -> a:
  34. boolean equals(java.lang.Object,java.lang.Object) -> a
  35. $r8$twr$utility -> b:
  36. void $closeResource(java.lang.Throwable,java.lang.Object) -> a
  37. android.support.v4.app.RemoteActionCompatParcelizer -> android.support.v4.app.RemoteActionCompatParcelizer:
  38. 1:1:void <init>():11:11 -> <init>
  39. io.sentry.sample.-$$Lambda$r3Avcbztes2hicEObh02jjhQqd4 -> e.a.c.a:
  40. io.sentry.sample.MainActivity f$0 -> b
  41. io.sentry.sample.MainActivity -> io.sentry.sample.MainActivity:
  42. 1:1:void <init>():15:15 -> <init>
  43. 1:1:boolean onCreateOptionsMenu(android.view.Menu):60:60 -> onCreateOptionsMenu
  44. 1:1:boolean onOptionsItemSelected(android.view.MenuItem):69:69 -> onOptionsItemSelected
  45. 2:2:boolean onOptionsItemSelected(android.view.MenuItem):76:76 -> onOptionsItemSelected
  46. 1:1:void bar():54:54 -> t
  47. 1:1:void foo():44 -> t
  48. 1:1:void onClickHandler(android.view.View):40 -> t
  49. """
  50. PROGUARD_BUG_UUID = "071207ac-b491-4a74-957c-2c94fd9594f2"
  51. PROGUARD_BUG_SOURCE = b"x"
  52. JVM_DEBUG_ID = "6dc7fdb0-d2fb-4c8e-9d6b-bb1aa98929b1"
  53. JVM_SOURCE = b"""\
  54. package io.sentry.samples
  55. import android.content.Intent
  56. import android.os.Bundle
  57. import androidx.activity.ComponentActivity
  58. class MainActivity : ComponentActivity() {
  59. override fun onCreate(savedInstanceState: Bundle?) {
  60. super.onCreate(savedInstanceState)
  61. setContentView(R.layout.activity_main)
  62. InnerClass().whoops()
  63. val list = findViewById<RecyclerView>(R.id.list)
  64. list.layoutManager = LinearLayoutManager(this)
  65. list.adapter = TrackAdapter()
  66. }
  67. class InnerClass {
  68. fun whoops() {
  69. AnotherInnerClass().whoops2()
  70. }
  71. }
  72. class AnotherInnerClass {
  73. fun whoops2() {
  74. AdditionalInnerClass().whoops3()
  75. }
  76. }
  77. class AdditionalInnerClass {
  78. fun whoops3() {
  79. OneMoreInnerClass().whoops4()
  80. }
  81. }
  82. class OneMoreInnerClass {
  83. fun whoops4() {
  84. throw RuntimeException("whoops")
  85. }
  86. }
  87. }
  88. """
  89. PROGUARD_SOURCE_LOOKUP_UUID = "05d96b1c-1786-477c-8615-d3cf83e027c7"
  90. PROGUARD_SOURCE_LOOKUP_SOURCE = b"""\
  91. io.sentry.samples.instrumentation.ui.EditActivity -> io.sentry.samples.instrumentation.ui.EditActivity:
  92. # {"id":"sourceFile","fileName":"EditActivity.kt"}
  93. int $r8$clinit -> a
  94. 0:65535:void <init>():15:15 -> <init>
  95. 1:6:void onCreate(android.os.Bundle):18:18 -> onCreate
  96. 7:12:void onCreate(android.os.Bundle):19:19 -> onCreate
  97. 13:22:void onCreate(android.os.Bundle):21:21 -> onCreate
  98. 23:32:void onCreate(android.os.Bundle):22:22 -> onCreate
  99. 33:42:void onCreate(android.os.Bundle):23:23 -> onCreate
  100. 43:49:void onCreate(android.os.Bundle):24:24 -> onCreate
  101. 50:71:void onCreate(android.os.Bundle):26:26 -> onCreate
  102. 72:73:java.lang.String io.sentry.samples.instrumentation.data.Track.getName():46:46 -> onCreate
  103. 72:73:void onCreate(android.os.Bundle):28 -> onCreate
  104. 74:76:void onCreate(android.os.Bundle):28:28 -> onCreate
  105. 77:78:java.lang.String io.sentry.samples.instrumentation.data.Track.getComposer():48:48 -> onCreate
  106. 77:78:void onCreate(android.os.Bundle):29 -> onCreate
  107. 79:81:void onCreate(android.os.Bundle):29:29 -> onCreate
  108. 82:83:long io.sentry.samples.instrumentation.data.Track.getMillis():51:51 -> onCreate
  109. 82:83:void onCreate(android.os.Bundle):30 -> onCreate
  110. 84:90:void onCreate(android.os.Bundle):30:30 -> onCreate
  111. 91:92:float io.sentry.samples.instrumentation.data.Track.getPrice():53:53 -> onCreate
  112. 91:92:void onCreate(android.os.Bundle):31 -> onCreate
  113. 93:102:void onCreate(android.os.Bundle):31:31 -> onCreate
  114. 103:119:void onCreate(android.os.Bundle):34:34 -> onCreate
  115. io.sentry.samples.instrumentation.ui.EditActivity$$ExternalSyntheticLambda0 -> io.sentry.samples.instrumentation.ui.g:
  116. # {"id":"sourceFile","fileName":"R8$$SyntheticClass"}
  117. # {"id":"com.android.tools.r8.synthesized"}
  118. android.widget.EditText io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.f$4 -> e
  119. android.widget.EditText io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.f$3 -> d
  120. android.widget.EditText io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.f$2 -> c
  121. io.sentry.samples.instrumentation.data.Track io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.f$0 -> a
  122. android.widget.EditText io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.f$1 -> b
  123. io.sentry.samples.instrumentation.ui.EditActivity io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.f$5 -> f
  124. void io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.<init>(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity) -> <init>
  125. # {"id":"com.android.tools.r8.synthesized"}
  126. 19:21:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):0:0 -> onMenuItemClick
  127. 19:21:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  128. # {"id":"com.android.tools.r8.synthesized"}
  129. 22:35:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):35:35 -> onMenuItemClick
  130. 22:35:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  131. # {"id":"com.android.tools.r8.synthesized"}
  132. 36:44:void io.sentry.samples.instrumentation.ui.AnotherClassInSameFile$AnotherInnerClass.helloOtherInner():26:26 -> onMenuItemClick
  133. 36:44:void io.sentry.samples.instrumentation.ui.AnotherClassInSameFile.otherFun():21 -> onMenuItemClick
  134. 36:44:void io.sentry.samples.instrumentation.ui.AnotherClassInSameFile.helloOther():17 -> onMenuItemClick
  135. 36:44:void io.sentry.samples.instrumentation.ui.SomeService$InnerClassOfSomeService.helloInner():10 -> onMenuItemClick
  136. 36:44:void io.sentry.samples.instrumentation.ui.SomeService.helloThere():5 -> onMenuItemClick
  137. 36:44:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):37 -> onMenuItemClick
  138. 36:44:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  139. # {"id":"com.android.tools.r8.synthesized"}
  140. 45:58:io.sentry.protocol.SentryId io.sentry.Sentry.captureException(java.lang.Throwable):433:433 -> onMenuItemClick
  141. 45:58:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):39 -> onMenuItemClick
  142. 45:58:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  143. # {"id":"com.android.tools.r8.synthesized"}
  144. 59:68:io.sentry.ITransaction io.sentry.Sentry.startTransaction(java.lang.String,java.lang.String,boolean):697:697 -> onMenuItemClick
  145. 59:68:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):42 -> onMenuItemClick
  146. 59:68:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  147. # {"id":"com.android.tools.r8.synthesized"}
  148. 69:71:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):42:42 -> onMenuItemClick
  149. 69:71:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  150. # {"id":"com.android.tools.r8.synthesized"}
  151. 72:79:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):48:48 -> onMenuItemClick
  152. 72:79:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  153. # {"id":"com.android.tools.r8.synthesized"}
  154. 80:87:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):49:49 -> onMenuItemClick
  155. 80:87:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  156. # {"id":"com.android.tools.r8.synthesized"}
  157. 88:95:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):50:50 -> onMenuItemClick
  158. 88:95:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  159. # {"id":"com.android.tools.r8.synthesized"}
  160. 96:103:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):51:51 -> onMenuItemClick
  161. 96:103:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  162. # {"id":"com.android.tools.r8.synthesized"}
  163. 104:125:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):52:52 -> onMenuItemClick
  164. 104:125:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  165. # {"id":"com.android.tools.r8.synthesized"}
  166. 126:142:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):53:53 -> onMenuItemClick
  167. 126:142:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  168. # {"id":"com.android.tools.r8.synthesized"}
  169. 143:164:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):54:54 -> onMenuItemClick
  170. 143:164:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  171. # {"id":"com.android.tools.r8.synthesized"}
  172. 165:175:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):64:64 -> onMenuItemClick
  173. 165:175:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  174. # {"id":"com.android.tools.r8.synthesized"}
  175. 176:187:void io.sentry.samples.instrumentation.ui.EditActivity.addNewTrack(java.lang.String,java.lang.String,long,float):84:84 -> onMenuItemClick
  176. 176:187:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):64 -> onMenuItemClick
  177. 176:187:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  178. # {"id":"com.android.tools.r8.synthesized"}
  179. 188:190:void io.sentry.samples.instrumentation.data.Track.<init>(long,java.lang.String,java.lang.Long,java.lang.String,java.lang.Long,java.lang.Long,long,java.lang.Long,float,int,kotlin.jvm.internal.DefaultConstructorMarker):43:43 -> onMenuItemClick
  180. 188:190:void io.sentry.samples.instrumentation.ui.EditActivity.addNewTrack(java.lang.String,java.lang.String,long,float):84 -> onMenuItemClick
  181. 188:190:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):64 -> onMenuItemClick
  182. 188:190:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  183. # {"id":"com.android.tools.r8.synthesized"}
  184. 191:198:void io.sentry.samples.instrumentation.ui.EditActivity.addNewTrack(java.lang.String,java.lang.String,long,float):94:94 -> onMenuItemClick
  185. 191:198:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):64 -> onMenuItemClick
  186. 191:198:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  187. # {"id":"com.android.tools.r8.synthesized"}
  188. 199:211:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):66:66 -> onMenuItemClick
  189. 199:211:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  190. # {"id":"com.android.tools.r8.synthesized"}
  191. 212:227:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):67:67 -> onMenuItemClick
  192. 212:227:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  193. # {"id":"com.android.tools.r8.synthesized"}
  194. 228:238:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):69:69 -> onMenuItemClick
  195. 228:238:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  196. # {"id":"com.android.tools.r8.synthesized"}
  197. 239:250:io.sentry.samples.instrumentation.data.Track io.sentry.samples.instrumentation.data.Track.copy$default(io.sentry.samples.instrumentation.data.Track,long,java.lang.String,java.lang.Long,java.lang.String,java.lang.Long,java.lang.Long,long,java.lang.Long,float,int,java.lang.Object):0:0 -> onMenuItemClick
  198. 239:250:void io.sentry.samples.instrumentation.ui.EditActivity.update(io.sentry.samples.instrumentation.data.Track,java.lang.String,java.lang.String,long,float):100 -> onMenuItemClick
  199. 239:250:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):69 -> onMenuItemClick
  200. 239:250:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  201. # {"id":"com.android.tools.r8.synthesized"}
  202. 251:265:io.sentry.samples.instrumentation.data.Track io.sentry.samples.instrumentation.data.Track.copy(long,java.lang.String,java.lang.Long,java.lang.String,java.lang.Long,java.lang.Long,long,java.lang.Long,float):0:0 -> onMenuItemClick
  203. 251:265:io.sentry.samples.instrumentation.data.Track io.sentry.samples.instrumentation.data.Track.copy$default(io.sentry.samples.instrumentation.data.Track,long,java.lang.String,java.lang.Long,java.lang.String,java.lang.Long,java.lang.Long,long,java.lang.Long,float,int,java.lang.Object):0 -> onMenuItemClick
  204. 251:265:void io.sentry.samples.instrumentation.ui.EditActivity.update(io.sentry.samples.instrumentation.data.Track,java.lang.String,java.lang.String,long,float):100 -> onMenuItemClick
  205. 251:265:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):69 -> onMenuItemClick
  206. 251:265:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  207. # {"id":"com.android.tools.r8.synthesized"}
  208. 266:273:void io.sentry.samples.instrumentation.ui.EditActivity.update(io.sentry.samples.instrumentation.data.Track,java.lang.String,java.lang.String,long,float):106:106 -> onMenuItemClick
  209. 266:273:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):69 -> onMenuItemClick
  210. 266:273:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  211. # {"id":"com.android.tools.r8.synthesized"}
  212. 274:286:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):71:71 -> onMenuItemClick
  213. 274:286:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  214. # {"id":"com.android.tools.r8.synthesized"}
  215. 287:301:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):72:72 -> onMenuItemClick
  216. 287:301:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  217. # {"id":"com.android.tools.r8.synthesized"}
  218. 302:306:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):74:74 -> onMenuItemClick
  219. 302:306:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  220. # {"id":"com.android.tools.r8.synthesized"}
  221. 307:312:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):75:75 -> onMenuItemClick
  222. 307:312:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  223. # {"id":"com.android.tools.r8.synthesized"}
  224. 313:316:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):56:56 -> onMenuItemClick
  225. 313:316:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  226. # {"id":"com.android.tools.r8.synthesized"}
  227. 317:320:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):61:61 -> onMenuItemClick
  228. 317:320:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  229. # {"id":"com.android.tools.r8.synthesized"}
  230. """
  231. EDIT_ACTIVITY_SOURCE = b"""\
  232. package io.sentry.samples.instrumentation.ui
  233. import android.os.Bundle
  234. import android.widget.EditText
  235. import android.widget.Toast
  236. import androidx.activity.ComponentActivity
  237. import androidx.appcompat.widget.Toolbar
  238. import io.sentry.Sentry
  239. import io.sentry.SpanStatus
  240. import io.sentry.samples.instrumentation.R
  241. import io.sentry.samples.instrumentation.SampleApp
  242. import io.sentry.samples.instrumentation.data.Track
  243. import kotlinx.coroutines.runBlocking
  244. class EditActivity : ComponentActivity() {
  245. override fun onCreate(savedInstanceState: Bundle?) {
  246. super.onCreate(savedInstanceState)
  247. setContentView(R.layout.activity_edit)
  248. val nameInput = findViewById<EditText>(R.id.track_name)
  249. val composerInput = findViewById<EditText>(R.id.track_composer)
  250. val durationInput = findViewById<EditText>(R.id.track_duration)
  251. val unitPriceInput = findViewById<EditText>(R.id.track_unit_price)
  252. val originalTrack: Track? = intent.getSerializableExtra(TRACK_EXTRA_KEY) as? Track
  253. originalTrack?.run {
  254. nameInput.setText(name)
  255. composerInput.setText(composer)
  256. durationInput.setText(millis.toString())
  257. unitPriceInput.setText(price.toString())
  258. }
  259. findViewById<Toolbar>(R.id.toolbar).setOnMenuItemClickListener {
  260. if (it.itemId == R.id.action_save) {
  261. try {
  262. SomeService().helloThere()
  263. } catch (e: Exception) {
  264. Sentry.captureException(e)
  265. }
  266. val transaction = Sentry.startTransaction(
  267. "Track Interaction",
  268. if (originalTrack == null) "ui.action.add" else "ui.action.edit",
  269. true
  270. )
  271. val name = nameInput.text.toString()
  272. val composer = composerInput.text.toString()
  273. val duration = durationInput.text.toString()
  274. val unitPrice = unitPriceInput.text.toString()
  275. if (name.isEmpty() || composer.isEmpty() ||
  276. duration.isEmpty() || duration.toLongOrNull() == null ||
  277. unitPrice.isEmpty() || unitPrice.toFloatOrNull() == null
  278. ) {
  279. Toast.makeText(
  280. this,
  281. "Some of the inputs are empty or have wrong format " +
  282. "(duration/unitprice not a number)",
  283. Toast.LENGTH_LONG
  284. ).show()
  285. } else {
  286. if (originalTrack == null) {
  287. addNewTrack(name, composer, duration.toLong(), unitPrice.toFloat())
  288. val createCount = SampleApp.analytics.getInt("create_count", 0) + 1
  289. SampleApp.analytics.edit().putInt("create_count", createCount).apply()
  290. } else {
  291. originalTrack.update(name, composer, duration.toLong(), unitPrice.toFloat())
  292. val editCount = SampleApp.analytics.getInt("edit_count", 0) + 1
  293. SampleApp.analytics.edit().putInt("edit_count", editCount).apply()
  294. }
  295. transaction.finish(SpanStatus.OK)
  296. finish()
  297. }
  298. return@setOnMenuItemClickListener true
  299. }
  300. return@setOnMenuItemClickListener false
  301. }
  302. }
  303. private fun addNewTrack(name: String, composer: String, duration: Long, unitPrice: Float) {
  304. val newTrack = Track(
  305. name = name,
  306. albumId = null,
  307. composer = composer,
  308. mediaTypeId = null,
  309. genreId = null,
  310. millis = duration,
  311. bytes = null,
  312. price = unitPrice
  313. )
  314. runBlocking {
  315. SampleApp.database.tracksDao().insert(newTrack)
  316. }
  317. }
  318. private fun Track.update(name: String, composer: String, duration: Long, unitPrice: Float) {
  319. val updatedTrack = copy(
  320. name = name,
  321. composer = composer,
  322. millis = duration,
  323. price = unitPrice
  324. )
  325. runBlocking {
  326. SampleApp.database.tracksDao().update(updatedTrack)
  327. }
  328. }
  329. companion object {
  330. const val TRACK_EXTRA_KEY = "EditActivity.Track"
  331. }
  332. }
  333. """
  334. SOME_SERVICE_SOURCE = b"""\
  335. package io.sentry.samples.instrumentation.ui
  336. class SomeService {
  337. fun helloThere() {
  338. InnerClassOfSomeService().helloInner()
  339. }
  340. class InnerClassOfSomeService {
  341. fun helloInner() {
  342. AnotherClassInSameFile().helloOther()
  343. }
  344. }
  345. }
  346. class AnotherClassInSameFile {
  347. fun helloOther() {
  348. otherFun()
  349. }
  350. private fun otherFun() {
  351. AnotherInnerClass().helloOtherInner()
  352. }
  353. class AnotherInnerClass {
  354. fun helloOtherInner() {
  355. throw RuntimeException("thrown on purpose to test ProGuard Android source context")
  356. }
  357. }
  358. }
  359. """
  360. @pytest.mark.django_db(transaction=True)
  361. class BasicResolvingIntegrationTest(RelayStoreHelper, TransactionTestCase):
  362. @pytest.fixture(autouse=True)
  363. def initialize(self, set_sentry_option, live_server):
  364. with set_sentry_option("system.url-prefix", live_server.url):
  365. # Run test case
  366. yield
  367. def upload_proguard_mapping(self, uuid, mapping_file_content):
  368. url = reverse(
  369. "sentry-api-0-dsym-files",
  370. kwargs={
  371. "organization_slug": self.project.organization.slug,
  372. "project_slug": self.project.slug,
  373. },
  374. )
  375. self.login_as(user=self.user)
  376. out = BytesIO()
  377. f = zipfile.ZipFile(out, "w")
  378. f.writestr("proguard/%s.txt" % uuid, mapping_file_content)
  379. f.writestr("ignored-file.txt", b"This is just some stuff")
  380. f.close()
  381. response = self.client.post(
  382. url,
  383. {
  384. "file": SimpleUploadedFile(
  385. "symbols.zip", out.getvalue(), content_type="application/zip"
  386. )
  387. },
  388. format="multipart",
  389. )
  390. assert response.status_code == 201, response.content
  391. assert len(response.json()) == 1
  392. def test_basic_resolving(self):
  393. self.upload_proguard_mapping(PROGUARD_UUID, PROGUARD_SOURCE)
  394. event_data = {
  395. "user": {"ip_address": "31.172.207.97"},
  396. "extra": {},
  397. "project": self.project.id,
  398. "platform": "java",
  399. "debug_meta": {"images": [{"type": "proguard", "uuid": PROGUARD_UUID}]},
  400. "exception": {
  401. "values": [
  402. {
  403. "stacktrace": {
  404. "frames": [
  405. {
  406. "function": "a",
  407. "abs_path": None,
  408. "module": "org.a.b.g$a",
  409. "filename": None,
  410. "lineno": 67,
  411. },
  412. {
  413. "function": "a",
  414. "abs_path": None,
  415. "module": "org.a.b.g$a",
  416. "filename": None,
  417. "lineno": 69,
  418. },
  419. ]
  420. },
  421. "module": "org.a.b",
  422. "type": "g$a",
  423. "value": "Attempt to invoke virtual method 'org.a.b.g$a.a' on a null object reference",
  424. }
  425. ]
  426. },
  427. "timestamp": iso_format(before_now(seconds=1)),
  428. }
  429. event = self.post_and_retrieve_event(event_data)
  430. if not self.use_relay():
  431. # We measure the number of queries after an initial post,
  432. # because there are many queries polluting the array
  433. # before the actual "processing" happens (like, auth_user)
  434. with self.assertWriteQueries(
  435. {
  436. "nodestore_node": 2,
  437. "sentry_eventuser": 1,
  438. "sentry_groupedmessage": 1,
  439. "sentry_userreport": 1,
  440. }
  441. ):
  442. self.post_and_retrieve_event(event_data)
  443. exc = event.interfaces["exception"].values[0]
  444. bt = exc.stacktrace
  445. frames = bt.frames
  446. assert exc.type == "Util$ClassContextSecurityManager"
  447. assert (
  448. exc.value
  449. == "Attempt to invoke virtual method 'org.slf4j.helpers.Util$ClassContextSecurityManager.getExtraClassContext' on a null object reference"
  450. )
  451. assert exc.module == "org.slf4j.helpers"
  452. assert frames[0].function == "getClassContext"
  453. assert frames[0].module == "org.slf4j.helpers.Util$ClassContextSecurityManager"
  454. assert frames[1].function == "getExtraClassContext"
  455. assert frames[1].module == "org.slf4j.helpers.Util$ClassContextSecurityManager"
  456. assert event.culprit == (
  457. "org.slf4j.helpers.Util$ClassContextSecurityManager " "in getExtraClassContext"
  458. )
  459. @requires_symbolicator
  460. @pytest.mark.symbolicator
  461. def test_basic_resolving_symbolicator(self):
  462. with override_options({"symbolicator.proguard-processing-sample-rate": 1.0}):
  463. self.test_basic_resolving()
  464. def test_resolving_does_not_fail_when_no_value(self):
  465. self.upload_proguard_mapping(PROGUARD_UUID, PROGUARD_SOURCE)
  466. event_data = {
  467. "user": {"ip_address": "31.172.207.97"},
  468. "extra": {},
  469. "project": self.project.id,
  470. "platform": "java",
  471. "debug_meta": {"images": [{"type": "proguard", "uuid": PROGUARD_UUID}]},
  472. "exception": {
  473. "values": [
  474. {
  475. "stacktrace": {
  476. "frames": [
  477. {
  478. "function": "a",
  479. "abs_path": None,
  480. "module": "org.a.b.g$a",
  481. "filename": None,
  482. "lineno": 67,
  483. },
  484. {
  485. "function": "a",
  486. "abs_path": None,
  487. "module": "org.a.b.g$a",
  488. "filename": None,
  489. "lineno": 69,
  490. },
  491. ]
  492. },
  493. "module": "org.a.b",
  494. "type": "g$a",
  495. }
  496. ]
  497. },
  498. "timestamp": iso_format(before_now(seconds=1)),
  499. }
  500. event = self.post_and_retrieve_event(event_data)
  501. if not self.use_relay():
  502. # We measure the number of queries after an initial post,
  503. # because there are many queries polluting the array
  504. # before the actual "processing" happens (like, auth_user)
  505. with self.assertWriteQueries(
  506. {
  507. "nodestore_node": 2,
  508. "sentry_eventuser": 1,
  509. "sentry_groupedmessage": 1,
  510. "sentry_userreport": 1,
  511. }
  512. ):
  513. self.post_and_retrieve_event(event_data)
  514. metrics = event.data["_metrics"]
  515. assert not metrics.get("flag.processing.error")
  516. @requires_symbolicator
  517. @pytest.mark.symbolicator
  518. def test_resolving_does_not_fail_when_no_value_symbolicator(self):
  519. with override_options({"symbolicator.proguard-processing-sample-rate": 1.0}):
  520. self.test_resolving_does_not_fail_when_no_value()
  521. def test_resolving_does_not_fail_when_no_module_or_function(self):
  522. self.upload_proguard_mapping(PROGUARD_UUID, PROGUARD_SOURCE)
  523. event_data = {
  524. "user": {"ip_address": "31.172.207.97"},
  525. "extra": {},
  526. "project": self.project.id,
  527. "platform": "java",
  528. "debug_meta": {"images": [{"type": "proguard", "uuid": PROGUARD_UUID}]},
  529. "exception": {
  530. "values": [
  531. {
  532. "stacktrace": {
  533. "frames": [
  534. {
  535. "function": "a",
  536. "abs_path": None,
  537. "module": "org.a.b.g$a",
  538. "filename": None,
  539. "lineno": 67,
  540. },
  541. {
  542. "function": "a",
  543. "abs_path": None,
  544. "module": "org.a.b.g$a",
  545. "filename": None,
  546. "lineno": 69,
  547. },
  548. {
  549. "function": "__start_thread",
  550. "package": "/apex/com.android.art/lib64/libart.so",
  551. "lineno": 196,
  552. "in_app": False,
  553. },
  554. {
  555. "package": "/apex/com.android.art/lib64/libart.so",
  556. "lineno": 214,
  557. "in_app": False,
  558. },
  559. ]
  560. },
  561. "module": "org.a.b",
  562. "type": "g$a",
  563. "value": "Attempt to invoke virtual method 'org.a.b.g$a.a' on a null object reference",
  564. }
  565. ]
  566. },
  567. "timestamp": iso_format(before_now(seconds=1)),
  568. }
  569. event = self.post_and_retrieve_event(event_data)
  570. if not self.use_relay():
  571. # We measure the number of queries after an initial post,
  572. # because there are many queries polluting the array
  573. # before the actual "processing" happens (like, auth_user)
  574. with self.assertWriteQueries(
  575. {
  576. "nodestore_node": 2,
  577. "sentry_eventuser": 1,
  578. "sentry_groupedmessage": 1,
  579. "sentry_userreport": 1,
  580. }
  581. ):
  582. self.post_and_retrieve_event(event_data)
  583. metrics = event.data["_metrics"]
  584. assert not metrics.get("flag.processing.error")
  585. @requires_symbolicator
  586. @pytest.mark.symbolicator
  587. def test_resolving_does_not_fail_when_no_module_or_function_symbolicator(self):
  588. with override_options({"symbolicator.proguard-processing-sample-rate": 1.0}):
  589. self.test_resolving_does_not_fail_when_no_module_or_function()
  590. def test_sets_inapp_after_resolving(self):
  591. self.upload_proguard_mapping(PROGUARD_UUID, PROGUARD_SOURCE)
  592. version = "org.slf4j@1.2.3"
  593. env_name = "some_env"
  594. event = self.store_event(
  595. data={"release": version, "environment": env_name}, project_id=self.project.id
  596. )
  597. event_data = {
  598. "user": {"ip_address": "31.172.207.97"},
  599. "extra": {},
  600. "release": "org.slf4j@1.2.3",
  601. "project": self.project.id,
  602. "platform": "java",
  603. "debug_meta": {"images": [{"type": "proguard", "uuid": PROGUARD_UUID}]},
  604. "exception": {
  605. "values": [
  606. {
  607. "stacktrace": {
  608. "frames": [
  609. {
  610. "function": "a",
  611. "abs_path": None,
  612. "module": "org.a.b.g$a",
  613. "filename": None,
  614. "lineno": 67,
  615. },
  616. {
  617. "function": "a",
  618. "abs_path": None,
  619. "module": "org.a.b.g$a",
  620. "filename": None,
  621. "lineno": 69,
  622. "in_app": False,
  623. },
  624. {
  625. "function": "a",
  626. "abs_path": None,
  627. "module": "org.a.b.g$a",
  628. "filename": None,
  629. "lineno": 68,
  630. "in_app": True,
  631. },
  632. {
  633. "function": "init",
  634. "abs_path": None,
  635. "module": "com.android.Zygote",
  636. "filename": None,
  637. "lineno": 62,
  638. },
  639. {
  640. "function": "a",
  641. "abs_path": None,
  642. "module": "org.a.b.g$b",
  643. "filename": None,
  644. "lineno": 70,
  645. },
  646. ]
  647. },
  648. "module": "org.a.b",
  649. "type": "g$a",
  650. "value": "Attempt to invoke virtual method 'org.a.b.g$a.a' on a null object reference",
  651. }
  652. ]
  653. },
  654. "timestamp": iso_format(before_now(seconds=1)),
  655. }
  656. event = self.post_and_retrieve_event(event_data)
  657. if not self.use_relay():
  658. # We measure the number of queries after an initial post,
  659. # because there are many queries polluting the array
  660. # before the actual "processing" happens (like, auth_user)
  661. with self.assertWriteQueries(
  662. {
  663. "nodestore_node": 2,
  664. "sentry_eventuser": 1,
  665. "sentry_groupedmessage": 1,
  666. "sentry_userreport": 1,
  667. }
  668. ):
  669. self.post_and_retrieve_event(event_data)
  670. exc = event.interfaces["exception"].values[0]
  671. bt = exc.stacktrace
  672. frames = bt.frames
  673. assert exc.module == "org.slf4j.helpers"
  674. assert frames[0].in_app is True
  675. assert frames[1].in_app is False
  676. assert frames[2].in_app is True
  677. assert frames[3].in_app is False
  678. assert frames[4].in_app is True
  679. @requires_symbolicator
  680. @pytest.mark.symbolicator
  681. def test_sets_inapp_after_resolving_symbolicator(self):
  682. with override_options({"symbolicator.proguard-processing-sample-rate": 1.0}):
  683. self.test_sets_inapp_after_resolving()
  684. def test_resolving_inline(self):
  685. self.upload_proguard_mapping(PROGUARD_INLINE_UUID, PROGUARD_INLINE_SOURCE)
  686. event_data = {
  687. "user": {"ip_address": "31.172.207.97"},
  688. "extra": {},
  689. "project": self.project.id,
  690. "platform": "java",
  691. "debug_meta": {"images": [{"type": "proguard", "uuid": PROGUARD_INLINE_UUID}]},
  692. "exception": {
  693. "values": [
  694. {
  695. "stacktrace": {
  696. "frames": [
  697. {
  698. "function": "onClick",
  699. "abs_path": None,
  700. "module": "e.a.c.a",
  701. "filename": None,
  702. "lineno": 2,
  703. },
  704. {
  705. "function": "t",
  706. "abs_path": None,
  707. "module": "io.sentry.sample.MainActivity",
  708. "filename": "MainActivity.java",
  709. "lineno": 1,
  710. },
  711. ]
  712. },
  713. "module": "org.a.b",
  714. "type": "g$a",
  715. "value": "Oh no",
  716. }
  717. ]
  718. },
  719. "timestamp": iso_format(before_now(seconds=1)),
  720. }
  721. event = self.post_and_retrieve_event(event_data)
  722. if not self.use_relay():
  723. # We measure the number of queries after an initial post,
  724. # because there are many queries polluting the array
  725. # before the actual "processing" happens (like, auth_user)
  726. with self.assertWriteQueries(
  727. {
  728. "nodestore_node": 2,
  729. "sentry_eventuser": 1,
  730. "sentry_groupedmessage": 1,
  731. "sentry_userreport": 1,
  732. }
  733. ):
  734. self.post_and_retrieve_event(event_data)
  735. exc = event.interfaces["exception"].values[0]
  736. bt = exc.stacktrace
  737. frames = bt.frames
  738. assert len(frames) == 4
  739. assert frames[0].function == "onClick"
  740. assert frames[0].module == "io.sentry.sample.-$$Lambda$r3Avcbztes2hicEObh02jjhQqd4"
  741. assert frames[1].filename == "MainActivity.java"
  742. assert frames[1].module == "io.sentry.sample.MainActivity"
  743. assert frames[1].function == "onClickHandler"
  744. assert frames[1].lineno == 40
  745. assert frames[2].function == "foo"
  746. assert frames[2].lineno == 44
  747. assert frames[3].function == "bar"
  748. assert frames[3].lineno == 54
  749. assert frames[3].filename == "MainActivity.java"
  750. assert frames[3].module == "io.sentry.sample.MainActivity"
  751. @requires_symbolicator
  752. @pytest.mark.symbolicator
  753. def test_resolving_inline_symbolicator(self):
  754. with override_options({"symbolicator.proguard-processing-sample-rate": 1.0}):
  755. self.test_resolving_inline()
  756. def test_resolving_inline_with_native_frames(self):
  757. self.upload_proguard_mapping(PROGUARD_INLINE_UUID, PROGUARD_INLINE_SOURCE)
  758. event_data = {
  759. "user": {"ip_address": "31.172.207.97"},
  760. "extra": {},
  761. "project": self.project.id,
  762. "platform": "java",
  763. "debug_meta": {"images": [{"type": "proguard", "uuid": PROGUARD_INLINE_UUID}]},
  764. "exception": {
  765. "values": [
  766. {
  767. "stacktrace": {
  768. "frames": [
  769. {
  770. "function": "onClick",
  771. "abs_path": None,
  772. "module": "e.a.c.a",
  773. "filename": None,
  774. "lineno": 2,
  775. },
  776. {
  777. "function": "t",
  778. "abs_path": None,
  779. "module": "io.sentry.sample.MainActivity",
  780. "filename": "MainActivity.java",
  781. "lineno": 1,
  782. },
  783. {
  784. "abs_path": "Thread.java",
  785. "filename": "Thread.java",
  786. "function": "sleep",
  787. "lineno": 450,
  788. "lock": {
  789. "address": "0x0ddc1f22",
  790. "class_name": "Object",
  791. "package_name": "java.lang",
  792. "type:": 1,
  793. },
  794. "module": "java.lang.Thread",
  795. },
  796. {
  797. "function": "__start_thread",
  798. "package": "/apex/com.android.art/lib64/libart.so",
  799. "lineno": 196,
  800. "in_app": False,
  801. },
  802. ]
  803. },
  804. "module": "org.a.b",
  805. "type": "g$a",
  806. "value": "Oh no",
  807. }
  808. ]
  809. },
  810. "timestamp": iso_format(before_now(seconds=1)),
  811. }
  812. event = self.post_and_retrieve_event(event_data)
  813. if not self.use_relay():
  814. # We measure the number of queries after an initial post,
  815. # because there are many queries polluting the array
  816. # before the actual "processing" happens (like, auth_user)
  817. with self.assertWriteQueries(
  818. {
  819. "nodestore_node": 2,
  820. "sentry_eventuser": 1,
  821. "sentry_groupedmessage": 1,
  822. "sentry_userreport": 1,
  823. }
  824. ):
  825. self.post_and_retrieve_event(event_data)
  826. exc = event.interfaces["exception"].values[0]
  827. bt = exc.stacktrace
  828. frames = bt.frames
  829. assert len(frames) == 6
  830. assert frames[0].function == "onClick"
  831. assert frames[0].module == "io.sentry.sample.-$$Lambda$r3Avcbztes2hicEObh02jjhQqd4"
  832. assert frames[1].filename == "MainActivity.java"
  833. assert frames[1].module == "io.sentry.sample.MainActivity"
  834. assert frames[1].function == "onClickHandler"
  835. assert frames[1].lineno == 40
  836. assert frames[2].function == "foo"
  837. assert frames[2].lineno == 44
  838. assert frames[3].function == "bar"
  839. assert frames[3].lineno == 54
  840. assert frames[3].filename == "MainActivity.java"
  841. assert frames[3].module == "io.sentry.sample.MainActivity"
  842. assert frames[4].function == "sleep"
  843. assert frames[4].lineno == 450
  844. assert frames[4].filename == "Thread.java"
  845. assert frames[4].module == "java.lang.Thread"
  846. assert frames[5].function == "__start_thread"
  847. assert frames[5].package == "/apex/com.android.art/lib64/libart.so"
  848. @requires_symbolicator
  849. @pytest.mark.symbolicator
  850. def test_resolving_inline_with_native_frames_symbolicator(self):
  851. with override_options({"symbolicator.proguard-processing-sample-rate": 1.0}):
  852. self.test_resolving_inline_with_native_frames()
  853. def test_error_on_resolving(self):
  854. url = reverse(
  855. "sentry-api-0-dsym-files",
  856. kwargs={
  857. "organization_slug": self.project.organization.slug,
  858. "project_slug": self.project.slug,
  859. },
  860. )
  861. self.login_as(user=self.user)
  862. out = BytesIO()
  863. f = zipfile.ZipFile(out, "w")
  864. f.writestr("proguard/%s.txt" % PROGUARD_BUG_UUID, PROGUARD_BUG_SOURCE)
  865. f.close()
  866. response = self.client.post(
  867. url,
  868. {
  869. "file": SimpleUploadedFile(
  870. "symbols.zip", out.getvalue(), content_type="application/zip"
  871. )
  872. },
  873. format="multipart",
  874. )
  875. assert response.status_code == 201, response.content
  876. assert len(response.json()) == 1
  877. event_data = {
  878. "user": {"ip_address": "31.172.207.97"},
  879. "extra": {},
  880. "project": self.project.id,
  881. "platform": "java",
  882. "debug_meta": {"images": [{"type": "proguard", "uuid": PROGUARD_BUG_UUID}]},
  883. "exception": {
  884. "values": [
  885. {
  886. "stacktrace": {
  887. "frames": [
  888. {
  889. "function": "a",
  890. "abs_path": None,
  891. "module": "org.a.b.g$a",
  892. "filename": None,
  893. "lineno": 67,
  894. },
  895. {
  896. "function": "a",
  897. "abs_path": None,
  898. "module": "org.a.b.g$a",
  899. "filename": None,
  900. "lineno": 69,
  901. },
  902. ]
  903. },
  904. "type": "RuntimeException",
  905. "value": "Oh no",
  906. }
  907. ]
  908. },
  909. "timestamp": iso_format(before_now(seconds=1)),
  910. }
  911. event = self.post_and_retrieve_event(event_data)
  912. assert len(event.data["errors"]) == 1
  913. error = event.data["errors"][0]
  914. assert error["mapping_uuid"] == "071207ac-b491-4a74-957c-2c94fd9594f2"
  915. assert error["type"] == "proguard_missing_lineno"
  916. @requires_symbolicator
  917. @pytest.mark.symbolicator
  918. def test_error_on_resolving_symbolicator(self):
  919. with override_options({"symbolicator.proguard-processing-sample-rate": 1.0}):
  920. self.test_error_on_resolving()
  921. def upload_jvm_bundle(self, debug_id, source_files):
  922. files = {}
  923. for source_file in source_files:
  924. files[f"files/_/_/{source_file}"] = {"url": f"~/{source_file}"}
  925. manifest = {
  926. "org": self.project.organization.slug,
  927. "project": self.project.slug,
  928. "debug_id": debug_id,
  929. "files": files,
  930. }
  931. file_like = BytesIO(b"SYSB")
  932. with zipfile.ZipFile(file_like, "a") as zip:
  933. for path, contents in source_files.items():
  934. zip.writestr(f"files/_/_/{path}", contents)
  935. zip.writestr("manifest.json", json.dumps(manifest))
  936. file_like.seek(0)
  937. file = File.objects.create(
  938. name="bundle.zip",
  939. type="sourcebundle",
  940. headers={"Content-Type": "application/x-sentry-bundle+zip"},
  941. )
  942. file.putfile(file_like)
  943. ProjectDebugFile.objects.create(
  944. project_id=self.project.id,
  945. debug_id=debug_id,
  946. file=file,
  947. )
  948. def test_basic_source_lookup(self):
  949. debug_id = str(uuid4())
  950. self.upload_jvm_bundle(debug_id, {"io/sentry/samples/MainActivity.jvm": JVM_SOURCE})
  951. event_data = {
  952. "user": {"ip_address": "31.172.207.97"},
  953. "extra": {},
  954. "project": self.project.id,
  955. "platform": "java",
  956. "debug_meta": {"images": [{"type": "jvm", "debug_id": debug_id}]},
  957. "exception": {
  958. "values": [
  959. {
  960. "stacktrace": {
  961. "frames": [
  962. {
  963. "function": "otherMethod",
  964. "abs_path": "OtherActivity.java",
  965. "module": "OtherActivity",
  966. "filename": "OtherActivity.java",
  967. "lineno": 100,
  968. },
  969. {
  970. "function": "differentMethod",
  971. "abs_path": "DifferentActivity",
  972. "module": "DifferentActivity",
  973. "filename": "DifferentActivity",
  974. "lineno": 200,
  975. },
  976. {
  977. "function": "onCreate",
  978. "abs_path": None,
  979. "module": "io.sentry.samples.MainActivity",
  980. "filename": None,
  981. "lineno": 11,
  982. },
  983. {
  984. "function": "whoops",
  985. "abs_path": "MainActivity.kt",
  986. "module": "io.sentry.samples.MainActivity$InnerClass",
  987. "filename": "MainActivity.kt",
  988. "lineno": 20,
  989. },
  990. {
  991. "function": "whoops2",
  992. "abs_path": None,
  993. "module": "io.sentry.samples.MainActivity$AnotherInnerClass",
  994. "filename": None,
  995. "lineno": 26,
  996. },
  997. {
  998. "function": "whoops3",
  999. "abs_path": "MainActivity.kt",
  1000. "module": "io.sentry.samples.MainActivity$AdditionalInnerClass",
  1001. "filename": "MainActivity.kt",
  1002. "lineno": 32,
  1003. },
  1004. {
  1005. "function": "whoops4",
  1006. "abs_path": "SourceFile",
  1007. "module": "io.sentry.samples.MainActivity$OneMoreInnerClass",
  1008. "filename": "SourceFile",
  1009. "lineno": 38,
  1010. },
  1011. ]
  1012. },
  1013. "module": "io.sentry.samples",
  1014. "type": "RuntimeException",
  1015. "value": "whoops",
  1016. }
  1017. ]
  1018. },
  1019. "timestamp": iso_format(before_now(seconds=1)),
  1020. }
  1021. event = self.post_and_retrieve_event(event_data)
  1022. if not self.use_relay():
  1023. # We measure the number of queries after an initial post,
  1024. # because there are many queries polluting the array
  1025. # before the actual "processing" happens (like, auth_user)
  1026. with self.assertWriteQueries(
  1027. {
  1028. "nodestore_node": 2,
  1029. "sentry_eventuser": 1,
  1030. "sentry_groupedmessage": 1,
  1031. "sentry_userreport": 1,
  1032. }
  1033. ):
  1034. self.post_and_retrieve_event(event_data)
  1035. exc = event.interfaces["exception"].values[0]
  1036. bt = exc.stacktrace
  1037. frames = bt.frames
  1038. assert exc.type == "RuntimeException"
  1039. assert exc.value == "whoops"
  1040. assert exc.module == "io.sentry.samples"
  1041. assert frames[0].function == "otherMethod"
  1042. assert frames[0].module == "OtherActivity"
  1043. assert frames[0].lineno == 100
  1044. assert frames[0].context_line is None
  1045. assert frames[0].pre_context is None
  1046. assert frames[0].post_context is None
  1047. assert frames[1].function == "differentMethod"
  1048. assert frames[1].module == "DifferentActivity"
  1049. assert frames[1].lineno == 200
  1050. assert frames[1].context_line is None
  1051. assert frames[1].pre_context is None
  1052. assert frames[1].post_context is None
  1053. assert frames[2].function == "onCreate"
  1054. assert frames[2].module == "io.sentry.samples.MainActivity"
  1055. assert frames[2].lineno == 11
  1056. assert frames[2].context_line == " InnerClass().whoops()"
  1057. assert frames[2].pre_context == [
  1058. "",
  1059. "class MainActivity : ComponentActivity() {",
  1060. " override fun onCreate(savedInstanceState: Bundle?) {",
  1061. " super.onCreate(savedInstanceState)",
  1062. " setContentView(R.layout.activity_main)",
  1063. ]
  1064. assert frames[2].post_context == [
  1065. "",
  1066. " val list = findViewById<RecyclerView>(R.id.list)",
  1067. " list.layoutManager = LinearLayoutManager(this)",
  1068. " list.adapter = TrackAdapter()",
  1069. " }",
  1070. ]
  1071. assert frames[3].function == "whoops"
  1072. assert frames[3].module == "io.sentry.samples.MainActivity$InnerClass"
  1073. assert frames[3].lineno == 20
  1074. assert frames[3].context_line == " AnotherInnerClass().whoops2()"
  1075. assert frames[3].pre_context == [
  1076. " list.adapter = TrackAdapter()",
  1077. " }",
  1078. "",
  1079. " class InnerClass {",
  1080. " fun whoops() {",
  1081. ]
  1082. assert frames[3].post_context == [
  1083. " }",
  1084. " }",
  1085. "",
  1086. " class AnotherInnerClass {",
  1087. " fun whoops2() {",
  1088. ]
  1089. assert frames[4].function == "whoops2"
  1090. assert frames[4].module == "io.sentry.samples.MainActivity$AnotherInnerClass"
  1091. assert frames[4].lineno == 26
  1092. assert frames[4].context_line == " AdditionalInnerClass().whoops3()"
  1093. assert frames[4].pre_context == [
  1094. " }",
  1095. " }",
  1096. "",
  1097. " class AnotherInnerClass {",
  1098. " fun whoops2() {",
  1099. ]
  1100. assert frames[4].post_context == [
  1101. " }",
  1102. " }",
  1103. "",
  1104. " class AdditionalInnerClass {",
  1105. " fun whoops3() {",
  1106. ]
  1107. assert frames[5].function == "whoops3"
  1108. assert frames[5].module == "io.sentry.samples.MainActivity$AdditionalInnerClass"
  1109. assert frames[5].lineno == 32
  1110. assert frames[5].context_line == " OneMoreInnerClass().whoops4()"
  1111. assert frames[5].pre_context == [
  1112. " }",
  1113. " }",
  1114. "",
  1115. " class AdditionalInnerClass {",
  1116. " fun whoops3() {",
  1117. ]
  1118. assert frames[5].post_context == [
  1119. " }",
  1120. " }",
  1121. "",
  1122. " class OneMoreInnerClass {",
  1123. " fun whoops4() {",
  1124. ]
  1125. assert frames[6].function == "whoops4"
  1126. assert frames[6].module == "io.sentry.samples.MainActivity$OneMoreInnerClass"
  1127. assert frames[6].lineno == 38
  1128. assert frames[6].context_line == ' throw RuntimeException("whoops")'
  1129. assert frames[6].pre_context == [
  1130. " }",
  1131. " }",
  1132. "",
  1133. " class OneMoreInnerClass {",
  1134. " fun whoops4() {",
  1135. ]
  1136. assert frames[6].post_context == [" }", " }", "}", ""]
  1137. @requires_symbolicator
  1138. @pytest.mark.symbolicator
  1139. def test_basic_source_lookup_symbolicator(self):
  1140. with override_options({"symbolicator.proguard-processing-sample-rate": 1.0}):
  1141. self.test_basic_source_lookup()
  1142. def test_source_lookup_with_proguard(self):
  1143. self.upload_proguard_mapping(PROGUARD_SOURCE_LOOKUP_UUID, PROGUARD_SOURCE_LOOKUP_SOURCE)
  1144. debug_id1 = str(uuid4())
  1145. self.upload_jvm_bundle(
  1146. debug_id1,
  1147. {
  1148. "io/sentry/samples/instrumentation/ui/EditActivity.jvm": EDIT_ACTIVITY_SOURCE,
  1149. },
  1150. )
  1151. debug_id2 = str(uuid4())
  1152. self.upload_jvm_bundle(
  1153. debug_id2,
  1154. {
  1155. "io/sentry/samples/instrumentation/ui/SomeService.jvm": SOME_SERVICE_SOURCE,
  1156. },
  1157. )
  1158. event_data = {
  1159. "user": {"ip_address": "31.172.207.97"},
  1160. "extra": {},
  1161. "project": self.project.id,
  1162. "platform": "java",
  1163. "debug_meta": {
  1164. "images": [
  1165. {
  1166. "type": "jvm",
  1167. "debug_id": debug_id1,
  1168. },
  1169. {
  1170. "type": "jvm",
  1171. "debug_id": debug_id2,
  1172. },
  1173. {
  1174. "type": "jvm",
  1175. "debug_id": str(uuid4()),
  1176. }, # does not exist
  1177. {"type": "proguard", "uuid": PROGUARD_SOURCE_LOOKUP_UUID},
  1178. {"type": "proguard", "uuid": str(uuid4())}, # does not exist
  1179. ]
  1180. },
  1181. "exception": {
  1182. "values": [
  1183. {
  1184. "type": "RuntimeException",
  1185. "value": "thrown on purpose to test ProGuard Android source context",
  1186. "module": "java.lang",
  1187. "thread_id": 1,
  1188. "stacktrace": {
  1189. "frames": [
  1190. {
  1191. "filename": "ZygoteInit.java",
  1192. "function": "main",
  1193. "module": "com.android.internal.os.ZygoteInit",
  1194. "lineno": 698,
  1195. "native": False,
  1196. },
  1197. {
  1198. "filename": "ZygoteInit.java",
  1199. "function": "run",
  1200. "module": "com.android.internal.os.ZygoteInit$MethodAndArgsCaller",
  1201. "lineno": 903,
  1202. "native": False,
  1203. },
  1204. {
  1205. "filename": "Method.java",
  1206. "function": "invoke",
  1207. "module": "java.lang.reflect.Method",
  1208. "lineno": 372,
  1209. "native": False,
  1210. },
  1211. {
  1212. "filename": "Method.java",
  1213. "function": "invoke",
  1214. "module": "java.lang.reflect.Method",
  1215. "native": True,
  1216. },
  1217. {
  1218. "filename": "ActivityThread.java",
  1219. "function": "main",
  1220. "module": "android.app.ActivityThread",
  1221. "lineno": 5254,
  1222. "native": False,
  1223. },
  1224. {
  1225. "filename": "Looper.java",
  1226. "function": "loop",
  1227. "module": "android.os.Looper",
  1228. "lineno": 135,
  1229. "native": False,
  1230. },
  1231. {
  1232. "filename": "Handler.java",
  1233. "function": "dispatchMessage",
  1234. "module": "android.os.Handler",
  1235. "lineno": 95,
  1236. "native": False,
  1237. },
  1238. {
  1239. "filename": "Handler.java",
  1240. "function": "handleCallback",
  1241. "module": "android.os.Handler",
  1242. "lineno": 739,
  1243. "native": False,
  1244. },
  1245. {
  1246. "filename": "View.java",
  1247. "function": "run",
  1248. "module": "android.view.View$PerformClick",
  1249. "lineno": 19866,
  1250. "native": False,
  1251. },
  1252. {
  1253. "filename": "View.java",
  1254. "function": "performClick",
  1255. "module": "android.view.View",
  1256. "lineno": 4780,
  1257. "native": False,
  1258. },
  1259. {
  1260. "filename": "ActionMenuItemView.java",
  1261. "function": "onClick",
  1262. "module": "androidx.appcompat.view.menu.ActionMenuItemView",
  1263. "lineno": 7,
  1264. "native": False,
  1265. },
  1266. {
  1267. "filename": "ActionMenuView.java",
  1268. "function": "invokeItem",
  1269. "module": "androidx.appcompat.widget.ActionMenuView",
  1270. "lineno": 4,
  1271. "native": False,
  1272. },
  1273. {
  1274. "filename": "MenuBuilder.java",
  1275. "function": "performItemAction",
  1276. "module": "androidx.appcompat.view.menu.MenuBuilder",
  1277. "lineno": 1,
  1278. "native": False,
  1279. },
  1280. {
  1281. "filename": "MenuBuilder.java",
  1282. "function": "performItemAction",
  1283. "module": "androidx.appcompat.view.menu.MenuBuilder",
  1284. "lineno": 4,
  1285. "native": False,
  1286. },
  1287. {
  1288. "filename": "MenuItemImpl.java",
  1289. "function": "invoke",
  1290. "module": "androidx.appcompat.view.menu.MenuItemImpl",
  1291. "lineno": 15,
  1292. "native": False,
  1293. },
  1294. {
  1295. "filename": "MenuBuilder.java",
  1296. "function": "dispatchMenuItemSelected",
  1297. "module": "androidx.appcompat.view.menu.MenuBuilder",
  1298. "lineno": 5,
  1299. "native": False,
  1300. },
  1301. {
  1302. "filename": "ActionMenuView.java",
  1303. "function": "onMenuItemSelected",
  1304. "module": "androidx.appcompat.widget.ActionMenuView$MenuBuilderCallback",
  1305. "lineno": 7,
  1306. "native": False,
  1307. },
  1308. {
  1309. "filename": "Toolbar.java",
  1310. "function": "onMenuItemClick",
  1311. "module": "androidx.appcompat.widget.Toolbar$1",
  1312. "lineno": 7,
  1313. "native": False,
  1314. },
  1315. {
  1316. "filename": "R8$$SyntheticClass",
  1317. "function": "onMenuItemClick",
  1318. "module": "io.sentry.samples.instrumentation.ui.g",
  1319. "lineno": 40,
  1320. "in_app": True,
  1321. "native": False,
  1322. },
  1323. ]
  1324. },
  1325. }
  1326. ]
  1327. },
  1328. "timestamp": iso_format(before_now(seconds=1)),
  1329. }
  1330. event = self.post_and_retrieve_event(event_data)
  1331. if not self.use_relay():
  1332. # We measure the number of queries after an initial post,
  1333. # because there are many queries polluting the array
  1334. # before the actual "processing" happens (like, auth_user)
  1335. with self.assertWriteQueries(
  1336. {
  1337. "nodestore_node": 2,
  1338. "sentry_eventuser": 1,
  1339. "sentry_groupedmessage": 1,
  1340. "sentry_userreport": 1,
  1341. }
  1342. ):
  1343. self.post_and_retrieve_event(event_data)
  1344. exc = event.interfaces["exception"].values[0]
  1345. bt = exc.stacktrace
  1346. frames = bt.frames
  1347. assert exc.type == "RuntimeException"
  1348. assert exc.value == "thrown on purpose to test ProGuard Android source context"
  1349. assert exc.module == "java.lang"
  1350. assert frames[18].function == "onMenuItemClick"
  1351. assert (
  1352. frames[18].module
  1353. == "io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0"
  1354. )
  1355. assert frames[18].lineno == 0
  1356. assert frames[18].context_line is None
  1357. assert frames[18].pre_context is None
  1358. assert frames[18].post_context is None
  1359. assert frames[19].function == "onCreate$lambda-1"
  1360. assert frames[19].module == "io.sentry.samples.instrumentation.ui.EditActivity"
  1361. assert frames[19].lineno == 37
  1362. assert frames[19].context_line == " SomeService().helloThere()"
  1363. assert frames[19].pre_context == [
  1364. " }",
  1365. "",
  1366. " findViewById<Toolbar>(R.id.toolbar).setOnMenuItemClickListener {",
  1367. " if (it.itemId == R.id.action_save) {",
  1368. " try {",
  1369. ]
  1370. assert frames[19].post_context == [
  1371. " } catch (e: Exception) {",
  1372. " Sentry.captureException(e)",
  1373. " }",
  1374. "",
  1375. " val transaction = Sentry.startTransaction(",
  1376. ]
  1377. assert frames[20].function == "helloThere"
  1378. assert frames[20].module == "io.sentry.samples.instrumentation.ui.SomeService"
  1379. assert frames[20].lineno == 5
  1380. assert frames[20].context_line == " InnerClassOfSomeService().helloInner()"
  1381. assert frames[20].pre_context == [
  1382. "package io.sentry.samples.instrumentation.ui",
  1383. "",
  1384. "class SomeService {",
  1385. " fun helloThere() {",
  1386. ]
  1387. assert frames[20].post_context == [
  1388. " }",
  1389. "",
  1390. " class InnerClassOfSomeService {",
  1391. " fun helloInner() {",
  1392. " AnotherClassInSameFile().helloOther()",
  1393. ]
  1394. assert frames[21].function == "helloInner"
  1395. assert (
  1396. frames[21].module
  1397. == "io.sentry.samples.instrumentation.ui.SomeService$InnerClassOfSomeService"
  1398. )
  1399. assert frames[21].lineno == 10
  1400. assert frames[21].context_line == " AnotherClassInSameFile().helloOther()"
  1401. assert frames[21].pre_context == [
  1402. " InnerClassOfSomeService().helloInner()",
  1403. " }",
  1404. "",
  1405. " class InnerClassOfSomeService {",
  1406. " fun helloInner() {",
  1407. ]
  1408. assert frames[21].post_context == [
  1409. " }",
  1410. " }",
  1411. "}",
  1412. "",
  1413. "class AnotherClassInSameFile {",
  1414. ]
  1415. assert frames[22].function == "helloOther"
  1416. assert frames[22].module == "io.sentry.samples.instrumentation.ui.AnotherClassInSameFile"
  1417. assert frames[22].lineno == 17
  1418. assert frames[22].context_line is None
  1419. assert frames[22].pre_context is None
  1420. assert frames[22].post_context is None
  1421. assert frames[23].function == "otherFun"
  1422. assert frames[23].module == "io.sentry.samples.instrumentation.ui.AnotherClassInSameFile"
  1423. assert frames[23].lineno == 21
  1424. assert frames[23].context_line is None
  1425. assert frames[23].pre_context is None
  1426. assert frames[23].post_context is None
  1427. assert frames[24].function == "helloOtherInner"
  1428. assert (
  1429. frames[24].module
  1430. == "io.sentry.samples.instrumentation.ui.AnotherClassInSameFile$AnotherInnerClass"
  1431. )
  1432. assert frames[24].lineno == 26
  1433. assert frames[24].context_line is None
  1434. assert frames[24].pre_context is None
  1435. assert frames[24].post_context is None
  1436. @requires_symbolicator
  1437. @pytest.mark.symbolicator
  1438. def test_source_lookup_with_proguard_symbolicator(self):
  1439. with override_options({"symbolicator.proguard-processing-sample-rate": 1.0}):
  1440. self.test_source_lookup_with_proguard()
  1441. @requires_symbolicator
  1442. @pytest.mark.symbolicator
  1443. def test_invalid_exception(self):
  1444. with override_options({"symbolicator.proguard-processing-sample-rate": 1.0}):
  1445. event_data = {
  1446. "user": {"ip_address": "31.172.207.97"},
  1447. "extra": {},
  1448. "project": self.project.id,
  1449. "platform": "java",
  1450. "debug_meta": {},
  1451. "exception": {
  1452. "values": [
  1453. {"type": "PlatformException"},
  1454. {"type": "SecurityException", "module": "java.lang"},
  1455. {"type": "RemoteException", "module": "android.os"},
  1456. ]
  1457. },
  1458. "timestamp": iso_format(before_now(seconds=1)),
  1459. }
  1460. event = self.post_and_retrieve_event(event_data)
  1461. expected = [
  1462. {"type": e.get("type", None), "module": e.get("module", None)}
  1463. for e in event_data["exception"]["values"]
  1464. ]
  1465. received = [
  1466. {"type": e.type, "module": e.module} for e in event.interfaces["exception"].values
  1467. ]
  1468. assert received == expected
  1469. def test_is_jvm_event(self):
  1470. from sentry.lang.java.utils import is_jvm_event
  1471. from sentry.stacktraces.processing import find_stacktraces_in_data
  1472. event = {
  1473. "user": {"ip_address": "31.172.207.97"},
  1474. "extra": {},
  1475. "project": self.project.id,
  1476. "platform": "java",
  1477. "debug_meta": {"images": [{"type": "jvm", "debug_id": PROGUARD_INLINE_UUID}]},
  1478. "exception": {
  1479. "values": [
  1480. {
  1481. "stacktrace": {
  1482. "frames": [
  1483. {
  1484. "function": "whoops4",
  1485. "abs_path": "SourceFile",
  1486. "module": "io.sentry.samples.MainActivity$OneMoreInnerClass",
  1487. "filename": "SourceFile",
  1488. "lineno": 38,
  1489. },
  1490. ]
  1491. },
  1492. "module": "io.sentry.samples",
  1493. "type": "RuntimeException",
  1494. "value": "whoops",
  1495. }
  1496. ]
  1497. },
  1498. "timestamp": iso_format(before_now(seconds=1)),
  1499. }
  1500. stacktraces = find_stacktraces_in_data(event)
  1501. assert is_jvm_event(event, stacktraces)
  1502. event = {
  1503. "user": {"ip_address": "31.172.207.97"},
  1504. "extra": {},
  1505. "project": self.project.id,
  1506. "debug_meta": {"images": [{"type": "jvm", "debug_id": PROGUARD_INLINE_UUID}]},
  1507. "exception": {
  1508. "values": [
  1509. {
  1510. "stacktrace": {
  1511. "frames": [
  1512. {
  1513. "function": "whoops4",
  1514. "abs_path": "SourceFile",
  1515. "module": "io.sentry.samples.MainActivity$OneMoreInnerClass",
  1516. "filename": "SourceFile",
  1517. "lineno": 38,
  1518. },
  1519. ]
  1520. },
  1521. "module": "io.sentry.samples",
  1522. "type": "RuntimeException",
  1523. "value": "whoops",
  1524. }
  1525. ]
  1526. },
  1527. "timestamp": iso_format(before_now(seconds=1)),
  1528. }
  1529. stacktraces = find_stacktraces_in_data(event)
  1530. # has no platform
  1531. assert not is_jvm_event(event, stacktraces)
  1532. event = {
  1533. "user": {"ip_address": "31.172.207.97"},
  1534. "extra": {},
  1535. "project": self.project.id,
  1536. "platform": "java",
  1537. "debug_meta": {},
  1538. "exception": {
  1539. "values": [
  1540. {
  1541. "stacktrace": {
  1542. "frames": [
  1543. {
  1544. "function": "whoops4",
  1545. "abs_path": "SourceFile",
  1546. "module": "io.sentry.samples.MainActivity$OneMoreInnerClass",
  1547. "filename": "SourceFile",
  1548. "lineno": 38,
  1549. },
  1550. ]
  1551. },
  1552. "module": "io.sentry.samples",
  1553. "type": "RuntimeException",
  1554. "value": "whoops",
  1555. }
  1556. ]
  1557. },
  1558. "timestamp": iso_format(before_now(seconds=1)),
  1559. }
  1560. stacktraces = find_stacktraces_in_data(event)
  1561. # has no modules
  1562. assert not is_jvm_event(event, stacktraces)