Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple Application Insights with different connection strings using JavaScript(Web) SDK v3 giving warnings #2355

Open
rubiks-cube opened this issue May 28, 2024 · 18 comments
Assignees
Milestone

Comments

@rubiks-cube
Copy link

I am trying to have multiple Application Insights(vesrion 3) with different connection strings using JavaScript(Web) SDK Loader Script on the same HTML page. I have also given different name in the configuration. But I am getting in this warning in console:

Two extensions have same priority

WhatsApp Image 2024-05-28 at 6 22 55 PM

How can I fix this? or is there any different way to have multiple instances using loader script? In the docs, it is mentioned that we can use "name" if you need to initialize two different SDKs at the same time.

@MSNev
Copy link
Collaborator

MSNev commented May 28, 2024

The SDK loaded does not support loading / initializing (directly) multiple SDK instances as (by default) it will always set (and sometimes (race condition) replace the global appInsights instance).

So I suspect that the (not often used) config that will help with what you are trying to achieve is the name (

// name: "appInsights", // Global SDK Instance name defaults to "appInsights" when not supplied
) configuration, this is the name of the global window.appInsights (by default) where the SDK instance is registered.
It's also has some additional documentation in the table in this section https://github.com/microsoft/ApplicationInsights-JS?tab=readme-ov-file#reporting-script-load-exceptions

This will require 3 separate SDK Loader instances with the 3 separate SDK Loader configs, you can't do it with a single SDK Loader config. The other option is via npm where you can load the SDK code once (in your own bundle) and then initialize multiple instances.

@rubiks-cube
Copy link
Author

rubiks-cube commented May 28, 2024

I am already using the name property in the config and getting the issue as above. Loading 2 separate SDK configs using Script Loader separately with different name. I don't want to use npm package since I am not using any bundler.

@MSNev
Copy link
Collaborator

MSNev commented May 28, 2024

Hmm, that is a little odd, its sounding like the multiple versions are "sharing" the same config object and therefore as each one is initialized it keeps "adding" to the existing values.

By default, when the SDK initializes (for version 3+) it uses the "provided" config as a template and effective clones the objects / arrays (to avoid this exact issue) as internally it "adds" objects that are being listed as duplicates... The only time it doesn't do this is if the config has already been converted into a dynamic config (it's already undergone the initialization process)...

This is the code that uses the name config, and the sdk loader doesn't use the createDynamicConfig() so this (shouldn't) be occurring... I'll need to have someone investigate this a little more, however, the person I would get to do this is currently on Leave, so it might be a while before they get to it....

If you have some time if you could do some initial debugging that would be helpful, the issue sounds like it would revolve around the handling / initializing of the SDK. One simple approach (assuming the issue is not in the SDK loader itself) is that if you change the "src" to https://js.monitor.azure.com/scripts/b/ai.3.gbl.js this will use download and use the unminified version of the SDK (although the minified one also includes the map file which is publically available) and trace into the AppInsightsCore initialize function this should be the line of code that "clones" the config while this is where we "add" the standard extensions to the provided config (which is calling the AppInsightsCore config)

@MSNev MSNev added the investigation required Further investigation or discussions required label May 28, 2024
@rubiks-cube
Copy link
Author

Any update on this issue?

@siyuniu-ms
Copy link
Contributor

Hi @rubiks-cube, apologies for the delay - I've just returned from vacation and am taking a look at the issue now. Thank you for your patience!

@siyuniu-ms
Copy link
Contributor

Hello @rubiks-cube, thank you for bringing this issue to our attention. We were able to reproduce the problem and have identified that it is caused by a race condition. To address this, we will be releasing a new version of the snippet and SDK. Please note that this solution will not support IE and Opera Mini. However, you won't need to make any changes on your end. Thank you for your patience as we work to resolve this issue.

@rubiks-cube
Copy link
Author

@siyuniu-ms thanks for the update.

