Using logger with Electron and AngularJS

Angular provides $log for logging, but if you'd like to use different logger (and use it throughout your Electron app), you will have to handle it bit more differently.

Motivation

I'd like to have single logger to output logs to console and external file. It has to work in both AngularJS files and Electron files.

For my project, I've chosen to go with Winston which seems pretty powerful and stable, but you can use whatever you want.

So, let's install it:

npm install winston --save  

Problem

Great thing about Winston is that it provides default logger which you can use and configure. Once you modify it, you can use it throughout your modules. This means that when you require('winston'), you will get your version of logger (not new instance).

Problem is that it will not work when calling it from your BrowserWindow. It will actually give you new instance. We could extract this logic to i.e. logger.js file which will return modified version of logger, but that is just dirty hacking (plus I don't like doing require('../........./../something')).

Solution

In my main.js which is starting point of my Electron app, we can get default logger and modify it. You can also create your own if you want.

const logger = require('winston');  
logger.add(logger.transports.File, { filename: "./logs/app.log" });  
global.logger = logger;  

In this case, I don't have problem polluting global scope, since alternative is even worse.

So before bootstrapping our Angular app, we'll have to grab this instance an register it for Angular. In my index.js which is starting point of my Angular app we can:

const remote = require('remote');  
const logger = remote.getGlobal('logger');  
angular  
    .module('app')
    .value('logger', logger);
angular  
    .bootstrap(document, ["app"], {
        strictDi: true
    });

This will make logger available for use in our app. One caveat to be aware is that value provider in Angular will not be available in config phase. But for anything else, I can just use:

angular  
    .module('app')
    .controller('ctrl', ['logger', ctrl]);

function ctrl(logger) { ... }  

That's how I handled it. I would be really interested to hear how others are handling this problem.

About Vjekoslav Ratkajec

Software developer from Zagreb, Croatia. Love programming, running, hiking and biking. Adore nature and animals. Also author of this blog.

Comments