WinJS.log is an interesting function. Though it's ostensibly part of the WinJS namespace, it's not actually directly implemented within WinJS itself! At the same time, it's used all over the place within the library. Take a look throughout the base.js and ui.js files of WinJS and you'll see many lines like this:

WinJS.log && WinJS.log(safeSerialize(e), "winjs", "error");

That is, WinJS checks if WinJS.log exists, and if so, outputs some log informaion for many different kinds of conditions, primarily error conditions. In other words, this logging will tell you various things that are happening inside WinJS.

To see all that output, though, you need to provide an implementation of WinJS.log yourself; that is, you need to assign some function to this particular variable. That function, as described in the documentation, should accept three parameters:

  1. The message to log
  2. A string with a tag or tags to categorize the message. WinJS always uses "winjs" and sometimes adds an additional tag like "binding" in which case the second parameter is "winjs binding"
  3. A string describing the type of the message. WinJS will use "error", "info", "warn", and "perf"

The simplest way to do this is just map WinJS.log to console.log like so:

WinJS.log = console.log.bind(console);

But this doesn't make for very nice output. For example, this call:

WinJS.log("message", "tag", "type");

Will create the output "messagetagtype" all smooshed together.

To make things a little better, WinJS itself offers a basic implementation of a logger, which is set up by calling WinJS.Utilities.startLog:

WinJS.Utilities.startLog();

Calling this with no parameters, as shown here, sets WinJS.log to a basic function that formats the output a little more nicely using WinJS.Utilities.formatLog (which you can call directly), and outputs the result to the console. So the same test call above will then appear on the console as "type: tag: message".

If you want to filter for specific tags, which is especially useful if you're using WinJS.log in your own code and use tags to identify the module you're calling from, then you can reduce the output. The syntax is to just pass a string with tags separated by spaces. So this code:

WinJS.Utilities.startLog("tag1 tag2");
WinJS.log("message", "tag1", "type");
WinJS.log("message", "tag2", "type");
WinJS.log("message", "tag3", "type");
WinJS.log("message", "tag4", "type");

Will output two lines, "type: tag1: message" and "type: tag2: message" but ignore the other two.

You can actually do much more with that one parameter by passing an object that specified additional options, such as filtering the type and so forth. See the WinJS.Utilities.startLog documentation for details.

Note also that if you call WinJS.Utilities.startLog multiple times, it aggregates the tags you're using. This means you can call it from different modules where each module starts logging for itself.

When you're done logging, you can call WinJS.Utilities.stopLog, which just calls delete WinJS.log. This is an all-or-nothing call, though–you can't remove individual tags from the logging.

All that said, you can certainly do more interesting things with WinJS.log if you want. You could, for example, have the function call msWriteProfilerMark and use it more for perf checking than error logging (in which case you can filter on a type of "perf" or something like that).

With console.log, it's helpful to know that you can, if desired, save that output in the system Event Log, visible in Event Viewer. The steps to do that are as follows:

  1. Launch Event viewer (eventvwr.exe)
  2. Under Application And Services\Microsoft\Windows\AppHost node, use the context menu to View->Show Analytic and Debug Logs
  3. Once the App Tracing channel shows up under the AppHost node, use the context menu to “Enable Log”
  4. Restart your app
  5. The console messages should now be in event viewer

You'll see a bunch of other events from wwahost.exe showing up here too, but you can filter on your process ID to whittle down the list. It's best to be running only your app when checking the Event Viewer!

Finally, if you use WinJS.log, you'll want to make sure it isn't being employed in release versions of your app. For this reason, when callign WinJS.log, use the same syntax as WinJS: WinJS.log && WinJS.log(…). This way you won't be spending extra cycles in your release version writing to a console that the user will never see.

Then be sure to remove the one line that assigns a function to WinJS.log (or calls WinJS.Utilities.startLog) before you build your package to upload to the Store. This is much easier than trying to scrub your app for direct console.log calls.

Thanks to Josh Williams and Andy Sterland who provided many of the details here.


4 Comments

  1. Corrado Cavalli
    Posted January 30, 2013 at 6:52 am | Permalink

    Hi Kraig, do you have a sample for msWriteProfilerMark? tried it but can’t see any entry on Event Viewer apart “Navigation occurred”.

  2. Posted January 30, 2013 at 5:55 pm | Permalink

    msWriteProfilerMark generated what called an ETW event (Event Traching for Windows), which doesn’t go into the Event Viewer as does console.log. Tools like xperf will pick those up, however, which is why it’s typically more for profiling than logging.

    • Corrado Cavalli
      Posted January 31, 2013 at 6:41 am | Permalink

      Thanks for clarification.

  3. Posted March 12, 2013 at 12:03 pm | Permalink

    we are using log4javascript where you also can toggle the log level via settings pane, and it works quite well. Might redirect WinJS.log to log4javascript now too. Thanks Kraig!