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

[Gutenberg] Add Sentry React native SDK #16700

Closed
wants to merge 24 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
99596ca
Add bridge methods for React native crash logging
fluiddot Jun 10, 2021
ed72263
Autocorrect lint issues
fluiddot Jun 15, 2021
2ef1920
Add getSentryUser to Gutenberg view controller
fluiddot Jun 16, 2021
edd59e5
Add upload Gutenberg source maps lane to Fastfile
fluiddot Jun 16, 2021
23d2a62
Update Tracks ref
fluiddot Jun 17, 2021
4d40f39
Update Podfile.lock
fluiddot Jun 17, 2021
6440d98
Update Gutenberg Mobile ref
fluiddot Jun 17, 2021
1240e89
Change internal value in build_and_upload_internal lane
fluiddot Jun 23, 2021
86a6ca9
Merge branch 'develop' into gutenberg/add/sentry-react-native
fluiddot Jun 23, 2021
70aa63d
Update Gutenberg Mobile ref
fluiddot Jun 24, 2021
32ff050
Remove redundant comment from Fastfile file
fluiddot Jul 1, 2021
d1f3788
Remove redundant comment from Fastfile file
fluiddot Jul 1, 2021
cff282e
Remove redundant comment from Fastfile file
fluiddot Jul 1, 2021
73aadc9
Add details to RN bundle naming in Fastfile file
fluiddot Jul 1, 2021
98f7252
Add info comments to upload_gutenberg_sourcemaps lane
fluiddot Jul 1, 2021
20f1892
Use temporary dir for uploading JS source maps
fluiddot Jul 1, 2021
ac313a9
Add Gutenberg Sentry native module
fluiddot Jul 2, 2021
14f6cd7
Rename RNSentry to GutenbergSentry
fluiddot Jul 5, 2021
2adce8c
Update Gutenberg Mobile ref
fluiddot Jul 5, 2021
04d18c8
Apply swift lint autocorrection
fluiddot Jul 5, 2021
8d591c8
Rename gutenberg sentry options function
fluiddot Jul 9, 2021
7fb5928
Update Gutenberg Mobile ref
fluiddot Jul 9, 2021
3f1a4fc
Merge branch 'develop' into gutenberg/add/sentry-react-native
fluiddot Jul 21, 2021
848924d
Update WordPress/Classes/ViewRelated/Gutenberg/GutenbergViewControlle…
fluiddot Jul 28, 2021
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
6 changes: 3 additions & 3 deletions Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ abstract_target 'Apps' do
## Gutenberg (React Native)
## =====================
##
gutenberg :tag => 'v1.58.0-alpha2'
gutenberg :commit => 'cd920e964f8163f918fecb4afd742f783d51ddba'

## Third party libraries
## =====================
Expand Down Expand Up @@ -198,9 +198,9 @@ abstract_target 'Apps' do

# Production

pod 'Automattic-Tracks-iOS', '~> 0.9.1'
#pod 'Automattic-Tracks-iOS', '~> 0.9.1'
# While in PR
# pod 'Automattic-Tracks-iOS', :git => 'https://github.com/Automattic/Automattic-Tracks-iOS.git', :branch => ''
pod 'Automattic-Tracks-iOS', :git => 'https://github.com/Automattic/Automattic-Tracks-iOS.git', :branch => 'crash-logging-hybrid-sdk-helpers'
# Local Development
#pod 'Automattic-Tracks-iOS', :path => '~/Projects/Automattic-Tracks-iOS'

Expand Down
183 changes: 94 additions & 89 deletions Podfile.lock

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -265,8 +265,10 @@ class GutenbergViewController: UIViewController, PostEditor {
return GutenbergImageLoader(post: post)
}()

private lazy var gutenbergSentry = GutenbergSentry()

private lazy var gutenberg: Gutenberg = {
return Gutenberg(dataSource: self, extraModules: [gutenbergImageLoader])
return Gutenberg(dataSource: self, extraModules: [gutenbergImageLoader, gutenbergSentry])
}()

