Search code examples
reactjsservice-workerazure-application-insightsweb-worker

How can I utilise ApplicationInsights-JS in a service worker?


I am currently using ApplicationInsights-JS in my progressive web app. It works in my react components as I can import what I need from the relevant npm packages.

In my service worker however, I can only import logic using importScripts.

I did manage to find a CDN for ApplicationInsights-JS on their Github page however it seems that in order to initialise app insights using this library you need to have access to window in order to store the appinsights, which you cannot do from a service worker.

I tried to use the web snippet approach since the CDN seemed to be related to that particular library, but I can't use window and am not sure how else to implement this solution.

This is a copy paste of the suggested snippet to init the app insights object from: https://github.com/Microsoft/ApplicationInsights-JS

importScripts('https://az416426.vo.msecnd.net/beta/ai.2.min.js');

const sdkInstance = 'appInsightsSDK';
window[sdkInstance] = 'appInsights';
const aiName = window[sdkInstance];

const aisdk =
  window[aiName] ||
  (function(e) {
    function n(e) {
      i[e] = function() {
        const n = arguments;
        i.queue.push(function() {
          i[e](...n);
        });
      };
    }
    let i = { config: e };
    i.initialize = !0;
    const a = document;

    const t = window;
    setTimeout(function() {
      const n = a.createElement('script');
      (n.src = e.url || 'https://az416426.vo.msecnd.net/next/ai.2.min.js'),
        a.getElementsByTagName('script')[0].parentNode.appendChild(n);
    });
    try {
      i.cookie = a.cookie;
    } catch (e) {}
    (i.queue = []), (i.version = 2);
    for (
      const r = [
        'Event',
        'PageView',
        'Exception',
        'Trace',
        'DependencyData',
        'Metric',
        'PageViewPerformance'
      ];
      r.length;

    )
      n(`track${r.pop()}`);
    n('startTrackPage'), n('stopTrackPage');
    const o = `Track${r[0]}`;
    if (
      (n(`start${o}`),
      n(`stop${o}`),
      !(
        !0 === e.disableExceptionTracking ||
        (e.extensionConfig &&
          e.extensionConfig.ApplicationInsightsAnalytics &&
          !0 ===
            e.extensionConfig.ApplicationInsightsAnalytics
              .disableExceptionTracking)
      ))
    ) {
      n(`_${(r = 'onerror')}`);
      const s = t[r];
      (t[r] = function(e, n, a, t, o) {
        const c = s && s(e, n, a, t, o);
        return (
          !0 !== c &&
            i[`_${r}`]({
              message: e,
              url: n,
              lineNumber: a,
              columnNumber: t,
              error: o
            }),
          c
        );
      }),
        (e.autoExceptionInstrumented = !0);
    }
    return i;
  })({ instrumentationKey: 'xxx-xxx-xxx-xxx-xxx' });
(window[aiName] = aisdk),
  aisdk.queue && aisdk.queue.length === 0 && aisdk.trackPageView({});

I get window is not defined which is expected, but I'm not sure how else I can make use of this library from the service worker.

Has anyone else had a similar implementation in which they successfully logged telemetry using ApplicationInsights from a service worker?


Solution

  • I realised that I was over complicating this.

    Since I only needed to track a custom event, and didn't need all the automated page tracking etc that appInsights does, I ended up doing a fetch from my service worker.

    I just copied the header and body format from the requests that I made using my react pages.

    The below successfully logged telemetry to my app insights dashboard:

    fetch(url, {
      method: 'post',
      headers: {
        'Content-type': 'application/json'
      },
      body: JSON.stringify([
        {
          time: '2019-05-02T15:56:37.589Z',
          iKey: 'INSTRUMENTATION_KEY',
          name:
            'Microsoft.ApplicationInsights.INSTRUMENTATION_KEY.Event',
          tags: {
            'ai.user.id': 'l6Tey',
            'ai.session.id': 'TL+Ry',
            'ai.device.id': 'browser',
            'ai.device.type': 'Browser',
            'ai.operation.id': 'HUfNE',
            SampleRate: '100',
            // eslint-disable-next-line no-script-url
            'ai.internal.sdkVersion': 'javascript:2.0.0-rc4'
          },
          data: {
            baseType: 'EventData',
            baseData: {
              ver: 2,
              name: 'Testing manual event',
              properties: {},
              measurements: {}
            }
          }
        }
      ])
    })
      .then(json)
      .then(function(data) {
      })
      .catch(function(error) {
      });