Skip to main content

Activity history

Shake tracks user's interaction with your app, their network traffic, notifications, logs and system events, and automatically attaches all of those to the ticket.

Setup

User actions

Shake automatically observes taps made on your app's UI elements.

note

This feature is disabled for apps built with SwiftUI.

Network traffic

Setup

Network traffic logging works by stubbing the URLSessionConfiguration object attached to your app's URLSession.

note

Make sure to call Shake's registerSessionConfiguration method before initialising your URLSession.

NetworkService.swift
let userConf = URLSessionConfiguration.default
Shake.registerSessionConfiguration(userConf)
let customSession = URLSession(configuration: userConf, delegate: self, delegateQueue: nil)

In the example above, Shake will start intercepting network requests made by your customSession and they will appear in activity history.

note

Shake can intercept only http and https network requests. Other protocols are neither intercepted or affected.

Apps can have multiple URLSessions or create them for individual requests, but as long as the URLSessionConfiguration is passed to Shake via Shake.registerSessionConfiguration, the requests will be intercepted.

Integration with other networking libraries is done by registering the URLSessionConfiguration object with Shake and passing the configuration to the library initializer method.

Advanced: Handle authentication challenges

Advanced users may use SSL pinning for their URL requests.

Without Shake, the delegate of the native URLSession receives authentication challenges via the native URLSession:didReceiveChallenge:completionHandler method and is in charge of calling the completion handler with the appropriate arguments.

Because of the way Shake network traffic logging works, those authentication delegate methods won't get called any more. You address that by registering an Authentication Delegate which conforms to the SHKSessionAuthenticationProtocol protocol. Shake will forward all authentication challenges to the delegate object which is in charge of calling the completionHandler closure with the appropriate result.

Apps which require server authentication usually have the authentication mechanism already implemented. It should be easy to just tweak it so it starts from the Shake authentication delegate instead.

note

Shake doesn't intercept or affect auth mechanisms of other SDKs in your app.

NetworkService.swift
class AuthenticationDelegate: NSObject, SHKSessionAuthenticationProtocol {
func didReceive(_ challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
/// React to challenge and call the completion handler
completionHandler(.performDefaultHandling, nil)
}
}
class NetworkService {
private lazy var authenticationDelegate: SHKSessionAuthenticationProtocol = {
let authDelegate = AuthenticationDelegate() /// Inject trust certificate handlers etc...
return authDelegate
}()
private func configureSession() -> URLSession {
let userConf = URLSessionConfiguration.default
let authDelegate = self.authenticationDelegate
Shake.registerSessionConfiguration(userConf)
let customSession = URLSession(configuration: userConf, delegate: self, delegateQueue: nil)
Shake.registerAuthDelegate(authDelegate)
}
}

The snippet above causes authentication challenges from your URLSession to sink through the protocol method in your AuthenticationDelegate class.

Advanced: Custom URLProtocol

If your app is registering a custom URLProtocol class and is already intercepting your app's requests, do not use the Shake.registerSessionConfiguration or Shake.registerAuthDelegate methods as they would interfere with the URLProtocol subclass you defined. Instead, use the Shake.insertNetworkRequest method to insert network requests manually while maintaining your custom implementation intact.

Advanced: Manual inserting

Network events can also be manually inserted into Shake's activity history. Use this if your app is using its own URLProtocol or if there are only certain network events that should be logged. Here's an example:

UserService.swift
private func getUser(withSession session: URLSession, andRequest request: URLRequest) {
session.dataTask(with: request) { (data, res, error) in
let networkRequest = NetworkRequestEditor(request, response: res, responseData: data, error: error, timestamp: .init(), duration: 0.5)
Shake.insertNetworkRequest(networkRequest)
}
.resume()
}

System events

App lifecycle events

App lifecycle events are tracked automatically and require no additional setup.

Screen changes

In apps built with UIKit, Shake automatically logs app screen (ViewController lifecycle) changes.

Apps built with SwiftUI have to use the provided View extension in their top-level Views which represent screens. shakeIntercept View extension allows Shake to hook into the View lifecycle so it can get notified of screen changes. The extension won't alter your Views in any way.

MySwiftUIContentView.swift
struct UserDetailsView: View {
var user: UserModel
var body: some View {
VStack {
user.avatar
Text("Name: \(user.name)")
/// Additional layout
}.shakeIntercept(viewName: "UserDetails")
}
}

Notifications

Notifications are tracked automatically and require no additional setup. If you want Shake to manually handle notification tracking, use this method instead:

AppDelegate.swift
Shake.handleNotification(withNotificationTitle: notificationTitle, notificationDescription: notificationDescription)

Custom logs

You can add your own logs to Activity history too:

AppDelegate.swift
Shake.log(LogLevel.info, "Log message goes here!")

You have these log levels at your disposal:

AppDelegate.swift
LogLevel.verbose
LogLevel.debug
LogLevel.info
LogLevel.warn
LogLevel.error

Console logs

Console logs are recorded automatically and require no additional setup. If you want to disable this feature use the method below:

AppDelegate.swift
Shake.configuration.isConsoleLogsEnabled = false

Limitations

In a Free workspace you can see up to 20 events that led to the ticket being reported. If you need to dive really deep to find causes of the weirdest bugs, in a Premium workspace you can browse the full Activity history.

The network request limits for both the request body and the response body are 100 kB each. If the request body or the response body contains binary data, it will be presented as a Binary data string.

Disable

Activity history is enabled by default, use the method below to disable it altogether:

AppDelegate.swift
Shake.configuration.isActivityHistoryEnabled = false