private var requestHTMLReason: RequestHTMLReason?
Expand Down Expand Up @@ -1049,6 +1051,10 @@ extension GutenbergViewController: GutenbergBridgeDataSource {
].compactMap { $0 }
}

func gutenbergCrashLoggingOptions() -> [String: Any]? {
return WordPressAppDelegate.crashLogging?.getOptionsDict()
}

func gutenbergCapabilities() -> [Capabilities: Bool] {
let isFreeWPCom = post.blog.isHostedAtWPcom && !post.blog.hasPaidPlan
let isWPComSite = post.blog.isHostedAtWPcom || post.blog.isAtomic()
Expand Down
40 changes: 40 additions & 0 deletions WordPress/Classes/ViewRelated/Gutenberg/Sentry/GutenbergSentry.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#import <React/RCTBridgeModule.h>

@interface RCT_EXTERN_MODULE(RNSentry, NSObject)

// Extra methods to extract data from the Sentry SDK configured in the main apps.
RCT_EXTERN_METHOD(getUser:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)rejecter)
RCT_EXTERN_METHOD(attachScopeToEvent:(NSDictionary * _Nonnull)event resolve:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)rejecter)
RCT_EXTERN_METHOD(shouldSendEvent:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)rejecter)


// This methods are extracted from the original implementation.
// Reference: https://github.com/getsentry/sentry-react-native/blob/master/ios/RNSentry.m
RCT_EXTERN_METHOD(startWithOptions:(NSDictionary *_Nonnull)options resolve:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)rejecter)
RCT_EXTERN_METHOD(deviceContexts:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)rejecter)
RCT_EXTERN_METHOD(setLogLevel:(int)level)
RCT_EXTERN_METHOD(fetchRelease:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)rejecter)
RCT_EXTERN_METHOD(captureEnvelope:(NSDictionary * _Nonnull)envelopeDict
resolve:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)rejecter)
RCT_EXTERN_METHOD(setUser:(NSDictionary *)user
otherUserKeys:(NSDictionary *)otherUserKeys
)
RCT_EXTERN_METHOD(addBreadcrumb:(NSDictionary *)breadcrumb)
RCT_EXTERN_METHOD(clearBreadcrumbs)
RCT_EXTERN_METHOD(setExtra:(NSString *)key
extra:(NSString *)extra
)
RCT_EXTERN_METHOD(setContext:(NSString *)key
context:(NSDictionary *)context
)
RCT_EXTERN_METHOD(setTag:(NSString *)key
value:(NSString *)value
)
RCT_EXTERN_METHOD(crash)
@end
108 changes: 108 additions & 0 deletions WordPress/Classes/ViewRelated/Gutenberg/Sentry/GutenbergSentry.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
@objc (RNSentry)
public class GutenbergSentry: NSObject, RCTBridgeModule {
public static func moduleName() -> String! {
return "RNSentry"
}

public static func requiresMainQueueSetup() -> Bool {
return true
}

public func constantsToExport() -> [AnyHashable: Any]! {
return ["nativeClientAvailable": true, "nativeTransport": true]
}

/// Asks the Crash logging library for the current Sentry scope and includes it to an event.
///
/// - Returns: Event object with attached scope.
@objc
func attachScopeToEvent(_ event: [String: Any], resolve: @escaping RCTPromiseResolveBlock, rejecter:@escaping RCTPromiseRejectBlock) {
DispatchQueue.main.async {
let eventWithScope = WordPressAppDelegate.crashLogging?.attachScopeToEvent(event)
resolve(eventWithScope)
}
}

/// Asks the Crash logging library to know if the app should send Sentry events depending on user preferences.
///
/// - Returns: True if Sentry events can be sent.
@objc
func shouldSendEvent(_ resolve: @escaping RCTPromiseResolveBlock, rejecter:@escaping RCTPromiseRejectBlock) {
DispatchQueue.main.async {
let shouldSendEvent = WordPressAppDelegate.crashLogging?.shouldSendEvent()
resolve(shouldSendEvent)
}
}

/// Asks the Crash logging library for the current user of Sentry SDK.
///
/// - Returns: Sentry user.
@objc
func getUser(_ resolve: @escaping RCTPromiseResolveBlock, rejecter:@escaping RCTPromiseRejectBlock) {
DispatchQueue.main.async {
resolve(WordPressAppDelegate.crashLogging?.getSentryUserDict())
}
}

@objc
func captureEnvelope(_ envelopeDict: [String: Any], resolve: @escaping RCTPromiseResolveBlock, rejecter:@escaping RCTPromiseRejectBlock) {
DispatchQueue.main.async {
WordPressAppDelegate.crashLogging?.logEnvelope(envelopeDict)
resolve(true)
}
}
}

