Repository: microsoft/ApplicationInsights-node.js
Pull request #1183 (2023-08-12 01:19:24)

[Shim] Fully Support JSON Configuration
* Support configuring the SDK via both the JSON file and environment variables


Patch:
diff --git a/src/shared/util/configHelper.ts b/src/shared/util/configHelper.ts
index 8aab205..74cd62b 100644
--- a/src/shared/util/configHelper.ts
+++ b/src/shared/util/configHelper.ts
@@ -66,7 +66,7 @@ export function setAutoCollectDependencies(options: ApplicationInsightsOptions,
     }
 }
 
-export function setAutoCollectConsole(options: ApplicationInsightsOptions, value: boolean, enableConsole: boolean, collectConsoleLog = false) {
+export function setAutoCollectConsole(options: ApplicationInsightsOptions, value: boolean, collectConsoleLog = false) {
     if (options) {
         options.logInstrumentations = {
             bunyan: { enabled: value },
@@ -75,3 +75,64 @@ export function setAutoCollectConsole(options: ApplicationInsightsOptions, value
         }
     }
 }
+
+export function enableAutoCollectExternalLoggers(options: ApplicationInsightsOptions, value: boolean) {
+    options.logInstrumentations = {
+        ...options.logInstrumentations,
+        winston: { enabled: value },
+        bunyan: { enabled: value },
+    }
+}
+
+export function enableAutoCollectConsole(options: ApplicationInsightsOptions, value: boolean) {
+    options.logInstrumentations = {
+        ...options.logInstrumentations,
+        console: { enabled: value },
+    }
+}
+
+export function enableAutoCollectExtendedMetrics(options: ApplicationInsightsOptions, value: boolean) {
+    options.extendedMetrics = {
+        [ExtendedMetricType.gc]: value,
+        [ExtendedMetricType.heap]: value,
+        [ExtendedMetricType.loop]: value,
+    }
+}
+
+export function setMaxBatchIntervalMs(options: ApplicationInsightsOptions, value: number) {
+    options.otlpTraceExporterConfig = { ...options.otlpTraceExporterConfig, timeoutMillis: value };
+    options.otlpMetricExporterConfig = { ...options.otlpMetricExporterConfig, timeoutMillis: value };
+    options.otlpLogExporterConfig = { ...options.otlpLogExporterConfig, timeoutMillis: value };
+}
+
+export function setProxyUrl(options: ApplicationInsightsOptions, proxyUrlString: string) {
+    const proxyUrl = new URL(proxyUrlString);
+    options.azureMonitorExporterConfig.proxyOptions = {
+        host: proxyUrl.hostname,
+        port: Number(proxyUrl.port),
+    }
+}
+
+export function setExtendedMetricDisablers(options: ApplicationInsightsOptions, disablers: string) {
+    const extendedMetricDisablers: string[] = disablers.split(",");
+    for (const extendedMetricDisabler of extendedMetricDisablers) {
+        if (extendedMetricDisabler === "gc") {
+            options.extendedMetrics = {
+                ...options.extendedMetrics,
+                [ExtendedMetricType.gc]: false
+            };
+        }
+        if (extendedMetricDisabler === "heap") {
+            options.extendedMetrics = {
+                ...options.extendedMetrics,
+                [ExtendedMetricType.heap]: false
+            };
+        }
+        if (extendedMetricDisabler === "loop") {
+            options.extendedMetrics = {
+                ...options.extendedMetrics,
+                [ExtendedMetricType.loop]: false
+            };
+        }
+    }
+}
diff --git a/src/shim/config.ts b/src/shim/config.ts
index a141a97..a844349 100644
--- a/src/shim/config.ts
+++ b/src/shim/config.ts
@@ -2,8 +2,8 @@ import { DistributedTracingModes, IConfig, IDisabledExtendedMetrics, IWebInstrum
 import http = require("http");
 import https = require("https");
 import azureCoreAuth = require("@azure/core-auth");
+import { ShimJsonConfig } from "./shim-jsonConfig";
 import { Logger } from "../shared/logging";
-import constants = require("../declarations/constants");
 
 class config implements IConfig {
 
@@ -61,8 +61,6 @@ class config implements IConfig {
     public enableAutoWebSnippetInjection: boolean;
 
     public correlationId: string; // TODO: Should be private NOTE: This is not noted in the README
-    private _connectionString: string;
-    private _endpointBase: string = constants.DEFAULT_BREEZE_ENDPOINT;
 
     private _instrumentationKey: string;
     public _webInstrumentationConnectionString: string;
@@ -72,17 +70,12 @@ class config implements IConfig {
 
     constructor(setupString?: string) {
         this.instrumentationKey = setupString;
-
-        this.maxBatchSize = this.maxBatchSize || 250;
-        this.maxBatchIntervalMs = this.maxBatchIntervalMs || 15000;
-        this.disableAppInsights = this.disableAppInsights || false;
-        this.samplingPercentage = this.samplingPercentage || 100;
-        this.correlationIdRetryIntervalMs = this.correlationIdRetryIntervalMs || 30 * 1000;
         // this.enableWebInstrumentation = this.enableWebInstrumentation || this.enableAutoWebSnippetInjection || false;
         this.webInstrumentationConfig = this.webInstrumentationConfig || null;
         // this.enableAutoWebSnippetInjection = this.enableWebInstrumentation;
         this.correlationHeaderExcludedDomains =
             this.correlationHeaderExcludedDomains ||
+            ShimJsonConfig.getInstance().correlationHeaderExcludedDomains ||
             [
                 "*.core.windows.net",
                 "*.core.chinacloudapi.cn",
@@ -139,6 +132,11 @@ class config implements IConfig {
     * Fifth section has 12 characters
     */
     private static _validateInstrumentationKey(iKey: string): boolean {
+        if (iKey.startsWith("InstrumentationKey=")) {
+            const startIndex = iKey.indexOf("InstrumentationKey=") + "InstrumentationKey=".length;
+            const endIndex = iKey.indexOf(";", startIndex);
+            iKey = iKey.substring(startIndex, endIndex);
+        }
         const UUID_Regex = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$";
         const regexp = new RegExp(UUID_Regex);
         return regexp.test(iKey);
diff --git a/src/shim/shim-jsonConfig.ts b/src/shim/shim-jsonConfig.ts
new file mode 100644
index 0000000..a0aeb4a
--- /dev/null
+++ b/src/shim/shim-jsonConfig.ts
@@ -0,0 +1,179 @@
+import * as fs from "fs";
+import * as path from "path";
+import { Logger } from "../shared/logging/logger";
+import { DistributedTracingModes, IDisabledExtendedMetrics, IJsonConfig, IWebInstrumentationConfig } from "./types";
+import * as http from "http";
+import * as https from "https";
+import * as azureCoreAuth from "@azure/core-auth";
+
+const ENV_CONFIGURATION_FILE = "APPLICATIONINSIGHTS_CONFIGURATION_FILE";
+const ENV_CONTENT = "APPLICATIONINSIGHTS_CONFIGURATION_CONTENT";
+
+const ENV_connectionString = "APPLICATIONINSIGHTS_CONNECTION_STRING";
+const ENV_azurePrefix = "APPSETTING_"; // Azure adds this prefix to all environment variables
+const ENV_instrumentationKey = "APPINSIGHTS_INSTRUMENTATIONKEY";
+const ENV_legacyInstrumentationKey = "APPINSIGHTS_INSTRUMENTATION_KEY"
+const ENV_nativeMetricsDisablers = "APPLICATION_INSIGHTS_DISABLE_EXTENDED_METRIC";
+const ENV_nativeMetricsDisableAll = "APPLICATION_INSIGHTS_DISABLE_ALL_EXTENDED_METRICS";
+const ENV_http_proxy = "http_proxy";
+const ENV_https_proxy = "https_proxy";
+const ENV_noDiagnosticChannel = "APPLICATION_INSIGHTS_NO_DIAGNOSTIC_CHANNEL";
+const ENV_noStatsbeat = "APPLICATION_INSIGHTS_NO_STATSBEAT";
+const ENV_noHttpAgentKeepAlive = "APPLICATION_INSIGHTS_NO_HTTP_AGENT_KEEP_ALIVE";
+const ENV_noPatchModules = "APPLICATION_INSIGHTS_NO_PATCH_MODULES";
+
+export class ShimJsonConfig implements IJsonConfig {
+    private static _instance: ShimJsonConfig;
+
+    public endpointUrl: string;
+    public connectionString: string;
+    public instrumentationKey: string;
+    public disableAllExtendedMetrics: boolean;
+    public extendedMetricDisablers: string;
+    public proxyHttpUrl: string;
+    public proxyHttpsUrl: string;
+    public noDiagnosticChannel: boolean;
+    public disableStatsbeat: boolean;
+    public noHttpAgentKeepAlive: boolean;
+    public noPatchModules: string;
+    public maxBatchSize: number;
+    public maxBatchIntervalMs: number;
+    public disableAppInsights: boolean;
+    public samplingPercentage: number;
+    public correlationIdRetryIntervalMs: number;
+    public correlationHeaderExcludedDomains: string[];
+    public httpAgent: http.Agent;
+    public httpsAgent: https.Agent;
+    public ignoreLegacyHeaders: boolean;
+    public aadTokenCredential?: azureCoreAuth.TokenCredential;
+    public enableAutoCollectConsole: boolean;
+    public enableLoggerErrorToTrace: boolean;
+    public enableAutoCollectPerformance: boolean;
+    public enableAutoCollectExternalLoggers: boolean;
+    public enableAutoCollectPreAggregatedMetrics: boolean;
+    public enableAutoCollectHeartbeat: boolean;
+    public enableAutoCollectRequests: boolean;
+    public enableAutoCollectDependencies: boolean;
+    public enableAutoDependencyCorrelation: boolean;
+    public enableAutoCollectIncomingRequestAzureFunctions: boolean;
+    public enableSendLiveMetrics: boolean;
+    public enableUseDiskRetryCaching: boolean;
+    public enableUseAsyncHooks: boolean;
+    public distributedTracingMode: DistributedTracingModes;
+    public enableAutoCollectExtendedMetrics: boolean | IDisabledExtendedMetrics;
+    public enableResendInterval: number;
+    public enableMaxBytesOnDisk: number;
+    public enableInternalDebugLogging: boolean;
+    public enableInternalWarningLogging: boolean;
+    public quickPulseHost: string;
+    public enableWebInstrumentation: boolean;
+    public enableAutoCollectExceptions: boolean;
+    public webInstrumentationConnectionString?: string;
+    public webInstrumentationConfig: IWebInstrumentationConfig[];
+    public webInstrumentationSrc: string;
+    public enableAutoWebSnippetInjection?: boolean;
+    public webSnippetConnectionString?: string;
+
+    public static getInstance() {
+        if (!ShimJsonConfig._instance) {
+            ShimJsonConfig._instance = new ShimJsonConfig();
+        }
+        return ShimJsonConfig._instance;
+    }
+
+    constructor() {
+        // Load environment variables first
+        this.connectionString = process.env[ENV_connectionString];
+        this.instrumentationKey = process.env[ENV_instrumentationKey]
+            || process.env[ENV_azurePrefix + ENV_instrumentationKey]
+            || process.env[ENV_legacyInstrumentationKey]
+            || process.env[ENV_azurePrefix + ENV_legacyInstrumentationKey];
+        this._loadJsonFile();
+        if (!this.connectionString && this.instrumentationKey) {
+            Logger.getInstance().warn("APPINSIGHTS_INSTRUMENTATIONKEY is in path of deprecation, please use APPLICATIONINSIGHTS_CONNECTION_STRING env variable to setup the SDK.");
+        }
+        this.disableAllExtendedMetrics = !!process.env[ENV_nativeMetricsDisableAll];
+        this.extendedMetricDisablers = process.env[ENV_nativeMetricsDisablers];
+        this.proxyHttpUrl = process.env[ENV_http_proxy] ? process.env[ENV_http_proxy] : this.proxyHttpUrl;
+        this.proxyHttpsUrl = process.env[ENV_https_proxy] ? process.env[ENV_https_proxy] : this.proxyHttpsUrl;
+        this.noDiagnosticChannel = process.env[ENV_noDiagnosticChannel] ? !!process.env[ENV_noDiagnosticChannel] : this.noDiagnosticChannel;
+        this.disableStatsbeat = !!process.env[ENV_noStatsbeat];
+        this.noHttpAgentKeepAlive = process.env[ENV_noHttpAgentKeepAlive] ? !!process.env[ENV_noHttpAgentKeepAlive] : this.noHttpAgentKeepAlive;
+        this.noPatchModules = process.env[ENV_noPatchModules] ? process.env[ENV_noPatchModules] : this.noPatchModules || "";
+    }
+
+    private _loadJsonFile() {
+        let jsonString = "";
+        const contentJsonConfig = process.env[ENV_CONTENT];
+        // JSON string added directly in env variable
+        if (contentJsonConfig) {
+            jsonString = contentJsonConfig;
+        }
+        // JSON file
+        else {
+            const configFileName = "applicationinsights.json";
+            const rootPath = path.join(__dirname, "../../../../"); // Root of folder (__dirname = ../dist-esm/src)
+            let tempDir = path.join(rootPath, configFileName); // default
+            const configFile = process.env[ENV_CONFIGURATION_FILE];
+            if (configFile) {
+                if (path.isAbsolute(configFile)) {
+                    tempDir = configFile;
+                } else {
+                    tempDir = path.join(rootPath, configFile); // Relative path to applicationinsights folder
+                }
+            }
+            try {
+                jsonString = fs.readFileSync(tempDir, "utf8");
+            } catch (err) {
+                Logger.getInstance().info("Failed to read JSON config file: ", err);
+            }
+        }
+        try {
+            const jsonConfig: IJsonConfig = JSON.parse(jsonString);
+            this.connectionString = jsonConfig.connectionString;
+            this.enableAutoCollectExceptions = jsonConfig.enableAutoCollectExceptions;
+            this.instrumentationKey = jsonConfig.instrumentationKey;
+            this.endpointUrl = jsonConfig.endpointUrl;
+            this.samplingPercentage = jsonConfig.samplingPercentage;
+            this.enableAutoCollectExternalLoggers = jsonConfig.enableAutoCollectExternalLoggers;
+            this.enableAutoCollectConsole = jsonConfig.enableAutoCollectConsole;
+            this.enableLoggerErrorToTrace = jsonConfig.enableLoggerErrorToTrace;
+            this.enableAutoCollectExceptions = jsonConfig.enableAutoCollectExceptions;
+            this.enableAutoCollectPerformance = jsonConfig.enableAutoCollectPerformance;
+            this.enableAutoCollectPreAggregatedMetrics = jsonConfig.enableAutoCollectPreAggregatedMetrics;
+            this.enableAutoDependencyCorrelation = jsonConfig.enableAutoDependencyCorrelation;
+            this.maxBatchSize = jsonConfig.maxBatchSize;
+            this.maxBatchIntervalMs = jsonConfig.maxBatchIntervalMs;
+            this.disableAppInsights = jsonConfig.disableAppInsights;
+            this.correlationHeaderExcludedDomains = jsonConfig.correlationHeaderExcludedDomains;
+            this.ignoreLegacyHeaders = jsonConfig.ignoreLegacyHeaders;
+            this.distributedTracingMode = jsonConfig.distributedTracingMode;
+            this.enableAutoCollectExtendedMetrics = jsonConfig.enableAutoCollectExtendedMetrics;
+            this.enableAutoCollectHeartbeat = jsonConfig.enableAutoCollectHeartbeat;
+            this.enableAutoCollectRequests = jsonConfig.enableAutoCollectRequests;
+            this.enableAutoCollectDependencies = jsonConfig.enableAutoCollectDependencies;
+            this.enableAutoCollectIncomingRequestAzureFunctions = jsonConfig.enableAutoCollectIncomingRequestAzureFunctions;
+            this.enableUseAsyncHooks = jsonConfig.enableUseAsyncHooks;
+            this.enableUseDiskRetryCaching = jsonConfig.enableUseDiskRetryCaching;
+            this.enableResendInterval = jsonConfig.enableResendInterval;
+            this.enableMaxBytesOnDisk = jsonConfig.enableMaxBytesOnDisk;
+            this.enableInternalDebugLogging = jsonConfig.enableInternalDebugLogging;
+            this.enableInternalWarningLogging = jsonConfig.enableInternalWarningLogging;
+            this.enableSendLiveMetrics = jsonConfig.enableSendLiveMetrics;
+            this.disableAllExtendedMetrics = jsonConfig.disableAllExtendedMetrics;
+            this.extendedMetricDisablers = jsonConfig.extendedMetricDisablers;
+            this.noDiagnosticChannel = jsonConfig.noDiagnosticChannel;
+            this.noPatchModules = jsonConfig.noPatchModules;
+            this.noHttpAgentKeepAlive = jsonConfig.noHttpAgentKeepAlive;
+            this.proxyHttpUrl = jsonConfig.proxyHttpUrl;
+            this.proxyHttpsUrl = jsonConfig.proxyHttpsUrl;
+            this.webInstrumentationConnectionString = jsonConfig.webInstrumentationConnectionString;
+            this.webInstrumentationConfig = jsonConfig.webInstrumentationConfig;
+            this.webInstrumentationSrc = jsonConfig.webInstrumentationSrc;
+            this.enableAutoWebSnippetInjection = jsonConfig.enableAutoWebSnippetInjection;
+            this.webSnippetConnectionString = jsonConfig.webSnippetConnectionString;
+        } catch (err) {
+            Logger.getInstance().info("Missing or invalid JSON config file: ", err);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/shim/telemetryClient.ts b/src/shim/telemetryClient.ts
index b5f0ab5..88f3078 100644
--- a/src/shim/telemetryClient.ts
+++ b/src/shim/telemetryClient.ts
@@ -20,6 +20,7 @@ import { IConfig } from "../shim/types";
 import Config = require("./config");
 import { dispose, Configuration, _setupCalled } from "./shim-applicationinsights";
 import { HttpInstrumentationConfig } from "@opentelemetry/instrumentation-http";
+import { ShimJsonConfig } from "./shim-jsonConfig";
 import ConfigHelper = require("../shared/util/configHelper");
 
 /**
@@ -70,7 +71,7 @@ export class TelemetryClient {
      * Parse the config property to set the appropriate values on the ApplicationInsightsOptions
      * @param input 
      */
-    private _parseConfig(input?: ApplicationInsightsOptions) {
+    private _parseConfig(jsonConfig: ShimJsonConfig, input?: ApplicationInsightsOptions) {
         // If we have a defined input (in the case that we are initializing from the start method) then we should use that
         if (input) {
             this._options = input;
@@ -81,13 +82,12 @@ export class TelemetryClient {
             dispose();
         }
 
-        if (this.config.instrumentationKey && this.config.endpointUrl) {
-            this._options.azureMonitorExporterConfig.connectionString = `InstrumentationKey=${this.config.instrumentationKey};IngestionEndpoint=${this.config.endpointUrl}`;
+        if (this.config.samplingPercentage) {
+            this._options.samplingRatio = this.config.samplingPercentage / 100;
         }
 
-        this._options.samplingRatio = this.config.samplingPercentage ? (this.config.samplingPercentage / 100) : 1;
-
         this._options.instrumentationOptions = {
+            ...this._options.instrumentationOptions,
             http: {
                 ...input?.instrumentationOptions?.http,
                 ignoreOutgoingUrls: this.config.correlationHeaderExcludedDomains,
@@ -99,11 +99,7 @@ export class TelemetryClient {
         }
 
         if (typeof(this.config.enableAutoCollectConsole) === "boolean") {
-            const setting: boolean = this.config.enableAutoCollectConsole;
-            this._options.logInstrumentations = {
-                ...this._options.logInstrumentations,
-                console: { enabled: setting },
-            }
+            ConfigHelper.enableAutoCollectConsole(this._options, this.config.enableAutoCollectConsole);
         }
 
         if (typeof(this.config.enableAutoCollectExceptions) === "boolean") {
@@ -123,18 +119,17 @@ export class TelemetryClient {
         }
 
         if (typeof(this.config.enableAutoCollectExternalLoggers) === "boolean") {
-            this._options.logInstrumentations = {
-                ...this._options.logInstrumentations,
-                winston: { enabled: this.config.enableAutoCollectExternalLoggers },
-                bunyan: { enabled: this.config.enableAutoCollectExternalLoggers },
-            }
+            ConfigHelper.enableAutoCollectExternalLoggers(this._options, this.config.enableAutoCollectExternalLoggers);
         }
 
         if (typeof(this.config.enableAutoCollectPreAggregatedMetrics) === "boolean") {
             this._options.enableAutoCollectStandardMetrics = this.config.enableAutoCollectPreAggregatedMetrics;
         }
 
-        if (typeof(this.config.enableAutoCollectHeartbeat) === "boolean") {
+        if (
+            typeof(this.config.enableAutoCollectHeartbeat) === "boolean" ||
+            typeof(jsonConfig.enableAutoCollectHeartbeat) === "boolean"
+        ) {
             Configuration.setAutoCollectHeartbeat(this.config.enableAutoCollectHeartbeat);
         }
 
@@ -154,7 +149,7 @@ export class TelemetryClient {
             Configuration.setUseDiskRetryCaching(this.config.enableUseDiskRetryCaching);
         }
 
-        if (this.config.enableUseAsyncHooks === false) {
+        if (this.config.enableUseAsyncHooks === false || jsonConfig.enableUseAsyncHooks === false) {
             Logger.getInstance().warn("The use of non async hooks is no longer supported.");
         }
 
@@ -163,12 +158,7 @@ export class TelemetryClient {
         }
 
         if (typeof(this.config.enableAutoCollectExtendedMetrics) === "boolean") {
-            const setting = this.config.enableAutoCollectExtendedMetrics;
-            this._options.extendedMetrics = {
-                [ExtendedMetricType.gc]: setting,
-                [ExtendedMetricType.heap]: setting,
-                [ExtendedMetricType.loop]: setting,
-            }
+            ConfigHelper.enableAutoCollectExtendedMetrics(this._options, this.config.enableAutoCollectExtendedMetrics);
         }
 
         if (this.config.enableResendInterval) {
@@ -180,76 +170,280 @@ export class TelemetryClient {
         }
 
         if (typeof(this.config.enableInternalDebugLogging) === "boolean") {
-            if (this.config.enableInternalDebugLogging) {
-                Logger.getInstance().updateLogLevel(DiagLogLevel.DEBUG);
-            }
+            Logger.getInstance().updateLogLevel(DiagLogLevel.DEBUG);
         }
 
         if (typeof(this.config.enableInternalWarningLogging) === "boolean") {
-            if (this.config.enableInternalWarningLogging) {
-                Logger.getInstance().updateLogLevel(DiagLogLevel.WARN);
-            }
+            Logger.getInstance().updateLogLevel(DiagLogLevel.WARN);
         }
 
-        // Disable or enable all extended metrics
-        if (this.config.disableAllExtendedMetrics === true) {
+        if (
+            this.config.disableAllExtendedMetrics === true ||
+            jsonConfig.disableAllExtendedMetrics === true
+        ) {
             for (const type in this._options.extendedMetrics) {
                 this._options.extendedMetrics[type] = false;
             }
             this._options.extendedMetrics = {
+                ...this._options.extendedMetrics,
                 [ExtendedMetricType.gc]: false,
                 [ExtendedMetricType.heap]: false,
                 [ExtendedMetricType.loop]: false,
             };
         }
 
-        if (typeof(this.config.disableStatsbeat) === "boolean") {
+        if (typeof(this.config.disableStatsbeat || jsonConfig.disableStatsbeat) === "boolean") {
             Logger.getInstance().warn("The disableStatsbeat configuration option is deprecated.");
         }
 
         if (this.config.extendedMetricDisablers) {
-            const disabler = this.config.extendedMetricDisablers;
-            this._options.extendedMetrics[disabler] = false;
+            ConfigHelper.setExtendedMetricDisablers(this._options, this.config.extendedMetricDisablers);
         }
 
-        if (this.config.ignoreLegacyHeaders === false) {
+        if (this.config.ignoreLegacyHeaders === false || jsonConfig.ignoreLegacyHeaders === false) {
             Logger.getInstance().warn("LegacyHeaders are not supported by the shim.");
         }
 
         if (this.config.proxyHttpUrl || this.config.proxyHttpsUrl) {
-            const proxyUrl = new URL(this.config.proxyHttpsUrl || this.config.proxyHttpUrl);
-            this._options.azureMonitorExporterConfig.proxyOptions = {
-                host: proxyUrl.hostname,
-                port: Number(proxyUrl.port),
-            }
+            ConfigHelper.setProxyUrl(this._options, this.config.proxyHttpsUrl || this.config.proxyHttpUrl);
         }
 
-        if (this.config.maxBatchSize) {
+        if (this.config.maxBatchSize || jsonConfig.maxBatchSize) {
             Logger.getInstance().warn("The maxBatchSize configuration option is not supported by the shim.");
         }
 
         if (this.config.maxBatchIntervalMs) {
-            this._options.otlpTraceExporterConfig = { ...this._options.otlpTraceExporterConfig, timeoutMillis: this.config.maxBatchIntervalMs };
-            this._options.otlpMetricExporterConfig = { ...this._options.otlpMetricExporterConfig, timeoutMillis: this.config.maxBatchIntervalMs };
-            this._options.otlpLogExporterConfig = { ...this._options.otlpLogExporterConfig, timeoutMillis: this.config.maxBatchIntervalMs };
+            ConfigHelper.setMaxBatchIntervalMs(this._options, this.config.maxBatchIntervalMs);
         }
 
-        if (this.config.correlationIdRetryIntervalMs) {
+        if (this.config.correlationIdRetryIntervalMs || jsonConfig.correlationIdRetryIntervalMs) {
             Logger.getInstance().warn("The correlationIdRetryIntervalMs configuration option is not supported by the shim.");
         }
 
-        if (this.config.enableLoggerErrorToTrace) {
+        if (this.config.enableLoggerErrorToTrace || jsonConfig.enableLoggerErrorToTrace) {
             Logger.getInstance().warn("The enableLoggerErrorToTrace configuration option is not supported by the shim.");
         }
 
-        if (this.config.httpAgent || this.config.httpsAgent) {
+        if (this.config.httpAgent || this.config.httpsAgent || jsonConfig.httpAgent || jsonConfig.httpsAgent) {
             Logger.getInstance().warn("The httpAgent and httpsAgent configuration options are not supported by the shim.");
         }
 
-        if (this.config.enableWebInstrumentation || this.config.webInstrumentationConfig || this.config.webInstrumentationSrc || this.config.webInstrumentationConnectionString) {
+        if (
+            this.config.enableWebInstrumentation || this.config.webInstrumentationConfig || this.config.webInstrumentationSrc || this.config.webInstrumentationConnectionString ||
+            jsonConfig.enableWebInstrumentation || jsonConfig.webInstrumentationConfig || jsonConfig.webInstrumentationSrc || jsonConfig.webInstrumentationConnectionString
+        ) {
             Logger.getInstance().warn("The webInstrumentation configuration options are not supported by the shim.");
         }
     }
+
+    /**
+     * Parse the JSON config file to set the appropriate values on the ApplicationInsightsOptions
+     */
+    private _parseJson(jsonConfig: ShimJsonConfig) {
+        const resendInterval: number | undefined = jsonConfig.enableResendInterval;
+
+        if (jsonConfig.instrumentationKey || jsonConfig.endpointUrl) {
+            Logger.getInstance().warn("Please pass a connection string to the setup method to initialize the SDK client.");
+        }
+
+        if (jsonConfig.connectionString) {
+            this._options.azureMonitorExporterConfig.connectionString = jsonConfig.connectionString;
+        }
+
+        if (jsonConfig.disableAppInsights) {
+            dispose();
+        }
+
+        if (jsonConfig.samplingPercentage) {
+            this._options.samplingRatio = jsonConfig.samplingPercentage / 100;
+        }
+
+        this._options.instrumentationOptions = {
+            http: {
+                ...this._options?.instrumentationOptions?.http,
+                ignoreOutgoingUrls: jsonConfig.correlationHeaderExcludedDomains,
+            } as HttpInstrumentationConfig,
+        }
+
+        if (jsonConfig.distributedTracingMode) {
+            Configuration.setDistributedTracingMode(jsonConfig.distributedTracingMode);
+        }
+
+        if (jsonConfig.enableAutoCollectExternalLoggers) {
+            ConfigHelper.enableAutoCollectExternalLoggers(this._options, jsonConfig.enableAutoCollectExternalLoggers);
+        }
+
+        if (jsonConfig.enableAutoCollectConsole) {
+            ConfigHelper.enableAutoCollectConsole(this._options, jsonConfig.enableAutoCollectConsole);
+        }
+
+        if (jsonConfig.enableAutoCollectExceptions) {
+            this._options.enableAutoCollectExceptions = jsonConfig.enableAutoCollectExceptions;
+        }
+
+        if (jsonConfig.enableAutoCollectPerformance) {
+            ConfigHelper.setAutoCollectPerformance(this._options, jsonConfig.enableAutoCollectPerformance);
+        }
+
+        if (typeof(jsonConfig.enableAutoCollectExtendedMetrics) === "boolean") {
+            ConfigHelper.enableAutoCollectExtendedMetrics(this._options, jsonConfig.enableAutoCollectExtendedMetrics);
+        }
+
+        if (jsonConfig.enableAutoCollectRequests) {
+            ConfigHelper.setAutoCollectRequests(this._options, jsonConfig.enableAutoCollectRequests);
+        }
+
+        if (jsonConfig.enableAutoCollectDependencies) {
+            ConfigHelper.setAutoCollectDependencies(this._options, jsonConfig.enableAutoCollectDependencies);
+        }
+
+        if (typeof(jsonConfig.enableAutoDependencyCorrelation) === "boolean") {
+            Configuration.setAutoDependencyCorrelation(jsonConfig.enableAutoDependencyCorrelation);
+        }
+
+        if (jsonConfig.maxBatchIntervalMs) {
+            ConfigHelper.setMaxBatchIntervalMs(this._options, jsonConfig.maxBatchIntervalMs);
+        }
+
+        if (jsonConfig.proxyHttpUrl || jsonConfig.proxyHttpsUrl) {
+            ConfigHelper.setProxyUrl(this._options, jsonConfig.proxyHttpsUrl || jsonConfig.proxyHttpUrl);
+        }
+
+        if (jsonConfig.enableAutoCollectIncomingRequestAzureFunctions) {
+            Configuration.setAutoCollectIncomingRequestAzureFunctions(jsonConfig.enableAutoCollectIncomingRequestAzureFunctions);
+        }
+
+        if (jsonConfig.enableUseDiskRetryCaching) {
+            Configuration.setUseDiskRetryCaching(jsonConfig.enableUseDiskRetryCaching);
+        }
+
+        if (jsonConfig.enableResendInterval) {
+            Configuration.setUseDiskRetryCaching(true, jsonConfig.enableResendInterval);
+        }
+
+        if (jsonConfig.enableMaxBytesOnDisk) {
+            Configuration.setUseDiskRetryCaching(true, resendInterval, jsonConfig.enableMaxBytesOnDisk);
+        }
+
+        if (jsonConfig.enableInternalDebugLogging) {
+            Logger.getInstance().updateLogLevel(DiagLogLevel.DEBUG);
+        }
+
+        if (jsonConfig.enableInternalWarningLogging) {
+            Logger.getInstance().updateLogLevel(DiagLogLevel.WARN);
+        }
+
+        if (jsonConfig.enableSendLiveMetrics) {
+            Configuration.setSendLiveMetrics(jsonConfig.enableSendLiveMetrics);
+        }
+
+        if (jsonConfig.extendedMetricDisablers) {
+            ConfigHelper.setExtendedMetricDisablers(this._options, jsonConfig.extendedMetricDisablers);
+        }
+
+        if (jsonConfig.noDiagnosticChannel) {
+            this._options.instrumentationOptions = {
+                azureSdk: { enabled: false },
+                http: { enabled: false },
+                mongoDb: { enabled: false },
+                mySql: { enabled: false },
+                postgreSql: { enabled: false },
+                redis: { enabled: false },
+                redis4: { enabled: false },
+            }
+            this._options.logInstrumentations = {
+                console: { enabled: false },
+                winston: { enabled: false },
+                bunyan: { enabled: false },
+            }
+        }
+
+        if (jsonConfig.noPatchModules) {
+            const modules: string[] = jsonConfig.noPatchModules.split(",");
+            for (const module of modules) {
+                switch (module) {
+                    case "console":
+                        this._options.logInstrumentations = {
+                            ...this._options.logInstrumentations,
+                            console: { enabled: false },
+                        }
+                        break;
+                    case "winston":
+                        this._options.logInstrumentations = {
+                            ...this._options.logInstrumentations,
+                            winston: { enabled: false },
+                        }
+                        break;
+                    case "bunyan":
+                        this._options.logInstrumentations = {
+                            ...this._options.logInstrumentations,
+                            bunyan: { enabled: false },
+                        }
+                        break;
+                    case "azuresdk":
+                        this._options.instrumentationOptions = {
+                            ...this._options.instrumentationOptions,
+                            azureSdk: { enabled: false },
+                        }
+                        break;
+                    case "http":
+                        this._options.instrumentationOptions = {
+                            ...this._options.instrumentationOptions,
+                            http: { enabled: false },
+                        }
+                        break;
+                    case "mongodb":
+                        this._options.instrumentationOptions = {
+                            ...this._options.instrumentationOptions,
+                            mongoDb: { enabled: false },
+                        }
+                        break;
+                    case "mysql":
+                        this._options.instrumentationOptions = {
+                            ...this._options.instrumentationOptions,
+                            mySql: { enabled: false },
+                        }
+                        break;
+                    case "postgresql":
+                        this._options.instrumentationOptions = {
+                            ...this._options.instrumentationOptions,
+                            postgreSql: { enabled: false },
+                        }
+                        break;
+                    case "redis":
+                        this._options.instrumentationOptions = {
+                            ...this._options.instrumentationOptions,
+                            redis: { enabled: false },
+                        }
+                        break;
+                    case "redis4":
+                        this._options.instrumentationOptions = {
+                            ...this._options.instrumentationOptions,
+                            redis4: { enabled: false },
+                        }
+                        break;
+                    default:
+                        Logger.getInstance().warn(`Unknown module ${module} passed to noPatchModules.`);
+                        break;
+                }
+            }
+        }
+
+        if (jsonConfig.noHttpAgentKeepAlive === true) {
+            this._options.otlpTraceExporterConfig = {
+                ...this._options.otlpTraceExporterConfig,
+                enabled: false
+            };
+            this._options.otlpMetricExporterConfig = {
+                ...this._options.otlpMetricExporterConfig,
+                enabled: false
+            };
+            this._options.otlpLogExporterConfig = {
+                ...this._options.otlpLogExporterConfig,
+                enabled: false
+            };
+        }
+    }
     
     /**
      * Starts automatic collection of telemetry. Prior to calling start no telemetry will be collected
@@ -258,7 +452,10 @@ export class TelemetryClient {
     public start(input?: ApplicationInsightsOptions) {
         // Only parse config if we're running the shim
         if (_setupCalled) {
-            this._parseConfig(input);
+            const jsonConfig = ShimJsonConfig.getInstance();
+            // Create the internalConfig based on the JSONConfig, and override with the client.config if defined
+            this._parseJson(jsonConfig);
+            this._parseConfig(jsonConfig, input);
         }
         this._internalConfig = new InternalConfig(this._options);
         this._client = new AzureMonitorOpenTelemetryClient(this._options);


Test patch:
diff --git a/test/unitTests/shim/config.json b/test/unitTests/shim/config.json
new file mode 100644
index 0000000..82c1501
--- /dev/null
+++ b/test/unitTests/shim/config.json
@@ -0,0 +1,29 @@
+{
+    "connectionString": "InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333;IngestionEndpoint=https://centralus-0.in.applicationinsights.azure.com/",
+    "endpointUrl": "testEndpointUrl",
+    "disableAllExtendedMetrics": false,
+    "disableAppInsights": false,
+    "samplingPercentage": 30,
+    "correlationHeaderExcludedDomains": [
+        "bing.com"
+    ],
+    "proxyHttpsUrl": "https://test:3000",
+    "enableAutoCollectExternalLoggers": true,
+    "enableAutoCollectConsole": true,
+    "enableAutoCollectExceptions": true,
+    "enableAutoCollectPerformance": true,
+    "enableAutoCollectExtendedMetrics": true,
+    "enableAutoCollectPreAggregatedMetrics": true,
+    "enableAutoCollectRequests": true,
+    "enableAutoCollectDependencies": true,
+    "enableAutoDependencyCorrelation": true,
+    "enableAutoCollectIncomingRequestAzureFunctions": false,
+    "noHttpAgentKeepAlive": false,
+    "distributedTracingMode": 0,
+    "enableInternalDebugLogging": false,
+    "enableInternalWarningLogging": false,
+    "extendedMetricDisablers": "gc,heap",
+    "noDiagnosticChannel": false,
+    "noPatchModules": "redis,azuresdk",
+    "maxBatchIntervalMs": 1000
+}
\ No newline at end of file
diff --git a/test/unitTests/shim/config.tests.ts b/test/unitTests/shim/config.tests.ts
index b37e675..797ff09 100644
--- a/test/unitTests/shim/config.tests.ts
+++ b/test/unitTests/shim/config.tests.ts
@@ -32,13 +32,10 @@ describe("shim/configuration/config", () => {
 
     beforeEach(() => {
         originalEnv = process.env;
-        process.env["APPLICATION_INSIGHTS_SHIM_CONFIGURATION"] = "true";
         sandbox = sinon.createSandbox();
     });
 
     afterEach(() => {
-        process.env = originalEnv;
-        delete process.env.APPLICATION_INSIGHTS_SHIM_CONFIGURATION;
         sandbox.restore();
     })
 
diff --git a/test/unitTests/shim/jsonConfig.tests.ts b/test/unitTests/shim/jsonConfig.tests.ts
new file mode 100644
index 0000000..0025ed4
--- /dev/null
+++ b/test/unitTests/shim/jsonConfig.tests.ts
@@ -0,0 +1,147 @@
+import assert = require("assert");
+import path = require("path");
+import { ShimJsonConfig } from "../../../src/shim/shim-jsonConfig";
+import { HttpInstrumentationConfig } from "@opentelemetry/instrumentation-http";
+const applicationInsights = require('../../../applicationinsights');
+
+describe("Json Config", () => {
+    const connectionString = "InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333;IngestionEndpoint=https://centralus-0.in.applicationinsights.azure.com/";
+
+    beforeEach(() => {
+        ShimJsonConfig["_instance"] = undefined;
+        applicationInsights.dispose();
+    });
+
+    afterEach(() => {
+        ShimJsonConfig["_instance"] = undefined;
+        applicationInsights.dispose();
+    });
+
+    describe("configuration values", () => {
+        it("should take configurations from the JSON config file", () => {
+            const cutstomConfigJsonPath = path.resolve(__dirname, "../../../../test/unitTests/shim/config.json");
+            process.env["APPLICATIONINSIGHTS_CONFIGURATION_FILE"] = cutstomConfigJsonPath;
+
+            applicationInsights.setup(connectionString);
+            applicationInsights.start();
+
+            assert.equal(applicationInsights["defaultClient"]["_options"].azureMonitorExporterConfig.connectionString, "InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333;IngestionEndpoint=https://centralus-0.in.applicationinsights.azure.com/");
+            assert.equal(applicationInsights["defaultClient"]["_options"].azureMonitorExporterConfig.proxyOptions.host, "test");
+            assert.equal(applicationInsights["defaultClient"]["_options"].azureMonitorExporterConfig.proxyOptions.port, 3000);
+            assert.equal(applicationInsights["defaultClient"]["_options"].samplingRatio, 0.3, JSON.stringify(ShimJsonConfig["_instance"]));
+            const ignoreOutgoingUrls = applicationInsights["defaultClient"]["_options"].instrumentationOptions.http as HttpInstrumentationConfig;
+            assert.equal(ignoreOutgoingUrls.ignoreOutgoingUrls, "bing.com");
+            assert.equal(JSON.stringify(applicationInsights["defaultClient"]["_options"].logInstrumentations), JSON.stringify({ winston: { enabled: true }, bunyan: { enabled: true }, console: { enabled: true } }));
+            assert.equal(applicationInsights["defaultClient"]["_options"].enableAutoCollectExceptions, true);
+            assert.equal(applicationInsights["defaultClient"]["_options"].enableAutoCollectPerformance, true);
+            assert.equal(JSON.stringify(applicationInsights["defaultClient"]["_options"].extendedMetrics), JSON.stringify({ gc: true, heap: true, loop: true }));
+            assert.equal(applicationInsights["defaultClient"]["_options"].instrumentationOptions.http.hasOwnProperty("ignoreIncomingRequestHook"), true);
+            assert.equal(applicationInsights["defaultClient"]["_options"].instrumentationOptions.http.hasOwnProperty("ignoreOutgoingRequestHook"), true);
+            assert.equal(
+                JSON.stringify(applicationInsights["defaultClient"]["_options"].otlpTraceExporterConfig),
+                JSON.stringify({timeoutMillis: 1000})
+            );
+            assert.equal(
+                JSON.stringify(applicationInsights["defaultClient"]["_options"].otlpMetricExporterConfig),
+                JSON.stringify({timeoutMillis: 1000})
+            );
+            assert.equal(
+                JSON.stringify(applicationInsights["defaultClient"]["_options"].otlpLogExporterConfig),
+                JSON.stringify({timeoutMillis: 1000})
+            );
+            assert.equal(JSON.stringify(applicationInsights["defaultClient"]["_options"].instrumentationOptions.redis), JSON.stringify({ enabled: false }));
+            assert.equal(JSON.stringify(applicationInsights["defaultClient"]["_options"].instrumentationOptions.azureSdk), JSON.stringify({ enabled: false }));
+
+            delete process.env.APPLICATIONINSIGHTS_CONFIGURATION_FILE;
+        });
+
+        it("should take configurations from environment variables", () => {
+            process.env["APPLICATIONINSIGHTS_CONNECTION_STRING"] = connectionString;
+            process.env["APPLICATION_INSIGHTS_DISABLE_EXTENDED_METRIC"] = "gc";
+            process.env["APPLICATION_INSIGHTS_NO_PATCH_MODULES"] = "azuresdk";
+            process.env["APPLICATION_INSIGHTS_DISABLE_ALL_EXTENDED_METRICS"] = "true";
+            process.env["APPLICATION_INSIGHTS_NO_DIAGNOSTIC_CHANNEL"] = "true";
+            process.env["APPLICATION_INSIGHTS_NO_HTTP_AGENT_KEEP_ALIVE"] = "true";
+            process.env["https_proxy"] = "https://testproxy:3000";
+
+            applicationInsights.setup();
+            applicationInsights.start();
+            assert.equal(applicationInsights["defaultClient"]["_options"].azureMonitorExporterConfig.connectionString, connectionString);
+            assert.equal(JSON.stringify(applicationInsights["defaultClient"]["_options"].extendedMetrics), JSON.stringify({ gc: false, heap: false, loop: false }, applicationInsights["defaultClient"]["_options"].extendedMetrics));
+            assert.equal(JSON.stringify(applicationInsights["defaultClient"]["_options"].instrumentationOptions.redis), JSON.stringify({ enabled: false }));
+            assert.equal(JSON.stringify(applicationInsights["defaultClient"]["_options"].instrumentationOptions.redis4), JSON.stringify({ enabled: false }));
+            assert.equal(JSON.stringify(applicationInsights["defaultClient"]["_options"].instrumentationOptions.postgreSql), JSON.stringify({ enabled: false }));
+            assert.equal(applicationInsights["defaultClient"]["_options"].azureMonitorExporterConfig.proxyOptions.host, "testproxy");
+            assert.equal(applicationInsights["defaultClient"]["_options"].azureMonitorExporterConfig.proxyOptions.port, 3000);
+
+            delete process.env.APPLICATIONINSIGHTS_CONNECTION_STRING;
+            delete process.env.APPLICATION_INSIGHTS_DISABLE_EXTENDED_METRIC;
+            delete process.env.APPLICATION_INSIGHTS_NO_PATCH_MODULES;
+            delete process.env.APPLICATION_INSIGHTS_DISABLE_ALL_EXTENDED_METRICS;
+            delete process.env.APPLICATION_INSIGHTS_NO_DIAGNOSTIC_CHANNEL;
+            delete process.env.APPLICATION_INSIGHTS_NO_HTTP_AGENT_KEEP_ALIVE;
+            delete process.env.https_proxy;
+        });
+
+        it("should take configuration from JSON string", () => {
+            const inputJson = {
+                "connectionString": "InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333;IngestionEndpoint=https://centralus-0.in.applicationinsights.azure.com/",
+                "endpointUrl": "testEndpointUrl",
+                "disableAllExtendedMetrics": false,
+                "disableAppInsights": false,
+                "samplingPercentage": 60,
+                "correlationHeaderExcludedDomains": ["bing.com"],
+                "proxyHttpsUrl": "https://test:3000",
+                "enableAutoCollectExternalLoggers": true,
+                "enableAutoCollectConsole": true,
+                "enableAutoCollectExceptions": true,
+                "enableAutoCollectPerformance": true,
+                "enableAutoCollectExtendedMetrics": true,
+                "enableAutoCollectPreAggregatedMetrics": true,
+                "enableAutoCollectRequests": true,
+                "enableAutoCollectDependencies": true,
+                "enableAutoDependencyCorrelation": true,
+                "enableAutoCollectIncomingRequestAzureFunctions": false,
+                "noHttpAgentKeepAlive": true,
+                "distributedTracingMode": 0,
+                "enableInternalDebugLogging": false,
+                "enableInternalWarningLogging": false,
+                "extendedMetricDisablers": "gc,heap",
+                "noDiagnosticChannel": false,
+                "noPatchModules": "redis,azuresdk",
+                "maxBatchIntervalMs": 1500
+            };
+            process.env["APPLICATIONINSIGHTS_CONFIGURATION_CONTENT"] = JSON.stringify(inputJson);
+            applicationInsights.setup();
+            applicationInsights.start();
+            assert.equal(applicationInsights["defaultClient"]["_options"].azureMonitorExporterConfig.connectionString, "InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333;IngestionEndpoint=https://centralus-0.in.applicationinsights.azure.com/");
+            assert.equal(applicationInsights["defaultClient"]["_options"].azureMonitorExporterConfig.proxyOptions.host, "test");
+            assert.equal(applicationInsights["defaultClient"]["_options"].azureMonitorExporterConfig.proxyOptions.port, 3000);
+            assert.equal(applicationInsights["defaultClient"]["_options"].samplingRatio, 0.6, JSON.stringify(ShimJsonConfig["_instance"]));
+            const ignoreOutgoingUrls = applicationInsights["defaultClient"]["_options"].instrumentationOptions.http as HttpInstrumentationConfig;
+            assert.equal(ignoreOutgoingUrls.ignoreOutgoingUrls, "bing.com");
+            assert.equal(JSON.stringify(applicationInsights["defaultClient"]["_options"].logInstrumentations), JSON.stringify({ console: { enabled: true }, winston: { enabled: true }, bunyan: { enabled: true } }));
+            assert.equal(applicationInsights["defaultClient"]["_options"].enableAutoCollectExceptions, true);
+            assert.equal(applicationInsights["defaultClient"]["_options"].enableAutoCollectPerformance, true);
+            assert.equal(JSON.stringify(applicationInsights["defaultClient"]["_options"].extendedMetrics), JSON.stringify({ gc: true, heap: true, loop: true }));
+            assert.equal(applicationInsights["defaultClient"]["_options"].instrumentationOptions.http.hasOwnProperty("ignoreIncomingRequestHook"), true);
+            assert.equal(applicationInsights["defaultClient"]["_options"].instrumentationOptions.http.hasOwnProperty("ignoreOutgoingRequestHook"), true);
+            assert.equal(
+                JSON.stringify(applicationInsights["defaultClient"]["_options"].otlpTraceExporterConfig),
+                JSON.stringify({ timeoutMillis: 1500, enabled: false })
+            );
+            assert.equal(
+                JSON.stringify(applicationInsights["defaultClient"]["_options"].otlpMetricExporterConfig),
+                JSON.stringify({ timeoutMillis: 1500, enabled: false })
+            );
+            assert.equal(
+                JSON.stringify(applicationInsights["defaultClient"]["_options"].otlpLogExporterConfig),
+                JSON.stringify({ timeoutMillis: 1500, enabled: false })
+            );
+            assert.equal(JSON.stringify(applicationInsights["defaultClient"]["_options"].instrumentationOptions.redis), JSON.stringify({ enabled: false }));
+            assert.equal(JSON.stringify(applicationInsights["defaultClient"]["_options"].instrumentationOptions.azureSdk), JSON.stringify({ enabled: false }));
+
+            delete process.env.APPLICATIONINSIGHTS_CONFIGURATION_CONTENT;
+        });
+    });
+});