diff --git a/README.md b/README.md index 15a8710..11e3d65 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,10 @@ The following configuration options are available. // should the value of $location.absUrl() be sent as a "url" key in the // message object that's sent to loggly? Default is false. .includeUrl( false ) + + // should the value of $window.navigator.userAgent be sent as a "userAgent" key in the + // message object that's sent to loggly? Default is false. + .includeUserAgent( false ) // should the current timestamp be included? Default is false. .includeTimestamp( false ) @@ -112,6 +116,21 @@ The following configuration options are available. // keep sending messages to Loggly in production without also sending them // to the console. Default is true. .logToConsole( true ) + + // Custom labels for standard log fields. Use this to customize your log + // message format or to shorten your logging payload. All available labels + // are listed in this example. + .labels({ + col: 'c', + level: 'lvl', + line: 'l', + logger: 'lgr', + message: 'msg', + stack: 'stk', + timestamp: 'ts', + url: 'url', + userAgent: 'userAgent' + }) ``` diff --git a/angular-loggly-logger.js b/angular-loggly-logger.js index d267bd3..a4abce1 100644 --- a/angular-loggly-logger.js +++ b/angular-loggly-logger.js @@ -20,10 +20,12 @@ var extra = {}; var includeCurrentUrl = false; var includeTimestamp = false; + var includeUserAgent = false; var tag = null; var sendConsoleErrors = false; var logToConsole = true; var loggingEnabled = true; + var labels = {}; // The minimum level of messages that should be sent to loggly. var level = 0; @@ -49,6 +51,15 @@ return extra; }; + this.labels = function(l) { + if (angular.isObject(l)) { + labels = l; + return self; + } + + return labels; + }; + this.inputToken = function ( s ) { if (angular.isDefined(s)) { token = s; @@ -85,6 +96,15 @@ return includeTimestamp; }; + this.includeUserAgent = function (flag) { + if (angular.isDefined(flag)) { + includeUserAgent = !!flag; + return self; + } + + return includeUserAgent; + }; + this.inputTag = function (usrTag){ if (angular.isDefined(usrTag)) { tag = usrTag; @@ -159,6 +179,7 @@ } //TODO we're injecting this here to resolve circular dependency issues. Is this safe? + var $window = $injector.get( '$window' ); var $location = $injector.get( '$location' ); //we're injecting $http var $http = $injector.get( '$http' ); @@ -175,6 +196,10 @@ sentData.timestamp = lastLog.toISOString(); } + if( includeUserAgent ) { + sentData.userAgent = $window.navigator.userAgent; + } + //Loggly's API doesn't send us cross-domain headers, so we can't interact directly //Set header var config = { @@ -184,6 +209,13 @@ withCredentials: false }; + // Apply labels + for (var label in labels) { + if (label in sentData) { + sentData[labels[label]] = sentData[label]; + delete sentData[label]; + } + } //Ajax call to send data to loggly $http.post(buildUrl(),sentData,config); diff --git a/angular-loggly-logger.min.js b/angular-loggly-logger.min.js index 8924818..2fbc9ae 100644 --- a/angular-loggly-logger.min.js +++ b/angular-loggly-logger.min.js @@ -1,2 +1,2 @@ -!function(a){"use strict";a.module("logglyLogger.logger",[]).provider("LogglyLogger",function(){var b=this,c=["DEBUG","INFO","WARN","ERROR"],d=!0,e={},f=!1,g=!1,h=null,i=!1,j=!0,k=!0,l=0,m=null,n="://logs-01.loggly.com/inputs/",o=function(){return(d?"https":"http")+n+m+"/tag/"+(h?h:"AngularJS")+"/"};this.setExtra=function(a){return e=a,b},this.fields=function(c){return a.isDefined(c)?(e=c,b):e},this.inputToken=function(c){return a.isDefined(c)?(m=c,b):m},this.useHttps=function(c){return a.isDefined(c)?(d=!!c,b):d},this.includeUrl=function(c){return a.isDefined(c)?(f=!!c,b):f},this.includeTimestamp=function(c){return a.isDefined(c)?(g=!!c,b):g},this.inputTag=function(c){return a.isDefined(c)?(h=c,b):h},this.sendConsoleErrors=function(c){return a.isDefined(c)?(i=!!c,b):i},this.level=function(d){if(a.isDefined(d)){var e=c.indexOf(d.toUpperCase());if(0>e)throw"Invalid logging level specified: "+d;return l=e,b}return c[l]},this.isLevelEnabled=function(a){return c.indexOf(a.toUpperCase())>=l},this.loggingEnabled=function(c){return a.isDefined(c)?(k=!!c,b):k},this.logToConsole=function(c){return a.isDefined(c)?(j=!!c,b):j},this.$get=["$injector",function(c){var d=null,h=function(b){if(m&&k){var h=c.get("$location"),i=c.get("$http");d=new Date;var j=a.extend({},e,b);f&&(j.url=h.absUrl()),g&&(j.timestamp=d.toISOString());var l={headers:{"Content-Type":"text/plain"},withCredentials:!1};i.post(o(),j,l)}},n=function(){},p=function(b){return a.isDefined(b)&&(m=b),m};return{lastLog:function(){return d},sendConsoleErrors:function(){return i},level:function(){return l},loggingEnabled:b.loggingEnabled,isLevelEnabled:b.isLevelEnabled,attach:n,sendMessage:h,logToConsole:j,inputToken:p,fields:function(c){return a.isDefined(c)&&b.fields(c),b.fields()}}}]}),a.module("logglyLogger",["logglyLogger.logger"]).config(["$provide",function(b){b.decorator("$log",["$delegate","$injector",function(b,c){var d=c.get("LogglyLogger");if(d.sendConsoleErrors()===!0){var e=window.onerror;window.onerror=function(a,b,c,f){d.sendMessage({level:"ERROR",message:a,url:b,line:c,col:f}),e&&"function"==typeof e&&e.apply(window,arguments)}}var f=function(b,c,e){var f=function(){var f=Array.prototype.slice.call(arguments);if(d.logToConsole&&b.apply(null,f),d.loggingEnabled()&&d.isLevelEnabled(c)){var g=(1===f.length?f[0]:f)||{},h={level:c};if(a.isDefined(g.stack)||a.isDefined(g[0])&&a.isDefined(g[0].stack)){if(d.sendConsoleErrors()!==!0)return;h.message=g.message||g[0].message,h.stack=g.stack||g[0].stack}else a.isObject(g)?h=a.extend({},g,h):h.message=g;e&&(h.logger=g),d.sendMessage(h)}};return f.logs=[],f},g=function(a){return{log:a.log,info:a.info,warn:a.warn,error:a.error}}(b),h=function(a){return{log:f(g.log,"INFO",a),debug:f(g.debug,"DEBUG",a),info:f(g.info,"INFO",a),warn:f(g.warn,"WARN",a),error:f(g.error,"ERROR",a)}};return b.log=f(b.log,"INFO"),b.debug=f(b.debug,"DEBUG"),b.info=f(b.info,"INFO"),b.warn=f(b.warn,"WARN"),b.error=f(b.error,"ERROR"),b.getLogger=h,b}])}])}(window.angular); +!function(a){"use strict";a.module("logglyLogger.logger",[]).provider("LogglyLogger",function(){var b=this,c=["DEBUG","INFO","WARN","ERROR"],d=!0,e={},f=!1,g=!1,h=!1,i=null,j=!1,k=!0,l=!0,m={},n=0,o=null,p="://logs-01.loggly.com/inputs/",q=function(){return(d?"https":"http")+p+o+"/tag/"+(i?i:"AngularJS")+"/"};this.setExtra=function(a){return e=a,b},this.fields=function(c){return a.isDefined(c)?(e=c,b):e},this.labels=function(c){return a.isObject(c)?(m=c,b):m},this.inputToken=function(c){return a.isDefined(c)?(o=c,b):o},this.useHttps=function(c){return a.isDefined(c)?(d=!!c,b):d},this.includeUrl=function(c){return a.isDefined(c)?(f=!!c,b):f},this.includeTimestamp=function(c){return a.isDefined(c)?(g=!!c,b):g},this.includeUserAgent=function(c){return a.isDefined(c)?(h=!!c,b):h},this.inputTag=function(c){return a.isDefined(c)?(i=c,b):i},this.sendConsoleErrors=function(c){return a.isDefined(c)?(j=!!c,b):j},this.level=function(d){if(a.isDefined(d)){var e=c.indexOf(d.toUpperCase());if(0>e)throw"Invalid logging level specified: "+d;return n=e,b}return c[n]},this.isLevelEnabled=function(a){return c.indexOf(a.toUpperCase())>=n},this.loggingEnabled=function(c){return a.isDefined(c)?(l=!!c,b):l},this.logToConsole=function(c){return a.isDefined(c)?(k=!!c,b):k},this.$get=["$injector",function(c){var d=null,i=function(b){if(o&&l){var i=c.get("$window"),j=c.get("$location"),k=c.get("$http");d=new Date;var n=a.extend({},e,b);f&&(n.url=j.absUrl()),g&&(n.timestamp=d.toISOString()),h&&(n.userAgent=i.navigator.userAgent);var p={headers:{"Content-Type":"text/plain"},withCredentials:!1};for(var r in m)r in n&&(n[m[r]]=n[r],delete n[r]);k.post(q(),n,p)}},p=function(){},r=function(b){return a.isDefined(b)&&(o=b),o};return{lastLog:function(){return d},sendConsoleErrors:function(){return j},level:function(){return n},loggingEnabled:b.loggingEnabled,isLevelEnabled:b.isLevelEnabled,attach:p,sendMessage:i,logToConsole:k,inputToken:r,fields:function(c){return a.isDefined(c)&&b.fields(c),b.fields()}}}]}),a.module("logglyLogger",["logglyLogger.logger"]).config(["$provide",function(b){b.decorator("$log",["$delegate","$injector",function(b,c){var d=c.get("LogglyLogger");if(d.sendConsoleErrors()===!0){var e=window.onerror;window.onerror=function(a,b,c,f){d.sendMessage({level:"ERROR",message:a,url:b,line:c,col:f}),e&&"function"==typeof e&&e.apply(window,arguments)}}var f=function(b,c,e){var f=function(){var f=Array.prototype.slice.call(arguments);if(d.logToConsole&&b.apply(null,f),d.loggingEnabled()&&d.isLevelEnabled(c)){var g=(1===f.length?f[0]:f)||{},h={level:c};if(a.isDefined(g.stack)||a.isDefined(g[0])&&a.isDefined(g[0].stack)){if(d.sendConsoleErrors()!==!0)return;h.message=g.message||g[0].message,h.stack=g.stack||g[0].stack}else a.isObject(g)?h=a.extend({},g,h):h.message=g;e&&(h.logger=g),d.sendMessage(h)}};return f.logs=[],f},g=function(a){return{log:a.log,info:a.info,warn:a.warn,error:a.error}}(b),h=function(a){return{log:f(g.log,"INFO",a),debug:f(g.debug,"DEBUG",a),info:f(g.info,"INFO",a),warn:f(g.warn,"WARN",a),error:f(g.error,"ERROR",a)}};return b.log=f(b.log,"INFO"),b.debug=f(b.debug,"DEBUG"),b.info=f(b.info,"INFO"),b.warn=f(b.warn,"WARN"),b.error=f(b.error,"ERROR"),b.getLogger=h,b}])}])}(window.angular); //# sourceMappingURL=angular-loggly-logger.min.map \ No newline at end of file diff --git a/angular-loggly-logger.min.map b/angular-loggly-logger.min.map index 7a2506d..2b4a716 100644 --- a/angular-loggly-logger.min.map +++ b/angular-loggly-logger.min.map @@ -1 +1 @@ -{"version":3,"sources":["angular-loggly-logger.js"],"names":["angular","module","provider","self","this","logLevels","https","extra","includeCurrentUrl","includeTimestamp","tag","sendConsoleErrors","logToConsole","loggingEnabled","level","token","endpoint","buildUrl","setExtra","d","fields","isDefined","inputToken","s","useHttps","flag","includeUrl","inputTag","usrTag","name","newLevel","indexOf","toUpperCase","isLevelEnabled","$get","$injector","lastLog","sendMessage","data","$location","get","$http","Date","sentData","extend","url","absUrl","timestamp","toISOString","config","headers","Content-Type","withCredentials","post","attach","$provide","decorator","$delegate","logger","_onerror","window","onerror","msg","line","col","message","apply","arguments","wrapLogFunction","logFn","loggerName","wrappedFn","args","Array","prototype","slice","call","length","sending","stack","isObject","logs","_$log","log","info","warn","error","getLogger","debug"],"mappings":"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","file":"angular-loggly-logger.min.js"} \ No newline at end of file +{"version":3,"sources":["angular-loggly-logger.js"],"names":["angular","module","provider","self","this","logLevels","https","extra","includeCurrentUrl","includeTimestamp","includeUserAgent","tag","sendConsoleErrors","logToConsole","loggingEnabled","labels","level","token","endpoint","buildUrl","setExtra","d","fields","isDefined","l","isObject","inputToken","s","useHttps","flag","includeUrl","inputTag","usrTag","name","newLevel","indexOf","toUpperCase","isLevelEnabled","$get","$injector","lastLog","sendMessage","data","$window","get","$location","$http","Date","sentData","extend","url","absUrl","timestamp","toISOString","userAgent","navigator","config","headers","Content-Type","withCredentials","label","post","attach","$provide","decorator","$delegate","logger","_onerror","window","onerror","msg","line","col","message","apply","arguments","wrapLogFunction","logFn","loggerName","wrappedFn","args","Array","prototype","slice","call","length","sending","stack","logs","_$log","log","info","warn","error","getLogger","debug"],"mappings":"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","file":"angular-loggly-logger.min.js"} \ No newline at end of file diff --git a/test/unit/logglySenderSpec.js b/test/unit/logglySenderSpec.js index 30ce7ed..73534da 100644 --- a/test/unit/logglySenderSpec.js +++ b/test/unit/logglySenderSpec.js @@ -4,8 +4,7 @@ describe('logglyLogger Module:', function() { var logglyLoggerProvider, - moduleTest = this, - levels = ['DEBUG', 'INFO', 'WARN', 'ERROR']; + levels = ['DEBUG', 'INFO', 'WARN', 'ERROR']; beforeEach(function () { // Initialize the service provider @@ -25,34 +24,31 @@ describe('logglyLogger Module:', function() { describe( 'LogglyLoggerProvider', function() { - it( 'can have a logging level configured', function() { - for( var i in levels ) { - logglyLoggerProvider.level( levels[i] ); - expect( logglyLoggerProvider.level() ).toEqual( levels[i] ); - } + for( var i in levels ) { + logglyLoggerProvider.level( levels[i] ); + expect( logglyLoggerProvider.level() ).toEqual( levels[i] ); + } }); - it( 'will throw an exception if an invalid level is supplied', function() { - expect( function() { logglyLoggerProvider.level('TEST') } ).toThrow(); + expect( function() { logglyLoggerProvider.level('TEST') } ).toThrow(); }); it( 'can determine if a given level is enabled', function() { - for( var a in levels ) { + for( var a in levels ) { - logglyLoggerProvider.level( levels[a] ); + logglyLoggerProvider.level( levels[a] ); - for( var b in levels ) { - expect( logglyLoggerProvider.isLevelEnabled( levels[b] )).toBe( b >= a ); - } + for( var b in levels ) { + expect( logglyLoggerProvider.isLevelEnabled( levels[b] )).toBe( b >= a ); } + } }); it( 'can specify extra fields to be sent with each log message', function() { - var extra = { "test": "extra" }; logglyLoggerProvider.fields( extra ); @@ -64,17 +60,20 @@ describe('logglyLogger Module:', function() { }); describe( 'LogglyLogger', function() { - - var service, $log, $httpBackend; + var token = 'test123456', + tag = 'logglyLogger', + message, service, $log, $httpBackend; beforeEach(function () { + message = {message: 'A test message'}; + inject(function ($injector) { - $log = $injector.get('$log'); + $log = $injector.get('$log'); $httpBackend = $injector.get('$httpBackend'); service = $injector.get('LogglyLogger'); service.attach(); - }); }); + }); afterEach(function () { $httpBackend.verifyNoOutstandingExpectation(); @@ -86,25 +85,22 @@ describe('logglyLogger Module:', function() { }); it('will not send a message to loggly if a token is not specified', function () { - var url = 'https://logs-01.loggly.com'; - var forbiddenCallTriggered = false; - $httpBackend - .when(url) - .respond(function () { - forbiddenCallTriggered = true; - return [400, '']; - }); - + var url = 'https://logs-01.loggly.com'; + var forbiddenCallTriggered = false; + $httpBackend + .when(url) + .respond(function () { + forbiddenCallTriggered = true; + return [400, '']; + }); + service.sendMessage("A test message"); // Let test fail when request was triggered. expect(forbiddenCallTriggered).toBe(false); }); it('will send a message to loggly only when properly configured', function () { - var token = 'test123456'; - var message = { message: 'A test message' }; var expectMessage = { message: 'A test message' }; - var url = 'https://logs-01.loggly.com/inputs/' + token; var tag = 'logglyLogger'; var testURL = 'https://logs-01.loggly.com/inputs/test123456/tag/logglyLogger/'; var generatedURL; @@ -114,11 +110,11 @@ describe('logglyLogger Module:', function() { logglyLoggerProvider.inputTag(tag); $httpBackend - .expectPOST(testURL, expectMessage) - .respond(function (method, url, data) { - generatedURL = url; - return [200, "", {}]; - }); + .expectPOST(testURL, expectMessage) + .respond(function (method, url, data) { + generatedURL = url; + return [200, "", {}]; + }); service.sendMessage(message); $httpBackend.flush(); @@ -127,10 +123,6 @@ describe('logglyLogger Module:', function() { }); it('will use http if useHttps is set to false', function () { - var token = 'test123456'; - var message = { message: 'A message' }; - var expectMessage = { message: 'A message' }; - var url = 'http://logs-01.loggly.com/inputs/' + token; var testURL = 'http://logs-01.loggly.com/inputs/test123456/tag/AngularJS/'; var generatedURL; @@ -139,12 +131,12 @@ describe('logglyLogger Module:', function() { logglyLoggerProvider.includeUrl(false); $httpBackend - .expectPOST(testURL, expectMessage) - .respond(function (method, url, data) { - generatedURL = new URL(url); - return [200, "", {}]; - }); - + .expectPOST(testURL, message) + .respond(function (method, url, data) { + generatedURL = new URL(url); + return [200, "", {}]; + }); + service.sendMessage(message); $httpBackend.flush(); @@ -154,10 +146,7 @@ describe('logglyLogger Module:', function() { }); it('will include the current url if includeUrl() is not set to false', function () { - var token = 'test123456'; - var message = { message: 'A Test message' }; - var expectMessage = { message: 'A Test message', url: 'http://bloggly.com' }; - var url = 'https://logs-01.loggly.com/inputs/' + token; + var expectMessage = angular.extend(message, { url: 'http://bloggly.com' }); var testURL = 'https://logs-01.loggly.com/inputs/test123456/tag/AngularJS/'; var payload; @@ -169,13 +158,13 @@ describe('logglyLogger Module:', function() { logglyLoggerProvider.inputToken( token ); logglyLoggerProvider.includeUrl( true ); - $httpBackend - .expectPOST(testURL, expectMessage) - .respond(function (method, url, data) { - payload = JSON.parse(data); - return [200, "", {}]; + $httpBackend + .expectPOST(testURL, expectMessage) + .respond(function (method, url, data) { + payload = JSON.parse(data); + return [200, "", {}]; }); - + service.sendMessage( message ); $httpBackend.flush(); @@ -183,6 +172,28 @@ describe('logglyLogger Module:', function() { }); + it('will include the current userAgent if includeUserAgent() is not set to false', function () { + var expectMessage = angular.extend(message, { userAgent: window.navigator.userAgent }); + var testURL = 'https://logs-01.loggly.com/inputs/test123456/tag/AngularJS/'; + var payload; + + logglyLoggerProvider.inputToken( token ); + logglyLoggerProvider.includeUserAgent( true ); + + $httpBackend + .expectPOST(testURL, expectMessage) + .respond(function (method, url, data) { + payload = JSON.parse(data); + return [200, "", {}]; + }); + + service.sendMessage( message ); + + $httpBackend.flush(); + expect(payload.userAgent).toEqual(window.navigator.userAgent); + + }); + it( 'can set extra fields using the fields method', function() { var extra = { appVersion: '1.1.0', browser: 'Chrome' }; @@ -193,10 +204,8 @@ describe('logglyLogger Module:', function() { it( 'will include extra fields if set via provider and service', function() { var payload, payload2; - var token = 'test123456'; var extra = { appVersion: '1.1.0', browser: 'Chrome' }; - var message = 'A Test message'; - var expectMessage = { appVersion: "1.1.0", browser: "Chrome", message: "A Test message" }; + var expectMessage = angular.extend(message, extra); var testURL = 'https://logs-01.loggly.com/inputs/test123456/tag/AngularJS/'; logglyLoggerProvider.inputToken( token ); @@ -204,62 +213,55 @@ describe('logglyLogger Module:', function() { logglyLoggerProvider.fields( extra ); $httpBackend - .expectPOST(testURL, expectMessage) - .respond(function (method, url, data) { - payload = JSON.parse(data); - return [200, "", {}]; + .expectPOST(testURL, expectMessage) + .respond(function (method, url, data) { + payload = JSON.parse(data); + return [200, "", {}]; }); - service.sendMessage( { message: message } ); + service.sendMessage(message); - $httpBackend.flush(); - expect(payload).toEqual({ appVersion: '1.1.0', browser: 'Chrome', message: message }); + $httpBackend.flush(); + expect(payload).toEqual(expectMessage); - var expectMessage2 = { appVersion: '1.1.0', browser: 'Chrome', username: 'baldrin', message: 'A Test message' }; + var expectMessage2 = angular.extend(message, { appVersion: '1.1.0', browser: 'Chrome', username: 'baldrin' }); extra.username = "baldrin"; service.fields( extra ); $httpBackend - .expectPOST(testURL, expectMessage2) - .respond(function (method, url, data) { - payload2 = JSON.parse(data); - return [200, "", {}]; + .expectPOST(testURL, expectMessage2) + .respond(function (method, url, data) { + payload2 = JSON.parse(data); + return [200, "", {}]; }); - service.sendMessage( { message: message } ); + service.sendMessage(message); $httpBackend.flush(); - expect(payload2).toEqual({ appVersion: '1.1.0', browser: 'Chrome', username: 'baldrin', message: message }); - + expect(payload2).toEqual(expectMessage2); }); - it( 'will include extra fields if set via the service', function() { var payload; - var token = 'test123456'; var testURL = 'https://logs-01.loggly.com/inputs/test123456/tag/AngularJS/'; var extra = { appVersion: '1.1.0', browser: 'Chrome' }; - var message = 'A Test message'; - var expectMessage = { appVersion: '1.1.0', browser: 'Chrome', message: message }; + var expectMessage = angular.extend(message, extra); logglyLoggerProvider.inputToken( token ); logglyLoggerProvider.fields( extra ); $httpBackend - .expectPOST(testURL, expectMessage) - .respond(function (method, url, data) { - payload = JSON.parse(data); - return [200, "", {}]; - }); + .expectPOST(testURL, expectMessage) + .respond(function (method, url, data) { + payload = JSON.parse(data); + return [200, "", {}]; + }); - service.sendMessage( { message: message } ); + service.sendMessage(message); $httpBackend.flush(); - expect(payload).toEqual( { appVersion: '1.1.0', browser: 'Chrome', message: message }); + expect(payload).toEqual(expectMessage); }); it( '$log has a logglySender attached', function() { - var token = 'test123456'; - var logMessage = { message: 'A Test Log Message' }; - var url = 'https://logs-01.loggly.com/inputs/' + token; var testURL = 'https://logs-01.loggly.com/inputs/test123456/tag/AngularJS/'; var payload, expectMessage; @@ -267,108 +269,94 @@ describe('logglyLogger Module:', function() { logglyLoggerProvider.includeUrl( false ); angular.forEach( levels, function (level) { - expectMessage = { message: 'A Test Log Message', level: level }; + expectMessage = angular.extend(message, { level: level }); $httpBackend - .expectPOST(testURL, expectMessage) - .respond(function (method, url, data) { - payload = JSON.parse(data); - return [200, "", {}]; - }); - $log[level.toLowerCase()].call($log, logMessage); + .expectPOST(testURL, expectMessage) + .respond(function (method, url, data) { + payload = JSON.parse(data); + return [200, "", {}]; + }); + $log[level.toLowerCase()].call($log, message); $httpBackend.flush(); expect(payload.level).toEqual(level); }); - }); it( 'will not send messages for levels that are not enabled', function() { - var logMessage = 'A Test Log Message'; + spyOn(service, 'sendMessage').and.callThrough(); - spyOn(service, 'sendMessage').and.callThrough(); + for( var a in levels ) { - for( var a in levels ) { + logglyLoggerProvider.level( levels[a] ); - logglyLoggerProvider.level( levels[a] ); + for( var b in levels ) { - for( var b in levels ) { + $log[levels[b].toLowerCase()].call($log, message.message); + if( b >= a ) { + expect(service.sendMessage).toHaveBeenCalled(); + } else { + expect(service.sendMessage).not.toHaveBeenCalled(); + } - $log[levels[b].toLowerCase()].call($log, logMessage); - if( b >= a ) { - expect(service.sendMessage).toHaveBeenCalled(); - } else { - expect(service.sendMessage).not.toHaveBeenCalled(); - } - - service.sendMessage.calls.reset(); - } + service.sendMessage.calls.reset(); } - + } }); it( 'will not send messages if logs are not enabled', function() { - var token = 'test123456'; - var message = { message: 'A test message' }; - var expectMessage = { message: 'A test message' }; - var url = 'https://logs-01.loggly.com/inputs/' + token; - var tag = 'logglyLogger'; - var testURL = 'https://logs-01.loggly.com/inputs/test123456/tag/logglyLogger/'; - var generatedURL; - - logglyLoggerProvider.inputToken(token); - logglyLoggerProvider.includeUrl(false); - logglyLoggerProvider.loggingEnabled(false); - logglyLoggerProvider.inputTag(tag); - - var forbiddenCallTriggered = false; - $httpBackend + var url = 'https://logs-01.loggly.com/inputs/' + token; + var tag = 'logglyLogger'; + + logglyLoggerProvider.inputToken(token); + logglyLoggerProvider.includeUrl(false); + logglyLoggerProvider.loggingEnabled(false); + logglyLoggerProvider.inputTag(tag); + + var forbiddenCallTriggered = false; + $httpBackend .when(url) .respond(function () { - forbiddenCallTriggered = true; - return [400, '']; - }); - service.sendMessage("A test message"); - // Let test fail when request was triggered. - expect(forbiddenCallTriggered).toBe(false); + forbiddenCallTriggered = true; + return [400, '']; }); + service.sendMessage("A test message"); + // Let test fail when request was triggered. + expect(forbiddenCallTriggered).toBe(false); + }); it( 'will disable logs after config had them enabled and not send messages', function() { - var token = 'test123456'; - var message = { message: 'A test message' }; - var expectMessage = { message: 'A test message' }; - var url = 'https://logs-01.loggly.com/inputs/' + token; - var tag = 'logglyLogger'; - var testURL = 'https://logs-01.loggly.com/inputs/test123456/tag/logglyLogger/'; - var generatedURL; - - logglyLoggerProvider.inputToken(token); - logglyLoggerProvider.includeUrl(false); - logglyLoggerProvider.loggingEnabled(true); - logglyLoggerProvider.inputTag(tag); + var tag = 'logglyLogger'; + var testURL = 'https://logs-01.loggly.com/inputs/test123456/tag/logglyLogger/'; + var generatedURL; - $httpBackend - .expectPOST(testURL, expectMessage) + logglyLoggerProvider.inputToken(token); + logglyLoggerProvider.includeUrl(false); + logglyLoggerProvider.loggingEnabled(true); + logglyLoggerProvider.inputTag(tag); + + $httpBackend + .expectPOST(testURL, message) .respond(function (method, url, data) { - generatedURL = url; - return [200, "", {}]; + generatedURL = url; + return [200, "", {}]; }); - - service.sendMessage(message); - $httpBackend.flush(); - expect(generatedURL).toEqual(testURL); - }); - it( 'will not fail if the logged message is null or undefined', function() { - var undefinedMessage; - var nullMessage = null; + service.sendMessage(message); + $httpBackend.flush(); + expect(generatedURL).toEqual(testURL); + }); - expect( function() { - $log.debug( undefinedMessage ); - }).not.toThrow(); + it( 'will not fail if the logged message is null or undefined', function() { + var undefinedMessage; + var nullMessage = null; - expect( function() { - $log.debug( nullMessage ); - }).not.toThrow(); + expect( function() { + $log.debug( undefinedMessage ); + }).not.toThrow(); + expect( function() { + $log.debug( nullMessage ); + }).not.toThrow(); }); it( 'can update the Loggly token', function() { @@ -377,7 +365,25 @@ describe('logglyLogger Module:', function() { expect(logglyLoggerProvider.inputToken()).toEqual('foo'); }); + it('will override labels as specified', function () { + var expectMessage = { msg: message.message }; + var testURL = 'https://logs-01.loggly.com/inputs/test123456/tag/AngularJS/'; - }); + logglyLoggerProvider.inputToken( token ); + logglyLoggerProvider.labels({ + message: 'msg' + }); + $httpBackend + .whenPOST(testURL) + .respond(function (method, url, data) { + expect(JSON.parse(data)).toEqual(expectMessage); + return [200, "", {}]; + }); + + service.sendMessage( message ); + + $httpBackend.flush(); + }); + }); });