// MARK: - Disabled original methods

extension GutenbergSentry {
// Disabled because the Sentry SDK is initialized in the main apps.
@objc
func startWithOptions(_ options: [String: Any], resolve: @escaping RCTPromiseResolveBlock, rejecter:@escaping RCTPromiseRejectBlock) {
resolve(true)
}

// Disabled because the device context is fetched via the attachScopeToEvent method.
@objc
func deviceContexts(_ resolve: @escaping RCTPromiseResolveBlock, rejecter:@escaping RCTPromiseRejectBlock) {
resolve({})
}

// Disabled as it's set by the main apps.
@objc
func setLogLevel(_ level: Int) { }

// Disabled as it's not required by the current Sentry integrations.
@objc
func fetchRelease(_ resolve: @escaping RCTPromiseResolveBlock, rejecter:@escaping RCTPromiseRejectBlock) {
resolve({})
}

// Disabled as it's set by the main apps.
@objc
func setUser(_ user: [String: Any], otherUserKeys: [String: Any]) { }

// Disabled as breadcrumbs are managed by the main apps.
@objc
func addBreadcrumb(_ breadcrumb: [String: Any]) { }

// Disabled as breadcrumbs are managed by the main apps.
@objc
func clearBreadcrumbs() { }

// Disabled as extra tags are managed by the main apps.
@objc
func setExtra(_ key: String, extra: String) { }

// Disabled as context is managed by the main apps.
@objc
func setContext(_ key: String, context: [String: Any]) { }

// Disabled as tags are managed by the main apps.
@objc
func setTag(_ key: String, value: String) { }

// Disabled as it's already exposed from the main apps.
@objc
func crash() { }
}
20 changes: 20 additions & 0 deletions WordPress/WordPress.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,10 @@
17FCA6811FD84B4600DBA9C8 /* NoticeStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17FCA6801FD84B4600DBA9C8 /* NoticeStore.swift */; };
1A433B1D2254CBEE00AE7910 /* WordPressComRestApi+Defaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A433B1C2254CBEE00AE7910 /* WordPressComRestApi+Defaults.swift */; };
1ABA150822AE5F870039311A /* WordPressUIBundleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ABA150722AE5F870039311A /* WordPressUIBundleTests.swift */; };
1D031A47268F772A0071372F /* GutenbergSentry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D031A45268F772A0071372F /* GutenbergSentry.swift */; };
1D031A48268F772A0071372F /* GutenbergSentry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D031A45268F772A0071372F /* GutenbergSentry.swift */; };
1D031A49268F772A0071372F /* GutenbergSentry.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D031A46268F772A0071372F /* GutenbergSentry.m */; };
1D031A4A268F772A0071372F /* GutenbergSentry.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D031A46268F772A0071372F /* GutenbergSentry.m */; };
1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
1E0462162566938300EB98EF /* GutenbergFileUploadProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E0462152566938300EB98EF /* GutenbergFileUploadProcessor.swift */; };
1E0FF01E242BC572008DA898 /* GutenbergWebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E0FF01D242BC572008DA898 /* GutenbergWebViewController.swift */; };
Expand Down Expand Up @@ -4835,6 +4839,8 @@
1A433B1C2254CBEE00AE7910 /* WordPressComRestApi+Defaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WordPressComRestApi+Defaults.swift"; sourceTree = "<group>"; };
1ABA150722AE5F870039311A /* WordPressUIBundleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WordPressUIBundleTests.swift; sourceTree = "<group>"; };
1B77149F6C65D343E7E3AD09 /* Pods-WordPressUITests.release-alpha.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WordPressUITests.release-alpha.xcconfig"; path = "../Pods/Target Support Files/Pods-WordPressUITests/Pods-WordPressUITests.release-alpha.xcconfig"; sourceTree = "<group>"; };
1D031A45268F772A0071372F /* GutenbergSentry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GutenbergSentry.swift; sourceTree = "<group>"; };
1D031A46268F772A0071372F /* GutenbergSentry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GutenbergSentry.m; sourceTree = "<group>"; };
1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
1D6058910D05DD3D006BFB54 /* WordPress.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WordPress.app; sourceTree = BUILT_PRODUCTS_DIR; };
1E0462152566938300EB98EF /* GutenbergFileUploadProcessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GutenbergFileUploadProcessor.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -8336,6 +8342,15 @@
path = Networking;
sourceTree = "<group>";
};
1D031A44268F772A0071372F /* Sentry */ = {
isa = PBXGroup;
children = (
1D031A45268F772A0071372F /* GutenbergSentry.swift */,
1D031A46268F772A0071372F /* GutenbergSentry.m */,
);
path = Sentry;
sourceTree = "<group>";
};
1E5D00152493FC3A0004B708 /* Views */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -10481,6 +10496,7 @@
children = (
B0637542253E7E7A00FD45D2 /* GutenbergSuggestionsViewController.swift */,
FF2EC3BE2209A105006176E1 /* Processors */,
1D031A44268F772A0071372F /* Sentry */,
1ED046CE244F26B1008F6365 /* GutenbergWeb */,
4631359224AD057E0017E65C /* Layout Picker */,
1E5D00152493FC3A0004B708 /* Views */,
Expand Down Expand Up @@ -17308,6 +17324,7 @@
2FA6511721F26A24009AA935 /* ChangePasswordViewController.swift in Sources */,
D816C1F020E0893A00C4D82F /* LikeComment.swift in Sources */,
982DA9A7263B1E2F00E5743B /* CommentService+Likes.swift in Sources */,
1D031A49268F772A0071372F /* GutenbergSentry.m in Sources */,
59E1D46E1CEF77B500126697 /* Page.swift in Sources */,
321955BF24BE234C00E3F316 /* ReaderInterestsCoordinator.swift in Sources */,
FAE4327425874D140039EB8C /* ReaderSavedPostCellActions.swift in Sources */,
Expand Down Expand Up @@ -17631,6 +17648,7 @@
B55086211CC15CCB004EADB4 /* PromptViewController.swift in Sources */,
40C403EC2215CD1300E8C894 /* SearchResultsStatsRecordValue+CoreDataProperties.swift in Sources */,
82FC612C1FA8B7FC00A1757E /* ActivityListRow.swift in Sources */,
1D031A47268F772A0071372F /* GutenbergSentry.swift in Sources */,
436110E022C4241A000773AD /* UIColor+MurielColorsObjC.swift in Sources */,
B5B68BD41C19AAED00EB59E0 /* InteractiveNotificationsManager.swift in Sources */,
46183CF5251BD658004F9AFD /* PageTemplateLayout+CoreDataProperties.swift in Sources */,
Expand Down Expand Up @@ -19120,6 +19138,7 @@
FABB222A2602FC2C00C8785C /* JetpackScanThreatSectionGrouping.swift in Sources */,
FABB222B2602FC2C00C8785C /* MediaService+Swift.swift in Sources */,
FABB222C2602FC2C00C8785C /* ReaderActionHelpers.swift in Sources */,
1D031A48268F772A0071372F /* GutenbergSentry.swift in Sources */,
FABB222D2602FC2C00C8785C /* NoteBlockUserTableViewCell.swift in Sources */,
FABB222E2602FC2C00C8785C /* WPStyleGuide+Sharing.swift in Sources */,
FABB222F2602FC2C00C8785C /* StoryPoster.swift in Sources */,
Expand Down Expand Up @@ -19540,6 +19559,7 @@
FABB23B72602FC2C00C8785C /* Notifiable.swift in Sources */,
FABB23B82602FC2C00C8785C /* RegisterDomainDetailsViewModel+CountryDialCodes.swift in Sources */,
FABB23B92602FC2C00C8785C /* BlogListViewController+SiteCreation.swift in Sources */,
1D031A4A268F772A0071372F /* GutenbergSentry.m in Sources */,
FABB23BA2602FC2C00C8785C /* CommentAnalytics.swift in Sources */,
FABB23BB2602FC2C00C8785C /* TableViewHeaderDetailView.swift in Sources */,
FABB23BC2602FC2C00C8785C /* MenuItemAbstractView.m in Sources */,
Expand Down
46 changes: 46 additions & 0 deletions fastlane/Fastfile
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,8 @@ platform :ios do
dsym_path: lane_context[SharedValues::DSYM_OUTPUT_PATH]
)

