Aardvark is a library that makes it dead simple to create actionable bug reports.

Overview

Aardvark

CI Status Carthage Compatibility License Platform

Aardvark Version CoreAardvark Version AardvarkLoggingUI Version AardvarkMailUI Version

Aardvark makes it dead simple to create actionable bug reports.

Aardvark is made up of a collection of frameworks that provide different bug reporting and logging components.

  • CoreAardvark - The core structures for Aardvark. Safe to run in app extensions.
  • Aardvark - The core tools for building a bug report.
  • AardvarkMailUI - A bug reporter implementation that sends the bug report via an email composer.
  • AardvarkLoggingUI - UI components for viewing Aardvark logs in an iOS app.

Getting Started

There are only three steps to get Aardvark logging and bug reporting up and running.

1) Install Aardvark

The easiest way to get Aardvark up and running is to add a dependency on the AardvarkMailUI framework.

Using CocoaPods

pod 'AardvarkMailUI'

Using Carthage

github "Square/Aardvark"

Using Git Submodules

Manually checkout the submodule with git submodule add [email protected]:Square/Aardvark.git, drag Aardvark.xcodeproj to your project, and add AardvarkMailUI as a build dependency.

2) Set up email bug reporting with a single method call

It is best to do this when you load your application’s UI.

In Swift:

Aardvark.addDefaultBugReportingGestureWithEmailBugReporter(withRecipient:)

In Objective-C:

[Aardvark addDefaultBugReportingGestureWithEmailBugReporterWithRecipient:]

3) Replace calls to print with log.

In Swift, replace calls to print with log. In Objective-C, replace calls to NSLog with ARKLog.

Reporting Bugs

After doing the above, your users can report a bug by making a two-finger long-press gesture. This gesture triggers a UIAlert asking the user what went wrong. When the user enters this information, an email bug report is generated complete with an attached app screenshot and a text file containing the last 2000 logs. Screenshots are created and stored within Aardvark and do not require camera roll access.

Bug Report Flow

Want to look at logs on device? Add the AardvarkLoggingUI framework as a dependency and push an instance of ARKLogTableViewController onto the screen to view your logs.

Performance

Logs are distributed to loggers on an internal background queue that will never slow down your app. Logs observed by the log store are incrementally appended to disk and not stored in memory.

Exception Logging

To turn on logging of uncaught exceptions, call ARKEnableLogOnUncaughtException(). When an uncaught exception occurs, the stack trace will be logged to the default log distributor. To test this out in the sample app, hold one finger down on the screen for at least 5 seconds.

Once the exception is logged, it will be propogated to any existing uncaught exception handler. By default, the exception will be logged to the default log distributor. To log to a different distributor, call ARKEnableLogOnUncaughtExceptionToLogDistributor(...). You can enable logging to multiple log distributors by calling the method multiple times.

Customize Aardvark

Want to customize how bug reports are filed? Pass your own object conforming to the ARKBugReporter protocol and the desired subclass of UIGestureRecognizer to [Aardvark addBugReporter:triggeringGestureRecognizerClass:]. You can further customize how bug reports will be triggered by modifying the returned gesture recognizer.

Want to change how logs are formatted? Or use different log files for different features? Or send your logs to third party services? Check out the logging documentation.

Want to log with Aardvark but don’t want to use Aardvark’s bug reporting tool? Change the dependency to be on Aardvark and skip step #2 in the Getting Started guide.

Extensions

  • AardvarkReveal provides components for generating a bug report attachment containing a Reveal file, which can be a huge help in debugging UI issues.
  • AardvarkCrashReport provides components for generating a bug report attachment containing a crash report, either from a crash on the prior app launch or a live report showing the current state of each thread.

Requirements

  • Xcode 11.0 or later
  • iOS 12.0 or later
  • watchOS 4.0 or later

Contributing

We’re glad you’re interested in Aardvark, and we’d love to see where you take it. Please read our contributing guidelines prior to submitting a Pull Request.

