Logger Module

API Docs for: 1.0.1
Show:

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 (c) 2012-2013 by Logical Labs, LLC