Skip to content
23 changes: 21 additions & 2 deletions AISKU/src/AISku.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,13 @@ import { IPromise, createPromise, createSyncPromise, doAwaitResponse } from "@ne
import { arrForEach, arrIndexOf, isPromiseLike, objDefine, objForEachKey, strIndexOf, throwUnsupported } from "@nevware21/ts-utils";
import { IApplicationInsights } from "./IApplicationInsights";
import {
CONFIG_ENDPOINT_URL, STR_ADD_TELEMETRY_INITIALIZER, STR_CLEAR_AUTHENTICATED_USER_CONTEXT, STR_EVT_NAMESPACE, STR_GET_COOKIE_MGR,
CONFIG_ENDPOINT_URL, SSR_DISABLED_FEATURE, STR_ADD_TELEMETRY_INITIALIZER, STR_CLEAR_AUTHENTICATED_USER_CONTEXT, STR_EVT_NAMESPACE, STR_GET_COOKIE_MGR,
STR_GET_PLUGIN, STR_POLL_INTERNAL_LOGS, STR_SET_AUTHENTICATED_USER_CONTEXT, STR_SNIPPET, STR_START_TRACK_EVENT, STR_START_TRACK_PAGE,
STR_STOP_TRACK_EVENT, STR_STOP_TRACK_PAGE, STR_TRACK_DEPENDENCY_DATA, STR_TRACK_EVENT, STR_TRACK_EXCEPTION, STR_TRACK_METRIC,
STR_TRACK_PAGE_VIEW, STR_TRACK_TRACE
} from "./InternalConstants";
import { Snippet } from "./Snippet";
import { isServerSideRenderingEnvironment } from "./ApplicationInsightsContainer";

export { IRequestHeaders };

Expand Down Expand Up @@ -82,7 +83,8 @@ const defaultConfigValues: IConfigDefaults<IConfiguration & IConfig> = {
[IKEY_USAGE]: {mode: FeatureOptInMode.enable}, //for versions after 3.1.2 (>= 3.2.0)
[CDN_USAGE]: {mode: FeatureOptInMode.disable},
[SDK_LOADER_VER]: {mode: FeatureOptInMode.disable},
[ZIP_PAYLOAD]: {mode: FeatureOptInMode.none}
[ZIP_PAYLOAD]: {mode: FeatureOptInMode.none},
[SSR_DISABLED_FEATURE]: {mode: FeatureOptInMode.disable} // By default, SSR detection is enabled (so this feature is disabled)
},
throttleMgrCfg: cfgDfMerge<{[key:number]: IThrottleMgrConfig}>(
{
Expand Down Expand Up @@ -322,6 +324,23 @@ export class AppInsightsSku implements IApplicationInsights {
throwUnsupported("Legacy Mode is no longer supported")
}

// Check for Server-Side Rendering environments and skip initialization if detected
const isServerSideEnv = isServerSideRenderingEnvironment();
const ssrDisabled = isFeatureEnabled(SSR_DISABLED_FEATURE, _config, false);
if (isServerSideEnv && !ssrDisabled) {
// Log a message (if logger is available) mentioning the SDK is not loading in SSR mode
if (logger) {
logger.warnToConsole("Application Insights SDK is not initializing in server-side rendering environment. " +
"This is by design to avoid issues in Angular SSR and similar environments. " +
"To disable this check, set the feature flag 'ssr_disabled' to true in the config.");
} else if (typeof console !== "undefined" && console) {
console.warn("Application Insights SDK is not initializing in server-side rendering environment. " +
"This is by design to avoid issues in Angular SSR and similar environments. " +
"To disable this check, set the feature flag 'ssr_disabled' to true in the config.");
}
return _self;
}

function _updateSnippetProperties(snippet: Snippet) {
if (snippet) {
let snippetVer = "";
Expand Down
39 changes: 38 additions & 1 deletion AISKU/src/ApplicationInsightsContainer.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,45 @@
import { throwUnsupported } from "@nevware21/ts-utils";
import { hasWindow, isUndefined, throwUnsupported } from "@nevware21/ts-utils";
import { AppInsightsSku } from "./AISku";
import { IApplicationInsights } from "./IApplicationInsights";
import { Snippet } from "./Snippet";

/**
* Detects if the current environment is a server-side rendering environment.
* This is used to prevent the SDK from initializing in environments like
* Angular SSR in Cloudflare Workers where certain operations are prohibited.
* @returns {boolean} True if the environment appears to be server-side rendering
*/
export function isServerSideRenderingEnvironment(): boolean {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No!
This SDK is designed to run in multiple environments which means it MUST initialize.
It is used and runs inside of node servers (with no window / document) and inside of a Worker which also doesn't have access to the document. As well as other environments that don't provides these.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've modified the SSR detection to only check for the specific property redefinition issue in Cloudflare Workers, instead of broadly preventing initialization in all server-side environments. The SDK will now initialize properly in Node.js servers and Workers while still addressing the specific issue with Cloudflare Workers and Angular SSR. Changes in commit db27b5e.

// Check for typical SSR environments:
// 1. No window object (Node.js, most SSR)
// 2. Window exists but document is not fully initialized (some hybrid SSR)
// 3. Process exists and is running in a Node-like environment

// Check if we're in a non-browser environment
if (!hasWindow()) {
return true;
}

// Check for Angular Universal/SSR specific indicators
const win = window as any;
if (win && typeof win === 'object') {
// Angular Universal might have these properties
if (win["process"] && win["process"]["browser"] === false) {
return true;
}
}

// Check for CloudFlare worker environment
if (typeof self !== 'undefined' && typeof self.WorkerGlobalScope !== 'undefined') {
// Additional CloudFlare worker check
if (self instanceof self.WorkerGlobalScope) {
return true;
}
}

return false;
}

export class ApplicationInsightsContainer {

public static getAppInsights(snippet: Snippet, version: number) : IApplicationInsights {
Expand Down
1 change: 1 addition & 0 deletions AISKU/src/InternalConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@ export const STR_TRACK_DEPENDENCY_DATA = _TRACK + "DependencyData" as "trackDepe
export const STR_SET_AUTHENTICATED_USER_CONTEXT = "set" + _AUTHENTICATED_USER_CONTEXT as "setAuthenticatedUserContext";
export const STR_CLEAR_AUTHENTICATED_USER_CONTEXT = "clear" + _AUTHENTICATED_USER_CONTEXT as "clearAuthenticatedUserContext";
export const CONFIG_ENDPOINT_URL = "https://js.monitor.azure.com/scripts/b/ai.config.1.cfg.json";
export const SSR_DISABLED_FEATURE = "ssr_disabled"; // Feature flag to disable SSR detection
2 changes: 1 addition & 1 deletion AISKU/src/applicationinsights-web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ export { Snippet } from "./Snippet";
export { IApplicationInsights } from "./IApplicationInsights";
export { AppInsightsSku as ApplicationInsights } from "./AISku";

export { ApplicationInsightsContainer } from "./ApplicationInsightsContainer";
export { ApplicationInsightsContainer, isServerSideRenderingEnvironment } from "./ApplicationInsightsContainer";
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove isServerSideRenderEnvironment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed isServerSideRenderEnvironment function from the export in applicationinsights-web.ts in commit 33ad868.


// Re-exports
export {
Expand Down