Thanks, and happy logging!

Comments
  • add a new dynamic framework target for iOS 8+

    add a new dynamic framework target for iOS 8+

    • Adds a new target to generate a dynamic framework
    • removed a framework search path in the test target which was pointed to an non existent system directory to get rid of a warning
    opened by ekimia 20
  • [3.0] Swift!

    [3.0] Swift!

    • Add ARKLogging.swift to allow for ARKLog use in Swift.
    • Remove support for iOS 6 and 7
    • Remove static library build target
    • Better ivar naming: ARKLogMessage.creationDate -> ARKLogMessage.date
    • Banish use of NS_ASSUME_NONNULL_*

    Please provide feedback @peter @natan @shawnwelch @rhgills. Happy to add more Swift to 2.0 if we think there's benefit (that won't screw current clients more than 2.0 already will).

    opened by dfed 12
  • Swift 4

    Swift 4

    Built on top of #49.

    @mthole or @pwesten, mind testing this in Cash/Caviar before this branch goes to master? I no longer work on an app that uses Aardvark 😞.

    I'm hoping the @objc changes are fine, since we were already explicitly calling out which swift methods were objc-available.

    opened by dfed 9
  • [RI-11328] Fix crash when displaying action menu on iPad.

    [RI-11328] Fix crash when displaying action menu on iPad.

    [RI-11328] Fixes crash when displaying action menu on iPad. Improves initializer correctness.

    Changes:

    • Obey Apple's guidelines for displaying UIActivityViewController - was causing crashes on iPad when trying to display.
    • Enforce passing a non-nil logStore and formatter to the ARKLogTableViewController. Deeper down the stack, the logFormatter is used to add formatted log messages to an array. This fails when one is missing.
    • Ensure that we override our superclasses designated initializers. Mark one of our initializers as designated. Ensure our designated initializer calls through to (one of) our superclasses designated initializers.
    opened by rhgills 6
  • Bump iOS Deployment Target to 9 & Fix Deprecations

    Bump iOS Deployment Target to 9 & Fix Deprecations

    Because Xcode 12 drops support for iOS 8 deployment target, we need to upgrade Aardvark's deployment target.

    • Bumps iOS Deployment Target to 9
    • Migrate from deprecated APIs
    • Updates to Swift 5
    • Update xcodeproj to recommended settings
    opened by JustinDSN 5
  • Use GitHub Actions for CI builds

    Use GitHub Actions for CI builds

    This moves us from Travis CI to GitHub actions, and parallelizes our builds a bit more, which should speed up CI times.

    I also bumped to the latest (non-beta) release of CocoaPods, since we were a bit behind.

    opened by NickEntin 5
  • [2.0] Use two podspecs instead of one

    [2.0] Use two podspecs instead of one

    #37 didn't do what we needed. Going to 2 pod specs should do it.

    CI will fail this PR, since we'll need to publish CoreAardvak before Aardvark will lint.

    cc @justinseanmartin @pwesten @natan

    opened by dfed 5
  • Decompose Aardvark into smaller modules

    Decompose Aardvark into smaller modules

    Aardvark currently has a lot of responsibilities - adding log messages, viewing those log messages in the app, generating data for a bug report, and sending that bug report via email. Breaking it down into smaller modules unlocks a couple of distinct advantages:

    • Support including only necessary portions of the bug reporting system based on build configuration. In particular, consumers should be able to include the core parts of the bug reporting functionality (taking a screenshot, generating attachments, etc.) without including the mail dialogs. By modularizing the core components of generating a bug report, we can make it easier to generate more customizable bug reporting workflows, while still supporting the simple-setup case with the existing email bug reporter.
    • Improve extensibility for future additions. In particular, I think there is a lot of power in being able to extend the variety of attachments that can be generated and included in a bug reported, as well as the ways in which that bug report can be shared.

    The disadvantage comes in the form of a few extra sets in setting up the dependencies (since there are now more dependencies) and discoverability of new features (since they may be in a not-yet-imported module), but I think these are greatly outweighed by the advantages.

    The current frameworks (Aardvark and CoreAardvark) will be broken down into four separate frameworks based on functionality. Frameworks related to the logging functionality with be prefixed with "CoreAardvark" (where CoreAardvark itself is the core logging framework) and frameworks related to the bug reporting functionality will be prefixed with "Aardvark" (where Aardvark itself is the core bug reporting framework). This gives us:

    • CoreAardvark - Core log message distribution and storage functionality. This has no dependencies and can be run in app extensions (no change from the current framework).
    • CoreAardvarkLoggingUI - User interfaces to view log messages inside an app.
    • Aardvark - Core bug reporting functionality. This will include the informational pieces of bug reporting, such as generating a screenshot and view hierarchy description.
    • AardvarkMailUI - User interfaces to submit a bug report via the Mail app.

    This provides us with a solid foundation to build out new logging and bug reporting functionality in a modular fashion on top of the two core frameworks, CoreAardvark and Aardvark.

    In the interest of making the addition of new bug reporting flows simpler, I think we should keep the bug report "attachment" concept in the main Aardvark framework. Since it isn't inherently tied to the mail concepts right now, the only change to the class will be a rename from ARKEmailAttachment to ARKBugReportAttachment.

    We can then begin to add new modules over time, which will generally fall into one of the following categories for most cases:

    • Attachment vendors - Frameworks that provide additional data that can be attached to a bug report.
    • Bug reporting workflows - Frameworks that provide alternate ways to file a bug report. For example, #47 mentions using the Gmail SDK to provide an alternate mail client to the built-in mail dialog. This could be provided as an alternate bug reporter podspec that has a dependency on that SDK. Similarly, we could introduce new bug reporters that connect directly to various services' APIs, for instance to create a new issue on GitHub.

    With this, the frameworks will be broken down into small components and restructured as follows:

    | | Current | Proposed | | :--- | :---: | :---: | | Log methods (Aardvark.log(), ARKLog(), ARKLogWithType()) | CoreAardvark | CoreAardvark | | Log message primitives (ARKLogMessage, ARKLogType) | CoreAardvark | CoreAardvark | | Log storage (ARKLogStore, ARKDataArchive, file management utilities) | CoreAardvark | CoreAardvark | | Log distribution (ARKLogDistributor, ARKLogObserver) | CoreAardvark | CoreAardvark | | Exception logging (ARKExceptionLogging) | CoreAardvark | CoreAardvark | | Log formatting (ARKLogFormatter, ARKDefaultLogFormatter | Aardvark | CoreAardvark | | In-app log viewing (view controllers and sharing utilities) | Aardvark | CoreAardvarkLoggingUI | | Screenshot logging (ARKLogScreenshot() and distributor additions) | Aardvark | Aardvark | | Bug reporter protocol (ARKBugReporter) | Aardvark | Aardvark | | Bug report attachments (ARKBugReportAttachment) | Aardvark | Aardvark | | Convenience method to add (generic) bug reporter via gesture | Aardvark | Aardvark | | Email bug reporter (ARKEmailBugReporter, ARKEmailBugReportConfiguration) | Aardvark | AardvarkMailUI | | Convenience method to add email bug reporter via gesture | Aardvark | AardvarkMailUI |

    opened by NickEntin 4
  • iOS 9 : can trigger composeBug only once per session

    iOS 9 : can trigger composeBug only once per session

    Steps: (I used aardvark sample app)

    • Run aarvark against any iOS 9 device
    • Two finder long tap to trigger a bug report
    • after coming back to the app try and trigger another bug report by a long 2 finger tap. Notice that the Compose report code is never called.

    Things work again after restart

    opened by sagpatil 4
  • Include system build version in email body

    Include system build version in email body

    When bugs are reported from a beta OS, the prefilled email body looked like:

    System Version: 11.0

    It's useful to be able to determine which beta/build of the OS, and this PR updates it to be:

    System: Version 11.0 (Build 15A5361a)

    opened by natan 3
  • avoid leaking objects when exceptions are thrown

    avoid leaking objects when exceptions are thrown

    @jbmorgan pointed out that by default, under ARC, the lifetime of a variable caught in an exception does not end when a scope ends https://clang.llvm.org/docs/AutomaticReferenceCounting.html#exceptions

    by making a __weak reference before entering an @try block, we can avoid leaking memory when hitting assertions around low disk space (to avoid also crashing due to low memory!)

    similarly @JaviSoto pointed out that we should combine data into one object before calling write, to ensure we atomically write everything or nothing.

    opened by zadr 0
  • Non-existent path referenced in podspec

    Non-existent path referenced in podspec

    The AardvarkLoggingUI podspec has a source file pattern that matches Swift code however the pod is Objective-C only.

      s.source_files = 'Sources/AardvarkLoggingUI/**/*.{h,m,swift}'
    
    opened by jszumski 0
  • Filtered highlight errors in log stores to only recent errors

    Filtered highlight errors in log stores to only recent errors

    The highlighted errors can often contain red herrings in the form of old errors that aren't relevant to the issue that was seen just prior to filing the bug report. While some errors can have downstream effects much later, I've found that more often than not an older error message is unrelated and simply adds noise.

    This filters out error messages that are older than 1 hour from the highlighted errors. The time interval is configurable, so developers can adjust as appropriate for their app's behavior.

    opened by NickEntin 1
  • Provide a mechanism for surfacing highlights from attachments

    Provide a mechanism for surfacing highlights from attachments

    This stems from a desire to have bug reporters (in particular the ARKEmailBugReporter) treat the log store as just another attachment, rather than special casing it. Currently the only major behavioral difference between the log stores and the other attachments is that the reporter pulls the recent errors out of the logs and surfaces them at the top level. This is vital behavior in the case where attachments aren't available, but it's also very useful when there are attachments to provide a quick hint as to what the problem might be before digging into each attachment.

    I think it would be fairly straightforward to introduce a highlightsSummary property (exact naming TBD) to ARKBugReportAttachment so that any attachment could optionally surface highlights at the top level. This would also unblock making the log store be a regular attachment, since the recent error logic could be easily moved to the LogStoreAttachmentGenerator.

    enhancement 
    opened by NickEntin 0
  • Logging before the default log store is accessed results in dropped messages

    Logging before the default log store is accessed results in dropped messages

    The default log store get lazily created the first time you access the defaultLogStore property. If you follow the one-line setup approach, this happens immediately since we access the default log store in order to create the bug reporter. If you don't use this setup, however, instead opting to create the bug reporter later, calling log(...) will send the message nowhere (or really will send the message to other log observers you've added, but not the default log store).

    I think the expected behavior would be to create the default log store the first time log(...) is called if it doesn't already exist.

    bug 
    opened by NickEntin 2
