microsoft / applicationinsights-react-native

Microsoft Application Insights React Native Plugin
MIT License
18 stars 7 forks source link

[BUG] React Native: Not setting correlation headers on fetch requests #9

Open niklas-r opened 3 years ago

niklas-r commented 3 years ago

Description/Screenshot Hi

We're trying to integrate our React Native app with Applications Insight but we're facing multiple issues. Mainly, it's not setting correlation headers (Request-Id, Request-Context etc.).

Steps to Reproduce

OS/Browser:

SDK Version [e.g. 22]:

How you initialized the SDK:

import { ApplicationInsights } from '@microsoft/applicationinsights-web';
import { ReactNativePlugin } from '@microsoft/applicationinsights-react-native';
import { applicationInsightsKey } from 'react-native-dotenv';

let appInsights;

export function setupApplicationInsights() {
  var RNPlugin = new ReactNativePlugin();
  appInsights = new ApplicationInsights({
    config: {
      instrumentationKey: applicationInsightsKey,
      disableAjaxTracking: false,
      extensions: [RNPlugin],
      samplingPercentage: 100,
      loggingLevelTelemetry: 2,
      diagnosticLogInterval: 100,
      disableFetchTracking: false,
      disableCorrelationHeaders: false,
      enableCorsCorrelation: true,
      enableRequestHeaderTracking: true,
      enableResponseHeaderTracking: true,
    },
  });

  appInsights.loadAppInsights();

  var telemetryInitializer = envelope => {
    if (envelope.baseData.name != null && envelope.baseData.name.includes('heartbeat')) {
      return false;
    }

    envelope.tags['ai.cloud.role'] = 'courier-app';
    envelope.tags['ai.cloud.roleInstance'] = 'courier-app';
  };

  appInsights.addTelemetryInitializer(telemetryInitializer);
}

Expected behavior

We thought this would add the necessary headers to each fetch request and also send the necessary tracking data to the AI backend but it seems we're only getting some data in to AI which is not being correlated with our other services.

Additional context We managed to get the application to send correlation data by adding this hack before we initialize AI.

  global.fetch.polyfill = false;

But this feels like a bad thing to do and it still didn't correlate the requests in the application map.

We're using react-navigation v5 and are sending appInsights.trackPageView(/*data*/) on each screen change. These page views does show in AI.

So our biggest issues right now are:

  1. Data isn't being correlated correctly in the Application Map view.
  2. Transactions aren't being grouped in a sane way in the end-to-end transactions view. They all seem to fall under the same operation id which we're not sure how to fix.
MSNev commented 3 years ago

React Native uses a polyfill from whatwg-fetch, which uses XHR.

As such to avoid double reporting of both fetch and XHR for the same request ApplicationInsights does not instrument requests originating from a polyfill instance. So you should not need to set global.fetch.polyfill = false as your outbound fetch requests should still be getting instrumented via the standard XHR requests (you should be able to confirm this via reviewing the F12 developer tools (or fiddler trace)

On the grouping / correlation (I think they are probably related), I'll let someone else (@xiao-lix, @Karlie-777 or @kryalama) jump in as I'm going to be unavailable for the next couple of weeks.

If react-navigation supports updating the URL, by default the applicationinsights-analytics extension (included in the main AISKU) will listen to the locationchange event (https://github.com/microsoft/ApplicationInsights-JS/blob/master/extensions/applicationinsights-analytics-js/src/JavaScriptSDK/ApplicationInsights.ts#L679-L689 and enabled/disabled by the enableAutoRouteTracking config) which update the traceId. So if it doesn't update the URL, you may need to do something similar before calling trackPageView

Karlie-777 commented 3 years ago

Hi @niklas-r , For the correlation header: headers should be included if the current domain matches the request domain. If they do not match (CORS), we will check correlationHeaderDomains or correlationHeaderExcludedDomains to determine if headers are included. Some environments don't give information on currentHost and if this is the case, domains must be manually supplied to include correlation headers otherwise no headers will be added. But I am not sure if this applies to your issues, let us know if it works.

niklas-r commented 3 years ago

@MSNev Thank you for your response. I also have a feeling that the grouping and correlation might be related. You're right about React Native using whatwg-fetch. So you're suggesting that we disable fetch tracking because it's a polyfill and instead use the regular ajax tracking?

There's no concept of URL in React Native since it's compiled into a native app, so I don't think we can make it work with enableAutoRouteTracking. Unless there would be a native component in @microsoft/applicationinsights-react-native which could detect screen changes on the native level, I think we're bound to use trackPageView, which is totally fine.

@Karlie-777 Thank you for your response. We can try to configure correlationHeaderDomains but I'm not sure it's going to work since CORS is not a thing in native apps. But since React Native has done a lot of polyfilling of global objects to make the environment somewhat seem like a browser it might just do the trick.

MSNev commented 3 years ago

Sorry for the delayed response as I've been Away.

So you're suggesting that we disable fetch tracking because it's a polyfill and instead use the regular ajax tracking?

Correct