[TIC-Web] add log framework 57/108057/4
authorChangHyun Lee <leechwin.lee@samsung.com>
Mon, 2 Jan 2017 13:48:51 +0000 (22:48 +0900)
committerChangHyun Lee <leechwin.lee@samsung.com>
Tue, 3 Jan 2017 06:11:29 +0000 (15:11 +0900)
- apply logger framework

Change-Id: I47c06d51dcf9440ec82617c7fa0abb6d501ba91d
Signed-off-by: ChangHyun Lee <leechwin.lee@samsung.com>
13 files changed:
app.js
gulpfile.js
package.json
public/src/index.html
public/src/js/config.js
public/src/js/logger.js [new file with mode: 0644]
public/src/js/main.js
public/src/js/page/image.js
public/src/js/page/package.js
public/src/js/page/settings.js
public/src/lib/jsnlog/jsnlog.js [new file with mode: 0644]
server/fs/filesystem.js
server/fs/mic.js

diff --git a/app.js b/app.js
index 4e24bea..cb07b4e 100644 (file)
--- a/app.js
+++ b/app.js
@@ -6,6 +6,10 @@ var socketio = require('socket.io');
 var fs = require('fs');
 var express = require('express');
 var bodyParser = require('body-parser');
+var JL = require('jsnlog').JL;
+var jsnlog_nodejs = require('jsnlog-nodejs').jsnlog_nodejs;
+
+var logger = JL('app.js');
 var app = express();
 var server = http.createServer(app);
 var io = socketio.listen(server);
@@ -17,6 +21,7 @@ var Mic = require('./server/fs/mic');
 var Router = require('./server/routes/router');
 var SocketEvent = require('./server/fs/socketEvent');
 
+
 /* app config */
 app.set('port', process.env.PORT || Config.TIC_WEB.PORT);
 app.use(bodyParser.json());
@@ -26,12 +31,24 @@ app.use('/api', Router);
 
 server.listen(app.get('port'), process.env.IP || "0.0.0.0", function () {
     var addr = server.address();
-    console.log('Server listening at', addr.address + ':' + addr.port);
+    logger.info('Server listening at' + addr.address + ':' + addr.port);
 
     FileSystem.init();
 });
 
 