Releases(CoreAardvark/3.0.2)
Owner
Square
Square
Awesome bug reporting for iOS apps

Buglife is an awesome bug reporting SDK & web platform for iOS apps. Here's how it works: User takes a screenshot, or stops screen recording User anno

Buglife 498 Dec 17, 2022
Flexible bug report framework for iOS

Clue is a simple smart-bug report framework for iOS, which allows your users to record full bug/crash report and send it to you as a single .clue file

Ahmed Sulaiman 279 Nov 3, 2022
Example repo for reproduction of a cocoapods bug

CocoapodsBugExample Run a pod install with use_frameworks! un-commented, see how Pods/CoreDataPodSample compile sources includes CoreDataPodSample.xcd

null 0 Nov 3, 2021
Makes it easier to support older versions of iOS by fixing things and adding missing methods

PSTModernizer PSTModernizer carefully applies patches to UIKit and related Apple frameworks to fix known radars with the least impact. The current set

PSPDFKit Labs 217 Aug 9, 2022
Trackable is a simple analytics integration helper library. It’s especially designed for easy and comfortable integration with existing projects.

Trackable Trackable is a simple analytics integration helper library. It’s especially designed for easy and comfortable integration with existing proj

Vojta Stavik 145 Apr 14, 2022
Simple iOS app blackbox assessment tool. Powered by frida.re and vuejs.