@MSNev MSNev added this to the 3.2.2 milestone Jun 10, 2024
@rubiks-cube
Copy link
Author

@siyuniu-ms I see v3.2.2 is released and through npm it is installing this latest version but script loader is still loading 3.2.1

@siyuniu-ms
Copy link
Contributor

Hi, our cdn release (where our snippet live) will take around 5 days after our npm is released to make sure we didn't break anything.

@rubiks-cube
Copy link
Author

any update on script loader v3.2.2? still it is fetching old version file.

@siyuniu-ms
Copy link
Contributor

@rubiks-cube It would be released early next week. Thanks for waiting.

@siyuniu-ms siyuniu-ms modified the milestones: 3.2.2, webldr-1.2.0 Jun 21, 2024
@siyuniu-ms
Copy link
Contributor

@rubiks-cube Both snippet package and AI 3.2.2 CDN is published which contains the newest changes.

@rubiks-cube
Copy link
Author

rubiks-cube commented Jun 24, 2024

@siyuniu-ms I am still facing the above same issue of warnings with updated version and also onInit callback function is getting called for the last appinisghts one only and not for every appInsights instance added by script loader in the html. Also there is another error I see in console:
Screenshot 2024-06-25 024255

@siyuniu-ms
Copy link
Contributor

Hi, could you provide more error details? I just did a local test with two snippet inited at the same time wtih two different ikey and both track message is delivered successfully.

@siyuniu-ms
Copy link
Contributor

siyuniu-ms commented Jun 24, 2024

and below is my test code for reference

<!DOCTYPE html>

<meta name="viewport" content="width=device-width, initial-scale=1.0">
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>AISKU Sample</title>
    <link rel="stylesheet" href="style/style.css"/>
<script type="text/javascript">
!(function (cfg){function e(){cfg.onInit&&cfg.onInit(n)}var x,w,D,t,E,n,C=window,O=document,b=C.location,q="script",I="ingestionendpoint",L="disableExceptionTracking",j="ai.device.";"instrumentationKey"[x="toLowerCase"](),w="crossOrigin",D="POST",t="appInsightsSDK",E=cfg.name||"appInsights",(cfg.name||C[t])&&(C[t]=E),n=C[E]||function(g){var f=!1,m=!1,h={initialize:!0,queue:[],sv:"8",version:2,config:g};function v(e,t){var n={},i="Browser";function a(e){e=""+e;return 1===e.length?"0"+e:e}return n[j+"id"]=i[x](),n[j+"type"]=i,n["ai.operation.name"]=b&&b.pathname||"_unknown_",n["ai.internal.sdkVersion"]="javascript:snippet_"+(h.sv||h.version),{time:(i=new Date).getUTCFullYear()+"-"+a(1+i.getUTCMonth())+"-"+a(i.getUTCDate())+"T"+a(i.getUTCHours())+":"+a(i.getUTCMinutes())+":"+a(i.getUTCSeconds())+"."+(i.getUTCMilliseconds()/1e3).toFixed(3).slice(2,5)+"Z",iKey:e,name:"Microsoft.ApplicationInsights."+e.replace(/-/g,"")+"."+t,sampleRate:100,tags:n,data:{baseData:{ver:2}},ver:undefined,seq:"1",aiDataContract:undefined}}var n,i,t,a,y=-1,T=0,S=["js.monitor.azure.com","js.cdn.applicationinsights.io","js.cdn.monitor.azure.com","js0.cdn.applicationinsights.io","js0.cdn.monitor.azure.com","js2.cdn.applicationinsights.io","js2.cdn.monitor.azure.com","az416426.vo.msecnd.net"],o=g.url||cfg.src,r=function(){return s(o,null)};function s(d,t){if((n=navigator)&&(~(n=(n.userAgent||"").toLowerCase()).indexOf("msie")||~n.indexOf("trident/"))&&~d.indexOf("ai.3")&&(d=d.replace(/(\/)(ai\.3\.)([^\d]*)$/,function(e,t,n){return t+"ai.2"+n})),!1!==cfg.cr)for(var e=0;e<S.length;e++)if(0<d.indexOf(S[e])){y=e;break}var n,i=function(e){var a,t,n,i,o,r,s,c,u,l;h.queue=[],m||(0<=y&&T+1<S.length?(a=(y+T+1)%S.length,p(d.replace(/^(.*\/\/)([\w\.]*)(\/.*)$/,function(e,t,n,i){return t+S[a]+i})),T+=1):(f=m=!0,s=d,!0!==cfg.dle&&(c=(t=function(){var e,t={},n=g.connectionString;if(n)for(var i=n.split(";"),a=0;a<i.length;a++){var o=i[a].split("=");2===o.length&&(t[o[0][x]()]=o[1])}return t[I]||(e=(n=t.endpointsuffix)?t.location:null,t[I]="https://"+(e?e+".":"")+"dc."+(n||"services.visualstudio.com")),t}()).instrumentationkey||g.instrumentationKey||"",t=(t=(t=t[I])&&"/"===t.slice(-1)?t.slice(0,-1):t)?t+"/v2/track":g.endpointUrl,t=g.userOverrideEndpointUrl||t,(n=[]).push((i="SDK LOAD Failure: Failed to load Application Insights SDK script (See stack for details)",o=s,u=t,(l=(r=v(c,"Exception")).data).baseType="ExceptionData",l.baseData.exceptions=[{typeName:"SDKLoadFailed",message:i.replace(/\./g,"-"),hasFullStack:!1,stack:i+"\nSnippet failed to load ["+o+"] -- Telemetry is disabled\nHelp Link: https://go.microsoft.com/fwlink/?linkid=2128109\nHost: "+(b&&b.pathname||"_unknown_")+"\nEndpoint: "+u,parsedStack:[]}],r)),n.push((l=s,i=t,(u=(o=v(c,"Message")).data).baseType="MessageData",(r=u.baseData).message='AI (Internal): 99 message:"'+("SDK LOAD Failure: Failed to load Application Insights SDK script (See stack for details) ("+l+")").replace(/\"/g,"")+'"',r.properties={endpoint:i},o)),s=n,c=t,JSON&&((u=C.fetch)&&!cfg.useXhr?u(c,{method:D,body:JSON.stringify(s),mode:"cors"}):XMLHttpRequest&&((l=new XMLHttpRequest).open(D,c),l.setRequestHeader("Content-type","application/json"),l.send(JSON.stringify(s)))))))},a=function(e,t){m||setTimeout(function(){!t&&h.core||i()},500),f=!1},p=function(e){var n=O.createElement(q),e=(n.src=e,t&&(n.integrity=t),n.setAttribute("data-ai-name",E),cfg[w]);return!e&&""!==e||"undefined"==n[w]||(n[w]=e),n.onload=a,n.onerror=i,n.onreadystatechange=function(e,t){"loaded"!==n.readyState&&"complete"!==n.readyState||a(0,t)},cfg.ld&&cfg.ld<0?O.getElementsByTagName("head")[0].appendChild(n):setTimeout(function(){O.getElementsByTagName(q)[0].parentNode.appendChild(n)},cfg.ld||0),n};p(d)}cfg.sri&&(n=o.match(/^((http[s]?:\/\/.*\/)\w+(\.\d+){1,5})\.(([\w]+\.){0,2}js)$/))&&6===n.length?(d="".concat(n[1],".integrity.json"),i="@".concat(n[4]),l=window.fetch,t=function(e){if(!e.ext||!e.ext[i]||!e.ext[i].file)throw Error("Error Loading JSON response");var t=e.ext[i].integrity||null;s(o=n[2]+e.ext[i].file,t)},l&&!cfg.useXhr?l(d,{method:"GET",mode:"cors"}).then(function(e){return e.json()["catch"](function(){return{}})}).then(t)["catch"](r):XMLHttpRequest&&((a=new XMLHttpRequest).open("GET",d),a.onreadystatechange=function(){if(a.readyState===XMLHttpRequest.DONE)if(200===a.status)try{t(JSON.parse(a.responseText))}catch(e){r()}else r()},a.send())):o&&r();try{h.cookie=O.cookie}catch(k){}function e(e){for(;e.length;)!function(t){h[t]=function(){var e=arguments;f||h.queue.push(function(){h[t].apply(h,e)})}}(e.pop())}var c,u,l="track",d="TrackPage",p="TrackEvent",l=(e([l+"Event",l+"PageView",l+"Exception",l+"Trace",l+"DependencyData",l+"Metric",l+"PageViewPerformance","start"+d,"stop"+d,"start"+p,"stop"+p,"addTelemetryInitializer","setAuthenticatedUserContext","clearAuthenticatedUserContext","flush"]),h.SeverityLevel={Verbose:0,Information:1,Warning:2,Error:3,Critical:4},(g.extensionConfig||{}).ApplicationInsightsAnalytics||{});return!0!==g[L]&&!0!==l[L]&&(e(["_"+(c="onerror")]),u=C[c],C[c]=function(e,t,n,i,a){var o=u&&u(e,t,n,i,a);return!0!==o&&h["_"+c]({message:e,url:t,lineNumber:n,columnNumber:i,error:a,evt:C.event}),o},g.autoExceptionInstrumented=!0),h}(cfg.cfg),(C[E]=n).queue&&0===n.queue.length?(n.queue.push(e),n.trackPageView({})):e();})({
    src: "https://js.monitor.azure.com/scripts/b/ai.3.gbl.min.js",
    name: "appInsights",
    crossOrigin: "anonymous", // When supplied this will add the provided value as the cross origin attribute on the script tag
    sri: true, // Custom optional value to specify whether fetching the snippet from integrity file and do integrity check 
    cfg: { // Application Insights Configuration
        connectionString: ""
    }
});
  </script>
  <script type="text/javascript">
    !(function (cfg){function e(){cfg.onInit&&cfg.onInit(n)}var x,w,D,t,E,n,C=window,O=document,b=C.location,q="script",I="ingestionendpoint",L="disableExceptionTracking",j="ai.device.";"instrumentationKey"[x="toLowerCase"](),w="crossOrigin",D="POST",t="appInsightsSDK",E=cfg.name||"appInsights",(cfg.name||C[t])&&(C[t]=E),n=C[E]||function(g){var f=!1,m=!1,h={initialize:!0,queue:[],sv:"8",version:2,config:g};function v(e,t){var n={},i="Browser";function a(e){e=""+e;return 1===e.length?"0"+e:e}return n[j+"id"]=i[x](),n[j+"type"]=i,n["ai.operation.name"]=b&&b.pathname||"_unknown_",n["ai.internal.sdkVersion"]="javascript:snippet_"+(h.sv||h.version),{time:(i=new Date).getUTCFullYear()+"-"+a(1+i.getUTCMonth())+"-"+a(i.getUTCDate())+"T"+a(i.getUTCHours())+":"+a(i.getUTCMinutes())+":"+a(i.getUTCSeconds())+"."+(i.getUTCMilliseconds()/1e3).toFixed(3).slice(2,5)+"Z",iKey:e,name:"Microsoft.ApplicationInsights."+e.replace(/-/g,"")+"."+t,sampleRate:100,tags:n,data:{baseData:{ver:2}},ver:undefined,seq:"1",aiDataContract:undefined}}var n,i,t,a,y=-1,T=0,S=["js.monitor.azure.com","js.cdn.applicationinsights.io","js.cdn.monitor.azure.com","js0.cdn.applicationinsights.io","js0.cdn.monitor.azure.com","js2.cdn.applicationinsights.io","js2.cdn.monitor.azure.com","az416426.vo.msecnd.net"],o=g.url||cfg.src,r=function(){return s(o,null)};function s(d,t){if((n=navigator)&&(~(n=(n.userAgent||"").toLowerCase()).indexOf("msie")||~n.indexOf("trident/"))&&~d.indexOf("ai.3")&&(d=d.replace(/(\/)(ai\.3\.)([^\d]*)$/,function(e,t,n){return t+"ai.2"+n})),!1!==cfg.cr)for(var e=0;e<S.length;e++)if(0<d.indexOf(S[e])){y=e;break}var n,i=function(e){var a,t,n,i,o,r,s,c,u,l;h.queue=[],m||(0<=y&&T+1<S.length?(a=(y+T+1)%S.length,p(d.replace(/^(.*\/\/)([\w\.]*)(\/.*)$/,function(e,t,n,i){return t+S[a]+i})),T+=1):(f=m=!0,s=d,!0!==cfg.dle&&(c=(t=function(){var e,t={},n=g.connectionString;if(n)for(var i=n.split(";"),a=0;a<i.length;a++){var o=i[a].split("=");2===o.length&&(t[o[0][x]()]=o[1])}return t[I]||(e=(n=t.endpointsuffix)?t.location:null,t[I]="https://"+(e?e+".":"")+"dc."+(n||"services.visualstudio.com")),t}()).instrumentationkey||g.instrumentationKey||"",t=(t=(t=t[I])&&"/"===t.slice(-1)?t.slice(0,-1):t)?t+"/v2/track":g.endpointUrl,t=g.userOverrideEndpointUrl||t,(n=[]).push((i="SDK LOAD Failure: Failed to load Application Insights SDK script (See stack for details)",o=s,u=t,(l=(r=v(c,"Exception")).data).baseType="ExceptionData",l.baseData.exceptions=[{typeName:"SDKLoadFailed",message:i.replace(/\./g,"-"),hasFullStack:!1,stack:i+"\nSnippet failed to load ["+o+"] -- Telemetry is disabled\nHelp Link: https://go.microsoft.com/fwlink/?linkid=2128109\nHost: "+(b&&b.pathname||"_unknown_")+"\nEndpoint: "+u,parsedStack:[]}],r)),n.push((l=s,i=t,(u=(o=v(c,"Message")).data).baseType="MessageData",(r=u.baseData).message='AI (Internal): 99 message:"'+("SDK LOAD Failure: Failed to load Application Insights SDK script (See stack for details) ("+l+")").replace(/\"/g,"")+'"',r.properties={endpoint:i},o)),s=n,c=t,JSON&&((u=C.fetch)&&!cfg.useXhr?u(c,{method:D,body:JSON.stringify(s),mode:"cors"}):XMLHttpRequest&&((l=new XMLHttpRequest).open(D,c),l.setRequestHeader("Content-type","application/json"),l.send(JSON.stringify(s)))))))},a=function(e,t){m||setTimeout(function(){!t&&h.core||i()},500),f=!1},p=function(e){var n=O.createElement(q),e=(n.src=e,t&&(n.integrity=t),n.setAttribute("data-ai-name",E),cfg[w]);return!e&&""!==e||"undefined"==n[w]||(n[w]=e),n.onload=a,n.onerror=i,n.onreadystatechange=function(e,t){"loaded"!==n.readyState&&"complete"!==n.readyState||a(0,t)},cfg.ld&&cfg.ld<0?O.getElementsByTagName("head")[0].appendChild(n):setTimeout(function(){O.getElementsByTagName(q)[0].parentNode.appendChild(n)},cfg.ld||0),n};p(d)}cfg.sri&&(n=o.match(/^((http[s]?:\/\/.*\/)\w+(\.\d+){1,5})\.(([\w]+\.){0,2}js)$/))&&6===n.length?(d="".concat(n[1],".integrity.json"),i="@".concat(n[4]),l=window.fetch,t=function(e){if(!e.ext||!e.ext[i]||!e.ext[i].file)throw Error("Error Loading JSON response");var t=e.ext[i].integrity||null;s(o=n[2]+e.ext[i].file,t)},l&&!cfg.useXhr?l(d,{method:"GET",mode:"cors"}).then(function(e){return e.json()["catch"](function(){return{}})}).then(t)["catch"](r):XMLHttpRequest&&((a=new XMLHttpRequest).open("GET",d),a.onreadystatechange=function(){if(a.readyState===XMLHttpRequest.DONE)if(200===a.status)try{t(JSON.parse(a.responseText))}catch(e){r()}else r()},a.send())):o&&r();try{h.cookie=O.cookie}catch(k){}function e(e){for(;e.length;)!function(t){h[t]=function(){var e=arguments;f||h.queue.push(function(){h[t].apply(h,e)})}}(e.pop())}var c,u,l="track",d="TrackPage",p="TrackEvent",l=(e([l+"Event",l+"PageView",l+"Exception",l+"Trace",l+"DependencyData",l+"Metric",l+"PageViewPerformance","start"+d,"stop"+d,"start"+p,"stop"+p,"addTelemetryInitializer","setAuthenticatedUserContext","clearAuthenticatedUserContext","flush"]),h.SeverityLevel={Verbose:0,Information:1,Warning:2,Error:3,Critical:4},(g.extensionConfig||{}).ApplicationInsightsAnalytics||{});return!0!==g[L]&&!0!==l[L]&&(e(["_"+(c="onerror")]),u=C[c],C[c]=function(e,t,n,i,a){var o=u&&u(e,t,n,i,a);return!0!==o&&h["_"+c]({message:e,url:t,lineNumber:n,columnNumber:i,error:a,evt:C.event}),o},g.autoExceptionInstrumented=!0),h}(cfg.cfg),(C[E]=n).queue&&0===n.queue.length?(n.queue.push(e),n.trackPageView({})):e();})({
        src: "https://js.monitor.azure.com/scripts/b/ai.3.gbl.min.js",
        name: "appInsights2",
        crossOrigin: "anonymous", // When supplied this will add the provided value as the cross origin attribute on the script tag
        sri: true, // Custom optional value to specify whether fetching the snippet from integrity file and do integrity check 
        cfg: { // Application Insights Configuration
          connectionString: ""
        }
    });
      </script>
  </head>
  <body>
    <h1>Microsoft Application Insights JavaScript SDK - AISKU</h1>
    <script>
      let appInsights = new ApplicationInsights.ApplicationInsights({ config: {connectionString: "InstrumentationKey=88888888", disableInstrumentationKeyValidation: true}});
      appInsights.loadAppInsights();
      window.appInsights = appInsights;
    </script>
  </body>
</html>

@MSNev
Copy link
Collaborator

MSNev commented Jun 24, 2024

For some context, you will need both the new version "8" (see "sv": "8") of the SDK Loader AND version 3.2.2 of the SDK, if either version does not match (or greater) then the identifed race condition causing SDK A to use Loader B and Vica-versa configuration may still occur.
This is because v3.2.2 is now (optionally) using the data-tag to identify the "global" instance name (this also requires that you runtime supports the document.currentScript (as this is what it uses to get access to any passed attribute on the script tag). And only v8 onwards will add this new data attribute to the script tag.

@rubiks-cube
Copy link
Author

The script loader mentioned in docs is different : Script Loader. Using the above snippet doesn't have this issue.

@MSNev
Copy link
Collaborator

MSNev commented Jun 24, 2024

Yeah, not all of the documentation has been updated yet, it is included on the main readme https://github.com/microsoft/ApplicationInsights-JS/blob/main/tools/grunt-tasks/minifyNames.js and it is included in v1.2.0 of the web-snippet package https://www.npmjs.com/package/@microsoft/applicationinsights-web-snippet (which we published on friday)

@siyuniu-ms siyuniu-ms added released - NPM and removed investigation required Further investigation or discussions required labels Jul 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants