-
-
Notifications
You must be signed in to change notification settings - Fork 333
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
File IO integration not working for iOS 18 #4546
Comments
If we can't swizzle certain file IO operations, we can create an Extension or a SentryFileManager class wrapping file IO operations and adding spans. |
To figure out when the changes were introduced, I went ahead and ran the failing unit tests in
It seems that the internal implementation of Based on the current implementation it is assumed that NSFileManager uses NSData to create the new file. This was most likely changed to a different implementation without NSData, therefore not getting recognized by the NSData swizzling. Next I'll try to figure out if we have to swizzle NSFileManager to fix this, or if it still uses some alternative class like NSData we want to track instead. |
I focused on the failing test For visualization of the differences, I added logging statements to Test Log iOS 17.5:Test Suite 'Selected tests' started at 2024-12-06 10:56:21.317. Test Suite 'SentryTests.xctest' started at 2024-12-06 10:56:21.318. Test Suite 'SentryFileIOTrackingIntegrationObjCTests' started at 2024-12-06 10:56:21.318. Test Case '-[SentryFileIOTrackingIntegrationObjCTests test_NSFileManagerCreateFile]' started. SWIZZLE NSData.writeToFile:options:error: --> SentryNSDataTracker.measureNSData:writeToFile:options:error SWIZZLE NSData.initWithContentsOfFile: --> SentryNSDataTracker.measureNSDataFromFile:path: SWIZZLE NSData.initWithContentsOfFile: --> SentryNSDataTracker.measureNSDataFromFile:path: SWIZZLE NSData.writeToFile:options:error: --> SentryNSDataTracker.measureNSData:writeToFile:options:error Test Case '-[SentryFileIOTrackingIntegrationObjCTests test_NSFileManagerCreateFile]' passed (0.067 seconds). Test Suite 'SentryFileIOTrackingIntegrationObjCTests' passed at 2024-12-06 10:56:21.385. Executed 1 test, with 0 failures (0 unexpected) in 0.067 (0.068) seconds Test Suite 'SentryTests.xctest' passed at 2024-12-06 10:56:21.386. Executed 1 test, with 0 failures (0 unexpected) in 0.067 (0.068) seconds Test Suite 'Selected tests' passed at 2024-12-06 10:56:21.386. Executed 1 test, with 0 failures (0 unexpected) in 0.067 (0.069) seconds Program ended with exit code: 0 Test Log iOS 18.1:Test Suite 'Selected tests' started at 2024-12-06 10:55:39.607. Test Suite 'SentryTests.xctest' started at 2024-12-06 10:55:39.607. Test Suite 'SentryFileIOTrackingIntegrationObjCTests' started at 2024-12-06 10:55:39.607. Test Case '-[SentryFileIOTrackingIntegrationObjCTests test_NSFileManagerCreateFile]' started. SentryFileIOTrackingIntegrationObjCTests.m:212: error: -[SentryFileIOTrackingIntegrationObjCTests test_NSFileManagerCreateFile] : ((parentTransaction.children.count) equal to (1)) failed: ("0") is not equal to ("1") SentryFileIOTrackingIntegrationObjCTests.m:213: error: -[SentryFileIOTrackingIntegrationObjCTests test_NSFileManagerCreateFile] : (([ioSpan.data[@"file.size"] unsignedIntValue]) equal to (someData.length)) failed: ("0") is not equal to ("9") SentryFileIOTrackingIntegrationObjCTests.m:214: error: -[SentryFileIOTrackingIntegrationObjCTests test_NSFileManagerCreateFile] : ((ioSpan.data[@"file.path"]) equal to (filePath)) failed: ("(null)") is not equal to ("/Users/philip/Library/Developer/CoreSimulator/Devices/772691D9-D886-456C-8801-DFEC684B3ACF/data/Documents/TestFile") SentryFileIOTrackingIntegrationObjCTests.m:215: error: -[SentryFileIOTrackingIntegrationObjCTests test_NSFileManagerCreateFile] : ((operation) equal to (ioSpan.operation)) failed: ("file.write") is not equal to ("(null)") SentryFileIOTrackingIntegrationObjCTests.m:225: error: -[SentryFileIOTrackingIntegrationObjCTests test_NSFileManagerCreateFile] : ((ioSpan.spanDescription) equal to (expectedString)) failed: ("(null)") is not equal to ("TestFile (9 bytes)") SWIZZLE NSData.initWithContentsOfFile: --> SentryNSDataTracker.measureNSDataFromFile:path: SWIZZLE NSData.initWithContentsOfFile: --> SentryNSDataTracker.measureNSDataFromFile:path: SWIZZLE NSData.writeToFile:options:error: --> SentryNSDataTracker.measureNSData:writeToFile:options:error Test Case '-[SentryFileIOTrackingIntegrationObjCTests test_NSFileManagerCreateFile]' failed (0.106 seconds). Test Suite 'SentryFileIOTrackingIntegrationObjCTests' failed at 2024-12-06 10:55:39.713. Executed 1 test, with 5 failures (0 unexpected) in 0.106 (0.106) seconds Test Suite 'SentryTests.xctest' failed at 2024-12-06 10:55:39.713. Executed 1 test, with 5 failures (0 unexpected) in 0.106 (0.106) seconds Test Suite 'Selected tests' failed at 2024-12-06 10:55:39.714. Executed 1 test, with 5 failures (0 unexpected) in 0.106 (0.107) seconds Program ended with exit code: 1 Test Log macOS 15.1.1:Test Suite 'Selected tests' started at 2024-12-06 10:55:19.464. Test Suite 'SentryTests.xctest' started at 2024-12-06 10:55:19.470. Test Suite 'SentryFileIOTrackingIntegrationObjCTests' started at 2024-12-06 10:55:19.474. Test Case '-[SentryFileIOTrackingIntegrationObjCTests test_NSFileManagerCreateFile]' started. SentryFileIOTrackingIntegrationObjCTests.m:212: error: -[SentryFileIOTrackingIntegrationObjCTests test_NSFileManagerCreateFile] : ((parentTransaction.children.count) equal to (1)) failed: ("0") is not equal to ("1") SentryFileIOTrackingIntegrationObjCTests.m:213: error: -[SentryFileIOTrackingIntegrationObjCTests test_NSFileManagerCreateFile] : (([ioSpan.data[@"file.size"] unsignedIntValue]) equal to (someData.length)) failed: ("0") is not equal to ("9") SentryFileIOTrackingIntegrationObjCTests.m:214: error: -[SentryFileIOTrackingIntegrationObjCTests test_NSFileManagerCreateFile] : ((ioSpan.data[@"file.path"]) equal to (filePath)) failed: ("(null)") is not equal to ("/Users/philip/Documents/TestFile") SentryFileIOTrackingIntegrationObjCTests.m:215: error: -[SentryFileIOTrackingIntegrationObjCTests test_NSFileManagerCreateFile] : ((operation) equal to (ioSpan.operation)) failed: ("file.write") is not equal to ("(null)") SentryFileIOTrackingIntegrationObjCTests.m:225: error: -[SentryFileIOTrackingIntegrationObjCTests test_NSFileManagerCreateFile] : ((ioSpan.spanDescription) equal to (expectedString)) failed: ("(null)") is not equal to ("TestFile (9 bytes)") SWIZZLE NSData.initWithContentsOfFile: --> SentryNSDataTracker.measureNSDataFromFile:path: Test Case '-[SentryFileIOTrackingIntegrationObjCTests test_NSFileManagerCreateFile]' failed (0.597 seconds). Test Suite 'SentryFileIOTrackingIntegrationObjCTests' failed at 2024-12-06 10:55:20.080. Executed 1 test, with 5 failures (0 unexpected) in 0.597 (0.606) seconds Test Suite 'SentryTests.xctest' failed at 2024-12-06 10:55:20.086. Executed 1 test, with 5 failures (0 unexpected) in 0.597 (0.615) seconds Test Suite 'Selected tests' failed at 2024-12-06 10:55:20.092. Executed 1 test, with 5 failures (0 unexpected) in 0.597 (0.628) seconds Program ended with exit code: 1 It seems like I enabled objc message logging by setting the test run environment flag The full message log just for the call of After swizzling |
We also have this failing tests:
But we could split the solutions into different PRs. |
@brustolin I see tests failing now too. I believe they are related to my changes so I will look into it in this PR. I enabled testing for iOS 18 and macOS 15 due to the results of the investigation and verifying backwards compatibility |
This tests also fail in my draft PR, I dont think its related to your changes but other IO api changes from Apple. |
I created a simple Objective-C message logger to log the messages dispatched by let tempPath = URL(fileURLWithPath: NSTemporaryDirectory())
.appending(path: UUID().uuidString)
.appendingPathExtension("tmp")
let data = Data()
let manager = FileManager.default
// -- EXECUTE --
let logs = try collectLogs {
// manager.createFile(atPath: tempPath.absoluteString, contents: data, attributes: nil)
let _ = NSString("Hello World")
} This excerpt of the diff clearly shows how the new internal implementation is not using macOS 14.6.1:
< - _NSZeroData NSData writeToFile:options:error:
< - __NSCFString NSString getFileSystemRepresentation:maxLength:
< - __NSCFString __NSCFString isEqual:
< - __NSCFString NSString stringByDeletingLastPathComponent
< - __NSCFString __NSCFString length
< - __NSCFString __NSCFString getCharacters:range:
< + NSPathStore2 NSPathStore2 pathStoreWithCharacters:length:
macOS 15.1.1:
> - _NSFileManagerBridge _NSFileManagerBridge createFileAtPath:contents:attributes:
> - __NSCFString __NSCFString retain
> - __NSCFString __NSCFString copyWithZone:
> - __NSCFString __NSCFString _fastCStringContents:
> - __NSCFString __NSCFString length
> - __NSCFString __NSCFString retain
> - __NSCFString __NSCFString release
> - __NSCFString __NSCFString release
> - _NSZeroData _NSZeroData retain
> - _NSZeroData _NSZeroData length
> - _NSZeroData _NSZeroData release
> - __NSCFString __NSCFString retain
> + NSURL NSURL allocWithZone:
> - __NSCFString __NSCFString retain
> - __NSCFString __NSCFString release
> - NSURL NSURL initFileURLWithPath:
> - __NSCFString __NSCFString length
> - __NSCFString NSString isAbsolutePath
> - __NSCFString __NSCFString length
> - __NSCFString __NSCFString getCharacters:range:
> - __NSCFString NSString stringByStandardizingPath
> - __NSCFString NSString _stringByStandardizingPathUsingCache:
> - __NSCFString __NSCFString length
> - __NSCFString __NSCFString length
> - __NSCFString __NSCFString getCharacters:range:
> - NSPathStore2 NSPathStore2 length
> - NSPathStore2 NSPathStore2 characterAtIndex: Based on these results I am confident in my assumption that Regarding the failing tests in |
If I got it right, we need to address two different problems to fix this issue:
NSFileManager.createFileAtPathBefore iOS 18 NSFileManager.createFileAtPath used NSData, so it was a nice side effect of getting the file manager's instrumentation by only swizzling NSData. I think this stopped working because they ported the Data(contentsOf::)It seems like Swift Data also stopped using NSData under the hood. That's the main goal of https://github.com/swiftlang/swift-foundation. So the SentryDataWrapper you proposed in #4605 (comment) seems like the only solution for us to fix this, but I still need to check the details of the wrapper. |
@philipphofmann you summarized it correctly. ad 1.: Yes, swizzling ad 2.: Yes, my proposed |
OK, then I would split this issue up into two issues. One for the NSFileManager and another one for Swift.Data. I would first swizzle the NSFileManager behind an experimental feature to minimize the risk of breaking something. After we merge this, we can look at Swift.Data. For that, I would first start with the code you want to write. Maybe the Wrapper you proposed is the best solution, maybe we can use extensions. We still need to evaluate which approach works best. |
I split the PR into two separate PRs: |
somewhat related, so FYI #4238 |
Description
Some file IO operations not being tracked for iOS 18.
See https://github.com/getsentry/sentry-cocoa/actions/runs/11858258351/job/33048500905?pr=4542
The text was updated successfully, but these errors were encountered: