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

Add Sentry for error reporting #443

Closed
wants to merge 16 commits into from
Closed

Add Sentry for error reporting #443

wants to merge 16 commits into from

Conversation

pepicrft
Copy link
Contributor

@pepicrft pepicrft commented Jul 14, 2019

Short description πŸ“

Handled bugs and unhandled errors are not being reported at the moment. Therefore, we can only know about them if developers open issues on this repository.

Solution πŸ“¦

Create a project on Sentry and set up Tuist to use it.

Implementation πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

  • Add Sentry.framework
  • Set up the project generation to link the TuistCore target against it.
  • Change the ErrorHandler logic to report bugs.
  • Observe unhandled errors and report them using the error handler.
  • Update the Rake package task to override the linking settings of the tuist and tuistenv binaries to link dynamically against Sentry.framework.
  • Pass the SentryDSN when building the Package for release.
  • Update the install logic in TuistEnv to pull the Sentry.framework
  • Update the install script to place the Sentry.framework next to tuistenv.
  • Document how to disable tracking.

Setup code

do {
        Client.shared = try Client(dsn: "xxx")
        try Client.shared?.startCrashHandler()
    } catch let error {
        print("\(error)")
    }

@pepicrft pepicrft changed the title [WIPSentry [WIP] Add Sentry for error reporting Jul 14, 2019
@tuistbot
Copy link
Contributor

tuistbot commented Jul 14, 2019

1 Warning
⚠️ Have you introduced any user-facing changes? If so, please take some time to update the documentation. Keeping the documentation up to date makes it easier for users to learn how to use Tuist.

Rubocop violations

File Line Reason
Rakefile 90 Line is too long. [162/120] (https://shopify.github.io/ruby-style-guide/#80-character-limits)
install/install 141 Line is too long. [160/120] (https://shopify.github.io/ruby-style-guide/#80-character-limits)

Generated by 🚫 Danger

@pepicrft pepicrft self-assigned this Jul 14, 2019
@pepicrft pepicrft requested a review from a team July 14, 2019 08:29
@codecov
Copy link

codecov bot commented Jul 14, 2019

Codecov Report

Merging #443 into master will decrease coverage by 0.17%.
The diff coverage is 88.33%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #443      +/-   ##
==========================================
- Coverage   92.23%   92.06%   -0.18%     
==========================================
  Files         319      319              
  Lines       16393    16492      +99     
==========================================
+ Hits        15120    15183      +63     
- Misses       1273     1309      +36
Impacted Files Coverage Ξ”
Sources/TuistKit/Commands/CommandRegistry.swift 0% <0%> (ΓΈ) ⬆️
Sources/TuistCore/Errors/FatalError.swift 22.22% <0%> (-44.45%) ⬇️
Sources/TuistEnvKit/Commands/CommandRegistry.swift 71.73% <100%> (+1.28%) ⬆️
Sources/TuistEnvKit/Installer/BuildCopier.swift 100% <100%> (ΓΈ) ⬆️
.../TuistEnvKitTests/Installer/BuildCopierTests.swift 100% <100%> (ΓΈ) ⬆️
...tEnvKitTests/Installer/Mocks/MockBuildCopier.swift 100% <100%> (ΓΈ) ⬆️
Sources/TuistEnvKit/Installer/Installer.swift 84.92% <100%> (-0.16%) ⬇️
...ces/TuistCoreTesting/Errors/MockErrorHandler.swift 100% <100%> (ΓΈ) ⬆️
Sources/TuistCore/Errors/ErrorHandler.swift 57.69% <18.18%> (-29.81%) ⬇️
...ts/TuistEnvKitTests/Installer/InstallerTests.swift 98.16% <98.94%> (+0.05%) ⬆️
... and 5 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Ξ” = absolute <relative> (impact), ΓΈ = not affected, ? = missing data
Powered by Codecov. Last update 1f8a75a...65f1575. Read the comment docs.

Rakefile Outdated
@@ -100,6 +135,16 @@ def storage
)
end

def with_sentry_dsn
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 sentry_dsn is a secret so this piece of code makes sure the value is defined in the SentryDsn.swift file when packaging a new release of Tuist.

/// Returns true if the user decided to disable the analytics by setting the TUIST_ANALYTICS_DISABLED environment variable.
///
/// - Returns: True if the analytics are disabled.
func isDisabled() -> Bool {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

cc @kwridan do you think this should be enough?

@pepicrft pepicrft changed the title [WIP] Add Sentry for error reporting Add Sentry for error reporting Jul 16, 2019
@pepicrft
Copy link
Contributor Author

The PR is blocked by this issue. We need the Sentry SDK API to provide an interface to send all the events and subscribe to the completion of the delivery. That'll allow Tuist to wait until the events are reported, otherwise it exits before the events reach the server.

@pepicrft
Copy link
Contributor Author

After some tests, I realized that the Swift Package Manager doesn't export the dSYMs and therefore the stacktraces in Sentry can't be desymbolicated. That complicates debugging the issue.

I suggest taking a different approach here. Instead of reporting the errors to Sentry, use the GitHubClient to report the errors as GitHub issues. What do you think @tuist/core ?

@kwridan
Copy link
Collaborator

kwridan commented Jul 19, 2019

Agreed, I think a simpler alternate is better suited here - from @ollieatkinson suggestions (from slack) we can start by catching / surfacing the errors in the command line that will aid better bug reports.

@ollieatkinson
Copy link
Collaborator

The suggestion on slack was to create a global function for tagging errors which can be propagated through standard swift error handling.

@discardableResult @inlinable
public func report<T>(_ block: @autoclosure () throws -> T, message: String = "", file: String = #file, line: Int = #line, function: String = #function) throws -> T {

    do {
        return try block()
    } catch let error as ReportedError {
        throw error
    } catch let error as FatalError {
        throw ReportedError(error: error, message: message, file: file, line: line, function: function)
    } catch let error {
        throw ReportedError(error: UnhandledError(error: error), message: message, file: file, line: line, function: function)
    }
    
}

We should expand on this further and provide support for capturing the output of the shell command which failed.

@pepicrft
Copy link
Contributor Author

I'll open a PR following the suggested approach.

@pepicrft pepicrft closed this Jul 25, 2019
@pepicrft pepicrft deleted the sentry branch July 25, 2019 14:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants