From 244a003a6df2df487d903c99f75fd497d698dede Mon Sep 17 00:00:00 2001 From: Vladimir Rybalko Date: Thu, 25 May 2017 17:10:39 +0700 Subject: [PATCH] Ability to chamge user, session and device info. --- README.md | 25 ++++++++++++-- dist/angular-applicationinsights.js | 43 ++++++++++++++++++------ dist/angular-applicationinsights.min.js | 2 +- src/ApplicationInsights.ts | 44 +++++++++++++++++++++---- src/ExceptionInterceptor.ts | 6 ++-- 5 files changed, 98 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 710e4ab..b350f5a 100644 --- a/README.md +++ b/README.md @@ -121,8 +121,9 @@ Sends a custom event to Application Insights. Sends error data to Application Insights. ```Javascript // exception (Error) : Required - the error object to be processed. +// properties (Hash): Optional - a String/String hash object of properties to associate with this exception - applicationInsightsService.trackException( exception ); + applicationInsightsService.trackException(exception, properties); ``` Note: if the *autoTrackExceptions* option is enabled, this method will be called any time the **$exceptionHandler** is invoked. ```Javascript @@ -169,7 +170,7 @@ Sends a trace log message to Application Insights. // severity (String) : Optional - The message severity Level (debug,info,warn, error). Defaults to 'info'. // properties (Hash) : Optional - a String/String hash object of properties to associate with this event. - applicationInsightsService.trackTraceMessage( message , severity , properties); + applicationInsightsService.trackTraceMessage( message, severity, properties); ``` If the *autoLogTracking* option is enabled, trackTraceMessage will be called any time one of the **$log** service methods are called. ```Javascript @@ -177,7 +178,27 @@ If the *autoLogTracking* option is enabled, trackTraceMessage will be called any $log.info('message'); ``` +#### defineUser +Define a new user metadata. +```Javascript +// userId (Guid) : Required - The user unique identifier. + applicationInsightsService.defineUser( userId ); +``` +#### defineSession +Define a new session identifier of Application Insights. +```Javascript +// sessionId (Guid) : Required - The session identifier. + applicationInsightsService.defineSession( sessionId ); +``` + +#### defineDevice +Define a new device metadata. +```Javascript +// id (Guid) : Required - The device unique identifier. +// type (String) : Required - The device type. + applicationInsightsService.defineDevice( id, type ); +``` [travisCI-image]: https://travis-ci.org/khaines/angular-applicationinsights.svg?branch=master& [travisCI-url]: https://travis-ci.org/khaines/angular-applicationinsights diff --git a/dist/angular-applicationinsights.js b/dist/angular-applicationinsights.js index 22b5df6..0463eec 100644 --- a/dist/angular-applicationinsights.js +++ b/dist/angular-applicationinsights.js @@ -339,9 +339,7 @@ var StackFrame = (function () { //} StackFrame.prototype.setLineNumber = function (v) { if (!Tools.isNumber(v)) { - /* test-code */ - console.log('LineNumber is ' + v); - /* end-test-code */ + this.line = undefined; return; } @@ -572,14 +570,14 @@ var ExceptionInterceptor = (function () { $provide.decorator('$exceptionHandler', [ '$delegate', function ($delegate) { _this._origExceptionHandler = $delegate; - return function (exception, cause) { + return function (exception) { // track the call // ... only if there is no active issues/errors sending data over http, in order to prevent an infinite loop. if (!ExceptionInterceptor.errorOnHttpCall) { - _this._interceptFunction(exception, cause); + _this._interceptFunction(exception); } // Call the original - _this._origExceptionHandler(exception, cause); + _this._origExceptionHandler(exception); }; } ]); @@ -650,6 +648,8 @@ var ApplicationInsights = (function () { var _this = this; this._sessionKey = "$$appInsights__session"; this._userKey = "$$appInsights__uuid"; + this._deviceKey = "$$appInsights__device"; + this._deviceTypeKey = "$$appInsights__device__type"; this._version = "angular:0.3.0"; this._analyticsServiceUrl = "https://dc.services.visualstudio.com/v2/track"; this._contentType = "application/json"; @@ -668,7 +668,7 @@ var ApplicationInsights = (function () { this._logInterceptor.setInterceptFunction(function (message, level, properties) { return _this.trackTraceMessage(message, level, properties); }); } if (this.options.autoExceptionTracking) { - this._exceptionInterceptor.setInterceptFunction(function (exception, cause, exceptionProperties) { return _this.trackException(exception, cause, exceptionProperties); }); + this._exceptionInterceptor.setInterceptFunction(function (exception, exceptionProperties) { return _this.trackException(exception, exceptionProperties); }); } } ApplicationInsights.prototype.getUserId = function () { @@ -683,6 +683,25 @@ var ApplicationInsights = (function () { ApplicationInsights.prototype.setUserId = function (userId) { this._localStorage.set(this._userKey, userId); }; + ApplicationInsights.prototype.getDeviceId = function () { + var id = this._localStorage.get(this._deviceKey); + if (Tools.isNullOrUndefined(id)) { + id = Tools.generateGuid(); + this._localStorage.set(this._deviceKey, id); + } + return id; + }; + ApplicationInsights.prototype.getDeviceType = function () { + var type = this._localStorage.get(this._deviceTypeKey); + if (Tools.isNullOrUndefined(type)) { + type = "Browser"; + } + return type; + }; + ApplicationInsights.prototype.setDeviceInfo = function (id, type) { + this._localStorage.set(this._deviceKey, id); + this._localStorage.set(this._deviceTypeKey, type); + }; ApplicationInsights.prototype.getOperationId = function () { var uuidKey = "$$appInsights__operationid"; var uuid = Tools.generateGuid(); @@ -876,7 +895,7 @@ var ApplicationInsights = (function () { }); this.sendData(data); }; - ApplicationInsights.prototype.trackException = function (exception, cause, exceptionProperties) { + ApplicationInsights.prototype.trackException = function (exception, exceptionProperties) { if (Tools.isNullOrUndefined(exception)) { return; } @@ -910,6 +929,9 @@ var ApplicationInsights = (function () { ApplicationInsights.prototype.defineSession = function (sessionId) { this.makeNewSession(sessionId); }; + ApplicationInsights.prototype.defineDevice = function (id, type) { + this.setDeviceInfo(id, type); + }; ApplicationInsights.prototype.generateAppInsightsData = function (payloadName, payloadDataType, payloadData) { if (this._commonProperties) { payloadData.properties = payloadData.properties || {}; @@ -931,10 +953,10 @@ var ApplicationInsights = (function () { id: payloadName === ApplicationInsights.names.pageViews ? this.getOperationId() : this.getStoredOperationId() }, device: { - id: "browser", + id: this.getDeviceId(), locale: this._locale.id, resolution: this._window.screen.availWidth + "x" + this._window.screen.availHeight, - type: "Browser" + type: this.getDeviceType() }, internal: { sdkVersion: this._version @@ -1061,3 +1083,4 @@ var AppInsightsProvider = (function () { }; // invoked when the provider is run return AppInsightsProvider; }()); +//# sourceMappingURL=angular-applicationinsights.js.map \ No newline at end of file diff --git a/dist/angular-applicationinsights.min.js b/dist/angular-applicationinsights.min.js index 8a86d4b..5057f6b 100644 --- a/dist/angular-applicationinsights.min.js +++ b/dist/angular-applicationinsights.min.js @@ -1,2 +1,2 @@ /*! angular-applicationinsights version 0.3.1 2017-05-25 */ -var Tools=function(){function a(b){a.isDefined=b.isDefined,a.isUndefined=b.isUndefined,a.isObject=b.isObject,a.isArray=b.isArray,a.isString=b.isString,a.extend=b.extend,a.toJson=b.toJson,a.fromJson=b.fromJson,a.forEach=b.forEach,a.copy=b.copy,a.noop=b.noop}return a.isNullOrUndefined=function(b){return a.isUndefined(b)||null===b},a.isNumber=function(a){return!isNaN(parseFloat(a))&&isFinite(a)},a.generateGuid=function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(a){var b=16*Math.random()|0,c="x"==a?b:3&b|8;return c.toString(16)})},a}(),AppInsightsStorage=function(){function a(b){var c=this;this._config=Tools.extend(a.defaultConfig,b),this._self=this._config,this._prefix=this._config.prefix,this._cookie=this._config.cookie,this._notify=this._config.notify,this._storageType=this._config.storageType,this._$rootScope=this._config.rootScope,this._$window=this._config.window,this._$document=this._config.document,this._$parse=this._config.parse,this._$document?this._$document[0]&&(this._$document=this._$document[0]):this._$document=document,"."!==this._prefix.substr(-1)&&(this._prefix=this._prefix?this._prefix+".":""),this._deriveQualifiedKey=function(a){return c._prefix+a}}return a.prototype.isStringNumber=function(a){return/^-?\d+\.?\d*$/.test(a.replace(/["']/g,""))},a.prototype.browserSupportsLocalStorage=function(){try{var a=this._storageType in this._$window&&null!==this._$window[this._storageType],b=this._deriveQualifiedKey("__"+Math.round(1e7*Math.random()));return a&&(this._webStorage=this._$window[this._storageType],this._webStorage.setItem(b,""),this._webStorage.removeItem(b)),a}catch(c){return this._storageType="cookie",this._$rootScope.$broadcast("AngularAppInsights.Storage.notification.error",c.message),!1}},a.prototype.browserSupportsCookies=function(){try{return this._$window.navigator.cookieEnabled||"cookie"in this._$document&&(this._$document.cookie.length>0||(this._$document.cookie="test").indexOf.call(this._$document.cookie,"test")>-1)}catch(a){return this._$rootScope.$broadcast("AngularAppInsights.Storage.notification.error",a.message),!1}},a.prototype.addToCookies=function(a,b){if(Tools.isUndefined(b))return!1;if((Tools.isArray(b)||Tools.isObject(b))&&(b=Tools.toJson(b)),!this.browserSupportsCookies)return this._$rootScope.$broadcast("AngularAppInsights.Storage.notification.error","COOKIES_NOT_SUPPORTED"),!1;try{var c="",d=new Date,e="";if(null===b?(d.setTime(d.getTime()+-864e5),c="; expires="+d.toUTCString(),b=""):0!==this._cookie.expiry&&(d.setTime(d.getTime()+24*this._cookie.expiry*60*60*1e3),c="; expires="+d.toUTCString()),a){var f="; path="+this._cookie.path;this._cookie.domain&&(e="; domain="+this._cookie.domain),this._$document.cookie=this._deriveQualifiedKey(a)+"="+encodeURIComponent(b)+c+f+e}}catch(g){return this._$rootScope.$broadcast("AngularAppInsights.Storage.notification.error",g.message),!1}return!0},a.prototype.getFromCookies=function(a){if(!this.browserSupportsCookies)return this._$rootScope.$broadcast("AngularAppInsights.Storage.notification.error","COOKIES_NOT_SUPPORTED"),!1;for(var b=this._$document.cookie&&this._$document.cookie.split(";")||[],c=0;c-1&&a.message.split("\n").length>a.stacktrace.split("\n").length?this.parseOpera9(a):a.stack?this.parseOpera11(a):this.parseOpera10(a)},a.parseOpera9=function(a){for(var b=/Line (\d+).*script (?:in )?(\S+)/i,c=a.message.split("\n"),d=[],e=2,f=c.length;f>e;e+=2){var g=b.exec(c[e]);if(g){var h=0;d.push(new StackFrame(void 0,void 0,g[2],g[1],void 0,h++))}}return d},a.parseOpera10=function(a){for(var b=/Line (\d+).*script (?:in )?(\S+)(?:: In function (\S+))?$/i,c=a.stacktrace.split("\n"),d=[],e=0,f=c.length;f>e;e+=2){var g=b.exec(c[e]);if(g){var h=0;d.push(new StackFrame(g[3]||void 0,void 0,g[2],g[1],void 0,h++))}}return d},a.parseOpera11=function(b){var c=0;return b.stack.split("\n").filter(function(b){return!!b.match(a.firefoxSafariStackRegexp)&&!b.match(/^Error created at/)},this).map(function(b){var d,e=b.split("@"),f=a.extractLocation(e.pop()),g=e.shift()||"",h=g.replace(//,"$2").replace(/\([^\)]*\)/g,"")||void 0;g.match(/\(([^\)]*)\)/)&&(d=g.replace(/^[^\(]+\(([^\)]*)\)$/,"$1"));var i=void 0===d||"[arguments not available]"===d?void 0:d?d.split(","):"";return new StackFrame(h,i,f[0],f[1],f[2],c++)},this)},a.firefoxSafariStackRegexp=/\S+\:\d+/,a.chromeIeStackRegexp=/\s+at /,a}(),LogInterceptor=function(){function a(b,c){var d=this;this._angular=c,this._noop=this._angular.noop,a.interceptFuntion=this._noop,b.decorator("$log",["$delegate",function(a){return d._debugFn=a.debug,d._infoFn=a.info,d._warnFn=a.warn,d._errorFn=a.error,d._logFn=a.log,a.debug=c.extend(d.delegator(d._debugFn,"debug"),d._debugFn),a.info=c.extend(d.delegator(d._infoFn,"info"),d._infoFn),a.warn=c.extend(d.delegator(d._warnFn,"warn"),d._warnFn),a.error=c.extend(d.delegator(d._errorFn,"error"),d._errorFn),a.log=c.extend(d.delegator(d._logFn,"log"),d._logFn),a}])}return a.prototype.setInterceptFunction=function(b){a.interceptFuntion=b},a.prototype.getPrivateLoggingObject=function(){return{debug:Tools.isNullOrUndefined(this._debugFn)?Tools.noop:this._debugFn,info:Tools.isNullOrUndefined(this._infoFn)?Tools.noop:this._infoFn,warn:Tools.isNullOrUndefined(this._warnFn)?Tools.noop:this._warnFn,error:Tools.isNullOrUndefined(this._errorFn)?Tools.noop:this._errorFn,log:Tools.isNullOrUndefined(this._logFn)?Tools.noop:this._logFn}},a.prototype.delegator=function(b,c){var d=function(){var d=[].slice.call(arguments),e=d.join(" ");a.interceptFuntion(e,c),b.apply(null,d)};for(var e in b)d[e]=b[e];return d},a}(),ExceptionInterceptor=function(){function a(b){var c=this;a.errorOnHttpCall=!1,this._interceptFunction=Tools.noop,b.decorator("$exceptionHandler",["$delegate",function(b){return c._origExceptionHandler=b,function(b,d){a.errorOnHttpCall||c._interceptFunction(b,d),c._origExceptionHandler(b,d)}}])}return a.prototype.setInterceptFunction=function(a){this._interceptFunction=a},a.prototype.getPrivateExceptionHanlder=function(){return Tools.isNullOrUndefined(this._origExceptionHandler)?Tools.noop:this._origExceptionHandler},a}(),Options=function(){function a(){this.applicationName="",this.autoPageViewTracking=!0,this.autoStateChangeTracking=!1,this.autoLogTracking=!0,this.autoExceptionTracking=!0,this.sessionInactivityTimeout=18e5,this.instrumentationKey="",this.developerMode=!1,this.properties={}}return a}(),HttpRequest=function(){function a(){}return a.prototype.send=function(a,b,c){var d=new XMLHttpRequest;d.onerror=function(){c(0)},d.onload=function(){200==d.status?b():c(d.status)},d.open(a.method,a.url,!0);for(var e in a.headers)d.setRequestHeader(e,a.headers[e]);d.send(JSON.stringify(a.data))},a}(),HttpRequestOptions=function(){function a(){}return a}(),ApplicationInsights=function(){function a(a,b,c,d,e,f,g,h){var i=this;this._sessionKey="$$appInsights__session",this._userKey="$$appInsights__uuid",this._version="angular:0.3.0",this._analyticsServiceUrl="https://dc.services.visualstudio.com/v2/track",this._contentType="application/json",this._localStorage=a,this._locale=b,this._window=c,this._location=d,this._httpRequestFactory=g,this.options=h,this._log=e.getPrivateLoggingObject(),this._exceptionHandler=f.getPrivateExceptionHanlder(),this._logInterceptor=e,this._exceptionInterceptor=f,this.options.autoLogTracking&&this._logInterceptor.setInterceptFunction(function(a,b,c){return i.trackTraceMessage(a,b,c)}),this.options.autoExceptionTracking&&this._exceptionInterceptor.setInterceptFunction(function(a,b,c){return i.trackException(a,b,c)})}return a.prototype.getUserId=function(){var a=this._localStorage.get(this._userKey);return Tools.isNullOrUndefined(a)&&(a=Tools.generateGuid(),this._localStorage.set(this._userKey,a)),a},a.prototype.setUserId=function(a){this._localStorage.set(this._userKey,a)},a.prototype.getOperationId=function(){var a="$$appInsights__operationid",b=Tools.generateGuid();return this._localStorage.set(a,b),b},a.prototype.getStoredOperationId=function(){var a="$$appInsights__operationid",b=this._localStorage.get(a);return Tools.isNullOrUndefined(b)&&(b=this.getOperationId()),b},a.prototype.makeNewSession=function(a){var b={id:a||Tools.generateGuid(),accessed:(new Date).getTime()};return this._localStorage.set(this._sessionKey,b),b},a.prototype.getSessionId=function(){var a=this._localStorage.get(this._sessionKey);if(Tools.isNullOrUndefined(a))a=this.makeNewSession(null);else{var b=Tools.isNullOrUndefined(a.accessed)?0:a.accessed,c=(new Date).getTime();c-b>this.options.sessionInactivityTimeout?a=this.makeNewSession(null):(a.accessed=c,this._localStorage.set(this._sessionKey,a))}return a.id},a.prototype.validateMeasurements=function(a){if(Tools.isNullOrUndefined(a))return null;if(!Tools.isObject(a))return this._log.warn("The value of the measurements parameter must be an object consisting of a string/number pairs."),null;var b={};for(var c in a)Tools.isNumber(a[c])?b[c]=a[c]:this._log.warn("The value of measurement "+c+" is not a number.");return b},a.prototype.validateProperties=function(a){if(Tools.isNullOrUndefined(a))return null;if(!Tools.isObject(a))return this._log.warn("The value of the properties parameter must be an object consisting of a string/string pairs."),null;var b={};for(var c in a){var d=a[c];Tools.isNullOrUndefined(d)||Tools.isObject(d)||Tools.isArray(d)?this._log.warn("The value of property "+c+" could not be determined to be a string or number."):b[c]=d}return b},a.prototype.validateDuration=function(a){return Tools.isNullOrUndefined(a)?null:!Tools.isNumber(a)||0>a?(this._log.warn("The value of the durations parameter must be a positive number"),null):a},a.prototype.validateSeverityLevel=function(a){var b=["debug","info","warn","error"],c=b.indexOf(a);return c>-1?c:0},a.prototype.sendData=function(a){if(this.options.developerMode)return void console.log(a);var b=this._httpRequestFactory(),c={};c.Accept=this._contentType,c["Content-Type"]=this._contentType;var d={method:"POST",url:this._analyticsServiceUrl,headers:c,data:a};try{b.send(d,function(){ExceptionInterceptor.errorOnHttpCall=!1},function(){ExceptionInterceptor.errorOnHttpCall=!0})}catch(e){}},a.prototype.trackPageView=function(b,c,d,e,f){var g=this.generateAppInsightsData(a.names.pageViews,a.types.pageViews,{ver:1,url:Tools.isNullOrUndefined(c)?this._location.absUrl():c,name:Tools.isNullOrUndefined(b)?this._location.path():b,properties:this.validateProperties(d),measurements:this.validateMeasurements(e),duration:this.validateDuration(f)});this.sendData(g)},a.prototype.trackEvent=function(b,c,d){var e=this.generateAppInsightsData(a.names.events,a.types.events,{ver:1,name:b,properties:this.validateProperties(c),measurements:this.validateMeasurements(d)});this.sendData(e)},a.prototype.trackTraceMessage=function(b,c,d){if(!Tools.isNullOrUndefined(b)&&Tools.isString(b)){this.options.properties&&(d=d||{},Tools.extend(d,this.options.properties));var e=this.generateAppInsightsData(a.names.traceMessage,a.types.traceMessage,{ver:1,message:b,severityLevel:this.validateSeverityLevel(c),properties:this.validateProperties(d)});this.sendData(e)}},a.prototype.trackMetric=function(b,c,d){this.options.properties&&(d=d||{},Tools.extend(d,this.options.properties));var e=this.generateAppInsightsData(a.names.metrics,a.types.metrics,{ver:1,metrics:[{name:b,value:c}],properties:this.validateProperties(d)});this.sendData(e)},a.prototype.trackException=function(b,c,d){if(!Tools.isNullOrUndefined(b)){var e=StackParser.parse(b),f={};Tools.copy(this.options.properties,f),d&&(d=d||{},Tools.extend(f,d));var g=this.generateAppInsightsData(a.names.exception,a.types.exception,{ver:1,handledAt:"Unhandled",exceptions:[{typeName:b.name||"Unhandled",message:b.message||"Unhandled",stack:b.stack||"Unhandled",parsedStack:e,hasFullStack:!Tools.isNullOrUndefined(e)}],properties:f});this.sendData(g)}},a.prototype.defineUser=function(a){this.setUserId(a)},a.prototype.defineSession=function(a){this.makeNewSession(a)},a.prototype.generateAppInsightsData=function(b,c,d){return this._commonProperties&&(d.properties=d.properties||{},Tools.extend(d.properties,this._commonProperties)),{name:b,time:(new Date).toISOString(),ver:1,iKey:this.options.instrumentationKey,user:{id:this.getUserId(),type:"User"},session:{id:this.getSessionId()},operation:{id:b===a.names.pageViews?this.getOperationId():this.getStoredOperationId()},device:{id:"browser",locale:this._locale.id,resolution:this._window.screen.availWidth+"x"+this._window.screen.availHeight,type:"Browser"},internal:{sdkVersion:this._version},data:{type:c,item:d}}},a.prototype.setCommonProperties=function(a){this.validateProperties(a),this._commonProperties=this._commonProperties||{},Tools.extend(this._commonProperties,a)},a.namespace="Microsoft.ApplicationInsights.",a.names={pageViews:a.namespace+"Pageview",traceMessage:a.namespace+"Message",events:a.namespace+"Event",metrics:a.namespace+"Metric",exception:a.namespace+"Exception"},a.types={pageViews:a.namespace+"PageViewData",traceMessage:a.namespace+"MessageData",events:a.namespace+"EventData",metrics:a.namespace+"MetricData",exception:a.namespace+"ExceptionData"},a}(),httpRequestService=angular.module("$$ApplicationInsights-HttpRequestModule",[]);httpRequestService.factory("$$applicationInsightsHttpRequestService",function(){return function(){return new HttpRequest}});var angularAppInsights=angular.module("ApplicationInsightsModule",["$$ApplicationInsights-HttpRequestModule"]),logInterceptor,exceptionInterceptor,tools=new Tools(angular);angularAppInsights.config(["$provide","$httpProvider",function(a,b){logInterceptor=new LogInterceptor(a,angular),exceptionInterceptor=new ExceptionInterceptor(a),b&&b.interceptors&&b.interceptors.push("ApplicationInsightsInterceptor")}]),angularAppInsights.provider("applicationInsightsService",function(){return new AppInsightsProvider}),angularAppInsights.run(["$rootScope","$location","applicationInsightsService",function(a,b,c){var d,e;a.$on("$locationChangeStart",function(){c.options.autoPageViewTracking&&!c.options.autoStateChangeTracking&&(d=(new Date).getTime())}),a.$on("$locationChangeSuccess",function(a,e){if(c.options.autoPageViewTracking&&!c.options.autoStateChangeTracking){var f=(new Date).getTime()-d,g=c.options.applicationName+b.path(),h=c.options.properties;e&&(g+="#"+e),c.trackPageView(g,null,h,null,f)}}),a.$on("$stateChangeStart",function(){c.options.autoPageViewTracking&&c.options.autoStateChangeTracking&&(e=(new Date).getTime())}),a.$on("$stateChangeSuccess",function(){if(c.options.autoPageViewTracking&&c.options.autoStateChangeTracking){var a=(new Date).getTime()-e,d=c.options.applicationName+b.path(),f=c.options.properties;c.trackPageView(d,null,f,null,a)}})}]),angularAppInsights.factory("ApplicationInsightsInterceptor",["applicationInsightsService","$q",function(a){return{request:function(b){return b?(b.headers=b.headers||{},b.headers["x-ms-request-root-id"]=a.getStoredOperationId(),b.headers["x-ms-request-id"]=a.getUserId(),b):void 0}}}]);var AppInsightsProvider=function(){function a(){var a=this;this._options=new Options,this.$get=["$locale","$window","$location","$rootScope","$parse","$document","$$applicationInsightsHttpRequestService",function(b,c,d,e,f,g,h){var i=new AppInsightsStorage({window:c,rootScope:e,document:g,parse:f});return new ApplicationInsights(i,b,c,d,logInterceptor,exceptionInterceptor,h,a._options)}]}return a.prototype.configure=function(a,b){Tools.extend(this._options,b),this._options.instrumentationKey=a},a}(); \ No newline at end of file +var Tools=function(){function a(b){a.isDefined=b.isDefined,a.isUndefined=b.isUndefined,a.isObject=b.isObject,a.isArray=b.isArray,a.isString=b.isString,a.extend=b.extend,a.toJson=b.toJson,a.fromJson=b.fromJson,a.forEach=b.forEach,a.copy=b.copy,a.noop=b.noop}return a.isNullOrUndefined=function(b){return a.isUndefined(b)||null===b},a.isNumber=function(a){return!isNaN(parseFloat(a))&&isFinite(a)},a.generateGuid=function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(a){var b=16*Math.random()|0,c="x"==a?b:3&b|8;return c.toString(16)})},a}(),AppInsightsStorage=function(){function a(b){var c=this;this._config=Tools.extend(a.defaultConfig,b),this._self=this._config,this._prefix=this._config.prefix,this._cookie=this._config.cookie,this._notify=this._config.notify,this._storageType=this._config.storageType,this._$rootScope=this._config.rootScope,this._$window=this._config.window,this._$document=this._config.document,this._$parse=this._config.parse,this._$document?this._$document[0]&&(this._$document=this._$document[0]):this._$document=document,"."!==this._prefix.substr(-1)&&(this._prefix=this._prefix?this._prefix+".":""),this._deriveQualifiedKey=function(a){return c._prefix+a}}return a.prototype.isStringNumber=function(a){return/^-?\d+\.?\d*$/.test(a.replace(/["']/g,""))},a.prototype.browserSupportsLocalStorage=function(){try{var a=this._storageType in this._$window&&null!==this._$window[this._storageType],b=this._deriveQualifiedKey("__"+Math.round(1e7*Math.random()));return a&&(this._webStorage=this._$window[this._storageType],this._webStorage.setItem(b,""),this._webStorage.removeItem(b)),a}catch(c){return this._storageType="cookie",this._$rootScope.$broadcast("AngularAppInsights.Storage.notification.error",c.message),!1}},a.prototype.browserSupportsCookies=function(){try{return this._$window.navigator.cookieEnabled||"cookie"in this._$document&&(this._$document.cookie.length>0||(this._$document.cookie="test").indexOf.call(this._$document.cookie,"test")>-1)}catch(a){return this._$rootScope.$broadcast("AngularAppInsights.Storage.notification.error",a.message),!1}},a.prototype.addToCookies=function(a,b){if(Tools.isUndefined(b))return!1;if((Tools.isArray(b)||Tools.isObject(b))&&(b=Tools.toJson(b)),!this.browserSupportsCookies)return this._$rootScope.$broadcast("AngularAppInsights.Storage.notification.error","COOKIES_NOT_SUPPORTED"),!1;try{var c="",d=new Date,e="";if(null===b?(d.setTime(d.getTime()+-864e5),c="; expires="+d.toUTCString(),b=""):0!==this._cookie.expiry&&(d.setTime(d.getTime()+24*this._cookie.expiry*60*60*1e3),c="; expires="+d.toUTCString()),a){var f="; path="+this._cookie.path;this._cookie.domain&&(e="; domain="+this._cookie.domain),this._$document.cookie=this._deriveQualifiedKey(a)+"="+encodeURIComponent(b)+c+f+e}}catch(g){return this._$rootScope.$broadcast("AngularAppInsights.Storage.notification.error",g.message),!1}return!0},a.prototype.getFromCookies=function(a){if(!this.browserSupportsCookies)return this._$rootScope.$broadcast("AngularAppInsights.Storage.notification.error","COOKIES_NOT_SUPPORTED"),!1;for(var b=this._$document.cookie&&this._$document.cookie.split(";")||[],c=0;c-1&&a.message.split("\n").length>a.stacktrace.split("\n").length?this.parseOpera9(a):a.stack?this.parseOpera11(a):this.parseOpera10(a)},a.parseOpera9=function(a){for(var b=/Line (\d+).*script (?:in )?(\S+)/i,c=a.message.split("\n"),d=[],e=2,f=c.length;f>e;e+=2){var g=b.exec(c[e]);if(g){var h=0;d.push(new StackFrame(void 0,void 0,g[2],g[1],void 0,h++))}}return d},a.parseOpera10=function(a){for(var b=/Line (\d+).*script (?:in )?(\S+)(?:: In function (\S+))?$/i,c=a.stacktrace.split("\n"),d=[],e=0,f=c.length;f>e;e+=2){var g=b.exec(c[e]);if(g){var h=0;d.push(new StackFrame(g[3]||void 0,void 0,g[2],g[1],void 0,h++))}}return d},a.parseOpera11=function(b){var c=0;return b.stack.split("\n").filter(function(b){return!!b.match(a.firefoxSafariStackRegexp)&&!b.match(/^Error created at/)},this).map(function(b){var d,e=b.split("@"),f=a.extractLocation(e.pop()),g=e.shift()||"",h=g.replace(//,"$2").replace(/\([^\)]*\)/g,"")||void 0;g.match(/\(([^\)]*)\)/)&&(d=g.replace(/^[^\(]+\(([^\)]*)\)$/,"$1"));var i=void 0===d||"[arguments not available]"===d?void 0:d?d.split(","):"";return new StackFrame(h,i,f[0],f[1],f[2],c++)},this)},a.firefoxSafariStackRegexp=/\S+\:\d+/,a.chromeIeStackRegexp=/\s+at /,a}(),LogInterceptor=function(){function a(b,c){var d=this;this._angular=c,this._noop=this._angular.noop,a.interceptFuntion=this._noop,b.decorator("$log",["$delegate",function(a){return d._debugFn=a.debug,d._infoFn=a.info,d._warnFn=a.warn,d._errorFn=a.error,d._logFn=a.log,a.debug=c.extend(d.delegator(d._debugFn,"debug"),d._debugFn),a.info=c.extend(d.delegator(d._infoFn,"info"),d._infoFn),a.warn=c.extend(d.delegator(d._warnFn,"warn"),d._warnFn),a.error=c.extend(d.delegator(d._errorFn,"error"),d._errorFn),a.log=c.extend(d.delegator(d._logFn,"log"),d._logFn),a}])}return a.prototype.setInterceptFunction=function(b){a.interceptFuntion=b},a.prototype.getPrivateLoggingObject=function(){return{debug:Tools.isNullOrUndefined(this._debugFn)?Tools.noop:this._debugFn,info:Tools.isNullOrUndefined(this._infoFn)?Tools.noop:this._infoFn,warn:Tools.isNullOrUndefined(this._warnFn)?Tools.noop:this._warnFn,error:Tools.isNullOrUndefined(this._errorFn)?Tools.noop:this._errorFn,log:Tools.isNullOrUndefined(this._logFn)?Tools.noop:this._logFn}},a.prototype.delegator=function(b,c){var d=function(){var d=[].slice.call(arguments),e=d.join(" ");a.interceptFuntion(e,c),b.apply(null,d)};for(var e in b)d[e]=b[e];return d},a}(),ExceptionInterceptor=function(){function a(b){var c=this;a.errorOnHttpCall=!1,this._interceptFunction=Tools.noop,b.decorator("$exceptionHandler",["$delegate",function(b){return c._origExceptionHandler=b,function(b){a.errorOnHttpCall||c._interceptFunction(b),c._origExceptionHandler(b)}}])}return a.prototype.setInterceptFunction=function(a){this._interceptFunction=a},a.prototype.getPrivateExceptionHanlder=function(){return Tools.isNullOrUndefined(this._origExceptionHandler)?Tools.noop:this._origExceptionHandler},a}(),Options=function(){function a(){this.applicationName="",this.autoPageViewTracking=!0,this.autoStateChangeTracking=!1,this.autoLogTracking=!0,this.autoExceptionTracking=!0,this.sessionInactivityTimeout=18e5,this.instrumentationKey="",this.developerMode=!1,this.properties={}}return a}(),HttpRequest=function(){function a(){}return a.prototype.send=function(a,b,c){var d=new XMLHttpRequest;d.onerror=function(){c(0)},d.onload=function(){200==d.status?b():c(d.status)},d.open(a.method,a.url,!0);for(var e in a.headers)d.setRequestHeader(e,a.headers[e]);d.send(JSON.stringify(a.data))},a}(),HttpRequestOptions=function(){function a(){}return a}(),ApplicationInsights=function(){function a(a,b,c,d,e,f,g,h){var i=this;this._sessionKey="$$appInsights__session",this._userKey="$$appInsights__uuid",this._deviceKey="$$appInsights__device",this._deviceTypeKey="$$appInsights__device__type",this._version="angular:0.3.0",this._analyticsServiceUrl="https://dc.services.visualstudio.com/v2/track",this._contentType="application/json",this._localStorage=a,this._locale=b,this._window=c,this._location=d,this._httpRequestFactory=g,this.options=h,this._log=e.getPrivateLoggingObject(),this._exceptionHandler=f.getPrivateExceptionHanlder(),this._logInterceptor=e,this._exceptionInterceptor=f,this.options.autoLogTracking&&this._logInterceptor.setInterceptFunction(function(a,b,c){return i.trackTraceMessage(a,b,c)}),this.options.autoExceptionTracking&&this._exceptionInterceptor.setInterceptFunction(function(a,b){return i.trackException(a,b)})}return a.prototype.getUserId=function(){var a=this._localStorage.get(this._userKey);return Tools.isNullOrUndefined(a)&&(a=Tools.generateGuid(),this._localStorage.set(this._userKey,a)),a},a.prototype.setUserId=function(a){this._localStorage.set(this._userKey,a)},a.prototype.getDeviceId=function(){var a=this._localStorage.get(this._deviceKey);return Tools.isNullOrUndefined(a)&&(a=Tools.generateGuid(),this._localStorage.set(this._deviceKey,a)),a},a.prototype.getDeviceType=function(){var a=this._localStorage.get(this._deviceTypeKey);return Tools.isNullOrUndefined(a)&&(a="Browser"),a},a.prototype.setDeviceInfo=function(a,b){this._localStorage.set(this._deviceKey,a),this._localStorage.set(this._deviceTypeKey,b)},a.prototype.getOperationId=function(){var a="$$appInsights__operationid",b=Tools.generateGuid();return this._localStorage.set(a,b),b},a.prototype.getStoredOperationId=function(){var a="$$appInsights__operationid",b=this._localStorage.get(a);return Tools.isNullOrUndefined(b)&&(b=this.getOperationId()),b},a.prototype.makeNewSession=function(a){var b={id:a||Tools.generateGuid(),accessed:(new Date).getTime()};return this._localStorage.set(this._sessionKey,b),b},a.prototype.getSessionId=function(){var a=this._localStorage.get(this._sessionKey);if(Tools.isNullOrUndefined(a))a=this.makeNewSession(null);else{var b=Tools.isNullOrUndefined(a.accessed)?0:a.accessed,c=(new Date).getTime();c-b>this.options.sessionInactivityTimeout?a=this.makeNewSession(null):(a.accessed=c,this._localStorage.set(this._sessionKey,a))}return a.id},a.prototype.validateMeasurements=function(a){if(Tools.isNullOrUndefined(a))return null;if(!Tools.isObject(a))return this._log.warn("The value of the measurements parameter must be an object consisting of a string/number pairs."),null;var b={};for(var c in a)Tools.isNumber(a[c])?b[c]=a[c]:this._log.warn("The value of measurement "+c+" is not a number.");return b},a.prototype.validateProperties=function(a){if(Tools.isNullOrUndefined(a))return null;if(!Tools.isObject(a))return this._log.warn("The value of the properties parameter must be an object consisting of a string/string pairs."),null;var b={};for(var c in a){var d=a[c];Tools.isNullOrUndefined(d)||Tools.isObject(d)||Tools.isArray(d)?this._log.warn("The value of property "+c+" could not be determined to be a string or number."):b[c]=d}return b},a.prototype.validateDuration=function(a){return Tools.isNullOrUndefined(a)?null:!Tools.isNumber(a)||0>a?(this._log.warn("The value of the durations parameter must be a positive number"),null):a},a.prototype.validateSeverityLevel=function(a){var b=["debug","info","warn","error"],c=b.indexOf(a);return c>-1?c:0},a.prototype.sendData=function(a){if(this.options.developerMode)return void console.log(a);var b=this._httpRequestFactory(),c={};c.Accept=this._contentType,c["Content-Type"]=this._contentType;var d={method:"POST",url:this._analyticsServiceUrl,headers:c,data:a};try{b.send(d,function(){ExceptionInterceptor.errorOnHttpCall=!1},function(){ExceptionInterceptor.errorOnHttpCall=!0})}catch(e){}},a.prototype.trackPageView=function(b,c,d,e,f){var g=this.generateAppInsightsData(a.names.pageViews,a.types.pageViews,{ver:1,url:Tools.isNullOrUndefined(c)?this._location.absUrl():c,name:Tools.isNullOrUndefined(b)?this._location.path():b,properties:this.validateProperties(d),measurements:this.validateMeasurements(e),duration:this.validateDuration(f)});this.sendData(g)},a.prototype.trackEvent=function(b,c,d){var e=this.generateAppInsightsData(a.names.events,a.types.events,{ver:1,name:b,properties:this.validateProperties(c),measurements:this.validateMeasurements(d)});this.sendData(e)},a.prototype.trackTraceMessage=function(b,c,d){if(!Tools.isNullOrUndefined(b)&&Tools.isString(b)){this.options.properties&&(d=d||{},Tools.extend(d,this.options.properties));var e=this.generateAppInsightsData(a.names.traceMessage,a.types.traceMessage,{ver:1,message:b,severityLevel:this.validateSeverityLevel(c),properties:this.validateProperties(d)});this.sendData(e)}},a.prototype.trackMetric=function(b,c,d){this.options.properties&&(d=d||{},Tools.extend(d,this.options.properties));var e=this.generateAppInsightsData(a.names.metrics,a.types.metrics,{ver:1,metrics:[{name:b,value:c}],properties:this.validateProperties(d)});this.sendData(e)},a.prototype.trackException=function(b,c){if(!Tools.isNullOrUndefined(b)){var d=StackParser.parse(b),e={};Tools.copy(this.options.properties,e),c&&(c=c||{},Tools.extend(e,c));var f=this.generateAppInsightsData(a.names.exception,a.types.exception,{ver:1,handledAt:"Unhandled",exceptions:[{typeName:b.name||"Unhandled",message:b.message||"Unhandled",stack:b.stack||"Unhandled",parsedStack:d,hasFullStack:!Tools.isNullOrUndefined(d)}],properties:e});this.sendData(f)}},a.prototype.defineUser=function(a){this.setUserId(a)},a.prototype.defineSession=function(a){this.makeNewSession(a)},a.prototype.defineDevice=function(a,b){this.setDeviceInfo(a,b)},a.prototype.generateAppInsightsData=function(b,c,d){return this._commonProperties&&(d.properties=d.properties||{},Tools.extend(d.properties,this._commonProperties)),{name:b,time:(new Date).toISOString(),ver:1,iKey:this.options.instrumentationKey,user:{id:this.getUserId(),type:"User"},session:{id:this.getSessionId()},operation:{id:b===a.names.pageViews?this.getOperationId():this.getStoredOperationId()},device:{id:this.getDeviceId(),locale:this._locale.id,resolution:this._window.screen.availWidth+"x"+this._window.screen.availHeight,type:this.getDeviceType()},internal:{sdkVersion:this._version},data:{type:c,item:d}}},a.prototype.setCommonProperties=function(a){this.validateProperties(a),this._commonProperties=this._commonProperties||{},Tools.extend(this._commonProperties,a)},a.namespace="Microsoft.ApplicationInsights.",a.names={pageViews:a.namespace+"Pageview",traceMessage:a.namespace+"Message",events:a.namespace+"Event",metrics:a.namespace+"Metric",exception:a.namespace+"Exception"},a.types={pageViews:a.namespace+"PageViewData",traceMessage:a.namespace+"MessageData",events:a.namespace+"EventData",metrics:a.namespace+"MetricData",exception:a.namespace+"ExceptionData"},a}(),httpRequestService=angular.module("$$ApplicationInsights-HttpRequestModule",[]);httpRequestService.factory("$$applicationInsightsHttpRequestService",function(){return function(){return new HttpRequest}});var angularAppInsights=angular.module("ApplicationInsightsModule",["$$ApplicationInsights-HttpRequestModule"]),logInterceptor,exceptionInterceptor,tools=new Tools(angular);angularAppInsights.config(["$provide","$httpProvider",function(a,b){logInterceptor=new LogInterceptor(a,angular),exceptionInterceptor=new ExceptionInterceptor(a),b&&b.interceptors&&b.interceptors.push("ApplicationInsightsInterceptor")}]),angularAppInsights.provider("applicationInsightsService",function(){return new AppInsightsProvider}),angularAppInsights.run(["$rootScope","$location","applicationInsightsService",function(a,b,c){var d,e;a.$on("$locationChangeStart",function(){c.options.autoPageViewTracking&&!c.options.autoStateChangeTracking&&(d=(new Date).getTime())}),a.$on("$locationChangeSuccess",function(a,e){if(c.options.autoPageViewTracking&&!c.options.autoStateChangeTracking){var f=(new Date).getTime()-d,g=c.options.applicationName+b.path(),h=c.options.properties;e&&(g+="#"+e),c.trackPageView(g,null,h,null,f)}}),a.$on("$stateChangeStart",function(){c.options.autoPageViewTracking&&c.options.autoStateChangeTracking&&(e=(new Date).getTime())}),a.$on("$stateChangeSuccess",function(){if(c.options.autoPageViewTracking&&c.options.autoStateChangeTracking){var a=(new Date).getTime()-e,d=c.options.applicationName+b.path(),f=c.options.properties;c.trackPageView(d,null,f,null,a)}})}]),angularAppInsights.factory("ApplicationInsightsInterceptor",["applicationInsightsService","$q",function(a){return{request:function(b){return b?(b.headers=b.headers||{},b.headers["x-ms-request-root-id"]=a.getStoredOperationId(),b.headers["x-ms-request-id"]=a.getUserId(),b):void 0}}}]);var AppInsightsProvider=function(){function a(){var a=this;this._options=new Options,this.$get=["$locale","$window","$location","$rootScope","$parse","$document","$$applicationInsightsHttpRequestService",function(b,c,d,e,f,g,h){var i=new AppInsightsStorage({window:c,rootScope:e,document:g,parse:f});return new ApplicationInsights(i,b,c,d,logInterceptor,exceptionInterceptor,h,a._options)}]}return a.prototype.configure=function(a,b){Tools.extend(this._options,b),this._options.instrumentationKey=a},a}(); \ No newline at end of file diff --git a/src/ApplicationInsights.ts b/src/ApplicationInsights.ts index e651fdf..ee73e85 100644 --- a/src/ApplicationInsights.ts +++ b/src/ApplicationInsights.ts @@ -22,6 +22,8 @@ class ApplicationInsights { private _exceptionInterceptor: ExceptionInterceptor; private _sessionKey = "$$appInsights__session"; private _userKey = "$$appInsights__uuid"; + private _deviceKey = "$$appInsights__device"; + private _deviceTypeKey = "$$appInsights__device__type"; options: Options; private static namespace = "Microsoft.ApplicationInsights."; @@ -73,7 +75,7 @@ class ApplicationInsights { this._logInterceptor.setInterceptFunction((message, level, properties?) => this.trackTraceMessage(message, level, properties)); } if (this.options.autoExceptionTracking) { - this._exceptionInterceptor.setInterceptFunction((exception, cause, exceptionProperties) => this.trackException(exception, cause, exceptionProperties)); + this._exceptionInterceptor.setInterceptFunction((exception, exceptionProperties) => this.trackException(exception, exceptionProperties)); } } @@ -91,6 +93,32 @@ class ApplicationInsights { this._localStorage.set(this._userKey, userId); } + private getDeviceId() { + var id = this._localStorage.get(this._deviceKey); + + if (Tools.isNullOrUndefined(id)) { + id = Tools.generateGuid(); + this._localStorage.set(this._deviceKey, id); + } + + return id; + } + + private getDeviceType() { + var type = this._localStorage.get(this._deviceTypeKey); + + if (Tools.isNullOrUndefined(type)) { + type = "Browser"; + } + + return type; + } + + private setDeviceInfo(id, type) { + this._localStorage.set(this._deviceKey, id); + this._localStorage.set(this._deviceTypeKey, type); + } + private getOperationId() { const uuidKey = "$$appInsights__operationid"; var uuid = Tools.generateGuid(); @@ -325,7 +353,7 @@ class ApplicationInsights { this.sendData(data); } - trackException(exception, cause, exceptionProperties) { + trackException(exception, exceptionProperties) { if (Tools.isNullOrUndefined(exception)) { return; } @@ -350,7 +378,7 @@ class ApplicationInsights { typeName: exception.name || "Unhandled", message: exception.message || "Unhandled", stack: exception.stack || "Unhandled", - parsedStack: parsedStack, + parsedStack: parsedStack, hasFullStack: !Tools.isNullOrUndefined(parsedStack) } ], @@ -367,13 +395,17 @@ class ApplicationInsights { this.makeNewSession(sessionId); } + defineDevice(id, type) { + this.setDeviceInfo(id, type); + } + private generateAppInsightsData(payloadName, payloadDataType, payloadData) { if (this._commonProperties) { payloadData.properties = payloadData.properties || {}; Tools.extend(payloadData.properties, this._commonProperties); } - + return { name: payloadName, time: new Date().toISOString(), @@ -390,10 +422,10 @@ class ApplicationInsights { id: payloadName === ApplicationInsights.names.pageViews ? this.getOperationId() : this.getStoredOperationId() }, device: { - id: "browser", + id: this.getDeviceId(), locale: this._locale.id, resolution: this._window.screen.availWidth + "x" + this._window.screen.availHeight, - type: "Browser" + type: this.getDeviceType() }, internal: { sdkVersion: this._version diff --git a/src/ExceptionInterceptor.ts b/src/ExceptionInterceptor.ts index 5069ebc..8a45aeb 100644 --- a/src/ExceptionInterceptor.ts +++ b/src/ExceptionInterceptor.ts @@ -27,14 +27,14 @@ $provide.decorator('$exceptionHandler', [ '$delegate', ($delegate) => { this._origExceptionHandler = $delegate; - return (exception, cause) => { + return (exception) => { // track the call // ... only if there is no active issues/errors sending data over http, in order to prevent an infinite loop. if (!ExceptionInterceptor.errorOnHttpCall) { - this._interceptFunction(exception, cause); + this._interceptFunction(exception); } // Call the original - this._origExceptionHandler(exception, cause); + this._origExceptionHandler(exception); }; } ]);