CoreData monitor

Browser for CoreData stores in your app. Shows model scheme just like Xcode editor, allows to navigate data, follow relations, switching contexts and running custom fetch requests against any model / context.

15601560

SQLite monitor

Provides browser for sqlite databases found in your app. Allows to track all queries, shows DB scheme and data in DB. You can issue custom SQL query on any DB and see results in browser immediately.

15601560

HTTP monitor

Shows all HTTP traffic in your app. You can examine any request, see request/response headers and body.
We provide XML and JSON highliting for request/responses with formatting and folding options so even huge responses are easy to look through.

15601560

Logs monitor

Displays all logs generated by your app. Logs monitor gets data from two main sources, one is stdout/stderr streams of your app and second is logs generated via AppSpector SDK built in logger. To use SDK logger there is a class ASAppSpectorLogger with a logMessage(_ message: String, tag: String, level: ASLogEventLevel) class method. Message and tag will be displayed along with other log messages in log monitor in web dashboard. Log level could be used to filter logs.

Log monitor has API to provide available log sources, you can use following property in AppSpectorConfig class: logMonitorSources: [LogSource]. Available values for LogSource are system that represents stdout/stderr streams and user for SDK logger. By default both sources are enabled. You can change sources anytime before the SDK run() call.

We also provide integration with popular logging framework CocoaLumberjack, all your logs written with loggers from it will be displayed with respect to their logging levels.

15601560

Location monitor

Most of the apps are location-aware. Testing it requires changing locations yourself. In this case, location mocking is a real time saver. Just point to the location on the map and your app will change its geodata right away.

15601560

Screenshot monitor

Simply captures screenshot from the device.

Performance monitor

Displays real-time graphs of the CPU / Memory/ Network / Disk / Battery usage.

Environment monitor

Gathers all of the environment variables and arguments in one place, info.plist, cli arguments and much more.

Notification Center monitor

Tracks all posted notifications and subscriptions. You can examine notification user info, sender/reciever objects, etc.
And naturally you can post notifications to your app from the frontend.

File System monitor

Provides access to the application sandbox and bundle. Using this monitor you can download, remove or upload files, create directories and just walk around your app FS.

Commands monitor

In short commands monitor is a remote callback collection. It allows you to register custom class as a command then trigger it from the frontend and complete or fail it from your code after performing some actions. To register the command it should be inherited from the ASCommand class:

class GetAppAuthStatus: ASCommand {
    override class var category: String { "utils" }
    override class var name: String { "logs" }
    override init() {}
}
@interface GetAppAuthStatus : ASCommand
@end

@implementation MyCommand
+ (NSString *)category { return @"utils"; }
+ (NSString *)name { return @"logs"; }
@end

Note that you need to mark command parameters as @objc dynamic var and optional in Swift.
For more details please see ASCommand header.

After creating command class you need to register it with SDK and provide callback:

AppSpector.addCommand(GetAppAuthStatus.self, withCallback: { c in
   let status = AuthService.shared().status;
   c.complete(status);
})
[AppSpector addCommand:[GetAppAuthStatus class] withCallback:^(GetAppAuthStatus *c) {
   Status status = [[AuthService shared] status];
   c.complete(status);
}];

Once you trigger command from the frontend callback will be triggered and command instance populated with data you filled in on the frontend will be passed as an argument. Inside the callback you should either call complete with params to finish te command or fail to fail it. Note please that queue callback will be triggered on is not guaranteed and never will be the main queue.

Events monitor

Events monitor allows you to send custom built event to the current session. Event will be processed as any other monitor event, displayed and stored in history.
To send event you build an instance of any object conforming to ASCustomEventPayload protocol.
Payload protocol defines three properties of the event:

  • name is a unique name for the event. It's how you'll distinguish deifferent events.
  • category is used for a events grouping. e.g. you can have a "networking" group where you have events related to your app network layer.
  • payload is a dictionary containing data as a key/value pairs you want to attach to the event. Only KVC compliant types are supported.

All of the above will be displayed on a frontend so you can easily find events.

After you have an instance of the payload you need to send it to the AppSpector SDK:

open class func sendCustomEvent(with payload: ASCustomEventPayload)
+ (void)sendCustomEventWith:(id <ASCustomEventPayload>)payload;

This method is thread safe and can be used from any thread.
Payloads are just data containers so you can store them in your app as you want, send later, persist etc.

Lets see an example of sendind a simple event:
First define a class conforming to a ASCustomEventPayload protocol:

class ASTestCustomEventPayload: NSObject, ASCustomEventPayload {
    var name: String!
    var category: String!
    var payload: [AnyHashable : Any]!
}
// ASTestCustomEventPayload.h
#import <AppSpectorSDK/AppSpector.h>

@interface ASTestCustomEventPayload : NSObject <ASCustomEventPayload>

@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *category;
@property (nonatomic, strong) NSDictionary *payload;

@end

// ASTestCustomEventPayload.m
@implementation ASTestCustomEventPayload
@end

Then make an instance of it:

let payload = ASTestCustomEventPayload()
payload.name = "My sample event"
payload.category = "Testing events"
payload.payload = ["Triggered at": "\(Date())"]
STestCustomEventPayload *payload = [ASTestCustomEventPayload new];
payload.name = @"My sample event";
payload.category = @"Testing events";
payload.payload = @{ @"int" : @1,
                     @"float" : @(3.14f),
                     @"bool" : @YES,
                     @"string" : @"foo bar" };

And finally send it to the SDK:

AppSpector.sendCustomEvent(with: payload)
[AppSpector sendCustomEventWith:payload];