diff --git a/package-lock.json b/package-lock.json index 7cc0a774..44b53a05 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,7 +6,7 @@ "packages": { "": { "name": "@azure/app-configuration-provider", - "version": "1.1.2", + "version": "2.0.0-preview.1", "license": "MIT", "dependencies": { "@azure/app-configuration": "^1.6.1", @@ -1138,10 +1138,11 @@ } }, "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -1425,10 +1426,11 @@ "dev": true }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -1439,11 +1441,12 @@ } }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -1501,10 +1504,11 @@ } }, "node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } @@ -2574,32 +2578,32 @@ } }, "node_modules/mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", - "dev": true, - "dependencies": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz", + "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-colors": "^4.1.3", + "browser-stdout": "^1.3.1", + "chokidar": "^3.5.3", + "debug": "^4.3.5", + "diff": "^5.2.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^8.1.0", + "he": "^1.2.0", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^5.1.6", + "ms": "^2.1.3", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^6.5.1", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.9", + "yargs-unparser": "^2.0.0" }, "bin": { "_mocha": "bin/_mocha", @@ -2607,10 +2611,6 @@ }, "engines": { "node": ">= 14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" } }, "node_modules/mocha/node_modules/brace-expansion": { @@ -2618,15 +2618,38 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, + "node_modules/mocha/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -2634,12 +2657,6 @@ "node": ">=10" } }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, "node_modules/mocha/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -2656,21 +2673,10 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/natural-compare": { "version": "1.4.0", @@ -2957,6 +2963,7 @@ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "^5.1.0" } @@ -3178,10 +3185,11 @@ } }, "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" } @@ -3238,15 +3246,6 @@ "url": "https://opencollective.com/sinon" } }, - "node_modules/sinon/node_modules/diff": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", - "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -3480,10 +3479,11 @@ } }, "node_modules/workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", + "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", + "dev": true, + "license": "Apache-2.0" }, "node_modules/wrap-ansi": { "version": "7.0.0", @@ -3559,10 +3559,11 @@ } }, "node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } diff --git a/src/AzureAppConfigurationImpl.ts b/src/AzureAppConfigurationImpl.ts index d709a808..5a66cfb6 100644 --- a/src/AzureAppConfigurationImpl.ts +++ b/src/AzureAppConfigurationImpl.ts @@ -33,7 +33,7 @@ import { } from "./featureManagement/constants.js"; import { AzureKeyVaultKeyValueAdapter } from "./keyvault/AzureKeyVaultKeyValueAdapter.js"; import { RefreshTimer } from "./refresh/RefreshTimer.js"; -import { getConfigurationSettingWithTrace, listConfigurationSettingsWithTrace, requestTracingEnabled } from "./requestTracing/utils.js"; +import { RequestTracingOptions, getConfigurationSettingWithTrace, listConfigurationSettingsWithTrace, requestTracingEnabled } from "./requestTracing/utils.js"; import { KeyFilter, LabelFilter, SettingSelector } from "./types.js"; import { ConfigurationClientManager } from "./ConfigurationClientManager.js"; @@ -197,11 +197,12 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration { return this.#featureFlagEnabled && !!this.#options?.featureFlagOptions?.refresh?.enabled; } - get #requestTraceOptions() { + get #requestTraceOptions(): RequestTracingOptions { return { - requestTracingEnabled: this.#requestTracingEnabled, - initialLoadCompleted: this.#isInitialLoadCompleted, + enabled: this.#requestTracingEnabled, appConfigOptions: this.#options, + initialLoadCompleted: this.#isInitialLoadCompleted, + replicaCount: this.#clientManager.getReplicaCount(), isFailoverRequest: this.#isFailoverRequest }; } diff --git a/src/ConfigurationClientManager.ts b/src/ConfigurationClientManager.ts index 59e03aa5..b11e9350 100644 --- a/src/ConfigurationClientManager.ts +++ b/src/ConfigurationClientManager.ts @@ -30,8 +30,9 @@ export class ConfigurationClientManager { #clientOptions: AppConfigurationClientOptions | undefined; #appConfigOptions: AzureAppConfigurationOptions | undefined; #validDomain: string; - #staticClients: ConfigurationClientWrapper[]; + #staticClients: ConfigurationClientWrapper[]; // there should always be only one static client #dynamicClients: ConfigurationClientWrapper[]; + #replicaCount: number = 0; #lastFallbackClientRefreshTime: number = 0; #lastFallbackClientRefreshAttempt: number = 0; @@ -96,7 +97,11 @@ export class ConfigurationClientManager { this.#isFailoverable = true; } - async getClients() : Promise { + getReplicaCount(): number { + return this.#replicaCount; + } + + async getClients(): Promise { if (!this.#isFailoverable) { return this.#staticClients; } @@ -161,6 +166,7 @@ export class ConfigurationClientManager { this.#dynamicClients = newDynamicClients; this.#lastFallbackClientRefreshTime = Date.now(); + this.#replicaCount = this.#dynamicClients.length; } /** diff --git a/src/requestTracing/constants.ts b/src/requestTracing/constants.ts index 8b39b636..30a12f43 100644 --- a/src/requestTracing/constants.ts +++ b/src/requestTracing/constants.ts @@ -37,16 +37,20 @@ export const CONTAINER_APP_ENV_VAR = "CONTAINER_APP_NAME"; export const KUBERNETES_ENV_VAR = "KUBERNETES_PORT"; export const SERVICE_FABRIC_ENV_VAR = "Fabric_NodeName"; // See: https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-environment-variables-reference -// Request Type +// Request type export const REQUEST_TYPE_KEY = "RequestType"; export enum RequestType { STARTUP = "Startup", WATCH = "Watch" } -export const FEATURES_KEY = "Features"; +// Replica count +export const REPLICA_COUNT_KEY = "ReplicaCount"; // Tag names -export const FAILOVER_REQUEST_TAG = "Failover"; export const KEY_VAULT_CONFIGURED_TAG = "UsesKeyVault"; +export const FAILOVER_REQUEST_TAG = "Failover"; + +// Compact feature tags +export const FEATURES_KEY = "Features"; export const LOAD_BALANCE_CONFIGURED_TAG = "LB"; diff --git a/src/requestTracing/utils.ts b/src/requestTracing/utils.ts index d48bd5ec..23ec4602 100644 --- a/src/requestTracing/utils.ts +++ b/src/requestTracing/utils.ts @@ -20,29 +20,31 @@ import { RequestType, SERVICE_FABRIC_ENV_VAR, CORRELATION_CONTEXT_HEADER_NAME, + REPLICA_COUNT_KEY, FAILOVER_REQUEST_TAG, FEATURES_KEY, LOAD_BALANCE_CONFIGURED_TAG } from "./constants"; +export interface RequestTracingOptions { + enabled: boolean; + appConfigOptions: AzureAppConfigurationOptions | undefined; + initialLoadCompleted: boolean; + replicaCount: number; + isFailoverRequest: boolean; +} + // Utils export function listConfigurationSettingsWithTrace( - requestTracingOptions: { - requestTracingEnabled: boolean; - initialLoadCompleted: boolean; - appConfigOptions: AzureAppConfigurationOptions | undefined; - isFailoverRequest: boolean; - }, + requestTracingOptions: RequestTracingOptions, client: AppConfigurationClient, listOptions: ListConfigurationSettingsOptions ) { - const { requestTracingEnabled, initialLoadCompleted, appConfigOptions, isFailoverRequest } = requestTracingOptions; - const actualListOptions = { ...listOptions }; - if (requestTracingEnabled) { + if (requestTracingOptions.enabled) { actualListOptions.requestOptions = { customHeaders: { - [CORRELATION_CONTEXT_HEADER_NAME]: createCorrelationContextHeader(appConfigOptions, initialLoadCompleted, isFailoverRequest) + [CORRELATION_CONTEXT_HEADER_NAME]: createCorrelationContextHeader(requestTracingOptions) } }; } @@ -51,23 +53,17 @@ export function listConfigurationSettingsWithTrace( } export function getConfigurationSettingWithTrace( - requestTracingOptions: { - requestTracingEnabled: boolean; - initialLoadCompleted: boolean; - appConfigOptions: AzureAppConfigurationOptions | undefined; - isFailoverRequest: boolean; - }, + requestTracingOptions: RequestTracingOptions, client: AppConfigurationClient, configurationSettingId: ConfigurationSettingId, getOptions?: GetConfigurationSettingOptions, ) { - const { requestTracingEnabled, initialLoadCompleted, appConfigOptions, isFailoverRequest } = requestTracingOptions; const actualGetOptions = { ...getOptions }; - if (requestTracingEnabled) { + if (requestTracingOptions.enabled) { actualGetOptions.requestOptions = { customHeaders: { - [CORRELATION_CONTEXT_HEADER_NAME]: createCorrelationContextHeader(appConfigOptions, initialLoadCompleted, isFailoverRequest) + [CORRELATION_CONTEXT_HEADER_NAME]: createCorrelationContextHeader(requestTracingOptions) } }; } @@ -75,29 +71,43 @@ export function getConfigurationSettingWithTrace( return client.getConfigurationSetting(configurationSettingId, actualGetOptions); } -export function createCorrelationContextHeader(options: AzureAppConfigurationOptions | undefined, isInitialLoadCompleted: boolean, isFailoverRequest: boolean): string { +export function createCorrelationContextHeader(requestTracingOptions: RequestTracingOptions): string { /* RequestType: 'Startup' during application starting up, 'Watch' after startup completed. Host: identify with defined envs - Env: identify by env `NODE_ENV` which is a popular but not standard.usually the value can be "development", "production". + Env: identify by env `NODE_ENV` which is a popular but not standard. Usually, the value can be "development", "production". + ReplicaCount: identify how many replicas are found + Features: LB UsersKeyVault + Failover */ const keyValues = new Map(); - keyValues.set(REQUEST_TYPE_KEY, isInitialLoadCompleted ? RequestType.WATCH : RequestType.STARTUP); + const tags: string[] = []; + + keyValues.set(REQUEST_TYPE_KEY, requestTracingOptions.initialLoadCompleted ? RequestType.WATCH : RequestType.STARTUP); keyValues.set(HOST_TYPE_KEY, getHostType()); keyValues.set(ENV_KEY, isDevEnvironment() ? DEV_ENV_VAL : undefined); - if (options?.loadBalancingEnabled) { - keyValues.set(FEATURES_KEY, LOAD_BALANCE_CONFIGURED_TAG); - } - const tags: string[] = []; - if (options?.keyVaultOptions) { - const { credential, secretClients, secretResolver } = options.keyVaultOptions; + const appConfigOptions = requestTracingOptions.appConfigOptions; + if (appConfigOptions?.keyVaultOptions) { + const { credential, secretClients, secretResolver } = appConfigOptions.keyVaultOptions; if (credential !== undefined || secretClients?.length || secretResolver !== undefined) { tags.push(KEY_VAULT_CONFIGURED_TAG); } } + if (requestTracingOptions.isFailoverRequest) { + tags.push(FAILOVER_REQUEST_TAG); + } + if (requestTracingOptions.replicaCount > 0) { + keyValues.set(REPLICA_COUNT_KEY, requestTracingOptions.replicaCount.toString()); + } + + // Compact tags: Features=LB+... + if (appConfigOptions?.loadBalancingEnabled) { + keyValues.set(FEATURES_KEY, LOAD_BALANCE_CONFIGURED_TAG); + } + const contextParts: string[] = []; for (const [k, v] of keyValues) { if (v !== undefined) { @@ -108,10 +118,6 @@ export function createCorrelationContextHeader(options: AzureAppConfigurationOpt contextParts.push(tag); } - if (isFailoverRequest) { - contextParts.push(FAILOVER_REQUEST_TAG); - } - return contextParts.join(","); } diff --git a/test/clientOptions.test.ts b/test/clientOptions.test.ts index 62e1b21c..2e9417e9 100644 --- a/test/clientOptions.test.ts +++ b/test/clientOptions.test.ts @@ -6,7 +6,7 @@ import * as chaiAsPromised from "chai-as-promised"; chai.use(chaiAsPromised); const expect = chai.expect; import { load } from "./exportedApi.js"; -import { createMockedConnectionString } from "./utils/testHelper.js"; +import { MAX_TIME_OUT, createMockedConnectionString } from "./utils/testHelper.js"; import * as nock from "nock"; class HttpRequestCountPolicy { @@ -27,7 +27,7 @@ class HttpRequestCountPolicy { } describe("custom client options", function () { - this.timeout(15000); + this.timeout(MAX_TIME_OUT); const fakeEndpoint = "https://azure.azconfig.io"; beforeEach(() => { diff --git a/test/failover.test.ts b/test/failover.test.ts index 2671a1f2..e1f2f043 100644 --- a/test/failover.test.ts +++ b/test/failover.test.ts @@ -6,7 +6,7 @@ import * as chaiAsPromised from "chai-as-promised"; chai.use(chaiAsPromised); const expect = chai.expect; import { load } from "./exportedApi"; -import { createMockedConnectionString, createMockedFeatureFlag, createMockedKeyValue, mockConfigurationManagerGetClients, restoreMocks } from "./utils/testHelper"; +import { MAX_TIME_OUT, createMockedConnectionString, createMockedFeatureFlag, createMockedKeyValue, mockConfigurationManagerGetClients, restoreMocks } from "./utils/testHelper"; import { getValidDomain, isValidEndpoint } from "../src/ConfigurationClientManager"; const mockedKVs = [{ @@ -27,7 +27,7 @@ const mockedFeatureFlags = [{ ]); describe("failover", function () { - this.timeout(15000); + this.timeout(MAX_TIME_OUT); afterEach(() => { restoreMocks(); diff --git a/test/featureFlag.test.ts b/test/featureFlag.test.ts index 9294a451..2544e617 100644 --- a/test/featureFlag.test.ts +++ b/test/featureFlag.test.ts @@ -4,7 +4,7 @@ import * as chai from "chai"; import * as chaiAsPromised from "chai-as-promised"; import { load } from "./exportedApi.js"; -import { createMockedConnectionString, createMockedEndpoint, createMockedFeatureFlag, createMockedKeyValue, mockAppConfigurationClientListConfigurationSettings, restoreMocks } from "./utils/testHelper.js"; +import { MAX_TIME_OUT, createMockedConnectionString, createMockedEndpoint, createMockedFeatureFlag, createMockedKeyValue, mockAppConfigurationClientListConfigurationSettings, restoreMocks } from "./utils/testHelper.js"; chai.use(chaiAsPromised); const expect = chai.expect; @@ -199,7 +199,7 @@ const mockedKVs = [{ ]); describe("feature flags", function () { - this.timeout(10000); + this.timeout(MAX_TIME_OUT); before(() => { mockAppConfigurationClientListConfigurationSettings([mockedKVs]); diff --git a/test/json.test.ts b/test/json.test.ts index 47a3f670..cb937bd9 100644 --- a/test/json.test.ts +++ b/test/json.test.ts @@ -6,12 +6,14 @@ import * as chaiAsPromised from "chai-as-promised"; chai.use(chaiAsPromised); const expect = chai.expect; import { load } from "./exportedApi.js"; -import { mockAppConfigurationClientListConfigurationSettings, restoreMocks, createMockedConnectionString, createMockedKeyVaultReference, createMockedJsonKeyValue } from "./utils/testHelper.js"; +import { MAX_TIME_OUT, mockAppConfigurationClientListConfigurationSettings, restoreMocks, createMockedConnectionString, createMockedKeyVaultReference, createMockedJsonKeyValue } from "./utils/testHelper.js"; const jsonKeyValue = createMockedJsonKeyValue("json.settings.logging", '{"Test":{"Level":"Debug"},"Prod":{"Level":"Warning"}}'); const keyVaultKeyValue = createMockedKeyVaultReference("TestKey", "https://fake-vault-name.vault.azure.net/secrets/fakeSecretName"); describe("json", function () { + this.timeout(MAX_TIME_OUT); + beforeEach(() => { }); diff --git a/test/keyvault.test.ts b/test/keyvault.test.ts index 2877243b..e88044ea 100644 --- a/test/keyvault.test.ts +++ b/test/keyvault.test.ts @@ -6,7 +6,7 @@ import * as chaiAsPromised from "chai-as-promised"; chai.use(chaiAsPromised); const expect = chai.expect; import { load } from "./exportedApi.js"; -import { sinon, createMockedConnectionString, createMockedTokenCredential, mockAppConfigurationClientListConfigurationSettings, mockSecretClientGetSecret, restoreMocks, createMockedKeyVaultReference } from "./utils/testHelper.js"; +import { MAX_TIME_OUT, sinon, createMockedConnectionString, createMockedTokenCredential, mockAppConfigurationClientListConfigurationSettings, mockSecretClientGetSecret, restoreMocks, createMockedKeyVaultReference } from "./utils/testHelper.js"; import { KeyVaultSecret, SecretClient } from "@azure/keyvault-secrets"; const mockedData = [ @@ -27,7 +27,7 @@ function mockNewlyCreatedKeyVaultSecretClients() { mockSecretClientGetSecret(mockedData.map(([_key, secretUri, value]) => [secretUri, value])); } describe("key vault reference", function () { - this.timeout(10000); + this.timeout(MAX_TIME_OUT); beforeEach(() => { mockAppConfigurationClient(); diff --git a/test/load.test.ts b/test/load.test.ts index 6d2c94b8..d36a3311 100644 --- a/test/load.test.ts +++ b/test/load.test.ts @@ -6,7 +6,7 @@ import * as chaiAsPromised from "chai-as-promised"; chai.use(chaiAsPromised); const expect = chai.expect; import { load } from "./exportedApi.js"; -import { mockAppConfigurationClientListConfigurationSettings, restoreMocks, createMockedConnectionString, createMockedEndpoint, createMockedTokenCredential, createMockedKeyValue } from "./utils/testHelper.js"; +import { MAX_TIME_OUT, mockAppConfigurationClientListConfigurationSettings, restoreMocks, createMockedConnectionString, createMockedEndpoint, createMockedTokenCredential, createMockedKeyValue } from "./utils/testHelper.js"; const mockedKVs = [{ key: "app.settings.fontColor", @@ -77,7 +77,7 @@ const mockedKVs = [{ ].map(createMockedKeyValue); describe("load", function () { - this.timeout(10000); + this.timeout(MAX_TIME_OUT); before(() => { mockAppConfigurationClientListConfigurationSettings([mockedKVs]); diff --git a/test/loadBalance.test.ts b/test/loadBalance.test.ts index f0e04b01..59bdf0f8 100644 --- a/test/loadBalance.test.ts +++ b/test/loadBalance.test.ts @@ -6,7 +6,7 @@ import * as chaiAsPromised from "chai-as-promised"; chai.use(chaiAsPromised); const expect = chai.expect; import { load } from "./exportedApi.js"; -import { restoreMocks, createMockedConnectionString, sleepInMs, createMockedEndpoint, mockConfigurationManagerGetClients, mockAppConfigurationClientLoadBalanceMode } from "./utils/testHelper.js"; +import { MAX_TIME_OUT, restoreMocks, createMockedConnectionString, sleepInMs, createMockedEndpoint, mockConfigurationManagerGetClients, mockAppConfigurationClientLoadBalanceMode } from "./utils/testHelper.js"; import { AppConfigurationClient } from "@azure/app-configuration"; import { ConfigurationClientWrapper } from "../src/ConfigurationClientWrapper.js"; @@ -18,7 +18,7 @@ const clientRequestCounter_1 = {count: 0}; const clientRequestCounter_2 = {count: 0}; describe("load balance", function () { - this.timeout(10000); + this.timeout(MAX_TIME_OUT); beforeEach(() => { }); diff --git a/test/refresh.test.ts b/test/refresh.test.ts index 5fbeb973..6c537fb4 100644 --- a/test/refresh.test.ts +++ b/test/refresh.test.ts @@ -6,7 +6,7 @@ import * as chaiAsPromised from "chai-as-promised"; chai.use(chaiAsPromised); const expect = chai.expect; import { load } from "./exportedApi.js"; -import { mockAppConfigurationClientListConfigurationSettings, mockAppConfigurationClientGetConfigurationSetting, restoreMocks, createMockedConnectionString, createMockedKeyValue, sleepInMs, createMockedFeatureFlag } from "./utils/testHelper.js"; +import { MAX_TIME_OUT, mockAppConfigurationClientListConfigurationSettings, mockAppConfigurationClientGetConfigurationSetting, restoreMocks, createMockedConnectionString, createMockedKeyValue, sleepInMs, createMockedFeatureFlag } from "./utils/testHelper.js"; import * as uuid from "uuid"; let mockedKVs: any[] = []; @@ -33,7 +33,7 @@ const getKvCallback = () => { }; describe("dynamic refresh", function () { - this.timeout(10000); + this.timeout(MAX_TIME_OUT); beforeEach(() => { mockedKVs = [ diff --git a/test/requestTracing.test.ts b/test/requestTracing.test.ts index d146301d..311f857e 100644 --- a/test/requestTracing.test.ts +++ b/test/requestTracing.test.ts @@ -5,7 +5,8 @@ import * as chai from "chai"; import * as chaiAsPromised from "chai-as-promised"; chai.use(chaiAsPromised); const expect = chai.expect; -import { createMockedConnectionString, createMockedKeyValue, createMockedTokenCredential, mockAppConfigurationClientListConfigurationSettings, restoreMocks, sleepInMs } from "./utils/testHelper.js"; +import { MAX_TIME_OUT, createMockedConnectionString, createMockedKeyValue, createMockedTokenCredential, mockAppConfigurationClientListConfigurationSettings, restoreMocks, sinon, sleepInMs } from "./utils/testHelper.js"; +import { ConfigurationClientManager } from "../src/ConfigurationClientManager.js"; import { load } from "./exportedApi.js"; class HttpRequestHeadersPolicy { @@ -23,7 +24,7 @@ class HttpRequestHeadersPolicy { } describe("request tracing", function () { - this.timeout(15000); + this.timeout(MAX_TIME_OUT); const fakeEndpoint = "https://127.0.0.1"; // sufficient to test the request it sends out const headerPolicy = new HttpRequestHeadersPolicy(); @@ -75,6 +76,19 @@ describe("request tracing", function () { expect(correlationContext.includes("UsesKeyVault")).eq(true); }); + it("should have replica count in correlation-context header", async () => { + const replicaCount = 2; + sinon.stub(ConfigurationClientManager.prototype, "getReplicaCount").returns(replicaCount); + try { + await load(createMockedConnectionString(fakeEndpoint), { clientOptions }); + } catch (e) { /* empty */ } + expect(headerPolicy.headers).not.undefined; + const correlationContext = headerPolicy.headers.get("Correlation-Context"); + expect(correlationContext).not.undefined; + expect(correlationContext.includes(`ReplicaCount=${replicaCount}`)).eq(true); + sinon.restore(); + }); + it("should detect env in correlation-context header", async () => { process.env.NODE_ENV = "development"; try { diff --git a/test/utils/testHelper.ts b/test/utils/testHelper.ts index 3b51596c..d3e9a063 100644 --- a/test/utils/testHelper.ts +++ b/test/utils/testHelper.ts @@ -10,8 +10,10 @@ import { RestError } from "@azure/core-rest-pipeline"; import { promisify } from "util"; const sleepInMs = promisify(setTimeout); import * as crypto from "crypto"; -import { ConfigurationClientManager } from "../../src/ConfigurationClientManager"; -import { ConfigurationClientWrapper } from "../../src/ConfigurationClientWrapper"; +import { ConfigurationClientManager } from "../../src/ConfigurationClientManager.js"; +import { ConfigurationClientWrapper } from "../../src/ConfigurationClientWrapper.js"; + +const MAX_TIME_OUT = 20000; const TEST_CLIENT_ID = "00000000-0000-0000-0000-000000000000"; const TEST_TENANT_ID = "00000000-0000-0000-0000-000000000000"; @@ -262,5 +264,7 @@ export { createMockedKeyValue, createMockedFeatureFlag, - sleepInMs + sleepInMs, + + MAX_TIME_OUT };