+/**
+ * jsnlog.js on the client by default sends log messages to /jsnlog.logger, using POST.
+ * @URI /*.logger
+ * @TYPE POST
+ */
+app.post('*.logger', function (req, res) {
+    // TODO: save log to file or db
+    jsnlog_nodejs(JL, req.body);
+
+    // Send empty response. This is ok, because client side jsnlog does not use response from server.
+    res.send('');
+});
 
 /**
  * Get package data from tic-core via RESTful API
@@ -109,7 +126,7 @@ app.post('/exports', function(req, res) {
  * Connection with MIC
  */
 io.on('connection', function (socket) {
-    console.log('socket connection');
+    logger.info('socket connection');
 
     /**
      * SocketEvent.FS_IMAGE_LIST_FROM = 'ws/fs/image/list/from'
@@ -153,7 +170,7 @@ io.on('connection', function (socket) {
      * SocketEvent.MIC_AVAILABLE_FROM = 'ws/mic/available/from'
      */
     socket.on(SocketEvent.MIC_AVAILABLE_FROM, function () {
-        console.log('mic available: ' + Mic.isAvailable());
+        logger.info('mic available: ' + Mic.isAvailable());
         io.sockets.emit(SocketEvent.MIC_AVAILABLE_TO, Mic.isAvailable());
     });
 
@@ -165,12 +182,12 @@ io.on('connection', function (socket) {
     });
 
     socket.on('disconnect', function () {
-        console.log('socket disconnect');
+        logger.info('socket disconnect');
         // TODO
     });
 
     socket.on('message', function (msg) {
-        console.log('socket message');
+        logger.info('socket message');
         // TODO
     });
 
index 108ed1a..603fa37 100644 (file)
@@ -10,6 +10,7 @@ gulp.task('clean', function() {
 // copy
 gulp.task('copy', ['clean'], function() {
     var requirejs = gulp.src('node_modules/requirejs/require.js').pipe(gulp.dest('public/src/lib/requirejs'));
+    var jsnlog = gulp.src('node_modules/jsnlog/jsnlog.js').pipe(gulp.dest('public/src/lib/jsnlog'));
     var lodash = gulp.src('bower_components/lodash/dist/**/*').pipe(gulp.dest('public/src/lib/lodash'));
     var jquery = gulp.src('bower_components/jquery/dist/**/*').pipe(gulp.dest('public/src/lib/jquery'));
     var jquerySortable = gulp.src('bower_components/jquery-sortable/source/js/jquery-sortable.js').pipe(gulp.dest('public/src/lib/jquery-sortable'));
@@ -17,7 +18,7 @@ gulp.task('copy', ['clean'], function() {
     var bootstrapTreeview = gulp.src('bower_components/bootstrap-treeview/dist/**/*').pipe(gulp.dest('public/src/lib/bootstrap-treeview'));
     var componentsFontAwesomeCss = gulp.src('bower_components/components-font-awesome/css/**/*').pipe(gulp.dest('public/src/lib/components-font-awesome/css'));
     var componentsFontAwesomeFont = gulp.src('bower_components/components-font-awesome/fonts/**/*').pipe(gulp.dest('public/src/lib/components-font-awesome/fonts'));
-    return merge(requirejs, lodash, jquery, jquerySortable, bootstrap, bootstrapTreeview, componentsFontAwesomeCss, componentsFontAwesomeFont);
+    return merge(requirejs, jsnlog, lodash, jquery, jquerySortable, bootstrap, bootstrapTreeview, componentsFontAwesomeCss, componentsFontAwesomeFont);
 });
 
 // deploy to dist
index 000a43d..2ec2b5c 100644 (file)
@@ -33,7 +33,9 @@
     "body-parser": "~1.15.2",
     "socket.io": "~1.6.0",
     "mime": "~1.3.4",
-    "mkdirp": "~0.5.1"
+    "mkdirp": "~0.5.1",
+    "jsnlog": "~2.22.0",
+    "jsnlog-nodejs": "~2.22.0"
   },
   "devDependencies": {
     "bower": "~1.8.0",
index 5185dfe..a36336f 100644 (file)
 
         <!-- library loading -->
         <script src="/socket.io/socket.io.js"></script>
-        <script src="/lib/jquery/jquery.js"></script>
-        <script src="/lib/jquery-sortable/jquery-sortable.js"></script>
-        <script src="/lib/bootstrap/js/bootstrap.js"></script>
-        <script src="/lib/bootstrap-treeview/bootstrap-treeview.min.js"></script>
-        <script src="/lib/lodash/lodash.js"></script>
         <script src="/js/config.js"></script>
         <script src="/lib/requirejs/require.js" data-main="js/main"></script>
     </body>
index b5e0481..748b22c 100644 (file)
@@ -5,7 +5,8 @@ require = {
             'jquery-sortable': 'lib/jquery-sortable/jquery-sortable',
             'lodash': 'lib/lodash/lodash',
             'bootstrap': 'lib/bootstrap/js/bootstrap',
-            'bootstrap-treeview': 'lib/bootstrap-treeview/bootstrap-treeview.min'
+            'bootstrap-treeview': 'lib/bootstrap-treeview/bootstrap-treeview.min',
+            'jsnlog': 'lib/jsnlog/jsnlog'
     },
     shim: {
         'bootstrap': {
diff --git a/public/src/js/logger.js b/public/src/js/logger.js
new file mode 100644 (file)
index 0000000..1974fba
--- /dev/null
@@ -0,0 +1,13 @@
+define([
+    'jsnlog'
+], function (
+    JL
+) {
+    'use strict';
+
+    var ajaxAppender = JL.createAjaxAppender('ajaxAppender');
+    var consoleAppender = JL.createConsoleAppender('consoleAppender');
+    JL().setOptions({'appenders': [ajaxAppender, consoleAppender]});
+
+    return JL;
+});
index 8e29528..665bfcf 100644 (file)
@@ -5,7 +5,8 @@ define([
     'js/util',
     'js/page/package',
     'js/page/settings',
-    'js/page/image'
+    'js/page/image',
+    'js/logger'
 ], function (
     $,
     bootstrap,
@@ -13,12 +14,15 @@ define([
     Util,
     Package,
     Settings,
-    Image
+    Image,
+    Logger
 ) {
     'use strict';
 
+    var logger = Logger('main.js');
+
     function init() {
-        console.log("main: init")
+        logger.info("init");
 
         Util.showLoadingDialog(true);
 
@@ -28,7 +32,7 @@ define([
             Util.showLoadingDialog(false);
         })
         .catch(function (reason) {
-            console.log(reason);
+            logger.error(reason);
             Util.showLoadingDialog(false);
             Util.showAlertDialog('Failed to load package list.<br>Please check the tic-core.');
         });
index c26cc76..e78ca44 100644 (file)
@@ -1,14 +1,18 @@
 define([
     'jquery',
     'lodash',
-    'js/util'
+    'js/util',
+    'js/logger'
 ], function (
     $,
     _,
-    Util
+    Util,
+    Logger
 ) {
     'use strict';
 
+    var logger = Logger('image.js');
+
     var AppConfig = null;
 
     // connected socket object
@@ -167,13 +171,14 @@ define([
             getKickstartRecipeFile()
             .then(createImage)
             .catch(function (err) {
-                console.error(err);
+                logger.error(err);
                 Util.showAlertDialog('Failed to create a image.<br>Please check the ks file.');
                 $('#tic-image-create').prop('disabled', false);
                 $('#tic-image-cancel').toggleClass('hidden', true);
             });
         })
         .catch(function () {
+            logger.info('Image creation was canceled.');
             $('#tic-image-create').prop('disabled', false);
             $('#tic-image-cancel').toggleClass('hidden', true);
         });
@@ -194,7 +199,7 @@ define([
     }
 
     function init() {
-        console.log('image: init');
+        logger.info('init');
 
         _initWidgets();
         _initSocket(Util.getWebSocket());
index dd7491f..3662370 100644 (file)
@@ -2,15 +2,19 @@ define([
     'jquery',
     'lodash',
     'js/util',
-    'js/page/settings'
+    'js/page/settings',
+    'js/logger'
 ], function (
     $,
     _,
     Util,
-    Settings
+    Settings,
+    Logger
 ) {
     'use strict';
 
+    var logger = Logger('package.js');
+
     var $tree = $('#tic-package-left-col-tree');
     var packages = [];
     var repos = [];
@@ -127,7 +131,7 @@ define([
             return;
         }
 
-        console.info('checked: ' + node.text);
+        logger.info('checked: ' + node.text);
 
         _nodeSelected(event, node);
 
@@ -166,7 +170,7 @@ define([
             return;
         }
 
-        console.info('unchecked: ' + node.text);
+        logger.info('unchecked: ' + node.text);
         Util.showLoadingDialog(true);
 
         // TODO: Refactoring
@@ -200,7 +204,7 @@ define([
                 if (!_.isEqual(localNode.text, depNode.text)) {
                     if (depNode.state.checked === true) {
                         if (depNode.selfChecked === true) {
-                            console.warn('\'' + depNode.text + '\'' + ' package was still checked because user checked item.');
+                            logger.warn('\'' + depNode.text + '\'' + ' package was still checked because user checked item.');
                         } else {
                             toggleNode.push(depNode);
                         }
@@ -289,7 +293,7 @@ define([
     }
 
     function init() {
-        console.log('package: init');
+        logger.info('init');
 
         function _filter() {
             var filterText = $('#tic-package-toolbar-input').val();
index cafff55..2cc982a 100644 (file)
@@ -2,15 +2,19 @@ define([
     'jquery',
     'jquery-sortable',
     'lodash',
-    'js/util'
+    'js/util',
+    'js/logger'
 ], function (
     $,
     js,
     _,
-    Util
+    Util,
+    Logger
 ) {
     'use strict';
 
+    var logger = Logger('settings.js');
+
     var ANALYSIS_URL = '<%= url %>/analysis';
     var ROPO_LI = '<li class="list-group-item clearfix"><span class="tic-repository-url"><%= url %></span><button type="button" class="btn pull-right btn-default"><i class="fa fa-trash-o"></i></button></li>';
 
@@ -63,7 +67,7 @@ define([
     }
 
     function init() {
-        console.log('settings: init');
+        logger.info('init');
 
         /**
          * Recipe Import/Export
@@ -166,7 +170,7 @@ define([
                 Util.showLoadingDialog(false);
             })
             .catch(function (reason) {
-                console.log(reason);
+                logger.error(reason);
                 Util.showLoadingDialog(false);
                 Util.showAlertDialog('Failed to load package list.<br>Please check the tic-core.');
             });
diff --git a/public/src/lib/jsnlog/jsnlog.js b/public/src/lib/jsnlog/jsnlog.js
new file mode 100644 (file)
index 0000000..b3455ce
--- /dev/null
@@ -0,0 +1,834 @@
+/* \r
+ * JSNLog 2.22.0\r
+ * Open source under the MIT License.\r
+ * Copyright 2016 Mattijs Perdeck All rights reserved.\r
+ */\r
+/// <reference path="Definitions/jsnlog_interfaces.d.ts"/>\r
+var __extends = (this && this.__extends) || function (d, b) {\r
+    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];\r
+    function __() { this.constructor = d; }\r
+    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r
+};\r
+function JL(loggerName) {\r
+    // If name is empty, return the root logger\r
+    if (!loggerName) {\r
+        return JL.__;\r
+    }\r
+    // Implements Array.reduce. JSNLog supports IE8+ and reduce is not supported in that browser.\r
+    // Same interface as the standard reduce, except that \r
+    if (!Array.prototype.reduce) {\r
+        Array.prototype.reduce = function (callback, initialValue) {\r
+            var previousValue = initialValue;\r
+            for (var i = 0; i < this.length; i++) {\r
+                previousValue = callback(previousValue, this[i], i, this);\r
+            }\r
+            return previousValue;\r
+        };\r
+    }\r
+    var accumulatedLoggerName = '';\r
+    var logger = ('.' + loggerName).split('.').reduce(function (prev, curr, idx, arr) {\r
+        // if loggername is a.b.c, than currentLogger will be set to the loggers\r
+        // root   (prev: JL, curr: '')\r
+        // a      (prev: JL.__, curr: 'a')\r
+        // a.b    (prev: JL.__.__a, curr: 'b')\r
+        // a.b.c  (prev: JL.__.__a.__a.b, curr: 'c')\r
+        // Note that when a new logger name is encountered (such as 'a.b.c'),\r
+        // a new logger object is created and added as a property to the parent ('a.b').\r
+        // The root logger is added as a property of the JL object itself.\r
+        // It is essential that the name of the property containing the child logger\r
+        // contains the full 'path' name of the child logger ('a.b.c') instead of\r
+        // just the bit after the last period ('c').\r
+        // This is because the parent inherits properties from its ancestors.\r
+        // So if the root has a child logger 'c' (stored in a property 'c' of the root logger),\r
+        // then logger 'a.b' has that same property 'c' through inheritance.\r
+        // The names of the logger properties start with __, so the root logger \r
+        // (which has name ''), has a nice property name '__'.              \r
+        // accumulatedLoggerName evaluates false ('' is falsy) in first iteration when prev is the root logger.\r
+        // accumulatedLoggerName will be the logger name corresponding with the logger in currentLogger.\r
+        // Keep in mind that the currentLogger may not be defined yet, so can't get the name from\r
+        // the currentLogger object itself. \r
+        if (accumulatedLoggerName) {\r
+            accumulatedLoggerName += '.' + curr;\r
+        }\r
+        else {\r
+            accumulatedLoggerName = curr;\r
+        }\r
+        var currentLogger = prev['__' + accumulatedLoggerName];\r
+        // If the currentLogger (or the actual logger being sought) does not yet exist, \r
+        // create it now.\r
+        if (currentLogger === undefined) {\r
+            // Set the prototype of the Logger constructor function to the parent of the logger\r
+            // to be created. This way, __proto of the new logger object will point at the parent.\r
+            // When logger.level is evaluated and is not present, the JavaScript runtime will \r
+            // walk down the prototype chain to find the first ancestor with a level property.\r
+            //\r
+            // Note that prev at this point refers to the parent logger.\r
+            JL.Logger.prototype = prev;\r
+            currentLogger = new JL.Logger(accumulatedLoggerName);\r
+            prev['__' + accumulatedLoggerName] = currentLogger;\r
+        }\r
+        return currentLogger;\r
+    }, JL.__);\r
+    return logger;\r
+}\r
+var JL;\r
+(function (JL) {\r
+    // Initialise requestId to empty string. If you don't do this and the user\r
+    // does not set it via setOptions, then the JSNLog-RequestId header will\r
+    // have value "undefined", which doesn't look good in a log.\r
+    //\r
+    // Note that you always want to send a requestId as part of log requests,\r
+    // otherwise the server side component doesn't know this is a log request\r
+    // and may create a new request id for the log request, causing confusion\r
+    // in the log.\r
+    JL.requestId = '';\r
+    /**\r
+    Copies the value of a property from one object to the other.\r
+    This is used to copy property values as part of setOption for loggers and appenders.\r
+\r
+    Because loggers inherit property values from their parents, it is important never to\r
+    create a property on a logger if the intent is to inherit from the parent.\r
+\r
+    Copying rules:\r
+    1) if the from property is undefined (for example, not mentioned in a JSON object), the\r
+       to property is not affected at all.\r
+    2) if the from property is null, the to property is deleted (so the logger will inherit from\r
+       its parent).\r
+    3) Otherwise, the from property is copied to the to property.\r
+    */\r
+    function copyProperty(propertyName, from, to) {\r
+        if (from[propertyName] === undefined) {\r
+            return;\r
+        }\r
+        if (from[propertyName] === null) {\r
+            delete to[propertyName];\r
+            return;\r
+        }\r
+        to[propertyName] = from[propertyName];\r
+    }\r
+    /**\r
+    Returns true if a log should go ahead.\r
+    Does not check level.\r
+\r
+    @param filters\r
+        Filters that determine whether a log can go ahead.\r
+    */\r
+    function allow(filters) {\r
+        // If enabled is not null or undefined, then if it is false, then return false\r
+        // Note that undefined==null (!)\r
+        if (!(JL.enabled == null)) {\r
+            if (!JL.enabled) {\r
+                return false;\r
+            }\r
+        }\r
+        // If maxMessages is not null or undefined, then if it is 0, then return false.\r
+        // Note that maxMessages contains number of messages that are still allowed to send.\r
+        // It is decremented each time messages are sent. It can be negative when batch size > 1.\r
+        // Note that undefined==null (!)\r
+        if (!(JL.maxMessages == null)) {\r
+            if (JL.maxMessages < 1) {\r
+                return false;\r
+            }\r
+        }\r
+        // If the regex contains a bug, that will throw an exception.\r
+        // Ignore this, and pass the log item (better too much than too little).\r
+        try {\r
+            if (filters.userAgentRegex) {\r
+                if (!new RegExp(filters.userAgentRegex).test(navigator.userAgent)) {\r
+                    return false;\r
+                }\r
+            }\r
+        }\r
+        catch (e) { }\r
+        try {\r
+            if (filters.ipRegex && JL.clientIP) {\r
+                if (!new RegExp(filters.ipRegex).test(JL.clientIP)) {\r
+                    return false;\r
+                }\r
+            }\r
+        }\r
+        catch (e) { }\r
+        return true;\r
+    }\r
+    /**\r
+    Returns true if a log should go ahead, based on the message.\r
+\r
+    @param filters\r
+        Filters that determine whether a log can go ahead.\r
+\r
+    @param message\r
+        Message to be logged.\r
+    */\r
+    function allowMessage(filters, message) {\r
+        // If the regex contains a bug, that will throw an exception.\r
+        // Ignore this, and pass the log item (better too much than too little).\r
+        try {\r
+            if (filters.disallow) {\r
+                if (new RegExp(filters.disallow).test(message)) {\r
+                    return false;\r
+                }\r
+            }\r
+        }\r
+        catch (e) { }\r
+        return true;\r
+    }\r
+    // If logObject is a function, the function is evaluated (without parameters)\r
+    // and the result returned.\r
+    // Otherwise, logObject itself is returned.\r
+    function stringifyLogObjectFunction(logObject) {\r
+        if (typeof logObject == "function") {\r
+            if (logObject instanceof RegExp) {\r
+                return logObject.toString();\r
+            }\r
+            else {\r
+                return logObject();\r
+            }\r
+        }\r
+        return logObject;\r
+    }\r
+    var StringifiedLogObject = (function () {\r
+        // * msg - \r
+        //      if the logObject is a scalar (after possible function evaluation), this is set to\r
+        //      string representing the scalar. Otherwise it is left undefined.\r
+        // * meta -\r
+        //      if the logObject is an object (after possible function evaluation), this is set to\r
+        //      that object. Otherwise it is left undefined.\r
+        // * finalString -\r
+        //      This is set to the string representation of logObject (after possible function evaluation),\r
+        //      regardless of whether it is an scalar or an object. An object is stringified to a JSON string.\r
+        //      Note that you can't call this field "final", because as some point this was a reserved\r
+        //      JavaScript keyword and using final trips up some minifiers.\r
+        function StringifiedLogObject(msg, meta, finalString) {\r
+            this.msg = msg;\r
+            this.meta = meta;\r
+            this.finalString = finalString;\r
+        }\r
+        return StringifiedLogObject;\r
+    }());\r
+    // Takes a logObject, which can be \r
+    // * a scalar\r
+    // * an object\r
+    // * a parameterless function, which returns the scalar or object to log.\r
+    // Returns a stringifiedLogObject\r
+    function stringifyLogObject(logObject) {\r
+        // Note that this works if logObject is null.\r
+        // typeof null is object.\r
+        // JSON.stringify(null) returns "null".\r
+        var actualLogObject = stringifyLogObjectFunction(logObject);\r
+        var finalString;\r
+        // Note that typeof actualLogObject should not be "function", because that has \r
+        // been resolved with stringifyLogObjectFunction.\r
+        switch (typeof actualLogObject) {\r
+            case "string":\r
+                return new StringifiedLogObject(actualLogObject, null, actualLogObject);\r
+            case "number":\r
+                finalString = actualLogObject.toString();\r
+                return new StringifiedLogObject(finalString, null, finalString);\r
+            case "boolean":\r
+                finalString = actualLogObject.toString();\r
+                return new StringifiedLogObject(finalString, null, finalString);\r
+            case "undefined":\r
+                return new StringifiedLogObject("undefined", null, "undefined");\r
+            case "object":\r
+                if ((actualLogObject instanceof RegExp) ||\r
+                    (actualLogObject instanceof String) ||\r
+                    (actualLogObject instanceof Number) ||\r
+                    (actualLogObject instanceof Boolean)) {\r
+                    finalString = actualLogObject.toString();\r
+                    return new StringifiedLogObject(finalString, null, finalString);\r
+                }\r
+                else {\r
+                    if (typeof JL.serialize === 'function') {\r
+                        finalString = JL.serialize.call(this, actualLogObject);\r
+                    }\r
+                    else {\r
+                        finalString = JSON.stringify(actualLogObject);\r
+                    }\r
+                    return new StringifiedLogObject(null, actualLogObject, finalString);\r
+                }\r
+            default:\r
+                return new StringifiedLogObject("unknown", null, "unknown");\r
+        }\r
+    }\r
+    function setOptions(options) {\r
+        copyProperty("enabled", options, this);\r
+        copyProperty("maxMessages", options, this);\r
+        copyProperty("defaultAjaxUrl", options, this);\r
+        copyProperty("clientIP", options, this);\r
+        copyProperty("requestId", options, this);\r
+        copyProperty("defaultBeforeSend", options, this);\r
+        copyProperty("serialize", options, this);\r
+        return this;\r
+    }\r
+    JL.setOptions = setOptions;\r
+    function getAllLevel() { return -2147483648; }\r
+    JL.getAllLevel = getAllLevel;\r
+    function getTraceLevel() { return 1000; }\r
+    JL.getTraceLevel = getTraceLevel;\r
+    function getDebugLevel() { return 2000; }\r
+    JL.getDebugLevel = getDebugLevel;\r
+    function getInfoLevel() { return 3000; }\r
+    JL.getInfoLevel = getInfoLevel;\r
+    function getWarnLevel() { return 4000; }\r
+    JL.getWarnLevel = getWarnLevel;\r
+    function getErrorLevel() { return 5000; }\r
+    JL.getErrorLevel = getErrorLevel;\r
+    function getFatalLevel() { return 6000; }\r
+    JL.getFatalLevel = getFatalLevel;\r
+    function getOffLevel() { return 2147483647; }\r
+    JL.getOffLevel = getOffLevel;\r
+    function levelToString(level) {\r
+        if (level <= 1000) {\r
+            return "trace";\r
+        }\r
+        if (level <= 2000) {\r
+            return "debug";\r
+        }\r
+        if (level <= 3000) {\r
+            return "info";\r
+        }\r
+        if (level <= 4000) {\r
+            return "warn";\r
+        }\r
+        if (level <= 5000) {\r
+            return "error";\r
+        }\r
+        return "fatal";\r
+    }\r
+    // ---------------------\r
+    var Exception = (function () {\r
+        // data replaces message. It takes not just strings, but also objects and functions, just like the log function.\r
+        // internally, the string representation is stored in the message property (inherited from Error)\r
+        //\r
+        // inner: inner exception. Can be null or undefined. \r
+        function Exception(data, inner) {\r
+            this.inner = inner;\r
+            this.name = "JL.Exception";\r
+            this.message = stringifyLogObject(data).finalString;\r
+        }\r
+        return Exception;\r
+    }());\r
+    JL.Exception = Exception;\r
+    // Derive Exception from Error (a Host object), so browsers\r
+    // are more likely to produce a stack trace for it in their console.\r
+    //\r
+    // Note that instanceof against an object created with this constructor\r
+    // will return true in these cases:\r
+    // <object> instanceof JL.Exception);\r
+    // <object> instanceof Error);\r
+    Exception.prototype = new Error();\r
+    // ---------------------\r
+    var LogItem = (function () {\r
+        // l: level\r
+        // m: message\r
+        // n: logger name\r
+        // t (timeStamp) is number of milliseconds since 1 January 1970 00:00:00 UTC\r
+        //\r
+        // Keeping the property names really short, because they will be sent in the\r
+        // JSON payload to the server.\r
+        function LogItem(l, m, n, t) {\r
+            this.l = l;\r
+            this.m = m;\r
+            this.n = n;\r
+            this.t = t;\r
+        }\r
+        return LogItem;\r
+    }());\r
+    JL.LogItem = LogItem;\r
+    // ---------------------\r
+    var Appender = (function () {\r
+        // sendLogItems takes an array of log items. It will be called when\r
+        // the appender has items to process (such as, send to the server).\r
+        // Note that after sendLogItems returns, the appender may truncate\r
+        // the LogItem array, so the function has to copy the content of the array\r
+        // in some fashion (eg. serialize) before returning.\r
+        function Appender(appenderName, sendLogItems) {\r
+            this.appenderName = appenderName;\r
+            this.sendLogItems = sendLogItems;\r
+            this.level = JL.getTraceLevel();\r
+            // set to super high level, so if user increases level, level is unlikely to get \r
+            // above sendWithBufferLevel\r
+            this.sendWithBufferLevel = 2147483647;\r
+            this.storeInBufferLevel = -2147483648;\r
+            this.bufferSize = 0; // buffering switch off by default\r
+            this.batchSize = 1;\r
+            // Holds all log items with levels higher than storeInBufferLevel \r
+            // but lower than level. These items may never be sent.\r
+            this.buffer = [];\r
+            // Holds all items that we do want to send, until we have a full\r
+            // batch (as determined by batchSize).\r
+            this.batchBuffer = [];\r
+        }\r
+        Appender.prototype.setOptions = function (options) {\r
+            copyProperty("level", options, this);\r
+            copyProperty("ipRegex", options, this);\r
+            copyProperty("userAgentRegex", options, this);\r
+            copyProperty("disallow", options, this);\r
+            copyProperty("sendWithBufferLevel", options, this);\r
+            copyProperty("storeInBufferLevel", options, this);\r
+            copyProperty("bufferSize", options, this);\r
+            copyProperty("batchSize", options, this);\r
+            if (this.bufferSize < this.buffer.length) {\r
+                this.buffer.length = this.bufferSize;\r
+            }\r
+            return this;\r
+        };\r
+        /**\r
+        Called by a logger to log a log item.\r
+        If in response to this call one or more log items need to be processed\r
+        (eg., sent to the server), this method calls this.sendLogItems\r
+        with an array with all items to be processed.\r
+\r
+        Note that the name and parameters of this function must match those of the log function of\r
+        a Winston transport object, so that users can use these transports as appenders.\r
+        That is why there are many parameters that are not actually used by this function.\r
+\r
+        level - string with the level ("trace", "debug", etc.) Only used by Winston transports.\r
+        msg - human readable message. Undefined if the log item is an object. Only used by Winston transports.\r
+        meta - log object. Always defined, because at least it contains the logger name. Only used by Winston transports.\r
+        callback - function that is called when the log item has been logged. Only used by Winston transports.\r
+        levelNbr - level as a number. Not used by Winston transports.\r
+        message - log item. If the user logged an object, this is the JSON string.  Not used by Winston transports.\r
+        loggerName: name of the logger.  Not used by Winston transports.\r
+        */\r
+        Appender.prototype.log = function (level, msg, meta, callback, levelNbr, message, loggerName) {\r
+            var logItem;\r
+            if (!allow(this)) {\r
+                return;\r
+            }\r
+            if (!allowMessage(this, message)) {\r
+                return;\r
+            }\r
+            if (levelNbr < this.storeInBufferLevel) {\r
+                // Ignore the log item completely\r
+                return;\r
+            }\r
+            logItem = new LogItem(levelNbr, message, loggerName, (new Date).getTime());\r
+            if (levelNbr < this.level) {\r
+                // Store in the hold buffer. Do not send.\r
+                if (this.bufferSize > 0) {\r
+                    this.buffer.push(logItem);\r
+                    // If we exceeded max buffer size, remove oldest item\r
+                    if (this.buffer.length > this.bufferSize) {\r
+                        this.buffer.shift();\r
+                    }\r
+                }\r
+                return;\r
+            }\r
+            if (levelNbr < this.sendWithBufferLevel) {\r
+                // Want to send the item, but not the contents of the buffer\r
+                this.batchBuffer.push(logItem);\r
+            }\r
+            else {\r
+                // Want to send both the item and the contents of the buffer.\r
+                // Send contents of buffer first, because logically they happened first.\r
+                if (this.buffer.length) {\r
+                    this.batchBuffer = this.batchBuffer.concat(this.buffer);\r
+                    this.buffer.length = 0;\r
+                }\r
+                this.batchBuffer.push(logItem);\r
+            }\r
+            if (this.batchBuffer.length >= this.batchSize) {\r
+                this.sendBatch();\r
+                return;\r
+            }\r
+        };\r
+        // Processes the batch buffer\r
+        Appender.prototype.sendBatch = function () {\r
+            if (this.batchBuffer.length == 0) {\r
+                return;\r
+            }\r
+            if (!(JL.maxMessages == null)) {\r
+                if (JL.maxMessages < 1) {\r
+                    return;\r
+                }\r
+            }\r
+            // If maxMessages is not null or undefined, then decrease it by the batch size.\r
+            // This can result in a negative maxMessages.\r
+            // Note that undefined==null (!)\r
+            if (!(JL.maxMessages == null)) {\r
+                JL.maxMessages -= this.batchBuffer.length;\r
+            }\r
+            this.sendLogItems(this.batchBuffer);\r
+            this.batchBuffer.length = 0;\r
+        };\r
+        return Appender;\r
+    }());\r
+    JL.Appender = Appender;\r
+    // ---------------------\r
+    var AjaxAppender = (function (_super) {\r
+        __extends(AjaxAppender, _super);\r
+        function AjaxAppender(appenderName) {\r
+            _super.call(this, appenderName, AjaxAppender.prototype.sendLogItemsAjax);\r
+        }\r
+        AjaxAppender.prototype.setOptions = function (options) {\r
+            copyProperty("url", options, this);\r
+            copyProperty("beforeSend", options, this);\r
+            _super.prototype.setOptions.call(this, options);\r
+            return this;\r
+        };\r
+        AjaxAppender.prototype.sendLogItemsAjax = function (logItems) {\r
+            // JSON.stringify is only supported on IE8+\r
+            // Use try-catch in case we get an exception here.\r
+            //\r
+            // The "r" field is now obsolete. When writing a server side component, \r
+            // read the HTTP header "JSNLog-RequestId"\r
+            // to get the request id.\r
+            //\r
+            // The .Net server side component\r
+            // now uses the JSNLog-RequestId HTTP Header, because this allows it to\r
+            // detect whether the incoming request has a request id.\r
+            // If the request id were in the json payload, it would have to read the json\r
+            // from the stream, interfering with normal non-logging requests.\r
+            //\r
+            // To see what characters you can use in the HTTP header, visit:\r
+            // http://stackoverflow.com/questions/3561381/custom-http-headers-naming-conventions/3561399#3561399\r
+            //\r
+            // It needs this ability, so users of NLog can set a requestId variable in NLog\r
+            // before the server side component tries to log the client side log message\r
+            // through an NLog logger.\r
+            // Unlike Log4Net, NLog doesn't allow you to register an object whose ToString()\r
+            // is only called when it tries to log something, so the requestId has to be \r
+            // determined right at the start of request processing.\r
+            try {\r
+                // Only determine the url right before you send a log request.\r
+                // Do not set the url when constructing the appender.\r
+                //\r
+                // This is because the server side component sets defaultAjaxUrl\r
+                // in a call to setOptions, AFTER the JL object and the default appender\r
+                // have been created. \r
+                var ajaxUrl = "/jsnlog.logger";\r
+                // This evaluates to true if defaultAjaxUrl is null or undefined\r
+                if (!(JL.defaultAjaxUrl == null)) {\r
+                    ajaxUrl = JL.defaultAjaxUrl;\r
+                }\r
+                if (this.url) {\r
+                    ajaxUrl = this.url;\r
+                }\r
+                // Send the json to the server. \r
+                // Note that there is no event handling here. If the send is not\r
+                // successful, nothing can be done about it.\r
+                var xhr = this.getXhr(ajaxUrl);\r
+                var json = {\r
+                    r: JL.requestId,\r
+                    lg: logItems\r
+                };\r
+                // call beforeSend callback\r
+                // first try the callback on the appender\r
+                // then the global defaultBeforeSend callback\r
+                if (typeof this.beforeSend === 'function') {\r
+                    this.beforeSend.call(this, xhr, json);\r
+                }\r
+                else if (typeof JL.defaultBeforeSend === 'function') {\r
+                    JL.defaultBeforeSend.call(this, xhr, json);\r
+                }\r
+                var finalmsg = JSON.stringify(json);\r
+                xhr.send(finalmsg);\r
+            }\r
+            catch (e) { }\r
+        };\r
+        // Creates the Xhr object to use to send the log request.\r
+        // Sets out to create an Xhr object that can be used for CORS.\r
+        // However, if there seems to be no CORS support on the browser,\r
+        // returns a non-CORS capable Xhr.\r
+        AjaxAppender.prototype.getXhr = function (ajaxUrl) {\r
+            var xhr = new XMLHttpRequest();\r
+            // Check whether this xhr is CORS capable by checking whether it has\r
+            // withCredentials. \r
+            // "withCredentials" only exists on XMLHTTPRequest2 objects.\r
+            if (!("withCredentials" in xhr)) {\r
+                // Just found that no XMLHttpRequest2 available.\r
+                // Check if XDomainRequest is available.\r
+                // This only exists in IE, and is IE's way of making CORS requests.\r
+                if (typeof XDomainRequest != "undefined") {\r
+                    // Note that here we're not setting request headers on the XDomainRequest\r
+                    // object. This is because this object doesn't let you do that:\r
+                    // http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx\r
+                    // This means that for IE8 and IE9, CORS logging requests do not carry request ids.\r
+                    var xdr = new XDomainRequest();\r
+                    xdr.open('POST', ajaxUrl);\r
+                    return xdr;\r
+                }\r
+            }\r
+            // At this point, we're going with XMLHttpRequest, whether it is CORS capable or not.\r
+            // If it is not CORS capable, at least will handle the non-CORS requests.\r
+            xhr.open('POST', ajaxUrl);\r
+            xhr.setRequestHeader('Content-Type', 'application/json');\r
+            xhr.setRequestHeader('JSNLog-RequestId', JL.requestId);\r
+            return xhr;\r
+        };\r
+        return AjaxAppender;\r
+    }(Appender));\r
+    JL.AjaxAppender = AjaxAppender;\r
+    // ---------------------\r
+    var ConsoleAppender = (function (_super) {\r
+        __extends(ConsoleAppender, _super);\r
+        function ConsoleAppender(appenderName) {\r
+            _super.call(this, appenderName, ConsoleAppender.prototype.sendLogItemsConsole);\r
+        }\r
+        ConsoleAppender.prototype.clog = function (logEntry) {\r
+            console.log(logEntry);\r
+        };\r
+        ConsoleAppender.prototype.cerror = function (logEntry) {\r
+            if (console.error) {\r
+                console.error(logEntry);\r
+            }\r
+            else {\r
+                this.clog(logEntry);\r
+            }\r
+        };\r
+        ConsoleAppender.prototype.cwarn = function (logEntry) {\r
+            if (console.warn) {\r
+                console.warn(logEntry);\r
+            }\r
+            else {\r
+                this.clog(logEntry);\r
+            }\r
+        };\r
+        ConsoleAppender.prototype.cinfo = function (logEntry) {\r
+            if (console.info) {\r
+                console.info(logEntry);\r
+            }\r
+            else {\r
+                this.clog(logEntry);\r
+            }\r
+        };\r
+        // IE11 has a console.debug function. But its console doesn't have \r
+        // the option to show/hide debug messages (the same way Chrome and FF do),\r
+        // even though it does have such buttons for Error, Warn, Info.\r
+        //\r
+        // For now, this means that debug messages can not be hidden on IE.\r
+        // Live with this, seeing that it works fine on FF and Chrome, which\r
+        // will be much more popular with developers.\r
+        ConsoleAppender.prototype.cdebug = function (logEntry) {\r
+            if (console.debug) {\r
+                console.debug(logEntry);\r
+            }\r
+            else {\r
+                this.cinfo(logEntry);\r
+            }\r
+        };\r
+        ConsoleAppender.prototype.sendLogItemsConsole = function (logItems) {\r
+            try {\r
+                if (!console) {\r
+                    return;\r
+                }\r
+                var i;\r
+                for (i = 0; i < logItems.length; ++i) {\r
+                    var li = logItems[i];\r
+                    var msg = li.n + ": " + li.m;\r
+                    // Only log the timestamp if we're on the server\r
+                    // (window is undefined). On the browser, the user\r
+                    // sees the log entry probably immediately, so in that case\r
+                    // the timestamp is clutter.\r
+                    if (typeof window === 'undefined') {\r
+                        msg = new Date(li.t) + " | " + msg;\r
+                    }\r
+                    if (li.l <= JL.getDebugLevel()) {\r
+                        this.cdebug(msg);\r
+                    }\r
+                    else if (li.l <= JL.getInfoLevel()) {\r
+                        this.cinfo(msg);\r
+                    }\r
+                    else if (li.l <= JL.getWarnLevel()) {\r
+                        this.cwarn(msg);\r
+                    }\r
+                    else {\r
+                        this.cerror(msg);\r
+                    }\r
+                }\r
+            }\r
+            catch (e) {\r
+            }\r
+        };\r
+        return ConsoleAppender;\r
+    }(Appender));\r
+    JL.ConsoleAppender = ConsoleAppender;\r
+    // --------------------\r
+    var Logger = (function () {\r
+        function Logger(loggerName) {\r
+            this.loggerName = loggerName;\r
+            // Create seenRexes, otherwise this logger will use the seenRexes\r
+            // of its parent via the prototype chain.\r
+            this.seenRegexes = [];\r
+        }\r
+        Logger.prototype.setOptions = function (options) {\r
+            copyProperty("level", options, this);\r
+            copyProperty("userAgentRegex", options, this);\r
+            copyProperty("disallow", options, this);\r
+            copyProperty("ipRegex", options, this);\r
+            copyProperty("appenders", options, this);\r
+            copyProperty("onceOnly", options, this);\r
+            // Reset seenRegexes, in case onceOnly has been changed.\r
+            this.seenRegexes = [];\r
+            return this;\r
+        };\r
+        // Turns an exception into an object that can be sent to the server.\r
+        Logger.prototype.buildExceptionObject = function (e) {\r
+            var excObject = {};\r
+            if (e.stack) {\r
+                excObject.stack = e.stack;\r
+            }\r
+            else {\r
+                excObject.e = e;\r
+            }\r
+            if (e.message) {\r
+                excObject.message = e.message;\r
+            }\r
+            if (e.name) {\r
+                excObject.name = e.name;\r
+            }\r
+            if (e.data) {\r
+                excObject.data = e.data;\r
+            }\r
+            if (e.inner) {\r
+                excObject.inner = this.buildExceptionObject(e.inner);\r
+            }\r
+            return excObject;\r
+        };\r
+        // Logs a log item.\r
+        // Parameter e contains an exception (or null or undefined).\r
+        //\r
+        // Reason that processing exceptions is done at this low level is that\r
+        // 1) no need to spend the cpu cycles if the logger is switched off\r
+        // 2) fatalException takes both a logObject and an exception, and the logObject\r
+        //    may be a function that should only be executed if the logger is switched on.\r
+        //\r
+        // If an exception is passed in, the contents of logObject is attached to the exception\r
+        // object in a new property logData.\r
+        // The resulting exception object is than worked into a message to the server.\r
+        //\r
+        // If there is no exception, logObject itself is worked into the message to the server.\r
+        Logger.prototype.log = function (level, logObject, e) {\r
+            var i = 0;\r
+            var compositeMessage;\r
+            var excObject;\r
+            // If we can't find any appenders, do nothing\r
+            if (!this.appenders) {\r
+                return this;\r
+            }\r
+            if (((level >= this.level)) && allow(this)) {\r
+                if (e) {\r
+                    excObject = this.buildExceptionObject(e);\r
+                    excObject.logData = stringifyLogObjectFunction(logObject);\r
+                }\r
+                else {\r
+                    excObject = logObject;\r
+                }\r
+                compositeMessage = stringifyLogObject(excObject);\r
+                if (allowMessage(this, compositeMessage.finalString)) {\r
+                    // See whether message is a duplicate\r
+                    if (this.onceOnly) {\r
+                        i = this.onceOnly.length - 1;\r
+                        while (i >= 0) {\r
+                            if (new RegExp(this.onceOnly[i]).test(compositeMessage.finalString)) {\r
+                                if (this.seenRegexes[i]) {\r
+                                    return this;\r
+                                }\r
+                                this.seenRegexes[i] = true;\r
+                            }\r
+                            i--;\r
+                        }\r
+                    }\r
+                    // Pass message to all appenders\r
+                    // Note that these appenders could be Winston transports\r
+                    // https://github.com/flatiron/winston\r
+                    //\r
+                    // These transports do not take the logger name as a parameter.\r
+                    // So add it to the meta information, so even Winston transports will\r
+                    // store this info.\r
+                    compositeMessage.meta = compositeMessage.meta || {};\r
+                    compositeMessage.meta.loggerName = this.loggerName;\r
+                    i = this.appenders.length - 1;\r
+                    while (i >= 0) {\r
+                        this.appenders[i].log(levelToString(level), compositeMessage.msg, compositeMessage.meta, function () { }, level, compositeMessage.finalString, this.loggerName);\r
+                        i--;\r
+                    }\r
+                }\r
+            }\r
+            return this;\r
+        };\r
+        Logger.prototype.trace = function (logObject) { return this.log(getTraceLevel(), logObject); };\r
+        Logger.prototype.debug = function (logObject) { return this.log(getDebugLevel(), logObject); };\r
+        Logger.prototype.info = function (logObject) { return this.log(getInfoLevel(), logObject); };\r
+        Logger.prototype.warn = function (logObject) { return this.log(getWarnLevel(), logObject); };\r
+        Logger.prototype.error = function (logObject) { return this.log(getErrorLevel(), logObject); };\r
+        Logger.prototype.fatal = function (logObject) { return this.log(getFatalLevel(), logObject); };\r
+        Logger.prototype.fatalException = function (logObject, e) { return this.log(getFatalLevel(), logObject, e); };\r
+        return Logger;\r
+    }());\r
+    JL.Logger = Logger;\r
+    function createAjaxAppender(appenderName) {\r
+        return new AjaxAppender(appenderName);\r
+    }\r
+    JL.createAjaxAppender = createAjaxAppender;\r
+    function createConsoleAppender(appenderName) {\r
+        return new ConsoleAppender(appenderName);\r
+    }\r
+    JL.createConsoleAppender = createConsoleAppender;\r
+    // -----------------------\r
+    // In the browser, the default appender is the AjaxAppender.\r
+    // Under nodejs (where there is no "window"), use the ConsoleAppender instead.\r
+    var defaultAppender = new AjaxAppender("");\r
+    if (typeof window === 'undefined') {\r
+        defaultAppender = new ConsoleAppender("");\r
+    }\r
+    // Create root logger\r
+    //\r
+    // Note that this is the parent of all other loggers.\r
+    // Logger "x" will be stored at\r
+    // JL.__.x\r
+    // Logger "x.y" at\r
+    // JL.__.x.y\r
+    JL.__ = new JL.Logger("");\r
+    JL.__.setOptions({\r
+        level: JL.getDebugLevel(),\r
+        appenders: [defaultAppender]\r
+    });\r
+})(JL || (JL = {}));\r
+if (typeof exports !== 'undefined') {\r
+    exports.JL = JL;\r
+}\r
+// Support AMD module format\r
+var define;\r
+if (typeof define == 'function' && define.amd) {\r
+    define('jsnlog', [], function () {\r
+        return JL;\r
+    });\r
+}\r
+// If the __jsnlog_configure global function has been\r
+// created, call it now. This allows you to create a global function\r
+// setting logger options etc. inline in the page before jsnlog.js\r
+// has been loaded.\r
+if (typeof __jsnlog_configure == 'function') {\r
+    __jsnlog_configure(JL);\r
+}\r
+// Create onerror handler to log uncaught exceptions to the server side log, but only if there \r
+// is no such handler already.\r
+// Must use "typeof window" here, because in NodeJs, window is not defined at all, so cannot refer to window in any way.\r
+if (typeof window !== 'undefined' && !window.onerror) {\r
+    window.onerror = function (errorMsg, url, lineNumber, column, errorObj) {\r
+        // Send object with all data to server side log, using severity fatal, \r
+        // from logger "onerrorLogger"\r
+        JL("onerrorLogger").fatalException({\r
+            "msg": "Uncaught Exception",\r
+            "errorMsg": errorMsg, "url": url,\r
+            "line number": lineNumber, "column": column\r
+        }, errorObj);\r
+        // Tell browser to run its own error handler as well   \r
+        return false;\r
+    };\r
+}\r
+// Deal with unhandled exceptions thrown in promises\r
+if (typeof window !== 'undefined' && !window.onunhandledrejection) {\r
+    window.onunhandledrejection = function (event) {\r
+        // Send object with all data to server side log, using severity fatal, \r
+        // from logger "onerrorLogger"\r
+        JL("onerrorLogger").fatalException({\r
+            "msg": "unhandledrejection",\r
+            "errorMsg": event.reason.message\r
+        }, event.reason);\r
+        // Tell browser to run its own error handler as well   \r
+        return false;\r
+    };\r
+}\r
index 7982574..da5ac2a 100644 (file)
@@ -4,6 +4,9 @@ var fs = require('fs');
 var mime = require('mime');
 var path = require('path');
 var mkdirp = require('mkdirp');
+var JL = require('jsnlog').JL;
+
+var logger = JL('filesystem.js');
 
 var FileSystem = {};
 FileSystem.PATH_KS = '/tmp/tic/ks/';
@@ -18,9 +21,9 @@ FileSystem.init = function () {
     function fnMkdir(paramPath) {
         mkdirp(paramPath, function (err) {
             if (err) {
-                console.error(err);
+                logger.error(err);
             } else {
-                console.log(paramPath + ' exists');
+                logger.info(paramPath + ' exists');
             }
         });
     }
@@ -74,7 +77,7 @@ FileSystem.download = function (req, res) {
 };
 
 FileSystem.remove = function () {
-    console.log('filesystem.remove called');
+    logger.info('filesystem.remove called');
 };
 
 module.exports = FileSystem;
index fcf6657..423f6f4 100644 (file)
@@ -7,8 +7,11 @@ var fs = require('fs');
 var path = require('path');
 var exec = require('child_process').exec;
 var util = require('util');
+var JL = require('jsnlog').JL;
 var SocketEvent = require('./socketEvent');
 
+var logger = JL('mic.js');
+
 var Mic = {};
 var ps = null;
 
@@ -37,7 +40,7 @@ Mic.process = function (command, callback) {
 };
 
 Mic.create = function (paramObj, io) {
-    console.log('MIC Create');
+    logger.info('MIC Create');
 
     var micCommand = 'sudo mic cr auto ' + paramObj.pathKsFile + util.format(' -A %s', 'x86_64') + util.format(' -o %s', paramObj.pathOutput);
 
@@ -47,20 +50,20 @@ Mic.create = function (paramObj, io) {
 
     Mic.process(micCommand, {
         stdout: function (out) {
-            console.log(out);
+            logger.info(out);
             sendMsg(SocketEvent.FS_IMAGE_ADD_TO, out);
         },
         stderr: function (out) {
-            console.log(out);
+            logger.info(out);
             sendMsg(SocketEvent.FS_IMAGE_ADD_TO, out);
         },
         error: function (out) {
-            console.log(out);
+            logger.info(out);
             sendMsg(SocketEvent.FS_IMAGE_ADD_TO, out);
         },
         exit: function (code) {
             ps = null;
-            console.log('Terminated (' + code + ')');
+            logger.error('Terminated (' + code + ')');
             sendMsg(SocketEvent.FS_IMAGE_ADD_FINISH, 'Terminated (' + code + ')');
         }
     });