Whew, two months went by like a bullet. Previously, I wrote a post about what NSLogger is, and why we should exploit it to solve a problem. (About a month ago, even HN talked about NSLogger.)
In order to recap, NSLogger is a very powerful utility that collects logs from your application and provides you rich tool sets to analyze them. My goal is to take the power of NSLogger outside your cubicle to monitor how your app really behaves in unfabricated environments.
NSLogger comes with two parts; libraries for clients (iOS & Android. Yes, it does cover android.), a viewer on OSX. All we need is an iPad Viewer app we can carry outside. OSX viewer is thus a good place to start looking since it is written in same language (Object-C), and shares mostly the same ground with iOS.
So here comes an overview of OSX viewer.
The viewer is, in essence, a server application which accepts logs from client via stream sockets. It is built in classic MVC pattern having abstracted transports, connections, and log message as model.
The viewer supports three different types of streams (non-secure Bonjour, secure Bonjour with SSL, and direct TCP/IP) and abstracts them in LoggerTransport. Each transport runs its own thread managing client connections with LoggerConnection. A connection then collects and handles each log message with LoggerMessage.
Once instantiated, transports are there to be kept running throughout the life-cycle of the viewer. Meanwhile, a connection will get spawned and removed for each run of a client. If we are to look at how they fit altogether from 10,000 feet, it should look like below.
I believe the setup of model layer part is nicely done, and, at some degree, it is beautiful. The beauty is two folded.
1) First one being that with each layer of abstraction, we can expand or modify to totally different types of connections without too much hassle. Not a lot of network libraries get this right; some being too complicated, or some being too poorly constructed to see it through.
2) With each transport running its own thread and especially its own run-loop, stream events do not get in UI events and vice versa. You’d never miss a stream event just because you touch a cell too long. Plus, we can set up as many transports as we need and no stream event will interfere another as transports are all separated in their own thread and run-roop. Imagine you have ten stream sockets all running on main thread’s run loop. What mayhem are you willing to go though? This seems really no-brainer, but believe me. Even the most popular socket libraries are not built in this way.
LoggerDocument, a NSDocument subclass, is controller part of OSX viewer. It sticks to the idea ‘fat model, thin controller’, and really carries out. All the heavy lifting is done in model layer and LoggerDocument only routes the messages to view layer.
Each LoggerDocument instance organizes log messages and related views in the context of a client’s activity. LoggerDocument holds all the connections from a single client, and a connection holds all the log messages for a run. If you’re to navigate from a connection to another, you are effectively navigating log messages from one run to another. If you jump from a LoggerDocument to another, you actually move from an activity of a single client to that of another.
Looking down from LoggerDocument, you can see it really represents a whole collection of a client’s activity. This enables the Viewer to have multiple clients connected simultaneously, and to manage them in very organized fashion.
Finally, the view. LoggerWindowController, a subclass of NSWindowController, forms 1 to 1 relationship between LoggerMessageCell and LoggerMessage. LoggerMessageCell then draws LoggerMessage’s content. Simple as that. The thing that makes interesting is how LoggerMessage never gets opened between LoggerTransport and LoggerMessageCell. If you are with me until this point, you can see the whole OSX viewer really comes down to two parts; one that handles socket stream and unpacks raw log, and one that displays the unpacked message. You can take the two parts and put them together as an app, and none will stop you.
The structure in between the two parts, however, keeps collected data very neatly organized, and enables further modification/maintenance without headache. NSLogger OSX viewer really is an exemplary case to carefully study MVC pattern as well as handling of socket stream. I was blown away as soon as I found this was BSD licensed opensource.
In next post, I will describe how to setup iOS keychain to handle self-signed cert to open SSL connections. Please consider subscribing my blog as more awesome stuffs are already in pipeline, and dropping a word to Florent, who single-handedly made all these possible.
* Update : Controller and View parts were added.