How To: Instrument A Swift iOS App With New Relic Mobile

By Posted in Tech Topics 12 June 2014

I make iOS apps. I care about how stable and performant they are, so I’m excited by Apple’s announcement of its latest programming language, Swift. People have been asking me what it means for New Relic Mobile. swift1We’ve been experimenting with Swift. Of course we’re curious about how Swift code interacts with the Objective-C runtime and what app execution looks. Read on to learn what makes Swift apps tick and how we wired up the New Relic SDK to get a preview of what the future holds. In this blog post I will:

  1. Explain how Swift interacts with Objective-C,
  2. Show you how to get New Relic running in a Swift app, and
  3. Share some simple Swift code that demonstrates the power of code-level tracing.

Is it possible to instrument Swift apps?

Swift apps use Cocoa frameworks like Foundation and UIKit, just like Objective-C apps. Your Swift code runs side-by-side with system frameworks, C libraries, and other Objective-C code. New Relic already automatically instruments many of those libraries. So with a few minutes of work you will get the same visibility into networking, image loading, JSON parsing, and CoreData that you get in traditional iOS apps. Your Swift code itself is compiled down to machine code and is not visible to the current New Relic SDK. However, we can make use of the Swift/Objective-C bridge to capture performance data of your Swift classes and see how it interacts with the underlying Cocoa APIs that we already instrument.

Running New Relic in a Swift app

Deploying New Relic’s iOS SDK into a Swift app is almost exactly like an Objective-C app. The one difference is that you’ll have to set up your app to be a “mixed target” and configure the bridging code that allows Swift and Objective-C to talk to each other. This is covered in step 3 below. 1. Create a new iOS swift app in XCode If you’re an experienced developer, this one should need no explanation. I’ve created an app called Vaux’s Swift. 2. Add the New Relic framework Drag NewRelicAgent.framework into your project just like you’ve always done. swift11 3. Set up a Bridging Header Swift provides a mechanism, called Bridging, that allows Swift and Objective-C code to interact within the app. This bridging behavior has to be enabled for each project. How to enable bridging: If you don’t have a “[Project Name]-Bridging-Header.h” file in your project, the simplest way to set it up is to create an Objective-C file, name it Placeholder.m. XCode will prompt you to setup the Bridging Header. swift3 How to bridge the New Relic SDK: Now open the Bridging-Header and #import the New Relic header.

 // vaux_s_swift-Bridging-Header.h // // Use this file to import your target's public headers // that you would like to expose to Swift. // #import "NewRelicAgent/NewRelic.h" 

