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 today and Lumberjack has put a lot of effort in becoming more Swift-friendly, but in the interim @DaveWoodX released a native Swift logging framework known as XCGLogger.
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’s where XCGLogger shines in my opinion. Let’s take a look at how easy it is to add logging to a Swift project with XCGLogger (so easy I don’t even feel compelled to provide screenshots!).
Go to the XCGLogger Github page and click the Download ZIP button on the righthand side of the page. In your Downloads folder will be a new folder named XCGLogger-master. Open and head straight to XCGLogger – Library – XCGLogger. Drag-and-drop the single XCGLogger.swift
file into your project navigator ensuring that you select Copy items if needed.
Now, in your AppDelegate.swift
add the following after your imports but before your class
declaration:
1 |
let log = XCGLogger.defaultInstance() |
In your app delegate’s didFinishLaunchingWithOptions
function add:
1 |
log.setup(logLevel: .Debug, showLogLevel: true, showFileNames: true, showLineNumbers: true, writeToFile: nil) |
To test things out you can add a log.debug("Test")
right after that. Build and run your project. You should see the following in your console:
1 2 3 |
2014-12-29 20:35:41.595 [Info] : xcglogger Version: 1.0 Build: 1 PID: 99876 2014-12-29 20:35:41.595 [Info] : XCGLogger Version: 1.8 - LogLevel: Debug 2014-12-29 20:35:41.653 [Debug] [AppDelegate.swift:23] application(_:didFinishLaunchingWithOptions:): Test |
And really that’s it. It was so easy in fact we feel a little guilty, so let’s add the ability to log entry and exit points for functions. Create a new file, LogUtils.swift and add the following:
1 2 3 4 5 6 7 |
func ENTRY_LOG(functionName:String = __FUNCTION__, fileName: String = __FILE__, lineNumber: Int = __LINE__) -> Void { log.debug("ENTRY", functionName:functionName, fileName:fileName, lineNumber:lineNumber) } func EXIT_LOG(functionName:String = __FUNCTION__, fileName: String = __FILE__, lineNumber: Int = __LINE__) -> Void { log.debug("EXIT", functionName:functionName, fileName:fileName, lineNumber:lineNumber) } |
To test it out you can instrument one of the viewDid
or viewWill
routines of a view controller. Here I add instrumentation to viewDidLoad
:
1 2 3 4 5 |
override func viewDidLoad() { ENTRY_LOG() super.viewDidLoad() EXIT_LOG() } |
Running again and you get:
1 2 3 4 5 |
2014-12-29 20:39:04.244 [Info] : xcglogger Version: 1.0 Build: 1 PID: 128 2014-12-29 20:39:04.244 [Info] : XCGLogger Version: 1.8 - LogLevel: Debug 2014-12-29 20:39:04.268 [Debug] [AppDelegate.swift:23] application(_:didFinishLaunchingWithOptions:): Test 2014-12-29 20:39:04.279 [Debug] [ViewController.swift:14] viewDidLoad(): ENTRY 2014-12-29 20:39:04.280 [Debug] [ViewController.swift:16] viewDidLoad(): EXIT |
All of this by dragging and dropping a file out of the XCGLogger project into ours, and then adding a bit of wrapper for ENTRY_LOG
and EXIT_LOG
.
Using Swift build flags we can refine this even further by adding something along the lines of:
1 2 3 4 5 |
#if Debug log.setup(logLevel: .Debug, showLogLevel: true, showFileNames: true, showLineNumbers: true, writeToFile: nil) #else log.setup(logLevel: .Severe, showLogLevel: true, showFileNames: true, showLineNumbers: true, writeToFile: nil) #endif |
If our build configuration doesn’t include -DDebug
then our debugging severity level will be set to .Severe
. We could have also use .None
to eliminate logs altogether.
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’m going to wager that if your application is having size or performance issues its not because of your logging instrumentation.
Note: This is by no means an exhaustive summary of XCGLogger’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 XCGLogger.swift
is officially supported, I don’t know. Let’s hope it remains so easy as a great logging framework should be! For more information on XCGLogger see the official Github repository.
Please also check out my new Swift 2 Logger SwiftyBeaver which supports color(!), multi-threading and logging to file and is lightweight and fast.
Thanks for the heads up Sebastian, I will indeed check it out!
I would also appreciate your input on my logging framework
Evergreen
. It’s modeled after Python’s excellentlogging
module with adjustable log levels and everything you would expect from a logging framework:github.com/viwid/Evergreen
It’s based on a logger hierarchy that also allows you to adjust the verbosity of parts of your software, e.g. lower the log level for the part you are currently debugging. This also gives users of your framework the opportunity to configure the verbosity of your logging.
Any feedback welcome 🙂
This should be a working link: http://www.github.com/viwid/Evergreen