Skip to content
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

feat: add Sentry screenName tracking #4646

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Changelog

Check failure on line 1 in CHANGELOG.md

View workflow job for this annotation

GitHub Actions / danger / danger

Please consider adding a changelog entry for the next release.

Check notice on line 1 in CHANGELOG.md

View workflow job for this annotation

GitHub Actions / danger / danger

### Instructions and example for changelog Please add an entry to `CHANGELOG.md` to the "Unreleased" section. Make sure the entry includes this PR's number. Example: ```markdown ## Unreleased - add Sentry screenName tracking ([#4646](https://github.com/getsentry/sentry-cocoa/pull/4646)) ``` If none of the above apply, you can opt out of this check by adding `#skip-changelog` to the PR description.

## Unreleased

Expand All @@ -9,6 +9,7 @@
### Features

- Show session replay options as replay tags (#4639)
- Add UIViewController custom screenName for breadcrumb tracking (#4642)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So it matches the PR number.

Suggested change
- Add UIViewController custom screenName for breadcrumb tracking (#4642)
- Add UIViewController custom screenName for breadcrumb tracking (#4646)


### Fixes

Expand Down
4 changes: 4 additions & 0 deletions Sentry.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@
63FE722220DA66EC00CDBAE8 /* SentryCrashJSONCodec_Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 63FE71F920DA66EB00CDBAE8 /* SentryCrashJSONCodec_Tests.m */; };
63FE722420DA66EC00CDBAE8 /* SentryCrashMonitor_NSException_Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 63FE71FB20DA66EB00CDBAE8 /* SentryCrashMonitor_NSException_Tests.m */; };
63FE722520DA66EC00CDBAE8 /* SentryCrashFileUtils_Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 63FE71FC20DA66EB00CDBAE8 /* SentryCrashFileUtils_Tests.m */; };
64F9571D2D12DA1A00324652 /* SentryViewControllerBreadcrumbTracking.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64F9571C2D12DA1800324652 /* SentryViewControllerBreadcrumbTracking.swift */; };
69BEE6F72620729E006DF9DF /* UrlSessionDelegateSpy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69BEE6F62620729E006DF9DF /* UrlSessionDelegateSpy.swift */; };
71F116E8F40D530BB68A2987 /* SentryCrashUUIDConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 71F11CDEF5952DF5CC69AC74 /* SentryCrashUUIDConversion.h */; };
7B0002322477F0520035FEF1 /* SentrySessionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B0002312477F0520035FEF1 /* SentrySessionTests.m */; };
Expand Down Expand Up @@ -1344,6 +1345,7 @@
63FE71F920DA66EB00CDBAE8 /* SentryCrashJSONCodec_Tests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryCrashJSONCodec_Tests.m; sourceTree = "<group>"; };
63FE71FB20DA66EB00CDBAE8 /* SentryCrashMonitor_NSException_Tests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryCrashMonitor_NSException_Tests.m; sourceTree = "<group>"; };
63FE71FC20DA66EB00CDBAE8 /* SentryCrashFileUtils_Tests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryCrashFileUtils_Tests.m; sourceTree = "<group>"; };
64F9571C2D12DA1800324652 /* SentryViewControllerBreadcrumbTracking.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryViewControllerBreadcrumbTracking.swift; sourceTree = "<group>"; };
69BEE6F62620729E006DF9DF /* UrlSessionDelegateSpy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UrlSessionDelegateSpy.swift; sourceTree = "<group>"; };
71F11CDEF5952DF5CC69AC74 /* SentryCrashUUIDConversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashUUIDConversion.h; sourceTree = "<group>"; };
7B0002312477F0520035FEF1 /* SentrySessionTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentrySessionTests.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3966,6 +3968,7 @@
D8F016B12B9622B7007B9AFB /* Protocol */ = {
isa = PBXGroup;
children = (
64F9571C2D12DA1800324652 /* SentryViewControllerBreadcrumbTracking.swift */,
D8F016B22B9622D6007B9AFB /* SentryId.swift */,
D8CAC0402BA0984500E38F34 /* SentryIntegrationProtocol.swift */,
D87C89022BC43C9C0086C7DF /* SentryRedactOptions.swift */,
Expand Down Expand Up @@ -4757,6 +4760,7 @@
15360CCF2432777500112302 /* SentrySessionTracker.m in Sources */,
6334314320AD9AE40077E581 /* SentryMechanism.m in Sources */,
849B8F9C2C6E906900148E1F /* SentryUserFeedbackThemeConfiguration.swift in Sources */,
64F9571D2D12DA1A00324652 /* SentryViewControllerBreadcrumbTracking.swift in Sources */,
63FE70D320DA4C1000CDBAE8 /* SentryCrashMonitor_AppState.c in Sources */,
849B8F9D2C6E906900148E1F /* SentryUserFeedbackWidgetConfiguration.swift in Sources */,
639FCFA51EBC809A00778193 /* SentryStacktrace.m in Sources */,
Expand Down
17 changes: 12 additions & 5 deletions Sources/Sentry/SentryBreadcrumbTracker.m
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@
{
NSMutableDictionary *info = @{}.mutableCopy;

info[@"screen"] = [SwiftDescriptor getObjectClassName:controller];
info[@"screen"] = [self screenNameForViewController:controller];

if ([controller.navigationItem.title length] != 0) {
info[@"title"] = controller.navigationItem.title;
Expand All @@ -315,13 +315,11 @@
info[@"beingPresented"] = controller.beingPresented ? @"true" : @"false";

if (controller.presentingViewController != nil) {
info[@"presentingViewController"] =
[SwiftDescriptor getObjectClassName:controller.presentingViewController];
info[@"presentingViewController"] = [self screenNameForViewController:controller.presentingViewController];
}

Check warning on line 320 in Sources/Sentry/SentryBreadcrumbTracker.m

View check run for this annotation

Codecov / codecov/patch

Sources/Sentry/SentryBreadcrumbTracker.m#L318-L320

Added lines #L318 - L320 were not covered by tests
if (controller.parentViewController != nil) {
info[@"parentViewController"] =
[SwiftDescriptor getObjectClassName:controller.parentViewController];
info[@"parentViewController"] = [self screenNameForViewController:controller.parentViewController];
}

if (controller.view.window != nil) {
Expand All @@ -335,6 +333,15 @@

return info;
}

+ (NSString *)screenNameForViewController:(UIViewController *)controller {
if ([controller conformsToProtocol:@protocol(SentryViewControllerBreadcrumbTracking)]) {
return ((UIViewController<SentryViewControllerBreadcrumbTracking> *)controller).screenName;
} else {
return [SwiftDescriptor getObjectClassName:controller];
}
}

#endif // SENTRY_HAS_UIKIT

@end
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import Foundation

///
/// Use this protocol to customize the name used in the automatic
/// UIViewController performance tracker.
///
@objc
public protocol SentryViewControllerBreadcrumbTracking: NSObjectProtocol {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

h: We use SwiftDescriptor getObjectClassName in multiple locations in our code base for getting the UIViewControllerName; see https://github.com/search?q=repo%3Agetsentry%2Fsentry-cocoa%20SwiftDescriptor%20getObjectClassName&type=code

I think we should use SentryViewControllerBreadcrumbTracking in all of these scenarios for consistency. Therefore, we should rename this to SentryUIViewControllerName and update the code comment above accordingly.

Copy link
Author

@m1entus m1entus Dec 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok i will change, i was thinking about some generic protocol in case in future you would like to add some additional parameters which might be send with breadcrumb. If we name it UIViewControllerName and in future we would like to add additional parameters which might, propably we would have to rename it? What about SentryUIViewControllerDescriptionProviding or SentryUIViewControllerDescriptor ?


/// The custom name of the UIViewController
/// that will be used for the transaction name.
var screenName: String { get }
m1entus marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,45 @@

XCTAssertEqual(crumbData["accessibilityIdentifier"] as? String, "TestAccessibilityIdentifier")
}


func testBreadcrumbViewControllerCustomScreenName() throws {
let testReachability = TestSentryReachability()
SentryDependencyContainer.sharedInstance().reachability = testReachability

let scope = Scope()
let client = TestClient(options: Options())
let hub = TestHub(client: client, andScope: scope)
SentrySDK.setCurrentHub(hub)

let sut = SentryBreadcrumbTracker()
sut.start(with: delegate)
sut.startSwizzle()

let parentScreenName = UUID().uuidString
let screenName = UUID().uuidString
let title = UUID().uuidString

let parentController = CustomScreenNameViewController(screenName: parentScreenName)
let viewController = CustomScreenNameViewController(screenName: screenName)
parentController.addChild(viewController)
viewController.title = title

viewController.viewDidAppear(false)

let crumbs = delegate.addCrumbInvocations.invocations

// one breadcrumb for starting the tracker, one for the first reachability breadcrumb and one final one for the swizzled viewDidAppear
guard crumbs.count == 2 else {
XCTFail("Expected exactly 2 breadcrumbs, got: \(crumbs)")
return
}

let lifeCycleCrumb = try XCTUnwrap(crumbs.element(at: 1))
XCTAssertEqual(screenName, lifeCycleCrumb.data?["screen"] as? String)
XCTAssertEqual(title, lifeCycleCrumb.data?["title"] as? String)
XCTAssertEqual(parentScreenName, lifeCycleCrumb.data?["parentViewController"] as? String)
}

private class TestEvent: UIEvent {
let touchedView: UIView?
class TestEndTouch: UITouch {
Expand All @@ -307,7 +345,21 @@
TestEndTouch(touchedView: touchedView)
] }
}


fileprivate final class CustomScreenNameViewController: UIViewController, SentryViewControllerBreadcrumbTracking {

fileprivate required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

Check warning on line 353 in Tests/SentryTests/Integrations/Breadcrumbs/SentryBreadcrumbTrackerTests.swift

View check run for this annotation

Codecov / codecov/patch

Tests/SentryTests/Integrations/Breadcrumbs/SentryBreadcrumbTrackerTests.swift#L353

Added line #L353 was not covered by tests

fileprivate var screenName: String

fileprivate init(screenName: String) {
self.screenName = screenName
super.init(nibName: nil, bundle: nil)
}
}

#endif

}
Loading