elastic / apm-agent-ios

Apache License 2.0
31 stars 14 forks source link

Add "error.culprit" to errors & crashes where applicable #204

Open bryce-b opened 7 months ago

bryce-b commented 7 months ago

This may be calculated on the device or on the apm server, whichever makes more sense.

"culprit" : "description": "Culprit identifies the function call which was the primary perpetrator of this event.",

The culprit should be calculated as the first frame from the customer's application or framework. This can be done by looking at the stack trace frame by frame and calculate whether the memory address is from a relevant library. For example in this abbreviated stack trace:

 Thread 0 Crashed:
0   libswiftCore.dylib                  0x00000001a9b75534 0x1a9b3d000 + 230708
1   opbeans-swift                       0x0000000102c5c108 0x102c30000 + 180488
2   SwiftUI                             0x00000001b5fe9a4c 0x1b447b000 + 28764748
3   SwiftUI                             0x00000001b58e838c 0x1b447b000 + 21418892
4   SwiftUI                             0x00000001b55db624 0x1b447b000 + 18220580
5   SwiftUI                             0x00000001b55db64c 0x1b447b000 + 18220620
6   SwiftUI                             0x00000001b55db624 0x1b447b000 + 18220580
7   SwiftUI                             0x00000001b5e46ebc 0x1b447b000 + 27049660
8   SwiftUI                             0x00000001b5e475d4 0x1b447b000 + 27051476
9   SwiftUI                             0x00000001b6019d98 0x1b447b000 + 28962200
10  SwiftUI                             0x00000001b5d8f260 0x1b447b000 + 26296928
11  SwiftUI                             0x00000001b5d8d774 0x1b447b000 + 26290036
12  SwiftUI                             0x00000001b5d8d904 0x1b447b000 + 26290436
13  UIKitCore                           0x00000001b2b099e0 0x1b29a5000 + 1460704
14  UIKitCore                           0x00000001b29c3b2c 0x1b29a5000 + 125740
15  UIKitCore                           0x00000001b29c01ac 0x1b29a5000 + 111020
16  UIKitCore                           0x00000001b29c00d8 0x1b29a5000 + 110808
17  UIKitCore                           0x00000001b2ba762c 0x1b29a5000 + 2106924
18  UIKitCore                           0x00000001b2ba68bc 0x1b29a5000 + 2103484
19  UIKitCore                           0x00000001b2b691f8 0x1b29a5000 + 1851896
20  UIKitCore                           0x00000001b2b674fc 0x1b29a5000 + 1844476
21  UIKitCore                           0x00000001b2b65f08 0x1b29a5000 + 1838856
22  UIKitCore                           0x00000001b2a4f7e4 0x1b29a5000 + 698340
23  UIKitCore                           0x00000001b2a4eed4 0x1b29a5000 + 696020
24  UIKitCore                           0x00000001b2a4ef90 0x1b29a5000 + 696208
25  CoreFoundation                      0x00000001b07b112c 0x1b077a000 + 225580
26  CoreFoundation                      0x00000001b07b03a8 0x1b077a000 + 222120
27  CoreFoundation                      0x00000001b07aeb5c 0x1b077a000 + 215900
28  CoreFoundation                      0x00000001b07ad898 0x1b077a000 + 211096
29  CoreFoundation                      0x00000001b07ad478 0x1b077a000 + 210040
30  GraphicsServices                    0x00000001f3d2e4f8 0x1f3d2b000 + 13560
31  UIKitCore                           0x00000001b2bd162c 0x1b29a5000 + 2278956
32  UIKitCore                           0x00000001b2bd0c68 0x1b29a5000 + 2276456
33  SwiftUI                             0x00000001b55e14b8 0x1b447b000 + 18244792
34  SwiftUI                             0x00000001b55e12fc 0x1b447b000 + 18244348
35  SwiftUI                             0x00000001b5251e90 0x1b447b000 + 14511760
36  opbeans-swift                       0x0000000102c5f210 0x102c30000 + 193040
37  opbeans-swift                       0x0000000102c5f2c0 0x102c30000 + 193216
38  ???                                 0x00000001d34e6dcc 0x0 + 0

Binary Images:
0x102c30000 -        0x103c33fff +opbeans-swift arm64  <c3596057e5ac37ada926e0fdbf35d3d2> /private/var/containers/Bundle/Application/D285BC54-A109-4BA6-9A64-C7377280156A/opbeans-swift.app/opbeans-swift
       0x105404000 -        0x10540ffff  libobjc-trampolines.dylib arm64e  <26d68e81199a300dbc1530ba4630a611> /private/preboot/Cryptexes/OS/usr/lib/libobjc-trampolines.dylib
       0x1a8ac4000 -        0x1a8b11fe0  libobjc.A.dylib arm64e  <98c1e5b8c56e3b9c9783b0fef8f999ee> /usr/lib/libobjc.A.dylib
       0x1a8b12000 -        0x1a9b3cfff  MetalPerformanceShadersGraph arm64e  <7edabf0b3f683a48bd6bb4bf0ae0cac0> /System/Library/Frameworks/MetalPerformanceShadersGraph.framework/MetalPerformanceShadersGraph
       0x1a9b3d000 -        0x1aa092fff  libswiftCore.dylib arm64e  <27d61aad68b03df0925df1590bae4ac9> /usr/lib/swift/libswiftCore.dylib
       0x1aa093000 -        0x1aa0c7ffb  CoreServicesInternal arm64e  <ad2abdd3728531049088efad741d28c8> /System/Library/PrivateFrameworks/CoreServicesInternal.framework/CoreServicesInternal
       0x1af714000 -        0x1b0273fff  Foundation arm64e  <c52a963060f13d48a6c350a20de78c6a> /System/Library/Frameworks/Foundation.framework/Foundation
       0x1b0274000 -        0x1b0362fff  WebGPU arm64e  <d4ad9adb83343918beba2c0f52ff7ad7> /System/Library/PrivateFrameworks/WebGPU.framework/WebGPU
...

How can we determine a library is a "user library"? This can be determined by the path of the library. Above we can see opbeans-swift has the path : /private/var/containers/Bundle/Application/. This path indicates user package or framework. System libraries have /System/Library/Frameworks/, /usr/lib/', or/private/preboot/`

Looking at the crash frames : we see this structure:

0 libswiftCore.dylib 0x00000001a9b75534 0x1a9b3d000 + 230708 frame # library name line address image address line address offset
0 libswiftCore.dylib 0x00000001a9b75534 0x1a9b3d000 + 230708

note: image address + line address offset = line address

we can use either the library name or the image address from the frame to determine which binary image path to determine if it is a user library or system library.

libSwiftCore.dylib's path starts with /usr/lib/ which indicates a system library. This is not the culprit.

The next line: 1 opbeans-swift 0x0000000102c5c108 0x102c30000 + 180488 this frame is from opbeans-swift, which has the path prefix /private/var/containers/Bundle/Application/ which indicates it's a user library. We can use this address, 0x0000000102c5c108, as the culprit.

bryce-b commented 7 months ago

note: some errors will not have stack traces: such as network errors and http errors.