/*! * 1DS JS SDK Analytics Web, 3.2.8 * Copyright (c) Microsoft and contributors. All rights reserved. * (Microsoft Internal Only) */ var e=this,t=function(n){"use strict";var u="function",s="object",fe="undefined",f="prototype",l="hasOwnProperty",g=Object,v=g[f],y=g.assign,T=g.create,e=g.defineProperty,I=v[l],b=null;function C(e){e=!1===(e=void 0===e||e)?null:b;return e||((e=(e=(e=typeof globalThis!==fe?globalThis:e)||typeof self===fe?e:self)||typeof window===fe?e:window)||typeof global===fe||(e=global),b=e),e}function S(e){throw new TypeError(e)}function M(e){var t;return T?T(e):null==e?{}:((t=typeof e)!==s&&t!==u&&S("Object prototype may only be an Object:"+e),n[f]=e,new n);function n(){}}(C()||{}).Symbol,(C()||{}).Reflect;var N=y||function(e){for(var t,n=1,i=arguments.length;n=a&&!(e=i===r)){for(var o=0;o>>=0),Fi=123456789+e&Vi,Hi=987654321-e&Vi,Bi=!0}function Wi(){try{var e=2147483647&Yt();Ki((Math.random()*Ui^e)+e)}catch(t){}}function qi(e){var t=0,n=re(qn)||re(zn);return 0===(t=n&&n.getRandomValues?n.getRandomValues(new Uint32Array(1))[0]&Vi:t)&&fi()&&(Bi||Wi(),t=zi()&Vi),0===t&&(t=Math.floor(Ui*Math.random()|0)),e||(t>>>=0),t}function zi(e){var t=((Hi=36969*(65535&Hi)+(Hi>>16)&Vi)<<16)+(65535&(Fi=18e3*(65535&Fi)+(Fi>>16)&Vi))>>>0&Vi|0;return e||(t>>>=0),t}function Gi(e){void 0===e&&(e=22);for(var t=qi()>>>0,n=0,i=p;i[x]>>=6,5==++n&&(t=(qi()<<2&4294967295|3&t)>>>0,n=0);return i}var ji=e,Xi="2.8.9",Yi="."+Gi(6),Ji=0;function Qi(e){return 1===e[Me]||9===e[Me]||!+e[Me]}function $i(e,t){return xt(e+Ji+++((t=void 0!==t&&t)?"."+Xi:p)+Yi)}function Zi(e){var a={id:$i("_aiData-"+(e||p)+"."+Xi),accept:Qi,get:function(e,t,n,i){var r=e[a.id];return r?r[xt(t)]:(i&&((r=function(e,t){var n=t[e.id];if(!n){n={};try{Qi(t)&&!function(e,t,n){if(ji)try{return ji(e,t,{value:n,enumerable:!1,configurable:!0}),1}catch(i){}}(t,e.id,n)&&(t[e.id]=n)}catch(i){}}return n}(a,e))[xt(t)]=n),n)},kill:function(e,t){if(e&&e[t])try{delete e[t]}catch(n){}}};return a}var er="toGMTString",tr="toUTCString",nr="cookie",ir="expires",rr="enabled",ar="isCookieUseDisabled",or="disableCookiesUsage",cr="_ckMgr",ur=null,sr=null,lr=null,fr=oe(),dr={},pr={};function gr(e){return!e||e.isEnabled()}function vr(e,t){return t&&e&&E(e.ignoreCookies)&&-1!==e.ignoreCookies[De](t)}function hr(e,t){var n,i;return e?n=e.getCookieMgr():t&&(n=t[Pe][cr]||mr(t)),n||(e=(e||{})[q],(i=mr[cr]||pr[cr])||(i=mr[cr]=mr(t,e),pr[cr]=i),n=i),n}function mr(e,r){Jt(n=(e=e||pr)[Pe]=e[Pe]||{},"domain",e.cookieDomain,_t,Q),Jt(n,"path",e.cookiePath||"/",null,Q),Q(n[rr])&&(t=void 0,J(e[ar])||(t=!e[ar]),J(e[or])||(t=!e[or]),n[rr]=t);var t,n,s=n,l=s.path||"/",f=s.domain,i=!1!==s[rr],d=((e={isEnabled:function(){var e=i&&yr(r),t=pr[cr];return e&&t&&d!==t?gr(t):e}})[ke]=function(e){i=!1!==e},e.set=function(e,t,n,i,r){var a,o,c,u=!1;return!gr(d)||(o=s,(c=e)&&o&&E(o.blockedCookies)&&-1!==o.blockedCookies[De](c))||vr(o,c)||(o={},-1!==(a=(c=Z(t||p))[De](";"))&&(c=Z(t[_e](0,a)),o=Tr(t[_e](a+1))),Jt(o,"domain",i||f,Zt,J),Q(n)||(a=fi(),J(o[ir])&&0<(t=Yt()+1e3*n)&&((i=new Date).setTime(t),Jt(o,ir,Ir(i,a?er:tr)||Ir(i,a?er:tr)||p,Zt)),a)||Jt(o,"max-age",p+n,null,J),(t=oi())&&"https:"===t.protocol&&(Jt(o,"secure",null,null,J),sr=null===sr?!Er((ri()||{})[Oe]):sr)&&Jt(o,"SameSite","None",null,J),Jt(o,"path",r||l,null,J),(s.setCookie||Cr)(e,br(c,o)),u=!0),u},e.get=function(e){var t=p;return gr(d)&&!vr(s,e)?(s.getCookie||function(e){var t,n=p;return fr&&(t=fr[nr]||p,lr!==t&&(dr=Tr(t),lr=t),n=Z(dr[e]||p)),n})(e):t},e.del=function(e,t){return!!gr(d)&&d.purge(e,t)},e.purge=function(e,t){var n,i=!1;return yr(r)&&((n={}).path=t||"/",n[ir]="Thu, 01 Jan 1970 00:00:01 GMT",t=n,fi()||(t["max-age"]="0"),(s.delCookie||Cr)(e,br(p,t)),i=!0),i},e);return d[cr]=d}function yr(e){if(null===ur){ur=!1;try{ur=(fr||{})[nr]!==undefined}catch(t){ue(e,2,68,"Cannot access document.cookie - "+m(t),{exception:ce(t)})}}return ur}function Tr(e){var n={};return e&&e[x]&&te(Z(e)[xe](";"),function(e){var t;(e=Z(e||p))&&(-1===(t=e[De]("="))?n[e]=null:n[Z(e[_e](0,t))]=Z(e[_e](t+1)))}),n}function Ir(e,t){return j(e[t])?e[t]():null}function br(e,t){var n=e||p;return ee(t,function(e,t){n+="; "+e+(Q(t)?p:"="+t)}),n}function Cr(e,t){fr&&(fr[nr]=e+"="+t)}function Er(e){return!(!$(e)||!Mt(e,"CPU iPhone OS 12")&&!Mt(e,"iPad; CPU OS 12")&&!(Mt(e,"Macintosh; Intel Mac OS X 10_14")&&Mt(e,"Version/")&&Mt(e,"Safari"))&&(!Mt(e,"Macintosh; Intel Mac OS X 10_14")||!kt(e,"AppleWebKit/605.1.15 (KHTML, like Gecko)"))&&!Mt(e,"Chrome/5")&&!Mt(e,"Chrome/6")&&(!Mt(e,"UnrealEngine")||Mt(e,"Chrome"))&&!Mt(e,"UCBrowser/12")&&!Mt(e,"UCBrowser/11"))}var Sr="on",Nr="attachEvent",wr="addEventListener",Ar="detachEvent",Pr="removeEventListener",Dr="events",_r="visibilitychange",Or="pagehide",xr="pageshow",kr="unload",Rr="beforeunload",Mr=$i("aiEvtPageHide"),Lr=$i("aiEvtPageShow"),Ur=/\.[\.]+/g,Vr=/[\.]+$/,Br=1,Fr=Zi("events"),Hr=/^([^.]*)(?:\.(.+)|)/;function Kr(e){return e&&e[Ue]?e[Ue](/^[\s\.]+|(?=[\s\.])[\.\s]+$/g,p):e}function Wr(e,t){t&&(n=p,E(t)?(n=p,te(t,function(e){(e=Kr(e))&&("."!==e[0]&&(e="."+e),n+=e)})):n=Kr(t),n)&&("."!==n[0]&&(n="."+n),e=(e||p)+n);var n,t=Hr.exec(e||p)||[],e={};return e[Fe]=t[1],e.ns=(t[2]||p).replace(Ur,".").replace(Vr,p)[xe](".").sort().join("."),e}function qr(e,t,n){e=Fr.get(e,Dr,{},n=void 0===n||n);return e[t]||(e[t]=[])}function zr(e,t,n,i){e&&t&&t[Fe]&&(e[Pr]?e[Pr](t[Fe],n,i):e[Ar]&&e[Ar](Sr+t[Fe],n))}function Gr(e,t,n,i){for(var r=t[x];r--;){var a=t[r];!a||n.ns&&n.ns!==a.evtName.ns||i&&!i(a)||(zr(e,a.evtName,a[He],a.capture),t[Te](r,1))}}function jr(e,t){return t?Wr("xx",E(t)?[e].concat(t):[e,t]).ns[xe]("."):e}function Xr(e,t,n,i,r){void 0===r&&(r=!1);var a,o,c=!1;if(e)try{var u,s=Wr(t,i),l=s,f=n,d=r,p=!1;(o=e)&&l&&l[Fe]&&f&&(o[wr]?(o[wr](l[Fe],f,d),p=!0):o[Nr]&&(o[Nr](Sr+l[Fe],f),p=!0)),(c=p)&&Fr.accept(e)&&((a={guid:Br++,evtName:s})[He]=n,a.capture=r,u=a,qr(e,s.type)[O](u))}catch(g){}return c}function Yr(e,t,n,i,r){if(void 0===r&&(r=!1),e)try{var a=Wr(t,i),o=!1,c=e,u=function(e){return!((!a.ns||n)&&e[He]!==n)&&(o=!0)};(s=a)[Fe]?Gr(c,qr(c,s[Fe]),s,u):(ee(l=Fr.get(c,Dr,{}),function(e,t){Gr(c,t,s,u)}),0===Gt(l)[x]&&Fr.kill(c,Dr)),o||zr(e,a,n,r)}catch(f){}var s,l}function Jr(e,t,n){var i=!1,r=ae(),r=(r&&(i=Xr(r,e,t,n),i=Xr(r.body,e,t,n)||i),oe());return r&&Xr(r,e,t,n)||i}function Qr(e,t,n,i){var r=!1;return t&&e&&0>4&15]+t[e>>8&15]+t[e>>12&15]+t[e>>16&15]+t[e>>20&15]+t[e>>24&15]+t[e>>28&15];var r=t[8+(3&qi())|0];return n[Re](0,8)+n[Re](9,4)+"4"+n[Re](13,3)+r+n[Re](16,3)+n[Re](19,12)}var oa="00000000000000000000000000000000",ca="0000000000000000";function ua(e,t,n){return e&&e[x]===t&&e!==n&&e.match(/^[\da-f]*$/)}function sa(e){return ua(e,32,oa)}function la(e){return ua(e,16,ca)}var fa=Zi("plugin");function da(e){return fa.get(e,"state",{},!0)}function pa(n,i){for(var r,e=[],t=null,a=n[Se]();a;){var o=a[he]();o&&(t&&j(t[we])&&j(o[Ze])&&t[we](o),(j(o[H])?o[H]():(r=da(o))[H])||e[O](o),t=o,a=a[Se]())}te(e,function(e){var t=n[R]();e[U](n.getCfg(),t,i,n[Se]()),r=da(e),e[R]||r[R]||(r[R]=t),r[H]=!0,delete r[Ie]})}function ga(e){return e.sort(function(e,t){var n,i=0;return t?(n=j(t[Ze]),j(e[Ze])?i=n?e[et]-t[et]:1:n&&(i=-1)):i=e?1:-1,i})}var va="TelemetryPluginChain",ha="_hasRun",ma="_getTelCtx",ya=0;function Ta(e,o,n,t){var i=null,r=[],a=(null!==t&&(i=t?function(e,t,n){for(;e;){if(e[he]()===n)return e;e=e[Se]()}return Ea([n],t[K]||{},t)}(e,n,t):e),{_next:function(){var e,t=i;return i=t?t[Se]():null,t||(e=r)&&0Na&&n[O](e)}),Aa(c,n,t)),c)),C?(-1!==(u=Ht(d,C))&&d[Te](u,1),-1!==(u=Ht(b,C))&&b[Te](u,1),C._setQueue(S)):(s=S,l=v,f=!1,C={identifier:"ChannelControllerPlugin",priority:Na,initialize:function(t,n,i,e){f=!0,te(s,function(e){e&&0>>0:0},random32:qi,mwcRandomSeed:function(e){e?Ki(e):Wi()},mwcRandom32:zi,generateW3CId:aa};function Po(){var e=Ao.call(this)||this;return e.pluginVersionStringArr=[],ie(Po,e,function(u,s){u.logger&&u.logger.queue||(u.logger=new Ni({loggingLevelConsole:1})),u.initialize=function(r,a,o,c){Li(u,function(){return"AppInsightsCore.initialize"},function(){var t=u.pluginVersionStringArr;r&&(r.endpointUrl||(r.endpointUrl="https://browser.events.data.microsoft.com/OneCollector/1.0/"),!(e=r.propertyStorageOverride)||e.getProperty&&e.setProperty||X("Invalid property storage override passed."),r.channels)&&te(r.channels,function(e){e&&te(e,function(e){e.identifier&&e.version&&(e=e.identifier+"="+e.version,t.push(e))})}),u.getWParam=function(){return"undefined"!=typeof document||r.enableWParam?0:-1},a&&te(a,function(e){e&&e.identifier&&e.version&&(e=e.identifier+"="+e.version,t.push(e))}),u.pluginVersionString=t.join(";"),u.pluginVersionStringArr=t;try{s.initialize(r,a,o,c),u.pollInternalLogs("InternalLog")}catch(i){var e=u.logger,n=ce(i);~n.indexOf("channels")&&(n+="\n - Channels must be provided through config.channels only!"),ue(e,1,514,"SDK Initialization Failed - no telemetry will be sent: "+n)}},function(){return{config:r,extensions:a,logger:o,notificationManager:c}})},u.track=function(n){Li(u,function(){return"AppInsightsCore.track"},function(){var e,t=n;t&&(t.timings=t.timings||{},t.timings.trackStart=Co(),mo(t.latency)||(t.latency=1),(e=t.ext=t.ext||{}).sdk=e.sdk||{},e.sdk.ver=so,(e=t.baseData=t.baseData||{})[uo]=e[uo]||{},(e=e[uo])[co]=e[co]||u.pluginVersionString||oo),s.track(t)},function(){return{item:n}},!n.sync)}}),e}P(Po,Ao=i),Po.__ieDyn=1;var ja=Po,Do="REAL_TIME",_o="",Oo="drop",e="requeue",xo="application/x-json-stream",ko="cache-control",Ro="content-type",Mo="kill-duration",Lo="time-delta-millis",Uo="client-version",Vo="client-id",Bo="time-delta-to-apply-millis",Fo="upload-time",Ho="apikey",Ko="AuthMsaDeviceTicket",r="AuthXToken",Wo="msfpc",qo="user";function zo(e){e=(e.ext||{}).intweb;return e&&se(e[Wo])?e[Wo]:null}function Go(e){for(var t=null,n=0;null===t&&nYt()||(delete t[e],!1)}})}Qo.__ieDyn=1;var $o=Qo,Zo=.8,ec=1.2,tc=3e3,nc=6e5;function ic(e){var t=tc*Zo;return Math.min(Math.pow(2,e)*(Math.floor(Math.random()*(tc*ec-t))+t),nc)}var rc="metadata",ac="f",oc=/\./,cc=(uc.__ieDyn=1,uc);function uc(t,e,T,n){var a="baseData",I=!!n,b=e,C={};ie(uc,this,function(m){function y(e,f,d,p,g,v,h){ee(e,function(e,t){if(t||se(t)){var n,i=d,r=e,a=g,o=f;if(I&&!p&&oc.test(e)){var c=e.split("."),u=c.length;if(1=_)):V++,1))):a)&&T(wc,[e],un.QueueFull)}function a(e,t,n){m(e,t,n),P.sendQueuedRequests(t,n)}function o(){0<=Y&&m(Y,0,O)&&P.sendQueuedRequests(0,O),0=_&&(n=!0)})}v(!0,n)},l.pause=function(){u(),U=!0,P.pause()},l.resume=function(){U=!1,P.resume(),o()},l.addResponseHandler=function(e){P._responseHandlers.push(e)},l._loadTransmitProfiles=function(e){u(),t(),W=Do,o(),ee(e,function(e,t){var n,i=t.length;2<=i&&(n=2t[1]&&(n=t[1]),t.push(n),K[e]=t)})},l.flush=function(e,t,n){void 0===e&&(e=!0),U||(n=n||1,e?null==L?(u(),m(1,0,n),L=c(function(){L=null,function i(e,t){a(1,0,t),h(),function n(e){P.isCompletelyIdle()?e():L=c(function(){L=null,n(e)},.25)}(function(){e&&e(),0t.sessionExpirationMs(),t=n-e.renewalDate>t.sessionRenewalMs();i||t?a():(!(i=u)||nu.cookieUpdateIntervaln)&&(i=t[Zu]()[Ss](0,n),ue(e,2,61,"string value is too long. It has been truncated to "+n+" characters.",{value:t},!0)),i||t}function Vs(e,t){return Ks(e,t,2048,66)}function Bs(e,t){var n;return t&&32768n&&(r=t[Ss](0,n),ue(e,2,i,"input is too long, it has been truncated to "+n+" characters.",{data:t},!0)),r||t}var Ws=oe()||{},qs=0,zs=[null,null,null,null,null];function Gs(e,t){return 0===e||0===t||Q(e)||Q(t)?null:t-e}Xs.envelopeType="Microsoft.ApplicationInsights.{0}.Event",Xs.dataType="EventData";var js=Xs;function Xs(e,t,n,i){this.aiDataContract={ver:1,name:1,properties:0,measurements:0},this.ver=2,this[ts]=Us(e,t)||Xu,this[us]=Fs(e,n),this[ss]=Hs(e,i)}var Ys="error",Js="stack",Qs="stackDetails",$s="errorSrc",Zs="message",el="description";function tl(e,t){var n=e;return n&&!$(n)&&(JSON&&JSON[is]?(n=JSON[is](e),!t||n&&"{}"!==n||(n=j(e[Zu])?e[Zu]():""+e)):n=e+" - (Missing JSON.stringify)"),n||""}function nl(e,t){var n=e;return e&&((n=n&&!$(n)&&(e[Zs]||e[el])||n)&&!$(n)&&(n=tl(n,!0)),e.filename)&&(n=n+" @"+(e.filename||"")+":"+(e.lineno||"?")+":"+(e.colno||"?")),(t&&"String"!==t&&"Object"!==t&&"Error"!==t&&-1===(n||"")[as](t)?t+": "+n:n)||""}function il(e){return e&&e.src&&$(e.src)&&e.obj&&E(e.obj)}function rl(e){var e=e||"",t=(e=$(e)?e:$(e[Js])?e[Js]:""+e)[Qu]("\n");return{src:e,obj:t}}function al(e){var t,n=null;if(e)try{e[Js]?n=rl(e[Js]):e[Ys]&&e[Ys][Js]?n=rl(e[Ys][Js]):e.exception&&e.exception[Js]?n=rl(e.exception[Js]):il(e)?n=e:il(e[Qs])?n=e[Qs]:window&&window.opera&&e[Zs]?n=function(e){for(var t=[],n=e[Qu]("\n"),i=0;i",i[Ts]=Z(n),i[Is]="",i[bs]=0,(t=n.match(pl.regex))&&5<=t[h]&&(i[ys]=Z(t[2])||i[ys],i[Is]=Z(t[4]),i[bs]=parseInt(t[5])||0)):(i[ms]=e[ms],i[ys]=e[ys],i[Ts]=e[Ts],i[Is]=e[Is],i[bs]=e[bs],i[ls]=0),i.sizeInBytes+=i.method[h],i.sizeInBytes+=i.fileName[h],i.sizeInBytes+=i.assembly[h],i[ls]+=pl.baseSize,i.sizeInBytes+=i.level.toString()[h],i.sizeInBytes+=i.line.toString()[h]}var gl=function(){this.aiDataContract={name:1,kind:0,value:1,count:0,min:0,max:0,stdDev:0},this.kind=0},vl=(hl.envelopeType="Microsoft.ApplicationInsights.{0}.Metric",hl.dataType="MetricData",hl);function hl(e,t,n,i,r,a,o,c,u){this.aiDataContract={ver:1,metrics:1,properties:0},this.ver=2;var s=new gl;s.count=0=n[h]&&(p=0),qs=p,p=(n=g).host,o||(null!=n[rs]?("/"!=((g=0===n.pathname[h]?"/":n[rs])[0]||"")&&(g="/"+g),u=n[rs],Us(t,r?r+" "+g:g)):Us(t,c))):p=a,{target:p,name:o,data:u});v.data=Vs(e,i)||n.data,v.target=Us(e,n.target),s&&(v.target="".concat(v.target," | ").concat(s)),v[ts]=Us(e,n[ts]),v[us]=Fs(e,l),v[ss]=Hs(e,f)}Cl.envelopeType="Microsoft.ApplicationInsights.{0}.Message",Cl.dataType="MessageData";var bl=Cl;function Cl(e,t,n,i,r){this.aiDataContract={ver:1,message:1,severityLevel:0,properties:0};var a=this;a.ver=2,a[ns]=Bs(e,t=t||Xu),a[us]=Fs(e,i),a[ss]=Hs(e,r),n&&(a[ds]=n)}Sl.envelopeType="Microsoft.ApplicationInsights.{0}.PageviewPerformance",Sl.dataType="PageviewPerformanceData";var El=Sl;function Sl(e,t,n,i,r,a,o){this.aiDataContract={ver:1,name:0,url:0,duration:0,perfTotal:0,networkConnect:0,sentRequest:0,receivedResponse:0,domProcessing:0,properties:0,measurements:0};var c=this;c.ver=2,c.url=Vs(e,n),c[ts]=Us(e,t)||Xu,c[us]=Fs(e,r),c[ss]=Hs(e,a),o&&(c.domProcessing=o.domProcessing,c[Cs]=o[Cs],c.networkConnect=o.networkConnect,c.perfTotal=o.perfTotal,c[Es]=o[Es],c.sentRequest=o.sentRequest)}function Nl(e,t,n,i,r,a){n=Us(i,n)||Xu,(Q(e)||Q(t)||Q(n))&&X("Input doesn't contain all required fields");var o,i="",c=(e[Yu]&&(i=e[Yu],delete e[Yu]),(o={})[ts]=n,o.time=Ft(new Date),o.iKey=i,o.ext=a||{},o.tags=[],o.data={},o.baseType=t,o.baseData=e,o);return Q(r)||ee(r,function(e,t){c.data[e]=t}),c}var wl="toString",Al="disableExceptionTracking",Pl="autoTrackPageVisitTime",Dl="overridePageViewDuration",_l="enableUnhandledPromiseRejectionTracking",Ol="samplingPercentage",xl="isStorageUseDisabled",kl="isBrowserLinkTrackingEnabled",Rl="enableAutoRouteTracking",Ml="namePrefix",Ll="disableFlushOnBeforeUnload",Y="core",Ul="dataType",Vl="envelopeType",Bl="diagLog",Fl="track",Hl="trackPageView",Kl="trackPreviousPageVisit",Wl="sendPageViewInternal",ql="sendPageViewPerformanceInternal",zl="populatePageViewPerformanceEvent",Gl="href",jl="sendExceptionInternal",Xl="exception",Yl="error",Jl="_onerror",Ql="errorSrc",$l="lineNumber",Zl="columnNumber",ef="message",tf="CreateAutoException",nf="addTelemetryInitializer",rf="duration",af="length",of="isPerformanceTimingSupported",cf="getPerformanceTiming",uf="navigationStart",sf="shouldCollectDuration",lf="isPerformanceTimingDataReady",ff="responseStart",df="requestStart",pf="loadEventEnd",gf="responseEnd",vf="connectEnd",hf="pageVisitStartTime",mf=(yf.__ieDyn=1,yf);function yf(g,v,t,h){ie(yf,this,function(e){var l,f=null,d=[],p=!1;function n(e){t&&t.flush(e)}t&&(l=t.logger),e[Hl]=function(i,r){var e,a,o,c,t,u=i.name,s=(!Q(u)&&"string"==typeof u||(e=oe(),u=i.name=e&&e.title||""),i.uri);!Q(s)&&"string"==typeof s||(e=oi(),s=i.uri=e&&e[Gl]||""),h[of]()?(a=!1,0<(c=h[cf]()[uf])&&(o=Gs(c,+new Date),h[sf](o)||(o=undefined)),Q(r)||Q(r[rf])||(t=r[rf]),!v&&isNaN(t)||(isNaN(t)&&((r=r||{})[rf]=o),g[Wl](i,r),n(!0),a=!0),r=r||{},d.push(function(){var e,t=!1;try{h[lf]()?(t=!0,e={name:u,uri:s},h[zl](e),e.isValid||a?(a||(r[rf]=e.durationMs,g[Wl](i,r)),p||(g[ql](e,r),p=!0)):(r[rf]=o,g[Wl](i,r))):0e.v?t:e).v},c),l=!0)},e.resize=function(e){f||(e=qf(function(){o&&o.captureContentUpdate({isAuto:!0,actionType:rd.RESIZE})},null,e.resize,g),Xr(ae(),"resize",e,c),f=!0)},e.onUnload=function(){function e(){o&&o.capturePageUnload({isAuto:!0})}var t;d||(Zr(e,t=((o||{}).core||{}).config.disablePageUnloadEvents,c),ta(e,t,c),d=!0)},e.teardown=function(e,t){Yr(ae(),null,null,c),Yr(oe(),null,null,c),ea(null,c),na(null,c),i()},e._processClick=n})}var Td={longNames:{isShortNames:!1,id:"data-bi-id",areaName:"data-bi-area",slotNumber:"data-bi-slot",contentName:"data-bi-name",contentSource:"data-bi-source",templateName:"data-bi-view",productId:"data-bi-product",contentType:"data-bi-type",parentId:"data-bi-parentid",parentName:"data-bi-parentname"},shortNames:{isShortNames:!0,id:"data-bi-id",areaName:"data-bi-an",slotNumber:"data-bi-sn",contentName:"data-bi-cn",contentSource:"data-bi-cs",templateName:"data-bi-tn",productId:"data-bi-pid",contentType:"data-bi-ct",parentId:"data-bi-pi",parentName:"data-bi-pn"}},Id={parentId:"parentId",parentName:"parentName"},bd={parentId:"pI",parentName:"pN"},Cd=(Ed.prototype.getMetadata=function(){var e={},t={};return go&&(t=this._getMetaDataFromDOM("awa-",!0),this._config.autoCapture)&&this._config.autoCapture.msTags&&(e=this._getMetaDataFromDOM("ms.",!1)),le(!0,t,e)},Ed.prototype.getVisibleContent=function(){var e,t,n,i,r,a=Gf(),o={top:0,bottom:a.h,left:0,right:a.w},c=[];if(e=go?document.querySelectorAll(Wf(this._contentBlobFieldNames.areaName)+","+Wf(this._contentBlobFieldNames.slotNumber)+","+Wf(this._config.biBlobAttributeTag)):null)for(var u=0;u"),lineageById:a.join(">"),lineageContainerName:t}},Ed.prototype._populateElementContentwithDataBi=function(e,t){var n={};if(!e){if(!this._config.useDefaultContentName)return n;e=t}var i=Hf(e,this._contentBlobFieldNames.areaName),i=le({},this._getAreaContent(i)),r=this._config.callback.contentName?this._config.callback.contentName(e,this._config.useDefaultContentName):"",t=this._getDefaultContentName(t,this._config.useDefaultContentName);(n={id:e.getAttribute(this._contentBlobFieldNames.id)||e.id||"",aN:i.areaName,sN:e.getAttribute(this._contentBlobFieldNames.slotNumber),cN:r||e.getAttribute(this._contentBlobFieldNames.contentName)||t||e.getAttribute("alt")||"",cS:e.getAttribute(this._contentBlobFieldNames.contentSource)||i.contentSource,tN:i.templateName,pid:e.getAttribute(this._contentBlobFieldNames.productId),cT:e.getAttribute(this._contentBlobFieldNames.contentType)||i.type,pI:e.getAttribute(this._contentBlobFieldNames.parentId),pN:e.getAttribute(this._contentBlobFieldNames.parentName)}).id&&n.aN&&n.sN&&n.cN||ue(this._traceLogger,2,515,"Invalid content blob. Missing required attributes (id, aN/area, sN/slot), cN/contentName. Content information will still be collected!"),this._contentBlobFieldNames.isShortNames||(n={contentId:n.id,areaName:n.aN,slotNumber:n.sN,contentName:n.cN,contentSource:n.cS,templateName:n.tN,productId:n.pid,contentType:n.cT,parentId:n.pI,parentName:n.pN});for(var a,o=0;o")+" - "+t)}try{var xd,kd,Rd="oneDSWeb",Md=C();Md?Md[Rd=Md.onedsSDK||Rd]!==undefined&&(xd=Md[Rd],(kd=new r).updateSnippetDefinitions(xd),kd.initialize(xd.config,xd.extensions),(Md[Rd]=kd).emptySnippetQueue(xd)):Od(Rd,"Missing global/window")}catch(Ld){Od(Rd,"Unexpected Error: "+ce(Ld))}n.ActionType=rd,n.AppInsightsCore=ja,n.ApplicationInsights=r,n.AutoCaptureHandler=md,n.BE_PROFILE="BEST_EFFORT",n.CoreUtils=Ga,n.DiagnosticLogger=Ni,n.EventLatency=$a,n.EventPersistence=Xa,n.EventsDiscardedReason=un,n.MinChannelPriorty=100,n.NRT_PROFILE="NEAR_REAL_TIME",n.NotificationManager=Ka,n.PostChannel=xc,n.PropertiesPlugin=Hu,n.RT_PROFILE=Do,n.TraceLevel=Qa,n.Utils=Ya,n.ValueKind=Ja,n.WebAnalytics=Nd;var Za=n,c="__esModule",a={value:!0},mt=Object.defineProperty;if(mt)try{return void mt(Za,c,a)}catch(Ud){}typeof a.value!==undefined&&(Za[c]=a.value)};"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).oneDS=e.oneDS||{}); //# sourceMappingURL=ms.analytics-web-3.2.8.min.js.map /*! * 1DS JS SDK QoS plugin, 3.2.8 * Copyright (c) Microsoft and contributors. All rights reserved. * (Microsoft Internal Only) */ var e=this,t=function(i){"use strict";var c="function",l="object",f="undefined",z="prototype",T="hasOwnProperty",I=Object,D=I[z],e=I.assign,w=I.create,t=I.defineProperty,q=D[T],S=null;function ue(e){e=!1===(e=void 0===e||e)?null:S;return e||((e=(e=(e=typeof globalThis!==f?globalThis:e)||typeof self===f?e:self)||typeof window===f?e:window)||typeof global===f||(e=global),S=e),e}function k(e){throw new TypeError(e)}(ue()||{}).Symbol,(ue()||{}).Reflect;var ce=e||function(e){for(var t,n=1,r=arguments.length;n>>=0),qn=123456789+t&Dn,Sn=987654321-t&Dn,wn=!0}catch(o){}r=((Sn=36969*(65535&Sn)+(Sn>>16)&Dn)<<16)+(65535&(qn=18e3*(65535&qn)+(qn>>16)&Dn))>>>0&Dn|0,n=(r>>>=0)&Dn}return 0===n&&(n=Math.floor(In*Math.random()|0)),e||(n>>>=0),n}var _n=t,Pn="."+function(e){void 0===e&&(e=22);for(var t=kn()>>>0,n=0,r=d;r[X]>>=6,5==++n&&(t=(kn()<<2&4294967295|3&t)>>>0,n=0);return r}(6),Mn=0;function Nn(e){return 1===e[Ke]||9===e[Ke]||!+e[Ke]}function Hn(e,t){return _t(e+Mn+++((t=void 0!==t&&t)?".2.8.9":d)+Pn)}function An(e){var o={id:Hn("_aiData-"+(e||d)+".2.8.9"),accept:Nn,get:function(e,t,n,r){var a=e[o.id];return a?a[_t(t)]:(r&&((a=function(e,t){var n=t[e.id];if(!n){n={};try{Nn(t)&&!function(e,t,n){if(_n)try{return _n(e,t,{value:n,enumerable:!1,configurable:!0}),1}catch(r){}}(t,e.id,n)&&(t[e.id]=n)}catch(r){}}return n}(o,e))[_t(t)]=n),n)},kill:function(e,t){if(e&&e[t])try{delete e[t]}catch(n){}}};return o}var Rn="attachEvent",En="addEventListener",jn=(Hn("aiEvtPageHide"),Hn("aiEvtPageShow"),/\.[\.]+/g),Ln=/[\.]+$/,On=1,Fn=An("events"),Vn=/^([^.]*)(?:\.(.+)|)/;function Un(e){return e&&e[Qe]?e[Qe](/^[\s\.]+|(?=[\s\.])[\.\s]+$/g,d):e}function zn(e,t){t&&(n=d,$(t)?(n=d,G(t,function(e){(e=Un(e))&&("."!==e[0]&&(e="."+e),n+=e)})):n=Un(t),n)&&("."!==n[0]&&(n="."+n),e=(e||d)+n);var n,t=Vn.exec(e||d)||[],e={};return e[Je]=t[1],e.ns=(t[2]||d).replace(jn,".").replace(Ln,d)[Be](".").sort().join("."),e}function Bn(){for(var e,t=["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"],n=d,r=0;r<4;r++)n+=t[15&(e=kn())]+t[e>>4&15]+t[e>>8&15]+t[e>>12&15]+t[e>>16&15]+t[e>>20&15]+t[e>>24&15]+t[e>>28&15];var a=t[8+(3&kn())|0];return n[Xe](0,8)+n[Xe](9,4)+"4"+n[Xe](13,3)+a+n[Xe](16,3)+n[Xe](19,12)}var Xn="00",Kn="ff",Wn="00000000000000000000000000000000",Qn="0000000000000000";function $n(e,t,n){return e&&e[X]===t&&e!==n&&e.match(/^[\da-f]*$/)}function Gn(e,t,n){return $n(e,t)?e:n}function Jn(e,t,n,r){var a={};return a[rt]=$n(r,2,Kn)?r:Xn,a[tt]=Yn(e)?e:Bn(),a.spanId=Zn(t)?t:Bn()[Xe](0,16),a.traceFlags=0<=n&&n<=255?n:1,a}function Yn(e){return $n(e,32,Wn)}function Zn(e){return $n(e,16,Qn)}function er(e){var t,n;return e?($n(t=function(e){for(var t=(e=isNaN(e)||e<0||255n)&&(r=t[_r]()[Ar](0,n),b(e,2,61,"string value is too long. It has been truncated to "+n+" characters.",{value:t},!0)),r||t}function Fr(e,t){return e=e,(t=t)&&2048<(t=At(t))[C]&&(n=t[Ar](0,2048),b(e,2,66,"input is too long, it has been truncated to 2048 characters.",{data:t},!0)),n||t;var n}function Vr(r,e){var a;return e&&(a={},Q(e,function(e,t){if(h(t)&&cn())try{t=sn().stringify(t)}catch(n){b(r,2,49,"custom property is not valid",{exception:n},!0)}t=Or(r,t,8192),e=Lr(r,e,a),a[e]=t}),e=a),e}var Ur=rn()||{},zr=0,Br=[null,null,null,null,null];function Xr(n){var e=zr,t=Br,r=t[e];return Ur.createElement?t[e]||(r=t[e]=Ur.createElement("a")):r={host:function(){var e=Kr(n,!0)||"";if(e){var t=e.match(/(www\d{0,5}\.)?([^\/:]{1,256})(:\d{1,20})?/i);if(null!=t&&3=t[C]&&(e=0),zr=e,r}function Kr(e,t){var n=null;return e&&null!=(e=e.match(/(\w{1,150}):\/\/([^\/:]{1,256})(:\d{1,20})?/i))&&2 case insensitive match // g -> global match. All matches (don't return after first match) // m -> multi line matches. Causes ^ and $ to match the begin/end of each line (not only begin/end of string) this.regexPatternsToRedact = [ /secret["\\ ']*[:=]+["\\ ']*([a-zA-Z0-9~%_\.-]*)/igm, /code["\\ ']*[:=]+["\\ ']*([a-zA-Z0-9~%_\.-]*)/igm, /key["\\ ']*[:=]+["\\ ']*([a-zA-Z0-9~%_\.-]*)/igm, /token["\\ ']*[:=]+["\\ ']*([a-zA-Z0-9~%_\.-]*)/igm, /session["\\ ']*[:=]+["\\ ']*([a-zA-Z0-9~%_\.-]*)/igm, /password["\\ ']*[:=]+["\\ ']*([a-zA-Z0-9~%_\.-]*)/igm, /passwd["\\ ']*[:=]+["\\ ']*([a-zA-Z0-9~%_\.-]*)/igm, /pwd["\\ ']*[:=]+["\\ ']*([a-zA-Z0-9~%_\.-]*)/igm, /bearer["\\ ']*[:=]+["\\ ']*([a-zA-Z0-9~%_\.-]*)/igm, /connection["\\ ']*[:=]+["\\ ']*([a-zA-Z0-9~%_\.-]*)/igm, /sig["\\ ']*[:=]+["\\ ']*([a-zA-Z0-9~%_\.-]*)/igm, /certificate["\\ ']*[:=]+["\\ ']*([a-zA-Z0-9~%_\.-]*)/igm, /id["\\ ']*[:=]+["\\ ']*([a-zA-Z0-9~%_\.-]*)/igm, /auth["\\ ']*[:=]+["\\ ']*([a-zA-Z0-9~%_\.-]*)/igm, /assertion["\\ ']*[:=]+["\\ ']*([a-zA-Z0-9~%_\.-]*)/igm, /token_hint["\\ ']*[:=]+["\\ ']*([a-zA-Z0-9~%_\.-]*)/igm, ] this.appInsights = null; this.pageId = ""; this.pageUri = ""; this.isTelemetryDisabled = null; try { this.appInsights = new oneDS.ApplicationInsights(); var qosPlugin = new oneDS.QosPlugin(); //Get instrumentation settings var instrumentationSettings = this.getInstrumentationSettings(); //Get Web analytics SKU config var webAnalyticsConfig = this.getWebAnalyticsConfig(); //Get Qos Config for AJAX/API call tracing var qosConfig = this.getQosConfig(); var config = { endpointUrl: instrumentationSettings.collectorEndpoint, instrumentationKey: instrumentationSettings.instrumentationKey, channelConfiguration: { ignoreMc1Ms0CookieProcessing: true}, // Need excplicit blocking of post channel cookies MC1 and MS0 maxBatchSizeInBytes: 65536, //64kB restriction enforced by sendBeacon() in force flush scenarios (page unload) cookieCfg: { enabled: false }, extensions: [qosPlugin], extensionConfig: { [qosPlugin.identifier]: qosConfig }, propertyConfiguration: { populateBrowserInfo: true, populateOperatingSystemInfo: true, hashIdentifiers: true // Last octet of the client IP Address is redacted }, webAnalyticsConfiguration: webAnalyticsConfig }; this.appInsights.addTelemetryInitializer(this.getTelemetryInitializer()); this.appInsights.initialize(config, []); this.appInsights.getPostChannel()._setTransmitProfile(window["Microsoft"].Dynamic365.Portal.timerProfileForBatching); console.log("Initialized Client Telemetry"); //Create an event for any listener to indicate CST initialization is complete const cstInitialized = new Event("CST_Initialized", { bubbles: true, cancelable: false }); document.dispatchEvent(cstInitialized); } catch (exception) { console.log("Caught exception in client telemetry"); console.warn(exception); } } /// Trace info log traceInfo(message, component, subComponent = "", action = "", tag = "", contextInfo = {}) { var event = { name: this.globalLiterals.EVENT_TABLE_NAME, data: { EventType: this.traceType.TRACE_TYPE_INFO, Component: component, SubComponent: subComponent, ComponentAction: action, PerformanceTag: tag, Message: message, ContextInfo: JSON.stringify(contextInfo) } }; this.appInsights.track(event); } /// Trace warning log traceWarning(message, component, subComponent = "", action = "", tag = "", contextInfo = {}) { var event = { name: this.globalLiterals.EVENT_TABLE_NAME, data: { EventType: this.traceType.TRACE_TYPE_WARNING, Component: component, SubComponent: subComponent, ComponentAction: action, PerformanceTag: tag, Message: message, ContextInfo: JSON.stringify(contextInfo) } }; this.appInsights.track(event); } /// Trace error log traceError(message, component, subComponent = "", action = "", tag = "", contextInfo = {}) { var event = { name: this.globalLiterals.EVENT_TABLE_NAME, data: { EventType: this.traceType.TRACE_TYPE_ERROR, Component: component, SubComponent: subComponent, ComponentAction: action, PerformanceTag: tag, Message: message, ContextInfo: JSON.stringify(contextInfo) } }; this.appInsights.track(event); } /// Trace server error log traceServerError(message, component, subComponent = "", action = "", tag = "", contextInfo = {}) { var event = { name: this.globalLiterals.EVENT_TABLE_NAME, data: { EventType: this.traceType.TRACE_TYPE_SERVERERROR, Component: component, SubComponent: subComponent, ComponentAction: action, PerformanceTag: tag, Message: message, ContextInfo: JSON.stringify(contextInfo) } }; this.appInsights.track(event); } /// Extract instrumentation setting details based from window object getInstrumentationSettings() { return { collectorEndpoint: window["Microsoft"].Dynamic365.Portal.InstrumentationSettings.collectorEndpoint, instrumentationKey: window["Microsoft"].Dynamic365.Portal.InstrumentationSettings.instrumentationKey }; } /// Config for Web Analytics getWebAnalyticsConfig() { return { autoCapture: { pageView: true, onUnload: true, jsError: true } }; } /// Config for QoS extension plugin /// This is needed for AJAX/fetch API etc tracking getQosConfig() { return { manageCv: false, disableAjaxTracking: false, enableAjaxPerfTracking: true, enableCvHeaders: false, enableCorsCorrelation: false, disableCorrelationHeaders: false, maxAjaxCallsPerView: -1, disableFetchTracking: false, enableRequestHeaderTracking: true, enableResponseHeaderTracking: true }; } /// Telemetry initializer are used to modify the contents of collected telemetry before /// being sent from the user's browser. /// Example: https://github.com/Microsoft/ApplicationInsights-JS#example-setting-cloud-role-name getTelemetryInitializer() { return (envelope) => { try { // Page view event is the first event that gets generated for any given page if (envelope.name == this.events.PAGE_VIEW_EVENT) { //Store Page ID generated in Page view event, and use it across events for the same page this.pageId = envelope.baseData.id; //Store Page Uri and use in static assets as referrer this.pageUri = envelope.baseData.uri; return; } // For Request table, tracks auto page load along with performance and outgoing requests else if (envelope.name == this.events.PAGE_VIEW_PERFORMANCE_EVENT || envelope.name == this.events.OUTGOING_REQUEST_EVENT) { this.populateRequestTableAttributes(envelope); this.populateCommonAttributes(envelope); } // For Event table, tracks custom events sent out else if (envelope.name == this.globalLiterals.EVENT_TABLE_NAME) { this.populateEventTableAttributes(envelope); this.populateCommonAttributes(envelope); } // For Event table, tracks auto events for any JS errors else if (envelope.name == this.events.CLIENT_ERROR_EVENT) { envelope.name = this.globalLiterals.EVENT_TABLE_NAME; this.populateEventTableAttributes(envelope); this.populateExceptionAttributes(envelope); this.populateCommonAttributes(envelope); } // For Event table, tracks custom event for exceptions during event processing else if (envelope.name == this.globalLiterals.EVENT_PROCESSING_EXCEPTION) { envelope.name = this.globalLiterals.EVENT_TABLE_NAME; this.populatePortalIdentifierAttributes(envelope); } // For tracking static assets else if (envelope.name == this.globalLiterals.STATIC_ASSETS) { // Exclude capturing calls to collector endpoint wrongly as a static asset request if (envelope.data.Uri.includes("/OneCollector/")) { return false; } envelope.name = this.globalLiterals.REQUEST_TABLE_NAME; this.populateCommonAttributes(envelope); this.populateStaticAssetsAttributes(envelope); } // For all other events else { //Block every other event as we are not interested in //Page view event is not blocked, because it is needed for capturing accurate perf time in PageViewPerformance event //Details: Initial PageView is sent as soon as the onload event is triggered //Internally, this event is used to "measure" the clock drift between the client //and the collector servers, without this the adjusted timestamp // (an attempt to normalize the time difference between clients / servers) //won't be set. So if a client then has there clock set incorrectly the reported //time for events will not be correct. return false; } // Check if the domain name is valid and reeturn the domain + path for the Uri envelope = this.validateUri(envelope); // At the end of event enrichment, redact the sensitive data for all the applicable fields envelope = this.redactSensitiveDataFromEvent(envelope); // Set default values for columns envelope = this.setDefaultValues(envelope); } catch (exception) { // Such exceptions are likely if we are trying to process event attributes which don't exist // In such cases, only add common attributes and current exception details, and avoid processing the event attributes further // However, do log the baseData of the event along with its name in the exception event that gets sent out in this scenario console.warn("Caught exception processing the telemetry event: " + envelope.name); console.warn(exception.message); this.traceExceptionInEventProcessing(exception, envelope); return false; } } } /// Populate attributes that are common to all events populateCommonAttributes(envelope) { envelope.data = envelope.data || {}; // create data nested object if doesn't exist already' this.populatePortalIdentifierAttributes(envelope); envelope.data.UserLanguage = envelope.ext.user.locale; envelope.data.UserTimezone = envelope.ext.loc.tz; envelope.data.AppLanguage = envelope.ext.app.locale; envelope.data.SessionId = envelope.ext.app.sesId; envelope.data.PageId = this.pageId; } /// Populate portal identifier attributes from window object populatePortalIdentifierAttributes(envelope) { var portalDetails = window["Microsoft"].Dynamic365.Portal; envelope.data.PortalId = portalDetails.id; envelope.data.TenantId = portalDetails.tenant; envelope.data.Geo = portalDetails.geo; envelope.data.PortalVersion = portalDetails.version; envelope.data.OrgEnvironmentId = portalDetails.orgEnvironmentId; envelope.data.PortalProductionOrTrialType = portalDetails.portalProductionOrTrialType; envelope.data.UserId = portalDetails.User.contactId; envelope.data.IsAuthenticated = this.isAuthenticated(); envelope.data.VisitorId = this.getVisitorId(); envelope.data.Dynamics365PortalAnalytics = portalDetails.dynamics365PortalAnalytics; } setDefaultValues(envelope) { // Set default values for the properties const defaultValue = -1; // Directly set default values if they are undefined or null envelope.data.ResponsePayloadSizeEncoded = envelope.data.ResponsePayloadSizeEncoded ?? defaultValue; envelope.data.ResponsePayloadSizeDecoded = envelope.data.ResponsePayloadSizeDecoded ?? defaultValue; envelope.data.ResponseTransferSize = envelope.data.ResponseTransferSize ?? defaultValue; envelope.data.Duration = envelope.data.Duration ?? defaultValue; envelope.data.ConnectDuration = envelope.data.ConnectDuration ?? defaultValue; envelope.data.NetworkConnectDuration = envelope.data.NetworkConnectDuration ?? defaultValue; envelope.data.SentRequestDuration = envelope.data.SentRequestDuration ?? defaultValue; envelope.data.ReceivedResponseDuration = envelope.data.ReceivedResponseDuration ?? defaultValue; envelope.data.DomProcessingDuration = envelope.data.DomProcessingDuration ?? defaultValue; envelope.data.ResponseStatusCode = envelope.data.ResponseStatusCode ?? defaultValue; } /// Populate attributes for request table /// Used by Ms.Web.PageViewPerformance and Ms.Web.OutgoingRequest event flows populateRequestTableAttributes(envelope) { envelope.data = envelope.data || {}; // create data nested object if doesn't exist already' if (envelope.name == this.events.OUTGOING_REQUEST_EVENT) { envelope.data.Uri = envelope.baseData.target; envelope.data.ReferrerUri = envelope.data.uri; envelope.data.ResponseStatusCode = envelope.baseData.responseCode; envelope.data.RequestType = envelope.baseData.type; // Extract properties if available if (envelope.baseData.properties) { var ajaxEventData = envelope.baseData.properties; envelope.data.RequestMethod = ajaxEventData.HttpMethod; // Extract perf data if available if (ajaxEventData.ajaxPerf) { envelope.data.Duration = this.getMillis(ajaxEventData.ajaxPerf.duration); envelope.data.ConnectDuration = this.getMillis(ajaxEventData.ajaxPerf.connect); envelope.data.NetworkConnectDuration = this.getMillis(ajaxEventData.ajaxPerf.networkConnect); envelope.data.SentRequestDuration = this.getMillis(ajaxEventData.ajaxPerf.sentRequest); envelope.data.ReceivedResponseDuration = this.getMillis(ajaxEventData.ajaxPerf.response); envelope.data.ResponsePayloadSizeEncoded = ajaxEventData.ajaxPerf.encodedBodySize; envelope.data.ResponsePayloadSizeDecoded = ajaxEventData.ajaxPerf.decodedBodySize; envelope.data.ResponseTransferSize = ajaxEventData.ajaxPerf.transferSize; } //If Duration is still empty, perf details were missing in ajaxPerf object. Take it from alternative field if (!envelope.data.Duration) { envelope.data.Duration = envelope.baseData.duration; } } // Extract from response headers if available if (ajaxEventData.responseHeaders) { envelope.data.ResponseContentEncoding = ajaxEventData.responseHeaders['content-encoding']; envelope.data.ResponseCacheControl = ajaxEventData.responseHeaders['cache-control']; envelope.data.ResponseContentType = ajaxEventData.responseHeaders['content-type']; envelope.data.ResponseContentLength = ajaxEventData.responseHeaders['content-length']; envelope.data.RequestHeaders = JSON.stringify(ajaxEventData.requestHeaders); envelope.data.ResponseHeaders = JSON.stringify(ajaxEventData.responseHeaders); envelope.data.CorrelationId = ajaxEventData.responseHeaders['x-ms-request-id']; envelope.data['X-Cache'] = ajaxEventData.responseHeaders['x-cache']; envelope.data['X-Azure-Ref'] = ajaxEventData.responseHeaders['x-azure-ref']; } } else if (envelope.name == this.events.PAGE_VIEW_PERFORMANCE_EVENT) { envelope.data.Uri = envelope.baseData.uri; envelope.data.ReferrerUri = document.referrer; envelope.data.ResponseStatusCode = this.getResponseStatusCode(location.href); envelope.data.RequestType = "PageView"; envelope.data.RequestMethod = "GET"; envelope.data.Duration = this.getMillis(envelope.baseData.duration); envelope.data.NetworkConnectDuration = this.getMillis(envelope.baseData.networkConnect); envelope.data.SentRequestDuration = this.getMillis(envelope.baseData.sentRequest); envelope.data.ReceivedResponseDuration = this.getMillis(envelope.baseData.receivedResponse); envelope.data.DomProcessingDuration = this.getMillis(envelope.baseData.domProcessing); envelope.data.CorrelationId = window["Microsoft"].Dynamic365.Portal.correlationId; } envelope.name = this.globalLiterals.REQUEST_TABLE_NAME; //Clear fields in the event that are no longer needed so we can avoid sanitization on them envelope.baseData = this.clearOutFields(envelope.baseData); } /// Populate attributes for event table /// Used by both manual tracing flow and auto exception flow with Ms.Web.ClientError event populateEventTableAttributes(envelope) { envelope.data ||= {}; // create data nested object if doesn't exist already' envelope.data.CorrelationId = window["Microsoft"].Dynamic365.Portal.correlationId; } /// Populate attributes for exception from Ms.Web.ClientError event populateExceptionAttributes(envelope) { envelope.data.EventType = this.traceType.TRACE_TYPE_EXCEPTION; var exception = envelope.baseData.exceptions[0]; envelope.data.Message = exception.message; envelope.data.ExceptionMessage = exception.stack; envelope.data.ExceptionSource = envelope.data.errorSrc; if (exception.hasFullStack) { envelope.data.LineNumber = exception.parsedStack[0].line; envelope.data.FileName = exception.parsedStack[0].fileName; envelope.data.ComponentAction = exception.parsedStack[0].method; if (exception.parsedStack[0].assembly) { var splits = exception.parsedStack[0].assembly.split(/[:)]/); if (splits && splits.length >= 2) { envelope.data.ColumnNumber = splits[splits.length - 2]; } } } else { envelope.data.LineNumber = envelope.data.lineNumber; envelope.data.ColumnNumber = envelope.data.columnNumber; } //Store the exception object stringified and empty the original array as it caused issue in Geneva ingestion envelope.data.ExceptionDetails = JSON.stringify(envelope.baseData.exceptions); envelope.baseData.exceptions = []; //Clear fields in the event that are no longer needed so we can avoid sanitization on them envelope.baseData = this.clearOutFields(envelope.baseData); envelope.data.errorSrc = this.clearOutFields(envelope.data.errorSrc); envelope.data.url = this.clearOutFields(envelope.data.url); } /// Populate attributes for static assets populateStaticAssetsAttributes(envelope) { envelope.data = envelope.data || {}; // create data nested object if doesn't exist already envelope.data.RequestType = "StaticAssets"; envelope.data.RequestMethod = "GET"; envelope.data.ReferrerUri = this.pageUri; envelope.data.CorrelationId = this.getCorrelationId(envelope.data.Uri); } /// Trace exceptions in processing event attributes traceExceptionInEventProcessing(exception, envelope) { var event = { name: this.globalLiterals.EVENT_PROCESSING_EXCEPTION, data: { EventType: this.traceType.TRACE_TYPE_EXCEPTION, Component: envelope.name, // Log the original event name for tracking Message: exception.message, ExceptionMessage: JSON.stringify(exception), ExceptionSource: JSON.stringify(envelope.baseData) //Log the baseData part of the event along with exception to not lose the event details in exception scenarios } } this.appInsights.track(event); } /// Track perf. Log event is generated here for the elapsed millis tracePerf(duration, tag, component = "", subComponent = "", action = "", message = "", contextInfo = {}) { var event = { name: this.globalLiterals.EVENT_TABLE_NAME, data: { EventType: this.traceType.TRACE_TYPE_PERFORMANCE, Component: component, SubComponent: subComponent, ComponentAction: action, PerformanceTag: tag, Message: message, ContextInfo: JSON.stringify(contextInfo), Duration: duration } }; this.appInsights.track(event); } /// Generates visitor ID as unique GUID and stores it in local storage /// If a value is available, do not generate new getVisitorId() { if (!localStorage.getItem("visitorId")) { localStorage.setItem("visitorId", self.crypto.randomUUID()); return localStorage.getItem("visitorId"); } else { return localStorage.getItem("visitorId"); } } /// Checks if event is for authenticated user isAuthenticated() { if (!window["Microsoft"].Dynamic365.Portal.User.contactId) { return false; } else { return true; } } /// Get millis from the supplied time /// Sometimes the time format comes in millis directly, sometimes in HH:MM:SS.mmm format, process accordingly getMillis(time) { //If the attribue does not exist return if (!time) return; //If time is of type string and contains : it must be in HH:MM:SS format if (typeof time == "string" && time.includes(':')) { //Split the time string by colon and dot to get the time parts for hour, minute, seconds, millis var timeParts = time.split(/[:.]/); var totalMillis = ((+timeParts[0]) * 60 * 60 + (+timeParts[1]) * 60 + (+timeParts[2])) * 1000; //If there's a milliseconds part, 4th element will be present HH:MM:SS.mmm if (timeParts.length == 4) { totalMillis += (+timeParts[3]); } return totalMillis; } else { // Time is already in number format which must be millis. // Remove unneccessary precision digits after decimal point return Math.round(time); } } //// Get response status code via server timing header "response-code" added in server getResponseStatusCode(uri) { let responseStatusCode = ""; if (performance) { const performanceObject = performance.getEntriesByName(uri); if (performanceObject && performanceObject[0]) { const serverTiming = performanceObject[0].serverTiming; if (serverTiming) { serverTiming.forEach(function (object) { if (object.name == "response-code") responseStatusCode = object.description; }); } } } return responseStatusCode; } //// Get Correlation Id from server timing header. Required for static assets request getCorrelationId(uri) { let correlationId = ""; if (performance) { const performanceObject = performance.getEntriesByName(uri); if (performanceObject && performanceObject[0]) { const serverTiming = performanceObject[0].serverTiming; if (serverTiming) { serverTiming.forEach(function (object) { if (object.name == "correlationId") correlationId = object.description; }); } } } return correlationId; } //// Clear out fields the object and string fields that are no longer needed in the event post enrichment //// Other data types don't pose much issue hence can be left as is clearOutFields(value) { if(value) { // Valid value if (typeof (value) === 'object' && value.constructor === Object) { return []; } else if (typeof (value) === 'string') { return ""; } } else { // return as is. This scenario is handled already. Field corresponding to this value is not sent. return value; } } //// Redact Sensitive data for the fields susceptible to contain codes/tokens/keys/secrets etc. //// This is done post event enrichment is complete to not impact the dependencies (if any) on actual values like Uri etc. redactSensitiveDataFromEvent(envelope) { //Redact sensitive information from suseptible fields envelope.data.Uri = this.getAllSensitiveRedactedFromField(envelope.data.Uri); envelope.data.ReferrerUri = this.getAllSensitiveRedactedFromField(envelope.data.ReferrerUri); envelope.data.ExceptionMessage = this.getAllSensitiveRedactedFromField(envelope.data.ExceptionMessage); envelope.data.ExceptionDetails = this.getAllSensitiveRedactedFromField(envelope.data.ExceptionDetails); envelope.data.ExceptionSource = this.getAllSensitiveRedactedFromField(envelope.data.ExceptionSource); envelope.data.FileName = this.getAllSensitiveRedactedFromField(envelope.data.FileName); envelope.data.RequestHeaders = this.getAllSensitiveRedactedFromField(envelope.data.RequestHeaders); envelope.data.ResponseHeaders = this.getAllSensitiveRedactedFromField(envelope.data.ResponseHeaders); return envelope; } //// Validate domain name validateUri(envelope) { //Redact the domain name if not valid // if it contains special chars envelope.data.Uri = this.getDomainAndPathForField(envelope.data.Uri); envelope.data.ReferrerUri = this.getDomainAndPathForField(envelope.data.ReferrerUri); return envelope; } //// validate domain name getDomainAndPathForField(uri) { try { // Ensure the value is of type string if (!uri || typeof uri !== 'string') return uri; // Substrings which are whitelisted so that query params are not removed in case these are present const whitelistedsubstrings = ['omnichannelengagementhub', 'directline']; const url = new URL(uri); // Parse the URL const domain = url.hostname; // Extract hostname from parsed URL const path = url.pathname; // Extract path const params = url.search; // Extract queryparams // Get the query parameters const queryParams = new URLSearchParams(params); // Check if any key or value contains the whitelisted substrings for (const [key, value] of queryParams.entries()) { if (whitelistedsubstrings.some(whitelistedsubstrings => key.includes(whitelistedsubstrings) || value.includes(whitelistedsubstrings))) { return uri; } } // Return the combined domain and path if no whitelisted substring is found uri = domain + path; } catch (exception) { console.warn("Caught exception while processing telemetry data for redaction of query params (if any): " + value); console.warn(exception.message); } return uri; } //// Get redacted value after all sensitive information is redacted getAllSensitiveRedactedFromField(value) { try { // Ensure the value is of type string if (value && typeof value === 'string') { this.regexPatternsToRedact.forEach((pattern) => { value = this.getRedactedValueViaRegexMatch(value, pattern); }); } } catch (exception) { console.warn("Caught exception while processing telemetry data for redaction (if any): " + value); console.warn(exception.message); } return value; } //// Get redacted value getRedactedValueViaRegexMatch(value, regexPattern) { let matches; while ((matches = regexPattern.exec(value)) !== null) { // This is necessary to avoid infinite loops with zero-width matches if (matches.index === regexPattern.lastIndex) { regexPattern.lastIndex++; } matches.forEach((match, groupIndex) => { if (groupIndex == 0) { // Redact the entire matched string value = value.replace(match, this.globalLiterals.REDACTED); //Replace with string REDACTED } }); } return value; } //// Gets a new instance of BlockPerTracker for block level performance tracking getBlockPerfTracker() { return new BlockPerfTracker(); } } /// Track static assets via PerformanceObserver which observes assets as they are being requested // https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming // https://developer.mozilla.org/en-US/docs/Web/API/PerformanceObserver/PerformanceObserver function perfObserverForCstStaticAssets(list, observer, droppedEntriesCount) { list.getEntries().forEach((entry) => { if (entry.initiatorType != "xmlhttprequest" && entry.initiatorType != "beacon") { //Exclude XHR and Beacon requests var event = { // Compose event name: ClientLogger.getLogger().globalLiterals.STATIC_ASSETS, data: { Uri: entry.name, ResponseStatusCode: entry.responseStatus, ResponsePayloadSizeEncoded: entry.encodedBodySize, ResponsePayloadSizeDecoded: entry.decodedBodySize, ResponseTransferSize: entry.transferSize, Duration: Math.round(entry.duration), ConnectDuration: validateTimeForCst(Math.round(entry.connectStart - entry.connectEnd)), NetworkConnectDuration: validateTimeForCst(Math.round(entry.connectEnd - entry.startTime)), SentRequestDuration: validateTimeForCst(Math.round(entry.responseEnd - entry.requestStart)), ReceivedResponseDuration: validateTimeForCst(Math.round(entry.responseEnd - entry.responseStart)), Message: "initiatorType = " + entry.initiatorType } }; // Send out custom event ClientLogger.getLogger().appInsights.track(event); } }); if (droppedEntriesCount > 0) { const warningMessage = `WARNING: ${droppedEntriesCount} entries got dropped due to the buffer being full.`; console.warn(warningMessage); ClientLogger.getLogger().traceWarning(warningMessage, "PerformanceResourceTiming", "PerformanceObserver"); } } const observerForCstStaticAssets = new PerformanceObserver(perfObserverForCstStaticAssets); observerForCstStaticAssets.observe({ type: "resource", buffered: true }); /// Validate time duration. Return 0 if found negative else return as is. function validateTimeForCst(duration) { if (duration < 0) return 0; else return duration; } /// Increase the buffer size by 250 if buffer is found to be full /// The buffer is reset to 0 on page refresh function increaseFilledBufferSizeForCst(event) { const increaseBufferSizeBy = 250; const currentBufferSize = performance.getEntriesByType("resource").length; const warningMessage = `WARNING: Resource Timing Buffer is FULL ${currentBufferSize}! Increasing buffer size by ${increaseBufferSizeBy}.`; console.warn(warningMessage); performance.setResourceTimingBufferSize(currentBufferSize + increaseBufferSizeBy); /// Capture a warning log in CST for the same ClientLogger.getLogger().traceWarning(warningMessage, "PerformanceResourceTiming", "ResourceTimingBuffer"); } /// Add event listener for recognizing when the recource timing buffer is full, and increase buffer size performance.addEventListener("resourcetimingbufferfull", increaseFilledBufferSizeForCst); /// Tracks block level performance in millis class BlockPerfTracker{ /// Start the timer and set required details for tracking start(perfTag, component, subComponent = "", action = "", message = "", contextInfo = {}) { this.startTime = new Date().getTime(); this.perfTag = perfTag; this.component = component; this.subComponent = subComponent; this.action = action; this.message = message; this.contextInfo = JSON.stringify(contextInfo); return this; } /// End the timer and log required details for tracking stop() { this.endTime = new Date().getTime(); ClientLogger.getLogger().tracePerf(this.endTime - this.startTime, this.perfTag, this.component, this.subComponent, this.action, this.message, this.contextInfo); return this; } }