Once you’ve done this, it’s safe to delete the Placeholder.m file. 4. Initialize the agent in your AppDelegate.swift

 @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate var window: UIWindow? func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool { // Swift exposes the NewRelic class NewRelic.startWithApplicationToken("YOUR_APP_TOKEN_HERE") return true } … 

5. Add the required frameworks and libraries to your build settings Select your project in the navigator, then the application target, and the General properties tab. Scroll down to “Linked Frameworks” and ensure NewRelicAgent, CoreTelephony, SystemConfiguration, and libz.dylib are shown. swifttttt 6. Fire it up! When you run your app, it will initialize the SDK and report performance data to New Relic. swift31 Because Swift builds upon the Cocoa frameworks we already instrument, you’ll see network analytics, UIImage and JSON loading, etc.

Better Interaction tracing

Now that you’re up and running, you’ll notice that all of your Interactions show up in New Relic named UIViewController. Swift implements view controllers by subclassing the Objective-C UIViewController class. New Relic doesn’t yet automatically detect these subclasses. We can make your data much more interesting by starting Interaction traces at the right point in your Swift code. Simply add a call to NewRelic.startInteractionFromMethodName() in each Swift ViewController to improve the data New Relic reports.

 class ViewController: UIViewController { override func viewDidLoad() { // Manually start tracing the Interaction here, // rather than in the UIViewController parent class NewRelic.startInteractionFromMethodName("viewDidLoad", object: self) super.viewDidLoad() } 

Rebuild and run the app. After a couple of minutes, you will see an Interaction named after the generated name of each Swift ViewController class.

Using the New Relic SDK to instrument your Swift native code

Let’s look at instrumenting some of our Swift application code using New Relic’s SDK. As I mentioned earlier, at present the New Relic SDK does not automatically instrument compiled Swift code. First, I will create a helper class to make interacting with the SDK a bit easier. Then I’ll create a simple image downloader and add custom instrumentation using the helper class. 1. Implementing an SDK helper Create a new NRHelpers.swift file.

 import Foundation class NRMethodTimer { var timer: NRTimer init(methodName name:String, forObject context:AnyObject, ofCategory category:NRTraceType) { timer = NRTimer() NewRelic.startTracingMethod(Selector(name), object: context, timer: timer, category: category) } func exit() { NewRelic.endTracingMethodWithTimer(timer) } } 
Note: In Swift, instances of classes and structures are technically referred to as instances, not objects. As the New Relic SDK operates specifically on objects, we have chosen to use the object naming convention in this code.

2. Implement an ImageFetcher helper class ImageFetcher takes care of downloading an image from a URL and loading it into a UIImageView. After initializing an instance, you call run() to initiate the asynchronous retrieve and display functionality. Once the network request completes, the finish() method creates a UIImage and displays it in the stored UIImageView. You’ll notice I am using the NRMethodTimer to instrument the methods I care about. 3. Adding a UIImageView and loading an image I’ve added a new method, ViewController.loadImage(), that takes care of creating and starting a new ImageFetcher. In ViewController.viewDidLoad(), I create a UIImageView and call loadImage() to populate it asynchronously.

 class ViewController: UIViewController { func loadImage(source imageSource:String, forView imageView:UIImageView) { let timer = NRMethodTimer(methodName: "loadImage", forObject: self, ofCategory: NRTraceTypeViewLoading) let loader = ImageFetcher(source: imageSource, forView: imageView) loader.run() timer.exit() } override func viewDidLoad() { NewRelic.startInteractionFromMethodName("viewDidLoad", object: self) super.viewDidLoad() // an image to retrieve let sourceUrl = "https://farm4.staticflickr.com/3843/14356460721_3a1bdf3b40_b.jpg" // a view to display it let iView = UIImageView(frame: CGRectMake(10, 10, 340, 340)) self.view.addSubview(iView) self.loadImage(source: sourceUrl, forView: iView) } … // other ViewController methods } 

4. Enjoying the results Now in the Interaction breakdown you see execution data for all of your instrumented methods alongside the Cocoa APIs New Relic automatically instruments. swift32 Digging deeper into Interaction traces, you’ll see the Swift methods that make use of NRMethodTimer. Here’s a snapshot showing ImageFetcher.finish(), which creates a UIImage from the downloaded data and then assigns it to the saved UIImageView. swiftfinal At New Relic, we’ll continue to explore performance monitoring of apps built using Swift, and keep you updated on any interesting outcomes. In the meanwhile, if you want to try this out for one of your own Swift apps, download New Relic Mobile. Until next time, happy app building! You can download the source for this demo app, including NRMethodTimer and ImageHelper, from GitHub here: https://github.com/newrelic/vauxs-swift **Swift image via Flickr/Kat+Sam.

About the author

jkaron@newrelic.com'Jonathan Karon built New Relic's Mobile APM team. He spends his days inventing new ways to measure every aspect of mobile apps from the inside out and fine-tuning a world-class engineering group. When he's not talking about mobile apps as the ultimate distributed system, Jon can be found in the woods or experimenting with the menagerie of mobile projects. A tech polyglot he has been involved in various unfamous tech startups and was doing mobile-social-local-real-time apps when the Apple Newton was still hot.

Tell us your thoughts Or Send us an internal high five

Talk to @newrelic