Discontinued Project This project has been discontinued. Please use the new Grapefruit #74 frida@14 compatibility issues frida@14 introduces lots of b

Chaitin Tech 1.6k Dec 16, 2022
SwiftCop is a validation library fully written in Swift and inspired by the clarity of Ruby On Rails Active Record validations.

SwiftCop is a validation library fully written in Swift and inspired by the clarity of Ruby On Rails Active Record validations. Objective Build a stan

Andres Canal 542 Sep 17, 2022
iOS library to help detecting retain cycles in runtime.

FBRetainCycleDetector An iOS library that finds retain cycles using runtime analysis. About Retain cycles are one of the most common ways of creating

Facebook 4.1k Dec 26, 2022
A dynamic library for Cornerstone macOS.

Cornerstone-Hook A dynamic library for Cornerstone macOS. Screenshot Overview Quick Start sudo ./install.sh Install or Upgrade CornerstoneStart.app su

ivar 3 Oct 8, 2022
A library that enables dynamically rebinding symbols in Mach-O binaries running on iOS.

fishhook fishhook is a very simple library that enables dynamically rebinding symbols in Mach-O binaries running on iOS in the simulator and on device

Meta 4.9k Jan 8, 2023
DaisyChain is a micro framework which makes UIView animations chaining dead simple.

DaisyChain DaisyChain is a micro framework which makes UIView animations chaining dead simple. It uses the exact same interface you are familiars with

Ali Karagoz 31 Nov 3, 2022
Matthew Asaminew 0 Jan 25, 2022
Dead simple calendar implementation

Package provides a CalendarView which can be used to display simple calendar in your App.

Sergei Kononov 4 Oct 7, 2022
Dead-simple queue-oriented client for Spotify

Spotiqueue A terribly simple macOS app for keyboard-based, queue-oriented Spotify use. Many years ago i built a version which relied on a now-deprecat

paul 74 Dec 3, 2022
A dead-simple abstraction over the iOS BackgroundTask API to make background tasks easy to isolate, maintain and schedule

A dead-simple abstraction over the iOS BackgroundTask API to make background tasks easy to isolate, maintain and schedule. Designed to be as lightweight and flexible as possible while tightly integrating with the system APIs. And It's built with Swift Concurrency in mind.

Sam Spencer 31 Dec 11, 2022
A dead simple programming language.

checked Checked is a dead simple programming language. Variable declarations with type inference func main() { let constantVariable = 5 var va

Oliver Letterer 2 Oct 21, 2022
A Mac command-line tool that generates kick-ass Jamf Pro reports.

KMART - Kick-Ass Mac Admin Reporting Tool A command-line utility generating kick-ass Jamf Pro reports: Features Reporting on the following Jamf Pro ob

Nindi Gill 86 Dec 15, 2022
Measure Swift code metrics and get reports in Xcode, Jenkins and other CI platforms.

Taylor ⚠️ Taylor is DEPRECATED. Use SwiftLint instead. A tool aimed to increase Swift code quality, by checking for conformance to code metrics. Taylo

YOPESO 301 Dec 24, 2022
Convert xcodebuild plist and xcresult files to JUnit reports

trainer This is an alternative approach to generate JUnit files for your CI (e.g. Jenkins) without parsing the xcodebuild output, but using the Xcode

fastlane Community 247 Dec 13, 2022
Library that makes it easy to create multiple environments within a single app. You can switch environments without deleting the application.

AppContainer Library that makes it easy to create multiple environments within a single app. You can switch environments without deleting the applicat

null 8 Dec 15, 2022