@duffcloudservices/telemetry 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,96 @@
1
+ # @duffcloudservices/telemetry
2
+
3
+ Shared **Azure Application Insights** telemetry for DCS Vue sites. One place owns
4
+ the App Insights config and the `useTelemetry` composable, so every DCS surface
5
+ (marketing `web/`, generated customer sites) gets the same behavior — including
6
+ the fleet-wide **bfcache / Lighthouse unload fix**.
7
+
8
+ ## Why this package exists
9
+
10
+ The App Insights JavaScript SDK, by default, registers a listener on the
11
+ deprecated **`unload`** event. That:
12
+
13
+ - makes pages ineligible for the browser **back/forward cache (bfcache)**, and
14
+ - trips the Lighthouse **"avoid `unload` event listeners"** best-practices audit
15
+ (~19 points — enough to pin flagship sites at Best-Practices 54).
16
+
17
+ The fix is a single config field — [`disablePageUnloadEvents: ['unload']`][ai-cfg]
18
+ — which tells the SDK to skip the `unload` hook while still flushing telemetry on
19
+ `pagehide` / `visibilitychange` (the supported path). This package bakes that
20
+ into the **default** config so no consumer can forget it.
21
+
22
+ [ai-cfg]: https://microsoft.github.io/ApplicationInsights-JS/PageUnloadEvents.html
23
+
24
+ ## Install
25
+
26
+ ```bash
27
+ pnpm add @duffcloudservices/telemetry
28
+ # peers you already have on a DCS Vue site:
29
+ pnpm add @microsoft/applicationinsights-web vue
30
+ ```
31
+
32
+ ## Usage — composable (SPA / eager)
33
+
34
+ The connection string, cloud role, environment and app version are supplied by
35
+ the consumer (read your own `import.meta.env` / build defines and pass plain
36
+ values in), keeping this package portable.
37
+
38
+ ```ts
39
+ import { useTelemetry } from '@duffcloudservices/telemetry'
40
+
41
+ const telemetry = useTelemetry({
42
+ connectionString: import.meta.env.VITE_APP_INSIGHTS_CONNECTION_STRING,
43
+ instrumentationKey: import.meta.env.VITE_APP_INSIGHTS_INSTRUMENT_KEY,
44
+ cloudRole: 'dcs-web',
45
+ dev: import.meta.env.DEV,
46
+ environment: import.meta.env.MODE,
47
+ appVersion: __APP_VERSION__,
48
+ })
49
+
50
+ telemetry.initialize() // synchronous; no-op (with a loud one-shot warn) when unconfigured
51
+ telemetry.trackCtaClick('hero-cta', '/contact')
52
+ ```
53
+
54
+ `initialize()` is **synchronous** because the SDK is statically imported.
55
+
56
+ ## Usage — config only (lazy / inert loaders)
57
+
58
+ Sites that lazy-load the SDK themselves (to stay inert when telemetry is
59
+ unconfigured) can import just the config — no SDK is pulled in:
60
+
61
+ ```ts
62
+ import { createTelemetryConfig } from '@duffcloudservices/telemetry/config'
63
+
64
+ const { ApplicationInsights } = await import('@microsoft/applicationinsights-web')
65
+ const ai = new ApplicationInsights({
66
+ config: createTelemetryConfig({ connectionString: cs, enableAutoRouteTracking: false }),
67
+ })
68
+ ai.loadAppInsights()
69
+ ```
70
+
71
+ ## API
72
+
73
+ | Export | Description |
74
+ | --- | --- |
75
+ | `useTelemetry(options?)` | Full composable: `initialize`, `trackEvent`, `trackPageView`, `trackCtaClick`, `trackException`, `trackMetric`, `trackDependency`, `flush`, `startTrackPage`, `stopTrackPage`, plus `isEnabled` / `isInitialized` / `initializationError` refs. |
76
+ | `createTelemetryConfig(options?)` | Builds the App Insights config with DCS defaults + the `disablePageUnloadEvents: ['unload']` fix. Pure, no SDK import. |
77
+ | `DEFAULT_DISABLE_PAGE_UNLOAD_EVENTS` | `['unload']` — the disabled-events default. |
78
+ | `DEFAULT_CLOUD_ROLE` | `'dcs-site'`. |
79
+ | types | `TelemetryOptions`, `TelemetryConfigOptions`, `ApplicationInsightsConfig`, `TelemetryEvent`, `TelemetryPageView`, `TelemetryException`, `TelemetryDependency`, `TelemetryMetric`. |
80
+
81
+ ### `TelemetryOptions`
82
+
83
+ | Option | Default | Notes |
84
+ | --- | --- | --- |
85
+ | `connectionString` / `instrumentationKey` | — | at least one enables telemetry |
86
+ | `cloudRole` | `'dcs-site'` | `ai.cloud.role` + `app_name` property |
87
+ | `appVersion` | `window.__APP_VERSION__` ?? `'unknown'` | stamped on every event |
88
+ | `environment` | `'unknown'` | e.g. `import.meta.env.MODE` |
89
+ | `dev` | `false` | verbose SDK logging when `true` |
90
+ | `enableAutoRouteTracking` | `true` | SDK built-in SPA route tracking |
91
+ | `disablePageUnloadEvents` | `['unload']` | **the fix** — override only if you know why |
92
+ | `overrides` | — | deep `Partial<ApplicationInsightsConfig>`, applied last |
93
+
94
+ ## License
95
+
96
+ MIT © Duff Cloud Services
@@ -0,0 +1,60 @@
1
+ // src/config.ts
2
+ var DEFAULT_DISABLE_PAGE_UNLOAD_EVENTS = ["unload"];
3
+ var DEFAULT_CLOUD_ROLE = "dcs-site";
4
+ var DEFAULT_CORRELATION_HEADER_DOMAINS = [
5
+ "localhost",
6
+ "127.0.0.1",
7
+ "*.duffcloudservices.com"
8
+ ];
9
+ var DEFAULT_CORRELATION_HEADER_EXCLUDED_DOMAINS = [
10
+ "*.googleapis.com",
11
+ "*.stripe.com",
12
+ "*.auth0.com",
13
+ "*.linkedin.com",
14
+ "*.github.com",
15
+ "*.microsoft.com",
16
+ "*.microsoftonline.com"
17
+ ];
18
+ function createTelemetryConfig(options = {}) {
19
+ const {
20
+ connectionString,
21
+ instrumentationKey,
22
+ enableAutoRouteTracking = true,
23
+ dev = false,
24
+ disablePageUnloadEvents = [...DEFAULT_DISABLE_PAGE_UNLOAD_EVENTS],
25
+ overrides
26
+ } = options;
27
+ const config = {
28
+ connectionString,
29
+ instrumentationKey,
30
+ // ── BP-54 fleet fix ──────────────────────────────────────────────────
31
+ // Never register a listener on the deprecated `unload` event. Keeping it
32
+ // out restores back/forward-cache eligibility and clears the Lighthouse
33
+ // "avoid unload event listeners" audit (~19 best-practices points). The
34
+ // SDK still flushes on pagehide/visibilitychange, so telemetry is intact.
35
+ disablePageUnloadEvents: [...disablePageUnloadEvents],
36
+ enableAutoRouteTracking,
37
+ enableCorsCorrelation: true,
38
+ enableRequestHeaderTracking: true,
39
+ enableResponseHeaderTracking: true,
40
+ autoTrackPageVisitTime: true,
41
+ enableAjaxErrorStatusText: true,
42
+ enableAjaxPerfTracking: true,
43
+ disableExceptionTracking: false,
44
+ disableTelemetry: false,
45
+ loggingLevelConsole: dev ? 1 : 2,
46
+ loggingLevelTelemetry: dev ? 1 : 2,
47
+ samplingPercentage: 100,
48
+ isCookieUseDisabled: false,
49
+ distributedTracingMode: 2,
50
+ correlationHeaderDomains: [...DEFAULT_CORRELATION_HEADER_DOMAINS],
51
+ correlationHeaderExcludedDomains: [...DEFAULT_CORRELATION_HEADER_EXCLUDED_DOMAINS],
52
+ ...overrides
53
+ };
54
+ config.disablePageUnloadEvents = [...disablePageUnloadEvents];
55
+ return config;
56
+ }
57
+
58
+ export { DEFAULT_CLOUD_ROLE, DEFAULT_DISABLE_PAGE_UNLOAD_EVENTS, createTelemetryConfig };
59
+ //# sourceMappingURL=chunk-MX6WFWG4.js.map
60
+ //# sourceMappingURL=chunk-MX6WFWG4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config.ts"],"names":[],"mappings":";AASO,IAAM,kCAAA,GAAwD,CAAC,QAAQ;AAGvE,IAAM,kBAAA,GAAqB;AAGlC,IAAM,kCAAA,GAAwD;AAAA,EAC5D,WAAA;AAAA,EACA,WAAA;AAAA,EACA;AACF,CAAA;AAGA,IAAM,2CAAA,GAAiE;AAAA,EACrE,kBAAA;AAAA,EACA,cAAA;AAAA,EACA,aAAA;AAAA,EACA,gBAAA;AAAA,EACA,cAAA;AAAA,EACA,iBAAA;AAAA,EACA;AACF,CAAA;AAeO,SAAS,qBAAA,CACd,OAAA,GAAkC,EAAC,EACR;AAC3B,EAAA,MAAM;AAAA,IACJ,gBAAA;AAAA,IACA,kBAAA;AAAA,IACA,uBAAA,GAA0B,IAAA;AAAA,IAC1B,GAAA,GAAM,KAAA;AAAA,IACN,uBAAA,GAA0B,CAAC,GAAG,kCAAkC,CAAA;AAAA,IAChE;AAAA,GACF,GAAI,OAAA;AAEJ,EAAA,MAAM,MAAA,GAAoC;AAAA,IACxC,gBAAA;AAAA,IACA,kBAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,uBAAA,EAAyB,CAAC,GAAG,uBAAuB,CAAA;AAAA,IACpD,uBAAA;AAAA,IACA,qBAAA,EAAuB,IAAA;AAAA,IACvB,2BAAA,EAA6B,IAAA;AAAA,IAC7B,4BAAA,EAA8B,IAAA;AAAA,IAC9B,sBAAA,EAAwB,IAAA;AAAA,IACxB,yBAAA,EAA2B,IAAA;AAAA,IAC3B,sBAAA,EAAwB,IAAA;AAAA,IACxB,wBAAA,EAA0B,KAAA;AAAA,IAC1B,gBAAA,EAAkB,KAAA;AAAA,IAClB,mBAAA,EAAqB,MAAM,CAAA,GAAI,CAAA;AAAA,IAC/B,qBAAA,EAAuB,MAAM,CAAA,GAAI,CAAA;AAAA,IACjC,kBAAA,EAAoB,GAAA;AAAA,IACpB,mBAAA,EAAqB,KAAA;AAAA,IACrB,sBAAA,EAAwB,CAAA;AAAA,IACxB,wBAAA,EAA0B,CAAC,GAAG,kCAAkC,CAAA;AAAA,IAChE,gCAAA,EAAkC,CAAC,GAAG,2CAA2C,CAAA;AAAA,IACjF,GAAG;AAAA,GACL;AAOA,EAAA,MAAA,CAAO,uBAAA,GAA0B,CAAC,GAAG,uBAAuB,CAAA;AAE5D,EAAA,OAAO,MAAA;AACT","file":"chunk-MX6WFWG4.js","sourcesContent":["import type { ApplicationInsightsConfig, TelemetryConfigOptions } from './types'\n\n/**\n * The page-unload events the DCS default config tells the App Insights web SDK\n * to leave un-hooked. Only the deprecated `unload` event is disabled — the SDK\n * still hooks `pagehide` / `visibilitychange` (the supported flush path), so no\n * telemetry is lost, back/forward-cache eligibility is restored, and the\n * Lighthouse \"avoid `unload` event listeners\" audit passes.\n */\nexport const DEFAULT_DISABLE_PAGE_UNLOAD_EVENTS: readonly string[] = ['unload']\n\n/** Cloud-role default when a consumer does not name itself. */\nexport const DEFAULT_CLOUD_ROLE = 'dcs-site'\n\n/** Correlation is added to first-party requests to these domains. */\nconst DEFAULT_CORRELATION_HEADER_DOMAINS: readonly string[] = [\n 'localhost',\n '127.0.0.1',\n '*.duffcloudservices.com',\n]\n\n/** Correlation headers are never attached to these third-party domains. */\nconst DEFAULT_CORRELATION_HEADER_EXCLUDED_DOMAINS: readonly string[] = [\n '*.googleapis.com',\n '*.stripe.com',\n '*.auth0.com',\n '*.linkedin.com',\n '*.github.com',\n '*.microsoft.com',\n '*.microsoftonline.com',\n]\n\n/**\n * Build the App Insights web SDK config with DCS's shared defaults.\n *\n * The DEFAULT always includes {@link DEFAULT_DISABLE_PAGE_UNLOAD_EVENTS}\n * (`disablePageUnloadEvents: ['unload']`) — the fleet-wide bfcache / Lighthouse\n * best-practices fix. Callers only need to supply their connection string; every\n * field is overridable via the typed options (and the escape-hatch `overrides`).\n *\n * This function performs no SDK import and reads no `import.meta.env` — it is\n * pure, so it is safe to call from lazy/inert telemetry loaders (the SDK is only\n * pulled in when the composable, or the consumer, actually constructs\n * `ApplicationInsights`).\n */\nexport function createTelemetryConfig(\n options: TelemetryConfigOptions = {},\n): ApplicationInsightsConfig {\n const {\n connectionString,\n instrumentationKey,\n enableAutoRouteTracking = true,\n dev = false,\n disablePageUnloadEvents = [...DEFAULT_DISABLE_PAGE_UNLOAD_EVENTS],\n overrides,\n } = options\n\n const config: ApplicationInsightsConfig = {\n connectionString,\n instrumentationKey,\n // ── BP-54 fleet fix ──────────────────────────────────────────────────\n // Never register a listener on the deprecated `unload` event. Keeping it\n // out restores back/forward-cache eligibility and clears the Lighthouse\n // \"avoid unload event listeners\" audit (~19 best-practices points). The\n // SDK still flushes on pagehide/visibilitychange, so telemetry is intact.\n disablePageUnloadEvents: [...disablePageUnloadEvents],\n enableAutoRouteTracking,\n enableCorsCorrelation: true,\n enableRequestHeaderTracking: true,\n enableResponseHeaderTracking: true,\n autoTrackPageVisitTime: true,\n enableAjaxErrorStatusText: true,\n enableAjaxPerfTracking: true,\n disableExceptionTracking: false,\n disableTelemetry: false,\n loggingLevelConsole: dev ? 1 : 2,\n loggingLevelTelemetry: dev ? 1 : 2,\n samplingPercentage: 100,\n isCookieUseDisabled: false,\n distributedTracingMode: 2,\n correlationHeaderDomains: [...DEFAULT_CORRELATION_HEADER_DOMAINS],\n correlationHeaderExcludedDomains: [...DEFAULT_CORRELATION_HEADER_EXCLUDED_DOMAINS],\n ...overrides,\n }\n\n // Re-assert the unload fix AFTER the overrides spread so a caller that passes\n // `overrides` can never accidentally re-enable the deprecated `unload` listener\n // and regress the fleet-wide BP-54 / bfcache fix. A caller that genuinely needs\n // a different unload policy sets `disablePageUnloadEvents` via the dedicated\n // option (applied above), not through `overrides`.\n config.disablePageUnloadEvents = [...disablePageUnloadEvents]\n\n return config\n}\n"]}
@@ -0,0 +1,123 @@
1
+ import { IConfiguration, IConfig } from '@microsoft/applicationinsights-web';
2
+
3
+ /**
4
+ * The concrete config shape accepted by the App Insights web SDK's
5
+ * `ApplicationInsights` constructor (`{ config }`). The SDK types the field as
6
+ * `IConfiguration & IConfig`; `disablePageUnloadEvents` lives on `IConfiguration`.
7
+ */
8
+ type ApplicationInsightsConfig = IConfiguration & IConfig;
9
+ interface TelemetryEvent {
10
+ name: string;
11
+ properties?: Record<string, string>;
12
+ measurements?: Record<string, number>;
13
+ }
14
+ interface TelemetryPageView {
15
+ name?: string;
16
+ uri?: string;
17
+ properties?: Record<string, string>;
18
+ measurements?: Record<string, number>;
19
+ }
20
+ interface TelemetryException {
21
+ exception: Error;
22
+ properties?: Record<string, string>;
23
+ measurements?: Record<string, number>;
24
+ }
25
+ interface TelemetryDependency {
26
+ name: string;
27
+ data: string;
28
+ duration: number;
29
+ success: boolean;
30
+ resultCode?: number;
31
+ properties?: Record<string, string>;
32
+ measurements?: Record<string, number>;
33
+ }
34
+ interface TelemetryMetric {
35
+ name: string;
36
+ average: number;
37
+ sampleCount?: number;
38
+ min?: number;
39
+ max?: number;
40
+ properties?: Record<string, string>;
41
+ }
42
+ /**
43
+ * Options that shape the App Insights *config object* — everything
44
+ * {@link createTelemetryConfig} needs. All fields are per-consumer variance;
45
+ * the package supplies the shared DCS defaults (including the unload fix).
46
+ */
47
+ interface TelemetryConfigOptions {
48
+ /** App Insights connection string (preferred). Sourced from the consumer's env. */
49
+ connectionString?: string;
50
+ /** Legacy instrumentation key, if a connection string is not available. */
51
+ instrumentationKey?: string;
52
+ /** Enable the SDK's built-in SPA route tracking. Default `true`. */
53
+ enableAutoRouteTracking?: boolean;
54
+ /**
55
+ * Dev mode — routes internal SDK logs more verbosely to the console
56
+ * (`loggingLevel* = 1` vs `2`). The consumer passes `import.meta.env.DEV`.
57
+ * Default `false`.
58
+ */
59
+ dev?: boolean;
60
+ /**
61
+ * Page-unload events the SDK must NOT hook. Defaults to `['unload']`.
62
+ *
63
+ * This is the fleet-wide "BP-54" fix: the App Insights web SDK otherwise
64
+ * registers a listener on the deprecated `unload` event, which (a) blocks
65
+ * back/forward-cache eligibility and (b) trips the Lighthouse
66
+ * "avoid `unload` event listeners" best-practices audit (~19 points).
67
+ * The SDK keeps flushing telemetry on `pagehide` / `visibilitychange`
68
+ * (the supported path), so nothing is lost. See the SDK's own
69
+ * `IConfiguration.disablePageUnloadEvents` docs.
70
+ */
71
+ disablePageUnloadEvents?: string[];
72
+ /**
73
+ * Deep overrides spread over the DCS defaults *last*, so a consumer can
74
+ * change any App Insights config field (correlation domains, sampling, …).
75
+ */
76
+ overrides?: Partial<ApplicationInsightsConfig>;
77
+ }
78
+ /**
79
+ * Options for the {@link useTelemetry} composable — the config options plus the
80
+ * per-app enrichment values that the SDK config itself does not carry.
81
+ */
82
+ interface TelemetryOptions extends TelemetryConfigOptions {
83
+ /** `ai.cloud.role` for this app, e.g. `'dcs-web'`. Default `'dcs-site'`. */
84
+ cloudRole?: string;
85
+ /**
86
+ * App version stamped onto every event (`app_version` property +
87
+ * `ai.application.ver` tag). The consumer passes its build-time version
88
+ * define; falls back to `window.__APP_VERSION__` then `'unknown'`.
89
+ */
90
+ appVersion?: string;
91
+ /**
92
+ * Environment label added as the `environment` property, e.g. the consumer's
93
+ * `import.meta.env.MODE`. Falls back to `'unknown'`.
94
+ */
95
+ environment?: string;
96
+ }
97
+
98
+ /**
99
+ * The page-unload events the DCS default config tells the App Insights web SDK
100
+ * to leave un-hooked. Only the deprecated `unload` event is disabled — the SDK
101
+ * still hooks `pagehide` / `visibilitychange` (the supported flush path), so no
102
+ * telemetry is lost, back/forward-cache eligibility is restored, and the
103
+ * Lighthouse "avoid `unload` event listeners" audit passes.
104
+ */
105
+ declare const DEFAULT_DISABLE_PAGE_UNLOAD_EVENTS: readonly string[];
106
+ /** Cloud-role default when a consumer does not name itself. */
107
+ declare const DEFAULT_CLOUD_ROLE = "dcs-site";
108
+ /**
109
+ * Build the App Insights web SDK config with DCS's shared defaults.
110
+ *
111
+ * The DEFAULT always includes {@link DEFAULT_DISABLE_PAGE_UNLOAD_EVENTS}
112
+ * (`disablePageUnloadEvents: ['unload']`) — the fleet-wide bfcache / Lighthouse
113
+ * best-practices fix. Callers only need to supply their connection string; every
114
+ * field is overridable via the typed options (and the escape-hatch `overrides`).
115
+ *
116
+ * This function performs no SDK import and reads no `import.meta.env` — it is
117
+ * pure, so it is safe to call from lazy/inert telemetry loaders (the SDK is only
118
+ * pulled in when the composable, or the consumer, actually constructs
119
+ * `ApplicationInsights`).
120
+ */
121
+ declare function createTelemetryConfig(options?: TelemetryConfigOptions): ApplicationInsightsConfig;
122
+
123
+ export { type ApplicationInsightsConfig as A, DEFAULT_CLOUD_ROLE as D, type TelemetryOptions as T, type TelemetryDependency as a, type TelemetryEvent as b, type TelemetryException as c, type TelemetryMetric as d, type TelemetryPageView as e, createTelemetryConfig as f, DEFAULT_DISABLE_PAGE_UNLOAD_EVENTS as g, type TelemetryConfigOptions as h };
@@ -0,0 +1,2 @@
1
+ export { D as DEFAULT_CLOUD_ROLE, g as DEFAULT_DISABLE_PAGE_UNLOAD_EVENTS, f as createTelemetryConfig } from './config-BPmCpvmt.js';
2
+ import '@microsoft/applicationinsights-web';
package/dist/config.js ADDED
@@ -0,0 +1,3 @@
1
+ export { DEFAULT_CLOUD_ROLE, DEFAULT_DISABLE_PAGE_UNLOAD_EVENTS, createTelemetryConfig } from './chunk-MX6WFWG4.js';
2
+ //# sourceMappingURL=config.js.map
3
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"config.js"}
@@ -0,0 +1,33 @@
1
+ import * as vue from 'vue';
2
+ import { T as TelemetryOptions, a as TelemetryDependency, b as TelemetryEvent, c as TelemetryException, d as TelemetryMetric, e as TelemetryPageView } from './config-BPmCpvmt.js';
3
+ export { A as ApplicationInsightsConfig, D as DEFAULT_CLOUD_ROLE, g as DEFAULT_DISABLE_PAGE_UNLOAD_EVENTS, h as TelemetryConfigOptions, f as createTelemetryConfig } from './config-BPmCpvmt.js';
4
+ import '@microsoft/applicationinsights-web';
5
+
6
+ /**
7
+ * Azure Application Insights composable for DCS Vue apps.
8
+ *
9
+ * The connection string, cloud role, environment and app version are supplied
10
+ * by the consumer (they read their own `import.meta.env` / build defines and
11
+ * pass plain values in) so this package stays portable and build-tool agnostic.
12
+ * The shared App Insights config — including the `disablePageUnloadEvents:
13
+ * ['unload']` bfcache/Lighthouse fix — comes from {@link createTelemetryConfig}.
14
+ */
15
+ declare function useTelemetry(options?: TelemetryOptions): {
16
+ isEnabled: vue.ComputedRef<boolean>;
17
+ isInitialized: vue.Ref<boolean, boolean>;
18
+ initializationError: vue.Ref<string | null, string | null>;
19
+ initialize: () => boolean;
20
+ flush: () => void;
21
+ startTrackPage: (name?: string) => void;
22
+ stopTrackPage: (name?: string, url?: string, properties?: Record<string, string>, measurements?: Record<string, number>) => void;
23
+ trackDependency: (dependency: TelemetryDependency) => void;
24
+ trackEvent: (event: TelemetryEvent) => void;
25
+ trackException: (exception: TelemetryException) => void;
26
+ trackMetric: (metric: TelemetryMetric) => void;
27
+ trackPageView: (pageView?: TelemetryPageView) => void;
28
+ trackCtaClick: (label: string, page?: string) => void;
29
+ };
30
+ /** The full public API returned by {@link useTelemetry}. */
31
+ type TelemetryApi = ReturnType<typeof useTelemetry>;
32
+
33
+ export { type TelemetryApi, TelemetryDependency, TelemetryEvent, TelemetryException, TelemetryMetric, TelemetryOptions, TelemetryPageView, useTelemetry };
package/dist/index.js ADDED
@@ -0,0 +1,253 @@
1
+ import { DEFAULT_CLOUD_ROLE, createTelemetryConfig } from './chunk-MX6WFWG4.js';
2
+ export { DEFAULT_CLOUD_ROLE, DEFAULT_DISABLE_PAGE_UNLOAD_EVENTS, createTelemetryConfig } from './chunk-MX6WFWG4.js';
3
+ import { ApplicationInsights } from '@microsoft/applicationinsights-web';
4
+ import { ref, computed } from 'vue';
5
+
6
+ var appInsights = null;
7
+ var isInitialized = ref(false);
8
+ var initializationError = ref(null);
9
+ var warnedDisabled = false;
10
+ var warnedNotInitialized = false;
11
+ function resolveAppVersion(explicit) {
12
+ if (explicit) return explicit;
13
+ const w = typeof window !== "undefined" ? window : void 0;
14
+ return w?.__APP_VERSION__ ?? "unknown";
15
+ }
16
+ function useTelemetry(options = {}) {
17
+ const cloudRole = options.cloudRole ?? DEFAULT_CLOUD_ROLE;
18
+ const environment = options.environment ?? "unknown";
19
+ const isEnabled = computed(() => {
20
+ return !!(options.connectionString || options.instrumentationKey);
21
+ });
22
+ function buildSharedProperties() {
23
+ const appVersion = resolveAppVersion(options.appVersion);
24
+ const referrerHost = typeof document !== "undefined" && document.referrer ? (() => {
25
+ try {
26
+ return new URL(document.referrer).hostname;
27
+ } catch {
28
+ return "unknown";
29
+ }
30
+ })() : "direct";
31
+ return {
32
+ app_version: appVersion,
33
+ app_name: cloudRole,
34
+ app_host: typeof window !== "undefined" ? window.location.hostname : "",
35
+ page_path: typeof window !== "undefined" ? window.location.pathname : "",
36
+ referrer_host: referrerHost
37
+ };
38
+ }
39
+ function buildEventProperties(additional) {
40
+ return {
41
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
42
+ environment,
43
+ ...buildSharedProperties(),
44
+ ...additional
45
+ };
46
+ }
47
+ function enrichTelemetryEnvelope(envelope) {
48
+ if (!envelope.data) {
49
+ envelope.data = {};
50
+ }
51
+ envelope.data.baseData = envelope.data.baseData || {};
52
+ envelope.data.baseData.properties = envelope.data.baseData.properties || {};
53
+ Object.assign(envelope.data.baseData.properties, buildSharedProperties());
54
+ const appVersion = resolveAppVersion(options.appVersion);
55
+ envelope.tags = envelope.tags || {};
56
+ envelope.tags["ai.application.ver"] = appVersion;
57
+ envelope.tags["ai.cloud.role"] = cloudRole;
58
+ envelope.tags["ai.cloud.roleInstance"] = typeof window !== "undefined" ? window.location.hostname : "";
59
+ }
60
+ const initialize = () => {
61
+ try {
62
+ if (isInitialized.value && appInsights) {
63
+ return true;
64
+ }
65
+ if (!isEnabled.value) {
66
+ if (!warnedDisabled) {
67
+ warnedDisabled = true;
68
+ console.warn(
69
+ "[telemetry] Application Insights DISABLED: no connection string or instrumentation key was provided at build time. All telemetry calls will silently no-op."
70
+ );
71
+ }
72
+ return false;
73
+ }
74
+ appInsights = new ApplicationInsights({
75
+ config: createTelemetryConfig({
76
+ connectionString: options.connectionString,
77
+ instrumentationKey: options.instrumentationKey,
78
+ enableAutoRouteTracking: options.enableAutoRouteTracking,
79
+ dev: options.dev,
80
+ disablePageUnloadEvents: options.disablePageUnloadEvents,
81
+ overrides: options.overrides
82
+ })
83
+ });
84
+ appInsights.loadAppInsights();
85
+ appInsights.addTelemetryInitializer((envelope) => {
86
+ try {
87
+ enrichTelemetryEnvelope(envelope);
88
+ } catch (error) {
89
+ console.warn("Failed to add web telemetry context:", error);
90
+ }
91
+ return true;
92
+ });
93
+ isInitialized.value = true;
94
+ initializationError.value = null;
95
+ console.log("Application Insights initialized successfully");
96
+ return true;
97
+ } catch (error) {
98
+ const errorMessage = error instanceof Error ? error.message : "Unknown initialization error";
99
+ initializationError.value = errorMessage;
100
+ console.error("Failed to initialize Application Insights:", error);
101
+ return false;
102
+ }
103
+ };
104
+ const trackEvent = (event) => {
105
+ if (!appInsights || !isInitialized.value) {
106
+ if (!warnedNotInitialized) {
107
+ warnedNotInitialized = true;
108
+ console.warn(
109
+ `[telemetry] Application Insights not initialized \u2014 dropping event "${event.name}" (and silencing further "not initialized" warnings for this session).`
110
+ );
111
+ }
112
+ return;
113
+ }
114
+ try {
115
+ appInsights.trackEvent({
116
+ name: event.name,
117
+ properties: buildEventProperties(event.properties),
118
+ measurements: event.measurements
119
+ });
120
+ } catch (error) {
121
+ console.error("Failed to track event:", error);
122
+ }
123
+ };
124
+ const trackPageView = (pageView) => {
125
+ if (!appInsights || !isInitialized.value) {
126
+ console.warn("Application Insights not initialized, skipping page view tracking");
127
+ return;
128
+ }
129
+ try {
130
+ const referrer = typeof document !== "undefined" ? document.referrer ?? "" : "";
131
+ appInsights.trackPageView({
132
+ name: pageView?.name || (typeof document !== "undefined" ? document.title : void 0),
133
+ uri: pageView?.uri || (typeof window !== "undefined" ? window.location.href : void 0),
134
+ properties: buildEventProperties({
135
+ referrer,
136
+ ...pageView?.properties
137
+ }),
138
+ measurements: pageView?.measurements
139
+ });
140
+ } catch (error) {
141
+ console.error("Failed to track page view:", error);
142
+ }
143
+ };
144
+ const trackCtaClick = (label, page) => {
145
+ trackEvent({
146
+ name: "cta_click",
147
+ properties: {
148
+ label,
149
+ page: page ?? (typeof window !== "undefined" ? window.location.pathname : "")
150
+ }
151
+ });
152
+ };
153
+ const trackException = (exception) => {
154
+ if (!appInsights || !isInitialized.value) {
155
+ console.warn("Application Insights not initialized, skipping exception tracking");
156
+ return;
157
+ }
158
+ try {
159
+ appInsights.trackException({
160
+ exception: exception.exception,
161
+ properties: buildEventProperties({
162
+ url: typeof window !== "undefined" ? window.location.href : "",
163
+ userAgent: typeof navigator !== "undefined" ? navigator.userAgent : "",
164
+ ...exception.properties
165
+ }),
166
+ measurements: exception.measurements
167
+ });
168
+ } catch (error) {
169
+ console.error("Failed to track exception:", error);
170
+ }
171
+ };
172
+ const trackDependency = (dependency) => {
173
+ if (!appInsights || !isInitialized.value) {
174
+ console.warn("Application Insights not initialized, skipping dependency tracking");
175
+ return;
176
+ }
177
+ try {
178
+ appInsights.trackDependencyData({
179
+ id: `dep-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`,
180
+ name: dependency.name,
181
+ data: dependency.data,
182
+ duration: dependency.duration,
183
+ success: dependency.success,
184
+ responseCode: dependency.resultCode || 0,
185
+ properties: buildEventProperties(dependency.properties),
186
+ measurements: dependency.measurements
187
+ });
188
+ } catch (error) {
189
+ console.error("Failed to track dependency:", error);
190
+ }
191
+ };
192
+ const trackMetric = (metric) => {
193
+ if (!appInsights || !isInitialized.value) {
194
+ console.warn("Application Insights not initialized, skipping metric tracking");
195
+ return;
196
+ }
197
+ try {
198
+ appInsights.trackMetric({
199
+ name: metric.name,
200
+ average: metric.average,
201
+ sampleCount: metric.sampleCount,
202
+ min: metric.min,
203
+ max: metric.max,
204
+ properties: buildEventProperties(metric.properties)
205
+ });
206
+ } catch (error) {
207
+ console.error("Failed to track metric:", error);
208
+ }
209
+ };
210
+ const flush = () => {
211
+ if (!appInsights || !isInitialized.value) return;
212
+ try {
213
+ appInsights.flush();
214
+ } catch (error) {
215
+ console.error("Failed to flush telemetry:", error);
216
+ }
217
+ };
218
+ const startTrackPage = (name) => {
219
+ if (!appInsights || !isInitialized.value) return;
220
+ try {
221
+ appInsights.startTrackPage(name);
222
+ } catch (error) {
223
+ console.error("Failed to start track page:", error);
224
+ }
225
+ };
226
+ const stopTrackPage = (name, url, properties, measurements) => {
227
+ if (!appInsights || !isInitialized.value) return;
228
+ try {
229
+ appInsights.stopTrackPage(name, url, buildEventProperties(properties), measurements);
230
+ } catch (error) {
231
+ console.error("Failed to stop track page:", error);
232
+ }
233
+ };
234
+ return {
235
+ isEnabled,
236
+ isInitialized,
237
+ initializationError,
238
+ initialize,
239
+ flush,
240
+ startTrackPage,
241
+ stopTrackPage,
242
+ trackDependency,
243
+ trackEvent,
244
+ trackException,
245
+ trackMetric,
246
+ trackPageView,
247
+ trackCtaClick
248
+ };
249
+ }
250
+
251
+ export { useTelemetry };
252
+ //# sourceMappingURL=index.js.map
253
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/composable.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { ApplicationInsights } from '@microsoft/applicationinsights-web'\nimport { computed, ref } from 'vue'\n\nimport { DEFAULT_CLOUD_ROLE, createTelemetryConfig } from './config'\nimport type {\n TelemetryDependency,\n TelemetryEvent,\n TelemetryException,\n TelemetryMetric,\n TelemetryOptions,\n TelemetryPageView,\n} from './types'\n\ninterface TelemetryEnvelope {\n data?: {\n baseData?: {\n properties?: Record<string, string>\n }\n }\n tags?: Record<string, string>\n}\n\n// Module-level singleton state: one App Insights instance per app bundle,\n// shared across every `useTelemetry()` call (matches the original per-app\n// composable). The reactive refs let views observe init state.\nlet appInsights: ApplicationInsights | null = null\nconst isInitialized = ref(false)\nconst initializationError = ref<string | null>(null)\n\n// One-shot guards so we surface \"App Insights is not configured\" loudly in\n// DevTools the FIRST time the app tries to use it, but don't spam the console\n// for every subsequent trackEvent / trackPageView call. See web/ site-audit F2\n// — `customEvents = 0` for 7d was a missing connection string silently\n// no-op'ing every telemetry call; the loud warning makes that mode visible.\nlet warnedDisabled = false\nlet warnedNotInitialized = false\n\nfunction resolveAppVersion(explicit?: string): string {\n if (explicit) return explicit\n const w =\n typeof window !== 'undefined'\n ? (window as Window & { __APP_VERSION__?: string })\n : undefined\n return w?.__APP_VERSION__ ?? 'unknown'\n}\n\n/**\n * Azure Application Insights composable for DCS Vue apps.\n *\n * The connection string, cloud role, environment and app version are supplied\n * by the consumer (they read their own `import.meta.env` / build defines and\n * pass plain values in) so this package stays portable and build-tool agnostic.\n * The shared App Insights config — including the `disablePageUnloadEvents:\n * ['unload']` bfcache/Lighthouse fix — comes from {@link createTelemetryConfig}.\n */\nexport function useTelemetry(options: TelemetryOptions = {}) {\n const cloudRole = options.cloudRole ?? DEFAULT_CLOUD_ROLE\n const environment = options.environment ?? 'unknown'\n\n const isEnabled = computed(() => {\n return !!(options.connectionString || options.instrumentationKey)\n })\n\n function buildSharedProperties(): Record<string, string> {\n const appVersion = resolveAppVersion(options.appVersion)\n const referrerHost =\n typeof document !== 'undefined' && document.referrer\n ? (() => {\n try {\n return new URL(document.referrer).hostname\n } catch {\n return 'unknown'\n }\n })()\n : 'direct'\n\n return {\n app_version: appVersion,\n app_name: cloudRole,\n app_host: typeof window !== 'undefined' ? window.location.hostname : '',\n page_path: typeof window !== 'undefined' ? window.location.pathname : '',\n referrer_host: referrerHost,\n }\n }\n\n function buildEventProperties(\n additional?: Record<string, string>,\n ): Record<string, string> {\n return {\n timestamp: new Date().toISOString(),\n environment,\n ...buildSharedProperties(),\n ...additional,\n }\n }\n\n function enrichTelemetryEnvelope(envelope: TelemetryEnvelope) {\n if (!envelope.data) {\n envelope.data = {}\n }\n\n envelope.data.baseData = envelope.data.baseData || {}\n envelope.data.baseData.properties = envelope.data.baseData.properties || {}\n Object.assign(envelope.data.baseData.properties, buildSharedProperties())\n\n const appVersion = resolveAppVersion(options.appVersion)\n envelope.tags = envelope.tags || {}\n envelope.tags['ai.application.ver'] = appVersion\n envelope.tags['ai.cloud.role'] = cloudRole\n envelope.tags['ai.cloud.roleInstance'] =\n typeof window !== 'undefined' ? window.location.hostname : ''\n }\n\n const initialize = (): boolean => {\n try {\n if (isInitialized.value && appInsights) {\n return true\n }\n\n if (!isEnabled.value) {\n if (!warnedDisabled) {\n warnedDisabled = true\n // Loud, one-shot warning so this is obvious in DevTools. If you see\n // this in production, the build pipeline is not injecting the App\n // Insights connection string — every track* call below silently\n // no-ops. See web/ site-audit F2.\n console.warn(\n '[telemetry] Application Insights DISABLED: no connection string ' +\n 'or instrumentation key was provided at build time. ' +\n 'All telemetry calls will silently no-op.',\n )\n }\n return false\n }\n\n appInsights = new ApplicationInsights({\n config: createTelemetryConfig({\n connectionString: options.connectionString,\n instrumentationKey: options.instrumentationKey,\n enableAutoRouteTracking: options.enableAutoRouteTracking,\n dev: options.dev,\n disablePageUnloadEvents: options.disablePageUnloadEvents,\n overrides: options.overrides,\n }),\n })\n\n appInsights.loadAppInsights()\n appInsights.addTelemetryInitializer((envelope) => {\n try {\n enrichTelemetryEnvelope(envelope as TelemetryEnvelope)\n } catch (error) {\n console.warn('Failed to add web telemetry context:', error)\n }\n\n return true\n })\n\n isInitialized.value = true\n initializationError.value = null\n console.log('Application Insights initialized successfully')\n return true\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown initialization error'\n initializationError.value = errorMessage\n console.error('Failed to initialize Application Insights:', error)\n return false\n }\n }\n\n const trackEvent = (event: TelemetryEvent) => {\n if (!appInsights || !isInitialized.value) {\n if (!warnedNotInitialized) {\n warnedNotInitialized = true\n console.warn(\n `[telemetry] Application Insights not initialized — dropping event \"${event.name}\" ` +\n '(and silencing further \"not initialized\" warnings for this session).',\n )\n }\n return\n }\n\n try {\n appInsights.trackEvent({\n name: event.name,\n properties: buildEventProperties(event.properties),\n measurements: event.measurements,\n })\n } catch (error) {\n console.error('Failed to track event:', error)\n }\n }\n\n const trackPageView = (pageView?: TelemetryPageView) => {\n if (!appInsights || !isInitialized.value) {\n console.warn('Application Insights not initialized, skipping page view tracking')\n return\n }\n\n try {\n // Attach the full document.referrer (not just hostname) so we can\n // attribute traffic sources in App Insights pageViews.\n const referrer =\n typeof document !== 'undefined' ? (document.referrer ?? '') : ''\n appInsights.trackPageView({\n name:\n pageView?.name ||\n (typeof document !== 'undefined' ? document.title : undefined),\n uri:\n pageView?.uri ||\n (typeof window !== 'undefined' ? window.location.href : undefined),\n properties: buildEventProperties({\n referrer,\n ...pageView?.properties,\n }),\n measurements: pageView?.measurements,\n })\n } catch (error) {\n console.error('Failed to track page view:', error)\n }\n }\n\n /**\n * Convenience helper for primary CTA conversion measurement. Fires a\n * `cta_click` custom event so conversion rate per landing page can be\n * computed in App Insights / KQL.\n */\n const trackCtaClick = (label: string, page?: string) => {\n trackEvent({\n name: 'cta_click',\n properties: {\n label,\n page:\n page ??\n (typeof window !== 'undefined' ? window.location.pathname : ''),\n },\n })\n }\n\n const trackException = (exception: TelemetryException) => {\n if (!appInsights || !isInitialized.value) {\n console.warn('Application Insights not initialized, skipping exception tracking')\n return\n }\n\n try {\n appInsights.trackException({\n exception: exception.exception,\n properties: buildEventProperties({\n url: typeof window !== 'undefined' ? window.location.href : '',\n userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : '',\n ...exception.properties,\n }),\n measurements: exception.measurements,\n })\n } catch (error) {\n console.error('Failed to track exception:', error)\n }\n }\n\n const trackDependency = (dependency: TelemetryDependency) => {\n if (!appInsights || !isInitialized.value) {\n console.warn('Application Insights not initialized, skipping dependency tracking')\n return\n }\n\n try {\n appInsights.trackDependencyData({\n id: `dep-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`,\n name: dependency.name,\n data: dependency.data,\n duration: dependency.duration,\n success: dependency.success,\n responseCode: dependency.resultCode || 0,\n properties: buildEventProperties(dependency.properties),\n measurements: dependency.measurements,\n })\n } catch (error) {\n console.error('Failed to track dependency:', error)\n }\n }\n\n const trackMetric = (metric: TelemetryMetric) => {\n if (!appInsights || !isInitialized.value) {\n console.warn('Application Insights not initialized, skipping metric tracking')\n return\n }\n\n try {\n appInsights.trackMetric({\n name: metric.name,\n average: metric.average,\n sampleCount: metric.sampleCount,\n min: metric.min,\n max: metric.max,\n properties: buildEventProperties(metric.properties),\n })\n } catch (error) {\n console.error('Failed to track metric:', error)\n }\n }\n\n const flush = () => {\n if (!appInsights || !isInitialized.value) return\n\n try {\n appInsights.flush()\n } catch (error) {\n console.error('Failed to flush telemetry:', error)\n }\n }\n\n const startTrackPage = (name?: string) => {\n if (!appInsights || !isInitialized.value) return\n\n try {\n appInsights.startTrackPage(name)\n } catch (error) {\n console.error('Failed to start track page:', error)\n }\n }\n\n const stopTrackPage = (\n name?: string,\n url?: string,\n properties?: Record<string, string>,\n measurements?: Record<string, number>,\n ) => {\n if (!appInsights || !isInitialized.value) return\n\n try {\n appInsights.stopTrackPage(name, url, buildEventProperties(properties), measurements)\n } catch (error) {\n console.error('Failed to stop track page:', error)\n }\n }\n\n return {\n isEnabled,\n isInitialized,\n initializationError,\n initialize,\n flush,\n startTrackPage,\n stopTrackPage,\n trackDependency,\n trackEvent,\n trackException,\n trackMetric,\n trackPageView,\n trackCtaClick,\n }\n}\n\n/** The full public API returned by {@link useTelemetry}. */\nexport type TelemetryApi = ReturnType<typeof useTelemetry>\n"]}