{"id":1196,"date":"2014-12-29T20:59:44","date_gmt":"2014-12-30T02:59:44","guid":{"rendered":"http:\/\/dev.iachieved.it\/iachievedit\/?p=1196"},"modified":"2014-12-29T20:59:44","modified_gmt":"2014-12-30T02:59:44","slug":"swift-logging-with-xcglogger","status":"publish","type":"post","link":"https:\/\/dev.iachieved.it\/iachievedit\/swift-logging-with-xcglogger\/","title":{"rendered":"Swift Logging with XCGLogger"},"content":{"rendered":"<p>When Swift was released earlier this year there was the inevitable rush to get some type of logging framework out there to use.  <a href=\"https:\/\/github.com\/CocoaLumberjack\/CocoaLumberjack\">CocoaLumberjack<\/a>, still one of my favorite logging frameworks for iOS development, made enough use of the C preprocessor to make working with it in a Swift application a pain.<\/p>\n<p>Fast forward to today and Lumberjack has put a lot of effort in becoming more Swift-friendly, but in the interim <a href=\"https:\/\/twitter.com\/DaveWoodX\">@DaveWoodX<\/a> released a native Swift logging framework known as <a href=\"https:\/\/github.com\/DaveWoodCom\/XCGLogger\">XCGLogger<\/a>.<\/p>\n<p>One of the things I look for in a logging framework is how quickly I can go from zero to logging.  If the instructions require CocoaPods or importing the logging project into my project or git submodules, well, you can forget it.  Here&#8217;s where XCGLogger shines in my opinion.  Let&#8217;s take a look at how easy it is to add logging to a Swift project with XCGLogger (so easy I don&#8217;t even feel compelled to provide screenshots!).<\/p>\n<p>Go to the <a href=\"https:\/\/github.com\/DaveWoodCom\/XCGLogger\">XCGLogger Github page<\/a> and click the <b>Download ZIP<\/b> button on the righthand side of the page.  In your Downloads folder will be a new folder named <b>XCGLogger-master<\/b>.  Open and head straight to <b>XCGLogger &#8211; Library &#8211; XCGLogger<\/b>.  Drag-and-drop the single <code>XCGLogger.swift<\/code> file into your project navigator ensuring that you select <b>Copy items if needed<\/b>.<\/p>\n<p>Now, in your <code>AppDelegate.swift<\/code> add the following <i>after<\/i> your imports but before your <code>class<\/code> declaration:<\/p>\n<pre>\r\nlet log = XCGLogger.defaultInstance()\r\n<\/pre>\n<p>In your app delegate&#8217;s <code>didFinishLaunchingWithOptions<\/code> function add:<\/p>\n<pre>\r\nlog.setup(logLevel: .Debug, showLogLevel: true, showFileNames: true, showLineNumbers: true, writeToFile: nil)\r\n<\/pre>\n<p>To test things out you can add a <code>log.debug(\"Test\")<\/code> right after that.  Build and run your project.  You should see the following in your console:<\/p>\n<pre>\r\n2014-12-29 20:35:41.595 [Info] : xcglogger Version: 1.0 Build: 1 PID: 99876\r\n2014-12-29 20:35:41.595 [Info] : XCGLogger Version: 1.8 - LogLevel: Debug\r\n2014-12-29 20:35:41.653 [Debug] [AppDelegate.swift:23] application(_:didFinishLaunchingWithOptions:): Test\r\n<\/pre>\n<p>And really that&#8217;s it.  It was so easy in fact we feel a little guilty, so let&#8217;s add the ability to log <i>entry<\/i> and <i>exit<\/i> points for functions.  Create a new file, <b>LogUtils.swift<\/b> and add the following:<\/p>\n<pre>\r\nfunc ENTRY_LOG(functionName:String = __FUNCTION__, fileName: String = __FILE__, lineNumber: Int = __LINE__) -> Void {\r\n  log.debug(\"ENTRY\", functionName:functionName, fileName:fileName, lineNumber:lineNumber)\r\n}\r\n\r\nfunc EXIT_LOG(functionName:String = __FUNCTION__, fileName: String = __FILE__, lineNumber: Int = __LINE__) -> Void {\r\n  log.debug(\"EXIT\", functionName:functionName, fileName:fileName, lineNumber:lineNumber)\r\n}\r\n<\/pre>\n<p>To test it out you can instrument one of the <code>viewDid<\/code> or <code>viewWill<\/code> routines of a view controller.  Here I add instrumentation to <code>viewDidLoad<\/code>:<\/p>\n<pre>\r\n  override func viewDidLoad() {\r\n    ENTRY_LOG()\r\n    super.viewDidLoad()\r\n    EXIT_LOG()\r\n  }\r\n<\/pre>\n<p>Running again and you get:<\/p>\n<pre>\r\n2014-12-29 20:39:04.244 [Info] : xcglogger Version: 1.0 Build: 1 PID: 128\r\n2014-12-29 20:39:04.244 [Info] : XCGLogger Version: 1.8 - LogLevel: Debug\r\n2014-12-29 20:39:04.268 [Debug] [AppDelegate.swift:23] application(_:didFinishLaunchingWithOptions:): Test\r\n2014-12-29 20:39:04.279 [Debug] [ViewController.swift:14] viewDidLoad(): ENTRY\r\n2014-12-29 20:39:04.280 [Debug] [ViewController.swift:16] viewDidLoad(): EXIT\r\n<\/pre>\n<p>All of this by dragging and dropping a file out of the XCGLogger project into ours, and then adding a bit of wrapper for <code>ENTRY_LOG<\/code> and <code>EXIT_LOG<\/code>.  <\/p>\n<p>Using <a href=\"http:\/\/dev.iachieved.it\/iachievedit\/build-configuration-management-with-swift\/\">Swift build flags<\/a> we can refine this even further by adding something along the lines of:<\/p>\n<pre>\r\n      #if Debug\r\n        log.setup(logLevel: .Debug, showLogLevel: true, showFileNames: true, showLineNumbers: true, writeToFile: nil)\r\n        #else\r\n        log.setup(logLevel: .Severe, showLogLevel: true, showFileNames: true, showLineNumbers: true, writeToFile: nil)\r\n      #endif\r\n<\/pre>\n<p>If our build configuration doesn&#8217;t include <code>-DDebug<\/code> then our debugging severity level will be set to <code>.Severe<\/code>.  We could have also use <code>.None<\/code> to eliminate logs altogether.<\/p>\n<p>Some might rightfully point out that the preprocessor mechanism employed here would be superior because it would allow for stripping out all of the code calls for logging.  This is true, but I&#8217;m going to wager that if your application is having size or performance issues its <i>not<\/i> because of your logging instrumentation.<\/p>\n<p>Note:  This is by no means an exhaustive summary of XCGLogger&#8217;s capabilities (it can be configured to write to files instead of the console, for example) and whether or not the drag-and-drop method of adding only <code>XCGLogger.swift<\/code> is officially supported, I don&#8217;t know.  Let&#8217;s hope it remains so easy as a great logging framework should be!  For more information on XCGLogger see the official <a href=\"https:\/\/github.com\/DaveWoodCom\/XCGLogger\">Github repository<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When Swift was released earlier this year there was the inevitable rush to get some type of logging framework out there to use. CocoaLumberjack, still one of my favorite logging frameworks for iOS development, made enough use of the C preprocessor to make working with it in a Swift application a pain. Fast forward to [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-1196","post","type-post","status-publish","format-standard","hentry","category-swift"],"_links":{"self":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/1196"}],"collection":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/comments?post=1196"}],"version-history":[{"count":9,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/1196\/revisions"}],"predecessor-version":[{"id":1205,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/1196\/revisions\/1205"}],"wp:attachment":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/media?parent=1196"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/categories?post=1196"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/tags?post=1196"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}