upload_gutenberg_sourcemaps(internal: true)

download_url = Actions.lane_context[SharedValues::APPCENTER_DOWNLOAD_LINK]
UI.message("Successfully built and uploaded installable build here: #{download_url}")
install_url = 'https://install.appcenter.ms/orgs/automattic/apps/WPiOS-One-Offs/'
Expand Down Expand Up @@ -586,6 +588,8 @@ platform :ios do
project_slug: 'wordpress-ios',
dsym_path: lane_context[SharedValues::DSYM_OUTPUT_PATH]
)

upload_gutenberg_sourcemaps(internal: true)
end

#####################################################################################
Expand Down Expand Up @@ -632,6 +636,8 @@ platform :ios do
dsym_path: lane_context[SharedValues::DSYM_OUTPUT_PATH]
)

upload_gutenberg_sourcemaps(internal: false)

if options[:create_release]
archive_zip_path = File.join(PROJECT_ROOT_FOLDER, 'WordPress.xarchive.zip')
zip(path: lane_context[SharedValues::XCODEBUILD_ARCHIVE], output_path: archive_zip_path)
Expand Down Expand Up @@ -790,6 +796,46 @@ platform :ios do
)
end

#####################################################################################
# upload_gutenberg_sourcemaps
# -----------------------------------------------------------------------------------
# This lane uploads the Gutenberg source maps
# -----------------------------------------------------------------------------------
# Usage:
# bundle exec fastlane upload_gutenberg_sourcemaps [internal:<internal>]
#
# Example:
# bundle exec fastlane upload_gutenberg_sourcemaps internal:true
#####################################################################################
lane :upload_gutenberg_sourcemaps do | options |
build_version = ios_get_build_version(internal: options[:internal])
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The build version is different depending on the internal option, here is an example:


gutenberg_bundle = File.join(PROJECT_ROOT_FOLDER, "Pods/Gutenberg/bundle/ios")

Dir.mktmpdir do |sourcemaps_folder|
# Name of bundle file must be set to main.jsbundle.
#
# It's important that the source map files have specific names, otherwise, Sentry
# won't un-minify the stack traces.
FileUtils.cp(File.join(gutenberg_bundle, 'App.js'), File.join(sourcemaps_folder, 'main.jsbundle'))
FileUtils.cp(File.join(gutenberg_bundle, 'App.js.map'), File.join(sourcemaps_folder, 'main.jsbundle.map'))

sentry_upload_sourcemap(
auth_token: get_required_env("SENTRY_AUTH_TOKEN"),
org_slug: 'a8c',
project_slug: 'wordpress-ios',
version: build_version,
dist: build_version,
# When the React native bundle is generated, the source map file references
# include the local machine path, with the `rewrite` and `strip_common_prefix`
# options Sentry automatically strips this part.
rewrite: true,
strip_common_prefix: true,
sourcemap: sourcemaps_folder
)
end
end

########################################################################
# Configure Lanes
########################################################################
Expand Down