+

Search Tips   |   Advanced Search

Client-side log capture

Applications in the field occasionally experience problems that require a developer's attention to fix. It is often difficult to reproduce problems in the field. Developers who worked on the code for the problem application often do not have the environment or exact device with which to test. In these situations, it is helpful to be able to retrieve debug logs from the client devices as the problems occur in the environment in which they happen.

Start in IBM Worklight v6.2.0, developers that use MobileFirst client-side APIs who want to capture both platform (IBM MobileFirst Platform Foundation) and application (your code) logs for debug and problem determination should use the appropriate client-side APIs. By doing so, debug log data is made available for capture and sending to the server.


Introduction to client-side logging

The APIs available with MobileFirst client libraries include a logger in JavaScript, Android native, and iOS native code base. The logger API is similar to commonly used logger APIs, such as console.log (JavaScript), java.util.logging (Java), and nslog (Objective-C). The MobileFirst logger API has the additional capability of persistently capturing logged data for sending to the server to be used for analytics gathering and developer inspection. Use the logger APIs to report log data at appropriate levels so that developers who inspect logs can triage and fix problems without having to reproduce problems in their labs.

There are seven levels. From least verbose to most verbose, they are FATAL, ERROR, WARN, INFO, LOG, DEBUG, TRACE.

Example usage of level-appropriate messages:


Default log capture feature behavior


During development


In production


Things to consider

During application development, consider the following questions.

Should capture be always on or always off?

The default setting of capture is ON. When capture is on, all logs at the specified level or filter are captured in a persisted rotating log buffer. We can change the default of the capture setting using the logger API.

Consider that turning capture on at a verbose logger level has an impact to resource consumption:

  • CPU

  • file system space

  • frequency of network usage when captured log data is also being sent to the server

  • size of network payload when captured log data is also being sent to the server

At what level should you set the logger?

There are seven levels. From least verbose to most verbose, they are FATAL, ERROR, WARN, INFO, LOG, DEBUG, TRACE.

For example, when capture is ON and the logger level is configured to FATAL, the logger captures uncaught exceptions. Uncaught exceptions often appear to users as application crashes or hangs, but does not capture any logs that lead up to the failure. Alternatively, a more verbose logger level ensures that logs that lead to a logger FATAL entry are captured.

Consider that verbose logger levels, when capture is ON, can affect:

  • frequency of network usage

  • size of the payload that is sent to the server

  • application performance, and therefore user experience

How frequently should clients check with the server for logger configuration changes?

By default, client applications check for updated logger configuration during the MobileFirst client network init sequence, which is not necessarily application startup or application foreground events.

The init sequence can be infrequent, depending on the design of the application. For example, the init sequence might happen only at check-out in a retail shopping application. In this example, the application can check for new configuration on every onForeground event to ensure that it retrieves and applies the configuration soon after the MobileFirst administrator sets in the Catalog tab of the operations console.

For example, to retrieve and apply configuration overrides from the server when the client comes to the foreground, we can place the WLClient updateConfigFromServer function call:

  • onResume (Android, in each Activity, if necessary)

  • applicationDidBecomeActive (iOS)

  • an onForeground event listener (JavaScript)

How can you guarantee that all captured log data on the client gets to the server?

The short answer is that there is no way to guarantee preservation of all captured data. Clients might be running the application offline and simultaneously accumulating captured log data. Because the client is offline with limited file system space, older log data must be purged in favor of preserving more recent log data, which is the behavior of the log capture feature.

We can make a best effort at ensuring that all captured data gets to the server by applying one or more of the following strategies:

  • Call the send function on a time interval.

  • Trigger a call to the send function on application lifecycle events, like pause, and resume events.

  • Batch the send call with other application network activity, like invokeProcedure. This approach allows the device radio to sleep and preserve battery.

  • Increase the capacity of the persistent log buffer on the client by calling the setMaxFileSize function.

How can you capture logs from the application only, and exclude logger entries from MobileFirst code?

If the application code is making good use of the MobileFirst logger API, and to capture logs from the application only, we can use a consistent package name or consistent set of package names for the logger instances. For example:

  • // JavaScript
    var logger = WL.Logger.create({pkg: 'MyAppPkg'});

  • // Android Logger logger = Logger.getInstance(MyClass.class.getName());
    or
    // Android Logger logger = Logger.getLogger(MyClass.class.getName());

  • // iOS OCLoggerDebugWithPackage(@"MyPackage", @"this is a debug message");
    // or Info, Log, Warn, and so on
    or
    // iOS OCLogger* logger = [OCLogger getInstanceWithPackage:@"MyPkg"];
    [logger debug:@"this is a debug message"];
    // or Info, Log, Warn, and so on

Then, set the filters on the logger to allow logging only for the package or packages:

  • // JavaScript
    WL.Logger.config({pkg : 'MyAppPkg', filters : {'MyAppPkg' : 'debug'}});

  • // Android HashMap filters = new HashMap();
     filters.put("MyAppPkg", Logger.LEVEL.DEBUG);
     Logger.setFilters(filters);

  • // iOS [OCLogger setFilters:@{@"MyAppPkg": @(OCLogger_DEBUG)}];

How can you never collect or send logs from deployed apps in the field?

Call setCapture(false) as early as possible in the application lifecycle code to set the default behavior. Avoid the logger tab in the Catalog tab of the operations console.


Parent topic: Develop MobileFirst applications