WARNING
This page supports the iOS agent prior to version 2.0. If you are still using this version, please upgrade as soon as possible. This version is no longer supported.
Introduction
The embedded agent is a bridge between your mobile application and the App47 service. It provides an easy to use API for recording session times and durations, log messages and performance events. Once you've added your iOS App to the App47 Dashboard, be sure to record the App ID as it will be used to configure the agent after installation.
iOS Agent
Download the iOS Embedded Agent, install and configure it in your iOS mobile App.
Required steps:
Optional steps:
-
Add EmbeddedAgentSettings.plist file to set additional configuration parameters
- Sending Cached Data
-
Add UncaughtException handler
-
Add logging statements to capture both debug and error conditions
-
Add timed events to capture performance data
-
Add generic events to capture user behavior
-
Using configuration groups
All of the above steps will be explained in the corresponding subsections below.
The Required Steps -- Explained
1. Download the embedded agent
- Download the embedded agent compressed disk image (DMG file) from: App47 Resource center
- Once you have downloaded the file, open the DMG file and you should see the following files:
For version 1.9 or greater:For less than 1.9:
File descriptions
File | Description | Required? |
---|---|---|
EmbeddedAgent.h | Header file for the embedded agent | Yes |
EmbeddedAgentSettings.plist | Additional settings for configuring the embedded agent. | No |
GoogleToolbox | Required files from Google Toolbox open source project to support capturing crash logs. | Yes if the UncaughExceptionHandler is used and GoogleToolbox is not already included in the project. |
JSON | (Required for agent versions lower than 1.9) SBJSON library used for messaging to the service. | Yes if the SBJSON library is not already included in your project. |
libEmbeddedAgent.a | Compiled fat (i386, armv6, armv7) library of the embedded agent. This library uses a UUID generator to create a unique identifier for each app instance, use this if deploying through the iTunes App Store. | Yes if you want geo location information sent by the embedded agent. The CoreLocation.framework must be linked included in your project. |
libEmbeddedEnterpriseAgent.a | Compiled fat (i386, armv6, armv7) library of the embedded agent. This library uses the deprecated deviceIdentifier method on UIDevice. It is needed for security features in the enterprise, do not use this for Apps submitted to the iTunes App store. | Yes if you want geo location information sent by the embedded agent. The CoreLocation.framework must be linked included in your project. |
libEmbeddedAgentWithNo CoreLocation.a | Compiled fat (i386, armv6, armv7) library of the embedded agent with no CoreLocation.Framework. This library uses a UUID generator to create a unique identifier for each app instance, use this if deploying through the iTunes App Store. | Yes if you do not need geo location information. |
libEmbeddedAgentEnteprise WithNoCoreLocation.a | Compiled fat (i386, armv6, armv7) library of the embedded agent with no CoreLocation.Framework. This library uses the deprecated deviceIdentifier method on UIDevice. It is needed for security features in the enterprise, do not use this for Apps submitted to the iTunes App store. | Yes if you do not need geo location information. |
libGMStackStrace.a | Compiled fat (i386, armv6, armv7) library of the Google Stack Trace Toolkit, include this library if you are working in an ARC configured project. | Yes only if you are working in an ARC configured project and do not already have the google toolkit included.. |
libSBJSon.a | (Required for agent versions lower than 1.9) Compiled fat (i386, armv6, armv7) library of the SBJSon librar, include this library if you are working in an ARC configured project. | Yes only if you are working in an ARC configured project and do not already have the google toolkit included.. |
2. Include embedded agent library in your project
- Create a folder in your project and copy the contents of the DMG file to the newly created folder
- Add these files to your project by right clicking on the project, or on a folder of your choosing.
Note: Copy either the libEmbeddedAgent.a or libEmbeddedAgentWithNoCoreLocation.a to this directory.
- Command-click on the app in which you are working and select Add Files to....
- Select the App47 directory and click on the Add button.
Note: If you already use either the SBJSON or GoogleToolbox library in your application, do not include these directories.
File Check List
There are several ways to include App47 into you iOS app, please make sure that you have selected only one option in each group below.
App47 Library
Select one of the libEmbeddedAgent libraries only, selecting more than one will cause compilation errors.
-
libEmbeddedAgent.a - Use this if you are going through iTunes and want GEO data.
-
libEmbeddedAgentEnterprise.a - Use this if you are deploying through App47's Enterprise App Store and want to use the security features with GEO data.
-
libEmbeddedAgentWithNoCoreLocation.a - Use this if you are going through iTunes and do NOT want GEO data.
-
libEmbeddedAgentEnterpriseWithNoCoreLocation.a - Use this if you are deploying through App47's Enterprise App Store and want to use the security features with NO GEO data.
SBJson Library
- Include either the JSON directory OR the libSBJSon.a file, but not both.
- If you have an ARC project and using the JSON directory, make sure you exclude the files form the ARC compiler, please read this article on how to do exclude them.
- If you are using the libSBJSon.a file, please include the -all_load flag in the linker flag.
Google Toolbox Library
- Include either the GoogleToolbox directory OR the libGMStackTrace.a file, but not both.
- If you have an ARC project and using the GoogleToolbox directory, make sure you exclude the files form the ARC compiler, please read this article on how to do exclude them.
- If you are using the libGMStackTrace.a file, please include the -all_load flag in the linker flag.
3. Configure the embedded agent
The simplest way to configure the embedded agent is to include the EmbeddedAgent.h file and use the configureAgentWithAppID: selector with the App ID obtained from the App47 Dashboard. This configuration will record session start, duration, location and capture relevant device and App information.
#import "MyAppAppDelegate.h" #import "MyAppViewController.h" #import "EmbeddedAgent.h" @implementation MyAppAppDelegate @synthesize window=_window; @synthesize viewController=_viewController; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. [EmbeddedAgent configureAgentWithAppID:@"4d556ab4530a69fb4b000002"]; self.window.rootViewController = self.viewController; [self.window makeKeyAndVisible]; return YES; }
Embedded Agent Performance
The goal of the embedded agent is to provide a valuable management capability to your App without getting in the way of the App it is managing. Although nothing is free, we did try to limit the amount of resources we consume during the execution. Three key points were measure and the results are listed below.
Metric | Description | Measurement |
---|---|---|
Delay on startup | The time it takes for the agent to startup and return control back to the main thread. All remaining operations are done in background threads. | Average delay in seconds: iPhone 3g - 0.052, iPhone 4 - 0.017, iPad 2 - 0.026 |
Memory | The amount additional memory the agent consumes at a steady state. | 116KB |
Network traffic | Although the specific amount of network traffic depends on how you use the service, most packets sent to the service are less than 2KB. | Less than 2KB |
Library file size | The net increase in your App’s image size as a result of including the embedded agent. | 1.3MB |
The Optional Steps -- Explained
Add EmbeddedAgentSettings.plist file to set additional configuration parameters
The agent can also be configured with the included EmbeddedAgentSettings.plist file that includes the App ID as well as additional parameters for the embedded agent.
Configuration parameters
Name | Type | Description | Default | Required? |
---|---|---|---|---|
application id | String | The App ID provided in your dashboard. | None | Yes |
configuration update frequency | Number | The amount of time in days the agent should update it’s configuration with the service. A value of 0.5 will cause the agent to update its configuration once every 12 hours. | 1 | No |
delay data upload interval | Number | The number of seconds to wait after startup before sending data to the service. This allows your App to startup and be responsive without competing for valuable cpu and network resources. | 1 | No |
send actual device identifier | Boolean | No longer used, please remove from your plist file. | NO | No |
show network activity | Boolean | If the network indicator in the status bar should be turned on when sending data to the service. If this value is set to YES, the network activity indicator is turned on and off when sending data, otherwise the indicator is not updated when sending data. | YES | No |
configuration endpoint | String | The fully qualified url for the configuration end point for the API service. | App47 production api server | No |
agent logging level | String | Logging level for the agent. It will only log information when running in a simulator, not on a device. Valid values are “debug”, “info”, “warn”, “error”. | error | No |
send events immediately | Boolean | If generic and timed events should be sent immediately, or batched together and sent at the start of the next session like log and session data. | YES | No |
upload on exit | Boolean | Attempt to upload session, log, and any remaining event data on exit. Requires iOS 4.0. When the application is put into the background, the agent will attempt to upload it's data to the server using the iOS backgrounding task. | No | No |
capture crashes | Boolean | Configuration option to capture crash logs via the agent, used instead of InstallExceptionHandlers, do not use both methods. | No | No |
When using the EmbeddedAgentSettings.plist, the following configuration selector must be used.
#import "MyAppAppDelegate.h" #import "MyAppViewController.h" #import "EmbeddedAgent.h" @implementation MyAppAppDelegate @synthesize window=_window; @synthesize viewController=_viewController; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. [EmbeddedAgent configureAgent]; self.window.rootViewController = self.viewController; [self.window makeKeyAndVisible]; return YES; }
Sending Cached Data
The Embedded Agent can be configured to send data at the beginning of session, or at the end. However if you want to force the sending of any cached data, use the following command anywhere in your mobile app.
[EmbeddedAgent sendCachedData];
Add UncaughtException handler
If you want crash log information captured and send to the service, add the following handleUncaughException handler to your application delegate. This will capture any crash log information locally. The crash log information will then be uploaded the next time application is started.
void handleUncaughtException(NSException *exception) { EALogCrashException(exception, @"Application Crashed"); } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. [EmbeddedAgent configureAgent]; NSSetUncaughtExceptionHandler(&handleUncaughtException); self.window.rootViewController = self.viewController; [self.window makeKeyAndVisible]; return YES; }
To capture all crash exceptions, use the InstallExceptionHandlers method to register default handlers for uncaught exceptions and signal handlers.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. [EmbeddedAgent configureAgent]; [EmbeddedAgent InstallExceptionHandlers]; self.window.rootViewController = self.viewController; [self.window makeKeyAndVisible]; return YES; }
Adding logging statements to your App
Additional level logging can be added to your App to capture debug, info, warn, error and crash log information. Log information is recorded locally and then uploaded to the service the next time the application resumes the active state or is started. Examples of logging statements:
// // MyAppViewController.m // MyApp // // #import "MyAppViewController.h" #import "EmbeddedAgent.h" @implementation MyAppViewController - (void)dealloc { [super dealloc]; } - (void)didReceiveMemoryWarning { // Warn level log statement EALogWarn(@"Received memory warning"); // Releases the view if it doesn't have a superview. [super didReceiveMemoryWarning]; // Release any cached data, images, etc that aren't in use. } #pragma mark - View lifecycle // Implement viewDidLoad to do additional setup after loading the view, typically from a nib. - (void)viewDidLoad { // List of tags can be added to log statements for additional // search criteria in the web app. EALogInfoWithTags([NSArray arrayWithObject:@"MyTag"], @"View is being loaded"); [super viewDidLoad]; } - (void)viewDidUnload { [super viewDidUnload===== Level 2 Headline ===== ]; // Release any retained subviews of the main view. // e.g. self.myOutlet = nil; } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // All log macros allow for standard string format replacements // found in NSLog and stringWithFormat EALogDebug(@"View is being asked to rotate to interface orientation %d", interfaceOrientation); // Return YES for supported orientations return (interfaceOrientation == UIInterfaceOrientationPortrait); } @end
Adding timed events to your App (to capture performance data)
Timed events allow you to measure and record events in your application along with the duration of the event. Timed events are sent to the service immediately upon completion. If the agent is unable to send the event immediately, it is cached locally and then sent at the next App startup or activation. However, Timed Events are not written to disk. So if an application crashes, or is stopped, all cached time events are removed. A simple example of using timed events in your application would look like the following code:
- (void) performMyTransaction{ NSString *eventID = [EmbeddedAgent startTimedEvent:@"Transaction"]; // Perform some business logic to complete the transaction // … // [EmbeddedAgent endTimedEvent:eventID]; }
Timed events can be cleared before sending to the service using the clearTimedEvent: method or clear all events using the clearTimedEventsOlderThanTimeInterval: method.
- (void) performMyTransaction{ BOOL successful = NO; NSString *eventID = [EmbeddedAgent startTimedEvent:@"Transaction"]; // Perform some business logic to complete the transaction // … // if (successful) [EmbeddedAgent endTimedEvent:eventID]; else [EmbeddedAgent clearTimedEvent:eventID]; }
… OR …
- (void) clearAllTimedEvents { [EmbeddedAgent clearTimedEventsOlderThanTimeInterval:0]; }
Adding generic events to your App (to capture user data)
Generic Events are like Timed Events, but with no duration. Generic Events are sent to the service immediately upon request. If the agent is unable to send the event immediately, it is cached locally and then sent at the next App startup or activation. A simple example of using Generic Events in your application would look like the following code:
- (void) handleMyEvent{ [EmbeddedAgent sendGenericEvent:@"myEventName"]; // Perform some business logic to handle the event // … // }
Using Configuration Groups in your App
Configuration Groups allows you to set a collection of key value pairs through the main web interface that are then downloaded by the agent at initial startup, and then subsequently at a frequency set by the “configuration update frequency” parameter in the EmbeddedAgentSettings.plist file. Configuration items must be requested by group name and key name. A default value may be given to be used in the event that the configuration group does not contain an item with the requested key name. If a default value is not given, and the key does not exist in the group, the value nil is returned. Configuration groups can be assigned to agents based on app version, os version and platform.
A simple example of using Configuration Groups in your application would look like the following code:
(void) myMethod{ NSString *serverURLString = [EmbeddedAgent configurationStringForKey:@"server url" group:@”Server Info” defaultValue:@”http://myserver.abc.com/restapi”]; // Use the serverURLString to perform additional work... // … // }
Receiving Configuration Group Notifications
The Embedded Agent will send notifications using NSNotificationCenter when new configuration settings are received from the service. The following messages are sent when the configuration change are received.
Name | Description |
---|---|
EmbeddedAgentAppConfigurationGroupDidInsert | A configuration group was added. The name of the group is included in the userInfo notification object with the key: EmbeddedAgentAppConfigurationGroupNameKey. |
EmbeddedAgentAppConfigurationGroupDidUpdate | A configuration group was updated. The name of the group is included in the userInfo notification object with the key: EmbeddedAgentAppConfigurationGroupNameKey. |
EmbeddedAgentAppConfigurationGroupDidDelete | A configuration group was deleted. The name of the group is included in the userInfo notification object with the key: EmbeddedAgentAppConfigurationGroupNameKey. |
EmbeddedAgentAppConfigurationGroupNameKey | A configuration group was changed, either added, updated or deleted. |
(void) updateViewFromConfigurationChange:(NSNotification *) notification{ NSDictionary *userInfo = [notification userInfo]; NSString *groupName = [[userInfo valueForKey:EmbeddedAgentAppConfigurationGroupNameKey]]; // // Update view based on groupName // ... } (void) viewDidLoad{ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateViewFromConfigurationChange:) name:EmbeddedAgentAppConfigurationGroupDidUpdate object:nil]; [super viewDidLoad]; }
Sending Cached Data
The Embedded Agent can be configured to send data at the beginning of session, or at the end. However if you want to force the sending of any cached data, use the following command anywhere in your mobile app.
[EmbeddedAgent sendCachedData];
Releases
1.9.2
-
Fixed issue with sending events right away.
1.9.1
-
Added “capture crashes” option to configuration parameter.
1.9
-
Removed SBJson from project, it is no longer required.
1.8.2
-
Removed support for arvm6 and added arvm7s, arvm7 is still included.
-
Added “sendCachedData” command which will force the sending of cached data.
1.7.11
-
Extended the time out for all requests.
-
Added retries when fetching configuration groups to address issues with spotty connections.
1.7.10
-
Fixed bug with empty configuration groups as it was causing a crash.
1.7.9
-
Fixed bug with security policy, if the network is disabled, the security policy wasn't being applied. Bug fixed.
-
Fixed bug when clearing timed events.
1.7.8
-
Added the ability to configure agent settings (as in EmbeddedAgentSettings.plist) programatically.
1.7.7
-
Fixed an issue uploading crash logs to server.
-
Fixed an issue on the Upload on exit feature.
1.7.6
-
Enabled the agent to be reconfigured on the fly without a restart.
1.7.5
-
Added new method to agent to retrieve all the keys and values for a configuration group in one call, see EmbeddedAgent.h file for more information on method configurationGroupAsDictionary:.
1.7.4
-
Fixed issue with configuration parameter configuration update frequency; the calculation was not correct.
1.7.3
-
Updated agent version number, 1.7.2 as it was reporting as version 1.7.1.
1.7.2
-
Updated Google Toolkit files to work nicely with iOS 6, please update ALL files contained in the Google Toolbox directory.
-
Updated the behavior of the version enforcement feature to only work on the device, not while running in the simulator.
1.7.1
-
Fixed agent logging messages to only appear when running in the simulator.
1.7
-
Added app version management feature that enforces the user to run the active version. This is configured at the server level.
-
Added “upload on exit” feature that uploads session, log, and event data when the app is backgrounded.
1.6.2
-
Fixed encoding issue with API server when sending XML documents as part of a log message.
1.6.1
-
Timed events were not being sent with the option send events immediately was set to NO. Fixed.
1.6
-
Print out agent version number if logging level is agent set to debug.
-
Added configuration parameter to support sending generic and timed events either immediately, as they have always been, or batched up and sent along with log and session data. The default behavior is to send the event data immediately.
1.5.7
-
Improved duration calculation.
-
Fixed memory leak reported by Instruments 4.3.1 that had not been seen before.
1.5.6
-
Added defensive coding for real time endpoints, if none are returned by the configuration endpoint, or the agent hasn't registered yet. The agent will first try the configuration endpoint.
1.5.5
-
Added defensive coding around key methods in the agent to ensure any failures do not crash the app.
-
Added new parameter in configuration to control the agent logging level. This will only send log messages to the console when running in the simulator.
-
Separated the libraries for enterprise and non enterprise builds. Non enterprise builds no longer have the call to obtain the UDID [[UIDevice currentDevice] deviceIdentifier] which has been deprecated and will eventually not be allowed through iTunes review process.
1.5.3
-
Added internal logging capability for the Agent. Instead of the agent logging to the console, it will send any agent errors or issues to the App47 service for diagnostics.
-
Updated the default production endpoint to use the app47 domain.
-
Changed the duration calculation for timed events to use the phone's relative time for start and end instead of the adjusted time for the event. This was causing negative durations due to the offset getting changed between the start of the event and the end.
1.5.2
-
Added [EmbeddedAgent InstallUncaughtExceptionHandler], which registers crash and signal handlers for your app and sends crash logs if any signals are received.
-
Added the ability to clear out timed events by either ID, or NSTimeInterval.
1.5.1
-
Added Armv6 library back into the build for all *.a files.
-
Fixed issue for configuration items not updating when the file changes, but the name does not.
Comments
0 comments
Please sign in to leave a comment.