Readme
The module has three independent functional areas. It provides
1) Convenience methods to log messages and granular control over which messages are being logged.
2) Collection of log messages into files.
3) Reporting error conditions (exceptions and crashes).
You can take advantage of any one of these features, together or independently from each other.
To access this module from JavaScript, you would do the following:
var Logger = require('com.logicallabs.logger');
var dummy = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, 'dummy');
Note the line starting with "var dummy". On iOS,
that line ensures that the Ti.Filesystem module (a standard part
of the Titanium SDK) will be linked into the app.
This is only necessary if the application doesn't otherwise reference the
Ti.Filesystem module.
The Logger module uses the
Ti.Filesystem module so that it can return the same type of File object as
what you get from Ti.Filesystem.getFile(). However, the build process of the
application itself is not aware of this, so if the app does not have any
references to Ti.Filesystem then, in an effort to decrease the app's footprint,
the Ti.Filesystem module will not be linked into the app.
This will result in a failure when the app is built.
Usage -- Logging
The basic logging function is Logger.log
. It can take 1, 2, or 3
arguments as follows:
Logger.log('Message');
Logger.log(Logger.INFO, 'Message');
Logger.log(Logger.DEBUG, 'Group1', 'Message');
Here Logger.INFO
and Logger.DEBUG
are what we refer
to as log-levels. The module provides a global logLevel
property
that allows you to limit the messages that are actually printed to a specific
log level and above:
Logger.logLevel = Logger.INFO;
This will make sure that only INFO level messages or higher will be printed, DEBUG level messages won't. The priority of the log levels, in decreasing order, are as follows:
Logger.ERROR
Logger.WARNING
Logger.INFO
Logger.DEBUG
Logger.TRACE
The DEBUG level has further 9 sub-levels, from Logger.DEBUG1 to Logger.DEBUG9.
The module also provides convenience functions that have an implied log level. For example,
Logger.log(Logger.DEBUG, 'Group1', 'Message');
can be written as:
Logger.debug('Group1', 'Message');
When the log
function is invoked with 3 parameters, the 2nd
parameter ('Group1' in the above example) is an arbitrary string that we call
the "group" of the message. Assigning the messages to groups allows another
way to control which messages are printed, via the Logger.enableGroups
function:
Logger.enableGroups('Group1', 'Group3');
This line would ensure that messages in Group1 and Group3 are printed, but other groups aren't. (Messages that are not assigned to a group are always printed, regardless of which groups are enabled).
The log
function has an alternative form that takes a single object
as a parameter. This makes it possible to specify a group without a log level:
Logger.log({
msg: 'Message',
group: 'Group1'
});
Usage -- Log Collection
To initiate log collection, that is the capturing of console messages into files, call the startLogCollection function. This will start the collection of log messages into a file. Use the getLogFileInfo function to get the details of the available log files.
Log collection happens periodically, by default every 10 seconds. This means that the log messages won't appear immediately in the file.
It is generally a good idea to suspend log collection when the app is sent to the background. Call the stopLogCollection or pauseLogCollection function from the pause event listener appropriate for the platform to achieve this. The difference between stopping and pausing log collection is that stop/start creates a new (set of) log file(s), while pause/resume will keep using the previous one.
On Android, Titanium doesn't generate application-level pause and resume events. To be notified when an application is paused and resumed, you must add event listeners to its individual activities. The sample app included with this module creates a heavyweight window, which creates its own activity.
Usage -- Reporting Error Conditions
We can distinguish four types of error conditions:
1) Fatal signals (hard crashes).
2) Uncaught exceptions.
3) Exceptions caught by the Titanium framework.
4) Exceptions caught in JavaScript.
The iOS version of the module handles fatal signals (hard crashes), uncaught exceptions that trigger a fatal signal, exceptions caught by the Titanium framework, and exceptions caught in JavaScript.
To initiate error monitoring, that is the capturing of information about fatal signals, exceptions that trigger a fatal signal, and exceptions caught by Titanium into files, call the startErrorMonitoring function. Note that on iOS, the information about fatal signals (hard crashes) will be written into a file when the app is restarted after the crash.
To capture information related to an exception caught in JavaScript, call the
logException from the
try
block with the JavaScript exception object.
Symbolication
On iOS, the information generated when the application receives a fatal signal (the so-called "crash file") must be symbolicated before it can be really useful. You will need the app's .app and .dsym file from the same build that experienced the crash.
Place the .app file under build/iphone/build/Debug-iphoneos (if it's a device) or Debug-iphonesimulator (for simulator).
Symbolication can be done in two ways.
Symbolication Through Xcode
Make sure the extension of the crash file is .crash.
Drag the file into Xcode -> Window -> Organizer -> Device Logs
Right click the file and click "Resymbolicate log".
Symbolication Through Command Line
Run the symbolicatecrash
utility found in /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks/DTDeviceKit.framework/Versions/A/Resources/
.
You will need to set the DEVELOPER_DIR environment variable before running the symbolicatecrash utility as follows:
export DEVELOPER_DIR="/Applications/Xcode.app/Contents/Developer"
Run the utility by typing this:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks/DTDeviceKit.framework/Versions/A/Resources/symbolicatecrash <yourfilename>.crash
More information about symbolication can be found here.
Issues and Limitations
Uncaught exceptions that do not trigger a hard crash are currently not handled by the iOS version of the module.
Change Log
Version 1.0.0
- First release
Version 1.0.1
- Fixed bug related to pause/resumed events.
- Fixed symbol conflict with other Logical Labs modules
- Minor changes to sample app
Author
Zsombor Papp, Logical Labs
titanium@logicallabs.com
License
Logical Labs Commercial License
Copyright
Copyright (c) 2012-2013 by Logical Labs, LLC